diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index dc1af82d21f16..4c06caaa9d30e 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1,4 +1,82 @@ import * as ts from "./_namespaces/ts"; +import { getNodeId } from "./checker"; +import { + append, appendIfUnique, cast, concatenate, contains, every, forEach, getRangesWhere, isString, length, Pattern, + some, tryCast, +} from "./core"; +import { ESMap, Map, Set } from "./corePublic"; +import { Debug } from "./debug"; +import { Diagnostics } from "./diagnosticInformationMap.generated"; +import { + isBinaryExpression, isBlock, isCallExpression, isClassStaticBlockDeclaration, isConditionalTypeNode, + isElementAccessExpression, isEnumDeclaration, isExportAssignment, isExportDeclaration, isExportSpecifier, + isFunctionDeclaration, isIdentifier, isJSDocEnumTag, isJSDocTemplateTag, isModuleBlock, isModuleDeclaration, + isNamespaceExport, isNonNullExpression, isObjectLiteralExpression, isOmittedExpression, isParenthesizedExpression, + isPrefixUnaryExpression, isPrivateIdentifier, isPropertyAccessExpression, isShorthandPropertyAssignment, + isSourceFile, isTypeAliasDeclaration, isTypeOfExpression, isVariableDeclaration, isVariableStatement, +} from "./factory/nodeTests"; +import { createBinaryExpressionTrampoline } from "./factory/utilities"; +import { forEachChild, isExternalModule } from "./parser"; +import { perfLogger } from "./perfLogger"; +import { mark, measure } from "./performance"; +import { tokenToString } from "./scanner"; +import { tracing, TracingNode } from "./tracing"; +import { + __String, AccessExpression, ArrayBindingElement, ArrayLiteralExpression, ArrowFunction, AssignmentDeclarationKind, + BinaryExpression, BinaryOperatorToken, BindableAccessExpression, BindableObjectDefinePropertyCall, + BindablePropertyAssignmentExpression, BindableStaticAccessExpression, BindableStaticNameExpression, + BindableStaticPropertyAssignmentExpression, BindingElement, Block, BreakOrContinueStatement, CallChain, + CallExpression, CaseBlock, CaseClause, CatchClause, ClassLikeDeclaration, ClassStaticBlockDeclaration, + CompilerOptions, ConditionalExpression, ConditionalTypeNode, Declaration, DeleteExpression, DestructuringAssignment, + DiagnosticCategory, DiagnosticMessage, DiagnosticRelatedInformation, DiagnosticWithLocation, DoStatement, + DynamicNamedDeclaration, ElementAccessChain, ElementAccessExpression, EntityNameExpression, EnumDeclaration, + ExportAssignment, ExportDeclaration, ExportSpecifier, Expression, ExpressionStatement, FlowFlags, FlowLabel, + FlowNode, FlowReduceLabel, ForInOrOfStatement, ForStatement, FunctionDeclaration, FunctionExpression, + FunctionLikeDeclaration, GetAccessorDeclaration, Identifier, IfStatement, ImportClause, InternalSymbolName, + JSDocCallbackTag, JSDocClassTag, JSDocEnumTag, JSDocFunctionType, JSDocParameterTag, JSDocPropertyLikeTag, + JSDocSignature, JSDocTypedefTag, JSDocTypeLiteral, JsxAttribute, JsxAttributes, LabeledStatement, + LiteralLikeElementAccessExpression, MappedTypeNode, MethodDeclaration, ModifierFlags, ModuleBlock, + ModuleDeclaration, NamespaceExportDeclaration, Node, NodeArray, NodeFlags, NonNullChain, NonNullExpression, + NumericLiteral, ObjectLiteralExpression, OptionalChain, ParameterDeclaration, ParenthesizedExpression, + PatternAmbientModule, PostfixUnaryExpression, PrefixUnaryExpression, PrivateIdentifier, PropertyAccessChain, + PropertyAccessExpression, PropertyDeclaration, PropertySignature, ReturnStatement, ScriptTarget, + SetAccessorDeclaration, ShorthandPropertyAssignment, SignatureDeclaration, SourceFile, SpreadElement, Statement, + StringLiteral, SwitchStatement, Symbol, SymbolFlags, SymbolTable, SyntaxKind, TextRange, ThrowStatement, TokenFlags, + TryStatement, TypeLiteralNode, TypeOfExpression, TypeParameterDeclaration, VariableDeclaration, WhileStatement, + WithStatement, +} from "./types"; +import { + addRelatedInfo, createDiagnosticForNodeInSourceFile, createFileDiagnostic, createSymbolTable, + declarationNameToString, exportAssignmentIsAlias, getAssignedExpandoInitializer, getAssignmentDeclarationKind, + getAssignmentDeclarationPropertyAccessKind, getContainingClass, getEffectiveContainerForJSDocTemplateTag, + getElementOrPropertyAccessName, getEmitScriptTarget, getEnclosingBlockScopeContainer, getErrorSpanForNode, + getEscapedTextOfIdentifierOrLiteral, getExpandoInitializer, getHostSignatureFromJSDoc, + getImmediatelyInvokedFunctionExpression, getLeftmostAccessExpression, getNameOrArgument, + getRightMostAssignedExpression, getSourceFileOfNode, getSourceTextOfNodeFromSourceFile, getSpanOfTokenAtPosition, + getStrictOptionValue, getSymbolNameForPrivateIdentifier, getTextOfIdentifierOrLiteral, getThisContainer, + getTokenPosOfNode, hasDynamicName, hasSyntacticModifier, isAliasableExpression, isAmbientModule, + isAssignmentExpression, isAssignmentOperator, isAssignmentTarget, isAsyncFunction, + isBindableObjectDefinePropertyCall, isBindableStaticAccessExpression, isBindableStaticNameExpression, + isBlockOrCatchScoped, isDestructuringAssignment, isDottedName, isEmptyObjectLiteral, isEntityNameExpression, + isEnumConst, isExportsIdentifier, isExternalOrCommonJsModule, isFunctionSymbol, isGlobalScopeAugmentation, + isIdentifierName, isInJSFile, isInTopLevelContext, isJSDocConstructSignature, isJSDocTypeAlias, isJsonSourceFile, + isLogicalOrCoalescingAssignmentOperator, isModuleAugmentationExternal, isModuleExportsAccessExpression, + isObjectLiteralMethod, isObjectLiteralOrClassExpressionMethodOrAccessor, isParameterDeclaration, isPartOfTypeQuery, + isPrologueDirective, isPropertyAccessEntityNameExpression, isPropertyNameLiteral, isPrototypeAccess, + isPushOrUnshiftIdentifier, isRequireCall, isSignedNumericLiteral, isSpecialPropertyDeclaration, isStatic, + isStringOrNumericLiteralLike, isThisInitializedDeclaration, isVariableDeclarationInitializedToBareOrAccessedRequire, + Mutable, nodeIsMissing, nodeIsPresent, objectAllocator, removeFileExtension, setParent, setParentRecursive, + setValueDeclaration, shouldPreserveConstEnums, skipParentheses, sliceAfter, tryParsePattern, unreachableCodeIsError, + unusedLabelIsError, +} from "./utilities"; +import { + escapeLeadingUnderscores, findAncestor, getCombinedModifierFlags, getCombinedNodeFlags, getJSDocTypeTag, + getNameOfDeclaration, hasJSDocNodes, idText, isBindingPattern, isDeclaration, isDeclarationStatement, isExpression, + isExpressionOfOptionalChainRoot, isForInOrOfStatement, isFunctionLike, isFunctionLikeDeclaration, + isFunctionLikeOrClassStaticBlockDeclaration, isLeftHandSideExpression, isNamedDeclaration, isNullishCoalesce, + isOptionalChain, isOptionalChainRoot, isOutermostOptionalChain, isParameterPropertyDeclaration, isStatement, + isStatementButNotDeclaration, isStringLiteralLike, nodeHasName, symbolName, unescapeLeadingUnderscores, +} from "./utilitiesPublic"; /* @internal */ export const enum ModuleInstanceState { @@ -9,24 +87,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 +114,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 +152,9 @@ function getModuleInstanceStateWorker(node: ts.Node, visited: ts.ESMap { + forEachChild(node, n => { const childState = getModuleInstanceStateCached(n, visited); switch (childState) { case ModuleInstanceState.NonInstantiated: @@ -91,35 +169,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 +245,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) { - ts.performance.mark("beforeBind"); - ts.perfLogger.logStartBindFile("" + file.fileName); +export function bindSourceFile(file: SourceFile, options: CompilerOptions) { + mark("beforeBind"); + perfLogger.logStartBindFile("" + file.fileName); binder(file, options); - ts.perfLogger.logStopBindFile(); - ts.performance.mark("afterBind"); - ts.performance.measure("Bind", "beforeBind", "afterBind"); + perfLogger.logStopBindFile(); + mark("afterBind"); + 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 +300,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 +312,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 +359,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 +374,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 as any).SyntaxKind ? (ts as any).SyntaxKind[node.parent.kind] : 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: ${(ts as any).SyntaxKind ? (ts as any).SyntaxKind[node.parent.kind] : 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 +490,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 +530,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 +546,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 +581,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 +626,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 +652,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 +669,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 +690,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 +716,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 +739,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 +761,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 +792,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 +803,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,109 +831,109 @@ 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.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; @@ -868,42 +946,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)) { @@ -911,89 +989,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)) { @@ -1003,12 +1081,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) { @@ -1017,12 +1095,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; @@ -1033,53 +1111,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; @@ -1089,15 +1167,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; @@ -1107,9 +1185,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; @@ -1117,7 +1195,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(); @@ -1130,7 +1208,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(); @@ -1143,7 +1221,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(); @@ -1158,18 +1236,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); @@ -1177,7 +1255,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(); @@ -1191,9 +1269,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); @@ -1202,7 +1280,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; @@ -1211,15 +1289,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); @@ -1233,7 +1311,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. @@ -1282,10 +1360,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; } @@ -1311,7 +1389,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; @@ -1320,7 +1398,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. @@ -1333,7 +1411,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; @@ -1350,13 +1428,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); @@ -1364,23 +1442,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, @@ -1392,54 +1470,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 { @@ -1448,20 +1526,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; @@ -1471,20 +1549,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); @@ -1507,17 +1585,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; @@ -1538,10 +1616,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); @@ -1555,41 +1633,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); } } } @@ -1606,22 +1684,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(); @@ -1637,27 +1715,27 @@ 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) { - if (ts.isBindingPattern(node.name)) { + function bindBindingElementFlow(node: BindingElement) { + if (isBindingPattern(node.name)) { // 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?` @@ -1675,45 +1753,45 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } } - 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); @@ -1721,7 +1799,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 @@ -1733,19 +1811,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); @@ -1756,8 +1834,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 { @@ -1765,8 +1843,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 { @@ -1774,94 +1852,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 @@ -1878,13 +1956,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; } @@ -1892,30 +1970,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 @@ -1923,26 +2001,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 @@ -1953,55 +2031,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 { @@ -2009,7 +2087,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) @@ -2018,42 +2096,42 @@ 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) { + function bindObjectLiteralExpression(node: ObjectLiteralExpression) { const enum ElementKind { Property = 1, Accessor = 2 } - if (inStrictMode && !ts.isAssignmentTarget(node)) { - const seen = new ts.Map(); + if (inStrictMode && !isAssignmentTarget(node)) { + const seen = new Map<__String, ElementKind>(); for (const prop of node.properties) { - if (prop.kind === ts.SyntaxKind.SpreadAssignment || prop.name.kind !== ts.SyntaxKind.Identifier) { + if (prop.kind === SyntaxKind.SpreadAssignment || prop.name.kind !== SyntaxKind.Identifier) { continue; } @@ -2067,7 +2145,7 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v // c.IsAccessorDescriptor(previous) is true and IsDataDescriptor(propId.descriptor) is true. // d.IsAccessorDescriptor(previous) is true and IsAccessorDescriptor(propId.descriptor) is true // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields - const currentKind = prop.kind === ts.SyntaxKind.PropertyAssignment || prop.kind === ts.SyntaxKind.ShorthandPropertyAssignment || prop.kind === ts.SyntaxKind.MethodDeclaration + const currentKind = prop.kind === SyntaxKind.PropertyAssignment || prop.kind === SyntaxKind.ShorthandPropertyAssignment || prop.kind === SyntaxKind.MethodDeclaration ? ElementKind.Property : ElementKind.Accessor; @@ -2079,40 +2157,40 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } } - return bindAnonymousDeclaration(node, ts.SymbolFlags.ObjectLiteral, ts.InternalSymbolName.Object); + 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); @@ -2130,52 +2208,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); @@ -2191,75 +2269,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) { @@ -2267,153 +2345,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, @@ -2442,7 +2520,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); @@ -2456,37 +2534,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; } @@ -2495,347 +2573,347 @@ 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) { - return bindPropertyOrMethodOrAccessor(node, ts.SymbolFlags.Property | (node.questionToken ? ts.SymbolFlags.Optional : ts.SymbolFlags.None), ts.SymbolFlags.PropertyExcludes); + function bindPropertyWorker(node: PropertyDeclaration | PropertySignature) { + return bindPropertyOrMethodOrAccessor(node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes); } - 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) { + function bindNamespaceExportDeclaration(node: NamespaceExportDeclaration) { if (node.modifiers && node.modifiers.length) { - file.bindDiagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.Modifiers_cannot_appear_here)); + 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) { return false; } @@ -2846,23 +2924,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)) { @@ -2870,19 +2948,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. @@ -2890,115 +2968,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 { @@ -3008,17 +3086,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); } @@ -3027,53 +3105,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)); } } @@ -3081,20 +3159,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); @@ -3102,69 +3180,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); @@ -3181,77 +3259,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); @@ -3269,37 +3347,37 @@ 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)) { - if (ts.isInJSFile(node) && ts.isVariableDeclarationInitializedToBareOrAccessedRequire(node) && !ts.getJSDocTypeTag(node) && !(ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export)) { - declareSymbolAndAddToSymbolTable(node as ts.Declaration, ts.SymbolFlags.Alias, ts.SymbolFlags.AliasExcludes); + if (!isBindingPattern(node.name)) { + if (isInJSFile(node) && isVariableDeclarationInitializedToBareOrAccessedRequire(node) && !getJSDocTypeTag(node) && !(getCombinedModifierFlags(node) & ModifierFlags.Export)) { + 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. // @@ -3309,138 +3387,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; @@ -3456,15 +3534,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)); } } } @@ -3472,54 +3550,54 @@ 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 = [node]; while (q.length && i < 100) { i++; node = q.shift()!; - 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.push(init); - if (ts.isAssignmentExpression(init, /*excludeCompoundAssignment*/ true)) { + if (isAssignmentExpression(init, /*excludeCompoundAssignment*/ true)) { q.push(init.left); q.push(init.right); } @@ -3529,12 +3607,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 6cf8e3d5b2654..ff784ad15c61f 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -1,4 +1,34 @@ import * as ts from "./_namespaces/ts"; +import { + AffectedFileResult, BuilderProgram, BuilderProgramHost, EmitAndSemanticDiagnosticsBuilderProgram, + SemanticDiagnosticsBuilderProgram, +} from "./builderPublic"; +import { BuilderState, ReusableBuilderState } from "./builderState"; +import { convertToOptionsWithAbsolutePaths, getOptionsNameMap } from "./commandLineParser"; +import { + addRange, arrayFrom, arrayToMap, compareStringsCaseSensitive, compareValues, concatenate, + createGetCanonicalFileName, emptyArray, every, forEach, GetCanonicalFileName, getOwnKeys, isArray, isNumber, + isString, map, mapDefined, maybeBind, noop, notImplemented, returnUndefined, tryAddToSet, +} from "./core"; +import { ESMap, Map, ReadonlyCollection, ReadonlyESMap, ReadonlySet, Set } from "./corePublic"; +import { Debug } from "./debug"; +import { getTsBuildInfoEmitOutputFilePath } from "./emitter"; +import { isDeclarationFileName } from "./parser"; +import { + ensurePathIsNonModuleName, getDirectoryPath, getNormalizedAbsolutePath, getRelativePathFromDirectory, +} from "./path"; +import { createProgram, emitSkippedWithNoDiagnostics, filterSemanticDiagnostics, handleNoEmitOptions } from "./program"; +import { generateDjb2Hash } from "./sys"; +import { + CancellationToken, CommandLineOption, CompilerHost, CompilerOptions, CompilerOptionsValue, CustomTransformers, + Diagnostic, DiagnosticCategory, DiagnosticMessageChain, DiagnosticRelatedInformation, EmitResult, Path, Program, + ProjectReference, SourceFile, SourceMapEmitResult, WriteFileCallback, +} from "./types"; +import { + compilerOptionsAffectEmit, compilerOptionsAffectSemanticDiagnostics, forEachEntry, forEachKey, getEmitDeclarations, + outFile, skipTypeChecking, +} from "./utilities"; +import { ReadBuildProgramHost } from "./watchPublic"; /* @internal */ export interface ReusableDiagnostic extends ReusableDiagnosticRelatedInformation { @@ -7,12 +37,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,55 +51,55 @@ export interface ReusableDiagnosticRelatedInformation { } /* @internal */ -export type ReusableDiagnosticMessageChain = ts.DiagnosticMessageChain; +export type ReusableDiagnosticMessageChain = DiagnosticMessageChain; /* @internal */ -export interface ReusableBuilderProgramState extends ts.ReusableBuilderState { +export interface ReusableBuilderProgramState extends ReusableBuilderState { /** * Cache of bind and check diagnostics for files with their Path being the key */ - semanticDiagnosticsPerFile?: ts.ReadonlyESMap | undefined; + semanticDiagnosticsPerFile?: ReadonlyESMap | undefined; /** * The map has key by source file's path that has been changed */ - changedFilesSet?: ts.ReadonlySet; + changedFilesSet?: ReadonlySet; /** * Set of affected files being iterated */ - affectedFiles?: readonly ts.SourceFile[] | undefined; + affectedFiles?: readonly SourceFile[] | undefined; /** * Current changed file for iterating over affected files */ - currentChangedFilePath?: ts.Path | undefined; + currentChangedFilePath?: Path | undefined; /** * Map of file signatures, with key being file path, calculated while getting current changed file's affected files * These will be committed whenever the iteration through affected files of current changed file is complete */ - currentAffectedFilesSignatures?: ts.ReadonlyESMap | undefined; + currentAffectedFilesSignatures?: ReadonlyESMap | undefined; /** * Newly computed visible to outside referencedSet */ - currentAffectedFilesExportedModulesMap?: ts.BuilderState.ReadonlyManyToManyPathMap | undefined; + currentAffectedFilesExportedModulesMap?: BuilderState.ReadonlyManyToManyPathMap | undefined; /** * True if the semantic diagnostics were copied from the old state */ - semanticDiagnosticsFromOldState?: ts.Set; + semanticDiagnosticsFromOldState?: 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?: readonly ts.Path[] | undefined; + affectedFilesPendingEmit?: readonly Path[] | undefined; /** * Files pending to be emitted kind. */ - affectedFilesPendingEmitKind?: ts.ReadonlyESMap | undefined; + affectedFilesPendingEmitKind?: ReadonlyESMap | undefined; /** * Current index to retrieve pending affected file */ @@ -91,19 +121,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 { +export interface BuilderProgramState 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; /** * Set of affected files being iterated */ - affectedFiles: readonly ts.SourceFile[] | undefined; + affectedFiles: readonly SourceFile[] | undefined; /** * Current index to retrieve affected file from */ @@ -111,22 +141,22 @@ export interface BuilderProgramState extends ts.BuilderState { /** * Current changed file for iterating over affected files */ - currentChangedFilePath: ts.Path | undefined; + currentChangedFilePath: Path | undefined; /** * Map of file signatures, with key being file path, calculated while getting current changed file's affected files * These will be committed whenever the iteration through affected files of current changed file is complete */ - currentAffectedFilesSignatures: ts.ESMap | undefined; + currentAffectedFilesSignatures: ESMap | undefined; /** * Newly computed visible to outside referencedSet * We need to store the updates separately in case the in-progress build is cancelled * and we need to roll back. */ - currentAffectedFilesExportedModulesMap: ts.BuilderState.ManyToManyPathMap | undefined; + currentAffectedFilesExportedModulesMap: BuilderState.ManyToManyPathMap | undefined; /** * Already seen affected files */ - seenAffectedFiles: ts.Set | undefined; + seenAffectedFiles: Set | undefined; /** * whether this program has cleaned semantic diagnostics cache for lib files */ @@ -134,23 +164,23 @@ export interface BuilderProgramState extends ts.BuilderState { /** * True if the semantic diagnostics were copied from the old state */ - semanticDiagnosticsFromOldState?: ts.Set; + semanticDiagnosticsFromOldState?: 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.Path[] | undefined; + affectedFilesPendingEmit: Path[] | undefined; /** * Files pending to be emitted kind. */ - affectedFilesPendingEmitKind: ts.ESMap | undefined; + affectedFilesPendingEmitKind: ESMap | undefined; /** * Current index to retrieve pending affected file */ @@ -162,56 +192,56 @@ export interface BuilderProgramState extends ts.BuilderState { /** * Already seen emitted files */ - seenEmittedFiles: ts.ESMap | undefined; + seenEmittedFiles: ESMap | undefined; /** * true if program has been emitted */ programEmitComplete?: true; /** Stores list of files that change signature during emit - test only */ - filesChangingSignature?: ts.Set; + filesChangingSignature?: Set; } -function hasSameKeys(map1: ts.ReadonlyCollection | 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; // With --out or --outFile, any change affects all semantic diagnostics so no need to cache them - if (!ts.outFile(compilerOptions)) { - state.semanticDiagnosticsPerFile = new ts.Map(); + if (!outFile(compilerOptions)) { + state.semanticDiagnosticsPerFile = new Map(); } - state.changedFilesSet = new ts.Set(); + state.changedFilesSet = new Set(); - 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!); if (useOldState) { // Verify the sanity of old state if (!oldState!.currentChangedFilePath) { const affectedSignatures = oldState!.currentAffectedFilesSignatures; - ts.Debug.assert(!oldState!.affectedFiles && (!affectedSignatures || !affectedSignatures.size), "Cannot reuse if only few affected files of currentChangedFile were iterated"); + Debug.assert(!oldState!.affectedFiles && (!affectedSignatures || !affectedSignatures.size), "Cannot reuse if only few affected files of currentChangedFile were iterated"); } const changedFilesSet = oldState!.changedFilesSet; if (canCopySemanticDiagnostics) { - ts.Debug.assert(!changedFilesSet || !ts.forEachKey(changedFilesSet, path => oldState!.semanticDiagnosticsPerFile!.has(path)), "Semantic diagnostics shouldnt be available for changed files"); + Debug.assert(!changedFilesSet || !forEachKey(changedFilesSet, path => oldState!.semanticDiagnosticsPerFile!.has(path)), "Semantic diagnostics shouldnt be available for changed files"); } // Copy old state's changed files set changedFilesSet?.forEach(value => state.changedFilesSet.add(value)); - if (!ts.outFile(compilerOptions) && oldState!.affectedFilesPendingEmit) { + if (!outFile(compilerOptions) && oldState!.affectedFilesPendingEmit) { state.affectedFilesPendingEmit = oldState!.affectedFilesPendingEmit.slice(); - state.affectedFilesPendingEmitKind = oldState!.affectedFilesPendingEmitKind && new ts.Map(oldState!.affectedFilesPendingEmitKind); + state.affectedFilesPendingEmitKind = oldState!.affectedFilesPendingEmitKind && new Map(oldState!.affectedFilesPendingEmitKind); state.affectedFilesPendingEmitIndex = oldState!.affectedFilesPendingEmitIndex; - state.seenAffectedFiles = new ts.Set(); + state.seenAffectedFiles = new Set(); } } @@ -221,8 +251,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 || @@ -233,7 +263,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 state.changedFilesSet.add(sourceFilePath); } @@ -246,9 +276,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); } @@ -256,19 +286,19 @@ function createBuilderProgramState(newProgram: ts.Program, getCanonicalFileName: }); // If the global file is removed, add all files as changed - if (useOldState && ts.forEachEntry(oldState!.fileInfos, (info, sourceFilePath) => info.affectsGlobalScope && !state.fileInfos.has(sourceFilePath))) { - ts.BuilderState.getAllFilesExcludingDefaultLibraryFile(state, newProgram, /*firstSourceFile*/ undefined) + if (useOldState && forEachEntry(oldState!.fileInfos, (info, sourceFilePath) => info.affectsGlobalScope && !state.fileInfos.has(sourceFilePath))) { + BuilderState.getAllFilesExcludingDefaultLibraryFile(state, newProgram, /*firstSourceFile*/ undefined) .forEach(file => state.changedFilesSet.add(file.resolvedPath)); } - else if (oldCompilerOptions && !ts.outFile(compilerOptions) && ts.compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions)) { + else if (oldCompilerOptions && !outFile(compilerOptions) && compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions)) { // Add all files to affectedFilesPendingEmit since emit changed newProgram.getSourceFiles().forEach(f => addToAffectedFilesPendingEmit(state, f.resolvedPath, BuilderFileEmit.Full)); - 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(); } if (useOldState) { // Any time the interpretation of a source file changes, mark it as changed - ts.forEachEntry(oldState!.fileInfos, (info, sourceFilePath) => { + forEachEntry(oldState!.fileInfos, (info, sourceFilePath) => { if (state.fileInfos.has(sourceFilePath) && state.fileInfos.get(sourceFilePath)!.impliedFormat !== info.impliedFormat) { state.changedFilesSet.add(sourceFilePath); } @@ -279,11 +309,11 @@ function createBuilderProgramState(newProgram: ts.Program, getCanonicalFileName: return state; } -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; @@ -302,7 +332,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, @@ -314,7 +344,7 @@ 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; } @@ -322,23 +352,23 @@ function releaseCache(state: BuilderProgramState) { * Creates a clone of the state */ function cloneBuilderProgramState(state: Readonly): BuilderProgramState { - const newState = ts.BuilderState.clone(state) as BuilderProgramState; - newState.semanticDiagnosticsPerFile = state.semanticDiagnosticsPerFile && new ts.Map(state.semanticDiagnosticsPerFile); - newState.changedFilesSet = new ts.Set(state.changedFilesSet); + const newState = BuilderState.clone(state) as BuilderProgramState; + newState.semanticDiagnosticsPerFile = state.semanticDiagnosticsPerFile && new Map(state.semanticDiagnosticsPerFile); + newState.changedFilesSet = new Set(state.changedFilesSet); newState.affectedFiles = state.affectedFiles; newState.affectedFilesIndex = state.affectedFilesIndex; newState.currentChangedFilePath = state.currentChangedFilePath; - newState.currentAffectedFilesSignatures = state.currentAffectedFilesSignatures && new ts.Map(state.currentAffectedFilesSignatures); + newState.currentAffectedFilesSignatures = state.currentAffectedFilesSignatures && new Map(state.currentAffectedFilesSignatures); newState.currentAffectedFilesExportedModulesMap = state.currentAffectedFilesExportedModulesMap?.clone(); - newState.seenAffectedFiles = state.seenAffectedFiles && new ts.Set(state.seenAffectedFiles); + newState.seenAffectedFiles = state.seenAffectedFiles && new Set(state.seenAffectedFiles); newState.cleanedDiagnosticsOfLibFiles = state.cleanedDiagnosticsOfLibFiles; - newState.semanticDiagnosticsFromOldState = state.semanticDiagnosticsFromOldState && new ts.Set(state.semanticDiagnosticsFromOldState); + newState.semanticDiagnosticsFromOldState = state.semanticDiagnosticsFromOldState && new Set(state.semanticDiagnosticsFromOldState); newState.program = state.program; newState.compilerOptions = state.compilerOptions; newState.affectedFilesPendingEmit = state.affectedFilesPendingEmit && state.affectedFilesPendingEmit.slice(); - newState.affectedFilesPendingEmitKind = state.affectedFilesPendingEmitKind && new ts.Map(state.affectedFilesPendingEmitKind); + newState.affectedFilesPendingEmitKind = state.affectedFilesPendingEmitKind && new Map(state.affectedFilesPendingEmitKind); newState.affectedFilesPendingEmitIndex = state.affectedFilesPendingEmitIndex; - newState.seenEmittedFiles = state.seenEmittedFiles && new ts.Map(state.seenEmittedFiles); + newState.seenEmittedFiles = state.seenEmittedFiles && new Map(state.seenEmittedFiles); newState.programEmitComplete = state.programEmitComplete; return newState; } @@ -346,8 +376,8 @@ function cloneBuilderProgramState(state: Readonly): Builder /** * 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)); } /** @@ -356,7 +386,7 @@ function assertSourceFileOkWithoutNextAffectedCall(state: BuilderProgramState, s * This is to allow the callers to be able to actually remove affected file only when the operation is complete * eg. if during diagnostics check cancellation token ends up cancelling the request, the affected file should be retained */ -function getNextAffectedFile(state: BuilderProgramState, cancellationToken: ts.CancellationToken | undefined, computeHash: ts.BuilderState.ComputeHash, host: ts.BuilderProgramHost): ts.SourceFile | ts.Program | undefined { +function getNextAffectedFile(state: BuilderProgramState, cancellationToken: CancellationToken | undefined, computeHash: BuilderState.ComputeHash, host: BuilderProgramHost): SourceFile | Program | undefined { while (true) { const { affectedFiles } = state; if (affectedFiles) { @@ -377,9 +407,9 @@ function getNextAffectedFile(state: BuilderProgramState, cancellationToken: ts.C state.changedFilesSet.delete(state.currentChangedFilePath!); state.currentChangedFilePath = undefined; // Commit the changes in file signature - ts.BuilderState.updateSignaturesFromCache(state, state.currentAffectedFilesSignatures!); + BuilderState.updateSignaturesFromCache(state, state.currentAffectedFilesSignatures!); state.currentAffectedFilesSignatures!.clear(); - ts.BuilderState.updateExportedFilesMapFromCache(state, state.currentAffectedFilesExportedModulesMap); + BuilderState.updateExportedFilesMapFromCache(state, state.currentAffectedFilesExportedModulesMap); state.currentAffectedFilesExportedModulesMap?.clear(); state.affectedFiles = undefined; } @@ -393,22 +423,22 @@ function getNextAffectedFile(state: BuilderProgramState, cancellationToken: ts.C // 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 - if (!state.currentAffectedFilesSignatures) state.currentAffectedFilesSignatures = new ts.Map(); + if (!state.currentAffectedFilesSignatures) state.currentAffectedFilesSignatures = new Map(); if (state.exportedModulesMap) { - state.currentAffectedFilesExportedModulesMap ||= ts.BuilderState.createManyToManyPathMap(); + state.currentAffectedFilesExportedModulesMap ||= BuilderState.createManyToManyPathMap(); } - state.affectedFiles = ts.BuilderState.getFilesAffectedBy(state, program, nextKey.value, cancellationToken, computeHash, state.currentAffectedFilesSignatures, state.currentAffectedFilesExportedModulesMap); + state.affectedFiles = BuilderState.getFilesAffectedBy(state, program, nextKey.value, cancellationToken, computeHash, state.currentAffectedFilesSignatures, state.currentAffectedFilesExportedModulesMap); state.currentChangedFilePath = nextKey.value; state.affectedFilesIndex = 0; - if (!state.seenAffectedFiles) state.seenAffectedFiles = new ts.Set(); + if (!state.seenAffectedFiles) state.seenAffectedFiles = new Set(); } } @@ -424,12 +454,12 @@ function clearAffectedFilesPendingEmit(state: BuilderProgramState) { function getNextAffectedFilePendingEmit(state: BuilderProgramState) { const { affectedFilesPendingEmit } = state; if (affectedFilesPendingEmit) { - const seenEmittedFiles = (state.seenEmittedFiles || (state.seenEmittedFiles = new ts.Map())); + const seenEmittedFiles = (state.seenEmittedFiles || (state.seenEmittedFiles = new Map())); for (let i = state.affectedFilesPendingEmitIndex!; i < affectedFilesPendingEmit.length; i++) { - const affectedFile = ts.Debug.checkDefined(state.program).getSourceFileByPath(affectedFilesPendingEmit[i]); + const affectedFile = Debug.checkDefined(state.program).getSourceFileByPath(affectedFilesPendingEmit[i]); if (affectedFile) { const seenKind = seenEmittedFiles.get(affectedFile.resolvedPath); - const emitKind = ts.Debug.checkDefined(ts.Debug.checkDefined(state.affectedFilesPendingEmitKind).get(affectedFile.resolvedPath)); + const emitKind = Debug.checkDefined(Debug.checkDefined(state.affectedFilesPendingEmitKind).get(affectedFile.resolvedPath)); if (seenKind === undefined || seenKind < emitKind) { // emit this file state.affectedFilesPendingEmitIndex = i; @@ -445,11 +475,11 @@ function getNextAffectedFilePendingEmit(state: BuilderProgramState) { 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) ); } @@ -461,10 +491,10 @@ function removeDiagnosticsOfLibraryFiles(state: BuilderProgramState) { */ function handleDtsMayChangeOfAffectedFile( state: BuilderProgramState, - affectedFile: ts.SourceFile, - cancellationToken: ts.CancellationToken | undefined, - computeHash: ts.BuilderState.ComputeHash, - host: ts.BuilderProgramHost, + affectedFile: SourceFile, + cancellationToken: CancellationToken | undefined, + computeHash: BuilderState.ComputeHash, + host: BuilderProgramHost, ) { removeSemanticDiagnosticsOf(state, affectedFile.resolvedPath); @@ -474,18 +504,18 @@ 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, - ts.Debug.checkDefined(state.currentAffectedFilesSignatures), + Debug.checkDefined(state.currentAffectedFilesSignatures), cancellationToken, computeHash, state.currentAffectedFilesExportedModulesMap ); return; } - ts.Debug.assert(state.hasCalledUpdateShapeSignature.has(affectedFile.resolvedPath) || state.currentAffectedFilesSignatures?.has(affectedFile.resolvedPath), `Signature not updated for affected file: ${affectedFile.fileName}`); + Debug.assert(state.hasCalledUpdateShapeSignature.has(affectedFile.resolvedPath) || state.currentAffectedFilesSignatures?.has(affectedFile.resolvedPath), `Signature not updated for affected file: ${affectedFile.fileName}`); if (state.compilerOptions.assumeChangesOnlyAffectDirectDependencies) return; handleDtsMayChangeOfReferencingExportOfAffectedFile(state, affectedFile, cancellationToken, computeHash, host); } @@ -496,15 +526,15 @@ function handleDtsMayChangeOfAffectedFile( */ function handleDtsMayChangeOf( state: BuilderProgramState, - path: ts.Path, - cancellationToken: ts.CancellationToken | undefined, - computeHash: ts.BuilderState.ComputeHash, - host: ts.BuilderProgramHost + path: Path, + cancellationToken: CancellationToken | undefined, + computeHash: BuilderState.ComputeHash, + 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 @@ -512,18 +542,18 @@ 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, - ts.Debug.checkDefined(state.currentAffectedFilesSignatures), + Debug.checkDefined(state.currentAffectedFilesSignatures), cancellationToken, computeHash, state.currentAffectedFilesExportedModulesMap, !host.disableUseFileVersionAsSignature ); // If not dts emit, nothing more to do - if (ts.getEmitDeclarations(state.compilerOptions)) { + if (getEmitDeclarations(state.compilerOptions)) { addToAffectedFilesPendingEmit(state, path, BuilderFileEmit.DtsOnly); } } @@ -534,7 +564,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; } @@ -543,25 +573,25 @@ function removeSemanticDiagnosticsOf(state: BuilderProgramState, path: ts.Path) return !state.semanticDiagnosticsFromOldState.size; } -function isChangedSignature(state: BuilderProgramState, path: ts.Path) { - const newSignature = ts.Debug.checkDefined(state.currentAffectedFilesSignatures).get(path); - const oldSignature = ts.Debug.checkDefined(state.fileInfos.get(path)).signature; +function isChangedSignature(state: BuilderProgramState, path: Path) { + const newSignature = Debug.checkDefined(state.currentAffectedFilesSignatures).get(path); + const oldSignature = Debug.checkDefined(state.fileInfos.get(path)).signature; return newSignature !== oldSignature; } function forEachKeyOfExportedModulesMap( state: BuilderProgramState, - filePath: ts.Path, - fn: (exportedFromPath: ts.Path) => T | undefined, + filePath: Path, + fn: (exportedFromPath: Path) => T | undefined, ): T | undefined { // Go through exported modules from cache first let keys = state.currentAffectedFilesExportedModulesMap!.getKeys(filePath); - const result = keys && ts.forEachKey(keys, fn); + const result = keys && forEachKey(keys, fn); if (result) return result; // If exported from path is not from cache and exported modules has path, all files referencing file exported from are affected keys = state.exportedModulesMap!.getKeys(filePath); - return keys && ts.forEachKey(keys, exportedFromPath => + return keys && forEachKey(keys, exportedFromPath => // If the cache had an updated value, skip !state.currentAffectedFilesExportedModulesMap!.hasKey(exportedFromPath) && !state.currentAffectedFilesExportedModulesMap!.deletedKeys()?.has(exportedFromPath) ? @@ -572,14 +602,14 @@ function forEachKeyOfExportedModulesMap( function handleDtsMayChangeOfGlobalScope( state: BuilderProgramState, - filePath: ts.Path, - cancellationToken: ts.CancellationToken | undefined, - computeHash: ts.BuilderState.ComputeHash, - host: ts.BuilderProgramHost, + filePath: Path, + cancellationToken: CancellationToken | undefined, + computeHash: BuilderState.ComputeHash, + 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, @@ -596,10 +626,10 @@ function handleDtsMayChangeOfGlobalScope( */ function handleDtsMayChangeOfReferencingExportOfAffectedFile( state: BuilderProgramState, - affectedFile: ts.SourceFile, - cancellationToken: ts.CancellationToken | undefined, - computeHash: ts.BuilderState.ComputeHash, - host: ts.BuilderProgramHost + affectedFile: SourceFile, + cancellationToken: CancellationToken | undefined, + computeHash: BuilderState.ComputeHash, + host: BuilderProgramHost ) { // If there was change in signature (dts output) for the changed file, // then only we need to handle pending file emit @@ -609,9 +639,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)) { @@ -619,21 +649,21 @@ function handleDtsMayChangeOfReferencingExportOfAffectedFile( if (handleDtsMayChangeOfGlobalScope(state, currentPath, cancellationToken, computeHash, host)) return; handleDtsMayChangeOf(state, currentPath, cancellationToken, computeHash, 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)); } } } } - ts.Debug.assert(!!state.currentAffectedFilesExportedModulesMap); - const seenFileAndExportsOfFile = new ts.Set(); + Debug.assert(!!state.currentAffectedFilesExportedModulesMap); + const seenFileAndExportsOfFile = new Set(); // Go through exported modules from cache first // If exported modules has path, all files referencing file exported from are affected forEachKeyOfExportedModulesMap(state, affectedFile.resolvedPath, exportedFromPath => { if (handleDtsMayChangeOfGlobalScope(state, exportedFromPath, cancellationToken, computeHash, host)) return true; const references = state.referencedMap!.getKeys(exportedFromPath); - return references && ts.forEachKey(references, filePath => + return references && forEachKey(references, filePath => handleDtsMayChangeOfFileAndExportsOfFile( state, filePath, @@ -652,17 +682,17 @@ function handleDtsMayChangeOfReferencingExportOfAffectedFile( */ function handleDtsMayChangeOfFileAndExportsOfFile( state: BuilderProgramState, - filePath: ts.Path, - seenFileAndExportsOfFile: ts.Set, - cancellationToken: ts.CancellationToken | undefined, - computeHash: ts.BuilderState.ComputeHash, - host: ts.BuilderProgramHost, + filePath: Path, + seenFileAndExportsOfFile: Set, + cancellationToken: CancellationToken | undefined, + computeHash: BuilderState.ComputeHash, + host: BuilderProgramHost, ): boolean | undefined { - if (!ts.tryAddToSet(seenFileAndExportsOfFile, filePath)) return undefined; + if (!tryAddToSet(seenFileAndExportsOfFile, filePath)) return undefined; if (handleDtsMayChangeOfGlobalScope(state, filePath, cancellationToken, computeHash, host)) return true; handleDtsMayChangeOf(state, filePath, cancellationToken, computeHash, host); - ts.Debug.assert(!!state.currentAffectedFilesExportedModulesMap); + Debug.assert(!!state.currentAffectedFilesExportedModulesMap); // If exported modules has path, all files referencing file exported from are affected forEachKeyOfExportedModulesMap(state, filePath, exportedFromPath => @@ -696,7 +726,7 @@ function handleDtsMayChangeOfFileAndExportsOfFile( */ function doneWithAffectedFile( state: BuilderProgramState, - affected: ts.SourceFile | ts.Program, + affected: SourceFile | Program, emitKind?: BuilderFileEmit, isPendingEmit?: boolean, isBuildInfoEmit?: boolean @@ -709,9 +739,9 @@ function doneWithAffectedFile( state.programEmitComplete = true; } else { - state.seenAffectedFiles!.add((affected as ts.SourceFile).resolvedPath); + state.seenAffectedFiles!.add((affected as SourceFile).resolvedPath); if (emitKind !== undefined) { - (state.seenEmittedFiles || (state.seenEmittedFiles = new ts.Map())).set((affected as ts.SourceFile).resolvedPath, emitKind); + (state.seenEmittedFiles || (state.seenEmittedFiles = new Map())).set((affected as SourceFile).resolvedPath, emitKind); } if (isPendingEmit) { state.affectedFilesPendingEmitIndex!++; @@ -726,7 +756,7 @@ function doneWithAffectedFile( /** * Returns the result with affected file */ -function toAffectedFileResult(state: BuilderProgramState, result: T, affected: ts.SourceFile | ts.Program): ts.AffectedFileResult { +function toAffectedFileResult(state: BuilderProgramState, result: T, affected: SourceFile | Program): AffectedFileResult { doneWithAffectedFile(state, affected); return { result, affected }; } @@ -736,12 +766,12 @@ function toAffectedFileResult(state: BuilderProgramState, result: T, affected */ function toAffectedFileEmitResult( state: BuilderProgramState, - result: ts.EmitResult, - affected: ts.SourceFile | ts.Program, + result: EmitResult, + affected: SourceFile | Program, emitKind: BuilderFileEmit, isPendingEmit?: boolean, isBuildInfoEmit?: boolean -): ts.AffectedFileResult { +): AffectedFileResult { doneWithAffectedFile(state, affected, emitKind, isPendingEmit, isBuildInfoEmit); return { result, affected }; } @@ -750,10 +780,10 @@ function toAffectedFileEmitResult( * 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) ); } @@ -761,22 +791,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 */ @@ -790,7 +820,7 @@ export type ProgramBuilderInfoFilePendingEmit = [fileId: ProgramBuildInfoFileId, /* @internal */ export type ProgramBuildInfoReferencedMap = [fileId: ProgramBuildInfoFileId, fileIdListId: ProgramBuildInfoFileIdListId][]; /* @internal */ -export type ProgramBuildInfoBuilderStateFileInfo = Omit & { +export type ProgramBuildInfoBuilderStateFileInfo = Omit & { /** * Signature is * - undefined if FileInfo.version === FileInfo.signature @@ -808,7 +838,7 @@ export type ProgramBuildInfoFileInfo = string | ProgramBuildInfoBuilderStateFile export interface ProgramBuildInfo { fileNames: readonly string[]; fileInfos: readonly ProgramBuildInfoFileInfo[]; - options: ts.CompilerOptions | undefined; + options: CompilerOptions | undefined; fileIdsList?: readonly (readonly ProgramBuildInfoFileId[])[]; referencedMap?: ProgramBuildInfoReferencedMap; exportedModulesMap?: ProgramBuildInfoReferencedMap; @@ -819,18 +849,18 @@ export interface ProgramBuildInfo { /** * Gets the program information to be emitted in buildInfo so that we can use it to create new program */ -function getProgramBuildInfo(state: Readonly, getCanonicalFileName: ts.GetCanonicalFileName): ProgramBuildInfo | undefined { - if (ts.outFile(state.compilerOptions)) return undefined; - const currentDirectory = ts.Debug.checkDefined(state.program).getCurrentDirectory(); - const buildInfoDirectory = ts.getDirectoryPath(ts.getNormalizedAbsolutePath(ts.getTsBuildInfoEmitOutputFilePath(state.compilerOptions)!, currentDirectory)); +function getProgramBuildInfo(state: Readonly, getCanonicalFileName: GetCanonicalFileName): ProgramBuildInfo | undefined { + if (outFile(state.compilerOptions)) return undefined; + const currentDirectory = Debug.checkDefined(state.program).getCurrentDirectory(); + const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(getTsBuildInfoEmitOutputFilePath(state.compilerOptions)!, currentDirectory)); const fileNames: string[] = []; - const fileNameToFileId = new ts.Map(); + const fileNameToFileId = new Map(); let fileIdsList: (readonly ProgramBuildInfoFileId[])[] | undefined; - let fileNamesToFileIdListId: ts.ESMap | undefined; - const fileInfos = ts.arrayFrom(state.fileInfos.entries(), ([key, value]): ProgramBuildInfoFileInfo => { + let fileNamesToFileIdListId: ESMap | undefined; + const fileInfos = arrayFrom(state.fileInfos.entries(), ([key, value]): ProgramBuildInfoFileInfo => { // Ensure fileId const fileId = toFileId(key); - ts.Debug.assert(fileNames[fileId - 1] === relativeToBuildInfo(key)); + Debug.assert(fileNames[fileId - 1] === relativeToBuildInfo(key)); const signature = state.currentAffectedFilesSignatures && state.currentAffectedFilesSignatures.get(key); const actualSignature = signature ?? value.signature; return value.version === actualSignature ? @@ -851,7 +881,7 @@ function getProgramBuildInfo(state: Readonly, 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)!) ]); @@ -859,7 +889,7 @@ function getProgramBuildInfo(state: Readonly, 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 => { if (state.currentAffectedFilesExportedModulesMap) { if (state.currentAffectedFilesExportedModulesMap.deletedKeys()?.has(key)) { return undefined; @@ -878,7 +908,7 @@ function getProgramBuildInfo(state: Readonly, 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 ? @@ -886,7 +916,7 @@ function getProgramBuildInfo(state: Readonly, getCa toFileId(key), state.hasReusableDiagnostic ? value as readonly ReusableDiagnostic[] : - convertToReusableDiagnostics(value as readonly ts.Diagnostic[], relativeToBuildInfo) + convertToReusableDiagnostics(value as readonly Diagnostic[], relativeToBuildInfo) ] : toFileId(key) ); @@ -895,9 +925,9 @@ function getProgramBuildInfo(state: Readonly, getCa let affectedFilesPendingEmit: ProgramBuilderInfoFilePendingEmit[] | undefined; if (state.affectedFilesPendingEmit) { - const seenFiles = new ts.Set(); - for (const path of state.affectedFilesPendingEmit.slice(state.affectedFilesPendingEmitIndex).sort(ts.compareStringsCaseSensitive)) { - if (ts.tryAddToSet(seenFiles, path)) { + const seenFiles = new Set(); + for (const path of state.affectedFilesPendingEmit.slice(state.affectedFilesPendingEmitIndex).sort(compareStringsCaseSensitive)) { + if (tryAddToSet(seenFiles, path)) { (affectedFilesPendingEmit ||= []).push([toFileId(path), state.affectedFilesPendingEmitKind!.get(path)!]); } } @@ -915,14 +945,14 @@ function getProgramBuildInfo(state: Readonly, getCa }; 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)); @@ -931,23 +961,23 @@ function getProgramBuildInfo(state: Readonly, 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; } } -function convertToProgramBuildInfoCompilerOptions(options: ts.CompilerOptions, relativeToBuildInfo: (path: string) => string) { - let result: ts.CompilerOptions | undefined; - const { optionsNameMap } = ts.getOptionsNameMap(); +function convertToProgramBuildInfoCompilerOptions(options: CompilerOptions, relativeToBuildInfo: (path: string) => string) { + let result: CompilerOptions | undefined; + const { optionsNameMap } = getOptionsNameMap(); - for (const name of ts.getOwnKeys(options).sort(ts.compareStringsCaseSensitive)) { + for (const name of getOwnKeys(options).sort(compareStringsCaseSensitive)) { const optionKey = name.toLowerCase(); const optionInfo = optionsNameMap.get(optionKey); if (optionInfo?.affectsEmit || optionInfo?.affectsSemanticDiagnostics || @@ -958,7 +988,7 @@ function convertToProgramBuildInfoCompilerOptions(options: ts.CompilerOptions, r optionKey === "skiplibcheck" || optionKey === "skipdefaultlibcheck") { (result ||= {})[name] = convertToReusableCompilerOptionValue( optionInfo, - options[name] as ts.CompilerOptionsValue, + options[name] as CompilerOptionsValue, relativeToBuildInfo ); } @@ -966,7 +996,7 @@ function convertToProgramBuildInfoCompilerOptions(options: ts.CompilerOptions, r return result; } -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)[]; @@ -981,8 +1011,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; @@ -999,7 +1029,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, @@ -1015,49 +1045,49 @@ 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 }; } /* @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 @@ -1071,11 +1101,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); let state = createBuilderProgramState(newProgram, getCanonicalFileName, oldState, host.disableUseFileVersionAsSignature); let backupState: BuilderProgramState | undefined; newProgram.getProgramBuildInfo = () => getProgramBuildInfo(state, getCanonicalFileName); @@ -1089,14 +1119,14 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos const builderProgram = createRedirectedBuilderProgram(getState, configFileParsingDiagnostics); builderProgram.getState = getState; builderProgram.backupState = () => { - ts.Debug.assert(backupState === undefined); + Debug.assert(backupState === undefined); backupState = cloneBuilderProgramState(state); }; builderProgram.restoreState = () => { - state = ts.Debug.checkDefined(backupState); + state = Debug.checkDefined(backupState); backupState = undefined; }; - 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 = () => { @@ -1105,26 +1135,26 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos }; 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; } /** @@ -1132,24 +1162,24 @@ 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, host); let emitKind = BuilderFileEmit.Full; let isPendingEmitFile = false; if (!affected) { - if (!ts.outFile(state.compilerOptions)) { + if (!outFile(state.compilerOptions)) { const pendingAffectedFile = getNextAffectedFilePendingEmit(state); if (!pendingAffectedFile) { if (!state.buildInfoEmitPending) { return undefined; } - const affected = ts.Debug.checkDefined(state.program); + const affected = Debug.checkDefined(state.program); return toAffectedFileEmitResult( state, // When whole program is affected, do emit only once (eg when --out or --outFile is specified) // Otherwise just affected file - affected.emitBuildInfo(writeFile || ts.maybeBind(host, host.writeFile), cancellationToken), + affected.emitBuildInfo(writeFile || maybeBind(host, host.writeFile), cancellationToken), affected, /*emitKind*/ BuilderFileEmit.Full, /*isPendingEmitFile*/ false, @@ -1160,7 +1190,7 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos isPendingEmitFile = true; } else { - const program = ts.Debug.checkDefined(state.program); + const program = Debug.checkDefined(state.program); if (state.programEmitComplete) return undefined; affected = program; } @@ -1170,11 +1200,11 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos state, // When whole program is affected, do emit only once (eg when --out or --outFile is specified) // Otherwise just affected file - ts.Debug.checkDefined(state.program).emit( - affected === state.program ? undefined : affected as ts.SourceFile, - affected !== state.program && ts.getEmitDeclarations(state.compilerOptions) && !customTransformers ? + Debug.checkDefined(state.program).emit( + affected === state.program ? undefined : affected as SourceFile, + affected !== state.program && getEmitDeclarations(state.compilerOptions) && !customTransformers ? getWriteFileUpdatingSignatureCallback(writeFile) : - writeFile || ts.maybeBind(host, host.writeFile), + writeFile || maybeBind(host, host.writeFile), cancellationToken, emitOnlyDtsFiles || emitKind === BuilderFileEmit.DtsOnly, customTransformers @@ -1185,24 +1215,24 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos ); } - function getWriteFileUpdatingSignatureCallback(writeFile: ts.WriteFileCallback | undefined): ts.WriteFileCallback { + function getWriteFileUpdatingSignatureCallback(writeFile: WriteFileCallback | undefined): WriteFileCallback { return (fileName, text, writeByteOrderMark, onError, sourceFiles, data) => { - if (ts.isDeclarationFileName(fileName)) { - ts.Debug.assert(sourceFiles?.length === 1); + if (isDeclarationFileName(fileName)) { + Debug.assert(sourceFiles?.length === 1); const file = sourceFiles[0]; const info = state.fileInfos.get(file.resolvedPath)!; const signature = state.currentAffectedFilesSignatures?.get(file.resolvedPath) || info.signature; if (signature === file.version) { - const newSignature = (computeHash || ts.generateDjb2Hash)(data?.sourceMapUrlPos !== undefined ? text.substring(0, data.sourceMapUrlPos) : text); + const newSignature = (computeHash || generateDjb2Hash)(data?.sourceMapUrlPos !== undefined ? text.substring(0, data.sourceMapUrlPos) : text); if (newSignature !== file.version) { // Update it - if (host.storeFilesChangingSignatureDuringEmit) (state.filesChangingSignature ||= new ts.Set()).add(file.resolvedPath); - if (state.exportedModulesMap) ts.BuilderState.updateExportedModules(file, file.exportedModulesFromDeclarationEmit, state.currentAffectedFilesExportedModulesMap ||= ts.BuilderState.createManyToManyPathMap()); + if (host.storeFilesChangingSignatureDuringEmit) (state.filesChangingSignature ||= new Set()).add(file.resolvedPath); + if (state.exportedModulesMap) BuilderState.updateExportedModules(file, file.exportedModulesFromDeclarationEmit, state.currentAffectedFilesExportedModulesMap ||= BuilderState.createManyToManyPathMap()); if (state.affectedFiles && state.affectedFilesIndex! < state.affectedFiles.length) { state.currentAffectedFilesSignatures!.set(file.resolvedPath, newSignature); } else { info.signature = newSignature; - if (state.exportedModulesMap) ts.BuilderState.updateExportedFilesMapFromCache(state, state.currentAffectedFilesExportedModulesMap); + if (state.exportedModulesMap) BuilderState.updateExportedFilesMapFromCache(state, state.currentAffectedFilesExportedModulesMap); } } } @@ -1224,54 +1254,54 @@ 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 }; } // In non Emit builder, clear affected files pending emit else if (state.affectedFilesPendingEmitKind?.size) { - ts.Debug.assert(kind === BuilderProgramKind.SemanticDiagnosticsBuilderProgram); + Debug.assert(kind === BuilderProgramKind.SemanticDiagnosticsBuilderProgram); // State can clear affected files pending emit if if (!emitOnlyDtsFiles // If we are doing complete emit, affected files pending emit can be cleared // If every file pending emit is pending on only dts emit - || ts.every(state.affectedFilesPendingEmit, (path, index) => + || every(state.affectedFilesPendingEmit, (path, index) => index < state.affectedFilesPendingEmitIndex! || state.affectedFilesPendingEmitKind!.get(path) === BuilderFileEmit.DtsOnly)) { clearAffectedFilesPendingEmit(state); } } } - return ts.Debug.checkDefined(state.program).emit( + return Debug.checkDefined(state.program).emit( targetSourceFile, - !ts.outFile(state.compilerOptions) && ts.getEmitDeclarations(state.compilerOptions) && !customTransformers ? + !outFile(state.compilerOptions) && getEmitDeclarations(state.compilerOptions) && !customTransformers ? getWriteFileUpdatingSignatureCallback(writeFile) : - writeFile || ts.maybeBind(host, host.writeFile), + writeFile || maybeBind(host, host.writeFile), cancellationToken, emitOnlyDtsFiles, customTransformers @@ -1282,7 +1312,7 @@ 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, host); if (!affected) { @@ -1301,11 +1331,11 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos // Add file to affected file pending emit to handle for later emit time // Apart for emit builder do this for tsbuildinfo, do this for non emit builder when noEmit is set as tsbuildinfo is written and reused between emitters if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram || state.compilerOptions.noEmit || state.compilerOptions.noEmitOnError) { - addToAffectedFilesPendingEmit(state, (affected as ts.SourceFile).resolvedPath, BuilderFileEmit.Full); + addToAffectedFilesPendingEmit(state, (affected as SourceFile).resolvedPath, BuilderFileEmit.Full); } // Get diagnostics for the affected file if its not ignored - if (ignoreSourceFile && ignoreSourceFile(affected as ts.SourceFile)) { + if (ignoreSourceFile && ignoreSourceFile(affected as SourceFile)) { // Get next affected file doneWithAffectedFile(state, affected); continue; @@ -1313,7 +1343,7 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos return toAffectedFileResult( state, - getSemanticDiagnosticsOfFile(state, affected as ts.SourceFile, cancellationToken), + getSemanticDiagnosticsOfFile(state, affected as SourceFile, cancellationToken), affected ); } @@ -1327,13 +1357,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) { @@ -1346,17 +1376,17 @@ 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) { if (!state.affectedFilesPendingEmit) state.affectedFilesPendingEmit = []; - if (!state.affectedFilesPendingEmitKind) state.affectedFilesPendingEmitKind = new ts.Map(); + if (!state.affectedFilesPendingEmitKind) state.affectedFilesPendingEmitKind = new Map(); const existingKind = state.affectedFilesPendingEmitKind.get(affectedFilePendingEmit); state.affectedFilesPendingEmit.push(affectedFilePendingEmit); @@ -1372,57 +1402,57 @@ function addToAffectedFilesPendingEmit(state: BuilderProgramState, affectedFileP } /* @internal */ -export function toBuilderStateFileInfo(fileInfo: ProgramBuildInfoFileInfo): ts.BuilderState.FileInfo { - return ts.isString(fileInfo) ? +export function toBuilderStateFileInfo(fileInfo: ProgramBuildInfoFileInfo): 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 createBuildProgramUsingProgramBuildInfo(program: ProgramBuildInfo, buildInfoPath: string, host: ts.ReadBuildProgramHost): ts.EmitAndSemanticDiagnosticsBuilderProgram { - const buildInfoDirectory = ts.getDirectoryPath(ts.getNormalizedAbsolutePath(buildInfoPath, host.getCurrentDirectory())); - const getCanonicalFileName = ts.createGetCanonicalFileName(host.useCaseSensitiveFileNames()); +export function createBuildProgramUsingProgramBuildInfo(program: ProgramBuildInfo, buildInfoPath: string, host: ReadBuildProgramHost): EmitAndSemanticDiagnosticsBuilderProgram { + const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(buildInfoPath, host.getCurrentDirectory())); + const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); const filePaths = program.fileNames.map(toPath); - const filePathsSetList = program.fileIdsList?.map(fileIds => new ts.Set(fileIds.map(toFilePath))); - const fileInfos = new ts.Map(); + const filePathsSetList = program.fileIdsList?.map(fileIds => new Set(fileIds.map(toFilePath))); + const fileInfos = new Map(); program.fileInfos.forEach((fileInfo, index) => fileInfos.set(toFilePath(index + 1 as ProgramBuildInfoFileId), toBuilderStateFileInfo(fileInfo))); const state: ReusableBuilderProgramState = { 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: ts.map(program.affectedFilesPendingEmit, value => toFilePath(value[0])), - affectedFilesPendingEmitKind: program.affectedFilesPendingEmit && ts.arrayToMap(program.affectedFilesPendingEmit, value => toFilePath(value[0]), value => value[1]), + affectedFilesPendingEmit: map(program.affectedFilesPendingEmit, value => toFilePath(value[0])), + affectedFilesPendingEmitKind: program.affectedFilesPendingEmit && arrayToMap(program.affectedFilesPendingEmit, value => toFilePath(value[0]), value => value[1]), affectedFilesPendingEmitIndex: program.affectedFilesPendingEmit && 0, }; return { getState: () => state, - backupState: ts.noop, - restoreState: ts.noop, - getProgram: ts.notImplemented, - getProgramOrUndefined: ts.returnUndefined, - releaseProgram: ts.noop, + backupState: noop, + restoreState: 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, + 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, }; function toPath(path: string) { @@ -1430,7 +1460,7 @@ export function createBuildProgramUsingProgramBuildInfo(program: ProgramBuildInf } function toAbsolutePath(path: string) { - return ts.getNormalizedAbsolutePath(path, buildInfoDirectory); + return getNormalizedAbsolutePath(path, buildInfoDirectory); } function toFilePath(fileId: ProgramBuildInfoFileId) { @@ -1441,12 +1471,12 @@ export function createBuildProgramUsingProgramBuildInfo(program: ProgramBuildInf 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)) ); @@ -1455,11 +1485,11 @@ export function createBuildProgramUsingProgramBuildInfo(program: ProgramBuildInf } /* @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, - backupState: ts.noop, - restoreState: ts.noop, + getState: notImplemented, + backupState: noop, + restoreState: noop, getProgram, getProgramOrUndefined: () => getState().program, releaseProgram: () => getState().program = undefined, @@ -1474,12 +1504,12 @@ export function createRedirectedBuilderProgram(getState: () => { program: ts.Pro 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 d3bab73d1e321..7e6b00bbe3d87 100644 --- a/src/compiler/builderPublic.ts +++ b/src/compiler/builderPublic.ts @@ -1,6 +1,13 @@ -import * as ts from "./_namespaces/ts"; +import { + BuilderProgramKind, createBuilderProgram, createRedirectedBuilderProgram, getBuilderCreationParameters, + ReusableBuilderProgramState, +} from "./builder"; +import { + CancellationToken, CompilerHost, CompilerOptions, CustomTransformers, Diagnostic, DiagnosticWithLocation, + EmitResult, Program, ProjectReference, SourceFile, WriteFileCallback, +} from "./types"; -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 +22,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 */ @@ -33,7 +40,7 @@ export interface BuilderProgramHost { */ export interface BuilderProgram { /*@internal*/ - getState(): ts.ReusableBuilderProgramState; + getState(): ReusableBuilderProgramState; /*@internal*/ backupState(): void; /*@internal*/ @@ -41,12 +48,12 @@ export interface BuilderProgram { /** * 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. */ @@ -55,39 +62,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 @@ -97,7 +104,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, @@ -109,9 +116,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 */ @@ -128,7 +135,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; } /** @@ -141,34 +148,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 6efbd0905d26a..35c46fcab6d12 100644 --- a/src/compiler/builderState.ts +++ b/src/compiler/builderState.ts @@ -1,9 +1,26 @@ -import * as ts from "./_namespaces/ts"; +import { EmitOutput, OutputFile } from "./builderStatePublic"; +import { + arrayFrom, emptyArray, firstOrUndefined, GetCanonicalFileName, mapDefined, mapDefinedIterator, some, +} from "./core"; +import { ESMap, Iterator, Map, ReadonlyESMap, ReadonlySet, Set } from "./corePublic"; +import { Debug } from "./debug"; +import { isStringLiteral } from "./factory/nodeTests"; +import { isDeclarationFileName } from "./parser"; +import { getAnyExtensionFromPath, getDirectoryPath, toPath } from "./path"; +import { generateDjb2Hash } from "./sys"; +import { + CancellationToken, CustomTransformers, ExportedModulesFromDeclarationEmit, ModuleDeclaration, ModuleKind, Path, + Program, SourceFile, StringLiteralLike, Symbol, TypeChecker, +} from "./types"; +import { + getSourceFileOfNode, isExternalOrCommonJsModule, isGlobalScopeAugmentation, isJsonSourceFile, + isModuleWithStringLiteralName, outFile, +} from "./utilities"; /* @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, exportedModulesFromDeclarationEmit } = program.emit(sourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers, forceDtsEmit); return { outputFiles, emitSkipped, diagnostics, exportedModulesFromDeclarationEmit }; @@ -17,7 +34,7 @@ export interface ReusableBuilderState { /** * Information of the file eg. its version, signature etc */ - fileInfos: ts.ReadonlyESMap; + fileInfos: ReadonlyESMap; /** * Contains the map of ReferencedSet=Referenced files of the file if module emit is enabled * Otherwise undefined @@ -36,7 +53,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 @@ -61,11 +78,11 @@ 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; /** * 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 */ @@ -86,30 +103,30 @@ export namespace BuilderState { export interface ReadonlyManyToManyPathMap { clone(): ManyToManyPathMap; - forEach(action: (v: ts.ReadonlySet, k: ts.Path) => void): void; - getKeys(v: ts.Path): ts.ReadonlySet | undefined; - getValues(k: ts.Path): ts.ReadonlySet | undefined; - hasKey(k: ts.Path): boolean; - keys(): ts.Iterator; + forEach(action: (v: ReadonlySet, k: Path) => void): void; + getKeys(v: Path): ReadonlySet | undefined; + getValues(k: Path): ReadonlySet | undefined; + hasKey(k: Path): boolean; + keys(): Iterator; /** * The set of arguments to {@link deleteKeys} which have not subsequently * been arguments to {@link set}. Note that a key does not have to have * ever been in the map to appear in this set. */ - deletedKeys(): ts.ReadonlySet | undefined; + deletedKeys(): ReadonlySet | undefined; } 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; clear(): 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 = { - clone: () => create(new ts.Map(forward), new ts.Map(reverse), deleted && new ts.Set(deleted)), + clone: () => create(new Map(forward), new Map(reverse), deleted && new Set(deleted)), forEach: fn => forward.forEach(fn), getKeys: v => reverse.get(v), getValues: k => forward.get(k), @@ -118,7 +135,7 @@ export namespace BuilderState { deletedKeys: () => deleted, deleteKey: k => { - (deleted ||= new ts.Set()).add(k); + (deleted ||= new Set()).add(k); const set = forward.get(k); if (!set) { @@ -159,19 +176,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)) { @@ -189,14 +206,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); } @@ -204,28 +221,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) { @@ -251,7 +268,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; @@ -269,13 +286,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); @@ -283,8 +300,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); } } @@ -298,11 +315,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(); - const referencedMap = newProgram.getCompilerOptions().module !== ts.ModuleKind.None ? createManyToManyPathMap() : undefined; + export function create(newProgram: Program, getCanonicalFileName: GetCanonicalFileName, oldState?: Readonly, disableUseFileVersionAsSignature?: boolean): BuilderState { + const fileInfos = new Map(); + const referencedMap = newProgram.getCompilerOptions().module !== ModuleKind.None ? createManyToManyPathMap() : undefined; const exportedModulesMap = referencedMap ? createManyToManyPathMap() : undefined; - const hasCalledUpdateShapeSignature = new ts.Set(); + const hasCalledUpdateShapeSignature = new Set(); const useOldState = canReuseOldState(referencedMap, oldState); // Ensure source files have parent pointers set @@ -310,7 +327,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 oldInfo = useOldState ? oldState!.fileInfos.get(sourceFile.resolvedPath) : undefined; if (referencedMap) { const newReferences = getReferencedFiles(newProgram, sourceFile, getCanonicalFileName); @@ -351,10 +368,10 @@ export namespace BuilderState { export function clone(state: Readonly): BuilderState { // Dont need to backup allFiles info since its cache anyway return { - fileInfos: new ts.Map(state.fileInfos), + fileInfos: new Map(state.fileInfos), referencedMap: state.referencedMap?.clone(), exportedModulesMap: state.exportedModulesMap?.clone(), - hasCalledUpdateShapeSignature: new ts.Set(state.hasCalledUpdateShapeSignature), + hasCalledUpdateShapeSignature: new Set(state.hasCalledUpdateShapeSignature), useFileVersionAsSignature: state.useFileVersionAsSignature, }; } @@ -362,15 +379,15 @@ export namespace BuilderState { /** * Gets the files affected by the path from the program */ - export function getFilesAffectedBy(state: BuilderState, programOfThisState: ts.Program, path: ts.Path, cancellationToken: ts.CancellationToken | undefined, computeHash: ComputeHash, cacheToUpdateSignature?: ts.ESMap, exportedModulesMapCache?: ManyToManyPathMap): readonly ts.SourceFile[] { + export function getFilesAffectedBy(state: BuilderState, programOfThisState: Program, path: Path, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash, cacheToUpdateSignature?: ESMap, exportedModulesMapCache?: ManyToManyPathMap): readonly SourceFile[] { // Since the operation could be cancelled, the signatures are always stored in the cache // They will be committed once it is safe to use them // eg when calling this api from tsserver, if there is no cancellation of the operation // In the other cases the affected files signatures are committed only after the iteration through the result is complete - const signatureCache = cacheToUpdateSignature || new ts.Map(); + const signatureCache = cacheToUpdateSignature || new Map(); const sourceFile = programOfThisState.getSourceFileByPath(path); if (!sourceFile) { - return ts.emptyArray; + return emptyArray; } if (!updateShapeSignature(state, programOfThisState, sourceFile, signatureCache, cancellationToken, computeHash, exportedModulesMapCache)) { @@ -389,11 +406,11 @@ export namespace BuilderState { * Updates the signatures from the cache into state's fileinfo signatures * This should be called whenever it is safe to commit the state of the builder */ - export function updateSignaturesFromCache(state: BuilderState, signatureCache: ts.ESMap) { + export function updateSignaturesFromCache(state: BuilderState, signatureCache: ESMap) { signatureCache.forEach((signature, path) => updateSignatureOfFile(state, signature, path)); } - 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.add(path); } @@ -401,9 +418,9 @@ export namespace BuilderState { /** * Returns if the shape of the signature has changed since last emit */ - export function updateShapeSignature(state: Readonly, programOfThisState: ts.Program, sourceFile: ts.SourceFile, cacheToUpdateSignature: ts.ESMap, cancellationToken: ts.CancellationToken | undefined, computeHash: ComputeHash, exportedModulesMapCache?: ManyToManyPathMap, useFileVersionAsSignature: boolean = state.useFileVersionAsSignature) { - ts.Debug.assert(!!sourceFile); - ts.Debug.assert(!exportedModulesMapCache || !!state.exportedModulesMap, "Compute visible to outside map only if visibleToOutsideReferencedMap present in the state"); + export function updateShapeSignature(state: Readonly, programOfThisState: Program, sourceFile: SourceFile, cacheToUpdateSignature: ESMap, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash, exportedModulesMapCache?: ManyToManyPathMap, useFileVersionAsSignature: boolean = state.useFileVersionAsSignature) { + Debug.assert(!!sourceFile); + Debug.assert(!exportedModulesMapCache || !!state.exportedModulesMap, "Compute visible to outside map only if visibleToOutsideReferencedMap present in the state"); // If we have cached the result for this file, that means hence forth we should assume file shape is uptodate if (state.hasCalledUpdateShapeSignature.has(sourceFile.resolvedPath) || cacheToUpdateSignature.has(sourceFile.resolvedPath)) { @@ -411,7 +428,7 @@ export namespace BuilderState { } const info = state.fileInfos.get(sourceFile.resolvedPath); - if (!info) return ts.Debug.fail(); + if (!info) return Debug.fail(); const prevSignature = info.signature; let latestSignature: string | undefined; @@ -424,10 +441,10 @@ export namespace BuilderState { /*customTransformers*/ undefined, /*forceDtsEmit*/ true ); - const firstDts = ts.firstOrUndefined(emitOutput.outputFiles); + const firstDts = firstOrUndefined(emitOutput.outputFiles); if (firstDts) { - ts.Debug.assert(ts.isDeclarationFileName(firstDts.name), "File extension for signature expected to be dts", () => `Found: ${ts.getAnyExtensionFromPath(firstDts.name)} for ${firstDts.name}:: All output files: ${JSON.stringify(emitOutput.outputFiles.map(f => f.name))}`); - latestSignature = (computeHash || ts.generateDjb2Hash)(firstDts.text); + Debug.assert(isDeclarationFileName(firstDts.name), "File extension for signature expected to be dts", () => `Found: ${getAnyExtensionFromPath(firstDts.name)} for ${firstDts.name}:: All output files: ${JSON.stringify(emitOutput.outputFiles.map(f => f.name))}`); + latestSignature = (computeHash || generateDjb2Hash)(firstDts.text); if (exportedModulesMapCache && latestSignature !== prevSignature) { updateExportedModules(sourceFile, emitOutput.exportedModulesFromDeclarationEmit, exportedModulesMapCache); } @@ -454,13 +471,13 @@ export namespace BuilderState { /** * Coverts the declaration emit result into exported modules map */ - export function updateExportedModules(sourceFile: ts.SourceFile, exportedModulesFromDeclarationEmit: ts.ExportedModulesFromDeclarationEmit | undefined, exportedModulesMapCache: ManyToManyPathMap) { + export function updateExportedModules(sourceFile: SourceFile, exportedModulesFromDeclarationEmit: ExportedModulesFromDeclarationEmit | undefined, exportedModulesMapCache: ManyToManyPathMap) { if (!exportedModulesFromDeclarationEmit) { exportedModulesMapCache.deleteKey(sourceFile.resolvedPath); return; } - let exportedModules: ts.Set | undefined; + let exportedModules: Set | undefined; exportedModulesFromDeclarationEmit.forEach(symbol => addExportedModule(getReferencedFilesFromImportedModuleSymbol(symbol))); if (exportedModules) { exportedModulesMapCache.set(sourceFile.resolvedPath, exportedModules); @@ -469,10 +486,10 @@ export namespace BuilderState { exportedModulesMapCache.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)); } @@ -485,7 +502,7 @@ export namespace BuilderState { */ export function updateExportedFilesMapFromCache(state: BuilderState, exportedModulesMapCache: ManyToManyPathMap | undefined) { if (exportedModulesMapCache) { - ts.Debug.assert(!!state.exportedModulesMap); + Debug.assert(!!state.exportedModulesMap); exportedModulesMapCache.deletedKeys()?.forEach(path => state.exportedModulesMap!.deleteKey(path)); exportedModulesMapCache.forEach((exportedModules, path) => state.exportedModulesMap!.set(path, exportedModules)); } @@ -494,10 +511,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); } @@ -507,7 +524,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()!; @@ -523,16 +540,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; } @@ -540,9 +557,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()) : []; } /** @@ -551,9 +568,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; } } @@ -564,38 +581,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); } @@ -605,11 +622,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); @@ -618,20 +635,20 @@ export namespace BuilderState { /** * When program emits modular code, gets the files affected by the sourceFile whose shape has changed */ - function getFilesAffectedByUpdatedShapeWhenModuleEmit(state: BuilderState, programOfThisState: ts.Program, sourceFileWithUpdatedShape: ts.SourceFile, cacheToUpdateSignature: ts.ESMap, cancellationToken: ts.CancellationToken | undefined, computeHash: ComputeHash, exportedModulesMapCache: ManyToManyPathMap | undefined) { + function getFilesAffectedByUpdatedShapeWhenModuleEmit(state: BuilderState, programOfThisState: Program, sourceFileWithUpdatedShape: SourceFile, cacheToUpdateSignature: ESMap, cancellationToken: CancellationToken | undefined, computeHash: ComputeHash, exportedModulesMapCache: ManyToManyPathMap | undefined) { 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); @@ -648,6 +665,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 70fcd25f38b20..acb13e630ef21 100644 --- a/src/compiler/builderStatePublic.ts +++ b/src/compiler/builderStatePublic.ts @@ -1,10 +1,10 @@ -import * as ts from "./_namespaces/ts"; +import { Diagnostic, ExportedModulesFromDeclarationEmit } from "./types"; export interface EmitOutput { outputFiles: OutputFile[]; emitSkipped: boolean; - /* @internal */ diagnostics: readonly ts.Diagnostic[]; - /* @internal */ exportedModulesFromDeclarationEmit?: ts.ExportedModulesFromDeclarationEmit; + /* @internal */ diagnostics: readonly Diagnostic[]; + /* @internal */ exportedModulesFromDeclarationEmit?: ExportedModulesFromDeclarationEmit; } export interface OutputFile { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6c19d63865738..3a2a0ed3fa279 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1,7 +1,237 @@ import * as ts from "./_namespaces/ts"; +import { bindSourceFile, getModuleInstanceState, ModuleInstanceState } from "./binder"; +import { + addRange, and, append, appendIfUnique, arrayFrom, arrayOf, arraysEqual, arrayToMultiMap, binarySearch, + cartesianProduct, cast, clear, compareValues, concatenate, contains, countWhere, createGetCanonicalFileName, + createUnderscoreEscapedMultiMap, deduplicate, emptyArray, endsWith, equateValues, every, filter, find, + findBestPatternMatch, findIndex, findLast, findLastIndex, first, firstDefined, firstOrUndefined, flatMap, flatten, + forEach, getEntries, getOrUpdate, getOwnKeys, getSpellingSuggestion, group, indicesOf, isArray, isString, last, + lastOrUndefined, length, map, mapDefined, maybeBind, memoize, not, or, orderedRemoveItemAt, pushIfUnique, + rangeEquals, reduceLeft, relativeComplement, removePrefix, replaceElement, sameMap, singleElementArray, some, + startsWith, stringContains, sum, tryAddToSet, tryCast, +} from "./core"; +import { Comparison, ESMap, Map, ReadonlyESMap, Set } from "./corePublic"; +import { Debug } from "./debug"; +import { Diagnostics } from "./diagnosticInformationMap.generated"; +import { createPrinter } from "./emitter"; +import { + addSyntheticLeadingComment, setCommentRange, setEmitFlags, setSyntheticLeadingComments, +} from "./factory/emitNode"; +import { factory, setOriginalNode } from "./factory/nodeFactory"; +import { + isArrayBindingPattern, isArrayLiteralExpression, isArrowFunction, isBinaryExpression, isBindingElement, isBlock, + isCallExpression, isCallSignatureDeclaration, isCatchClause, isClassDeclaration, isClassExpression, + isClassStaticBlockDeclaration, isComputedPropertyName, isConstructorDeclaration, isConstructorTypeNode, + isElementAccessExpression, isEnumDeclaration, isEnumMember, isExportAssignment, isExportDeclaration, + isExportSpecifier, isExpressionStatement, isExpressionWithTypeArguments, isExternalModuleReference, + isForInStatement, isForOfStatement, isForStatement, isFunctionDeclaration, isFunctionExpression, isFunctionTypeNode, + isGetAccessorDeclaration, isIdentifier, isIfStatement, isImportClause, isImportDeclaration, + isImportEqualsDeclaration, isImportKeyword, isImportSpecifier, isImportTypeNode, isIndexedAccessTypeNode, + isInterfaceDeclaration, isJSDocAllType, isJSDocAugmentsTag, isJSDocCallbackTag, isJSDocFunctionType, + isJSDocMemberName, isJSDocNameReference, isJSDocNonNullableType, isJSDocNullableType, isJSDocOptionalType, + isJSDocParameterTag, isJSDocReturnTag, isJSDocSignature, isJSDocTemplateTag, isJSDocTypedefTag, + isJSDocTypeExpression, isJSDocTypeLiteral, isJSDocTypeTag, isJSDocUnknownType, isJSDocVariadicType, isJsxAttribute, + isJsxAttributes, isJsxElement, isJsxOpeningElement, isJsxOpeningFragment, isJsxSelfClosingElement, + isJsxSpreadAttribute, isLiteralTypeNode, isMetaProperty, isMethodDeclaration, isMethodSignature, isModuleBlock, + isModuleDeclaration, isNamedExports, isNamedTupleMember, isNamespaceExport, isNamespaceExportDeclaration, + isNewExpression, isNumericLiteral, isObjectBindingPattern, isObjectLiteralExpression, isOmittedExpression, + isOptionalTypeNode, isParameter, isParenthesizedExpression, isParenthesizedTypeNode, isPrefixUnaryExpression, + isPrivateIdentifier, isPropertyAccessExpression, isPropertyAssignment, isPropertyDeclaration, isPropertySignature, + isQualifiedName, isRestTypeNode, isShorthandPropertyAssignment, isSourceFile, isSpreadAssignment, isSpreadElement, + isStringLiteral, isTaggedTemplateExpression, isTemplateSpan, isTupleTypeNode, isTypeAliasDeclaration, + isTypeLiteralNode, isTypeOfExpression, isTypeOperatorNode, isTypeParameterDeclaration, isTypePredicateNode, + isTypeQueryNode, isTypeReferenceNode, isVariableDeclaration, isVariableDeclarationList, isVariableStatement, +} from "./factory/nodeTests"; +import { + canHaveModifiers, createBinaryExpressionTrampoline, createEmptyExports, findUseStrictPrologue, + getJSDocTypeAssertionType, isCommaSequence, isJSDocTypeAssertion, skipOuterExpressions, +} from "./factory/utilities"; +import { setTextRange } from "./factory/utilitiesPublic"; +import { getTypesPackageName, mangleScopedPackageName } from "./moduleNameResolver"; +import { countPathComponents, getModuleSpecifiers } from "./moduleSpecifiers"; +import { + forEachChild, forEachChildRecursively, isExternalModule, parseIsolatedEntityName, parseNodeFactory, +} from "./parser"; +import { + comparePaths, fileExtensionIs, fileExtensionIsOneOf, getDirectoryPath, getNormalizedAbsolutePath, hasExtension, + pathIsRelative, +} from "./path"; +import { mark, measure } from "./performance"; +import { + getModeForUsageLocation, getResolutionDiagnostic, getResolutionModeOverrideForClause, + isExclusivelyTypeOnlyImportOrExport, resolveTripleslashReference, +} from "./program"; +import { + createScanner, getLineAndCharacterOfPosition, isIdentifierStart, isIdentifierText, isLineBreak, skipTrivia, + tokenToString, +} from "./scanner"; +import { createGetSymbolWalker } from "./symbolWalker"; +import { tracing, TracingNode } from "./tracing"; +import { nullTransformationContext } from "./transformer"; +import { + __String, AccessExpression, AccessFlags, AccessorDeclaration, AllAccessorDeclarations, AnonymousType, + AnyImportOrReExport, AnyImportSyntax, ArrayBindingPattern, ArrayLiteralExpression, ArrayTypeNode, ArrowFunction, + AssertionExpression, AssignmentDeclarationKind, AssignmentPattern, AwaitExpression, BaseType, BigIntLiteral, + BigIntLiteralType, BinaryExpression, BinaryOperatorToken, BindableObjectDefinePropertyCall, BindingElement, + BindingElementGrandparent, BindingName, BindingPattern, Block, BreakOrContinueStatement, CallChain, CallExpression, + CallLikeExpression, CallSignatureDeclaration, CancellationToken, CaseBlock, CaseClause, CaseOrDefaultClause, + CharacterCodes, CheckFlags, ClassDeclaration, ClassElement, ClassExpression, ClassLikeDeclaration, + ClassStaticBlockDeclaration, CompilerOptions, ComputedPropertyName, ConditionalExpression, ConditionalRoot, + ConditionalType, ConditionalTypeNode, ConstructorDeclaration, ConstructorTypeNode, ConstructSignatureDeclaration, + ContextFlags, Declaration, DeclarationName, DeclarationStatement, DeclarationWithTypeParameterChildren, + DeclarationWithTypeParameters, Decorator, DefaultClause, DeferredTypeReference, DeleteExpression, Diagnostic, + DiagnosticCategory, DiagnosticMessage, DiagnosticMessageChain, DiagnosticRelatedInformation, DiagnosticWithLocation, + DoStatement, DynamicNamedDeclaration, ElementAccessChain, ElementAccessExpression, ElementFlags, EmitFlags, + EmitHint, EmitResolver, EmitTextWriter, EntityName, EntityNameExpression, EntityNameOrEntityNameExpression, + EnumDeclaration, EnumKind, EnumMember, EvolvingArrayType, ExclamationToken, ExportAssignment, ExportDeclaration, + ExportSpecifier, Expression, ExpressionStatement, ExpressionWithTypeArguments, Extension, ExternalEmitHelpers, + FlowArrayMutation, FlowAssignment, FlowCall, FlowCondition, FlowFlags, FlowLabel, FlowNode, FlowReduceLabel, + FlowStart, FlowSwitchClause, FlowType, ForInOrOfStatement, ForInStatement, ForOfStatement, ForStatement, + FreshableIntrinsicType, FreshableType, FreshObjectLiteralType, FunctionDeclaration, FunctionExpression, + FunctionLikeDeclaration, FunctionTypeNode, GenericType, GetAccessorDeclaration, HasExpressionInitializer, + HasInitializer, HasModifiers, HeritageClause, Identifier, IdentifierTypePredicate, IfStatement, ImportCall, + ImportClause, ImportDeclaration, ImportEqualsDeclaration, ImportOrExportSpecifier, ImportsNotUsedAsValues, + ImportSpecifier, ImportTypeAssertionContainer, ImportTypeNode, IncompleteType, IndexedAccessType, + IndexedAccessTypeNode, IndexInfo, IndexKind, IndexSignatureDeclaration, IndexType, InferenceContext, InferenceFlags, + InferenceInfo, InferencePriority, InferTypeNode, InstantiableType, InstantiationExpressionType, + InterfaceDeclaration, InterfaceType, InterfaceTypeWithDeclaredMembers, InternalSymbolName, IntersectionType, + IntersectionTypeNode, IntrinsicType, IterableOrIteratorType, IterationTypes, JSDoc, JSDocAugmentsTag, + JSDocCallbackTag, JSDocContainer, JSDocEnumTag, JSDocFunctionType, JSDocImplementsTag, 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, LateBoundBinaryExpressionDeclaration, LateBoundDeclaration, LateBoundName, + LateVisibilityPaintedStatement, LeftHandSideExpression, LiteralExpression, LiteralType, LiteralTypeNode, + MappedSymbol, MappedType, MappedTypeNode, MatchingKeys, MemberName, MemberOverrideStatus, MetaProperty, + MethodDeclaration, MethodSignature, MinusToken, Modifier, ModifierFlags, ModuleBlock, ModuleDeclaration, ModuleKind, + ModuleResolutionKind, NamedDeclaration, NamedExports, NamedImportsOrExports, NamedTupleMember, NamespaceDeclaration, + NamespaceExport, NamespaceExportDeclaration, NamespaceImport, NewExpression, Node, NodeArray, NodeBuilderFlags, + NodeCheckFlags, NodeFlags, NodeLinks, NodeWithTypeArguments, NonNullChain, NonNullExpression, NumberLiteralType, + NumericLiteral, ObjectBindingPattern, ObjectFlags, ObjectFlagsType, ObjectLiteralElementLike, + ObjectLiteralExpression, ObjectType, OptionalChain, OptionalTypeNode, OuterExpressionKinds, ParameterDeclaration, + ParenthesizedExpression, ParenthesizedTypeNode, Path, PatternAmbientModule, PlusToken, PostfixUnaryExpression, + PrefixUnaryExpression, PrivateIdentifier, Program, PromiseOrAwaitableType, PropertyAccessChain, + PropertyAccessEntityNameExpression, PropertyAccessExpression, PropertyAssignment, PropertyDeclaration, PropertyName, + PropertySignature, PseudoBigInt, QualifiedName, QuestionToken, ReadonlyKeyword, RelationComparisonResult, + ResolvedModuleFull, ResolvedType, RestTypeNode, ReturnStatement, ReverseMappedSymbol, ReverseMappedType, ScriptKind, + ScriptTarget, SetAccessorDeclaration, ShorthandPropertyAssignment, Signature, SignatureDeclaration, SignatureFlags, + SignatureKind, SourceFile, SpreadAssignment, SpreadElement, Statement, StringLiteral, StringLiteralLike, + StringLiteralType, StringMappingType, StructuredType, SubstitutionType, SuperCall, SwitchStatement, Symbol, + SymbolAccessibility, SymbolAccessibilityResult, SymbolFlags, SymbolFormatFlags, SymbolId, SymbolLinks, SymbolTable, + SymbolTracker, SymbolVisibilityResult, SyntaxKind, SyntheticDefaultModuleType, SyntheticExpression, + TaggedTemplateExpression, TemplateExpression, TemplateLiteralType, TemplateLiteralTypeNode, Ternary, TextSpan, + ThisExpression, ThisTypeNode, ThrowStatement, TokenFlags, TransientSymbol, 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, UnionOrIntersectionType, UnionOrIntersectionTypeNode, UnionReduction, + UnionType, UnionTypeNode, UniqueESSymbolType, VariableDeclaration, VariableDeclarationList, VariableLikeDeclaration, + VariableStatement, VarianceFlags, Visitor, VisitResult, VoidExpression, WhileStatement, WideningContext, + WithStatement, YieldExpression, +} from "./types"; +import { + addRelatedInfo, arrayIsHomogeneous, AssignmentKind, chainDiagnosticMessages, compareDiagnostics, + concatenateDiagnosticMessageChains, containsParseError, copyEntries, createCompilerDiagnostic, + createDiagnosticCollection, createDiagnosticForFileFromMessageChain, createDiagnosticForNode, + createDiagnosticForNodeArray, createDiagnosticForNodeFromMessageChain, createDiagnosticMessageChainFromDiagnostic, + createFileDiagnostic, createPropertyNameNodeForIdentifierOrLiteral, createSymbolTable, createTextWriter, + declarationNameToString, defaultMaximumTruncationLength, entityNameToString, escapeString, exportAssignmentIsAlias, + expressionResultIsUnused, externalHelpersModuleNameText, forEachEnclosingBlockScopeContainer, forEachEntry, + forEachImportClauseDeclaration, forEachKey, forEachReturnStatement, forEachYieldExpression, formatMessage, + FunctionFlags, getAliasDeclarationFromName, getAllAccessorDeclarations, getAllowSyntheticDefaultImports, + getAncestor, getAssignedExpandoInitializer, getAssignmentDeclarationKind, + getAssignmentDeclarationPropertyAccessKind, getAssignmentTargetKind, getCheckFlags, getClassExtendsHeritageElement, + getClassLikeDeclarationOfSymbol, getCombinedLocalAndExportSymbolFlags, getContainingClass, getContainingFunction, + getContainingFunctionOrClassStaticBlock, getDeclarationModifierFlagsFromSymbol, getDeclarationOfKind, + getDeclarationsOfKind, getDeclaredExpandoInitializer, getEffectiveBaseTypeNode, + getEffectiveContainerForJSDocTemplateTag, getEffectiveImplementsTypeNodes, getEffectiveInitializer, + getEffectiveJSDocHost, getEffectiveModifierFlags, getEffectiveReturnTypeNode, + getEffectiveSetAccessorTypeAnnotationNode, getEffectiveTypeAnnotationNode, getElementOrPropertyAccessName, + getEmitDeclarations, getEmitModuleKind, getEmitModuleResolutionKind, getEmitScriptTarget, + getEnclosingBlockScopeContainer, getEntityNameFromTypeNode, getErrorSpanForNode, + getEscapedTextOfIdentifierOrLiteral, getESModuleInterop, getExpandoInitializer, getExportAssignmentExpression, + getExternalModuleImportEqualsDeclarationExpression, getExternalModuleName, getExternalModuleRequireArgument, + getFirstConstructorWithBody, getFirstIdentifier, getFunctionFlags, getHostSignatureFromJSDoc, + getImmediatelyInvokedFunctionExpression, getInitializerOfBinaryExpression, getInterfaceBaseTypeNodes, + getInvokedExpression, getJSDocHost, getJSDocRoot, getJSDocTypeParameterDeclarations, getJSXImplicitImportBase, + getJSXRuntimeImport, getJSXTransformEnabled, getLeftmostAccessExpression, getLocalSymbolForExportDefault, + getMembersOfDeclaration, getNameFromIndexInfo, getNameOfExpando, getNamespaceDeclarationNode, getNewTargetContainer, + getNonAugmentationDeclaration, getObjectFlags, getParameterSymbolFromJSDoc, + getPropertyAssignmentAliasLikeExpression, getPropertyNameForPropertyNameNode, getResolvedExternalModuleName, + getResolvedModule, getRestParameterElementType, getRootDeclaration, getScriptTargetFeatures, + getSelectedEffectiveModifierFlags, getSemanticJsxChildren, getSetAccessorValueParameter, + getSingleVariableOfVariableStatement, getSourceFileOfModule, getSourceFileOfNode, getSpanOfTokenAtPosition, + getStrictOptionValue, getSuperContainer, getSymbolNameForPrivateIdentifier, getTextOfIdentifierOrLiteral, + getTextOfNode, getTextOfPropertyName, getThisContainer, getThisParameter, getTrailingSemicolonDeferringWriter, + getTypeParameterFromJsDoc, getUseDefineForClassFields, hasAbstractModifier, hasAmbientModifier, + hasContextSensitiveParameters, hasDynamicName, hasEffectiveModifier, hasEffectiveModifiers, + hasEffectiveReadonlyModifier, hasJsonModuleEmitEnabled, hasOverrideModifier, hasPossibleExternalModuleReference, + hasQuestionToken, hasStaticModifier, hasSyntacticModifier, hasSyntacticModifiers, indexOfNode, + introducesArgumentsExoticObject, isAccessExpression, isAliasableExpression, isAmbientModule, + isAssignmentDeclaration, isAssignmentExpression, isAssignmentOperator, isAssignmentTarget, + isBindableObjectDefinePropertyCall, isBindableStaticElementAccessExpression, isBindableStaticNameExpression, + isBlockOrCatchScoped, isBlockScopedContainerTopLevel, isCatchClauseVariableDeclarationOrBindingElement, + isCheckJsEnabledForFile, isChildOfNodeWithKind, isCommonJsExportedExpression, isCommonJsExportPropertyAssignment, + isComputedNonLiteralName, isDeclarationName, isDeclarationReadonly, isDefaultedExpandoInitializer, isDeleteTarget, + isDottedName, isDynamicName, isEffectiveExternalModule, isEntityNameExpression, isEnumConst, isExportsIdentifier, + isExpressionNode, isExpressionWithTypeArgumentsInClassExtendsClause, isExternalModuleAugmentation, + isExternalModuleImportEqualsDeclaration, isExternalOrCommonJsModule, isFunctionExpressionOrArrowFunction, + isGlobalScopeAugmentation, isIdentifierTypePredicate, isIdentifierTypeReference, isImportCall, + isInExpressionContext, isInfinityOrNaNString, isInJSDoc, isInJSFile, isInJsonFile, + isInternalModuleImportEqualsDeclaration, isInTopLevelContext, isIntrinsicJsxName, isJSDocConstructSignature, + isJSDocIndexSignature, isJSDocTypeAlias, isJsonSourceFile, isJSXTagName, isKnownSymbol, + isLateVisibilityPaintedStatement, isLet, isLiteralComputedPropertyDeclarationName, isLiteralImportTypeNode, + isModuleExportsAccessExpression, isModuleIdentifier, isModuleWithStringLiteralName, isNamespaceReexportDeclaration, + isNightly, isNodeDescendantOf, isNumericLiteralName, isObjectLiteralMethod, + isObjectLiteralOrClassExpressionMethodOrAccessor, isParameterDeclaration, isParameterOrCatchClauseVariable, + isPartOfTypeNode, isPartOfTypeQuery, isPlainJsFile, isPropertyAccessEntityNameExpression, isPropertyNameLiteral, + isPrototypeAccess, isPrototypePropertyAssignment, isPushOrUnshiftIdentifier, isRequireCall, + isRightSideOfQualifiedNameOrPropertyAccess, isRightSideOfQualifiedNameOrPropertyAccessOrJSDocMemberName, + isSameEntityName, isShorthandAmbientModuleSymbol, isSingleOrDoubleQuote, isSourceFileJS, isStatementWithLocals, + isStatic, isStringANonContextualKeyword, isStringOrNumericLiteralLike, isSuperCall, isSuperProperty, + isThisContainerOrFunctionBlock, isThisIdentifier, isThisInitializedDeclaration, + isThisInitializedObjectBindingExpression, isThisInTypeQuery, isThisProperty, isThisTypeParameter, isTransientSymbol, + isTypeAlias, isTypeNodeKind, isUMDExportSymbol, isValidESSymbolDeclaration, isValidTypeOnlyAliasUseSite, + isValueSignatureDeclaration, isVarConst, isVariableDeclarationInitializedToBareOrAccessedRequire, + isVariableDeclarationInVariableStatement, isVariableLike, isVariableLikeOrAccessor, isWriteAccess, + isWriteOnlyAccess, minAndMax, modifiersToFlags, modifierToFlag, nodeCanBeDecorated, nodeIsDecorated, nodeIsMissing, + nodeIsPresent, nodeIsSynthesized, nodeStartsNewLexicalEnvironment, noTruncationMaximumTruncationLength, + objectAllocator, outFile, parameterIsThisKeyword, parsePseudoBigInt, pseudoBigIntToString, rangeOfNode, + rangeOfTypeParameters, removeExtension, resolutionExtensionIsTSOrJson, resolvingEmptyArray, setNodeFlags, setParent, + setTextRangePosEnd, setValueDeclaration, shouldPreserveConstEnums, skipParentheses, skipTypeChecking, stripQuotes, + tryExtractTSExtension, tryGetClassImplementingOrExtendingExpressionWithTypeArguments, + tryGetPropertyAccessOrIdentifierToString, usingSingleLineStringWriter, walkUpParenthesizedExpressions, + walkUpParenthesizedTypes, walkUpParenthesizedTypesAndGetParentAndChild, +} from "./utilities"; +import { + escapeLeadingUnderscores, findAncestor, getCombinedModifierFlags, getCombinedNodeFlags, + getEffectiveConstraintOfTypeParameter, getEffectiveTypeParameterDeclarations, getJSDocClassTag, + getJSDocDeprecatedTag, getJSDocEnumTag, getJSDocParameterTags, getJSDocTags, getJSDocThisTag, getJSDocType, + getJSDocTypeTag, getNameOfDeclaration, getOriginalNode, getParseTreeNode, getTextOfJSDocComment, hasInitializer, + hasJSDocNodes, hasJSDocParameterTags, hasOnlyExpressionInitializer, hasRestParameter, hasScopeMarker, idText, + isAccessor, isAssertionExpression, isAssignmentPattern, isBindingPattern, isCallChain, isCallLikeExpression, + isCallOrNewExpression, isClassElement, isClassLike, isConstTypeReference, isDeclaration, isEntityName, isExpression, + isExpressionOfOptionalChainRoot, isExternalModuleIndicator, isExternalModuleNameRelative, isForInOrOfStatement, + isFunctionLike, isFunctionLikeDeclaration, isFunctionLikeOrClassStaticBlockDeclaration, isFunctionOrModuleBlock, + isGeneratedIdentifier, isGetAccessor, isGetOrSetAccessorDeclaration, isImportOrExportSpecifier, + isIterationStatement, isJSDocLinkLike, isJSDocNode, isJSDocPropertyLikeTag, isJsxAttributeLike, + isJsxOpeningLikeElement, isLeftHandSideExpression, isLiteralExpression, isLiteralExpressionOfObject, + isModuleOrEnumDeclaration, isNamedDeclaration, isNullishCoalesce, isObjectLiteralElementLike, isOptionalChain, + isOptionalChainRoot, isOutermostOptionalChain, isParameterPropertyDeclaration, + isPrivateIdentifierClassElementDeclaration, isPrivateIdentifierPropertyAccessExpression, + isPropertyAccessOrQualifiedNameOrImportTypeNode, isPropertyName, isRestParameter, isSetAccessor, isStatement, + isStringLiteralLike, isTypeNode, isTypeOnlyImportOrExportDeclaration, isTypeReferenceType, needsScopeMarker, + nodeHasName, ParameterPropertyDeclaration, symbolName, textRangeContainsPositionInclusive, textSpanContainsPosition, + textSpanEnd, unescapeLeadingUnderscores, walkUpBindingElementsAndPatterns, +} from "./utilitiesPublic"; +import { visitEachChild, visitNode, visitNodes } from "./visitorPublic"; const ambientModuleSymbolRegex = /^".+"$/; -const anon = "(anonymous)" as ts.__String & string; +const anon = "(anonymous)" as __String & string; let nextSymbolId = 1; let nextNodeId = 1; @@ -44,14 +274,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 { @@ -139,7 +369,7 @@ const enum TypeFacts { AndFactsMask = All & ~OrFactsMask, } -const typeofEQFacts: ts.ReadonlyESMap = new ts.Map(ts.getEntries({ +const typeofEQFacts: ReadonlyESMap = new Map(getEntries({ string: TypeFacts.TypeofEQString, number: TypeFacts.TypeofEQNumber, bigint: TypeFacts.TypeofEQBigInt, @@ -150,7 +380,7 @@ const typeofEQFacts: ts.ReadonlyESMap = new ts.Map(ts.getEntr function: TypeFacts.TypeofEQFunction })); -const typeofNEFacts: ts.ReadonlyESMap = new ts.Map(ts.getEntries({ +const typeofNEFacts: ReadonlyESMap = new Map(getEntries({ string: TypeFacts.TypeofNEString, number: TypeFacts.TypeofNENumber, bigint: TypeFacts.TypeofNEBigInt, @@ -161,7 +391,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, @@ -236,9 +466,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, @@ -270,22 +500,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++; @@ -294,7 +524,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++; @@ -304,25 +534,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; @@ -343,13 +573,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; @@ -358,43 +588,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; @@ -404,10 +634,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: () => ({ @@ -425,38 +655,38 @@ 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, 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, @@ -478,88 +708,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) : 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); }, isContextSensitive, @@ -575,23 +805,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, @@ -600,7 +830,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { getExportsOfModule: getExportsOfModuleAsArray, getExportsAndPropertiesOfModule, forEachExportAndPropertyOfModule, - getSymbolWalker: ts.createGetSymbolWalker( + getSymbolWalker: createGetSymbolWalker( getRestTypeOfSignature, getTypePredicateOfSignature, getReturnTypeOfSignature, @@ -609,17 +839,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 @@ -660,43 +890,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) => { - const node = ts.getParseTreeNode(nodeIn); + const node = getParseTreeNode(nodeIn); return node && tryGetThisTypeAt(node, includeGlobalThis); }, 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 @@ -705,16 +935,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; @@ -738,8 +968,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { getMemberOverrideModifierStatus, }; - 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!; @@ -761,8 +991,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 : @@ -772,49 +1002,49 @@ 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 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"); - 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 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"); + 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; @@ -824,65 +1054,65 @@ 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"); - const nonInferrableType = 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"); + const nonInferrableType = 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); - const permissiveMapper: ts.TypeMapper = makeFunctionTypeMapper(t => t.flags & ts.TypeFlags.TypeParameter ? wildcardType : t); - 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); // 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); + const permissiveMapper: TypeMapper = makeFunctionTypeMapper(t => t.flags & TypeFlags.TypeParameter ? wildcardType : t); + 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); // replace all type parameters with the unique literal type (disregarding constraints) - 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 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(); markerSubType.constraint = markerSuperType; const markerOtherType = createTypeParameter(); - 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); @@ -898,9 +1128,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 = { @@ -912,91 +1142,91 @@ 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; - - 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; + + 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); @@ -1008,27 +1238,27 @@ 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 potentialThisCollisions: Node[] = []; + const potentialNewTargetCollisions: Node[] = []; + const potentialWeakMapSetCollisions: Node[] = []; + const potentialReflectCollisions: Node[] = []; const awaitedTypeStack: number[] = []; - const diagnostics = ts.createDiagnosticCollection(); - const suggestionDiagnostics = ts.createDiagnosticCollection(); + const diagnostics = createDiagnosticCollection(); + const suggestionDiagnostics = createDiagnosticCollection(); - const typeofTypesByName: ts.ReadonlyESMap = new ts.Map(ts.getEntries({ + const typeofTypesByName: ReadonlyESMap = new Map(getEntries({ string: stringType, number: numberType, bigint: bigintType, @@ -1038,18 +1268,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { })); const typeofType = createTypeofType(); - let _jsxNamespace: ts.__String; - let _jsxFactoryEntity: ts.EntityName | undefined; + let _jsxNamespace: __String; + let _jsxFactoryEntity: EntityName | undefined; let outofbandVarianceMarkerHandler: ((onlyUnreliable: boolean) => void) | 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. @@ -1063,7 +1293,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"], ]; @@ -1072,27 +1302,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return checker; - 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 { @@ -1104,55 +1334,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; @@ -1163,65 +1393,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 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 no-in-operator return; } - addErrorOrSuggestion(isError, "message" in message ? ts.createDiagnosticForNode(location, message, arg0, arg1, arg2, arg3) : ts.createDiagnosticForNodeFromMessageChain(location, message)); // eslint-disable-line no-in-operator + addErrorOrSuggestion(isError, "message" in message ? createDiagnosticForNode(location, message, arg0, arg1, arg2, arg3) : createDiagnosticForNodeFromMessageChain(location, message)); // eslint-disable-line 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. @@ -1229,51 +1459,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++; @@ -1281,14 +1511,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; } @@ -1297,15 +1527,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; @@ -1313,58 +1543,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); @@ -1376,69 +1606,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) : 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) { @@ -1446,25 +1676,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); } @@ -1475,52 +1705,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 target = resolveAlias(symbol); // Unknown symbol means an error occurred in alias resolution, treat it as positive answer to avoid cascading errors if (target === unknownSymbol || target.flags & meaning) { @@ -1538,29 +1768,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; } @@ -1573,34 +1803,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; @@ -1617,22 +1847,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 { @@ -1642,14 +1872,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)) { @@ -1660,34 +1890,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; } @@ -1695,8 +1925,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; } } @@ -1707,7 +1937,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; @@ -1715,25 +1945,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; @@ -1747,10 +1977,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 @@ -1760,57 +1990,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)); } /** @@ -1821,36 +2051,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, - getSpellingSuggstions = true): ts.Symbol | undefined { + getSpellingSuggstions = true): Symbol | undefined { return resolveNameHelper(location, name, meaning, nameNotFoundMessage, nameArg, isUse, excludeGlobals, getSpellingSuggstions, 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.Node | undefined; - let associatedDeclarationForContainingInitializerOrBindingName: ts.ParameterDeclaration | ts.BindingElement | undefined; + let result: Symbol | undefined; + let lastLocation: Node | undefined; + let lastSelfReferenceLocation: Node | undefined; + let propertyWithInvalidInitializer: Node | 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) { @@ -1863,47 +2093,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) { @@ -1916,18 +2146,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; } @@ -1947,15 +2177,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 { @@ -1963,64 +2193,64 @@ 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 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. - 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; } @@ -2034,48 +2264,48 @@ 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)) { - error(errorLocation, ts.Diagnostics.A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type); + if (result = lookup(getSymbolOfNode(grandparent as ClassLikeDeclaration | InterfaceDeclaration).members!, name, meaning & SymbolFlags.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. // @@ -2084,7 +2314,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; } // @@ -2100,42 +2330,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; } } @@ -2145,8 +2375,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; } @@ -2159,8 +2389,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; } } @@ -2170,8 +2400,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; } } @@ -2187,25 +2417,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { !checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) && !checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation, name, meaning) && !checkAndReportErrorForUsingValueAsType(errorLocation, name, meaning)) { - let suggestion: ts.Symbol | undefined; + let suggestion: Symbol | undefined; if (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) ); } } @@ -2228,13 +2458,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - if (propertyWithInvalidInitializer && !(ts.getEmitScriptTarget(compilerOptions) === ts.ScriptTarget.ESNext && useDefineForClassFields)) { + if (propertyWithInvalidInitializer && !(getEmitScriptTarget(compilerOptions) === ScriptTarget.ESNext && useDefineForClassFields)) { // 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. - const propertyName = (propertyWithInvalidInitializer as ts.PropertyDeclaration).name; - error(errorLocation, ts.Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor, - ts.declarationNameToString(propertyName), diagnosticName(nameArg!)); + const propertyName = (propertyWithInvalidInitializer as PropertyDeclaration).name; + error(errorLocation, Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor, + declarationNameToString(propertyName), diagnosticName(nameArg!)); return undefined; } @@ -2253,42 +2483,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)) { + if (result && errorLocation && meaning & SymbolFlags.Value && result.flags & SymbolFlags.Alias && !(result.flags & SymbolFlags.Value) && !isValidTypeOnlyAliasUseSite(errorLocation)) { const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(result); 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, @@ -2300,59 +2530,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)); // TODO: GH#18217 + return !(isJSDocTemplateTag(decl.parent) && find((decl.parent.parent as JSDoc).tags!, isJSDocTypeAlias)); // TODO: GH#18217 } } } @@ -2361,15 +2591,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; @@ -2378,16 +2608,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; } } @@ -2399,10 +2629,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; @@ -2411,14 +2641,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: @@ -2426,27 +2656,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; } } @@ -2454,46 +2684,46 @@ 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 & ~ts.SymbolFlags.NamespaceModule)) { + function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { + if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule)) { if (isPrimitiveTypeName(name)) { - 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)); - if (symbol && !(symbol.flags & ts.SymbolFlags.NamespaceModule)) { - const rawName = ts.unescapeLeadingUnderscores(name); + const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); + if (symbol && !(symbol.flags & SymbolFlags.NamespaceModule)) { + 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; } @@ -2501,17 +2731,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { 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": @@ -2524,61 +2754,61 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation: ts.Node, name: ts.__String, meaning: ts.SymbolFlags): boolean { - if (meaning & (ts.SymbolFlags.Value & ~ts.SymbolFlags.NamespaceModule & ~ts.SymbolFlags.Type)) { - const symbol = resolveSymbol(resolveName(errorLocation, name, ts.SymbolFlags.NamespaceModule & ~ts.SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); + function checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { + if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule & ~SymbolFlags.Type)) { + const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.NamespaceModule & ~SymbolFlags.Value, /*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.NamespaceModule & ~ts.SymbolFlags.Value)) { - const symbol = resolveSymbol(resolveName(errorLocation, name, (ts.SymbolFlags.ValueModule | ts.SymbolFlags.NamespaceModule) & ~ts.SymbolFlags.Type, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); + else if (meaning & (SymbolFlags.Type & ~SymbolFlags.NamespaceModule & ~SymbolFlags.Value)) { + const symbol = resolveSymbol(resolveName(errorLocation, name, (SymbolFlags.ValueModule | SymbolFlags.NamespaceModule) & ~SymbolFlags.Type, /*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) ); } } @@ -2589,28 +2819,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) ? "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) ? "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); } /** @@ -2628,42 +2858,42 @@ 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) - || ts.isVariableDeclarationInitializedToBareOrAccessedRequire(node); + || node.kind === SyntaxKind.ShorthandPropertyAssignment + || node.kind === SyntaxKind.PropertyAssignment && isAliasableOrJsExpression((node as PropertyAssignment).initializer) + || isVariableDeclarationInitializedToBareOrAccessedRequire(node); } - 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; @@ -2673,52 +2903,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 @@ -2729,13 +2959,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; @@ -2746,38 +2976,38 @@ 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 !file.externalModuleIndicator && !resolveExportByName(moduleSymbol, ts.escapeLeadingUnderscores("__esModule"), /*sourceNode*/ undefined, dontResolveAlias); + return !file.externalModuleIndicator && !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) { - let exportDefaultSymbol: ts.Symbol | undefined; - if (ts.isShorthandAmbientModuleSymbol(moduleSymbol)) { + 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 hasDefaultOnly = isOnlyImportedAsDefault(node.parent.moduleSpecifier); const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, node.parent.moduleSpecifier); 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_using_export_and_can_only_be_used_with_a_default_import_when_using_the_0_flag, + Diagnostics.This_module_is_declared_with_using_export_and_can_only_be_used_with_a_default_import_when_using_the_0_flag, compilerOptionName )); } @@ -2797,31 +3027,31 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - 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); @@ -2829,7 +3059,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); @@ -2855,24 +3085,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); @@ -2880,33 +3110,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 { @@ -2916,8 +3146,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); } @@ -2928,22 +3158,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { symbolFromModule || symbolFromVariable; if (!symbol) { 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 ); @@ -2958,76 +3188,76 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function reportNonExportedMember(node: ts.ImportDeclaration | ts.ExportDeclaration | ts.VariableDeclaration, name: ts.Identifier, declarationName: string, moduleSymbol: ts.Symbol, moduleName: string): void { + function reportNonExportedMember(node: ImportDeclaration | ExportDeclaration | VariableDeclaration, 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.ImportDeclaration | ts.ExportDeclaration | ts.VariableDeclaration, 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: ImportDeclaration | ExportDeclaration | VariableDeclaration, 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 { - const root = ts.isBindingElement(node) ? ts.getRootDeclaration(node) as ts.VariableDeclaration : node.parent.parent.parent; + function getTargetOfImportSpecifier(node: ImportSpecifier | BindingElement, dontResolveAlias: boolean): Symbol | undefined { + 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) { + function getTargetOfExportSpecifier(node: ExportSpecifier, meaning: SymbolFlags, dontResolveAlias?: boolean) { const resolved = node.parent.parent.moduleSpecifier ? getExternalModuleMember(node.parent.parent, node, dontResolveAlias) : resolveEntityName(node.propertyName || node.name, meaning, /*ignoreErrors*/ false, dontResolveAlias); @@ -3035,21 +3265,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; } @@ -3057,49 +3287,49 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return getNodeLinks(expression).resolvedSymbol; } - function getTargetOfPropertyAssignment(node: ts.PropertyAssignment, dontRecursivelyResolve: boolean): ts.Symbol | undefined { + function getTargetOfPropertyAssignment(node: PropertyAssignment, dontRecursivelyResolve: boolean): Symbol | undefined { const expression = node.initializer; return getTargetOfAliasLikeExpression(expression, dontRecursivelyResolve); } - 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 getTargetOfPropertyAssignment(node as ts.PropertyAssignment, 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 getTargetOfPropertyAssignment(node as PropertyAssignment, dontRecursivelyResolve); + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.PropertyAccessExpression: + return getTargetOfAccessExpression(node as AccessExpression, dontRecursivelyResolve); default: - return ts.Debug.fail(); + return Debug.fail(); } } @@ -3107,30 +3337,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) { @@ -3139,7 +3369,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); @@ -3169,17 +3399,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; @@ -3190,30 +3420,30 @@ 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): ts.TypeOnlyAliasDeclaration | undefined { - if (!(symbol.flags & ts.SymbolFlags.Alias)) { + function getTypeOnlyAliasDeclaration(symbol: Symbol): TypeOnlyAliasDeclaration | undefined { + if (!(symbol.flags & SymbolFlags.Alias)) { return undefined; } const links = getSymbolLinks(symbol); return links.typeOnlyDeclaration || 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 || - ((target.flags & ts.SymbolFlags.Value) && !isConstEnumOrConstEnumOnlyModule(target) && !getTypeOnlyAliasDeclaration(symbol)); + ((target.flags & SymbolFlags.Value) && !isConstEnumOrConstEnumOnlyModule(target) && !getTypeOnlyAliasDeclaration(symbol)); if (markAlias) { markAliasSymbolAsReferenced(symbol); @@ -3224,20 +3454,20 @@ 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 (isInternalModuleImportEqualsDeclaration(node)) { const target = resolveSymbol(symbol); - if (target === unknownSymbol || target.flags & ts.SymbolFlags.Value) { + if (target === unknownSymbol || target.flags & SymbolFlags.Value) { // import foo = - checkExpressionCached(node.moduleReference as ts.Expression); + checkExpressionCached(node.moduleReference as Expression); } } } @@ -3245,7 +3475,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; @@ -3253,46 +3483,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) { @@ -3306,26 +3536,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) { @@ -3333,12 +3563,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); @@ -3351,52 +3581,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); } @@ -3407,7 +3637,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) { @@ -3416,49 +3646,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; } @@ -3469,12 +3699,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) { @@ -3483,24 +3713,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); } @@ -3508,20 +3738,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. @@ -3529,17 +3759,17 @@ 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)) { - error(errorNode, ts.Diagnostics.Module_0_cannot_be_imported_using_this_construct_The_specifier_only_resolves_to_an_ES_module_which_cannot_be_imported_synchronously_Use_dynamic_import_instead, moduleReference); + if (isSyncImport && sourceFile.impliedNodeFormat === ModuleKind.ESNext && !getResolutionModeOverrideForClause(overrideClause)) { + error(errorNode, Diagnostics.Module_0_cannot_be_imported_using_this_construct_The_specifier_only_resolves_to_an_ES_module_which_cannot_be_imported_synchronously_Use_dynamic_import_instead, moduleReference); } } // merged symbol is module declaration symbol combined with all augmentations @@ -3547,13 +3777,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 @@ -3568,9 +3798,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 { @@ -3585,7 +3815,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; } } @@ -3594,40 +3824,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 { @@ -3638,64 +3868,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; @@ -3705,42 +3935,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); @@ -3755,7 +3985,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; @@ -3763,34 +3993,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)) { @@ -3808,14 +4038,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; @@ -3830,47 +4060,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); } } @@ -3886,8 +4116,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); @@ -3896,25 +4126,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 ); } } @@ -3924,11 +4154,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) )); } }); @@ -3938,43 +4168,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!; } } @@ -3984,106 +4214,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; } @@ -4092,7 +4322,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; } @@ -4102,54 +4332,54 @@ 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 && resolveAlias(symbol).flags & ts.SymbolFlags.Value && (includeTypeOnlyMembers || !getTypeOnlyAliasDeclaration(symbol))); + symbol.flags & SymbolFlags.Value || + symbol.flags & SymbolFlags.Alias && resolveAlias(symbol).flags & 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 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 = createType(ts.TypeFlags.Object) as ts.ObjectType; + function createObjectType(objectFlags: ObjectFlags, symbol?: Symbol): ObjectType { + const type = createType(TypeFlags.Object) as ObjectType; type.objectFlags = objectFlags; type.symbol = symbol!; type.members = undefined; @@ -4161,11 +4391,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } function createTypeofType() { - return getUnionType(ts.arrayFrom(typeofEQFacts.keys(), getStringLiteralType)); + return getUnionType(arrayFrom(typeofEQFacts.keys(), getStringLiteralType)); } - function createTypeParameter(symbol?: ts.Symbol) { - const type = createType(ts.TypeFlags.TypeParameter) as ts.TypeParameter; + function createTypeParameter(symbol?: Symbol) { + const type = createType(TypeFlags.TypeParameter) as TypeParameter; if (symbol) type.symbol = symbol; return type; } @@ -4174,38 +4404,38 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // @, 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; @@ -4214,28 +4444,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) @@ -4245,13 +4475,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) @@ -4259,9 +4489,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 @@ -4269,11 +4499,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))) { @@ -4286,17 +4516,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}`; @@ -4316,8 +4546,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; } @@ -4326,41 +4556,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); @@ -4380,7 +4610,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]; } @@ -4395,7 +4625,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 @@ -4411,7 +4641,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Qualify if the symbol from symbol table has same meaning as expected - symbolFromSymbolTable = (symbolFromSymbolTable.flags & ts.SymbolFlags.Alias && !ts.getDeclarationOfKind(symbolFromSymbolTable, ts.SyntaxKind.ExportSpecifier)) ? resolveAlias(symbolFromSymbolTable) : symbolFromSymbolTable; + symbolFromSymbolTable = (symbolFromSymbolTable.flags & SymbolFlags.Alias && !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier)) ? resolveAlias(symbolFromSymbolTable) : symbolFromSymbolTable; if (symbolFromSymbolTable.flags & meaning) { qualify = true; return true; @@ -4424,14 +4654,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; @@ -4442,25 +4672,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 @@ -4473,7 +4703,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 @@ -4484,7 +4714,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 }; } } @@ -4511,15 +4741,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, }; } } @@ -4532,11 +4762,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) { @@ -4545,75 +4775,75 @@ 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 (symbol.flags & ts.SymbolFlags.Alias && ts.isBindingElement(declaration) && 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 (symbol.flags & SymbolFlags.Alias && isBindingElement(declaration) && 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); @@ -4626,118 +4856,118 @@ 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 }; } // 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; } - const builder = flags & ts.SymbolFormatFlags.AllowAnyNodeKind ? nodeBuilder.symbolToExpression : nodeBuilder.symbolToEntityName; - return writer ? symbolToStringWorker(writer).getText() : ts.usingSingleLineStringWriter(symbolToStringWorker); + const builder = flags & SymbolFormatFlags.AllowAnyNodeKind ? nodeBuilder.symbolToExpression : 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) { @@ -4747,56 +4977,56 @@ 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)), }; - 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), @@ -4813,13 +5043,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, @@ -4852,142 +5082,142 @@ 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 { 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.EnumLiteral && !(type.flags & ts.TypeFlags.Union)) { + if (type.flags & TypeFlags.EnumLiteral && !(type.flags & TypeFlags.Union)) { 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`."); } } - if (type.flags & ts.TypeFlags.EnumLike) { - return symbolToTypeNode(type.symbol, context, ts.SymbolFlags.Type); + if (type.flags & TypeFlags.EnumLike) { + 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) { @@ -4995,122 +5225,122 @@ 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); - return symbolToTypeNode(type.aliasSymbol, context, ts.SymbolFlags.Type, typeArgumentNodes); + if (isReservedMemberName(type.aliasSymbol.escapedName) && !(type.aliasSymbol.flags & SymbolFlags.Class)) return factory.createTypeReferenceNode(factory.createIdentifier(""), 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 === markerSuperType || type === markerSubType) && varianceTypeParameter && varianceTypeParameter.symbol ? - (type === markerSubType ? "sub-" : "super-") + ts.symbolName(varianceTypeParameter.symbol) : "?"; - return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(name), /*typeArguments*/ undefined); + (type === markerSubType ? "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.combinedMapper || type.mapper); const saveInferTypeParameters = context.inferTypeParameters; @@ -5131,16 +5361,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; @@ -5149,13 +5379,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?.(); } @@ -5166,21 +5396,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return typeToTypeNodeHelper(type, context); } - 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 (!(getModifiersTypeFromMappedType(type).flags & ts.TypeFlags.TypeParameter) && context.flags & ts.NodeBuilderFlags.GenerateNamesForShadowedTypeParams) { - const newParam = createTypeParameter(createSymbol(ts.SymbolFlags.TypeParameter, "T" as ts.__String)); + if (!(getModifiersTypeFromMappedType(type).flags & TypeFlags.TypeParameter) && 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); @@ -5188,37 +5418,37 @@ 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 (isMappedTypeWithKeyofConstraintDeclaration(type) && !(getModifiersTypeFromMappedType(type).flags & ts.TypeFlags.TypeParameter) && context.flags & ts.NodeBuilderFlags.GenerateNamesForShadowedTypeParams) { + const result = setEmitFlags(mappedTypeNode, EmitFlags.SingleLine); + if (isMappedTypeWithKeyofConstraintDeclaration(type) && !(getModifiersTypeFromMappedType(type).flags & TypeFlags.TypeParameter) && 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 - return ts.factory.createConditionalTypeNode( + return factory.createConditionalTypeNode( typeToTypeNodeHelper(getModifiersTypeFromMappedType(type), context), - ts.factory.createInferTypeNode(ts.factory.createTypeParameterDeclaration(/*modifiers*/ undefined, ts.factory.cloneNode(newTypeVariable!.typeName) as ts.Identifier)), + factory.createInferTypeNode(factory.createTypeParameterDeclaration(/*modifiers*/ undefined, factory.cloneNode(newTypeVariable!.typeName) as Identifier)), 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 && symbol.valueDeclaration.kind === ts.SyntaxKind.ClassExpression && context.flags & ts.NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) || - symbol.flags & (ts.SymbolFlags.Enum | ts.SymbolFlags.ValueModule) || + && !(symbol.valueDeclaration && symbol.valueDeclaration.kind === SyntaxKind.ClassExpression && context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) || + symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule) || shouldWriteTypeOfFunctionSymbol()) { return symbolToTypeNode(symbol, context, isInstanceType); } @@ -5227,7 +5457,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); @@ -5242,40 +5472,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) { @@ -5283,7 +5513,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; @@ -5303,7 +5533,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) { @@ -5311,54 +5541,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 + @@ -5366,9 +5596,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 () => {}) & {}` @@ -5380,67 +5610,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); @@ -5448,7 +5678,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) { @@ -5460,52 +5690,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, qualifier, @@ -5516,31 +5746,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; } @@ -5548,20 +5778,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; @@ -5572,16 +5802,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; } @@ -5594,42 +5824,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 && ts.getCheckFlags(propertySymbol) & ts.CheckFlags.Late && isLateBoundName(propertySymbol.escapedName)) { + if (context.tracker.trackSymbol && getCheckFlags(propertySymbol) & CheckFlags.Late && 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); } } @@ -5645,36 +5875,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, @@ -5683,45 +5913,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); @@ -5732,7 +5962,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]); } } @@ -5747,9 +5977,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); } @@ -5762,17 +5992,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( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, @@ -5783,32 +6013,32 @@ 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( + return factory.createIndexSignature( /*decorators*/ undefined, - indexInfo.isReadonly ? [ts.factory.createToken(ts.SyntaxKind.ReadonlyKeyword)] : undefined, + 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 { @@ -5817,23 +6047,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 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 = 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); @@ -5841,47 +6071,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(/*decorators*/ undefined, modifiers, /*asteriskToken*/ undefined, options?.name ?? ts.factory.createIdentifier(""), /*questionToken*/ undefined, typeParameters, parameters, returnTypeNode, /*body*/ undefined) : - kind === ts.SyntaxKind.Constructor ? ts.factory.createConstructorDeclaration(/*decorators*/ undefined, modifiers, parameters, /*body*/ undefined) : - kind === ts.SyntaxKind.GetAccessor ? ts.factory.createGetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? ts.factory.createIdentifier(""), parameters, returnTypeNode, /*body*/ undefined) : - kind === ts.SyntaxKind.SetAccessor ? ts.factory.createSetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? ts.factory.createIdentifier(""), parameters, /*body*/ undefined) : - kind === ts.SyntaxKind.IndexSignature ? ts.factory.createIndexSignature(/*decorators*/ undefined, 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(/*decorators*/ undefined, 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(/*decorators*/ undefined, modifiers, /*asteriskToken*/ undefined, options?.name ?? factory.createIdentifier(""), /*questionToken*/ undefined, typeParameters, parameters, returnTypeNode, /*body*/ undefined) : + kind === SyntaxKind.Constructor ? factory.createConstructorDeclaration(/*decorators*/ undefined, modifiers, parameters, /*body*/ undefined) : + kind === SyntaxKind.GetAccessor ? factory.createGetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, returnTypeNode, /*body*/ undefined) : + kind === SyntaxKind.SetAccessor ? factory.createSetAccessorDeclaration(/*decorators*/ undefined, modifiers, options?.name ?? factory.createIdentifier(""), parameters, /*body*/ undefined) : + kind === SyntaxKind.IndexSignature ? factory.createIndexSignature(/*decorators*/ undefined, 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(/*decorators*/ undefined, 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( /* decorators */ undefined, /* modifiers */ undefined, /* dotDotDotToken */ undefined, @@ -5893,26 +6123,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); @@ -5921,18 +6151,18 @@ 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 && parameterDeclaration.modifiers ? parameterDeclaration.modifiers.map(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 && parameterDeclaration.modifiers ? parameterDeclaration.modifiers.map(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( /*decorators*/ undefined, modifiers, dotDotDotToken, @@ -5940,54 +6170,54 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { 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]; @@ -5995,17 +6225,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); @@ -6014,8 +6244,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; @@ -6035,9 +6265,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]; @@ -6047,10 +6277,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 countPathComponents(specifierA) - countPathComponents(specifierB); } if (isBRelative) { // A is non-relative, B is relative: prefer A @@ -6064,32 +6294,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); @@ -6101,19 +6331,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) { @@ -6122,8 +6352,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); } @@ -6138,22 +6368,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(getModuleSpecifiers( symbol, checker, specifierCompilerOptions, @@ -6162,46 +6392,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") ) ]))); } @@ -6209,11 +6439,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) { @@ -6221,10 +6451,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") ) ]))); } @@ -6239,55 +6469,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; } }); @@ -6295,11 +6525,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; } @@ -6307,37 +6537,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; @@ -6345,156 +6575,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)); } } } @@ -6514,37 +6744,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) { @@ -6554,32 +6784,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) { @@ -6591,157 +6821,157 @@ 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( /*decorators*/ undefined, /*modifiers*/ undefined, - [ts.factory.createParameterDeclaration( + [factory.createParameterDeclaration( /*decorators*/ undefined, /*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( node.modifiers, - 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( /*decorators*/ undefined, /*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( /*decorators*/ undefined, /*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.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) { @@ -6749,36 +6979,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); } } } @@ -6795,9 +7025,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((_decorators, 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((_decorators, 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 @@ -6806,22 +7036,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]); } } @@ -6833,57 +7063,57 @@ 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.decorators, 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( /*decorators*/ undefined, /*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 )]) ) @@ -6892,48 +7122,48 @@ 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( /*decorators*/ undefined, /*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( /*decorators*/ undefined, /*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 ) ]; @@ -6944,37 +7174,37 @@ 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 => 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.decorators, exportDecl.modifiers, exportDecl.isTypeOnly, - ts.factory.updateNamedExports( + factory.updateNamedExports( exportDecl.exportClause, replacements ), @@ -6986,7 +7216,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); @@ -6994,52 +7224,52 @@ 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 canHaveExportModifier(node: ts.Statement): node is Extract { - return ts.isEnumDeclaration(node) || - ts.isVariableStatement(node) || - ts.isFunctionDeclaration(node) || - ts.isClassDeclaration(node) || - (ts.isModuleDeclaration(node) && !ts.isExternalModuleAugmentation(node) && !ts.isGlobalScopeAugmentation(node)) || - ts.isInterfaceDeclaration(node) || + function canHaveExportModifier(node: Statement): node is Extract { + return isEnumDeclaration(node) || + isVariableStatement(node) || + isFunctionDeclaration(node) || + isClassDeclaration(node) || + (isModuleDeclaration(node) && !isExternalModuleAugmentation(node) && !isGlobalScopeAugmentation(node)) || + isInterfaceDeclaration(node) || isTypeDeclaration(node); } - 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) { + function serializeSymbol(symbol: Symbol, isPrivate: boolean, propertyAsAlias: boolean) { // 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); @@ -7049,7 +7279,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); const result = serializeSymbolWorker(symbol, isPrivate, propertyAsAlias); @@ -7071,41 +7301,41 @@ 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) { - 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) { + 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) + if (symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.FunctionScopedVariable | SymbolFlags.Property) + && symbol.escapedName !== InternalSymbolName.ExportEquals + && !(symbol.flags & SymbolFlags.Prototype) + && !(symbol.flags & SymbolFlags.Class) && !isConstMergedWithNSPrintableAsSignatureMerge) { if (propertyAsAlias) { const createdExport = serializeMaybeAliasAssignment(symbol); @@ -7117,45 +7347,45 @@ 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( /*decorators*/ undefined, /*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: @@ -7179,13 +7409,13 @@ 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( /*decorators*/ undefined, /*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; @@ -7194,14 +7424,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. @@ -7211,129 +7441,129 @@ 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(/*decorators*/ undefined, /*modifiers*/ undefined, /*isTypeOnly*/ false, /*exportClause*/ undefined, ts.factory.createStringLiteral(getSpecifierForModuleSymbol(resolvedModule, context))), ts.ModifierFlags.None); + addResult(factory.createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*isTypeOnly*/ false, /*exportClause*/ undefined, factory.createStringLiteral(getSpecifierForModuleSymbol(resolvedModule, context))), ModifierFlags.None); } } } if (needsPostExportDefault) { - addResult(ts.factory.createExportAssignment(/*decorators*/ undefined, /*modifiers*/ undefined, /*isExportAssignment*/ false, ts.factory.createIdentifier(getInternalSymbolName(symbol, symbolName))), ts.ModifierFlags.None); + addResult(factory.createExportAssignment(/*decorators*/ undefined, /*modifiers*/ undefined, /*isExportAssignment*/ false, factory.createIdentifier(getInternalSymbolName(symbol, symbolName))), ModifierFlags.None); } else if (needsExportDeclaration) { - addResult(ts.factory.createExportDeclaration( + addResult(factory.createExportDeclaration( /*decorators*/ undefined, /*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)) && + (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(/*decorators*/ undefined, /*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(/*decorators*/ undefined, /*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( /*decorators*/ undefined, /*modifiers*/ undefined, getInternalSymbolName(symbol, symbolName), @@ -7343,111 +7573,111 @@ 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 => !(resolveSymbol(m).flags & ts.SymbolFlags.Value)); + function isTypeOnlyNamespace(symbol: Symbol) { + return every(getNamespaceMembersForSerialization(symbol), m => !(resolveSymbol(m).flags & 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( /*decorators*/ undefined, /*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( /*decorators*/ undefined, /*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( + function serializeEnum(symbol: Symbol, symbolName: string, modifierFlags: ModifierFlags) { + addResult(factory.createEnumDeclaration( /*decorators*/ undefined, - ts.factory.createModifiersFromModifierFlags(isConstEnumSymbol(symbol) ? ts.ModifierFlags.Const : 0), + 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: @@ -7465,9 +7695,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(/*decorators*/ undefined, /*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(/*decorators*/ undefined, /*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; @@ -7478,41 +7708,41 @@ 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( /*decorators*/ undefined, /*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.decorators, 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; @@ -7521,8 +7751,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) ) @@ -7539,56 +7769,56 @@ 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 = getNonInterhitedProperties(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( /*decorators*/ undefined, /*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 @@ -7596,217 +7826,217 @@ 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(/*decorators*/ undefined, ts.factory.createModifiersFromModifierFlags(ts.ModifierFlags.Private), [], /*body*/ undefined)] : - serializeSignatures(ts.SignatureKind.Construct, staticType, staticBaseType, ts.SyntaxKind.Constructor) as ts.ConstructorDeclaration[]; + [factory.createConstructorDeclaration(/*decorators*/ undefined, 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( /*decorators*/ undefined, /*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( /*decorators*/ undefined, /*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( /*decorators*/ undefined, /*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( /*decorators*/ undefined, /*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( /*decorators*/ undefined, /*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( /*decorators*/ undefined, /*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( /*decorators*/ undefined, /*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( /*decorators*/ undefined, /*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( /*decorators*/ undefined, /*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 { @@ -7814,30 +8044,30 @@ 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( /*decorators*/ undefined, /*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 @@ -7846,13 +8076,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); } @@ -7865,31 +8095,31 @@ 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( /*decorators*/ undefined, /*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( /*decorators*/ undefined, /*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); } } @@ -7904,25 +8134,25 @@ 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( /*decorators*/ undefined, /*modifiers*/ undefined, isExportEquals, - ts.factory.createIdentifier(varName) + factory.createIdentifier(varName) )); return true; } @@ -7934,73 +8164,73 @@ 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: ( - decorators: readonly ts.Decorator[] | undefined, - 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: ( - decorators: readonly ts.Decorator[] | undefined, - 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: ( - decorators: readonly ts.Decorator[] | undefined, - 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: ( + decorators: readonly Decorator[] | undefined, + 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: ( + decorators: readonly Decorator[] | undefined, + 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: ( + decorators: readonly Decorator[] | undefined, + 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( + 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( /*decorators*/ undefined, - ts.factory.createModifiersFromModifierFlags(flag), + factory.createModifiersFromModifierFlags(flag), name, - [ts.factory.createParameterDeclaration( + [factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, @@ -8009,47 +8239,47 @@ 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( + if (p.flags & SymbolFlags.GetAccessor) { + const isPrivate = modifierFlags & ModifierFlags.Private; + result.push(setTextRange(factory.createGetAccessorDeclaration( /*decorators*/ undefined, - ts.factory.createModifiersFromModifierFlags(flag), + 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( + else if (p.flags & (SymbolFlags.Property | SymbolFlags.Variable | SymbolFlags.Accessor)) { + return setTextRange(createProperty( /*decorators*/ undefined, - ts.factory.createModifiersFromModifierFlags((isReadonlySymbol(p) ? ts.ModifierFlags.Readonly : 0) | flag), + 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, getTypeOfSymbol(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( + const signatures = getSignaturesOfType(type, SignatureKind.Call); + if (flag & ModifierFlags.Private) { + return setTextRange(createProperty( /*decorators*/ undefined, - ts.factory.createModifiersFromModifierFlags((isReadonlySymbol(p) ? ts.ModifierFlags.Readonly : 0) | flag), + 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 = []; @@ -8061,34 +8291,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) { @@ -8104,16 +8334,16 @@ 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( + return [setTextRange(factory.createConstructorDeclaration( /*decorators*/ undefined, - ts.factory.createModifiersFromModifierFlags(privateProtected), + factory.createModifiersFromModifierFlags(privateProtected), /*parameters*/ [], /*body*/ undefined, ), signatures[0].declaration)]; @@ -8124,13 +8354,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); @@ -8145,48 +8375,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)) { @@ -8209,25 +8439,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)!; @@ -8240,34 +8470,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; @@ -8277,78 +8507,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)}]`; } } } @@ -8360,26 +8590,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) { @@ -8387,29 +8617,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) { @@ -8422,90 +8652,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: @@ -8514,42 +8744,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); } } @@ -8600,25 +8830,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); } /** @@ -8631,15 +8861,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; @@ -8647,38 +8877,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); } @@ -8686,24 +8916,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); } @@ -8720,7 +8950,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; } @@ -8730,21 +8960,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); } @@ -8757,23 +8987,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; @@ -8781,52 +9011,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` @@ -8834,27 +9064,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); } } @@ -8869,12 +9099,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); } @@ -8885,50 +9115,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 && !(getFalsyFlags(checkDeclarationInitializer(declaration, CheckMode.Normal)) & ts.TypeFlags.Undefined) ? getNonUndefinedType(type) : type; + return strictNullChecks && !(getFalsyFlags(checkDeclarationInitializer(declaration, CheckMode.Normal)) & TypeFlags.Undefined) ? 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, @@ -8937,14 +9167,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.isPropertySignature(declaration); + const isProperty = isPropertyDeclaration(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 @@ -8953,13 +9183,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 @@ -8969,28 +9199,28 @@ 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); } } - if (ts.isInJSFile(declaration)) { + if (isInJSFile(declaration)) { const type = getParameterTypeOfTypeTag(func, declaration); if (type) return type; } // 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); } @@ -8998,9 +9228,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; } @@ -9009,26 +9239,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; @@ -9036,7 +9266,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); } @@ -9044,18 +9274,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; @@ -9063,55 +9293,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)) { @@ -9121,35 +9351,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); } @@ -9165,21 +9395,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; } @@ -9187,17 +9417,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; @@ -9209,41 +9439,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) { @@ -9254,7 +9484,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) { @@ -9267,24 +9497,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) { @@ -9296,24 +9526,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) { - if (s.flags & ts.SymbolFlags.Value && exportedMember.flags & ts.SymbolFlags.Value) { + 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: @@ -9324,20 +9554,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 { @@ -9354,9 +9584,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { exportedType.callSignatures, exportedType.constructSignatures, exportedType.indexInfos); - 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; } @@ -9367,27 +9597,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); }); } @@ -9395,15 +9625,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)) { @@ -9417,12 +9647,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; @@ -9431,41 +9661,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; } @@ -9477,8 +9707,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); } @@ -9492,20 +9722,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) { @@ -9513,7 +9743,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; } @@ -9521,7 +9751,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) { @@ -9532,20 +9762,20 @@ 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 getTypeOfVariableOrParameterOrProperty(symbol: ts.Symbol): ts.Type { + function getTypeOfVariableOrParameterOrProperty(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.type) { const type = getTypeOfVariableOrParameterOrPropertyWorker(symbol); @@ -9559,33 +9789,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; } @@ -9594,13 +9824,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); @@ -9609,74 +9839,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); @@ -9684,66 +9914,66 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function getAnnotatedAccessorTypeNode(accessor: ts.AccessorDeclaration | undefined): ts.TypeNode | undefined { + function getAnnotatedAccessorTypeNode(accessor: AccessorDeclaration | undefined): TypeNode | undefined { if (accessor) { - if (accessor.kind === ts.SyntaxKind.GetAccessor) { - const getterTypeAnnotation = ts.getEffectiveReturnTypeNode(accessor); + if (accessor.kind === SyntaxKind.GetAccessor) { + const getterTypeAnnotation = getEffectiveReturnTypeNode(accessor); return getterTypeAnnotation; } else { - const setterTypeAnnotation = ts.getEffectiveSetAccessorTypeAnnotationNode(accessor); + const setterTypeAnnotation = getEffectiveSetAccessorTypeAnnotationNode(accessor); return setterTypeAnnotation; } } return undefined; } - function getAnnotatedAccessorType(accessor: ts.AccessorDeclaration | undefined): ts.Type | undefined { + function getAnnotatedAccessorType(accessor: AccessorDeclaration | 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 getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); + const setter = getDeclarationOfKind(symbol, SyntaxKind.SetAccessor); // 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) || getter && getter.body && getReturnTypeFromBody(getter); 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)); } 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 (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; } @@ -9752,17 +9982,17 @@ 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); + const setter = getDeclarationOfKind(symbol, SyntaxKind.SetAccessor); 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; } @@ -9772,14 +10002,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) { @@ -9796,23 +10026,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); @@ -9820,27 +10050,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. @@ -9849,33 +10079,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 - : targetSymbol.flags & ts.SymbolFlags.Value ? getTypeOfSymbol(targetSymbol) + : targetSymbol.flags & 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 @@ -9884,22 +10114,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; } @@ -9909,80 +10139,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; } @@ -9991,23 +10221,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!; } } @@ -10016,49 +10246,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; } } @@ -10066,27 +10296,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; @@ -10094,14 +10324,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)) { @@ -10112,33 +10342,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); } /** @@ -10149,10 +10379,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; @@ -10162,31 +10392,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; @@ -10196,17 +10426,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); @@ -10218,30 +10448,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); } } @@ -10252,28 +10482,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 { @@ -10282,28 +10512,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 @@ -10313,21 +10543,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); @@ -10335,22 +10565,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); @@ -10361,7 +10591,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); } } } @@ -10377,21 +10607,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; } } @@ -10402,18 +10632,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 @@ -10421,24 +10651,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 @@ -10447,8 +10677,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; @@ -10458,17 +10688,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; @@ -10476,39 +10706,39 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.declaredType; } - function isStringConcatExpression(expr: ts.Node): boolean { - if (ts.isStringLiteralLike(expr)) { + function isStringConcatExpression(expr: Node): boolean { + if (isStringLiteralLike(expr)) { return true; } - else if (expr.kind === ts.SyntaxKind.BinaryExpression) { - return isStringConcatExpression((expr as ts.BinaryExpression).left) && isStringConcatExpression((expr as ts.BinaryExpression).right); + else if (expr.kind === SyntaxKind.BinaryExpression) { + return isStringConcatExpression((expr as BinaryExpression).left) && isStringConcatExpression((expr as BinaryExpression).right); } return false; } - function isLiteralEnumMember(member: ts.EnumMember) { + function isLiteralEnumMember(member: EnumMember) { const expr = member.initializer; if (!expr) { - return !(member.flags & ts.NodeFlags.Ambient); + return !(member.flags & NodeFlags.Ambient); } switch (expr.kind) { - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NumericLiteral: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.StringLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: return true; - case ts.SyntaxKind.PrefixUnaryExpression: - return (expr as ts.PrefixUnaryExpression).operator === ts.SyntaxKind.MinusToken && - (expr as ts.PrefixUnaryExpression).operand.kind === ts.SyntaxKind.NumericLiteral; - case ts.SyntaxKind.Identifier: - return ts.nodeIsMissing(expr) || !!getSymbolOfNode(member.parent).exports!.get((expr as ts.Identifier).escapedText); - case ts.SyntaxKind.BinaryExpression: + case SyntaxKind.PrefixUnaryExpression: + return (expr as PrefixUnaryExpression).operator === SyntaxKind.MinusToken && + (expr as PrefixUnaryExpression).operand.kind === SyntaxKind.NumericLiteral; + case SyntaxKind.Identifier: + return nodeIsMissing(expr) || !!getSymbolOfNode(member.parent).exports!.get((expr as Identifier).escapedText); + case SyntaxKind.BinaryExpression: return isStringConcatExpression(expr); default: return false; } } - function getEnumKind(symbol: ts.Symbol): ts.EnumKind { + function getEnumKind(symbol: Symbol): EnumKind { const links = getSymbolLinks(symbol); if (links.enumKind !== undefined) { return links.enumKind; @@ -10516,10 +10746,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { let hasNonLiteralMember = false; 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 (member.initializer && ts.isStringLiteralLike(member.initializer)) { - return links.enumKind = ts.EnumKind.Literal; + if (declaration.kind === SyntaxKind.EnumDeclaration) { + for (const member of (declaration as EnumDeclaration).members) { + if (member.initializer && isStringLiteralLike(member.initializer)) { + return links.enumKind = EnumKind.Literal; } if (!isLiteralEnumMember(member)) { hasNonLiteralMember = true; @@ -10528,25 +10758,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - return links.enumKind = hasNonLiteralMember ? ts.EnumKind.Numeric : ts.EnumKind.Literal; + return links.enumKind = hasNonLiteralMember ? EnumKind.Numeric : EnumKind.Literal; } - 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) { return links.declaredType; } - if (getEnumKind(symbol) === ts.EnumKind.Literal) { + if (getEnumKind(symbol) === EnumKind.Literal) { enumCount++; - 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) { const value = getEnumMemberValue(member); const memberType = getFreshTypeOfLiteralType(getEnumLiteralType(value !== undefined ? value : 0, enumCount, getSymbolOfNode(member))); getSymbolLinks(getSymbolOfNode(member)).declaredType = memberType; @@ -10556,20 +10786,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } if (memberTypeList.length) { - const enumType = getUnionType(memberTypeList, ts.UnionReduction.Literal, symbol, /*aliasTypeArguments*/ undefined); - if (enumType.flags & ts.TypeFlags.Union) { - enumType.flags |= ts.TypeFlags.EnumLiteral; + const enumType = getUnionType(memberTypeList, UnionReduction.Literal, symbol, /*aliasTypeArguments*/ undefined); + if (enumType.flags & TypeFlags.Union) { + enumType.flags |= TypeFlags.EnumLiteral; enumType.symbol = symbol; } return links.declaredType = enumType; } } - const enumType = createType(ts.TypeFlags.Enum); + const enumType = createType(TypeFlags.Enum); enumType.symbol = symbol; return links.declaredType = enumType; } - function getDeclaredTypeOfEnumMember(symbol: ts.Symbol): ts.Type { + function getDeclaredTypeOfEnumMember(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.declaredType) { const enumType = getDeclaredTypeOfEnum(getParentOfSymbol(symbol)!); @@ -10580,37 +10810,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; @@ -10621,32 +10851,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); } @@ -10654,9 +10884,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); } /** @@ -10664,10 +10894,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); } @@ -10679,20 +10909,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); } } } @@ -10701,15 +10931,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); @@ -10717,32 +10947,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); } /** @@ -10753,54 +10983,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(); } /** @@ -10808,8 +11038,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) { @@ -10818,7 +11048,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; } @@ -10853,22 +11083,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 @@ -10877,16 +11107,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; @@ -10897,12 +11127,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 @@ -10911,12 +11141,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) && hasLateBindableName(member)) { + if (isStatic === hasStaticModifier(member) && hasLateBindableName(member)) { lateBindMember(symbol, earlySymbols, lateSymbols, member); } } @@ -10924,13 +11154,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 && hasLateBindableName(member)) { lateBindMember(symbol, earlySymbols, lateSymbols, member); } @@ -10948,8 +11178,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; } @@ -10960,13 +11190,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 { @@ -10978,30 +11208,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; @@ -11016,44 +11246,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; @@ -11070,9 +11300,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; @@ -11080,94 +11310,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; @@ -11175,7 +11405,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. @@ -11189,7 +11419,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. @@ -11197,7 +11427,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!match) { return undefined; } - result = ts.appendIfUnique(result, match); + result = appendIfUnique(result, match); } return result; } @@ -11206,11 +11436,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 } @@ -11223,9 +11453,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); @@ -11236,18 +11466,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; } @@ -11255,11 +11485,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) { @@ -11282,7 +11512,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; } @@ -11293,7 +11523,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; @@ -11301,7 +11531,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) { @@ -11322,14 +11552,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); @@ -11339,9 +11569,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 @@ -11358,79 +11588,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 @@ -11439,9 +11669,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; @@ -11449,22 +11679,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]; @@ -11476,54 +11706,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) { @@ -11537,30 +11767,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) { @@ -11570,37 +11800,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; @@ -11608,50 +11838,50 @@ 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) { - return getIntersectionType(ts.sameMap((type as ts.UnionType).types, getLowerBoundOfKeyType)); + if (type.flags & TypeFlags.Intersection) { + 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); } } @@ -11659,20 +11889,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); @@ -11680,14 +11910,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)) { @@ -11695,7 +11925,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]); @@ -11703,13 +11933,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; @@ -11722,9 +11952,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)); @@ -11733,24 +11963,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; @@ -11758,128 +11988,128 @@ 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 { - return !!(ts.getObjectFlags(type) & ts.ObjectFlags.Mapped) && isGenericIndexType(getConstraintTypeFromMappedType(type as ts.MappedType)); + function isGenericMappedType(type: Type): type is MappedType { + return !!(getObjectFlags(type) & ObjectFlags.Mapped) && isGenericIndexType(getConstraintTypeFromMappedType(type as MappedType)); } - 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 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); } } - 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; @@ -11887,9 +12117,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)) { @@ -11901,7 +12131,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; } } @@ -11910,17 +12140,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); } @@ -11928,8 +12158,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; @@ -11938,50 +12168,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) { @@ -11997,7 +12227,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 @@ -12010,7 +12240,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 @@ -12027,7 +12257,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; } } @@ -12035,33 +12265,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) { + else if (t.flags & TypeFlags.DisjointDomains) { hasDisjointDomainType = true; } } @@ -12072,8 +12302,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) { - constraints = ts.append(constraints, t); + if (t.flags & TypeFlags.DisjointDomains) { + constraints = append(constraints, t); } } } @@ -12082,23 +12312,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; } @@ -12107,14 +12337,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; @@ -12127,18 +12357,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)); } } } @@ -12149,21 +12379,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); @@ -12180,49 +12410,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 ? getStringMappingType((t as ts.StringMappingType).symbol, constraint) : stringType; + if (t.flags & TypeFlags.StringMapping) { + const constraint = getBaseConstraint((t as StringMappingType).type); + return constraint ? 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((t as ts.SubstitutionType).substitute); + if (t.flags & TypeFlags.Substitution) { + return getBaseConstraint((t as SubstitutionType).substitute); } 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); @@ -12231,7 +12461,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. @@ -12253,27 +12483,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); @@ -12284,11 +12514,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) && - !(objectType as ts.MappedType).declaration.questionToken && !(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) && + !(objectType as MappedType).declaration.questionToken && !(objectType as MappedType).declaration.nameType); } /** @@ -12296,22 +12526,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(/*reportErrors*/ languageVersion >= ts.ScriptTarget.ES2020) : - t.flags & ts.TypeFlags.BooleanLike ? globalBooleanType : - t.flags & ts.TypeFlags.ESSymbolLike ? getGlobalESSymbolType(/*reportErrors*/ languageVersion >= ts.ScriptTarget.ES2015) : - 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(/*reportErrors*/ languageVersion >= ScriptTarget.ES2020) : + t.flags & TypeFlags.BooleanLike ? globalBooleanType : + t.flags & TypeFlags.ESSymbolLike ? getGlobalESSymbolType(/*reportErrors*/ languageVersion >= ScriptTarget.ES2015) : + 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 @@ -12319,24 +12549,24 @@ 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 = isUnion ? ts.SymbolFlags.None : ts.SymbolFlags.Optional; - let syntheticFlag = ts.CheckFlags.SyntheticMethod; - let checkFlags = isUnion ? 0 : ts.CheckFlags.Readonly; + let optionalFlag = isUnion ? SymbolFlags.None : SymbolFlags.Optional; + 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 (isUnion) { - optionalFlag |= (prop.flags & ts.SymbolFlags.Optional); + optionalFlag |= (prop.flags & SymbolFlags.Optional); } else { optionalFlag &= prop.flags; @@ -12349,15 +12579,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 it's 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); @@ -12367,62 +12597,62 @@ 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)) { + if (!singleProp || isUnion && (propSet || checkFlags & CheckFlags.Partial) && checkFlags & (CheckFlags.ContainsPrivate | CheckFlags.ContainsProtected)) { // 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) { @@ -12431,7 +12661,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; @@ -12439,21 +12669,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, name, syntheticFlag | checkFlags); + addRange(propTypes, indexTypes); + const result = createSymbol(SymbolFlags.Property | optionalFlag, name, syntheticFlag | checkFlags); result.containingType = containingType; if (!hasNonUniformValueDeclaration && firstValueDeclaration) { result.valueDeclaration = firstValueDeclaration; @@ -12468,7 +12698,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; @@ -12487,25 +12717,25 @@ 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 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; } /** @@ -12514,60 +12744,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; @@ -12581,10 +12811,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; @@ -12602,37 +12832,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; @@ -12649,69 +12879,69 @@ 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): 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): TypeParameter[] | undefined { + let result: TypeParameter[] | undefined; + for (const node of getEffectiveTypeParameterDeclarations(declaration)) { + result = appendIfUnique(result, getDeclaredTypeOfTypeParameter(node.symbol)); } return result; } - 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); @@ -12720,38 +12950,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 && @@ -12761,27 +12991,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isOptionalPropertyDeclaration(node: ts.Declaration) { - return ts.isPropertyDeclaration(node) && node.questionToken; + function isOptionalPropertyDeclaration(node: Declaration) { + return isPropertyDeclaration(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++) { @@ -12801,14 +13031,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 @@ -12829,23 +13059,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 @@ -12855,13 +13085,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; } @@ -12869,13 +13099,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) { @@ -12884,26 +13114,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, @@ -12918,16 +13148,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)); @@ -12936,7 +13166,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]; @@ -12949,73 +13179,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; @@ -13026,7 +13256,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); @@ -13038,13 +13268,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); @@ -13054,65 +13284,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; - if (!type && ts.isInJSFile(signature.declaration)) { + const type = signature.declaration && getEffectiveReturnTypeNode(signature.declaration); + let jsdocPredicate: TypePredicate | undefined; + if (!type && isInJSFile(signature.declaration)) { 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); } } } @@ -13123,23 +13353,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; @@ -13148,15 +13378,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; @@ -13165,7 +13395,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)); @@ -13180,8 +13410,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) { @@ -13190,32 +13420,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 @@ -13224,19 +13454,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++) { @@ -13249,7 +13479,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 @@ -13258,48 +13488,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)); } }); } @@ -13307,33 +13537,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) { @@ -13346,7 +13576,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const mapper = createTypeMapper(typeParameters, getEffectiveTypeArguments(typeReference, typeParameters)); const constraint = instantiateType(declaredConstraint, mapper); if (constraint !== typeParameter) { - inferences = ts.append(inferences, constraint); + inferences = append(inferences, constraint); } } } @@ -13354,31 +13584,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) )); } @@ -13389,7 +13619,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); @@ -13402,10 +13632,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; } @@ -13414,13 +13644,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; @@ -13444,7 +13674,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)}` : "") : ""; } @@ -13452,21 +13682,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 the anyFunctionType. 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 (!(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, /*excludeKinds*/ 0) : 0; type.target = target; @@ -13475,8 +13705,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function cloneTypeReference(source: ts.TypeReference): ts.TypeReference { - const type = createType(source.flags) as ts.TypeReference; + function cloneTypeReference(source: TypeReference): TypeReference { + const type = createType(source.flags) as TypeReference; type.symbol = source.symbol; type.objectFlags = source.objectFlags; type.target = source.target; @@ -13484,13 +13714,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { 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; @@ -13499,24 +13729,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) ); } @@ -13524,52 +13754,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]); @@ -13580,7 +13810,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; @@ -13591,13 +13821,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); @@ -13607,13 +13837,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); @@ -13630,20 +13860,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; @@ -13652,23 +13882,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; } @@ -13677,7 +13907,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; @@ -13687,15 +13917,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) @@ -13703,14 +13933,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); } } @@ -13721,13 +13951,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); @@ -13738,8 +13968,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedJSDocType; } - function getSubstitutionType(baseType: ts.Type, substitute: ts.Type) { - if (substitute.flags & ts.TypeFlags.AnyOrUnknown || substitute === baseType) { + function getSubstitutionType(baseType: Type, substitute: Type) { + if (substitute.flags & TypeFlags.AnyOrUnknown || substitute === baseType) { return baseType; } const id = `${getTypeId(baseType)}>${getTypeId(substitute)}`; @@ -13747,74 +13977,74 @@ 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.substitute = substitute; substitutionTypes.set(id, result); return result; } - 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])); } } } } node = parent; } - return constraints ? getSubstitutionType(type, getIntersectionType(ts.append(constraints, type))) : type; + return constraints ? getSubstitutionType(type, getIntersectionType(append(constraints, type))) : 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": @@ -13845,11 +14075,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; } @@ -13859,28 +14089,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 @@ -13900,11 +14130,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 @@ -13917,16 +14147,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; } } @@ -13937,262 +14167,262 @@ 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(reportErrors: boolean) { - return (deferredGlobalESSymbolType ||= getGlobalType("Symbol" as ts.__String, /*arity*/ 0, reportErrors)) || emptyObjectType; + return (deferredGlobalESSymbolType ||= getGlobalType("Symbol" as __String, /*arity*/ 0, reportErrors)) || 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(reportErrors: boolean) { - return (deferredGlobalBigIntType ||= getGlobalType("BigInt" as ts.__String, /*arity*/ 0, reportErrors)) || emptyObjectType; + return (deferredGlobalBigIntType ||= getGlobalType("BigInt" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType; } /** * 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; @@ -14200,74 +14430,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)); @@ -14282,21 +14512,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); @@ -14304,8 +14534,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 { @@ -14314,46 +14544,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; } } @@ -14362,34 +14592,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 { @@ -14399,12 +14629,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); @@ -14414,14 +14644,14 @@ 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(type); @@ -14435,44 +14665,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; @@ -14480,22 +14710,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); } @@ -14506,14 +14736,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; @@ -14528,19 +14758,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) { @@ -14552,23 +14782,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; } } @@ -14579,59 +14809,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; } @@ -14643,51 +14873,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); } } @@ -14696,26 +14926,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 { @@ -14742,12 +14972,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; } @@ -14755,92 +14985,92 @@ 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 removeRedundantPrimitiveTypes(types: ts.Type[], includes: ts.TypeFlags) { + function removeRedundantPrimitiveTypes(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 & 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; if (remove) { - ts.orderedRemoveItemAt(types, i); + orderedRemoveItemAt(types, i); } } } @@ -14848,13 +15078,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; @@ -14867,17 +15097,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)) { @@ -14888,11 +15118,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)); } @@ -14901,9 +15131,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; } @@ -14912,9 +15142,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++; @@ -14927,8 +15157,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)) { @@ -14939,13 +15169,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; @@ -14962,10 +15192,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[]): ts.Type { - const typeMembershipMap: ts.ESMap = new ts.Map(); + function getIntersectionType(types: readonly Type[], aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): 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, @@ -14975,37 +15205,37 @@ 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.Undefined ? undefinedType : nullType; + if (!strictNullChecks && includes & TypeFlags.Nullable) { + return 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) { + 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) { removeRedundantPrimitiveTypes(typeSet, includes); } - if (includes & ts.TypeFlags.IncludesEmptyObject && includes & ts.TypeFlags.Object) { - ts.orderedRemoveItemAt(typeSet, ts.findIndex(typeSet, isEmptyAnonymousObjectType)); + if (includes & TypeFlags.IncludesEmptyObject && includes & TypeFlags.Object) { + orderedRemoveItemAt(typeSet, findIndex(typeSet, isEmptyAnonymousObjectType)); } - if (includes & ts.TypeFlags.IncludesMissingType) { + if (includes & TypeFlags.IncludesMissingType) { typeSet[typeSet.indexOf(undefinedType)] = missingType; } if (typeSet.length === 0) { @@ -15017,21 +15247,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 @@ -15043,8 +15273,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const constituents = getCrossProductIntersections(typeSet); // 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). - const origin = ts.some(constituents, t => !!(t.flags & ts.TypeFlags.Intersection)) ? createOriginUnionOrIntersectionType(ts.TypeFlags.Intersection, typeSet) : undefined; - result = getUnionType(constituents, ts.UnionReduction.Literal, aliasSymbol, aliasTypeArguments, origin); + const origin = some(constituents, t => !!(t.flags & TypeFlags.Intersection)) ? createOriginUnionOrIntersectionType(TypeFlags.Intersection, typeSet) : undefined; + result = getUnionType(constituents, UnionReduction.Literal, aliasSymbol, aliasTypeArguments, origin); } } else { @@ -15055,64 +15285,64 @@ 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 getTypeFromIntersectionTypeNode(node: ts.IntersectionTypeNode): ts.Type { + function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { const aliasSymbol = getAliasSymbolForTypeNode(node); - links.resolvedType = getIntersectionType(ts.map(node.types, getTypeFromTypeNode), + links.resolvedType = getIntersectionType(map(node.types, getTypeFromTypeNode), aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol)); } 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)); @@ -15125,15 +15355,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 } @@ -15142,7 +15372,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 @@ -15158,13 +15388,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. @@ -15177,35 +15407,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).substitute) : - 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).substitute) : + 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; @@ -15214,16 +15444,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); } @@ -15233,29 +15463,29 @@ 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.UnionType): boolean { - return ts.some(type.types, t => { + function isPossiblyReducibleByInstantiation(type: UnionType): boolean { + return some(type.types, t => { const uniqueFilled = getUniqueLiteralFilledInstantiation(t); return getReducedType(uniqueFilled) !== uniqueFilled; }); } - function getIndexType(type: ts.Type, stringsOnly = keyofStringsOnly, noIndexSignatures?: boolean): ts.Type { + function getIndexType(type: Type, stringsOnly = keyofStringsOnly, noIndexSignatures?: boolean): Type { type = getReducedType(type); - return type.flags & ts.TypeFlags.Union ? isPossiblyReducibleByInstantiation(type as ts.UnionType) - ? getIndexTypeForGenericType(type as ts.InstantiableType | ts.UnionOrIntersectionType, stringsOnly) - : 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))) : - type.flags & ts.TypeFlags.InstantiableNonPrimitive || isGenericTupleType(type) || isGenericMappedType(type) && !hasDistributiveNameType(type) ? getIndexTypeForGenericType(type as ts.InstantiableType | ts.UnionOrIntersectionType, stringsOnly) : - ts.getObjectFlags(type) & ts.ObjectFlags.Mapped ? getIndexTypeForMappedType(type as ts.MappedType, stringsOnly, noIndexSignatures) : + return type.flags & TypeFlags.Union ? isPossiblyReducibleByInstantiation(type as UnionType) + ? getIndexTypeForGenericType(type as InstantiableType | UnionOrIntersectionType, stringsOnly) + : 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))) : + type.flags & TypeFlags.InstantiableNonPrimitive || isGenericTupleType(type) || isGenericMappedType(type) && !hasDistributiveNameType(type) ? getIndexTypeForGenericType(type as InstantiableType | UnionOrIntersectionType, stringsOnly) : + 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; } @@ -15263,54 +15493,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)) { @@ -15320,29 +15550,29 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return getStringLiteralType(text); } newTexts.push(text); - if (ts.every(newTexts, t => t === "") && ts.every(newTypes, t => !!(t.flags & ts.TypeFlags.String))) { + if (every(newTexts, t => t === "") && every(newTypes, t => !!(t.flags & TypeFlags.String))) { return stringType; } - 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; } @@ -15351,8 +15581,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) { @@ -15363,29 +15593,29 @@ 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)) : + function getStringMappingType(symbol: Symbol, type: Type): Type { + return type.flags & (TypeFlags.Union | TypeFlags.Never) ? mapType(type, t => getStringMappingType(symbol, t)) : isGenericIndexType(type) ? getStringMappingTypeForGenericType(symbol, type) : - type.flags & ts.TypeFlags.StringLiteral ? getStringLiteralType(applyStringMapping(symbol, (type as ts.StringLiteralType).value)) : + type.flags & TypeFlags.StringLiteral ? getStringLiteralType(applyStringMapping(symbol, (type as StringLiteralType).value)) : 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(); @@ -15395,7 +15625,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return str; } - 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) { @@ -15404,15 +15634,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function createStringMappingType(symbol: ts.Symbol, type: ts.Type) { - const result = createType(ts.TypeFlags.StringMapping) as ts.StringMappingType; + function createStringMappingType(symbol: Symbol, type: Type) { + const result = createType(TypeFlags.StringMapping) as StringMappingType; result.symbol = symbol; 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; @@ -15430,67 +15660,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)) { @@ -15498,51 +15728,51 @@ 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) && +propName >= 0) { - if (accessNode && everyType(objectType, t => !(t as ts.TupleTypeReference).target.hasRestElement) && !(accessFlags & ts.AccessFlags.NoTupleBoundsCheck)) { + if (everyType(objectType, isTupleType) && isNumericLiteralName(propName) && +propName >= 0) { + if (accessNode && everyType(objectType, t => !(t as TupleTypeReference).target.hasRestElement) && !(accessFlags & AccessFlags.NoTupleBoundsCheck)) { const indexNode = getIndexNodeForAccessExpression(accessNode); if (isTupleType(objectType)) { - 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)); } } 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); - return accessFlags & ts.AccessFlags.IncludeUndefined ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type; + return accessFlags & AccessFlags.IncludeUndefined ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type; } - if (indexType.flags & ts.TypeFlags.Never) { + if (indexType.flags & TypeFlags.Never) { return neverType; } if (isJSLiteralType(objectType)) { @@ -15550,65 +15780,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)); } } } @@ -15621,14 +15851,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)) { @@ -15636,80 +15866,80 @@ 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) { - return !!(type.flags & (ts.TypeFlags.Any | ts.TypeFlags.String | ts.TypeFlags.Number | ts.TypeFlags.BigInt)); + function isPatternLiteralPlaceholderType(type: Type) { + return !!(type.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)); } - function isPatternLiteralType(type: ts.Type) { - return !!(type.flags & ts.TypeFlags.TemplateLiteral) && ts.every((type as ts.TemplateLiteralType).types, isPatternLiteralPlaceholderType); + function isPatternLiteralType(type: Type) { + return !!(type.flags & TypeFlags.TemplateLiteral) && every((type as TemplateLiteralType).types, isPatternLiteralPlaceholderType); } - 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).substitute) | getGenericObjectFlags((type as ts.SubstitutionType).baseType); + if (type.flags & TypeFlags.Substitution) { + if (!((type as SubstitutionType).objectFlags & ObjectFlags.IsGenericTypeComputed)) { + (type as SubstitutionType).objectFlags |= ObjectFlags.IsGenericTypeComputed | + getGenericObjectFlags((type as SubstitutionType).substitute) | getGenericObjectFlags((type as SubstitutionType).baseType); } - 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.UnionOrIntersection) { - 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.UnionOrIntersection) { + 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); } } @@ -15717,7 +15947,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]!; @@ -15734,7 +15964,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] @@ -15749,8 +15979,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; } @@ -15767,25 +15997,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); } } @@ -15795,25 +16025,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), 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; } @@ -15822,32 +16052,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) { @@ -15860,11 +16090,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); } @@ -15880,32 +16110,32 @@ 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); - const resolved = getIndexedAccessType(objectType, indexType, ts.AccessFlags.None, node, potentialAlias, getTypeArgumentsForAliasSymbol(potentialAlias)); - links.resolvedType = resolved.flags & ts.TypeFlags.IndexedAccess && - (resolved as ts.IndexedAccessType).objectType === objectType && - (resolved as ts.IndexedAccessType).indexType === indexType ? + const resolved = getIndexedAccessType(objectType, indexType, AccessFlags.None, node, potentialAlias, getTypeArgumentsForAliasSymbol(potentialAlias)); + links.resolvedType = resolved.flags & TypeFlags.IndexedAccess && + (resolved as IndexedAccessType).objectType === objectType && + (resolved as IndexedAccessType).indexType === indexType ? getConditionalFlowTypeOfType(resolved, node) : resolved; } 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); @@ -15917,33 +16147,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)); } /** @@ -15951,13 +16181,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 @@ -15966,7 +16196,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; } @@ -15977,7 +16207,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 @@ -15996,9 +16226,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) { @@ -16011,11 +16241,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // if it was, it's trivial to say that extendsType = checkType, however such a pattern is used to // "reset" the type being build up during constraint calculation and avoid making an apparently "infinite" constraint // so in those cases we refain from performing inference and retain the uninfered type parameter - if (!checkTypeInstantiable || !ts.some(root.inferTypeParameters, t => t === extendsType)) { + if (!checkTypeInstantiable || !some(root.inferTypeParameters, t => t === extendsType)) { // 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 @@ -16031,16 +16261,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; @@ -16057,7 +16287,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)) { @@ -16068,7 +16298,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); @@ -16078,20 +16308,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; @@ -16107,49 +16337,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, @@ -16158,14 +16388,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)); @@ -16173,29 +16403,29 @@ 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) { @@ -16203,12 +16433,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedType = errorType; } 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 @@ -16217,7 +16447,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { ? getPropertyOfType(getTypeOfSymbol(mergedResolvedSymbol), current.escapedText, /*skipObjectFunctionPropertyAugment*/ false, /*includeTypeOnlyMembers*/ true) : getSymbol(getExportsOfSymbol(mergedResolvedSymbol), current.escapedText, meaning); 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; @@ -16231,9 +16461,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); @@ -16245,10 +16475,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 { @@ -16256,7 +16486,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 @@ -16265,10 +16495,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; @@ -16277,54 +16507,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; @@ -16332,8 +16562,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; } } @@ -16343,32 +16573,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; } @@ -16379,22 +16609,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)) { @@ -16409,11 +16639,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; @@ -16426,25 +16656,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; @@ -16452,70 +16682,70 @@ 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 = createType(flags) as ts.LiteralType; + function createLiteralType(flags: TypeFlags, value: string | number | PseudoBigInt, symbol?: Symbol, regularType?: LiteralType) { + const type = createType(flags) as LiteralType; type.symbol = symbol!; 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 qualifier = typeof value === "string" ? "@" : "#"; const key = enumId + qualifier + 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); @@ -16525,16 +16755,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedType; } - function createUniqueESSymbolType(symbol: ts.Symbol) { - const type = createType(ts.TypeFlags.UniqueESSymbol) as ts.UniqueESSymbolType; + function createUniqueESSymbolType(symbol: Symbol) { + const type = createType(TypeFlags.UniqueESSymbol) as UniqueESSymbolType; type.symbol = symbol; - type.escapedName = `__@${type.symbol.escapedName}@${getSymbolId(type.symbol)}` as ts.__String; + 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)); @@ -16543,35 +16773,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); @@ -16579,134 +16809,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: @@ -16714,9 +16944,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]; @@ -16734,29 +16964,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++) { @@ -16765,32 +16995,32 @@ 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 { kind: ts.TypeMapKind.Simple, source, target }; + function makeUnaryTypeMapper(source: Type, target: Type): TypeMapper { + return { kind: TypeMapKind.Simple, source, target }; } - function makeArrayTypeMapper(sources: readonly ts.TypeParameter[], targets: readonly ts.Type[] | undefined): ts.TypeMapper { - return { kind: ts.TypeMapKind.Array, sources, targets }; + function makeArrayTypeMapper(sources: readonly TypeParameter[], targets: readonly Type[] | undefined): TypeMapper { + return { kind: TypeMapKind.Array, sources, targets }; } - function makeFunctionTypeMapper(func: (t: ts.Type) => ts.Type): ts.TypeMapper { - return { kind: ts.TypeMapKind.Function, func }; + function makeFunctionTypeMapper(func: (t: Type) => Type): TypeMapper { + return { kind: TypeMapKind.Function, func }; } - function makeCompositeTypeMapper(kind: ts.TypeMapKind.Composite | ts.TypeMapKind.Merged, mapper1: ts.TypeMapper, mapper2: ts.TypeMapper): ts.TypeMapper { + function makeCompositeTypeMapper(kind: TypeMapKind.Composite | TypeMapKind.Merged, mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper { return { kind, mapper1, mapper2 }; } - function createTypeEraser(sources: readonly ts.TypeParameter[]): ts.TypeMapper { + function createTypeEraser(sources: readonly TypeParameter[]): TypeMapper { return createTypeMapper(sources, /*targets*/ undefined); } @@ -16798,51 +17028,51 @@ 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 { - return makeFunctionTypeMapper(t => ts.findIndex(context.inferences, info => info.typeParameter === t) >= index ? unknownType : t); + function createBackreferenceMapper(context: InferenceContext, index: number): TypeMapper { + return makeFunctionTypeMapper(t => findIndex(context.inferences, info => info.typeParameter === t) >= index ? unknownType : t); } - 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 === unknownType ? tp : tp.restrictiveInstantiation || ( tp.restrictiveInstantiation = createTypeParameter(tp.symbol), - (tp.restrictiveInstantiation as ts.TypeParameter).constraint = unknownType, + (tp.restrictiveInstantiation as TypeParameter).constraint = unknownType, 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; @@ -16857,20 +17087,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. @@ -16879,7 +17109,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; @@ -16893,13 +17123,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 @@ -16908,13 +17138,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; } @@ -16923,19 +17153,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); } @@ -16944,57 +17174,57 @@ 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 invening 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, we consider the type parameter possibly referenced. 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: + 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: 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. @@ -17010,10 +17240,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)); } @@ -17038,64 +17268,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; @@ -17104,13 +17334,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) { @@ -17120,7 +17350,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); @@ -17130,13 +17360,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; } @@ -17144,8 +17374,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++; @@ -17156,64 +17386,64 @@ 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 maybeVariable = instantiateType((type as ts.SubstitutionType).baseType, mapper); - if (maybeVariable.flags & ts.TypeFlags.TypeVariable) { - return getSubstitutionType(maybeVariable as ts.TypeVariable, instantiateType((type as ts.SubstitutionType).substitute, mapper)); + if (flags & TypeFlags.Substitution) { + const maybeVariable = instantiateType((type as SubstitutionType).baseType, mapper); + if (maybeVariable.flags & TypeFlags.TypeVariable) { + return getSubstitutionType(maybeVariable as TypeVariable, instantiateType((type as SubstitutionType).substitute, mapper)); } else { - const sub = instantiateType((type as ts.SubstitutionType).substitute, mapper); - if (sub.flags & ts.TypeFlags.AnyOrUnknown || isTypeAssignableTo(getRestrictiveInstantiation(maybeVariable), getRestrictiveInstantiation(sub))) { + const sub = instantiateType((type as SubstitutionType).substitute, mapper); + if (sub.flags & TypeFlags.AnyOrUnknown || isTypeAssignableTo(getRestrictiveInstantiation(maybeVariable), getRestrictiveInstantiation(sub))) { return maybeVariable; } return sub; @@ -17222,19 +17452,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { 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; @@ -17242,18 +17472,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) { @@ -17269,44 +17499,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); } } @@ -17314,63 +17544,63 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isContextSensitiveFunctionLikeDeclaration(node: ts.FunctionLikeDeclaration): boolean { - return (!ts.isFunctionDeclaration(node) || ts.isInJSFile(node) && !!getTypeForDeclarationFromJSDocComment(node)) && - (ts.hasContextSensitiveParameters(node) || hasContextSensitiveReturnExpression(node)); + function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean { + return (!isFunctionDeclaration(node) || isInJSFile(node) && !!getTypeForDeclarationFromJSDocComment(node)) && + (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.isInJSFile(func) && ts.isFunctionDeclaration(func) || ts.isFunctionExpressionOrArrowFunction(func) || ts.isObjectLiteralMethod(func)) && + function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration { + return (isInJSFile(func) && isFunctionDeclaration(func) || 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); } @@ -17382,12 +17612,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)); } @@ -17401,15 +17631,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); } @@ -17417,19 +17647,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)) { @@ -17438,18 +17668,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) @@ -17457,50 +17687,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; } @@ -17509,55 +17739,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; @@ -17566,20 +17796,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); @@ -17589,7 +17819,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` @@ -17597,18 +17827,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); @@ -17617,17 +17847,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); @@ -17644,19 +17874,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) )); } @@ -17668,16 +17898,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]; @@ -17692,48 +17922,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) { @@ -17747,7 +17977,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) ); @@ -17776,7 +18006,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) ); @@ -17790,39 +18020,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) return false; + if (target.flags & TypeFlags.Primitive) return false; if (isTupleLikeType(source)) { return elaborateElementwise(generateLimitedTupleElements(node, target), source, target, relation, containingMessageChain, errorOutputContainer); } @@ -17843,39 +18073,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) return false; + if (target.flags & TypeFlags.Primitive) return false; return elaborateElementwise(generateObjectLiteralElements(node), source, target, relation, containingMessageChain, errorOutputContainer); } @@ -17883,23 +18113,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)); @@ -17908,28 +18138,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) { @@ -17944,10 +18174,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) { @@ -17958,9 +18188,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; } @@ -17984,21 +18214,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const sourceSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(sourceType)); const targetSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(targetType)); const callbacks = sourceSig && targetSig && !getTypePredicateOfSignature(sourceSig) && !getTypePredicateOfSignature(targetSig) && - (getFalsyFlags(sourceType) & ts.TypeFlags.Nullable) === (getFalsyFlags(targetType) & ts.TypeFlags.Nullable); + (getFalsyFlags(sourceType) & TypeFlags.Nullable) === (getFalsyFlags(targetType) & TypeFlags.Nullable); let related = callbacks ? compareSignaturesRelated(targetSig, sourceSig, (checkMode & SignatureCheckMode.StrictArity) | (strictVariance ? SignatureCheckMode.StrictCallback : SignatureCheckMode.BivariantCallback), reportErrors, errorReporter, incompatibleErrorReporter, compareTypes, reportUnreliableMarkers) : !(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; } @@ -18024,11 +18254,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 { @@ -18048,39 +18278,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); @@ -18097,7 +18327,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 && @@ -18105,142 +18335,142 @@ 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 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(sourceSymbol: ts.Symbol, targetSymbol: ts.Symbol, errorReporter?: ErrorReporter) { + function isEnumTypeRelatedTo(sourceSymbol: Symbol, targetSymbol: Symbol, errorReporter?: ErrorReporter) { if (sourceSymbol === targetSymbol) { return true; } 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); } - if (sourceSymbol.escapedName !== targetSymbol.escapedName || !(sourceSymbol.flags & ts.SymbolFlags.RegularEnum) || !(targetSymbol.flags & ts.SymbolFlags.RegularEnum)) { - enumRelation.set(id, ts.RelationComparisonResult.Failed | ts.RelationComparisonResult.Reported); + if (sourceSymbol.escapedName !== targetSymbol.escapedName || !(sourceSymbol.flags & SymbolFlags.RegularEnum) || !(targetSymbol.flags & SymbolFlags.RegularEnum)) { + enumRelation.set(id, RelationComparisonResult.Failed | RelationComparisonResult.Reported); return false; } 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 && 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 (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 && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true; + 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(getParentOfSymbol(source.symbol)!, getParentOfSymbol(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) 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) 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; } 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) { - let 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)) : - type.flags & ts.TypeFlags.UnionOrIntersection ? getReducedType(type) : - type.flags & ts.TypeFlags.Substitution ? writing ? (type as ts.SubstitutionType).baseType : (type as ts.SubstitutionType).substitute : - type.flags & ts.TypeFlags.Simplifiable ? getSimplifiedType(type, writing) : + let t = isFreshLiteralType(type) ? (type as FreshableType).regularType : + getObjectFlags(type) & ObjectFlags.Reference && (type as TypeReference).node ? createTypeReference((type as TypeReference).target, getTypeArguments(type as TypeReference)) : + type.flags & TypeFlags.UnionOrIntersection ? getReducedType(type) : + type.flags & TypeFlags.Substitution ? writing ? (type as SubstitutionType).baseType : (type as SubstitutionType).substitute : + type.flags & TypeFlags.Simplifiable ? getSimplifiedType(type, writing) : type; t = getSingleBaseForNonAugmentingSubtype(t) || t; if (t === type) break; @@ -18261,39 +18491,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); } @@ -18302,27 +18532,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); @@ -18331,12 +18561,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; @@ -18352,11 +18582,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]); @@ -18378,11 +18608,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})`; @@ -18393,7 +18623,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 @@ -18406,51 +18636,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 ); } @@ -18470,15 +18700,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]; } @@ -18487,7 +18717,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; @@ -18495,16 +18725,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 !== markerSuperType && target !== markerSubType) { + if (target.flags & TypeFlags.TypeParameter && target !== markerSuperType && target !== markerSubType) { 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), @@ -18513,7 +18743,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 ); @@ -18522,35 +18752,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); @@ -18558,7 +18788,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { (globalNumberType === source && numberType === target) || (globalBooleanType === source && booleanType === target) || (getGlobalESSymbolType(/*reportErrors*/ false) === 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); } } @@ -18568,7 +18798,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. @@ -18579,7 +18809,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; } @@ -18587,7 +18817,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; } @@ -18597,7 +18827,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); } @@ -18607,17 +18837,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, @@ -18627,11 +18857,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); } @@ -18641,63 +18871,63 @@ 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 && !(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); let result = skipCaching ? unionOrIntersectionRelatedTo(source, target, reportErrors, intersectionState) : recursiveTypeRelatedTo(source, target, reportErrors, intersectionState, recursionFlags); @@ -18717,8 +18947,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 && (isPerformingExcessPropertyChecks || isPerformingCommonPropertyChecks) || - 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 && (isPerformingExcessPropertyChecks || isPerformingCommonPropertyChecks) || + 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 &= recursiveTypeRelatedTo(source, target, reportErrors, IntersectionState.PropertyCheck, recursionFlags); inPropertyCheck = false; @@ -18731,10 +18961,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; @@ -18743,25 +18973,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; } @@ -18777,16 +19007,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { reportRelationError(headMessage, source, target); } - 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; } @@ -18794,7 +19024,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, @@ -18806,30 +19036,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)) { @@ -18841,11 +19071,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; @@ -18854,33 +19084,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)); } } @@ -18889,7 +19119,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; } @@ -18898,35 +19128,35 @@ 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(getRegularTypeOfObjectLiteral(source), target as ts.IntersectionType, reportErrors, IntersectionState.Target); + if (target.flags & TypeFlags.Intersection) { + return typeRelatedToEachType(getRegularTypeOfObjectLiteral(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, getBaseConstraintOrType); - if (constraints !== (source as ts.IntersectionType).types) { + if (relation === comparableRelation && target.flags & TypeFlags.Primitive) { + const constraints = sameMap((source as IntersectionType).types, getBaseConstraintOrType); + if (constraints !== (source as IntersectionType).types) { source = getIntersectionType(constraints); - if (!(source.flags & ts.TypeFlags.Intersection)) { + if (!(source.flags & TypeFlags.Intersection)) { return isRelatedTo(source, target, RecursionFlags.Source, /*reportErrors*/ false); } } @@ -18935,29 +19165,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) { @@ -18978,26 +19208,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++) { @@ -19006,34 +19236,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; @@ -19041,43 +19271,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, @@ -19097,7 +19327,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } if (!related) { - return ts.Ternary.False; + return Ternary.False; } result &= related; } @@ -19110,30 +19340,30 @@ 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 keyIntersectionState = intersectionState | (inPropertyCheck ? IntersectionState.InPropertyCheck : 0); const id = getRelationKey(source, target, keyIntersectionState, 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, makeFunctionTypeMapper(reportUnmeasurableMarkers)); } - if (saved & ts.RelationComparisonResult.ReportsUnreliable) { + if (saved & RelationComparisonResult.ReportsUnreliable) { instantiateType(source, makeFunctionTypeMapper(reportUnreliableMarkers)); } } - return entry & ts.RelationComparisonResult.Succeeded ? ts.Ternary.True : ts.Ternary.False; + return entry & RelationComparisonResult.Succeeded ? Ternary.True : Ternary.False; } } if (!maybeKeys) { @@ -19149,12 +19379,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; @@ -19172,18 +19402,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, @@ -19191,12 +19421,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) { @@ -19210,12 +19440,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; @@ -19224,47 +19454,47 @@ 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 { if (intersectionState & IntersectionState.PropertyCheck) { return propertiesRelatedTo(source, target, reportErrors, /*excludedProperties*/ undefined, IntersectionState.None); } - let result: ts.Ternary; - let originalErrorInfo: ts.DiagnosticMessageChain | undefined; + let result: Ternary; + let originalErrorInfo: DiagnosticMessageChain | undefined; let varianceCheckFailed = false; const saveErrorInfo = captureErrorCalculationState(); 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; } } @@ -19272,18 +19502,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - if (sourceFlags & ts.TypeFlags.Substitution) { - return isRelatedTo((source as ts.SubstitutionType).substitute, (target as ts.SubstitutionType).substitute, RecursionFlags.Both, /*reportErrors*/ false); + if (sourceFlags & TypeFlags.Substitution) { + return isRelatedTo((source as SubstitutionType).substitute, (target as SubstitutionType).substitute, RecursionFlags.Both, /*reportErrors*/ false); } - 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; } - if (source.flags & ts.TypeFlags.Intersection || source.flags & ts.TypeFlags.TypeParameter && target.flags & ts.TypeFlags.Union) { + if (source.flags & TypeFlags.Intersection || source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.Union) { // The combined constraint of an intersection type is the intersection of the constraints of // the constituents. When an intersection type contains instantiable types with union type // constraints, there are situations where we need to examine the combined constraint. One is @@ -19297,7 +19527,7 @@ 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)` - const constraint = getEffectiveConstraintOfIntersection(source.flags & ts.TypeFlags.Intersection ? (source as ts.IntersectionType).types: [source], !!(target.flags & ts.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 if (result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState)) { @@ -19312,21 +19542,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) { @@ -19341,38 +19571,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 && constraint.flags & ts.TypeFlags.TypeParameter) { + while (constraint && constraint.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; } } @@ -19392,8 +19622,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)) { @@ -19408,10 +19638,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))) ); @@ -19421,18 +19651,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) { resetErrorInfo(saveErrorInfo); @@ -19445,12 +19675,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) { @@ -19479,9 +19709,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`. @@ -19496,16 +19726,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; } } @@ -19536,14 +19766,14 @@ 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)) { resetErrorInfo(saveErrorInfo); - 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. @@ -19552,8 +19782,8 @@ 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)) { - result &= skipFalse ? ts.Ternary.True : isRelatedTo(source, getFalseTypeFromConditionalType(c), RecursionFlags.Target, /*reportErrors*/ false); + if (result = skipTrue ? Ternary.True : isRelatedTo(source, getTrueTypeFromConditionalType(c), RecursionFlags.Target, /*reportErrors*/ false)) { + result &= skipFalse ? Ternary.True : isRelatedTo(source, getFalseTypeFromConditionalType(c), RecursionFlags.Target, /*reportErrors*/ false); if (result) { resetErrorInfo(saveErrorInfo); return result; @@ -19561,27 +19791,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - 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, makeFunctionTypeMapper(reportUnreliableMarkers)); } - if (isTypeMatchedByTemplateLiteralType(source, target as ts.TemplateLiteralType)) { - return ts.Ternary.True; + if (isTypeMatchedByTemplateLiteralType(source, target as TemplateLiteralType)) { + 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 (!getConstraintOfType(source as ts.TypeVariable) || (sourceFlags & ts.TypeFlags.TypeParameter && constraint.flags & ts.TypeFlags.Any)) { + if (!(sourceFlags & TypeFlags.IndexedAccess && targetFlags & TypeFlags.IndexedAccess)) { + const constraint = getConstraintOfType(source as TypeVariable) || unknownType; + if (!getConstraintOfType(source as TypeVariable) || (sourceFlags & TypeFlags.TypeParameter && constraint.flags & TypeFlags.Any)) { // A type variable with no constraint is not related to the non-primitive object type. - if (result = isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~ts.TypeFlags.NonPrimitive), RecursionFlags.Both)) { + if (result = isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~TypeFlags.NonPrimitive), RecursionFlags.Both)) { resetErrorInfo(saveErrorInfo); return result; } @@ -19592,16 +19822,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { 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)) { resetErrorInfo(saveErrorInfo); 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)) { resetErrorInfo(saveErrorInfo); return result; } @@ -19609,14 +19839,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - else if (sourceFlags & ts.TypeFlags.Index) { + else if (sourceFlags & TypeFlags.Index) { if (result = isRelatedTo(keyofConstraintType, target, RecursionFlags.Source, reportErrors)) { resetErrorInfo(saveErrorInfo); 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))) { resetErrorInfo(saveErrorInfo); @@ -19624,9 +19854,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - else if (sourceFlags & ts.TypeFlags.StringMapping) { - if (targetFlags & ts.TypeFlags.StringMapping && (source as ts.StringMappingType).symbol === (target as ts.StringMappingType).symbol) { - if (result = isRelatedTo((source as ts.StringMappingType).type, (target as ts.StringMappingType).type, RecursionFlags.Both, reportErrors)) { + else if (sourceFlags & TypeFlags.StringMapping) { + if (targetFlags & TypeFlags.StringMapping && (source as StringMappingType).symbol === (target as StringMappingType).symbol) { + if (result = isRelatedTo((source as StringMappingType).type, (target as StringMappingType).type, RecursionFlags.Both, reportErrors)) { resetErrorInfo(saveErrorInfo); return result; } @@ -19639,31 +19869,31 @@ 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)) { resetErrorInfo(saveErrorInfo); - 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) { resetErrorInfo(saveErrorInfo); @@ -19674,7 +19904,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)) { resetErrorInfo(saveErrorInfo); @@ -19685,7 +19915,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)) { resetErrorInfo(saveErrorInfo); @@ -19696,7 +19926,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)) { @@ -19705,34 +19935,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; } @@ -19744,27 +19974,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); } @@ -19781,28 +20011,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 @@ -19820,7 +20050,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 @@ -19829,8 +20059,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 @@ -19841,14 +20071,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function reportUnmeasurableMarkers(p: ts.TypeParameter) { + function reportUnmeasurableMarkers(p: TypeParameter) { if (outofbandVarianceMarkerHandler && (p === markerSuperType || p === markerSubType || p === markerOtherType)) { outofbandVarianceMarkerHandler(/*onlyUnreliable*/ false); } return p; } - function reportUnreliableMarkers(p: ts.TypeParameter) { + function reportUnreliableMarkers(p: TypeParameter) { if (outofbandVarianceMarkerHandler && (p === markerSuperType || p === markerSubType || p === markerOtherType)) { outofbandVarianceMarkerHandler(/*onlyUnreliable*/ true); } @@ -19858,11 +20088,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), makeFunctionTypeMapper(getCombinedMappedTypeOptionality(source) < 0 ? reportUnmeasurableMarkers : reportUnreliableMarkers)); if (result = isRelatedTo(targetConstraint, sourceConstraint, RecursionFlags.Both, reportErrors)) { @@ -19872,10 +20102,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. @@ -19888,7 +20118,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 @@ -19900,27 +20130,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) { @@ -19937,23 +20167,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 @@ -19970,9 +20200,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) { @@ -19986,46 +20216,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}, @@ -20038,18 +20268,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.Optional)) { + if (!skipOptional && sourceProp.flags & SymbolFlags.Optional && !(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.. @@ -20058,45 +20288,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); - 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)); + 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++; @@ -20104,10 +20334,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++; @@ -20116,105 +20346,105 @@ 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 startCount = Math.min(isTupleType(source) ? getStartElementCount(source.target, ts.ElementFlags.NonRest) : 0, getStartElementCount(target.target, ts.ElementFlags.NonRest)); - const endCount = Math.min(isTupleType(source) ? getEndElementCount(source.target, ts.ElementFlags.NonRest) : 0, targetRestFlag ? getEndElementCount(target.target, ts.ElementFlags.NonRest) : 0); + const startCount = Math.min(isTupleType(source) ? getStartElementCount(source.target, ElementFlags.NonRest) : 0, getStartElementCount(target.target, ElementFlags.NonRest)); + const endCount = Math.min(isTupleType(source) ? getEndElementCount(source.target, ElementFlags.NonRest) : 0, targetRestFlag ? getEndElementCount(target.target, ElementFlags.NonRest) : 0); let canExcludeDiscriminants = !!excludedProperties; for (let i = 0; i < targetArity; i++) { const sourceIndex = i < targetArity - endCount ? i : i + sourceArity - targetArity; - const sourceFlags = isTupleType(source) && (i < startCount || i >= targetArity - endCount) ? source.target.elementFlags[sourceIndex] : ts.ElementFlags.Rest; + const sourceFlags = isTupleType(source) && (i < startCount || i >= targetArity - endCount) ? source.target.elementFlags[sourceIndex] : ElementFlags.Rest; const targetFlags = target.target.elementFlags[i]; - 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, i); + reportError(Diagnostics.Source_provides_no_match_for_variadic_element_at_position_0_in_target, i); } - 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, sourceIndex, i); + reportError(Diagnostics.Variadic_element_at_position_0_in_source_does_not_match_element_at_position_1_in_target, sourceIndex, i); } - 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, i); + reportError(Diagnostics.Source_provides_no_match_for_required_element_at_position_0_in_target, i); } - 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(("" + i) as ts.__String)) { + if (canExcludeDiscriminants && excludedProperties?.has(("" + i) as __String)) { continue; } } const sourceType = !isTupleType(source) ? sourceTypeArguments[0] : - i < startCount || i >= targetArity - endCount ? removeMissingType(sourceTypeArguments[sourceIndex], !!(sourceFlags & targetFlags & ts.ElementFlags.Optional)) : + i < startCount || i >= targetArity - endCount ? removeMissingType(sourceTypeArguments[sourceIndex], !!(sourceFlags & targetFlags & ElementFlags.Optional)) : getElementTypeOfSliceOfTupleType(source, startCount, endCount) || neverType; const targetType = targetTypeArguments[i]; - 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 (i < startCount || i >= targetArity - endCount || sourceArity - startCount - endCount === 1) { - reportIncompatibleError(ts.Diagnostics.Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target, sourceIndex, i); + reportIncompatibleError(Diagnostics.Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target, sourceIndex, i); } else { - reportIncompatibleError(ts.Diagnostics.Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target, startCount, sourceArity - endCount - 1, i); + reportIncompatibleError(Diagnostics.Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target, startCount, sourceArity - endCount - 1, i); } } - 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); @@ -20223,17 +20453,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; } } } @@ -20244,12 +20474,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; } @@ -20258,70 +20488,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 @@ -20329,7 +20559,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; } @@ -20341,15 +20571,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; } } @@ -20368,23 +20598,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; @@ -20392,65 +20622,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, makeFunctionTypeMapper(reportUnreliableMarkers)); } - 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; } @@ -20459,7 +20689,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; } @@ -20467,39 +20697,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); @@ -20509,94 +20739,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); + return isUnitType(type) || !!(type.flags & TypeFlags.TemplateLiteral); } - 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) || @@ -20604,15 +20834,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; @@ -20646,19 +20876,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; @@ -20667,14 +20897,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); } @@ -20683,17 +20913,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; @@ -20704,90 +20934,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(); + tracing?.pop(); } 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) { @@ -20802,7 +21032,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; @@ -20815,7 +21045,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; @@ -20823,15 +21053,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) { @@ -20844,12 +21074,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); @@ -20857,7 +21087,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; @@ -20865,15 +21095,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; } @@ -20889,7 +21119,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; @@ -20918,16 +21148,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; @@ -20937,56 +21167,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); @@ -21011,17 +21241,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. @@ -21032,12 +21262,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) { @@ -21045,7 +21275,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; } @@ -21057,7 +21287,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; } @@ -21071,15 +21301,15 @@ 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) { const baseType = getBaseTypeOfLiteralType(t); if (!commonBaseType) { @@ -21095,70 +21325,70 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // 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. - function getSupertypeOrUnion(types: ts.Type[]): ts.Type { + function getSupertypeOrUnion(types: Type[]): Type { if (types.length === 1) { return types[0]; } return literalTypesWithSameBaseType(types) ? getUnionType(types) : - ts.reduceLeft(types, (s, t) => isTypeSubtypeOf(s, t) ? t : s)!; + reduceLeft(types, (s, t) => isTypeSubtypeOf(s, t) ? t : s)!; } - function getCommonSupertype(types: ts.Type[]): ts.Type { + function getCommonSupertype(types: Type[]): Type { if (!strictNullChecks) { return getSupertypeOrUnion(types); } - const primaryTypes = ts.filter(types, t => !(t.flags & ts.TypeFlags.Nullable)); + const primaryTypes = filter(types, t => !(t.flags & TypeFlags.Nullable)); return primaryTypes.length ? - getNullableType(getSupertypeOrUnion(primaryTypes), getFalsyFlagsOfTypes(types) & ts.TypeFlags.Nullable) : - getUnionType(types, ts.UnionReduction.Subtype); + getNullableType(getSupertypeOrUnion(primaryTypes), getFalsyFlagsOfTypes(types) & TypeFlags.Nullable) : + getUnionType(types, UnionReduction.Subtype); } // 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; } } @@ -21169,99 +21399,99 @@ 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 { - return type.flags & ts.TypeFlags.Intersection ? ts.some((type as ts.IntersectionType).types, isUnitType) : - !!(type.flags & ts.TypeFlags.Unit); + function isUnitLikeType(type: Type): boolean { + return type.flags & TypeFlags.Intersection ? some((type as IntersectionType).types, isUnitType) : + !!(type.flags & TypeFlags.Unit); } - 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 ? mapType(type as ts.UnionType, getBaseTypeOfLiteralType) : + 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 ? mapType(type as UnionType, getBaseTypeOfLiteralType) : type; } - 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 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) : @@ -21271,7 +21501,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); @@ -21284,52 +21514,52 @@ 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 getFalsyFlagsOfTypes(types: ts.Type[]): ts.TypeFlags { - let result: ts.TypeFlags = 0; + function getFalsyFlagsOfTypes(types: Type[]): TypeFlags { + let result: TypeFlags = 0; for (const t of types) { result |= getFalsyFlags(t); } @@ -21339,35 +21569,35 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Returns the String, Number, Boolean, StringLiteral, NumberLiteral, BooleanLiteral, Void, Undefined, or Null // flags for the string, number, boolean, "", 0, false, void, undefined, or null types respectively. Returns // no flags for all other types (including non-falsy literal types). - function getFalsyFlags(type: ts.Type): ts.TypeFlags { - return type.flags & ts.TypeFlags.Union ? getFalsyFlagsOfTypes((type as ts.UnionType).types) : - type.flags & ts.TypeFlags.StringLiteral ? (type as ts.StringLiteralType).value === "" ? ts.TypeFlags.StringLiteral : 0 : - type.flags & ts.TypeFlags.NumberLiteral ? (type as ts.NumberLiteralType).value === 0 ? ts.TypeFlags.NumberLiteral : 0 : - type.flags & ts.TypeFlags.BigIntLiteral ? isZeroBigInt(type as ts.BigIntLiteralType) ? ts.TypeFlags.BigIntLiteral : 0 : - type.flags & ts.TypeFlags.BooleanLiteral ? (type === falseType || type === regularFalseType) ? ts.TypeFlags.BooleanLiteral : 0 : - type.flags & ts.TypeFlags.PossiblyFalsy; - } - - function removeDefinitelyFalsyTypes(type: ts.Type): ts.Type { - return getFalsyFlags(type) & ts.TypeFlags.DefinitelyFalsy ? - filterType(type, t => !(getFalsyFlags(t) & ts.TypeFlags.DefinitelyFalsy)) : + function getFalsyFlags(type: Type): TypeFlags { + return type.flags & TypeFlags.Union ? getFalsyFlagsOfTypes((type as UnionType).types) : + type.flags & TypeFlags.StringLiteral ? (type as StringLiteralType).value === "" ? TypeFlags.StringLiteral : 0 : + type.flags & TypeFlags.NumberLiteral ? (type as NumberLiteralType).value === 0 ? TypeFlags.NumberLiteral : 0 : + type.flags & TypeFlags.BigIntLiteral ? isZeroBigInt(type as BigIntLiteralType) ? TypeFlags.BigIntLiteral : 0 : + type.flags & TypeFlags.BooleanLiteral ? (type === falseType || type === regularFalseType) ? TypeFlags.BooleanLiteral : 0 : + type.flags & TypeFlags.PossiblyFalsy; + } + + function removeDefinitelyFalsyTypes(type: Type): Type { + return getFalsyFlags(type) & TypeFlags.DefinitelyFalsy ? + filterType(type, t => !(getFalsyFlags(t) & TypeFlags.DefinitelyFalsy)) : type; } - 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; } @@ -21376,26 +21606,26 @@ 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); - return type.flags & ts.TypeFlags.Undefined ? type : getUnionType([type, isProperty ? missingType : undefinedType]); + function getOptionalType(type: Type, isProperty = false): Type { + Debug.assert(strictNullChecks); + return type.flags & TypeFlags.Undefined ? type : getUnionType([type, isProperty ? missingType : undefinedType]); } - function getGlobalNonNullableTypeInstantiation(type: ts.Type) { + function getGlobalNonNullableTypeInstantiation(type: Type) { // First reduce away any constituents that are assignable to 'undefined' or 'null'. This not only eliminates // 'undefined' and 'null', but also higher-order types such as a type parameter 'U extends undefined | null' // that isn't eliminated by a NonNullable instantiation. const reducedType = getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull); if (!deferredGlobalNonNullableTypeAlias) { - deferredGlobalNonNullableTypeAlias = getGlobalSymbol("NonNullable" as ts.__String, ts.SymbolFlags.TypeAlias, /*diagnostic*/ undefined) || unknownSymbol; + deferredGlobalNonNullableTypeAlias = getGlobalSymbol("NonNullable" as __String, SymbolFlags.TypeAlias, /*diagnostic*/ undefined) || unknownSymbol; } // If the NonNullable type is available, return an instantiation. Otherwise just return the reduced type. return deferredGlobalNonNullableTypeAlias !== unknownSymbol ? @@ -21403,37 +21633,37 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { reducedType; } - function getNonNullableType(type: ts.Type): ts.Type { + function getNonNullableType(type: Type): Type { return strictNullChecks ? getGlobalNonNullableTypeInstantiation(type) : 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); } @@ -21457,28 +21687,28 @@ 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 { - return type.flags & ts.TypeFlags.Intersection - ? ts.every((type as ts.IntersectionType).types, isObjectTypeWithInferableIndex) + function isObjectTypeWithInferableIndex(type: Type): boolean { + 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) - ) || !!(ts.getObjectFlags(type) & ts.ObjectFlags.ReverseMapped && isObjectTypeWithInferableIndex((type as ts.ReverseMappedType).source)); + ) || !!(getObjectFlags(type) & 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; @@ -21493,8 +21723,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); @@ -21508,31 +21738,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!); @@ -21548,23 +21778,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; @@ -21575,19 +21805,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)); } @@ -21598,41 +21828,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; @@ -21653,15 +21883,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; } @@ -21678,9 +21908,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; } @@ -21690,79 +21920,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); @@ -21771,7 +22001,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); @@ -21793,7 +22023,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) { @@ -21804,16 +22034,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, @@ -21824,7 +22054,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return context; } - function mapToInferredType(context: ts.InferenceContext, t: ts.Type, fix: boolean): ts.Type { + function mapToInferredType(context: InferenceContext, t: Type, fix: boolean): Type { const inferences = context.inferences; for (let i = 0; i < inferences.length; i++) { const inference = inferences[i]; @@ -21842,7 +22072,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return t; } - function clearCachedInferences(inferences: ts.InferenceInfo[]) { + function clearCachedInferences(inferences: InferenceInfo[]) { for (const inference of inferences) { if (!inference.isFixed) { inference.inferredType = undefined; @@ -21850,7 +22080,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 }); } @@ -21867,12 +22097,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); } @@ -21881,7 +22111,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, @@ -21894,7 +22124,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(), @@ -21907,60 +22137,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; @@ -21968,8 +22198,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); } /** @@ -21978,7 +22208,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; } @@ -21997,13 +22227,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))) { @@ -22015,22 +22245,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); @@ -22038,31 +22268,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; } } @@ -22071,17 +22301,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) : @@ -22089,21 +22319,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]; @@ -22116,12 +22346,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } function isValidBigIntString(s: string): boolean { - 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(); - if (result === ts.SyntaxKind.MinusToken) { + if (result === SyntaxKind.MinusToken) { result = scanner.scan(); } const flags = scanner.getTokenFlags(); @@ -22130,41 +22360,41 @@ 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); + return success && result === SyntaxKind.BigIntLiteral && scanner.getTextPos() === (s.length + 1) && !(flags & TokenFlags.ContainsSeparator); } - 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 && value !== "" && isFinite(+value) || - target.flags & ts.TypeFlags.BigInt && value !== "" && isValidBigIntString(value) || - target.flags & (ts.TypeFlags.BooleanLiteral | ts.TypeFlags.Nullable) && value === (target as ts.IntrinsicType).intrinsicName); + if (source.flags & TypeFlags.StringLiteral) { + const value = (source as StringLiteralType).value; + return !!(target.flags & TypeFlags.Number && value !== "" && isFinite(+value) || + target.flags & TypeFlags.BigInt && value !== "" && isValidBigIntString(value) || + target.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && value === (target as IntrinsicType).intrinsicName); } - 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 @@ -22186,7 +22416,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]; @@ -22197,7 +22427,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++) { @@ -22242,18 +22472,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 = ts.InferencePriority.MaxValue; + let propagationType: Type; + let inferencePriority = 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; } @@ -22273,18 +22503,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { inferFromTypeArguments(source.aliasTypeArguments, target.aliasTypeArguments!, getAliasVariances(source.aliasSymbol)); 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. @@ -22299,12 +22529,12 @@ 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.some((target as ts.IntersectionType).types, + else if (target.flags & TypeFlags.Intersection && some((target as IntersectionType).types, t => !!getInferenceInfoForType(t) || (isGenericMappedType(t) && !!getInferenceInfoForType(getHomomorphicTypeVariable(t) || neverType)))) { // We reduce intersection types only when they contain naked type parameters. For example, when // inferring from 'string[] & { extra: any }' to 'string[] & T' we want to remove string[] and @@ -22312,9 +22542,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // string[] on the source side and infer string for T. // Likewise, we consider a homomorphic mapped type constrainted to the target type parameter as similar to a "naked type variable" // in such scenarios. - 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; } @@ -22322,10 +22552,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) { // If target is a type parameter, make an inference, unless the source type contains // the anyFunctionType (the wildcard type that's used to avoid contextually typing functions). // Because the anyFunctionType is internal, it should not be exposed to the user by adding @@ -22333,12 +22563,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // not contain anyFunctionType when we come back to this argument for its second round // of inference. Also, we exclude inferences for silentNeverType (which is used as a wildcard // when constructing types from type parameters that had no inference candidates). - if (source === nonInferrableAnyType || source === silentNeverType || (priority & ts.InferencePriority.ReturnType && (source === autoType || source === autoArrayType)) || isFromInferenceBlockedSource(source)) { + if (source === nonInferrableAnyType || source === silentNeverType || (priority & InferencePriority.ReturnType && (source === autoType || source === autoArrayType)) || isFromInferenceBlockedSource(source)) { return; } const inference = getInferenceInfoForType(target); if (inference) { - if (ts.getObjectFlags(source) & ts.ObjectFlags.NonInferrableType) { + if (getObjectFlags(source) & ObjectFlags.NonInferrableType) { return; } if (!inference.isFixed) { @@ -22353,17 +22583,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); } @@ -22376,75 +22606,75 @@ 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) { + else if (source.flags & TypeFlags.Index && target.flags & TypeFlags.Index) { contravariant = !contravariant; - inferFromTypes((source as ts.IndexType).type, (target as ts.IndexType).type); + inferFromTypes((source as IndexType).type, (target as IndexType).type); contravariant = !contravariant; } - 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); contravariant = !contravariant; - inferWithPriority(empty, (target as ts.IndexType).type, ts.InferencePriority.LiteralKeyof); + inferWithPriority(empty, (target as IndexType).type, InferencePriority.LiteralKeyof); contravariant = !contravariant; } - 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); + else if (source.flags & TypeFlags.Substitution) { + inferFromTypes((source as SubstitutionType).baseType, target); const oldPriority = priority; - priority |= ts.InferencePriority.SubstituteSource; - inferFromTypes((source as ts.SubstitutionType).substitute, target); // Make substitute inference at a lower priority + priority |= InferencePriority.SubstituteSource; + inferFromTypes((source as SubstitutionType).substitute, target); // Make substitute inference at a lower priority priority = oldPriority; } - 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 @@ -22457,36 +22687,36 @@ 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 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); @@ -22495,35 +22725,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 { @@ -22532,8 +22762,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function inferFromContravariantTypes(source: ts.Type, target: ts.Type) { - if (strictFunctionTypes || priority & ts.InferencePriority.AlwaysStrict) { + function inferFromContravariantTypes(source: Type, target: Type) { + if (strictFunctionTypes || priority & InferencePriority.AlwaysStrict) { contravariant = !contravariant; inferFromTypes(source, target); contravariant = !contravariant; @@ -22543,8 +22773,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; @@ -22554,10 +22784,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; } @@ -22566,11 +22796,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 @@ -22585,10 +22815,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); } } @@ -22599,7 +22829,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; } @@ -22608,7 +22838,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; @@ -22632,47 +22862,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 @@ -22683,31 +22913,31 @@ 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 savePriority = priority; - priority |= contravariant ? ts.InferencePriority.ContravariantConditional : 0; + priority |= contravariant ? InferencePriority.ContravariantConditional : 0; const targetTypes = [getTrueTypeFromConditionalType(target), getFalseTypeFromConditionalType(target)]; inferToMultipleTypes(source, targetTypes, target.flags); priority = savePriority; } } - 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 @@ -22716,18 +22946,18 @@ 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++) { inferFromTypes(matches ? matches[i] : neverType, types[i]); } } } - 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)) { @@ -22739,9 +22969,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; } } @@ -22762,22 +22992,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) { @@ -22786,14 +23016,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) { @@ -22813,57 +23043,57 @@ 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; const targetLen = targetSignatures.length; const len = sourceLen < targetLen ? sourceLen : targetLen; - const skipParameters = !!(ts.getObjectFlags(source) & ts.ObjectFlags.NonInferrableType); + const skipParameters = !!(getObjectFlags(source) & ObjectFlags.NonInferrableType); for (let i = 0; i < len; i++) { inferFromSignature(getBaseSignature(sourceSignatures[sourceLen - len + i]), getErasedSignature(targetSignatures[targetLen - len + i]), skipParameters); } } - function inferFromSignature(source: ts.Signature, target: ts.Signature, skipParameters: boolean) { + function inferFromSignature(source: Signature, target: Signature, skipParameters: boolean) { if (!skipParameters) { 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, inferFromContravariantTypes); 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)) { @@ -22885,45 +23115,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 @@ -22933,35 +23163,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; } @@ -22983,7 +23213,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) { @@ -22997,12 +23227,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)); } @@ -23011,29 +23241,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": @@ -23052,150 +23282,150 @@ 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; } } 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 (isEntityNameExpression(node.argumentExpression)) { + const symbol = resolveEntityName(node.argumentExpression, SymbolFlags.Value, /*ignoreErrors*/ true); if (!symbol || !isConstVariable(symbol)) return undefined; const declaration = symbol.valueDeclaration; @@ -23209,16 +23439,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - if (ts.hasOnlyExpressionInitializer(declaration)) { - const initializer = ts.getEffectiveInitializer(declaration); + if (hasOnlyExpressionInitializer(declaration)) { + const initializer = getEffectiveInitializer(declaration); return initializer && tryGetNameFromType(getTypeOfExpression(initializer)); } } 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; @@ -23227,8 +23457,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; @@ -23237,23 +23467,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) { @@ -23270,11 +23500,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)) { @@ -23301,22 +23531,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; @@ -23324,30 +23554,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)) { @@ -23355,14 +23585,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++; @@ -23370,11 +23600,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; } @@ -23385,13 +23615,13 @@ 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) { - if (assignedType.flags & ts.TypeFlags.Never) { + if (assignedType.flags & TypeFlags.Never) { return assignedType; } let reducedType = filterType(declaredType, t => typeMaybeAssignableTo(assignedType, t)); - if (assignedType.flags & ts.TypeFlags.BooleanLiteral && isFreshLiteralType(assignedType)) { + if (assignedType.flags & TypeFlags.BooleanLiteral && isFreshLiteralType(assignedType)) { reducedType = mapType(reducedType, getFreshTypeOfLiteralType); // Ensure that if the assignment is a fresh type, that we narrow to fresh types } // Our crude heuristic produces an invalid result in some cases: see GH#26130. @@ -23405,93 +23635,93 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return 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, ignoreObjects = false): TypeFacts { + function getTypeFacts(type: Type, ignoreObjects = false): TypeFacts { const flags = type.flags; - if (flags & ts.TypeFlags.String) { + if (flags & TypeFlags.String) { return strictNullChecks ? TypeFacts.StringStrictFacts : TypeFacts.StringFacts; } - if (flags & ts.TypeFlags.StringLiteral) { - const isEmpty = (type as ts.StringLiteralType).value === ""; + if (flags & TypeFlags.StringLiteral) { + const isEmpty = (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) { + if (flags & TypeFlags.Object) { if (ignoreObjects) { return TypeFacts.AndFactsMask; // This is the identity element for computing type facts of intersection. } - return ts.getObjectFlags(type) & ts.ObjectFlags.Anonymous && isEmptyObjectType(type as ts.ObjectType) ? + 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 | ts.TypeFlags.Undefined)) { + if (flags & (TypeFlags.Void | 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.Instantiable) { + if (flags & TypeFlags.Instantiable) { return !isPatternLiteralType(type) ? getTypeFacts(getBaseConstraintOfType(type) || unknownType, ignoreObjects) : strictNullChecks ? TypeFacts.NonEmptyStringStrictFacts : TypeFacts.NonEmptyStringFacts; } - if (flags & ts.TypeFlags.Union) { - return ts.reduceLeft((type as ts.UnionType).types, (facts, t) => facts | getTypeFacts(t, ignoreObjects), TypeFacts.None); + if (flags & TypeFlags.Union) { + return reduceLeft((type as UnionType).types, (facts, t) => facts | getTypeFacts(t, ignoreObjects), TypeFacts.None); } - if (flags & ts.TypeFlags.Intersection) { + if (flags & TypeFlags.Intersection) { // 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. - ignoreObjects ||= maybeTypeOfKind(type, ts.TypeFlags.Primitive); - return getIntersectionTypeFacts(type as ts.IntersectionType, ignoreObjects); + ignoreObjects ||= maybeTypeOfKind(type, TypeFlags.Primitive); + return getIntersectionTypeFacts(type as IntersectionType, ignoreObjects); } return TypeFacts.All; } - function getIntersectionTypeFacts(type: ts.IntersectionType, ignoreObjects: boolean): TypeFacts { + function getIntersectionTypeFacts(type: IntersectionType, ignoreObjects: boolean): TypeFacts { // 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; @@ -23504,105 +23734,105 @@ 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); } - 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. @@ -23610,66 +23840,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 = []; @@ -23682,117 +23912,117 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Get the types from all cases in a switch on `typeof`. An // `undefined` element denotes an explicit `default` clause. - function getSwitchClauseTypeOfWitnesses(switchStatement: ts.SwitchStatement, retainDefault: false): string[]; - function getSwitchClauseTypeOfWitnesses(switchStatement: ts.SwitchStatement, retainDefault: boolean): (string | undefined)[]; - function getSwitchClauseTypeOfWitnesses(switchStatement: ts.SwitchStatement, retainDefault: boolean): (string | undefined)[] { + function getSwitchClauseTypeOfWitnesses(switchStatement: SwitchStatement, retainDefault: false): string[]; + function getSwitchClauseTypeOfWitnesses(switchStatement: SwitchStatement, retainDefault: boolean): (string | undefined)[]; + function getSwitchClauseTypeOfWitnesses(switchStatement: SwitchStatement, retainDefault: boolean): (string | undefined)[] { const witnesses: (string | undefined)[] = []; for (const clause of switchStatement.caseBlock.clauses) { - if (clause.kind === ts.SyntaxKind.CaseClause) { - if (ts.isStringLiteralLike(clause.expression)) { + if (clause.kind === SyntaxKind.CaseClause) { + if (isStringLiteralLike(clause.expression)) { witnesses.push(clause.expression.text); continue; } - return ts.emptyArray; + return emptyArray; } if (retainDefault) witnesses.push(/*explicitDefaultStatement*/ 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) { @@ -23803,16 +24033,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); } @@ -23821,78 +24051,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; @@ -23903,37 +24133,37 @@ 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) { - if (symbol.flags & (ts.SymbolFlags.Function | ts.SymbolFlags.Method | ts.SymbolFlags.Class | ts.SymbolFlags.ValueModule)) { + function getExplicitTypeOfSymbol(symbol: Symbol, diagnostic?: Diagnostic) { + 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); } @@ -23943,7 +24173,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) { @@ -23952,7 +24182,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))); } } } @@ -23962,26 +24192,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)); - return getExplicitTypeOfSymbol(symbol.flags & ts.SymbolFlags.Alias ? resolveAlias(symbol) : symbol, diagnostic); - case ts.SyntaxKind.ThisKeyword: + case SyntaxKind.Identifier: + const symbol = getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(node as Identifier)); + return getExplicitTypeOfSymbol(symbol.flags & SymbolFlags.Alias ? resolveAlias(symbol) : symbol, diagnostic); + 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); @@ -23990,13 +24220,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) { @@ -24004,12 +24234,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 @@ -24019,56 +24249,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]; @@ -24076,67 +24306,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]; @@ -24144,53 +24374,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; @@ -24208,8 +24438,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. @@ -24223,20 +24453,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. @@ -24248,57 +24478,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; } @@ -24321,14 +24551,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. @@ -24336,7 +24566,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)); } @@ -24347,8 +24577,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; } @@ -24362,77 +24592,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(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); } } @@ -24444,10 +24674,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 @@ -24457,7 +24687,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) { @@ -24466,25 +24696,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 = narrowBySwitchOnTypeOf(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); @@ -24495,15 +24725,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); @@ -24515,7 +24745,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. @@ -24532,7 +24762,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; } @@ -24545,14 +24775,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 @@ -24572,14 +24802,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) { @@ -24608,7 +24838,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. @@ -24624,7 +24854,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); } @@ -24635,49 +24865,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 = 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 = 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; } @@ -24687,9 +24917,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); @@ -24701,12 +24931,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; @@ -24715,17 +24945,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const narrowedPropType = narrowType(propType); return filterType(type, t => { const discriminantType = getTypeOfPropertyOrIndexSignature(t, propName); - return !(narrowedPropType.flags & ts.TypeFlags.Never) && isTypeComparableTo(narrowedPropType, discriminantType); + return !(narrowedPropType.flags & TypeFlags.Never) && isTypeComparableTo(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; } @@ -24734,10 +24964,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; } @@ -24745,9 +24975,9 @@ 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 type.flags & ts.TypeFlags.Unknown && assumeTrue ? nonNullUnknownType : + return type.flags & TypeFlags.Unknown && assumeTrue ? nonNullUnknownType : getTypeWithFacts(type, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy); } if (strictNullChecks && assumeTrue && optionalChainContainsReference(expr, reference)) { @@ -24760,43 +24990,43 @@ 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); if (prop) { - return prop.flags & ts.SymbolFlags.Optional ? true : assumeTrue; + return prop.flags & SymbolFlags.Optional ? true : assumeTrue; } return getApplicableIndexInfoForName(type, propName) ? true : !assumeTrue; } - function narrowByInKeyword(type: ts.Type, name: ts.__String, assumeTrue: boolean) { - if (type.flags & ts.TypeFlags.Union - || type.flags & ts.TypeFlags.Object && declaredType !== type - || ts.isThisTypeParameter(type) - || type.flags & ts.TypeFlags.Intersection && ts.every((type as ts.IntersectionType).types, t => t.symbol !== globalThisSymbol)) { + function narrowByInKeyword(type: Type, name: __String, assumeTrue: boolean) { + if (type.flags & TypeFlags.Union + || type.flags & TypeFlags.Object && declaredType !== type + || isThisTypeParameter(type) + || type.flags & TypeFlags.Intersection && every((type as IntersectionType).types, t => t.symbol !== globalThisSymbol)) { return filterType(type, t => isTypePresencePossible(t, name, assumeTrue)); } 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); @@ -24827,17 +25057,17 @@ 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 = getTypeOfNode(expr.left); - if (leftType.flags & ts.TypeFlags.StringLiteral) { - const name = ts.escapeLeadingUnderscores((leftType as ts.StringLiteralType).value); - if (containsMissingType(type) && ts.isAccessExpression(reference) && isMatchingReference(reference.expression, target) && + if (leftType.flags & TypeFlags.StringLiteral) { + const name = escapeLeadingUnderscores((leftType as StringLiteralType).value); + if (containsMissingType(type) && isAccessExpression(reference) && isMatchingReference(reference.expression, target) && getAccessedPropertyName(reference) === name) { return getTypeWithFacts(type, assumeTrue ? TypeFacts.NEUndefined : TypeFacts.EQUndefined); } @@ -24846,16 +25076,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } 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); @@ -24863,25 +25093,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, isTypeDerivedFrom); } - 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. @@ -24891,49 +25121,49 @@ 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 ? getTypeWithFacts(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); - if (assumeTrue && (type.flags & ts.TypeFlags.Unknown) && (operator === ts.SyntaxKind.EqualsEqualsToken || operator === ts.SyntaxKind.ExclamationEqualsToken) && (valueType.flags & ts.TypeFlags.Null)) { + if (assumeTrue && (type.flags & TypeFlags.Unknown) && (operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken) && (valueType.flags & TypeFlags.Null)) { return getUnionType([nullType, undefinedType]); } - if ((type.flags & ts.TypeFlags.Unknown) && assumeTrue && (operator === ts.SyntaxKind.EqualsEqualsEqualsToken || operator === ts.SyntaxKind.ExclamationEqualsEqualsToken)) { - if (valueType.flags & (ts.TypeFlags.Primitive | ts.TypeFlags.NonPrimitive)) { + if ((type.flags & TypeFlags.Unknown) && assumeTrue && (operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken)) { + if (valueType.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive)) { return valueType; } - if (valueType.flags & ts.TypeFlags.Object) { + if (valueType.flags & TypeFlags.Object) { return nonPrimitiveType; } return type; } - if (valueType.flags & ts.TypeFlags.Nullable) { + if (valueType.flags & TypeFlags.Nullable) { if (!strictNullChecks) { return type; } - const doubleEquals = operator === ts.SyntaxKind.EqualsEqualsToken || operator === ts.SyntaxKind.ExclamationEqualsToken; + const doubleEquals = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken; 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 type.flags & ts.TypeFlags.Unknown && facts & (TypeFacts.NENull | TypeFacts.NEUndefinedOrNull) ? nonNullUnknownType : getTypeWithFacts(type, facts); + return type.flags & TypeFlags.Unknown && facts & (TypeFacts.NENull | TypeFacts.NEUndefinedOrNull) ? nonNullUnknownType : getTypeWithFacts(type, facts); } if (assumeTrue) { - const filterFn: (t: ts.Type) => boolean = operator === ts.SyntaxKind.EqualsEqualsToken ? + const filterFn: (t: Type) => boolean = operator === SyntaxKind.EqualsEqualsToken ? t => areTypesComparable(t, valueType) || isCoercibleUnderDoubleEquals(t, valueType) : t => areTypesComparable(t, valueType); return replacePrimitivesWithLiterals(filterType(type, filterFn), valueType); @@ -24944,9 +25174,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); @@ -24956,10 +25186,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return type; } - if (type.flags & ts.TypeFlags.Any && literal.text === "function") { + if (type.flags & TypeFlags.Any && literal.text === "function") { return type; } - if (assumeTrue && type.flags & ts.TypeFlags.Unknown && literal.text === "object") { + if (assumeTrue && type.flags & TypeFlags.Unknown && literal.text === "object") { // The non-null unknown type is used to track whether a previous narrowing operation has removed the null type // from the unknown type. For example, the expression `x && typeof x === 'object'` first narrows x to the non-null // unknown type, and then narrows that to the non-primitive type. @@ -24972,12 +25202,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return getTypeWithFacts(assumeTrue && impliedType ? mapType(type, narrowUnionMemberByTypeof(impliedType)) : type, facts); } - 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 @@ -24987,17 +25217,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); } @@ -25011,21 +25241,21 @@ 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 getImpliedTypeFromTypeofGuard(type: ts.Type, text: string) { + function getImpliedTypeFromTypeofGuard(type: Type, text: string) { switch (text) { case "function": - return type.flags & ts.TypeFlags.Any ? type : globalFunctionType; + return type.flags & TypeFlags.Any ? type : globalFunctionType; case "object": - return type.flags & ts.TypeFlags.Unknown ? getUnionType([nonPrimitiveType, nullType]) : type; + return type.flags & TypeFlags.Unknown ? getUnionType([nonPrimitiveType, nullType]) : type; default: return typeofTypesByName.get(text); } @@ -25037,15 +25267,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // the guard. For example: narrowing `{} | undefined` by `"boolean"` should produce the type `boolean`, not // the filtered type `{}`. For this reason we narrow constituents of the union individually, in addition to // filtering by type-facts. - function narrowUnionMemberByTypeof(candidate: ts.Type) { - return (type: ts.Type) => { + function narrowUnionMemberByTypeof(candidate: Type) { + return (type: Type) => { if (isTypeSubtypeOf(type, candidate)) { return type; } if (isTypeSubtypeOf(candidate, type)) { return candidate; } - if (type.flags & ts.TypeFlags.Instantiable) { + if (type.flags & TypeFlags.Instantiable) { const constraint = getBaseConstraintOfType(type) || anyType; if (isTypeSubtypeOf(candidate, constraint)) { return getIntersectionType([type, candidate]); @@ -25055,13 +25285,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }; } - function narrowBySwitchOnTypeOf(type: ts.Type, switchStatement: ts.SwitchStatement, clauseStart: number, clauseEnd: number): ts.Type { + function narrowBySwitchOnTypeOf(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): Type { const switchWitnesses = getSwitchClauseTypeOfWitnesses(switchStatement, /*retainDefault*/ true); if (!switchWitnesses.length) { return type; } // Equal start and end denotes implicit fallthrough; undefined marks explicit default clause - const defaultCaseLocation = ts.findIndex(switchWitnesses, elem => elem === undefined); + const defaultCaseLocation = findIndex(switchWitnesses, elem => elem === undefined); const hasDefaultClause = clauseStart === clauseEnd || (defaultCaseLocation >= clauseStart && defaultCaseLocation < clauseEnd); let clauseWitnesses: string[]; let switchFacts: TypeFacts; @@ -25115,15 +25345,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return getTypeWithFacts(mapType(type, narrowUnionMemberByTypeof(impliedType)), switchFacts); } - 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; } @@ -25134,7 +25364,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; } @@ -25154,13 +25384,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; } @@ -25169,7 +25399,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)) { @@ -25184,8 +25414,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); @@ -25200,30 +25430,30 @@ 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, isTypeDerivedFrom); } - function getNarrowedType(type: ts.Type, candidate: ts.Type, assumeTrue: boolean, isRelated: (source: ts.Type, target: ts.Type) => boolean) { + function getNarrowedType(type: Type, candidate: Type, assumeTrue: boolean, isRelated: (source: Type, target: Type) => boolean) { if (!assumeTrue) { return filterType(type, t => !isRelated(t, candidate)); } // If the current type is a union type, remove all constituents that couldn't be instances of // the candidate type. If one or more constituents remain, return a union of those. - if (type.flags & ts.TypeFlags.Union) { + if (type.flags & TypeFlags.Union) { const assignableType = filterType(type, t => isRelated(t, candidate)); - if (!(assignableType.flags & ts.TypeFlags.Never)) { + if (!(assignableType.flags & TypeFlags.Never)) { return assignableType; } } @@ -25239,20 +25469,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { 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); } } @@ -25260,7 +25490,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); @@ -25283,21 +25513,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--; @@ -25306,28 +25536,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 getTypeWithFacts(type, assumePresent ? TypeFacts.NEUndefinedOrNull : TypeFacts.EQUndefinedOrNull); } @@ -25339,25 +25569,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 @@ -25368,23 +25598,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); } @@ -25392,37 +25622,37 @@ 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 && - getFalsyFlags(declaredType) & ts.TypeFlags.Undefined && - !(getFalsyFlags(checkExpression(declaration.initializer)) & ts.TypeFlags.Undefined); + getFalsyFlags(declaredType) & TypeFlags.Undefined && + !(getFalsyFlags(checkExpression(declaration.initializer)) & TypeFlags.Undefined); popTypeResolution(); return annotationIncludesUndefined ? getTypeWithFacts(declaredType, TypeFacts.NEUndefined) : declaredType; @@ -25433,40 +25663,40 @@ 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) { - return !!(type.flags & ts.TypeFlags.Instantiable && getBaseConstraintOrType(type).flags & (ts.TypeFlags.Nullable | ts.TypeFlags.Union)); + function isGenericTypeWithUnionConstraint(type: Type) { + return !!(type.flags & TypeFlags.Instantiable && getBaseConstraintOrType(type).flags & (TypeFlags.Nullable | TypeFlags.Union)); } - function isGenericTypeWithoutNullableConstraint(type: ts.Type) { - return !!(type.flags & ts.TypeFlags.Instantiable && !maybeTypeOfKind(getBaseConstraintOrType(type), ts.TypeFlags.Nullable)); + function isGenericTypeWithoutNullableConstraint(type: Type) { + return !!(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)); 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 @@ -25477,34 +25707,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const substituteConstraints = !(checkMode && checkMode & CheckMode.Inferential) && someType(type, isGenericTypeWithUnionConstraint) && (isConstraintPosition(type, reference) || hasContextualTypeWithNoGenericTypes(reference, checkMode)); - return substituteConstraints ? mapType(type, t => t.flags & ts.TypeFlags.Instantiable ? getBaseConstraintOrType(t) : t) : type; + return substituteConstraints ? mapType(type, t => t.flags & TypeFlags.Instantiable ? getBaseConstraintOrType(t) : t) : 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)) { + function markAliasReferenced(symbol: Symbol, location: Node) { + if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !isInTypeQuery(location) && !getTypeOnlyAliasDeclaration(symbol)) { const target = resolveAlias(symbol); - if (target.flags & ts.SymbolFlags.Value) { + if (target.flags & SymbolFlags.Value) { // 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(target) ) { markAliasSymbolAsReferenced(symbol); @@ -25516,7 +25746,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 @@ -25542,18 +25772,18 @@ 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); - links.flags &= ~ts.NodeCheckFlags.InCheckIdentifier; - if (parentType && parentType.flags & ts.TypeFlags.Union && !(parent.kind === ts.SyntaxKind.Parameter && isSymbolAssigned(symbol))) { + links.flags &= ~NodeCheckFlags.InCheckIdentifier; + if (parentType && parentType.flags & TypeFlags.Union && !(parent.kind === SyntaxKind.Parameter && isSymbolAssigned(symbol))) { const pattern = declaration.parent; const narrowedType = getFlowTypeOfReference(pattern, parentType, parentType, /*flowContainer*/ undefined, location.flowNode); - if (narrowedType.flags & ts.TypeFlags.Never) { + if (narrowedType.flags & TypeFlags.Never) { return neverType; } return getBindingElementTypeFromParentType(declaration, narrowedType); @@ -25581,15 +25811,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)); } } @@ -25599,8 +25829,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); } @@ -25617,27 +25847,27 @@ 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); } // We should only mark aliases as referenced if there isn't a local value declaration // for the symbol. Also, don't mark any property access expression LHS - checkPropertyAccessExpression will handle that - if (!(node.parent && ts.isPropertyAccessExpression(node.parent) && node.parent.expression === node)) { + if (!(node.parent && isPropertyAccessExpression(node.parent) && node.parent.expression === node)) { markAliasReferenced(symbol, node); } @@ -25648,38 +25878,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); } } } @@ -25687,38 +25917,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; } } @@ -25738,30 +25968,30 @@ 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); } // We only look for uninitialized variables in strict null checking mode, and only when we can analyze // 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 || ts.isBindingElement(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) : + const assumeInitialized = isParameter || isAlias || isOuterVariable || isSpreadDestructuringAssignmentTarget || isModuleExports || isBindingElement(declaration) || + 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); @@ -25771,40 +26001,40 @@ 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 && !(getFalsyFlags(type) & ts.TypeFlags.Undefined) && getFalsyFlags(flowType) & ts.TypeFlags.Undefined) { - error(node, ts.Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol)); + else if (!assumeInitialized && !(getFalsyFlags(type) & TypeFlags.Undefined) && getFalsyFlags(flowType) & TypeFlags.Undefined) { + 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 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; } @@ -25813,7 +26043,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); @@ -25821,16 +26051,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 @@ -25839,48 +26069,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) { @@ -25889,24 +26119,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); } /** @@ -25914,17 +26144,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. @@ -25935,53 +26165,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.length(container.parent.decorators)) { - 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) && length(container.parent.decorators)) { + 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); } @@ -25989,15 +26219,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)); } } } @@ -26005,10 +26235,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. @@ -26016,12 +26246,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); } @@ -26031,13 +26261,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); @@ -26053,110 +26283,110 @@ 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; // 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) { - container = ts.getSuperContainer(container, /*stopOnFunctions*/ true); - needToCaptureLexicalThis = languageVersion < ts.ScriptTarget.ES2015; + while (container && container.kind === SyntaxKind.ArrowFunction) { + container = getSuperContainer(container, /*stopOnFunctions*/ true); + needToCaptureLexicalThis = languageVersion < ScriptTarget.ES2015; } } 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 @@ -26164,43 +26394,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; @@ -26264,12 +26494,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 && ts.hasSyntacticModifier(container, ts.ModifierFlags.Async)) { - if (ts.isSuperProperty(node.parent) && ts.isAssignmentTarget(node.parent)) { - getNodeLinks(container).flags |= ts.NodeCheckFlags.AsyncMethodWithSuperBinding; + if (container.kind === SyntaxKind.MethodDeclaration && hasSyntacticModifier(container, ModifierFlags.Async)) { + if (isSuperProperty(node.parent) && isAssignmentTarget(node.parent)) { + getNodeLinks(container).flags |= NodeCheckFlags.AsyncMethodWithSuperBinding; } else { - getNodeLinks(container).flags |= ts.NodeCheckFlags.AsyncMethodWithSuper; + getNodeLinks(container).flags |= NodeCheckFlags.AsyncMethodWithSuper; } } @@ -26280,9 +26510,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 { @@ -26292,29 +26522,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; } @@ -26322,7 +26552,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) @@ -26331,23 +26561,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; } } } @@ -26356,26 +26586,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)) { @@ -26387,7 +26617,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) { @@ -26402,10 +26632,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); } // There was no contextual ThisType for the containing object literal, so the contextual type @@ -26415,14 +26645,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; } @@ -26436,12 +26666,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); @@ -26459,39 +26689,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): ts.Type | undefined { - const typeNode = ts.getEffectiveTypeAnnotationNode(declaration); + function getContextualTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration): 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); - case ts.SyntaxKind.PropertyDeclaration: - if (ts.isStatic(declaration)) { + case SyntaxKind.PropertyDeclaration: + if (isStatic(declaration)) { return getContextualTypeForStaticPropertyDeclaration(declaration); } // By default, do nothing and return undefined - only the above cases have context implied by a parent } } - function getContextualTypeForBindingElement(declaration: ts.BindingElement): ts.Type | undefined { + function getContextualTypeForBindingElement(declaration: BindingElement): Type | undefined { const parent = declaration.parent.parent; const name = declaration.propertyName || declaration.name; const parentType = getContextualTypeForVariableLikeDeclaration(parent) || - 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); } @@ -26502,8 +26732,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getContextualTypeForStaticPropertyDeclaration(declaration: ts.PropertyDeclaration): ts.Type | undefined { - const parentType = ts.isExpression(declaration.parent) && getContextualType(declaration.parent); + function getContextualTypeForStaticPropertyDeclaration(declaration: PropertyDeclaration): Type | undefined { + const parentType = isExpression(declaration.parent) && getContextualType(declaration.parent); if (!parentType) return undefined; return getTypeOfPropertyOfContextualType(parentType, getSymbolOfNode(declaration).escapedName); } @@ -26516,28 +26746,28 @@ 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): ts.Type | undefined { - const declaration = node.parent as ts.VariableLikeDeclaration; - if (ts.hasInitializer(declaration) && node === declaration.initializer) { + function getContextualTypeForInitializerExpression(node: Expression, contextFlags?: ContextFlags): Type | undefined { + const declaration = node.parent as VariableLikeDeclaration; + if (hasInitializer(declaration) && node === declaration.initializer) { const result = getContextualTypeForVariableLikeDeclaration(declaration); if (result) { return result; } - if (!(contextFlags! & ts.ContextFlags.SkipBindingPatterns) && ts.isBindingPattern(declaration.name)) { // This is less a contextual type and more an implied shape - in some cases, this may be undesirable + if (!(contextFlags! & ContextFlags.SkipBindingPatterns) && isBindingPattern(declaration.name)) { // This is less a contextual type and more an implied shape - in some cases, this may be undesirable return getTypeFromBindingPattern(declaration.name, /*includePatternInType*/ true, /*reportErrors*/ false); } } return undefined; } - function getContextualTypeForReturnExpression(node: ts.Expression): ts.Type | undefined { - const func = ts.getContainingFunction(node); + function getContextualTypeForReturnExpression(node: Expression): Type | undefined { + const func = getContainingFunction(node); if (func) { let contextualReturnType = getContextualReturnType(func); if (contextualReturnType) { - const functionFlags = ts.getFunctionFlags(func); - if (functionFlags & ts.FunctionFlags.Generator) { // Generator or AsyncGenerator function - const use = functionFlags & ts.FunctionFlags.Async ? IterationUse.AsyncGeneratorReturnType : IterationUse.GeneratorReturnType; + const functionFlags = getFunctionFlags(func); + if (functionFlags & FunctionFlags.Generator) { // Generator or AsyncGenerator function + const use = functionFlags & FunctionFlags.Async ? IterationUse.AsyncGeneratorReturnType : IterationUse.GeneratorReturnType; const iterationTypes = getIterationTypesOfIterable(contextualReturnType, use, /*errorNode*/ undefined); if (!iterationTypes) { return undefined; @@ -26546,7 +26776,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)]); @@ -26558,7 +26788,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function getContextualTypeForAwaitOperand(node: ts.AwaitExpression, contextFlags?: ts.ContextFlags): ts.Type | undefined { + function getContextualTypeForAwaitOperand(node: AwaitExpression, contextFlags?: ContextFlags): Type | undefined { const contextualType = getContextualType(node, contextFlags); if (contextualType) { const contextualAwaitedType = getAwaitedTypeNoAlias(contextualType); @@ -26567,28 +26797,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function getContextualTypeForYieldOperand(node: ts.YieldExpression): ts.Type | undefined { - const func = ts.getContainingFunction(node); + function getContextualTypeForYieldOperand(node: YieldExpression): Type | undefined { + const func = getContainingFunction(node); if (func) { - const functionFlags = ts.getFunctionFlags(func); + const functionFlags = getFunctionFlags(func); const contextualReturnType = getContextualReturnType(func); if (contextualReturnType) { return node.asteriskToken ? contextualReturnType - : getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, contextualReturnType, (functionFlags & ts.FunctionFlags.Async) !== 0); + : getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, contextualReturnType, (functionFlags & FunctionFlags.Async) !== 0); } } 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; } @@ -26598,8 +26828,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); if (contextualReturnType) { return getIterationTypeOfGeneratorFunctionReturnType(kind, contextualReturnType, isAsync) @@ -26609,7 +26839,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function getContextualReturnType(functionDecl: ts.SignatureDeclaration): ts.Type | undefined { + function getContextualReturnType(functionDecl: SignatureDeclaration): 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); @@ -26618,11 +26848,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); } @@ -26630,14 +26860,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; @@ -26647,44 +26877,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): ts.Type | undefined { - const binaryExpression = node.parent as ts.BinaryExpression; + function getContextualTypeForBinaryOperand(node: Expression, contextFlags?: ContextFlags): 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; @@ -26695,20 +26925,20 @@ 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); } 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); } @@ -26716,25 +26946,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)) || (decl.initializer && getTypeOfExpression(binaryExpression.left)); } - 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); } @@ -26748,18 +26978,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); } @@ -26767,42 +26997,42 @@ 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 AssignmentDeclarationKind.ExportsProperty: + case AssignmentDeclarationKind.Prototype: + case AssignmentDeclarationKind.PrototypeProperty: let valueDeclaration = binaryExpression.left.symbol?.valueDeclaration; // falls through - case ts.AssignmentDeclarationKind.ModuleExports: + case AssignmentDeclarationKind.ModuleExports: 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) { @@ -26810,29 +27040,29 @@ 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) { - return mapType(type, (t): ts.Type | undefined => { - if (t.flags & ts.TypeFlags.Intersection) { - const intersection = t as ts.IntersectionType; - let newTypes = ts.mapDefined(intersection.types, getTypeOfConcretePropertyOfContextualType); + function getTypeOfPropertyOfContextualType(type: Type, name: __String, nameType?: Type) { + return mapType(type, (t): Type | undefined => { + if (t.flags & TypeFlags.Intersection) { + const intersection = t as IntersectionType; + let newTypes = mapDefined(intersection.types, getTypeOfConcretePropertyOfContextualType); if (newTypes.length > 0) { return getIntersectionType(newTypes); } - newTypes = ts.mapDefined(intersection.types, getTypeOfApplicableIndexInfoOfContextualType); + newTypes = mapDefined(intersection.types, getTypeOfApplicableIndexInfoOfContextualType); if (newTypes.length > 0) { return getIntersectionType(newTypes); } @@ -26845,53 +27075,53 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return getTypeOfApplicableIndexInfoOfContextualType(t); }, /*noReductions*/ true); - function getTypeOfConcretePropertyOfContextualType(t: ts.Type) { + function getTypeOfConcretePropertyOfContextualType(t: Type) { 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); } return undefined; } - if (t.flags & ts.TypeFlags.StructuredType) { + 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 undefined; } - function getTypeOfApplicableIndexInfoOfContextualType(t: ts.Type) { - if (!(t.flags & ts.TypeFlags.StructuredType)) { + function getTypeOfApplicableIndexInfoOfContextualType(t: Type) { + if (!(t.flags & TypeFlags.StructuredType)) { return undefined; } - return findApplicableIndexInfo(getIndexInfosOfStructuredType(t), nameType || getStringLiteralType(ts.unescapeLeadingUnderscores(name)))?.type; + return findApplicableIndexInfo(getIndexInfosOfStructuredType(t), nameType || getStringLiteralType(unescapeLeadingUnderscores(name)))?.type; } } // 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): ts.Type | undefined { - ts.Debug.assert(ts.isObjectLiteralMethod(node)); - if (node.flags & ts.NodeFlags.InWithStatement) { + function getContextualTypeForObjectLiteralMethod(node: MethodDeclaration, contextFlags?: ContextFlags): 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) { - const objectLiteral = element.parent as ts.ObjectLiteralExpression; - const propertyAssignmentType = ts.isPropertyAssignment(element) && getContextualTypeForVariableLikeDeclaration(element); + function getContextualTypeForObjectLiteralElement(element: ObjectLiteralElementLike, contextFlags?: ContextFlags) { + const objectLiteral = element.parent as ObjectLiteralExpression; + const propertyAssignmentType = isPropertyAssignment(element) && getContextualTypeForVariableLikeDeclaration(element); if (propertyAssignmentType) { return propertyAssignmentType; } @@ -26917,9 +27147,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), @@ -26927,19 +27157,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): ts.Type | undefined { - const conditional = node.parent as ts.ConditionalExpression; + function getContextualTypeForConditionalOperand(node: Expression, contextFlags?: ContextFlags): 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) { + function getContextualTypeForChildJsxExpression(node: JsxElement, child: JsxChild) { const attributesType = getApparentTypeOfContextualType(node.openingElement.tagName); // 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 => { @@ -26952,20 +27182,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }, /*noReductions*/ true)); } - function getContextualTypeForJsxExpression(node: ts.JsxExpression): ts.Type | undefined { + function getContextualTypeForJsxExpression(node: JsxExpression): Type | undefined { const exprParent = node.parent; - return ts.isJsxAttributeLike(exprParent) + return isJsxAttributeLike(exprParent) ? getContextualType(node) - : ts.isJsxElement(exprParent) + : isJsxElement(exprParent) ? getContextualTypeForChildJsxExpression(exprParent, node) : undefined; } - function getContextualTypeForJsxAttribute(attribute: ts.JsxAttribute | ts.JsxSpreadAttribute): ts.Type | undefined { + function getContextualTypeForJsxAttribute(attribute: JsxAttribute | JsxSpreadAttribute): 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); if (!attributesType || isTypeAny(attributesType)) { return undefined; @@ -26980,37 +27210,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, @@ -27018,16 +27248,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, @@ -27037,30 +27267,30 @@ 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): ts.Type | undefined { - const contextualType = ts.isObjectLiteralMethod(node) ? + function getApparentTypeOfContextualType(node: Expression | MethodDeclaration, contextFlags?: ContextFlags): 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): ts.Type | undefined { - if (contextualType && maybeTypeOfKind(contextualType, ts.TypeFlags.Instantiable)) { + function instantiateContextualType(contextualType: Type | undefined, node: Node, contextFlags?: ContextFlags): Type | undefined { + if (contextualType && maybeTypeOfKind(contextualType, TypeFlags.Instantiable)) { const inferenceContext = getInferenceContext(node); // If no inferences have been made, nothing is gained from instantiating as type parameters // would just be replaced with their defaults similar to the apparent type. - if (inferenceContext && ts.some(inferenceContext.inferences, hasInferenceCandidates)) { + if (inferenceContext && some(inferenceContext.inferences, hasInferenceCandidates)) { // 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. - if (contextFlags && contextFlags & ts.ContextFlags.Signature) { + if (contextFlags && contextFlags & ContextFlags.Signature) { return instantiateInstantiableTypes(contextualType, inferenceContext.nonFixingMapper); } // For other purposes (e.g. determining whether to produce literal types) we only @@ -27069,7 +27299,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // literals actually end up widening to 'boolean' (see #48363). if (inferenceContext.returnMapper) { 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; } @@ -27081,15 +27311,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; } @@ -27111,8 +27341,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): ts.Type | undefined { - if (node.flags & ts.NodeFlags.InWithStatement) { + function getContextualType(node: Expression, contextFlags?: ContextFlags): Type | undefined { + if (node.flags & NodeFlags.InWithStatement) { // We cannot answer semantic questions within a with block, do not proceed any further return undefined; } @@ -27121,76 +27351,76 @@ 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); - case ts.SyntaxKind.YieldExpression: - return getContextualTypeForYieldOperand(parent as ts.YieldExpression); - 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); + 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.ExportAssignment: - return tryGetTypeFromEffectiveTypeNode(parent as ts.ExportAssignment); - case ts.SyntaxKind.JsxExpression: - return getContextualTypeForJsxExpression(parent as ts.JsxExpression); - case ts.SyntaxKind.JsxAttribute: - case ts.SyntaxKind.JsxSpreadAttribute: - return getContextualTypeForJsxAttribute(parent as ts.JsxAttribute | ts.JsxSpreadAttribute); - 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.ExportAssignment: + return tryGetTypeFromEffectiveTypeNode(parent as ExportAssignment); + case SyntaxKind.JsxExpression: + return getContextualTypeForJsxExpression(parent as JsxExpression); + case SyntaxKind.JsxAttribute: + case SyntaxKind.JsxSpreadAttribute: + return getContextualTypeForJsxAttribute(parent as JsxAttribute | JsxSpreadAttribute); + 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); } } - 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) { - if (ts.isJsxOpeningElement(node) && node.parent.contextualType && contextFlags !== ts.ContextFlags.Completions) { + function getContextualJsxElementAttributesType(node: JsxOpeningLikeElement, contextFlags?: ContextFlags) { + 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! @@ -27199,13 +27429,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); @@ -27215,14 +27445,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)) { @@ -27240,15 +27470,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; } @@ -27258,27 +27488,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 @@ -27292,8 +27522,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; } @@ -27313,7 +27543,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const hostClassType = getReturnTypeOfSignature(sig); apparentAttributesType = intersectTypes( typeParams - ? createTypeReference(intrinsicClassAttribs as ts.GenericType, fillMissingTypeArguments([hostClassType], typeParams, getMinTypeArgumentCount(typeParams), ts.isInJSFile(context))) + ? createTypeReference(intrinsicClassAttribs as GenericType, fillMissingTypeArguments([hostClassType], typeParams, getMinTypeArgumentCount(typeParams), isInJSFile(context))) : intrinsicClassAttribs, apparentAttributesType ); @@ -27328,9 +27558,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 @@ -27339,7 +27569,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; } @@ -27350,7 +27580,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; @@ -27358,7 +27588,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) { @@ -27379,14 +27609,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); @@ -27396,9 +27626,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 @@ -27415,26 +27645,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]; @@ -27442,16 +27672,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; } @@ -27460,21 +27690,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) { @@ -27498,43 +27728,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); - 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: @@ -27553,26 +27783,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); } } @@ -27584,90 +27814,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) || @@ -27676,41 +27906,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); 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; @@ -27720,7 +27950,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); } } @@ -27728,16 +27958,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); @@ -27749,11 +27979,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; } @@ -27762,22 +27992,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)); } } @@ -27794,21 +28024,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; @@ -27826,7 +28056,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; @@ -27837,11 +28067,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; @@ -27867,12 +28097,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // type with those properties for which the binding pattern specifies a default value. // If the object literal is spread into another object literal, skip this step and let the top-level object // literal handle it instead. - if (contextualTypeHasPattern && node.parent.kind !== ts.SyntaxKind.SpreadAssignment) { + if (contextualTypeHasPattern && node.parent.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); @@ -27888,7 +28118,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; } @@ -27903,13 +28133,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; @@ -27918,22 +28148,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); @@ -27948,41 +28178,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 @@ -27997,24 +28227,24 @@ 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 allAttributesTable = strictNullChecks ? ts.createSymbolTable() : undefined; - let attributesTable = ts.createSymbolTable(); - let spread: ts.Type = emptyJsxObjectType; + 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) { @@ -28029,10 +28259,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)) { @@ -28045,7 +28275,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; } } @@ -28058,33 +28288,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); 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); } @@ -28105,23 +28335,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 { @@ -28131,13 +28361,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)); } } } @@ -28148,14 +28378,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; } @@ -28165,33 +28395,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; } @@ -28199,8 +28429,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; @@ -28208,14 +28438,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) { @@ -28224,7 +28454,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; @@ -28234,11 +28464,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; @@ -28251,7 +28481,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 } @@ -28265,9 +28495,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 @@ -28275,7 +28505,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 @@ -28284,15 +28514,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, @@ -28300,23 +28530,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); @@ -28325,19 +28555,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"; @@ -28345,7 +28575,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); } @@ -28359,18 +28589,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 @@ -28380,12 +28610,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); } } @@ -28394,15 +28624,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; } @@ -28413,17 +28643,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]); @@ -28433,26 +28663,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); @@ -28463,33 +28693,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); } } } @@ -28515,8 +28745,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. @@ -28528,8 +28758,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; } @@ -28538,19 +28768,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; } @@ -28559,22 +28789,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; } } @@ -28587,13 +28817,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); } @@ -28608,11 +28838,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 @@ -28622,22 +28852,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)!)); } @@ -28646,34 +28876,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)!)); } @@ -28692,7 +28922,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 @@ -28701,10 +28931,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)); } @@ -28712,17 +28942,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; @@ -28730,113 +28960,113 @@ 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) { - return !!((strictNullChecks ? getFalsyFlags(type) : type.flags) & ts.TypeFlags.Nullable); + function isNullableType(type: Type) { + return !!((strictNullChecks ? getFalsyFlags(type) : type.flags) & TypeFlags.Nullable); } - function getNonNullableTypeIfNeeded(type: ts.Type) { + function getNonNullableTypeIfNeeded(type: Type) { return isNullableType(type) ? getNonNullableType(type) : type; } - function reportObjectPossiblyNullOrUndefinedError(node: ts.Node, flags: ts.TypeFlags) { - error(node, flags & ts.TypeFlags.Undefined ? flags & ts.TypeFlags.Null ? - ts.Diagnostics.Object_is_possibly_null_or_undefined : - ts.Diagnostics.Object_is_possibly_undefined : - ts.Diagnostics.Object_is_possibly_null + function reportObjectPossiblyNullOrUndefinedError(node: Node, flags: TypeFlags) { + error(node, flags & TypeFlags.Undefined ? flags & TypeFlags.Null ? + Diagnostics.Object_is_possibly_null_or_undefined : + Diagnostics.Object_is_possibly_undefined : + Diagnostics.Object_is_possibly_null ); } - function reportCannotInvokePossiblyNullOrUndefinedError(node: ts.Node, flags: ts.TypeFlags) { - error(node, flags & ts.TypeFlags.Undefined ? flags & ts.TypeFlags.Null ? - 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 + function reportCannotInvokePossiblyNullOrUndefinedError(node: Node, flags: TypeFlags) { + error(node, flags & TypeFlags.Undefined ? flags & TypeFlags.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, kind: ts.TypeFlags) => void - ): ts.Type { - if (strictNullChecks && type.flags & ts.TypeFlags.Unknown) { - error(node, ts.Diagnostics.Object_is_of_type_unknown); + type: Type, + node: Node, + reportError: (node: Node, kind: TypeFlags) => void + ): Type { + if (strictNullChecks && type.flags & TypeFlags.Unknown) { + error(node, Diagnostics.Object_is_of_type_unknown); return errorType; } - const kind = (strictNullChecks ? getFalsyFlags(type) : type.flags) & ts.TypeFlags.Nullable; + const kind = (strictNullChecks ? getFalsyFlags(type) : type.flags) & TypeFlags.Nullable; if (kind) { reportError(node, kind); 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) { - error(node, ts.Diagnostics.Object_is_possibly_undefined); + if (nonNullType.flags & TypeFlags.Void) { + 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; @@ -28844,26 +29074,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) { @@ -28872,8 +29102,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; } @@ -28884,19 +29114,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; } @@ -28904,34 +29134,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 ) ); @@ -28940,7 +29170,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) ); @@ -28949,38 +29179,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; } } @@ -28990,20 +29220,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 @@ -29012,17 +29242,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); @@ -29030,28 +29260,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); } } @@ -29062,10 +29292,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; } @@ -29082,30 +29312,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; } @@ -29118,87 +29348,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 && !(getFalsyFlags(propType) & ts.TypeFlags.Undefined) && getFalsyFlags(flowType) & ts.TypeFlags.Undefined) { - error(errorNode, ts.Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop!)); // TODO: GH#18217 + if (assumeUninitialized && !(getFalsyFlags(propType) & TypeFlags.Undefined) && getFalsyFlags(flowType) & TypeFlags.Undefined) { + 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"; } }); } @@ -29207,13 +29437,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; } @@ -29224,7 +29454,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; @@ -29232,172 +29462,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)); @@ -29405,12 +29635,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; } @@ -29421,9 +29651,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); } /** @@ -29441,12 +29671,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; } @@ -29454,7 +29684,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; @@ -29465,42 +29695,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)); } } @@ -29515,9 +29745,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); @@ -29525,10 +29755,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)) { @@ -29550,11 +29780,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)) { @@ -29563,9 +29793,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); @@ -29574,16 +29804,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; } @@ -29591,7 +29821,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); } @@ -29599,18 +29829,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; @@ -29621,19 +29851,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); @@ -29641,45 +29871,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; } @@ -29692,14 +29922,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; @@ -29738,49 +29968,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; @@ -29791,7 +30021,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 { @@ -29819,40 +30049,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]; } } @@ -29861,13 +30091,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 @@ -29875,31 +30105,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); } @@ -29907,8 +30137,8 @@ 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 contextualType = getContextualType(node, ts.every(signature.typeParameters, p => !!getDefaultFromTypeParameter(p)) ? ts.ContextFlags.SkipBindingPatterns : ts.ContextFlags.None); + if (node.kind !== SyntaxKind.Decorator) { + const contextualType = getContextualType(node, every(signature.typeParameters, p => !!getDefaultFromTypeParameter(p)) ? ContextFlags.SkipBindingPatterns : ContextFlags.None); if (contextualType) { const inferenceTargetType = getReturnTypeOfSignature(signature); if (couldContainTypeVariables(inferenceTargetType)) { @@ -29916,7 +30146,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // outer call expression. Effectively we just want a snapshot of whatever has been // inferred for any outer call expression so far. const outerContext = getInferenceContext(node); - 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 @@ -29930,7 +30160,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 // the source type uses the outer context's return mapper (which excludes inferences made from @@ -29938,17 +30168,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; } } @@ -29960,7 +30190,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); @@ -29977,21 +30207,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 = []; @@ -30000,41 +30230,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); } @@ -30052,18 +30282,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; } /** @@ -30073,13 +30303,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, @@ -30100,26 +30330,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; } @@ -30128,8 +30358,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)) { @@ -30158,10 +30388,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); @@ -30175,43 +30405,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), @@ -30219,9 +30449,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; } } } @@ -30231,16 +30461,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)) { @@ -30248,7 +30478,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)); } } } @@ -30257,45 +30487,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. @@ -30303,12 +30533,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); }); } @@ -30324,97 +30554,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 = parent.kind !== ts.SyntaxKind.PropertyDeclaration && languageVersion !== ts.ScriptTarget.ES3; + const hasPropDesc = parent.kind !== SyntaxKind.PropertyDeclaration && languageVersion !== ScriptTarget.ES3; 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: + case SyntaxKind.PropertyDeclaration: return 2; - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: + 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; } @@ -30425,17 +30655,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); @@ -30449,67 +30679,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); } @@ -30518,25 +30748,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) { - typeArguments = (node as ts.CallExpression).typeArguments; + 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); } } @@ -30545,7 +30775,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); } @@ -30565,7 +30795,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. @@ -30589,15 +30819,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 @@ -30627,33 +30857,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) { @@ -30664,26 +30894,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); @@ -30693,10 +30923,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!)); } @@ -30711,19 +30941,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return getCandidateForOverloadFailure(node, candidates, args, !!candidatesOutArray, checkMode); - 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)); } } @@ -30732,14 +30962,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)) { @@ -30755,12 +30985,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; @@ -30768,11 +30998,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)) { @@ -30795,7 +31025,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 && 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)) { @@ -30819,13 +31049,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`, @@ -30835,30 +31065,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, @@ -30871,21 +31101,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({ | @@ -30899,15 +31129,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(); @@ -30918,13 +31148,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; @@ -30943,8 +31173,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) { @@ -30955,26 +31185,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( @@ -30997,8 +31227,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 @@ -31007,7 +31237,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); } @@ -31016,17 +31246,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); } @@ -31047,15 +31277,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))); } @@ -31064,17 +31294,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); } } @@ -31099,7 +31329,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); } @@ -31108,7 +31338,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); @@ -31117,66 +31347,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; } } @@ -31188,39 +31418,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; } @@ -31228,13 +31458,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); @@ -31248,18 +31478,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) ); } @@ -31270,82 +31500,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); @@ -31354,102 +31584,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(/*decorators*/ undefined, /*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(/*decorators*/ undefined, /*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, @@ -31459,18 +31689,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; } @@ -31487,11 +31717,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); } /** @@ -31499,28 +31729,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."); } /** @@ -31530,7 +31760,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, @@ -31557,16 +31787,16 @@ 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) && node.initializer && ts.isFunctionExpression(node.initializer) ? node.initializer : + const func = isFunctionDeclaration(node) || isFunctionExpression(node) ? node : + isVariableDeclaration(node) && node.initializer && isFunctionExpression(node.initializer) ? node.initializer : undefined; if (func) { // If the node has a @class tag, treat it like a constructor. - if (ts.getJSDocClassTag(node)) return true; + if (getJSDocClassTag(node)) return true; // If the symbol of the node has members, treat it like a constructor. const symbol = getSymbolOfNode(func); @@ -31575,92 +31805,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; } } @@ -31669,7 +31899,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); @@ -31681,55 +31911,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]); } } @@ -31737,45 +31967,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; } @@ -31785,10 +32015,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); @@ -31804,14 +32034,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]); } } @@ -31829,20 +32059,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; @@ -31852,14 +32082,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; @@ -31873,91 +32103,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 && (symbol.flags & ts.SymbolFlags.Enum) && getEnumKind(symbol) === ts.EnumKind.Literal); + return !!(symbol && (symbol.flags & SymbolFlags.Enum) && getEnumKind(symbol) === EnumKind.Literal); } 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); } @@ -31969,43 +32199,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); @@ -32015,21 +32245,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); @@ -32038,59 +32268,59 @@ 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 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 { @@ -32099,37 +32329,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; @@ -32137,15 +32367,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); @@ -32161,7 +32391,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; @@ -32177,14 +32407,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; @@ -32193,18 +32423,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]); @@ -32222,7 +32452,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); @@ -32235,25 +32465,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]); @@ -32264,7 +32494,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) { @@ -32272,7 +32502,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; @@ -32280,7 +32510,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; @@ -32290,7 +32520,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; @@ -32300,7 +32530,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; @@ -32308,7 +32538,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)) { @@ -32321,32 +32551,32 @@ 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)); } } } const restType = getEffectiveRestType(context); - if (restType && restType.flags & ts.TypeFlags.TypeParameter) { + if (restType && restType.flags & TypeFlags.TypeParameter) { // The contextual signature has a generic rest parameter. We first instantiate the contextual // signature (without fixing type parameters) and assign types to contextually typed parameters. const instantiatedContext = instantiateSignature(context, inferenceContext.nonFixingMapper); @@ -32358,7 +32588,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; @@ -32369,7 +32599,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); } @@ -32379,19 +32609,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); @@ -32399,7 +32629,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function assignNonContextualParameterTypes(signature: ts.Signature) { + function assignNonContextualParameterTypes(signature: Signature) { if (signature.thisParameter) { assignParameterType(signature.thisParameter); } @@ -32408,12 +32638,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); @@ -32422,17 +32652,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 { @@ -32442,7 +32672,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) { @@ -32455,7 +32685,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) { @@ -32468,57 +32698,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 @@ -32527,29 +32757,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) { @@ -32595,7 +32825,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; @@ -32628,14 +32858,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, @@ -32646,18 +32876,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else { nextType = getContextualType(yieldExpression); } - 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); } /** @@ -32703,60 +32933,60 @@ 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); return links.isExhaustive !== undefined ? links.isExhaustive : (links.isExhaustive = computeExhaustiveSwitchStatement(node)); } - function computeExhaustiveSwitchStatement(node: ts.SwitchStatement): boolean { - if (node.expression.kind === ts.SyntaxKind.TypeOfExpression) { - const operandType = getTypeOfExpression((node.expression as ts.TypeOfExpression).expression); + function computeExhaustiveSwitchStatement(node: SwitchStatement): boolean { + if (node.expression.kind === SyntaxKind.TypeOfExpression) { + const operandType = getTypeOfExpression((node.expression as TypeOfExpression).expression); const witnesses = getSwitchClauseTypeOfWitnesses(node, /*retainDefault*/ false); // notEqualFacts states that the type of the switched value is not equal to every type in the switch. const notEqualFacts = getFactsFromTypeofSwitch(0, 0, witnesses, /*hasDefault*/ true); const type = getBaseConstraintOfType(operandType) || operandType; // Take any/unknown as a special condition. Or maybe we could change `type` to a union containing all primitive types. - if (type.flags & ts.TypeFlags.AnyOrUnknown) { + if (type.flags & TypeFlags.AnyOrUnknown) { return (TypeFacts.AllTypeofNE & notEqualFacts) === TypeFacts.AllTypeofNE; } - return !!(filterType(type, t => (getTypeFacts(t) & notEqualFacts) === notEqualFacts).flags & ts.TypeFlags.Never); + return !!(filterType(type, t => (getTypeFacts(t) & notEqualFacts) === notEqualFacts).flags & TypeFlags.Never); } const type = getTypeOfExpression(node.expression); if (!isLiteralType(type)) { 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; @@ -32768,17 +32998,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; } @@ -32793,38 +33023,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) { @@ -32839,23 +33069,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))) { @@ -32864,9 +33094,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; } } @@ -32875,7 +33105,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); } @@ -32884,17 +33114,17 @@ 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; } @@ -32924,15 +33154,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 @@ -32941,7 +33171,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 { @@ -32953,8 +33183,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 @@ -32965,7 +33195,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( @@ -32977,17 +33207,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; @@ -32995,7 +33225,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) { @@ -33004,11 +33234,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' @@ -33016,32 +33246,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; @@ -33056,114 +33286,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 : getFalsyFlags(type) & ts.TypeFlags.Undefined)) { - error(expr, ts.Diagnostics.The_operand_of_a_delete_operator_must_be_optional); + !(type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Never)) && + !(exactOptionalPropertyTypes ? symbol.flags & SymbolFlags.Optional : getFalsyFlags(type) & TypeFlags.Undefined)) { + 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; @@ -33172,13 +33402,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); } @@ -33186,81 +33416,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 (maybeTypeOfKind(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 (maybeTypeOfKind(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; @@ -33268,20 +33498,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; } @@ -33289,7 +33519,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; } @@ -33300,12 +33530,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; @@ -33315,40 +33545,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; } @@ -33358,27 +33588,27 @@ 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 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); } @@ -33387,9 +33617,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { leftType = checkNonNullType(leftType, left); // TypeScript 1.0 spec (April 2014): 4.15.5 // Require the left operand to be of type Any, the String primitive type, or the Number primitive type. - if (!(allTypesAssignableToKind(leftType, ts.TypeFlags.StringLike | ts.TypeFlags.NumberLike | ts.TypeFlags.ESSymbolLike) || - isTypeAssignableToKind(leftType, ts.TypeFlags.Index | ts.TypeFlags.TemplateLiteral | ts.TypeFlags.StringMapping | ts.TypeFlags.TypeParameter))) { - error(left, ts.Diagnostics.The_left_hand_side_of_an_in_expression_must_be_a_private_identifier_or_of_type_any_string_number_or_symbol); + if (!(allTypesAssignableToKind(leftType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbolLike) || + isTypeAssignableToKind(leftType, TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping | TypeFlags.TypeParameter))) { + error(left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_a_private_identifier_or_of_type_any_string_number_or_symbol); } } rightType = checkNonNullType(rightType, right); @@ -33413,18 +33643,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // // The result is always of the Boolean primitive type. const rightTypeConstraint = getConstraintOfType(rightType); - if (!allTypesAssignableToKind(rightType, ts.TypeFlags.NonPrimitive | ts.TypeFlags.InstantiableNonPrimitive) || + if (!allTypesAssignableToKind(rightType, TypeFlags.NonPrimitive | TypeFlags.InstantiableNonPrimitive) || rightTypeConstraint && ( - isTypeAssignableToKind(rightType, ts.TypeFlags.UnionOrIntersection) && !allTypesAssignableToKind(rightTypeConstraint, ts.TypeFlags.NonPrimitive | ts.TypeFlags.InstantiableNonPrimitive) || - !maybeTypeOfKind(rightTypeConstraint, ts.TypeFlags.NonPrimitive | ts.TypeFlags.InstantiableNonPrimitive | ts.TypeFlags.Object) + isTypeAssignableToKind(rightType, TypeFlags.UnionOrIntersection) && !allTypesAssignableToKind(rightTypeConstraint, TypeFlags.NonPrimitive | TypeFlags.InstantiableNonPrimitive) || + !maybeTypeOfKind(rightTypeConstraint, TypeFlags.NonPrimitive | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object) ) ) { - error(right, ts.Diagnostics.The_right_hand_side_of_an_in_expression_must_not_be_a_primitive); + error(right, Diagnostics.The_right_hand_side_of_an_in_expression_must_not_be_a_primitive); } 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); @@ -33436,10 +33666,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)) { @@ -33450,49 +33680,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); @@ -33500,17 +33730,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); @@ -33519,17 +33749,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); } @@ -33538,51 +33768,51 @@ 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. if (strictNullChecks && - !(getFalsyFlags(checkExpression(prop.objectAssignmentInitializer)) & ts.TypeFlags.Undefined)) { + !(getFalsyFlags(checkExpression(prop.objectAssignmentInitializer)) & TypeFlags.Undefined)) { sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined); } 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; } - 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; } @@ -33595,67 +33825,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() { @@ -33668,18 +33898,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; @@ -33695,7 +33925,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; @@ -33704,55 +33934,55 @@ 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) { - const parent = ts.walkUpParenthesizedExpressions(node.parent); - checkTestingKnownTruthyCallableOrAwaitableType(node.left, ts.isIfStatement(parent) ? parent.thenStatement : undefined); + if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) { + if (operator === SyntaxKind.AmpersandAmpersandToken) { + const parent = walkUpParenthesizedExpressions(node.parent); + checkTestingKnownTruthyCallableOrAwaitableType(node.left, 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); } @@ -33764,13 +33994,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)); @@ -33780,7 +34010,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; } @@ -33788,7 +34018,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 @@ -33797,27 +34027,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 { @@ -33829,37 +34059,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; } @@ -33867,38 +34097,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; @@ -33913,28 +34143,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; } @@ -33954,21 +34184,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)); @@ -33977,61 +34207,61 @@ 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"); } 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([removeDefinitelyFalsyTypes(leftType), rightType], ts.UnionReduction.Subtype) : + getUnionType([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); } @@ -34041,80 +34271,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); } @@ -34127,15 +34357,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 @@ -34144,18 +34374,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; @@ -34165,7 +34395,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; @@ -34173,7 +34403,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) { @@ -34194,23 +34424,23 @@ 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) { let typeName: string | undefined; switch (operatorToken.kind) { - case ts.SyntaxKind.EqualsEqualsEqualsToken: - case ts.SyntaxKind.EqualsEqualsToken: + case SyntaxKind.EqualsEqualsEqualsToken: + case SyntaxKind.EqualsEqualsToken: typeName = "false"; break; - case ts.SyntaxKind.ExclamationEqualsEqualsToken: - case ts.SyntaxKind.ExclamationEqualsToken: + case SyntaxKind.ExclamationEqualsEqualsToken: + case SyntaxKind.ExclamationEqualsToken: typeName = "true"; } @@ -34218,7 +34448,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return errorAndMaybeSuggestAwait( errNode, maybeMissingAwait, - ts.Diagnostics.This_condition_will_always_return_0_since_the_types_1_and_2_have_no_overlap, + Diagnostics.This_condition_will_always_return_0_since_the_types_1_and_2_have_no_overlap, typeName, leftStr, rightStr); } @@ -34226,7 +34456,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); @@ -34238,29 +34468,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); } } @@ -34291,10 +34521,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); 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); } } }); @@ -34302,37 +34532,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 { checkTruthinessExpression(node.condition); checkTestingKnownTruthyCallableOrAwaitableType(node.condition, 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); @@ -34340,19 +34570,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return isConstContext(node) || isTemplateLiteralContext(node) || someType(getContextualType(node) || 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; @@ -34368,7 +34598,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)) ? + const result = maybeTypeOfKind(type, TypeFlags.Literal) && isLiteralOfContextualType(type, instantiateContextualType(contextualType, node)) ? getRegularTypeOfLiteralType(type) : type; return result; } @@ -34381,7 +34611,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 && checkMode !== CheckMode.Normal) { return checkExpression(node, checkMode); } @@ -34401,38 +34631,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); } } @@ -34440,9 +34670,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; @@ -34455,68 +34685,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) : contextualType, node)); } - 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); } @@ -34524,15 +34754,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); @@ -34547,18 +34777,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) => { @@ -34569,7 +34799,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); } } @@ -34582,20 +34812,20 @@ 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 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; @@ -34604,7 +34834,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]; @@ -34612,19 +34842,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 { @@ -34640,30 +34870,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); @@ -34674,14 +34904,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; @@ -34693,34 +34923,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; @@ -34733,7 +34963,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; @@ -34752,8 +34982,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; @@ -34763,168 +34993,168 @@ 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.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.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); @@ -34933,39 +35163,39 @@ 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) { - const source = createMarkerType(symbol, typeParameter, modifiers === ts.ModifierFlags.Out ? markerSubType : markerSuperType); - const target = createMarkerType(symbol, typeParameter, modifiers === ts.ModifierFlags.Out ? markerSuperType : markerSubType); + else if (modifiers === ModifierFlags.In || modifiers === ModifierFlags.Out) { + const source = createMarkerType(symbol, typeParameter, modifiers === ModifierFlags.Out ? markerSubType : markerSuperType); + const target = createMarkerType(symbol, typeParameter, modifiers === ModifierFlags.Out ? markerSuperType : markerSubType); 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; } } } } - 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 @@ -34973,45 +35203,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 && 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 && 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; } @@ -35024,17 +35254,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, @@ -35046,29 +35276,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; } @@ -35076,22 +35306,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, @@ -35102,41 +35332,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) { - checkGrammarIndexSignature(node as ts.SignatureDeclaration); + if (node.kind === SyntaxKind.IndexSignature) { + checkGrammarIndexSignature(node as SignatureDeclaration); } // 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) { @@ -35147,24 +35377,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. @@ -35173,65 +35403,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; } @@ -35239,24 +35469,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); @@ -35280,19 +35510,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; @@ -35301,27 +35531,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); @@ -35330,9 +35560,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) { @@ -35345,8 +35575,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)); @@ -35362,14 +35592,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); @@ -35377,19 +35607,19 @@ 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); @@ -35397,44 +35627,44 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { 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 @@ -35443,7 +35673,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) { @@ -35451,7 +35681,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; } @@ -35459,27 +35689,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: @@ -35488,22 +35718,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; } @@ -35515,36 +35745,36 @@ 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) { + function checkAccessorDeclaration(node: AccessorDeclaration) { addLazyDiagnostic(checkAccessorDeclarationDiagnostics); checkSourceElement(node.body); setNodeLinksForPrivateIdentifierScope(node); @@ -35555,17 +35785,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); } @@ -35573,48 +35803,48 @@ 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 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]); @@ -35627,30 +35857,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) { @@ -35663,22 +35893,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } const symbol = getNodeLinks(node).resolvedSymbol; if (symbol) { - if (ts.some(symbol.declarations, d => isTypeDeclaration(d) && !!(d.flags & ts.NodeFlags.Deprecated))) { + if (some(symbol.declarations, d => isTypeDeclaration(d) && !!(d.flags & NodeFlags.Deprecated))) { addDeprecatedSuggestion( getDeprecatedSuggestionNode(node), symbol.declarations!, symbol.escapedName as string ); } - if (type.flags & ts.TypeFlags.Enum && symbol.flags & ts.SymbolFlags.EnumMember) { - error(node, ts.Diagnostics.Enum_type_0_has_members_with_initializers_that_are_not_literals, typeToString(type)); + if (type.flags & TypeFlags.Enum && symbol.flags & SymbolFlags.EnumMember) { + error(node, Diagnostics.Enum_type_0_has_members_with_initializers_that_are_not_literals, typeToString(type)); } } } } - 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; @@ -35686,12 +35916,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() { @@ -35702,100 +35932,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); @@ -35805,39 +36035,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); @@ -35846,12 +36076,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); } } } @@ -35859,7 +36089,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); @@ -35868,14 +36098,14 @@ 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.getEmitModuleResolutionKind(compilerOptions) !== ts.ModuleResolutionKind.Node16 && ts.getEmitModuleResolutionKind(compilerOptions) !== ts.ModuleResolutionKind.NodeNext) { - grammarErrorOnNode(node.assertions.assertClause, ts.Diagnostics.Resolution_modes_are_only_supported_when_moduleResolution_is_node16_or_nodenext); + if (getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Node16 && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeNext) { + grammarErrorOnNode(node.assertions.assertClause, Diagnostics.Resolution_modes_are_only_supported_when_moduleResolution_is_node16_or_nodenext); } } } @@ -35883,49 +36113,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 @@ -35935,62 +36165,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; } @@ -36002,49 +36232,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); } } } @@ -36052,12 +36282,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 @@ -36069,18 +36299,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) { @@ -36096,7 +36326,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (bodyIsPresent) { if (!bodyDeclaration) { - bodyDeclaration = node as ts.FunctionLikeDeclaration; + bodyDeclaration = node as FunctionLikeDeclaration; } } else { @@ -36106,37 +36336,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 ); } @@ -36145,7 +36375,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); } @@ -36160,9 +36390,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; } @@ -36171,11 +36401,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) { @@ -36189,7 +36419,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; } @@ -36198,10 +36428,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 { @@ -36224,65 +36454,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) @@ -36291,12 +36521,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); } @@ -36306,7 +36536,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 @@ -36321,70 +36551,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(type, ts.TypeFlags.Primitive | ts.TypeFlags.Never)) { + if (allTypesAssignableToKind(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); } /** @@ -36395,7 +36625,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); @@ -36405,24 +36635,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(type, ts.TypeFlags.Primitive | ts.TypeFlags.Never)) { + function isThenableType(type: Type): boolean { + if (allTypesAssignableToKind(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; } @@ -36432,13 +36662,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 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 @@ -36461,7 +36691,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const baseConstraint = getBaseConstraintOfType(type); // Only instantiate `Awaited` if `T` 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) || isThenableType(baseConstraint)) { + if (!baseConstraint || (baseConstraint.flags & TypeFlags.AnyOrUnknown) || isEmptyObjectType(baseConstraint) || isThenableType(baseConstraint)) { // Nothing to do if `Awaited` doesn't exist const awaitedSymbol = getGlobalAwaitedSymbol(/*reportErrors*/ true); if (awaitedSymbol) { @@ -36472,7 +36702,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; } @@ -36486,7 +36716,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); } @@ -36496,7 +36726,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; } @@ -36507,18 +36737,18 @@ 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) { - const mapper = errorNode ? (constituentType: ts.Type) => getAwaitedTypeNoAlias(constituentType, errorNode, diagnosticMessage, arg0) : getAwaitedTypeNoAlias; + if (type.flags & TypeFlags.Union) { + const mapper = errorNode ? (constituentType: Type) => getAwaitedTypeNoAlias(constituentType, errorNode, diagnosticMessage, arg0) : getAwaitedTypeNoAlias; return typeAsAwaitable.awaitedTypeOfType = mapType(type, mapper); } - 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) { @@ -36556,7 +36786,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; } @@ -36591,13 +36821,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; } @@ -36617,7 +36847,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 @@ -36644,7 +36874,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; } @@ -36652,7 +36882,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; } } @@ -36664,20 +36894,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; } @@ -36686,64 +36916,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( @@ -36757,17 +36987,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)) { @@ -36775,13 +37005,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))); } } } @@ -36794,43 +37024,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); @@ -36846,8 +37076,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; } @@ -36859,40 +37089,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 { if (!node.decorators) { return; } // skip this check for nodes that cannot have decorators. These should have already had an error reported by // checkGrammarDecorators. - if (!ts.nodeCanBeDecorated(node, node.parent, node.parent.parent)) { + if (!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 = node.decorators[0]; - 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 as ts.ClassDeclaration); + case SyntaxKind.ClassDeclaration: + const constructor = getFirstConstructorWithBody(node as ClassDeclaration); if (constructor) { for (const parameter of constructor.parameters) { markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter)); @@ -36900,27 +37130,27 @@ 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 as ts.AccessorDeclaration), otherKind); - markDecoratorMedataDataTypeNodeAsReferenced(getAnnotatedAccessorTypeNode(node as ts.AccessorDeclaration) || otherAccessor && getAnnotatedAccessorTypeNode(otherAccessor)); + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; + const otherAccessor = getDeclarationOfKind(getSymbolOfNode(node as AccessorDeclaration), otherKind); + markDecoratorMedataDataTypeNodeAsReferenced(getAnnotatedAccessorTypeNode(node as AccessorDeclaration) || otherAccessor && getAnnotatedAccessorTypeNode(otherAccessor)); break; - case ts.SyntaxKind.MethodDeclaration: - for (const parameter of (node as ts.FunctionLikeDeclaration).parameters) { + case SyntaxKind.MethodDeclaration: + for (const parameter of (node as FunctionLikeDeclaration).parameters) { markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter)); } - markDecoratorMedataDataTypeNodeAsReferenced(ts.getEffectiveReturnTypeNode(node as ts.FunctionLikeDeclaration)); + markDecoratorMedataDataTypeNodeAsReferenced(getEffectiveReturnTypeNode(node as FunctionLikeDeclaration)); break; - case ts.SyntaxKind.PropertyDeclaration: - markDecoratorMedataDataTypeNodeAsReferenced(ts.getEffectiveTypeAnnotationNode(node as ts.ParameterDeclaration)); + case SyntaxKind.PropertyDeclaration: + markDecoratorMedataDataTypeNodeAsReferenced(getEffectiveTypeAnnotationNode(node as ParameterDeclaration)); break; - case ts.SyntaxKind.Parameter: - markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(node as ts.ParameterDeclaration)); - const containingSignature = (node as ts.ParameterDeclaration).parent; + case SyntaxKind.Parameter: + markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(node as ParameterDeclaration)); + const containingSignature = (node as ParameterDeclaration).parent; for (const parameter of containingSignature.parameters) { markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter)); } @@ -36928,10 +37158,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - ts.forEach(node.decorators, checkDecorator); + forEach(node.decorators, checkDecorator); } - function checkFunctionDeclaration(node: ts.FunctionDeclaration): void { + function checkFunctionDeclaration(node: FunctionDeclaration): void { addLazyDiagnostic(checkFunctionDeclarationDiagnostics); function checkFunctionDeclarationDiagnostics() { @@ -36941,107 +37171,107 @@ 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 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); @@ -37059,7 +37289,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) { @@ -37072,29 +37302,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. @@ -37109,7 +37339,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 = []; @@ -37122,151 +37352,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 = 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) { @@ -37277,13 +37507,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 } @@ -37292,19 +37522,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; } @@ -37317,31 +37547,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); } } } @@ -37351,96 +37581,96 @@ 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))); } } }); } - 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); } }); } @@ -37450,36 +37680,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; } @@ -37488,15 +37718,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; } @@ -37504,15 +37734,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; } @@ -37520,9 +37750,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; } @@ -37531,109 +37761,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. @@ -37660,28 +37890,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; @@ -37689,10 +37919,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 @@ -37700,21 +37930,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); } @@ -37727,19 +37957,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 (node.initializer) { checkExpressionCached(node.initializer); } } - if (ts.isBindingElement(node)) { - if (ts.isObjectBindingPattern(node.parent) && node.dotDotDotToken && languageVersion < ts.ScriptTarget.ES2018) { - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.Rest); + if (isBindingElement(node)) { + 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); } @@ -37748,35 +37978,35 @@ 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 (node.initializer && ts.isParameterDeclaration(node) && 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 (node.initializer && isParameterDeclaration(node) && 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 = node.initializer && node.parent.parent.kind !== ts.SyntaxKind.ForInStatement; + if (isBindingPattern(node.name)) { + const needCheckInitializer = node.initializer && node.parent.parent.kind !== SyntaxKind.ForInStatement; const needCheckWidenedType = node.name.elements.length === 0; if (needCheckInitializer || needCheckWidenedType) { // Don't validate for-in initializer as it is already an error @@ -37792,7 +38022,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) { @@ -37804,7 +38034,7 @@ 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)) { + if (symbol.flags & SymbolFlags.Alias && isVariableDeclarationInitializedToBareOrAccessedRequire(node)) { checkAliasSymbol(node); return; } @@ -37813,19 +38043,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.getEffectiveInitializer(node); + const initializer = 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)); } } } @@ -37836,32 +38066,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 (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, @@ -37870,89 +38100,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); checkTruthinessExpression(node.expression); checkTestingKnownTruthyCallableOrAwaitableType(node.expression, 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, body?: ts.Statement | ts.Expression) { + function checkTestingKnownTruthyCallableOrAwaitableType(condExpr: Expression, 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 = checkTruthinessExpression(location); - const isPropertyExpressionCast = ts.isPropertyAccessExpression(location) && isTypeAssertion(location.expression); + const isPropertyExpressionCast = isPropertyAccessExpression(location) && isTypeAssertion(location.expression); if (getFalsyFlags(type) || isPropertyExpressionCast) return; // While it technically should be invalid for any known-truthy value @@ -37960,63 +38190,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)) { + if (isIdentifier(expr)) { 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; } @@ -38026,20 +38256,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; @@ -38049,7 +38279,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function checkDoStatement(node: ts.DoStatement) { + function checkDoStatement(node: DoStatement) { // Grammar checking checkGrammarStatementInAmbientContext(node); @@ -38057,7 +38287,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); @@ -38065,28 +38295,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); @@ -38101,25 +38331,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 @@ -38127,7 +38357,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 { @@ -38135,7 +38365,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. @@ -38145,8 +38375,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 @@ -38164,7 +38394,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkForInStatement(node: ts.ForInStatement) { + function checkForInStatement(node: ForInStatement) { // Grammar checking checkGrammarForInOrForOfStatement(node); @@ -38174,10 +38404,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); } @@ -38188,25 +38418,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); @@ -38215,8 +38445,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]; @@ -38224,12 +38454,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; } @@ -38241,14 +38471,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); @@ -38261,10 +38491,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); @@ -38284,31 +38514,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; } } @@ -38335,39 +38565,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": @@ -38387,7 +38617,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; } @@ -38396,7 +38626,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. @@ -38405,9 +38635,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) { @@ -38426,10 +38656,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; @@ -38437,9 +38667,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( @@ -38450,12 +38680,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; } /** @@ -38479,12 +38709,12 @@ 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)) { + if (!(type.flags & TypeFlags.Union)) { const iterationTypes = getIterationTypesOfIterableWorker(type, use, errorNode); if (iterationTypes === noIterationTypes) { if (errorNode) { @@ -38499,8 +38729,8 @@ 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) { + let allIterationTypes: IterationTypes[] | undefined; + for (const constituent of (type as UnionType).types) { const iterationTypes = getIterationTypesOfIterableWorker(constituent, use, errorNode); if (iterationTypes === noIterationTypes) { if (errorNode) { @@ -38510,7 +38740,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } else { - allIterationTypes = ts.append(allIterationTypes, iterationTypes); + allIterationTypes = append(allIterationTypes, iterationTypes); } } @@ -38519,7 +38749,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; @@ -38543,7 +38773,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) { + function getIterationTypesOfIterableWorker(type: Type, use: IterationUse, errorNode: Node | undefined) { if (isTypeAny(type)) { return anyIterationTypes; } @@ -38607,11 +38837,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); @@ -38630,15 +38860,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 @@ -38651,15 +38881,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; } /** @@ -38672,27 +38902,27 @@ 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) { + function getIterationTypesOfIterableSlow(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined) { 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 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 setCachedIterationTypes(type, resolver.iterableCacheKey, noIterationTypes); } - const iteratorType = getIntersectionType(ts.map(signatures, getReturnTypeOfSignature)); + const iteratorType = getIntersectionType(map(signatures, getReturnTypeOfSignature)); const iterationTypes = getIterationTypesOfIterator(iteratorType, resolver, errorNode) ?? noIterationTypes; return setCachedIterationTypes(type, resolver.iterableCacheKey, iterationTypes); } - function reportTypeNotIterableError(errorNode: ts.Node, type: ts.Type, allowAsyncIterables: boolean): void { + function reportTypeNotIterableError(errorNode: Node, type: Type, allowAsyncIterables: boolean): void { 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; errorAndMaybeSuggestAwait(errorNode, !!getAwaitedTypeOfPromise(type), message, typeToString(type)); } @@ -38702,7 +38932,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) { + function getIterationTypesOfIterator(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined) { if (isTypeAny(type)) { return anyIterationTypes; } @@ -38721,7 +38951,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); } @@ -38737,7 +38967,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` @@ -38745,7 +38975,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. @@ -38757,25 +38987,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); } @@ -38786,7 +39016,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; } @@ -38799,20 +39029,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); @@ -38832,15 +39062,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): ts.IterationTypes | undefined { - const method = getPropertyOfType(type, methodName as ts.__String); + function getIterationTypesOfMethod(type: Type, resolver: IterationTypesResolver, methodName: "next" | "return" | "throw", errorNode: Node | 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; @@ -38850,7 +39080,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" @@ -38871,11 +39101,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!), @@ -38884,19 +39114,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") { @@ -38906,12 +39136,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); @@ -38920,11 +39150,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { 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); @@ -38940,7 +39170,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) { + function getIterationTypesOfIteratorSlow(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined) { const iterationTypes = combineIterationTypes([ getIterationTypesOfMethod(type, resolver, "next", errorNode), getIterationTypesOfMethod(type, resolver, "return", errorNode), @@ -38954,7 +39184,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; } @@ -38963,7 +39193,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; } @@ -38974,62 +39204,62 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { getIterationTypesOfIterator(type, resolver, /*errorNode*/ 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); return isGenerator ? getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, isAsync) || errorType : 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 @@ -39039,60 +39269,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 @@ -39116,15 +39346,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; @@ -39135,11 +39365,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); } } @@ -39148,7 +39378,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkTryStatement(node: ts.TryStatement) { + function checkTryStatement(node: TryStatement) { // Grammar checking checkGrammarStatementInAmbientContext(node); @@ -39158,23 +39388,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); } }); } @@ -39189,24 +39419,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)); } } } @@ -39217,34 +39447,34 @@ 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 localPropDeclaration = declaration && declaration.kind === ts.SyntaxKind.BinaryExpression || - name && name.kind === ts.SyntaxKind.ComputedPropertyName || getParentOfSymbol(prop) === type.symbol ? declaration : undefined; + const interfaceDeclaration = getObjectFlags(type) & ObjectFlags.Interface ? getDeclarationOfKind(type.symbol, SyntaxKind.InterfaceDeclaration) : undefined; + const localPropDeclaration = declaration && declaration.kind === SyntaxKind.BinaryExpression || + name && name.kind === SyntaxKind.ComputedPropertyName || getParentOfSymbol(prop) === type.symbol ? declaration : undefined; for (const info of indexInfos) { const localIndexDeclaration = info.declaration && getParentOfSymbol(getSymbolOfNode(info.declaration)) === type.symbol ? info.declaration : undefined; // We check only when (a) the property is declared in the containing type, or (b) the applicable index signature is declared // 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)) { - error(errorNode, ts.Diagnostics.Property_0_of_type_1_is_not_assignable_to_2_index_type_3, + error(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)); } } } - 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; @@ -39253,15 +39483,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) { @@ -39282,49 +39512,49 @@ 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 }, index) => { - if (excludedParameters.has(index) || ts.isIdentifier(name) && parameters.has(name.escapedText)) { + forEach(jsdocParameters, ({ name }, 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 { - 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)); } }); } @@ -39333,7 +39563,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++) { @@ -39344,18 +39574,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)); } } }; @@ -39363,25 +39593,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; } @@ -39394,19 +39624,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) { @@ -39429,7 +39659,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 @@ -39451,58 +39681,58 @@ 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) { - if (ts.some(node.decorators) && ts.some(node.members, p => ts.hasStaticModifier(p) && ts.isPrivateIdentifierClassElementDeclaration(p))) { - grammarErrorOnNode(node.decorators[0], ts.Diagnostics.Class_decorators_can_t_be_used_with_static_private_identifier_Consider_removing_the_experimental_decorator); + function checkClassDeclaration(node: ClassDeclaration) { + if (some(node.decorators) && some(node.members, p => hasStaticModifier(p) && isPrivateIdentifierClassElementDeclaration(p))) { + grammarErrorOnNode(node.decorators[0], 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); } @@ -39515,8 +39745,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; @@ -39525,31 +39755,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); @@ -39559,11 +39789,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)); @@ -39577,41 +39807,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, @@ -39643,21 +39873,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( @@ -39667,11 +39897,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, ); } @@ -39685,23 +39915,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); @@ -39715,43 +39945,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; } } } @@ -39761,21 +39991,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); @@ -39783,9 +40013,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) @@ -39802,14 +40032,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)); } } } @@ -39821,26 +40051,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, @@ -39850,25 +40080,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. @@ -39888,7 +40118,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); @@ -39896,21 +40126,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.) @@ -39923,61 +40153,61 @@ 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 (baseDeclarationFlags & ts.ModifierFlags.Abstract && !(base.valueDeclaration && ts.isPropertyDeclaration(base.valueDeclaration) && base.valueDeclaration.initializer) - || base.valueDeclaration && base.valueDeclaration.parent.kind === ts.SyntaxKind.InterfaceDeclaration - || derived.valueDeclaration && ts.isBinaryExpression(derived.valueDeclaration)) { + if (baseDeclarationFlags & ModifierFlags.Abstract && !(base.valueDeclaration && isPropertyDeclaration(base.valueDeclaration) && base.valueDeclaration.initializer) + || base.valueDeclaration && base.valueDeclaration.parent.kind === SyntaxKind.InterfaceDeclaration + || derived.valueDeclaration && isBinaryExpression(derived.valueDeclaration)) { // when the base property is abstract or from an interface, base/derived flags don't need to match // 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)); } } } @@ -39986,33 +40216,33 @@ 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 getNonInterhitedProperties(type: ts.InterfaceType, baseTypes: ts.BaseType[], properties: ts.Symbol[]) { - if (!ts.length(baseTypes)) { + function getNonInterhitedProperties(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); }); @@ -40026,18 +40256,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; @@ -40057,9 +40287,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)); } } } @@ -40068,22 +40298,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 || getFalsyFlags(type) & ts.TypeFlags.Undefined)) { + if (!(type.flags & TypeFlags.AnyOrUnknown || getFalsyFlags(type) & TypeFlags.Undefined)) { 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)); } } } @@ -40091,23 +40321,23 @@ 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 (!(getFalsyFlags(flowType) & ts.TypeFlags.Undefined)) { + if (!(getFalsyFlags(flowType) & TypeFlags.Undefined)) { return true; } } @@ -40115,53 +40345,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 !(getFalsyFlags(flowType) & ts.TypeFlags.Undefined); + return !(getFalsyFlags(flowType) & TypeFlags.Undefined); } - 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); @@ -40169,15 +40399,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 { @@ -40186,10 +40416,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); @@ -40199,14 +40429,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) { @@ -40214,7 +40444,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) && getEnumKind(getSymbolOfNode(member.parent)) === ts.EnumKind.Numeric) { + if (member.parent.flags & NodeFlags.Ambient && !isEnumConst(member.parent) && getEnumKind(getSymbolOfNode(member.parent)) === EnumKind.Numeric) { return undefined; } // If the member declaration specifies no value, the member is considered a constant enum member. @@ -40224,37 +40454,37 @@ 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 { + function computeConstantValue(member: EnumMember): string | number | undefined { const enumKind = getEnumKind(getSymbolOfNode(member.parent)); - const isConstEnum = ts.isEnumConst(member.parent); + const isConstEnum = isEnumConst(member.parent); const initializer = member.initializer!; - const value = enumKind === ts.EnumKind.Literal && !isLiteralEnumMember(member) ? undefined : evaluate(initializer); + const value = enumKind === EnumKind.Literal && !isLiteralEnumMember(member) ? undefined : evaluate(initializer); 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 (enumKind === ts.EnumKind.Literal) { - error(initializer, ts.Diagnostics.Computed_values_are_not_permitted_in_an_enum_with_string_valued_members); + else if (enumKind === EnumKind.Literal) { + error(initializer, Diagnostics.Computed_values_are_not_permitted_in_an_enum_with_string_valued_members); return 0; } else if (isConstEnum) { - error(initializer, ts.Diagnostics.const_enum_member_initializers_can_only_contain_literal_values_and_other_computed_enum_values); + error(initializer, Diagnostics.const_enum_member_initializers_can_only_contain_literal_values_and_other_computed_enum_values); } - 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 { // Only here do we need to check that the initializer is assignable to the enum type. const source = checkExpression(initializer); - if (!isTypeAssignableToKind(source, ts.TypeFlags.NumberLike)) { - error(initializer, ts.Diagnostics.Only_numeric_enums_can_have_computed_members_but_this_expression_has_type_0_If_you_do_not_need_exhaustiveness_checks_consider_using_an_object_literal_instead, typeToString(source)); + if (!isTypeAssignableToKind(source, TypeFlags.NumberLike)) { + error(initializer, Diagnostics.Only_numeric_enums_can_have_computed_members_but_this_expression_has_type_0_If_you_do_not_need_exhaustiveness_checks_consider_using_an_object_literal_instead, typeToString(source)); } else { checkTypeAssignableTo(source, getDeclaredTypeOfSymbol(getSymbolOfNode(member.parent)), initializer, /*headMessage*/ undefined); @@ -40262,66 +40492,66 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return value; - function evaluate(expr: ts.Expression): string | number | undefined { + function evaluate(expr: Expression): string | number | undefined { switch (expr.kind) { - case ts.SyntaxKind.PrefixUnaryExpression: - const value = evaluate((expr as ts.PrefixUnaryExpression).operand); + case SyntaxKind.PrefixUnaryExpression: + const value = evaluate((expr as PrefixUnaryExpression).operand); 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); - const right = evaluate((expr as ts.BinaryExpression).right); + case SyntaxKind.BinaryExpression: + const left = evaluate((expr as BinaryExpression).left); + const right = evaluate((expr as BinaryExpression).right); 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; - } - } - else if (typeof left === "string" && typeof right === "string" && (expr as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.PlusToken) { + 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 right === "string" && (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.NumericLiteral: - checkGrammarNumericLiteral(expr as ts.NumericLiteral); - return +(expr as ts.NumericLiteral).text; - case ts.SyntaxKind.ParenthesizedExpression: - return evaluate((expr as ts.ParenthesizedExpression).expression); - case ts.SyntaxKind.Identifier: - const identifier = expr as ts.Identifier; - if (ts.isInfinityOrNaNString(identifier.escapedText)) { + case SyntaxKind.StringLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + return (expr as StringLiteralLike).text; + case SyntaxKind.NumericLiteral: + checkGrammarNumericLiteral(expr as NumericLiteral); + return +(expr as NumericLiteral).text; + case SyntaxKind.ParenthesizedExpression: + return evaluate((expr as ParenthesizedExpression).expression); + case SyntaxKind.Identifier: + const identifier = expr as Identifier; + if (isInfinityOrNaNString(identifier.escapedText)) { return +(identifier.escapedText); } - return ts.nodeIsMissing(expr) ? 0 : evaluateEnumMember(expr, getSymbolOfNode(member.parent), identifier.escapedText); - case ts.SyntaxKind.ElementAccessExpression: - case ts.SyntaxKind.PropertyAccessExpression: + return nodeIsMissing(expr) ? 0 : evaluateEnumMember(expr, getSymbolOfNode(member.parent), identifier.escapedText); + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.PropertyAccessExpression: if (isConstantMemberAccess(expr)) { const type = getTypeOfExpression(expr.expression); - if (type.symbol && type.symbol.flags & ts.SymbolFlags.Enum) { - let name: ts.__String; - if (expr.kind === ts.SyntaxKind.PropertyAccessExpression) { + if (type.symbol && type.symbol.flags & SymbolFlags.Enum) { + let name: __String; + if (expr.kind === SyntaxKind.PropertyAccessExpression) { name = expr.name.escapedText; } else { - name = ts.escapeLeadingUnderscores(ts.cast(expr.argumentExpression, ts.isLiteralExpression).text); + name = escapeLeadingUnderscores(cast(expr.argumentExpression, isLiteralExpression).text); } return evaluateEnumMember(expr, type.symbol, name); } @@ -40331,42 +40561,42 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function evaluateEnumMember(expr: ts.Expression, enumSymbol: ts.Symbol, name: ts.__String) { + function evaluateEnumMember(expr: Expression, enumSymbol: Symbol, name: __String) { const memberSymbol = enumSymbol.exports!.get(name); if (memberSymbol) { const declaration = memberSymbol.valueDeclaration; if (declaration !== member) { - if (declaration && isBlockScopedNameDeclaredBeforeUse(declaration, member) && ts.isEnumDeclaration(declaration.parent)) { - return getEnumMemberValue(declaration as ts.EnumMember); + if (declaration && isBlockScopedNameDeclaredBeforeUse(declaration, member) && isEnumDeclaration(declaration.parent)) { + return getEnumMemberValue(declaration as EnumMember); } - 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; } else { - error(expr, ts.Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(memberSymbol)); + error(expr, Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(memberSymbol)); } } return undefined; } } - function isConstantMemberAccess(node: ts.Expression): node is ts.AccessExpression { + function isConstantMemberAccess(node: Expression): node is AccessExpression { const type = getTypeOfExpression(node); if (type === errorType) { return false; } - return node.kind === ts.SyntaxKind.Identifier || - node.kind === ts.SyntaxKind.PropertyAccessExpression && isConstantMemberAccess((node as ts.PropertyAccessExpression).expression) || - node.kind === ts.SyntaxKind.ElementAccessExpression && isConstantMemberAccess((node as ts.ElementAccessExpression).expression) && - ts.isStringLiteralLike((node as ts.ElementAccessExpression).argumentExpression); + return node.kind === SyntaxKind.Identifier || + node.kind === SyntaxKind.PropertyAccessExpression && isConstantMemberAccess((node as PropertyAccessExpression).expression) || + node.kind === SyntaxKind.ElementAccessExpression && isConstantMemberAccess((node as ElementAccessExpression).expression) && + isStringLiteralLike((node as ElementAccessExpression).argumentExpression); } - 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); @@ -40383,26 +40613,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; } @@ -40410,7 +40640,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; @@ -40420,19 +40650,19 @@ 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); } } - 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; } } @@ -40440,9 +40670,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); } @@ -40454,10 +40684,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); } } @@ -40466,28 +40696,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); } @@ -40495,38 +40725,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); @@ -40535,46 +40765,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); @@ -40582,12 +40812,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; } @@ -40597,54 +40827,54 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // this is done it two steps // 1. quick check - if symbol for node is not merged - this is local symbol to this augmentation - report error // 2. main check - report error if value declaration of the parent symbol is module augmentation) - let reportError = !(symbol.flags & ts.SymbolFlags.Transient); + let reportError = !(symbol.flags & SymbolFlags.Transient); if (!reportError) { // symbol should not originate in augmentation - reportError = !!symbol.parent?.declarations && ts.isExternalModuleAugmentation(symbol.parent.declarations[0]); + reportError = !!symbol.parent?.declarations && isExternalModuleAugmentation(symbol.parent.declarations[0]); } } break; } } - 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)) { @@ -40652,16 +40882,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; @@ -40669,7 +40899,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) { + function checkAliasSymbol(node: ImportEqualsDeclaration | VariableDeclaration | ImportClause | NamespaceImport | ImportSpecifier | ExportSpecifier | NamespaceExport) { let symbol = getSymbolOfNode(node); const target = resolveAlias(symbol); @@ -40682,52 +40912,52 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // in order to prevent collisions with declarations that were exported from the current module (they still contribute to local names). symbol = getMergedSymbol(symbol.exportSymbol || symbol); 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 (target.flags & 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 = !(target.flags & ts.SymbolFlags.Value); + const isType = !(target.flags & 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, @@ -40740,7 +40970,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); @@ -40749,21 +40979,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; @@ -40781,57 +41011,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_modes_are_only_supported_when_moduleResolution_is_node16_or_nodenext); + if (getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Node16 && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeNext) { + return grammarErrorOnNode(declaration.assertClause, Diagnostics.Resolution_modes_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; @@ -40840,17 +41070,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); } } } @@ -40859,70 +41089,70 @@ 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) { - if (target.flags & ts.SymbolFlags.Value) { + if (target.flags & 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 (target.flags & ts.SymbolFlags.Type) { - checkTypeNameIsReserved(node.name, ts.Diagnostics.Import_name_cannot_be_0); + if (target.flags & 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 { @@ -40930,23 +41160,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); } } } @@ -40954,40 +41184,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) && @@ -40995,94 +41225,94 @@ 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 { markExportAsReferenced(node); - const target = symbol && (symbol.flags & ts.SymbolFlags.Alias ? resolveAlias(symbol) : symbol); - if (!target || target === unknownSymbol || target.flags & ts.SymbolFlags.Value) { + const target = symbol && (symbol.flags & SymbolFlags.Alias ? resolveAlias(symbol) : symbol); + if (!target || target === unknownSymbol || target.flags & 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 (target === unknownSymbol || target.flags & ts.SymbolFlags.Value) { + const target = sym.flags & SymbolFlags.Alias ? resolveAlias(sym) : sym; + if (target === unknownSymbol || target.flags & SymbolFlags.Value) { // However if it is a value, we need to check it's being used correctly checkExpressionCached(node.expression); } @@ -41091,8 +41321,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 { @@ -41101,35 +41331,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 @@ -41141,11 +41371,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; @@ -41154,7 +41384,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))); } } } @@ -41165,13 +41395,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; @@ -41181,9 +41411,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkSourceElementWorker(node: ts.Node): void { - if (ts.isInJSFile(node)) { - ts.forEach((node as ts.JSDocContainer).jsDoc, ({ tags }) => ts.forEach(tags, checkSourceElement)); + function checkSourceElementWorker(node: Node): void { + if (isInJSFile(node)) { + forEach((node as JSDocContainer).jsDoc, ({ tags }) => forEach(tags, checkSourceElement)); } const kind = node.kind; @@ -41191,231 +41421,231 @@ 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.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.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 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. @@ -41425,16 +41655,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); @@ -41449,72 +41679,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); - ts.performance.mark("beforeCheck"); + function checkSourceFile(node: SourceFile) { + tracing?.push(tracing.Phase.Check, "checkSourceFile", { path: node.path }, /*separateBeginAndEnd*/ true); + mark("beforeCheck"); checkSourceFileWorker(node); - ts.performance.mark("afterCheck"); - ts.performance.measure("Check", "beforeCheck", "afterCheck"); - ts.tracing?.pop(); + mark("afterCheck"); + measure("Check", "beforeCheck", "afterCheck"); + tracing?.pop(); } function unusedIsError(kind: UnusedKind, isAmbient: boolean): boolean { @@ -41527,36 +41757,36 @@ 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); + clear(potentialThisCollisions); + clear(potentialNewTargetCollisions); + clear(potentialWeakMapSetCollisions); + clear(potentialReflectCollisions); - ts.forEach(node.statements, checkSourceElement); + forEach(node.statements, checkSourceElement); checkSourceElement(node.endOfFileToken); checkDeferredNodes(node); - if (ts.isExternalOrCommonJsModule(node)) { + if (isExternalOrCommonJsModule(node)) { registerForUnusedIdentifiersCheck(node); } @@ -41564,49 +41794,49 @@ 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); } }); } }); - 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 @@ -41627,7 +41857,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) @@ -41640,7 +41870,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 @@ -41655,14 +41885,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; @@ -41670,29 +41900,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() { @@ -41702,17 +41932,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); } @@ -41720,29 +41950,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; } @@ -41756,8 +41986,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 @@ -41768,7 +41998,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); @@ -41776,11 +42006,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); } }); @@ -41788,55 +42018,55 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function isTypeDeclarationName(name: ts.Node): boolean { - return name.kind === ts.SyntaxKind.Identifier && + function isTypeDeclarationName(name: Node): boolean { + return name.kind === SyntaxKind.Identifier && isTypeDeclaration(name.parent) && - ts.getNameOfDeclaration(name.parent) === name; + getNameOfDeclaration(name.parent) === name; } - function isTypeDeclaration(node: ts.Node): node is ts.TypeParameterDeclaration | ts.ClassDeclaration | ts.InterfaceDeclaration | ts.TypeAliasDeclaration | ts.JSDocTypedefTag | ts.JSDocCallbackTag | ts.JSDocEnumTag | ts.EnumDeclaration | ts.ImportClause | ts.ImportSpecifier | ts.ExportSpecifier { + function isTypeDeclaration(node: Node): node is TypeParameterDeclaration | ClassDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag | EnumDeclaration | ImportClause | ImportSpecifier | ExportSpecifier { switch (node.kind) { - case ts.SyntaxKind.TypeParameter: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.JSDocTypedefTag: - case ts.SyntaxKind.JSDocCallbackTag: - case ts.SyntaxKind.JSDocEnumTag: + case SyntaxKind.TypeParameter: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JSDocCallbackTag: + case SyntaxKind.JSDocEnumTag: return true; - case ts.SyntaxKind.ImportClause: - return (node as ts.ImportClause).isTypeOnly; - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.ExportSpecifier: - return (node as ts.ImportSpecifier | ts.ExportSpecifier).parent.parent.isTypeOnly; + case SyntaxKind.ImportClause: + return (node as ImportClause).isTypeOnly; + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ExportSpecifier: + return (node as ImportSpecifier | ExportSpecifier).parent.parent.isTypeOnly; default: return false; } } // 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; } @@ -41844,12 +42074,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"; } @@ -41857,65 +42087,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; @@ -41923,22 +42153,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); @@ -41947,95 +42177,95 @@ 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, getSymbolOfNode(container)); } } 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); } 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; @@ -42049,35 +42279,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, container?: ts.Symbol): ts.Symbol | undefined { - if (ts.isEntityName(name)) { + function resolveJSDocMemberName(name: EntityName | JSDocMemberName, 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*/ false, /*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*/ false, /*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); - const right = ts.isIdentifier(name) ? name.escapedText : name.right.escapedText; + const left = isIdentifier(name) ? container : resolveJSDocMemberName(name.left); + 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; } @@ -42085,30 +42315,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; } @@ -42116,8 +42346,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; @@ -42125,145 +42355,145 @@ 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; } @@ -42278,7 +42508,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; @@ -42292,11 +42522,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); @@ -42304,7 +42534,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); } @@ -42317,31 +42547,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; @@ -42354,15 +42584,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)); } @@ -42371,39 +42601,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); } @@ -42412,29 +42642,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; } @@ -42443,22 +42673,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; } @@ -42473,26 +42703,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 && !!(s.flags & ts.SymbolFlags.Value); + return s && !!(s.flags & 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. @@ -42500,26 +42730,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); } } } @@ -42527,16 +42757,16 @@ 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 = getReferencedValueSymbol(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)) { + if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !getTypeOnlyAliasDeclaration(symbol)) { return getDeclarationOfAliasSymbol(symbol); } } @@ -42544,24 +42774,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 @@ -42577,11 +42807,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; @@ -42596,9 +42826,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)) { @@ -42612,8 +42842,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) { @@ -42624,42 +42854,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); - case ts.SyntaxKind.ExportDeclaration: - const exportClause = (node as ts.ExportDeclaration).exportClause; + 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; } @@ -42669,15 +42899,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 !!(target.flags & ts.SymbolFlags.Value) && - (ts.shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target)); + return !!(target.flags & 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); @@ -42685,23 +42915,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 && - target.flags & ts.SymbolFlags.Value && - (ts.shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target))) { + if (target && getEffectiveModifierFlags(node) & ModifierFlags.Export && + target.flags & 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 @@ -42721,73 +42951,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); } } @@ -42795,151 +43025,151 @@ 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); } - 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) { @@ -42951,61 +43181,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; @@ -43025,18 +43255,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, @@ -43053,7 +43283,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, @@ -43063,27 +43293,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, @@ -43093,13 +43323,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); @@ -43109,19 +43339,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; } @@ -43132,12 +43362,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; @@ -43145,9 +43375,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // property access can only be used as values, or types when within an expression with type arguments inside a heritage clause // qualified names can only be used as types\namespaces // identifiers are treated as values only if they appear in type queries - let 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; + let meaning = SymbolFlags.Type | SymbolFlags.Namespace; + if ((node.kind === SyntaxKind.Identifier && isInTypeQuery(node)) || (node.kind === SyntaxKind.PropertyAccessExpression && !isInHeritageClause(node))) { + meaning = SymbolFlags.Value | SymbolFlags.ExportValue; } const symbol = resolveEntityName(node, meaning, /*ignoreErrors*/ true); @@ -43155,17 +43385,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); @@ -43179,7 +43409,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; @@ -43198,13 +43428,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; } @@ -43212,11 +43442,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); @@ -43225,36 +43455,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!); @@ -43263,7 +43493,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); @@ -43290,48 +43520,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); } } @@ -43341,7 +43571,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); } @@ -43352,47 +43582,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); } } } @@ -43403,338 +43633,338 @@ 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.Node): boolean { + function checkGrammarDecoratorsAndModifiers(node: Node): boolean { return checkGrammarDecorators(node) || checkGrammarModifiers(node); } - function checkGrammarDecorators(node: ts.Node): boolean { + function checkGrammarDecorators(node: Node): boolean { if (!node.decorators) { return false; } - if (!ts.nodeCanBeDecorated(node, node.parent, node.parent.parent)) { - if (node.kind === ts.SyntaxKind.MethodDeclaration && !ts.nodeIsPresent((node as ts.MethodDeclaration).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 as MethodDeclaration).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); + else if (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor) { + const accessors = getAllAccessorDeclarations((node.parent as ClassDeclaration).members, node as AccessorDeclaration); if (accessors.firstAccessor.decorators && node === accessors.secondAccessor) { - return grammarErrorOnFirstToken(node, ts.Diagnostics.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name); + return grammarErrorOnFirstToken(node, Diagnostics.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name); } } return false; } - function checkGrammarModifiers(node: ts.Node): boolean { + function checkGrammarModifiers(node: Node): 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 (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 (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.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.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 (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.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 (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 as ts.ParameterDeclaration).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 as ParameterDeclaration).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 as ts.ParameterDeclaration).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 as ParameterDeclaration).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; @@ -43744,88 +43974,88 @@ 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.Node): boolean | undefined { + function reportObviousModifierErrors(node: Node): 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.Node): boolean { + function shouldReportBadModifier(node: Node): 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; 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.InterfaceDeclaration: - case ts.SyntaxKind.VariableStatement: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.ClassStaticBlockDeclaration: + case SyntaxKind.FunctionDeclaration: + return nodeHasAnyModifiersExcept(node, SyntaxKind.AsyncKeyword); + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ConstructorType: + return nodeHasAnyModifiersExcept(node, SyntaxKind.AbstractKeyword); + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.VariableStatement: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.ClassStaticBlockDeclaration: return true; - case ts.SyntaxKind.EnumDeclaration: - return nodeHasAnyModifiersExcept(node, ts.SyntaxKind.ConstKeyword); + case SyntaxKind.EnumDeclaration: + return nodeHasAnyModifiersExcept(node, SyntaxKind.ConstKeyword); default: - ts.Debug.fail(); + Debug.fail(); } } } - function nodeHasAnyModifiersExcept(node: ts.Node, allowedModifier: ts.SyntaxKind): boolean { + function nodeHasAnyModifiersExcept(node: Node, allowedModifier: SyntaxKind): boolean { return node.modifiers!.length > 1 || node.modifiers![0].kind !== allowedModifier; } - 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; @@ -43833,53 +44063,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; } } @@ -43887,149 +44117,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.SignatureDeclaration) { + function checkGrammarIndexSignature(node: SignatureDeclaration) { // 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; @@ -44041,21 +44271,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 @@ -44065,77 +44295,77 @@ 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 (prop.modifiers) { for (const mod of prop.modifiers) { - if (mod.kind !== ts.SyntaxKind.AsyncKeyword || prop.kind !== ts.SyntaxKind.MethodDeclaration) { - grammarErrorOnNode(mod, ts.Diagnostics._0_modifier_cannot_be_used_here, ts.getTextOfNode(mod)); + if (mod.kind !== SyntaxKind.AsyncKeyword || prop.kind !== SyntaxKind.MethodDeclaration) { + grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod)); } } } @@ -44150,32 +44380,32 @@ 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: - checkGrammarForInvalidExclamationToken(prop.exclamationToken, ts.Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context); + case SyntaxKind.ShorthandPropertyAssignment: + checkGrammarForInvalidExclamationToken(prop.exclamationToken, Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context); // falls through - case ts.SyntaxKind.PropertyAssignment: + case SyntaxKind.PropertyAssignment: // Grammar checking for computedPropertyName and shorthandPropertyAssignment - checkGrammarForInvalidQuestionMark(prop.questionToken, ts.Diagnostics.An_object_member_cannot_be_declared_optional); - if (name.kind === ts.SyntaxKind.NumericLiteral) { + 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; } @@ -44186,34 +44416,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; } @@ -44222,79 +44452,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; @@ -44304,12 +44534,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; @@ -44319,14 +44549,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; @@ -44342,23 +44572,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); } } @@ -44367,48 +44597,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; @@ -44418,91 +44648,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)) { @@ -44510,60 +44740,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; } @@ -44574,112 +44804,112 @@ 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; 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); } if (!isConstOrReadonly || isInvalidInitializer) { - 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". @@ -44691,16 +44921,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); } } @@ -44708,16 +44938,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); } } @@ -44725,87 +44955,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; @@ -44813,81 +45043,81 @@ 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 = ts.getEffectiveReturnTypeNode(node); + function checkGrammarConstructorTypeAnnotation(node: ConstructorDeclaration) { + const 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); } } - 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; } 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; } 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: // @@ -44900,23 +45130,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; } @@ -44925,16 +45155,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. @@ -44942,11 +45172,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 { @@ -44958,21 +45188,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); } @@ -44984,11 +45214,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 @@ -45006,15 +45236,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; } } @@ -45022,17 +45252,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) => { @@ -45045,72 +45275,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) { + if (moduleKind !== ModuleKind.ESNext && moduleKind !== ModuleKind.NodeNext) { // 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; @@ -45118,37 +45348,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; @@ -45160,10 +45390,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; } } @@ -45171,9 +45401,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; } @@ -45181,7 +45411,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); } } } @@ -45189,37 +45419,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) { @@ -45231,11 +45461,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 4210fb5d099a9..a83d15127cff4 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1,22 +1,58 @@ -import * as ts from "./_namespaces/ts"; +import { + append, arrayFrom, arrayToMap, assign, createGetCanonicalFileName, createMultiMap, emptyArray, endsWith, every, + extend, filter, filterMutate, find, findIndex, firstDefined, flatten, forEach, getEntries, getSpellingSuggestion, + hasProperty, isArray, isString, length, map, mapDefined, mapIterator, returnTrue, startsWith, toFileNameLowerCase, + trimString, +} from "./core"; +import { ESMap, Map, MapLike, Push } from "./corePublic"; +import { Debug } from "./debug"; +import { Diagnostics } from "./diagnosticInformationMap.generated"; +import { isArrayLiteralExpression, isObjectLiteralExpression, isStringLiteral } from "./factory/nodeTests"; +import { nodeModuleNameResolver } from "./moduleNameResolver"; +import { parseJsonText } from "./parser"; +import { + combinePaths, containsPath, convertToRelativePath, directorySeparator, ensureTrailingDirectorySeparator, + fileExtensionIs, fileExtensionIsOneOf, getBaseFileName, getDirectoryPath, getNormalizedAbsolutePath, + getRelativePathFromFile, hasExtension, isRootedDiskPath, normalizePath, normalizeSlashes, toPath, +} from "./path"; +import { sys } from "./sys"; +import { tracing } from "./tracing"; +import { BuildOptions } from "./tsbuildPublic"; +import { + AlternateModeDiagnostics, ArrayLiteralExpression, CharacterCodes, CommandLineOption, CommandLineOptionOfCustomType, + CommandLineOptionOfListType, CompilerOptions, CompilerOptionsValue, ConfigFileSpecs, Diagnostic, DiagnosticMessage, + DidYouMeanOptionsDiagnostics, Expression, Extension, FileExtensionInfo, ImportsNotUsedAsValues, JsonSourceFile, + JsxEmit, ModuleDetectionKind, ModuleKind, ModuleResolutionKind, NewLineKind, Node, NodeArray, NumericLiteral, + ObjectLiteralExpression, ParseConfigHost, ParsedCommandLine, Path, PollingWatchKind, PrefixUnaryExpression, + ProjectReference, PropertyName, ScriptTarget, StringLiteral, SyntaxKind, TsConfigOnlyOption, TsConfigSourceFile, + TypeAcquisition, WatchDirectoryFlags, WatchDirectoryKind, WatchFileKind, WatchOptions, +} from "./types"; +import { + changeExtension, createCompilerDiagnostic, createDiagnosticForNodeInSourceFile, forEachEntry, + getFileMatcherPatterns, getLocaleSpecificMessage, getRegexFromPattern, getRegularExpressionForWildcard, + getRegularExpressionsForWildcards, getSupportedExtensions, getSupportedExtensionsWithJsonIfResolveJsonModule, + getTextOfPropertyName, getTsConfigPropArray, getTsConfigPropArrayElementValue, isComputedNonLiteralName, + isImplicitGlob, isStringDoubleQuoted, +} from "./utilities"; +import { unescapeLeadingUnderscores } from "./utilitiesPublic"; /* @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 @@ -108,54 +144,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, }, { @@ -167,8 +203,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", @@ -179,20 +215,20 @@ 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, - category: ts.Diagnostics.Command_line_Options, - description: ts.Diagnostics.Print_this_message, + category: Diagnostics.Command_line_Options, + description: Diagnostics.Print_this_message, defaultValueDescription: false, }, { @@ -207,75 +243,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" }, { @@ -283,74 +319,74 @@ 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: "assumeChangesOnlyAffectDirectDependencies", type: "boolean", affectsSemanticDiagnostics: true, affectsEmit: 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, - 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, }; -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, }, { @@ -358,16 +394,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, }, { @@ -376,36 +412,36 @@ 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, affectsSemanticDiagnostics: true, affectsEmit: true, 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, }, @@ -414,26 +450,26 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ { 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, - 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, }, { @@ -446,8 +482,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 }, { @@ -455,16 +491,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, }, { @@ -473,10 +509,10 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsSourceFile: true, affectsEmit: 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, }, { @@ -485,20 +521,20 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsEmit: 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", type: "boolean", affectsEmit: 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", @@ -506,8 +542,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsEmit: 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, }, @@ -516,19 +552,19 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsEmit: 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: "outFile", type: "string", affectsEmit: 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, }, { @@ -536,57 +572,57 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "string", affectsEmit: 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", type: "string", affectsEmit: 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", type: "boolean", affectsEmit: 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", type: "string", affectsEmit: 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", type: "boolean", affectsEmit: 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, }, @@ -594,36 +630,36 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ name: "importHelpers", type: "boolean", affectsEmit: 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, - 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, - 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, }, @@ -635,8 +671,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ // Though this affects semantic diagnostics, affectsSemanticDiagnostics is not set here // The value of each strictFlag depends on own strictFlag value or this and never accessed directly. 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, }, { @@ -644,60 +680,60 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsSemanticDiagnostics: 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", type: "boolean", affectsSemanticDiagnostics: 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", type: "boolean", 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", type: "boolean", 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", type: "boolean", affectsSemanticDiagnostics: 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", type: "boolean", affectsSemanticDiagnostics: 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", type: "boolean", affectsSemanticDiagnostics: 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, }, { @@ -705,9 +741,9 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsSourceFile: 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 @@ -715,32 +751,32 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ name: "noUnusedLocals", type: "boolean", affectsSemanticDiagnostics: 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, }, { name: "noUnusedParameters", type: "boolean", affectsSemanticDiagnostics: 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, }, { name: "exactOptionalPropertyTypes", type: "boolean", affectsSemanticDiagnostics: 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, }, { name: "noImplicitReturns", type: "boolean", affectsSemanticDiagnostics: 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, }, { @@ -748,57 +784,57 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsBindDiagnostics: true, affectsSemanticDiagnostics: 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, }, { name: "noUncheckedIndexedAccess", type: "boolean", affectsSemanticDiagnostics: 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, }, { name: "noImplicitOverride", type: "boolean", affectsSemanticDiagnostics: 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, }, { name: "noPropertyAccessFromIndexSignature", type: "boolean", 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 @@ -807,8 +843,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 }, { @@ -823,10 +859,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", @@ -837,8 +873,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", @@ -849,17 +885,17 @@ 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 }, { name: "allowSyntheticDefaultImports", type: "boolean", affectsSemanticDiagnostics: 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", @@ -867,23 +903,23 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsSemanticDiagnostics: true, affectsEmit: 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, }, { name: "allowUmdGlobalAccess", type: "boolean", affectsSemanticDiagnostics: 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, }, { @@ -895,8 +931,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 @@ -904,32 +940,32 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ name: "sourceRoot", type: "string", affectsEmit: 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, - 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: "inlineSourceMap", type: "boolean", affectsEmit: 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, }, { name: "inlineSources", type: "boolean", affectsEmit: 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, }, @@ -938,8 +974,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ name: "experimentalDecorators", type: "boolean", affectsSemanticDiagnostics: 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, }, { @@ -947,8 +983,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsSemanticDiagnostics: true, affectsEmit: 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, }, @@ -956,15 +992,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", }, { @@ -973,16 +1009,16 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsSemanticDiagnostics: true, affectsEmit: 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, }, @@ -992,67 +1028,67 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsEmit: 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, - 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`", }, { name: "skipDefaultLibCheck", type: "boolean", - 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" }, { name: "emitBOM", type: "boolean", affectsEmit: 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, - 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, - 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, @@ -1062,8 +1098,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, @@ -1073,73 +1109,73 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ name: "stripInternal", type: "boolean", affectsEmit: 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, }, { name: "noImplicitUseStrict", type: "boolean", affectsSemanticDiagnostics: 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, }, { name: "noEmitHelpers", type: "boolean", affectsEmit: 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, }, { name: "noEmitOnError", type: "boolean", affectsEmit: 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, }, { name: "preserveConstEnums", type: "boolean", affectsEmit: 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, }, { @@ -1147,16 +1183,16 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "string", affectsEmit: 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", - 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, }, { @@ -1164,8 +1200,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsBindDiagnostics: true, affectsSemanticDiagnostics: 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, }, { @@ -1173,48 +1209,48 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsBindDiagnostics: true, affectsSemanticDiagnostics: 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, }, { name: "suppressExcessPropertyErrors", type: "boolean", affectsSemanticDiagnostics: 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, }, { name: "suppressImplicitAnyIndexErrors", type: "boolean", affectsSemanticDiagnostics: 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, }, { name: "noStrictGenericChecks", type: "boolean", affectsSemanticDiagnostics: 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, }, { @@ -1222,24 +1258,24 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsSemanticDiagnostics: true, affectsEmit: 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, - 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, }, { @@ -1251,98 +1287,98 @@ 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 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. @@ -1381,15 +1417,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); @@ -1406,15 +1442,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, @@ -1422,7 +1458,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 { @@ -1435,24 +1471,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 === "") { @@ -1461,40 +1497,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); @@ -1506,9 +1542,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 { @@ -1523,11 +1559,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); @@ -1538,7 +1574,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)); } } } @@ -1549,8 +1585,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; } @@ -1558,22 +1594,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)); } } @@ -1585,9 +1621,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]; @@ -1602,18 +1638,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") { @@ -1644,7 +1680,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; } @@ -1662,20 +1698,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. @@ -1690,10 +1726,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; @@ -1701,8 +1737,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 }; @@ -1710,9 +1746,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*/ @@ -1721,7 +1757,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 ." @@ -1730,28 +1766,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 */ @@ -1765,7 +1801,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; } @@ -1774,29 +1810,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, @@ -1808,9 +1844,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 }; } /** @@ -1818,8 +1854,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 @@ -1830,31 +1866,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; @@ -1864,25 +1900,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 = { @@ -1916,7 +1952,7 @@ function getTsconfigRootOptionsMap() { { name: "extends", type: "string", - category: ts.Diagnostics.File_Management, + category: Diagnostics.File_Management, }, { name: "references", @@ -1925,7 +1961,7 @@ function getTsconfigRootOptionsMap() { name: "references", type: "object" }, - category: ts.Diagnostics.Projects, + category: Diagnostics.Projects, }, { name: "files", @@ -1934,7 +1970,7 @@ function getTsconfigRootOptionsMap() { name: "files", type: "string" }, - category: ts.Diagnostics.File_Management, + category: Diagnostics.File_Management, }, { name: "include", @@ -1943,8 +1979,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", @@ -1953,8 +1989,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 ]) @@ -1973,7 +2009,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 @@ -1981,7 +2017,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 @@ -1989,24 +2025,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); } @@ -2019,7 +2055,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); } @@ -2030,11 +2066,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; @@ -2042,43 +2078,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); @@ -2114,8 +2150,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)); @@ -2123,38 +2159,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; @@ -2162,20 +2198,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 @@ -2184,7 +2220,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)); } @@ -2194,11 +2230,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 @@ -2206,16 +2242,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; } } @@ -2224,30 +2260,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; @@ -2255,12 +2291,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 */ @@ -2276,21 +2312,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: { @@ -2307,8 +2343,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 @@ -2318,24 +2354,24 @@ export function convertToTSConfig(configParseResult: ts.ParsedCommandLine, confi return config; } -function optionMapToObject(optionMap: ts.ESMap): object { +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)); @@ -2345,10 +2381,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; @@ -2361,9 +2397,9 @@ function getCustomTypeMapOfCommandLineOption(optionDefinition: ts.CommandLineOpt } } -function getNameOfCompilerOptionValue(value: ts.CompilerOptionsValue, customTypeMap: ts.ESMap): string | undefined { +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; } @@ -2371,13 +2407,13 @@ function getNameOfCompilerOptionValue(value: ts.CompilerOptionsValue, customType } 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()); } @@ -2385,18 +2421,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); @@ -2404,7 +2440,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); @@ -2429,7 +2465,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(); @@ -2450,7 +2486,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}`); } }); @@ -2462,8 +2498,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); } /** @@ -2472,7 +2508,7 @@ function getSerializedCompilerOption(options: ts.CompilerOptions): ts.ESMap(); + const categorizedOptions = createMultiMap(); for (const option of optionDeclarations) { const { category } = option; if (isAllowedOptionForOutput(option)) { - categorizedOptions.add(ts.getLocaleSpecificMessage(category!), option); + categorizedOptions.add(getLocaleSpecificMessage(category!), option); } } @@ -2516,7 +2552,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); } @@ -2527,7 +2563,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) { @@ -2552,15 +2588,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 ); } @@ -2571,7 +2607,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)[]; @@ -2593,7 +2629,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); } @@ -2604,15 +2640,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 }); } @@ -2625,7 +2661,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*/ @@ -2642,32 +2678,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, @@ -2684,24 +2720,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"); } } } @@ -2742,7 +2778,7 @@ function parseJsonConfigFileContentWorker( filesSpecs, includeSpecs, excludeSpecs, - validatedFilesSpec: ts.filter(filesSpecs, ts.isString), + validatedFilesSpec: filter(filesSpecs, isString), validatedIncludeSpecs, validatedExcludeSpecs, pathPatterns: undefined, // Initialized on first use @@ -2758,17 +2794,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 @@ -2781,75 +2817,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 */ @@ -2866,19 +2902,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) }; } @@ -2903,8 +2939,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 )); } @@ -2915,9 +2951,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 } @@ -2928,13 +2964,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); @@ -2946,32 +2982,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": @@ -2987,12 +3023,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; @@ -3002,17 +3038,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); } } }; @@ -3034,7 +3070,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 }; @@ -3042,47 +3078,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); @@ -3090,8 +3126,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 }); @@ -3110,50 +3146,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); @@ -3162,16 +3198,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; @@ -3183,48 +3219,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 = "."; } @@ -3232,15 +3268,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); @@ -3252,8 +3288,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); } /** @@ -3294,57 +3330,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)) { @@ -3376,29 +3412,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; } } @@ -3411,11 +3447,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; } @@ -3428,7 +3464,7 @@ export function matchesExclude( ) { return matchesExcludeWorker( pathToCheck, - ts.filter(excludeSpecs, spec => !invalidDotDotAfterRecursiveWildcard(spec)), + filter(excludeSpecs, spec => !invalidDotDotAfterRecursiveWildcard(spec)), useCaseSensitiveFileNames, currentDirectory ); @@ -3441,16 +3477,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)); @@ -3458,27 +3494,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: // @@ -3491,13 +3527,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; } @@ -3508,7 +3544,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); } } @@ -3517,9 +3553,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]; } } @@ -3530,7 +3566,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 @@ -3539,18 +3575,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: useCaseSensitiveFileNames ? spec : ts.toFileNameLowerCase(spec), - flags: ts.WatchDirectoryFlags.Recursive + key: useCaseSensitiveFileNames ? spec : toFileNameLowerCase(spec), + flags: WatchDirectoryFlags.Recursive }; } return undefined; @@ -3562,18 +3598,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. @@ -3592,17 +3628,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); } } @@ -3612,8 +3648,8 @@ 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 (opts.hasOwnProperty(key)) { const type = getOptionFromName(key); @@ -3625,7 +3661,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 ""; @@ -3637,9 +3673,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; } @@ -3648,7 +3684,7 @@ function getOptionValueWithEmptyStrings(value: any, option: ts.CommandLineOption } -function getDefaultValueForOption(option: ts.CommandLineOption) { +function getDefaultValueForOption(option: CommandLineOption) { switch (option.type) { case "number": return 1; @@ -3664,6 +3700,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 e75299f9eafae..35beab064b16f 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1,26 +1,32 @@ -import * as ts 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 : +import { + Comparer, Comparison, EqualityComparer, ESMap, Iterator, Map, MapLike, Push, ReadonlyESMap, ReadonlySet, Set, + SortedArray, SortedReadonlyArray, +} from "./corePublic"; +import { Debug } from "./debug"; +import { isWhiteSpaceLike } from "./scanner"; +import { __String, CharacterCodes, TextSpan, UnderscoreEscapedMap } from "./types"; + +/* @internal */ +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 +34,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 +94,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 +108,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 +121,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 +129,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 +144,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]); } @@ -246,11 +252,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)) { @@ -262,7 +268,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])); } @@ -367,7 +373,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(); @@ -470,7 +476,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; @@ -492,7 +498,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; } @@ -560,7 +566,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) { @@ -578,16 +584,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) { @@ -602,13 +608,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) { @@ -620,7 +626,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)!; } @@ -630,7 +636,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; @@ -639,10 +645,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() { @@ -706,16 +712,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); @@ -786,7 +792,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); @@ -808,7 +814,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); @@ -823,7 +829,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) : @@ -833,8 +839,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]; @@ -846,27 +852,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): void { +export function insertSorted(array: SortedArray, insert: T, compare: Comparer, allowDuplicates?: boolean): void { if (array.length === 0) { array.push(insert); return; @@ -882,20 +888,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; @@ -959,35 +965,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; @@ -1023,7 +1029,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; @@ -1097,7 +1103,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; } @@ -1111,7 +1117,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; @@ -1121,7 +1127,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)); } @@ -1130,12 +1136,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) { @@ -1149,7 +1155,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: () => { @@ -1168,10 +1174,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 */ @@ -1210,7 +1216,7 @@ export function firstOrUndefined(array: readonly T[]): T | undefined { /* @internal */ export function first(array: readonly T[]): T { - ts.Debug.assert(array.length !== 0); + Debug.assert(array.length !== 0); return array[0]; } @@ -1224,7 +1230,7 @@ export function lastOrUndefined(array: readonly T[]): T | undefined { /* @internal */ export function last(array: readonly T[]): T { - ts.Debug.assert(array.length !== 0); + Debug.assert(array.length !== 0); return array[array.length - 1]; } @@ -1276,7 +1282,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); } @@ -1291,7 +1297,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; } @@ -1302,12 +1308,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; } @@ -1354,7 +1360,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); } @@ -1365,7 +1371,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; } @@ -1373,7 +1379,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)) { @@ -1397,18 +1403,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++) { @@ -1418,7 +1424,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) : []; } @@ -1433,11 +1439,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); @@ -1466,7 +1472,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) { @@ -1496,16 +1502,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)); @@ -1601,7 +1607,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. @@ -1621,7 +1627,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; @@ -1647,18 +1653,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 */ @@ -1677,13 +1683,13 @@ export function createUnderscoreEscapedMultiMap(): UnderscoreEscapedMultiMap< * 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) { @@ -1709,7 +1715,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; @@ -1723,7 +1729,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)!; @@ -1800,13 +1806,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: () => { @@ -1862,7 +1868,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 */ @@ -1961,7 +1967,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); @@ -2057,14 +2063,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 */ @@ -2072,7 +2078,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); } @@ -2080,13 +2086,13 @@ 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(a: T, b: T, compare: ts.Comparer): T { - return compare(a, b) === ts.Comparison.LessThan ? a : b; +export function min(a: T, b: T, compare: Comparer): T { + return compare(a, b) === Comparison.LessThan ? a : b; } /* @internal */ @@ -2103,12 +2109,12 @@ export function min(a: T, b: T, compare: ts.Comparer): T { * 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 */ @@ -2122,7 +2128,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); } @@ -2135,28 +2141,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(); @@ -2167,7 +2173,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". @@ -2182,7 +2188,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; } } @@ -2219,7 +2225,7 @@ const createUIStringComparer = (() => { } })(); -let uiComparerCaseSensitive: ts.Comparer | undefined; +let uiComparerCaseSensitive: Comparer | undefined; let uiLocale: string | undefined; /* @internal */ @@ -2252,16 +2258,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); } @@ -2299,7 +2305,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; } @@ -2389,24 +2395,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; @@ -2417,7 +2423,7 @@ export function removeMinAndVersionNumbers(fileName: string) { break; } - if (ch !== ts.CharacterCodes.minus && ch !== ts.CharacterCodes.dot) { + if (ch !== CharacterCodes.minus && ch !== CharacterCodes.dot) { break; } @@ -2499,7 +2505,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); } @@ -2575,7 +2581,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; @@ -2586,12 +2592,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; @@ -2712,7 +2718,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/corePublic.ts b/src/compiler/corePublic.ts index 9443627d50413..abc1f5549d3d0 100644 --- a/src/compiler/corePublic.ts +++ b/src/compiler/corePublic.ts @@ -1,4 +1,6 @@ -import * as ts from "./_namespaces/ts"; +import { ShimCollections } from "../shims/collectionShims"; +import { getIterator } from "./core"; +import { MatchingKeys } from "./types"; // WARNING: The script `configurePrerelease.ts` uses a regexp to parse out these values. // If changing the text in this section, be sure to test `configurePrerelease` too. @@ -158,11 +160,11 @@ type GetIteratorCallback = | Readon /* @internal */ function getCollectionImplementation< - K1 extends ts.MatchingKeys any>, - K2 extends ts.MatchingKeys ReturnType<(typeof NativeCollections)[K1]>> + K1 extends MatchingKeys any>, + K2 extends MatchingKeys ReturnType<(typeof NativeCollections)[K1]>> >(name: string, nativeFactory: K1, shimFactory: K2): NonNullable> { // NOTE: ts.ShimCollections will be defined for typescriptServices.js but not for tsc.js, so we must test for it. - const constructor = NativeCollections[nativeFactory]() ?? ts.ShimCollections?.[shimFactory](ts.getIterator); + const constructor = NativeCollections[nativeFactory]() ?? ShimCollections?.[shimFactory](getIterator); if (constructor) return constructor as NonNullable>; throw new Error(`TypeScript requires an environment that provides a compatible native ${name} implementation.`); } diff --git a/src/compiler/debug.ts b/src/compiler/debug.ts index 5de1f5428ca4b..bc0dde4f05754 100644 --- a/src/compiler/debug.ts +++ b/src/compiler/debug.ts @@ -1,4 +1,32 @@ import * as ts from "./_namespaces/ts"; +import { + AnyFunction, AssertionLevel, compareValues, every, getOwnKeys, hasProperty, map, noop, stableSort, +} from "./core"; +import { version } from "./corePublic"; +import { + isArrayTypeNode, isBigIntLiteral, isCallSignatureDeclaration, isConditionalTypeNode, isConstructorDeclaration, + isConstructorTypeNode, isConstructSignatureDeclaration, isFunctionTypeNode, isGetAccessorDeclaration, isIdentifier, + isImportTypeNode, isIndexedAccessTypeNode, isIndexSignatureDeclaration, isInferTypeNode, isIntersectionTypeNode, + isLiteralTypeNode, isMappedTypeNode, isNamedTupleMember, isNumericLiteral, isOptionalTypeNode, isParameter, + isParenthesizedTypeNode, isPrivateIdentifier, isRestTypeNode, isSetAccessorDeclaration, isStringLiteral, + isThisTypeNode, isTupleTypeNode, isTypeLiteralNode, isTypeOperatorNode, isTypeParameterDeclaration, + isTypePredicateNode, isTypeQueryNode, isTypeReferenceNode, isUnionTypeNode, +} from "./factory/nodeTests"; +import { getDirectoryPath, resolvePath } from "./path"; +import { Version } from "./semver"; +import { sys } from "./sys"; +import { + BigIntLiteralType, EmitFlags, FlowFlags, FlowNode, FlowNodeBase, IntrinsicType, LiteralType, MatchingKeys, + ModifierFlags, Node, NodeArray, NodeFlags, ObjectFlags, ObjectType, RequireResult, Signature, SignatureFlags, + SnippetKind, Symbol, SymbolFlags, SyntaxKind, TransformFlags, Type, TypeFlags, +} from "./types"; +import { + formatStringFromArgs, getEffectiveModifierFlagsNoCache, getEmitFlags, getSourceFileOfNode, + getSourceTextOfNodeFromSourceFile, nodeIsSynthesized, objectAllocator, +} from "./utilities"; +import { + getParseTreeNode, idText, isGeneratedIdentifier, isParseTreeNode, symbolName, unescapeLeadingUnderscores, +} from "./utilitiesPublic"; /* @internal */ export enum LogLevel { @@ -18,26 +46,26 @@ 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; } /* @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; /* 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 { @@ -72,19 +100,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; @@ -94,7 +122,7 @@ export namespace Debug { } } - export function shouldAssert(level: ts.AssertionLevel): boolean { + export function shouldAssert(level: AssertionLevel): boolean { return currentAssertionLevel >= level; } @@ -104,16 +132,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) { @@ -122,13 +150,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) { @@ -138,78 +166,78 @@ 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: readonly ts.Node[], test: (node: ts.Node) => boolean, message?: string, stackCrawlMark?: ts.AnyFunction): void; - export function assertEachNode(nodes: readonly ts.Node[], 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: readonly Node[], test: (node: Node) => boolean, message?: string, stackCrawlMark?: AnyFunction): void; + export function assertEachNode(nodes: readonly Node[], 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.", @@ -218,10 +246,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.", @@ -230,11 +258,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.", @@ -243,11 +271,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.", @@ -256,9 +284,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.", @@ -275,7 +303,7 @@ 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 ""; } @@ -289,8 +317,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))} }`; } /** @@ -336,50 +364,50 @@ export namespace Debug { } } - return ts.stableSort<[number, string]>(result, (x, y) => ts.compareValues(x[0], y[0])); + return stableSort<[number, string]>(result, (x, y) => compareValues(x[0], y[0])); } - 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); } @@ -387,7 +415,7 @@ export namespace Debug { interface ExtendedDebugModule { init(_ts: typeof ts): void; - formatControlFlowGraph(flowNode: ts.FlowNode): string; + formatControlFlowGraph(flowNode: FlowNode): string; } let extendedDebugModule: ExtendedDebugModule | undefined; @@ -400,52 +428,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 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); @@ -457,13 +485,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 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. @@ -478,13 +506,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); @@ -503,8 +531,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) { @@ -522,56 +550,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); @@ -584,16 +612,16 @@ 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) { @@ -601,64 +629,64 @@ export namespace Debug { 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; @@ -670,9 +698,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; @@ -686,23 +714,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 (!hasWrittenDeprecation) { @@ -715,15 +743,15 @@ export namespace Debug { function createDeprecation(name: string, options: DeprecationOptions & { error: true }): () => never; function createDeprecation(name: string, options?: DeprecationOptions): () => void; 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 { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index e8ecf5f8baeb0..573e289227ecf 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1,10 +1,116 @@ import * as ts from "./_namespaces/ts"; +import { OutputFile } from "./builderStatePublic"; +import { getNodeId } from "./checker"; +import { + arrayToMap, cast, clone, contains, createGetCanonicalFileName, createMultiMap, emptyArray, filter, findIndex, + forEach, GetCanonicalFileName, isArray, last, lastOrUndefined, length, memoize, notImplemented, returnFalse, + returnUndefined, singleOrUndefined, some, stableSort, stringContains, +} from "./core"; +import { Comparison, Map, Set } from "./corePublic"; +import { Debug } from "./debug"; +import { compareEmitHelpers } from "./factory/emitHelpers"; +import { + getCommentRange, getConstantValue, getEmitHelpers, getSnippetElement, getSourceMapRange, getStartsOnNewLine, + getSyntheticLeadingComments, getSyntheticTrailingComments, getTypeNode, +} from "./factory/emitNode"; +import { createInputFiles, factory, setOriginalNode } from "./factory/nodeFactory"; +import { + isArrowFunction, isBinaryExpression, isBlock, isBundle, isEmptyStatement, isExportAssignment, isExportSpecifier, + isIdentifier, isJsxClosingElement, isJsxOpeningElement, isModuleDeclaration, isNumericLiteral, + isParenthesizedExpression, isPartiallyEmittedExpression, isSourceFile, isStringLiteral, isTypeParameterDeclaration, + isUnparsedPrepend, isUnparsedSource, isVariableStatement, +} from "./factory/nodeTests"; +import { + createBinaryExpressionTrampoline, getExternalHelpersModuleName, hasRecordedExternalHelpers, +} from "./factory/utilities"; +import { setTextRange } from "./factory/utilitiesPublic"; +import { forEachChild, isDeclarationFileName, isJSDocLikeText } from "./parser"; +import { + combinePaths, comparePaths, directorySeparator, ensurePathIsNonModuleName, ensureTrailingDirectorySeparator, + fileExtensionIs, fileExtensionIsOneOf, getBaseFileName, getDirectoryPath, getNormalizedAbsolutePath, + getRelativePathFromDirectory, getRelativePathToDirectoryOrUrl, getRootLength, normalizePath, normalizeSlashes, + resolvePath, +} from "./path"; +import { createTimer, createTimerIf } from "./performance"; +import { computeCommonSourceDirectoryOfFilenames, createPrependNodes } from "./program"; +import { + computeLineStarts, forEachLeadingCommentRange, forEachTrailingCommentRange, getLeadingCommentRanges, + getLineAndCharacterOfPosition, getLineStarts, getShebang, getTrailingCommentRanges, skipTrivia, tokenToString, +} from "./scanner"; +import { createSourceMapGenerator, tryParseRawSourceMap } from "./sourcemap"; +import { sys } from "./sys"; +import { tracing } from "./tracing"; +import { getTransformers, noEmitNotification, noEmitSubstitution, transformNodes } from "./transformer"; +import { isInternalDeclaration } from "./transformers/declarations"; +import { + AccessorDeclaration, ArrayBindingPattern, ArrayLiteralExpression, ArrayTypeNode, ArrowFunction, AsExpression, + AssertClause, AssertEntry, AwaitExpression, BigIntLiteral, BinaryExpression, BinaryOperatorToken, BindingElement, + BindingPattern, Block, BlockLike, BreakStatement, BuildInfo, Bundle, BundleBuildInfo, BundleFileInfo, + BundleFileSectionKind, BundleFileTextLike, BundleFileTextLikeKind, CallExpression, CallSignatureDeclaration, + CaseBlock, CaseClause, CaseOrDefaultClause, CatchClause, CharacterCodes, ClassDeclaration, ClassExpression, + ClassStaticBlockDeclaration, CommaListExpression, CommentRange, CompilerOptions, ComputedPropertyName, + ConditionalExpression, ConditionalTypeNode, ConstructorDeclaration, ConstructorTypeNode, + ConstructSignatureDeclaration, ContinueStatement, CustomTransformers, DebuggerStatement, DeclarationName, Decorator, + DefaultClause, DeleteExpression, DoStatement, DotToken, ElementAccessExpression, EmitFlags, EmitHint, EmitHost, + EmitResolver, EmitResult, EmitTextWriter, EmitTransformers, EntityName, EnumDeclaration, EnumMember, + ExportAssignment, ExportDeclaration, ExportedModulesFromDeclarationEmit, ExportSpecifier, Expression, + ExpressionStatement, ExpressionWithTypeArguments, Extension, ExternalModuleReference, FileReference, + ForInOrOfStatement, ForInStatement, ForOfStatement, ForStatement, FunctionDeclaration, FunctionExpression, + FunctionLikeDeclaration, FunctionTypeNode, GeneratedIdentifier, GeneratedIdentifierFlags, HeritageClause, + Identifier, IfStatement, ImportClause, ImportDeclaration, ImportEqualsDeclaration, ImportOrExportSpecifier, + ImportSpecifier, ImportTypeNode, IndexedAccessTypeNode, IndexSignatureDeclaration, InferTypeNode, + InterfaceDeclaration, IntersectionTypeNode, 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, LateBoundDeclaration, ListFormat, LiteralExpression, LiteralLikeNode, LiteralTypeNode, + MappedTypeNode, MetaProperty, MethodDeclaration, MethodSignature, Modifier, ModuleBlock, ModuleDeclaration, + ModuleKind, ModuleReference, ModuleResolutionHost, NamedDeclaration, NamedExports, NamedImports, + NamedImportsOrExports, NamedTupleMember, NamespaceExport, NamespaceExportDeclaration, NamespaceImport, + NewExpression, Node, NodeArray, NodeFlags, NonNullExpression, NumericLiteral, ObjectBindingPattern, + ObjectLiteralExpression, OptionalTypeNode, ParameterDeclaration, ParenthesizedExpression, ParenthesizedTypeNode, + ParsedCommandLine, PartiallyEmittedExpression, Placeholder, PostfixUnaryExpression, PrefixUnaryExpression, Printer, + PrinterOptions, PrintHandlers, PrivateIdentifier, ProjectReference, PropertyAccessExpression, PropertyAssignment, + PropertyDeclaration, PropertySignature, QualifiedName, RestTypeNode, ReturnStatement, ScriptTarget, + ShorthandPropertyAssignment, SignatureDeclaration, SnippetElement, SnippetKind, SourceFile, + SourceFilePrologueDirective, SourceFilePrologueInfo, SourceMapEmitResult, SourceMapGenerator, SourceMapSource, + SpreadAssignment, SpreadElement, Statement, StringLiteral, SwitchStatement, Symbol, SymbolFlags, SyntaxKind, + SynthesizedComment, TabStop, TaggedTemplateExpression, TemplateExpression, TemplateLiteralTypeNode, + TemplateLiteralTypeSpan, TemplateSpan, TextRange, ThrowStatement, 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, YieldExpression, +} from "./types"; +import { + base64encode, changeExtension, createDiagnosticCollection, createTextWriter, emitDetachedComments, EmitFileNames, + emitNewLineBeforeLeadingCommentOfPosition, escapeJsxAttributeString, escapeNonAsciiString, escapeString, + getAreDeclarationMapsEnabled, getContainingNodeArray, getDeclarationEmitExtensionForPath, + getDeclarationEmitOutputFilePath, getEmitDeclarations, getEmitFlags, getEmitModuleKind, getExternalModuleName, + getLinesBetweenPositionAndNextNonWhitespaceCharacter, getLinesBetweenPositionAndPrecedingNonWhitespaceCharacter, + getLinesBetweenRangeEndAndRangeStart, getLiteralText, GetLiteralTextFlags, getNewLineCharacter, + getOwnEmitOutputFilePath, getSourceFileOfNode, getSourceFilePathInNewDir, getSourceFilesToEmit, + getSourceTextOfNodeFromSourceFile, getTrailingSemicolonDeferringWriter, isAccessExpression, isBundleFileTextLike, + isIncrementalCompilation, isInJsonFile, isJsonSourceFile, isKeyword, isLet, isNodeDescendantOf, isPinnedComment, + isPrologueDirective, isRecognizedTripleSlashComment, isSourceFileNotJson, isVarConst, makeIdentifierFromModuleName, + nodeIsSynthesized, outFile, positionIsSynthesized, positionsAreOnSameLine, rangeEndIsOnSameLineAsRangeStart, + rangeEndPositionsAreOnSameLine, rangeIsOnSingleLine, rangeStartPositionsAreOnSameLine, removeFileExtension, + setEachParent, setParent, setTextRangePosEnd, setTextRangePosWidth, supportedJSExtensionsFlat, writeCommentRange, + writeFile, +} from "./utilities"; +import { + escapeLeadingUnderscores, getOriginalNode, getParseTreeNode, getTextOfJSDocComment, guessIndentation, idText, + isBindingPattern, isDeclaration, isExpression, isFunctionLike, isGeneratedIdentifier, isLiteralExpression, + isMemberName, isNodeArray, isTemplateLiteralKind, isTokenKind, isUnparsedNode, skipPartiallyEmittedExpressions, +} from "./utilitiesPublic"; const brackets = createBracketsMap(); /*@internal*/ export function isBuildInfoFile(file: string) { - return ts.fileExtensionIs(file, ts.Extension.TsBuildInfo); + return fileExtensionIs(file, Extension.TsBuildInfo); } /*@internal*/ @@ -18,17 +124,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 +157,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 +260,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 +273,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 +292,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 +348,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,47 +362,47 @@ 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 } = getOutputPathsForBundle(configFile.options, /*forceDtsPaths*/ false); - return ts.Debug.checkDefined(jsFilePath, `project ${configFile.options.configFilePath} expected to have at least one output`); + return Debug.checkDefined(jsFilePath, `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, emitOnlyDtsFiles?: boolean, onlyBuildInfo?: boolean, forceDtsEmit?: boolean): ts.EmitResult { +export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile | undefined, { scriptTransformers, declarationTransformers }: EmitTransformers, emitOnlyDtsFiles?: boolean, 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 { enter, exit } = ts.performance.createTimer("printTime", "beforePrint", "afterPrint"); - let bundleBuildInfo: ts.BundleBuildInfo | undefined; + const emitterDiagnostics = createDiagnosticCollection(); + const newLine = getNewLineCharacter(compilerOptions, () => host.getNewLine()); + const writer = createTextWriter(newLine); + const { enter, exit } = createTimer("printTime", "beforePrint", "afterPrint"); + let bundleBuildInfo: BundleBuildInfo | undefined; let emitSkipped = false; - let exportedModulesFromDeclarationEmit: ts.ExportedModulesFromDeclarationEmit | undefined; + let exportedModulesFromDeclarationEmit: ExportedModulesFromDeclarationEmit | undefined; // Emit each output file enter(); forEachEmittedFile( host, emitSourceFileOrBundle, - ts.getSourceFilesToEmit(host, targetSourceFile, forceDtsEmit), + getSourceFilesToEmit(host, targetSourceFile, forceDtsEmit), forceDtsEmit, onlyBuildInfo, !targetSourceFile @@ -312,26 +418,26 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo exportedModulesFromDeclarationEmit }; - 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 (!emitOnlyDtsFiles) { @@ -354,11 +460,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; const program = host.getProgramBuildInfo(); @@ -367,11 +473,11 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo return; } const version = ts.version; // Extracted into a const so the form is stable between namespace and module - ts.writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText({ bundle, program, version }), /*writeByteOrderMark*/ false); + writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText({ bundle, program, version }), /*writeByteOrderMark*/ false); } function emitJsFileOrBundle( - sourceFileOrBundle: ts.SourceFile | ts.Bundle | undefined, + sourceFileOrBundle: SourceFile | Bundle | undefined, jsFilePath: string | undefined, sourceMapFilePath: string | undefined, relativeToBuildInfo: (path: string) => string) { @@ -385,9 +491,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 +518,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.transformed[0], printer, compilerOptions); // Clean up emit nodes on parse tree @@ -421,7 +527,7 @@ 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) { @@ -430,23 +536,23 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo if (emitOnlyDtsFiles || 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 (emitOnlyDtsFiles && !ts.getEmitDeclarations(compilerOptions)) { + const inputListOrBundle = outFile(compilerOptions) ? [factory.createBundle(filesForEmit, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : filesForEmit; + if (emitOnlyDtsFiles && !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 +579,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, @@ -487,7 +593,7 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo // Explicitly do not passthru either `inline` option } ); - if (forceDtsEmit && declarationTransform.transformed[0].kind === ts.SyntaxKind.SourceFile) { + if (forceDtsEmit && declarationTransform.transformed[0].kind === SyntaxKind.SourceFile) { const sourceFile = declarationTransform.transformed[0]; exportedModulesFromDeclarationEmit = sourceFile.exportedModulesFromDeclarationEmit; } @@ -496,30 +602,30 @@ 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, sourceFileOrBundle: ts.SourceFile | ts.Bundle, printer: ts.Printer, mapOptions: SourceMapOptions) { - const bundle = sourceFileOrBundle.kind === ts.SyntaxKind.Bundle ? sourceFileOrBundle : undefined; - const sourceFile = sourceFileOrBundle.kind === ts.SyntaxKind.SourceFile ? sourceFileOrBundle : undefined; + function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, sourceFileOrBundle: SourceFile | Bundle, printer: Printer, mapOptions: SourceMapOptions) { + 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); @@ -557,7 +663,7 @@ 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); + writeFile(host, emitterDiagnostics, sourceMapFilePath, sourceMap, /*writeByteOrderMark*/ false, sourceFiles); } } else { @@ -565,7 +671,7 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo } // Write the output file - ts.writeFile(host, emitterDiagnostics, jsFilePath, writer.getText(), !!compilerOptions.emitBOM, sourceFiles, { sourceMapUrlPos }); + writeFile(host, emitterDiagnostics, jsFilePath, writer.getText(), !!compilerOptions.emitBOM, sourceFiles, { sourceMapUrlPos }); // Reset state writer.clear(); @@ -580,65 +686,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); @@ -646,110 +752,110 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo } /*@internal*/ -export function getBuildInfoText(buildInfo: ts.BuildInfo) { +export function getBuildInfoText(buildInfo: BuildInfo) { return JSON.stringify(buildInfo); } /*@internal*/ export function getBuildInfo(buildInfoText: string) { - return JSON.parse(buildInfoText) as ts.BuildInfo; + return JSON.parse(buildInfoText) as BuildInfo; } /*@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[]; /*@internal*/ -export interface EmitUsingBuildInfoHost extends ts.ModuleResolutionHost { +export interface EmitUsingBuildInfoHost extends ModuleResolutionHost { getCurrentDirectory(): string; getCanonicalFileName(fileName: string): string; useCaseSensitiveFileNames(): boolean; getNewLine(): string; } -function createSourceFilesFromBundleBuildInfo(bundle: ts.BundleBuildInfo, buildInfoDirectory: string, host: EmitUsingBuildInfoHost): 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: EmitUsingBuildInfoHost): 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, + config: ParsedCommandLine, host: EmitUsingBuildInfoHost, - getCommandLine: (ref: ts.ProjectReference) => ts.ParsedCommandLine | undefined, - customTransformers?: ts.CustomTransformers + getCommandLine: (ref: ProjectReference) => ParsedCommandLine | undefined, + customTransformers?: CustomTransformers ): EmitUsingBuildInfoResult { const { buildInfoPath, jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath } = getOutputPathsForBundle(config.options, /*forceDtsPaths*/ false); - const buildInfoText = host.readFile(ts.Debug.checkDefined(buildInfoPath)); + const buildInfoText = host.readFile(Debug.checkDefined(buildInfoPath)); if (!buildInfoText) return buildInfoPath!; - const jsFileText = host.readFile(ts.Debug.checkDefined(jsFilePath)); + const jsFileText = host.readFile(Debug.checkDefined(jsFilePath)); if (!jsFileText) return jsFilePath!; const sourceMapText = sourceMapFilePath && host.readFile(sourceMapFilePath); // error if no source map or for now if inline sourcemap @@ -763,8 +869,8 @@ export function emitUsingBuildInfo( const buildInfo = getBuildInfo(buildInfoText); if (!buildInfo.bundle || !buildInfo.bundle.js || (declarationText && !buildInfo.bundle.dts)) return buildInfoPath!; - const buildInfoDirectory = ts.getDirectoryPath(ts.getNormalizedAbsolutePath(buildInfoPath!, host.getCurrentDirectory())); - const ownPrependInput = ts.createInputFiles( + const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(buildInfoPath!, host.getCurrentDirectory())); + const ownPrependInput = createInputFiles( jsFileText, declarationText!, sourceMapFilePath, @@ -777,24 +883,24 @@ export function emitUsingBuildInfo( buildInfo, /*onlyOwnText*/ true ); - const outputFiles: ts.OutputFile[] = []; - const prependNodes = ts.createPrependNodes(config.projectReferences, getCommandLine, f => host.readFile(f)); + const outputFiles: OutputFile[] = []; + const prependNodes = createPrependNodes(config.projectReferences, getCommandLine, f => host.readFile(f)); const sourceFilesForJsEmit = createSourceFilesFromBundleBuildInfo(buildInfo.bundle, buildInfoDirectory, host); - const emitHost: ts.EmitHost = { - getPrependNodes: ts.memoize(() => [...prependNodes, ownPrependInput]), + 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) => { switch (name) { case jsFilePath: @@ -822,24 +928,24 @@ export function emitUsingBuildInfo( if (declarationMapText === text) return; break; default: - ts.Debug.fail(`Unexpected path: ${name}`); + Debug.fail(`Unexpected path: ${name}`); } outputFiles.push({ name, text, writeByteOrderMark }); }, - isEmitBlocked: ts.returnFalse, + isEmitBlocked: returnFalse, readFile: f => host.readFile(f), fileExists: f => host.fileExists(f), useCaseSensitiveFileNames: () => host.useCaseSensitiveFileNames(), - getProgramBuildInfo: ts.returnUndefined, - getSourceFileFromReference: ts.returnUndefined, - redirectTargetsMap: ts.createMultiMap(), - getFileIncludeReasons: ts.notImplemented, + getProgramBuildInfo: returnUndefined, + getSourceFileFromReference: returnUndefined, + redirectTargetsMap: createMultiMap(), + getFileIncludeReasons: notImplemented, }; emitFiles( notImplementedResolver, emitHost, /*targetSourceFile*/ undefined, - ts.getTransformers(config.options, customTransformers) + getTransformers(config.options, customTransformers) ); return outputFiles; } @@ -852,12 +958,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, @@ -867,37 +973,37 @@ 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 generatedNames: Set; // Set of names generated by the NameGenerator. 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 @@ -908,11 +1014,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; - const { enter: enterComment, exit: exitComment } = ts.performance.createTimerIf(extendedDiagnostics, "commentTime", "beforeComment", "afterComment"); - const parenthesizer = ts.factory.parenthesizer; - const typeArgumentParenthesizerRuleSelector: OrdinalParentheizerRuleSelector = { + let lastSubstitution: Node | undefined; + let currentParenthesizerRule: ((node: Node) => Node) | undefined; + const { enter: enterComment, exit: exitComment } = createTimerIf(extendedDiagnostics, "commentTime", "beforeComment", "afterComment"); + const parenthesizer = factory.parenthesizer; + const typeArgumentParenthesizerRuleSelector: OrdinalParentheizerRuleSelector = { select: index => index === 0 ? parenthesizer.parenthesizeLeadingTypeArgument : undefined }; const emitBinaryExpression = createEmitBinaryExpression(); @@ -933,43 +1039,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(); } @@ -977,9 +1083,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); @@ -987,7 +1093,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) { @@ -1002,8 +1108,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; } @@ -1012,17 +1118,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; @@ -1044,7 +1150,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); @@ -1058,19 +1164,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[] }); } } @@ -1078,7 +1184,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(); @@ -1103,27 +1209,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() { @@ -1132,7 +1238,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); } @@ -1140,7 +1246,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; @@ -1149,9 +1255,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 @@ -1162,7 +1268,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: function reset() { nodeIdToGeneratedName = []; autoGeneratedIdToGeneratedName = []; - generatedNames = new ts.Set(); + generatedNames = new Set(); tempFlagsStack = []; tempFlags = TempFlags.Auto; reservedNamesStack = []; @@ -1173,38 +1279,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; } } @@ -1213,34 +1319,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); } @@ -1260,20 +1366,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; @@ -1289,369 +1395,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; @@ -1662,116 +1768,116 @@ 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.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.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"); @@ -1779,22 +1885,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) { @@ -1808,20 +1914,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) { @@ -1851,7 +1957,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; } } @@ -1860,9 +1966,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); } // @@ -1871,7 +1977,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); } @@ -1881,10 +1987,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 { @@ -1895,7 +2001,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); @@ -1906,32 +2012,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); @@ -1942,29 +2048,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}`); } @@ -1973,30 +2079,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 { @@ -2004,7 +2110,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitComputedPropertyName(node: ts.ComputedPropertyName) { + function emitComputedPropertyName(node: ComputedPropertyName) { writePunctuation("["); emitExpression(node.expression, parenthesizer.parenthesizeExpressionOfComputedPropertyName); writePunctuation("]"); @@ -2014,7 +2120,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) { @@ -2031,13 +2137,13 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitParameter(node: ts.ParameterDeclaration) { + function emitParameter(node: ParameterDeclaration) { emitDecorators(node, node.decorators); emitModifiers(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 { @@ -2047,7 +2153,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.decorators ? node.decorators.end : node.pos, node, parenthesizer.parenthesizeExpressionForDisallowedComma); } - function emitDecorator(decorator: ts.Decorator) { + function emitDecorator(decorator: Decorator) { writePunctuation("@"); emitExpression(decorator.expression, parenthesizer.parenthesizeLeftSideOfAccess); } @@ -2056,7 +2162,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Type members // - function emitPropertySignature(node: ts.PropertySignature) { + function emitPropertySignature(node: PropertySignature) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); emitNodeWithWriter(node.name, writeProperty); @@ -2065,7 +2171,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writeTrailingSemicolon(); } - function emitPropertyDeclaration(node: ts.PropertyDeclaration) { + function emitPropertyDeclaration(node: PropertyDeclaration) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); emit(node.name); @@ -2076,7 +2182,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writeTrailingSemicolon(); } - function emitMethodSignature(node: ts.MethodSignature) { + function emitMethodSignature(node: MethodSignature) { pushNameGenerationScope(node); emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); @@ -2089,7 +2195,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: popNameGenerationScope(node); } - function emitMethodDeclaration(node: ts.MethodDeclaration) { + function emitMethodDeclaration(node: MethodDeclaration) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); emit(node.asteriskToken); @@ -2098,29 +2204,29 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emitSignatureAndBody(node, emitSignatureHead); } - function emitClassStaticBlockDeclaration(node: ts.ClassStaticBlockDeclaration) { + function emitClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); 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) { emitDecorators(node, node.decorators); emitModifiers(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); emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); @@ -2131,7 +2237,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: popNameGenerationScope(node); } - function emitConstructSignature(node: ts.ConstructSignatureDeclaration) { + function emitConstructSignature(node: ConstructSignatureDeclaration) { pushNameGenerationScope(node); emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); @@ -2144,7 +2250,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: popNameGenerationScope(node); } - function emitIndexSignature(node: ts.IndexSignatureDeclaration) { + function emitIndexSignature(node: IndexSignatureDeclaration) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); emitParametersForIndexSignature(node, node.parameters); @@ -2152,7 +2258,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writeTrailingSemicolon(); } - function emitTemplateTypeSpan(node: ts.TemplateLiteralTypeSpan) { + function emitTemplateTypeSpan(node: TemplateLiteralTypeSpan) { emit(node.type); emit(node.literal); } @@ -2165,7 +2271,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(); @@ -2179,12 +2285,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); @@ -2195,7 +2301,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(":"); @@ -2203,22 +2309,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"); @@ -2232,61 +2338,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"); @@ -2302,13 +2408,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(")"); @@ -2318,27 +2424,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 { @@ -2347,14 +2453,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"); @@ -2365,7 +2471,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("?"); } } @@ -2373,27 +2479,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(); @@ -2410,7 +2516,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("}"); } @@ -2426,19 +2532,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); @@ -2453,39 +2559,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(); @@ -2507,34 +2613,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"); @@ -2547,19 +2653,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"); @@ -2575,34 +2681,34 @@ 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) { emitDecorators(node, node.decorators); 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); @@ -2610,31 +2716,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(); @@ -2642,7 +2748,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 @@ -2656,12 +2762,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); } @@ -2677,9 +2783,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; @@ -2707,26 +2813,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); @@ -2745,33 +2851,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); @@ -2791,33 +2897,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(); @@ -2827,12 +2933,12 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitNonNullExpression(node: ts.NonNullExpression) { + function emitNonNullExpression(node: NonNullExpression) { emitExpression(node.expression, parenthesizer.parenthesizeLeftSideOfAccess); writeOperator("!"); } - function emitMetaProperty(node: ts.MetaProperty) { + function emitMetaProperty(node: MetaProperty) { writeToken(node.keywordToken, node.pos, writePunctuation); writePunctuation("."); emit(node.name); @@ -2842,7 +2948,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Misc // - function emitTemplateSpan(node: ts.TemplateSpan) { + function emitTemplateSpan(node: TemplateSpan) { emitExpression(node.expression); emit(node.literal); } @@ -2851,18 +2957,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(); @@ -2879,26 +2985,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); } @@ -2908,18 +3014,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 { @@ -2930,54 +3036,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 { @@ -2986,27 +3092,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(); } @@ -3017,23 +3123,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); } @@ -3044,65 +3150,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) { @@ -3111,14 +3217,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(); } @@ -3126,24 +3232,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) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); writeKeyword("function"); @@ -3153,17 +3259,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); @@ -3187,13 +3293,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. @@ -3202,7 +3308,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; } @@ -3210,18 +3316,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, body.statements, ts.ListFormat.PreserveLines) - || getClosingLineTerminatorCount(body, body.statements, ts.ListFormat.PreserveLines)) { + if (getLeadingLineTerminatorCount(body, body.statements, ListFormat.PreserveLines) + || getClosingLineTerminatorCount(body, body.statements, ListFormat.PreserveLines)) { 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; } @@ -3231,7 +3337,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: return true; } - function emitBlockFunctionBody(body: ts.Block) { + function emitBlockFunctionBody(body: Block) { onBeforeEmitNode?.(body); writeSpace(); writePunctuation("{"); @@ -3244,35 +3350,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); emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); @@ -3282,17 +3388,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) { @@ -3300,21 +3406,21 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitInterfaceDeclaration(node: ts.InterfaceDeclaration) { + function emitInterfaceDeclaration(node: InterfaceDeclaration) { emitDecorators(node, node.decorators); 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) { emitDecorators(node, node.decorators); emitModifiers(node, node.modifiers); writeKeyword("type"); @@ -3328,7 +3434,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(); @@ -3336,21 +3442,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; @@ -3360,37 +3466,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 { @@ -3398,14 +3504,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); @@ -3415,68 +3521,68 @@ 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) { - let nextPos = emitTokenWithComment(ts.SyntaxKind.ExportKeyword, node.pos, writeKeyword, node); + function emitExportDeclaration(node: ExportDeclaration) { + 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); } @@ -3486,61 +3592,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(); @@ -3548,7 +3654,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(); } @@ -3559,7 +3665,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); @@ -3570,13 +3676,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); @@ -3585,16 +3691,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); @@ -3609,28 +3715,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("}"); @@ -3638,13 +3744,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; } @@ -3652,24 +3758,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 { @@ -3681,56 +3787,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); @@ -3740,7 +3846,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Property assignments // - function emitPropertyAssignment(node: ts.PropertyAssignment) { + function emitPropertyAssignment(node: PropertyAssignment) { emit(node.name); writePunctuation(":"); writeSpace(); @@ -3752,14 +3858,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(); @@ -3769,9 +3875,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); } } @@ -3780,7 +3886,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); } @@ -3788,10 +3894,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) { @@ -3804,38 +3910,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("{"); @@ -3844,18 +3950,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 { @@ -3874,12 +3980,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(); @@ -3889,21 +3995,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(); @@ -3914,7 +4020,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitJSDocPropertyLikeTag(param: ts.JSDocPropertyLikeTag) { + function emitJSDocPropertyLikeTag(param: JSDocPropertyLikeTag) { emitJSDocTagName(param.tagName); emitJSDocTypeExpression(param.typeExpression); writeSpace(); @@ -3928,20 +4034,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("{"); @@ -3954,14 +4060,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; @@ -3969,10 +4075,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(); @@ -3981,15 +4087,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) { @@ -4010,63 +4116,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) { @@ -4076,7 +4182,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); } @@ -4091,13 +4197,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); } @@ -4105,14 +4211,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); @@ -4121,15 +4227,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({ @@ -4148,9 +4254,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(); @@ -4159,7 +4265,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; } @@ -4177,7 +4283,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; @@ -4185,14 +4291,14 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: write = savedWrite; } - function emitModifiers(node: ts.Node, modifiers: ts.NodeArray | undefined) { + function emitModifiers(node: Node, modifiers: NodeArray | undefined) { if (modifiers && modifiers.length) { - emitList(node, modifiers, ts.ListFormat.Modifiers); + emitList(node, modifiers, ListFormat.Modifiers); writeSpace(); } } - function emitTypeAnnotation(node: ts.TypeNode | undefined) { + function emitTypeAnnotation(node: TypeNode | undefined) { if (node) { writePunctuation(":"); writeSpace(); @@ -4200,53 +4306,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); @@ -4255,95 +4361,95 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitDecorators(parentNode: ts.Node, decorators: ts.NodeArray | undefined) { - emitList(parentNode, decorators, ts.ListFormat.Decorators); + function emitDecorators(parentNode: Node, decorators: NodeArray | undefined) { + 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.decorators) // parent may not have decorators - && !ts.some(parentNode.modifiers) // parent may not have modifiers - && !ts.some(parentNode.typeParameters) // parent may not have type parameters - && !ts.some(parameter.decorators) // parameter may not have decorators - && !ts.some(parameter.modifiers) // parameter may not have modifiers + && !some(parentNode.decorators) // parent may not have decorators + && !some(parentNode.modifiers) // parent may not have modifiers + && !some(parentNode.typeParameters) // parent may not have type parameters + && !some(parameter.decorators) // parameter may not have decorators + && !some(parameter.modifiers) // parameter may not have 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) { if (onBeforeEmitNodeArray) { onBeforeEmitNodeArray(children); } @@ -4353,7 +4459,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: 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 @@ -4366,43 +4472,43 @@ 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(); } } else { - ts.Debug.type>(children); + Debug.type>(children); // 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, format); // TODO: GH#18217 if (leadingLineTerminatorCount) { 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); @@ -4414,7 +4520,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); @@ -4425,7 +4531,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; } @@ -4433,7 +4539,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(); } } @@ -4441,7 +4547,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 { @@ -4460,12 +4566,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 hasTrailingComma = children?.hasTrailingComma && (format & ts.ListFormat.AllowTrailingComma) && (format & ts.ListFormat.CommaDelimited); + const emitFlags = previousSibling ? getEmitFlags(previousSibling) : 0; + const skipTrailingComments = commentsDisabled || !!(emitFlags & EmitFlags.NoTrailingComments); + const hasTrailingComma = children?.hasTrailingComma && (format & ListFormat.AllowTrailingComma) && (format & ListFormat.CommaDelimited); if (hasTrailingComma) { if (previousSibling && !skipTrailingComments) { - emitTokenWithComment(ts.SyntaxKind.CommaToken, previousSibling.end, writePunctuation, previousSibling); + emitTokenWithComment(SyntaxKind.CommaToken, previousSibling.end, writePunctuation, previousSibling); } else { writePunctuation(","); @@ -4478,12 +4584,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(hasTrailingComma && children?.end ? children.end : previousSibling.end); } // Decrease the indent, if requested. - if (format & ts.ListFormat.Indented) { + if (format & ListFormat.Indented) { decreaseIndent(); } @@ -4494,7 +4600,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(); } } @@ -4503,7 +4609,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 } @@ -4525,7 +4631,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); } @@ -4585,32 +4691,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) { @@ -4629,7 +4735,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) { @@ -4662,15 +4768,15 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function getLeadingLineTerminatorCount(parentNode: ts.Node | undefined, children: readonly ts.Node[], format: ts.ListFormat): number { - if (format & ts.ListFormat.PreserveLines || preserveSourceNewlines) { - if (format & ts.ListFormat.PreferNewLine) { + function getLeadingLineTerminatorCount(parentNode: Node | undefined, children: readonly Node[], format: ListFormat): number { + if (format & ListFormat.PreserveLines || preserveSourceNewlines) { + if (format & ListFormat.PreferNewLine) { return 1; } const firstChild = children[0]; 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 @@ -4690,45 +4796,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!, @@ -4740,49 +4846,49 @@ 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, children: readonly ts.Node[], format: ts.ListFormat): number { - if (format & ts.ListFormat.PreserveLines || preserveSourceNewlines) { - if (format & ts.ListFormat.PreferNewLine) { + function getClosingLineTerminatorCount(parentNode: Node | undefined, children: readonly Node[], format: ListFormat): number { + if (format & ListFormat.PreserveLines || preserveSourceNewlines) { + if (format & ListFormat.PreferNewLine) { return 1; } - const lastChild = ts.lastOrUndefined(children); + const lastChild = lastOrUndefined(children); 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 = ts.isNodeArray(children) && !ts.positionIsSynthesized(children.end) ? children.end : lastChild.end; + const end = isNodeArray(children) && !positionIsSynthesized(children.end) ? children.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; @@ -4791,7 +4897,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: // @@ -4812,36 +4918,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); + function writeLineSeparatorsAfter(node: Node, parent: Node) { + const trailingNewlines = preserveSourceNewlines && getClosingLineTerminatorCount(parent, [node], ListFormat.None); 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; } @@ -4850,88 +4956,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)) { + function getTextOfNode(node: Identifier | PrivateIdentifier | LiteralExpression, includeTrivia?: boolean): string { + if (isGeneratedIdentifier(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.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) || 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); @@ -4942,8 +5048,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()!; @@ -4951,118 +5057,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)) { + if (isGeneratedIdentifier(name)) { generateName(name); } - else if (ts.isBindingPattern(name)) { + else if (isBindingPattern(name)) { generateNames(name); } } @@ -5071,8 +5177,8 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: /** * Generate the text for a generated identifier. */ - function generateName(name: ts.GeneratedIdentifier) { - if ((name.autoGenerateFlags & ts.GeneratedIdentifierFlags.KindMask) === ts.GeneratedIdentifierFlags.Node) { + function generateName(name: GeneratedIdentifier) { + 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(getNodeForGeneratedName(name), name.autoGenerateFlags); @@ -5085,8 +5191,8 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function generateNameCached(node: ts.Node, flags?: ts.GeneratedIdentifierFlags) { - const nodeId = ts.getNodeId(node); + function generateNameCached(node: Node, flags?: GeneratedIdentifierFlags) { + const nodeId = getNodeId(node); return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = generateNameForNode(node, flags)); } @@ -5110,12 +5216,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; } } @@ -5145,7 +5251,7 @@ 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); if (isUniqueName(name)) { if (reservedInNestedScopes) { @@ -5177,7 +5283,7 @@ 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; @@ -5203,7 +5309,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); @@ -5212,10 +5318,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); } @@ -5233,8 +5339,8 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: return makeUniqueName("class"); } - function generateNameForMethodOrAccessor(node: ts.MethodDeclaration | ts.AccessorDeclaration) { - if (ts.isIdentifier(node.name)) { + function generateNameForMethodOrAccessor(node: MethodDeclaration | AccessorDeclaration) { + if (isIdentifier(node.name)) { return generateNameCached(node.name); } return makeTempVariableName(TempFlags.Auto); @@ -5243,32 +5349,32 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: /** * Generates a unique name from a node. */ - function generateNameForNode(node: ts.Node, flags?: ts.GeneratedIdentifierFlags): string { + function generateNameForNode(node: Node, flags?: GeneratedIdentifierFlags): string { switch (node.kind) { - case ts.SyntaxKind.Identifier: + case SyntaxKind.Identifier: 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) ); - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.EnumDeclaration: - return generateNameForModuleOrEnum(node as ts.ModuleDeclaration | ts.EnumDeclaration); - case ts.SyntaxKind.ImportDeclaration: - case ts.SyntaxKind.ExportDeclaration: - return generateNameForImportOrExportDeclaration(node as ts.ImportDeclaration | ts.ExportDeclaration); - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ExportAssignment: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.EnumDeclaration: + return generateNameForModuleOrEnum(node as ModuleDeclaration | EnumDeclaration); + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ExportDeclaration: + return generateNameForImportOrExportDeclaration(node as ImportDeclaration | ExportDeclaration); + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ExportAssignment: return generateNameForExportDefault(); - case ts.SyntaxKind.ClassExpression: + case SyntaxKind.ClassExpression: return generateNameForClassExpression(); - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - return generateNameForMethodOrAccessor(node as ts.MethodDeclaration | ts.AccessorDeclaration); - case ts.SyntaxKind.ComputedPropertyName: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return generateNameForMethodOrAccessor(node as MethodDeclaration | AccessorDeclaration); + case SyntaxKind.ComputedPropertyName: return makeTempVariableName(TempFlags.Auto, /*reserveInNestedScopes*/ true); default: return makeTempVariableName(TempFlags.Auto); @@ -5278,38 +5384,38 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: /** * Generates a unique identifier for a node. */ - function makeName(name: ts.GeneratedIdentifier) { - switch (name.autoGenerateFlags & ts.GeneratedIdentifierFlags.KindMask) { - case ts.GeneratedIdentifierFlags.Auto: - return makeTempVariableName(TempFlags.Auto, !!(name.autoGenerateFlags & ts.GeneratedIdentifierFlags.ReservedInNestedScopes)); - case ts.GeneratedIdentifierFlags.Loop: - return makeTempVariableName(TempFlags._i, !!(name.autoGenerateFlags & ts.GeneratedIdentifierFlags.ReservedInNestedScopes)); - case ts.GeneratedIdentifierFlags.Unique: + function makeName(name: GeneratedIdentifier) { + switch (name.autoGenerateFlags & GeneratedIdentifierFlags.KindMask) { + case GeneratedIdentifierFlags.Auto: + return makeTempVariableName(TempFlags.Auto, !!(name.autoGenerateFlags & GeneratedIdentifierFlags.ReservedInNestedScopes)); + case GeneratedIdentifierFlags.Loop: + return makeTempVariableName(TempFlags._i, !!(name.autoGenerateFlags & GeneratedIdentifierFlags.ReservedInNestedScopes)); + 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) + idText(name), + (name.autoGenerateFlags & GeneratedIdentifierFlags.FileLevel) ? isFileLevelUniqueName : isUniqueName, + !!(name.autoGenerateFlags & GeneratedIdentifierFlags.Optimistic), + !!(name.autoGenerateFlags & GeneratedIdentifierFlags.ReservedInNestedScopes) ); } - return ts.Debug.fail("Unsupported GeneratedIdentifierKind."); + return Debug.fail("Unsupported GeneratedIdentifierKind."); } /** * Gets the node from which a name should be generated. */ - function getNodeForGeneratedName(name: ts.GeneratedIdentifier) { + function getNodeForGeneratedName(name: GeneratedIdentifier) { 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.isIdentifier(node) - && !!(node.autoGenerateFlags! & ts.GeneratedIdentifierFlags.Node) + if (isIdentifier(node) + && !!(node.autoGenerateFlags! & GeneratedIdentifierFlags.Node) && node.autoGenerateId !== autoGenerateId) { break; } @@ -5323,7 +5429,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // 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; @@ -5333,73 +5439,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; @@ -5408,19 +5514,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 { @@ -5428,7 +5534,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitTrailingSynthesizedComment(comment: ts.SynthesizedComment) { + function emitTrailingSynthesizedComment(comment: SynthesizedComment) { if (!writer.isAtStartOfLine()) { writer.writeSpace(" "); } @@ -5438,30 +5544,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; @@ -5481,26 +5587,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; } @@ -5529,13 +5635,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); } @@ -5543,27 +5649,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(" "); } } @@ -5580,7 +5686,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()) { @@ -5588,7 +5694,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) { @@ -5605,25 +5711,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) { @@ -5634,33 +5740,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(); } @@ -5668,11 +5774,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); @@ -5683,10 +5789,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); } @@ -5696,32 +5802,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( @@ -5736,28 +5842,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); } @@ -5767,8 +5873,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); } /** @@ -5780,11 +5886,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(), @@ -5794,7 +5900,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; @@ -5815,32 +5921,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; } @@ -5867,31 +5973,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 @@ -5901,27 +6007,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 99cf8c548a254..b87efe442fc1a 100644 --- a/src/compiler/factory/baseNodeFactory.ts +++ b/src/compiler/factory/baseNodeFactory.ts @@ -1,4 +1,5 @@ -import * as ts from "../_namespaces/ts"; +import { Node, SyntaxKind } from "../types"; +import { objectAllocator } from "../utilities"; /** * A `BaseNodeFactory` is an abstraction over an `ObjectAllocator` that handles caching `Node` constructors @@ -6,11 +7,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 */ @@ -19,11 +20,11 @@ export interface BaseNodeFactory { */ export function createBaseNodeFactory(): BaseNodeFactory { // tslint:disable variable-name - 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; // tslint:enable variable-name return { @@ -34,23 +35,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); } } \ No newline at end of file diff --git a/src/compiler/factory/emitHelpers.ts b/src/compiler/factory/emitHelpers.ts index bd77c3b4efe4c..315b6bac91488 100644 --- a/src/compiler/factory/emitHelpers.ts +++ b/src/compiler/factory/emitHelpers.ts @@ -1,48 +1,61 @@ -import * as ts from "../_namespaces/ts"; +import { arrayToMap, compareValues, memoize } from "../core"; +import { Comparison, ReadonlyESMap } from "../corePublic"; +import { Debug } from "../debug"; +import { PrivateIdentifierKind } from "../transformers/classFields"; +import { + __String, ArrayLiteralExpression, BindingOrAssignmentElement, Block, EmitFlags, EmitHelper, + EmitHelperUniqueNameCallback, EmitNode, EntityName, Expression, FunctionExpression, GeneratedIdentifierFlags, + Identifier, ScriptTarget, SyntaxKind, TextRange, TransformationContext, UnscopedEmitHelper, +} from "../types"; +import { getEmitFlags, getEmitScriptTarget } from "../utilities"; +import { setEmitFlags } from "./emitNode"; +import { isCallExpression, isComputedPropertyName, isIdentifier } from "./nodeTests"; +import { createExpressionFromEntityName, getPropertyNameOfBindingOrAssignmentElement } from "./utilities"; +import { setTextRange } from "./utilitiesPublic"; /* @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 +98,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 +123,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 +135,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 +152,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 +166,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 +189,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 +199,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 +213,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 +245,7 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit /*typeArguments*/ undefined, [ value, - ts.setTextRange( + setTextRange( factory.createArrayLiteralExpression(propertyNames), location )] @@ -241,12 +254,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 +268,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 +276,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 +284,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 +302,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 +313,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 +322,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 +335,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 +345,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 +353,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 +367,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 +376,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 +388,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 +400,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 +412,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 +433,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 +447,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 +462,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 +474,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 +488,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 +508,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 +517,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 +537,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 +551,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 +568,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 +589,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 +609,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 +634,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 +647,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 +671,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 +690,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, @@ -757,7 +770,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, @@ -795,7 +808,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, @@ -815,7 +828,7 @@ export const createBindingHelper: ts.UnscopedEmitHelper = { }; /* @internal */ -export const setModuleDefaultHelper: ts.UnscopedEmitHelper = { +export const setModuleDefaultHelper: UnscopedEmitHelper = { name: "typescript:commonjscreatevalue", importName: "__setModuleDefault", scoped: false, @@ -830,7 +843,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, @@ -848,7 +861,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, @@ -859,7 +872,7 @@ export const importDefaultHelper: ts.UnscopedEmitHelper = { }; /* @internal */ -export const exportStarHelper: ts.UnscopedEmitHelper = { +export const exportStarHelper: UnscopedEmitHelper = { name: "typescript:export-star", importName: "__exportStar", scoped: false, @@ -920,7 +933,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, @@ -984,7 +997,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, @@ -1010,7 +1023,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, @@ -1021,11 +1034,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, @@ -1054,7 +1067,7 @@ export function getAllUnscopedEmitHelpers() { } /* @internal */ -export const asyncSuperHelper: ts.EmitHelper = { +export const asyncSuperHelper: EmitHelper = { name: "typescript:async-super", scoped: true, text: helperString` @@ -1062,7 +1075,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` @@ -1073,9 +1086,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..b1c1478f971ef 100644 --- a/src/compiler/factory/emitNode.ts +++ b/src/compiler/factory/emitNode.ts @@ -1,28 +1,35 @@ -import * as ts from "../_namespaces/ts"; +import { append, appendIfUnique, orderedRemoveItem, some } from "../core"; +import { Debug } from "../debug"; +import { + AccessExpression, EmitFlags, EmitHelper, EmitNode, Node, SnippetElement, SourceFile, SourceMapRange, SyntaxKind, + SynthesizedComment, TextRange, TypeNode, +} from "../types"; +import { getSourceFileOfNode } from "../utilities"; +import { getParseTreeNode, isParseTreeNode } from "../utilitiesPublic"; /** * 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 +38,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 +57,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 +68,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 +77,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 +86,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 +101,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 +119,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 +127,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 +135,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 +185,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 +201,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 +223,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 +234,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 +252,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 +268,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 +276,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 709ca5da3ae56..c3ac70382d70f 100644 --- a/src/compiler/factory/nodeConverters.ts +++ b/src/compiler/factory/nodeConverters.ts @@ -1,7 +1,21 @@ -import * as ts from "../_namespaces/ts"; +import { cast, map, notImplemented } from "../core"; +import { Debug } from "../debug"; +import { + ArrayBindingOrAssignmentElement, ArrayBindingOrAssignmentPattern, AssignmentPattern, + BindingOrAssignmentElementTarget, BindingOrAssignmentPattern, Block, ConciseBody, Expression, FunctionDeclaration, + NodeConverters, NodeFactory, ObjectBindingOrAssignmentElement, ObjectBindingOrAssignmentPattern, SyntaxKind, +} from "../types"; +import { isBindingPattern, isExpression, isObjectLiteralElementLike } from "../utilitiesPublic"; +import { getStartsOnNewLine, setStartsOnNewLine } from "./emitNode"; +import { setOriginalNode } from "./nodeFactory"; +import { + isArrayBindingPattern, isArrayLiteralExpression, isBindingElement, isBlock, isIdentifier, isObjectBindingPattern, + isObjectLiteralExpression, +} from "./nodeTests"; +import { setTextRange } from "./utilitiesPublic"; /* @internal */ -export function createNodeConverters(factory: ts.NodeFactory): ts.NodeConverters { +export function createNodeConverters(factory: NodeFactory): NodeConverters { return { convertToFunctionBlock, convertToFunctionExpression, @@ -13,17 +27,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 +47,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 +72,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 aa30050ddbda2..03b5893c7473e 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -1,4 +1,104 @@ -import * as ts from "../_namespaces/ts"; +import { + addRange, append, appendIfUnique, cast, emptyArray, every, hasProperty, isArray, isString, lastOrUndefined, map, + memoize, memoizeOne, reduceLeft, returnTrue, sameFlatMap, singleOrUndefined, some, startsWith, +} from "../core"; +import { Map, Push } from "../corePublic"; +import { Debug } from "../debug"; +import { getBuildInfo } from "../emitter"; +import { parseNodeFactory } from "../parser"; +import { createScanner, getLineAndCharacterOfPosition, Scanner, stringToToken } from "../scanner"; +import { + ArrayBindingElement, ArrayBindingPattern, ArrayLiteralExpression, ArrayTypeNode, ArrowFunction, AsExpression, + AssertClause, AssertEntry, AssertionKey, AssertsKeyword, AssignmentPattern, AsteriskToken, AwaitExpression, + AwaitKeyword, BigIntLiteral, BinaryExpression, BinaryOperator, BinaryOperatorToken, BindingElement, BindingName, + BindingPattern, Block, BooleanLiteral, BreakStatement, BuildInfo, Bundle, BundleFileHasNoDefaultLib, BundleFileInfo, + BundleFileReference, BundleFileSectionKind, CallBinding, CallChain, CallExpression, CallSignatureDeclaration, + CaseBlock, CaseClause, CaseOrDefaultClause, CatchClause, ClassDeclaration, ClassElement, ClassExpression, + ClassLikeDeclaration, ClassStaticBlockDeclaration, ColonToken, CommaListExpression, ComputedPropertyName, + ConciseBody, ConditionalExpression, ConditionalTypeNode, ConstructorDeclaration, ConstructorTypeNode, + ConstructSignatureDeclaration, ContinueStatement, DebuggerStatement, Declaration, DeclarationName, Decorator, + DefaultClause, DeleteExpression, DoStatement, DotDotDotToken, ElementAccessChain, ElementAccessExpression, + EmitFlags, EmitNode, EmptyStatement, EndOfDeclarationMarker, EndOfFileToken, EntityName, EnumDeclaration, + EnumMember, EqualsGreaterThanToken, ExclamationToken, ExportAssignment, ExportDeclaration, ExportSpecifier, + Expression, ExpressionStatement, ExpressionWithTypeArguments, ExternalModuleReference, FalseLiteral, FileReference, + ForInitializer, ForInStatement, ForOfStatement, ForStatement, FunctionDeclaration, FunctionExpression, + FunctionLikeDeclaration, FunctionTypeNode, GeneratedIdentifier, GeneratedIdentifierFlags, GetAccessorDeclaration, + HasModifiers, HeritageClause, Identifier, IfStatement, ImportClause, ImportDeclaration, ImportEqualsDeclaration, + ImportSpecifier, ImportTypeAssertionContainer, ImportTypeNode, IndexedAccessTypeNode, IndexSignatureDeclaration, + InferTypeNode, InputFiles, InterfaceDeclaration, IntersectionTypeNode, 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, + LeftHandSideExpression, LiteralToken, LiteralTypeNode, MappedTypeNode, MergeDeclarationMarker, MetaProperty, + MethodDeclaration, MethodSignature, MinusToken, MissingDeclaration, Modifier, ModifierFlags, ModifierSyntaxKind, + ModifierToken, ModuleBlock, ModuleBody, ModuleDeclaration, ModuleKind, ModuleName, ModuleReference, + MutableNodeArray, NamedDeclaration, NamedExportBindings, NamedExports, NamedImportBindings, NamedImports, + NamedTupleMember, NamespaceExport, NamespaceExportDeclaration, NamespaceImport, NewExpression, Node, NodeArray, + NodeFactory, NodeFlags, NonNullChain, NonNullExpression, NoSubstitutionTemplateLiteral, NotEmittedStatement, + NullLiteral, NumericLiteral, ObjectBindingPattern, ObjectLiteralElementLike, ObjectLiteralExpression, + OmittedExpression, OptionalTypeNode, OuterExpression, OuterExpressionKinds, ParameterDeclaration, + ParenthesizedExpression, ParenthesizedTypeNode, PartiallyEmittedExpression, PlusToken, PostfixUnaryExpression, + PostfixUnaryOperator, PrefixUnaryExpression, PrefixUnaryOperator, PrimaryExpression, PrivateIdentifier, + PrologueDirective, PropertyAccessChain, PropertyAccessExpression, PropertyAssignment, PropertyDeclaration, + PropertyDescriptorAttributes, PropertyName, PropertyNameLiteral, PropertySignature, PseudoBigInt, + PunctuationSyntaxKind, PunctuationToken, QualifiedName, QuestionDotToken, QuestionToken, ReadonlyKeyword, + RegularExpressionLiteral, RestTypeNode, ReturnStatement, ScriptTarget, SemicolonClassElement, + SetAccessorDeclaration, ShorthandPropertyAssignment, SignatureDeclarationBase, SourceFile, SourceMapSource, + SpreadAssignment, SpreadElement, Statement, StringLiteral, StringLiteralLike, 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, VisitResult, VoidExpression, WhileStatement, WithStatement, + YieldExpression, +} from "../types"; +import { + getEmitFlags, getTextOfIdentifierOrLiteral, hasInvalidEscape, hasStaticModifier, hasSyntacticModifier, + isCustomPrologue, isHoistedFunction, isHoistedVariableStatement, isLogicalOrCoalescingAssignmentOperator, + isPrologueDirective, isSuperProperty, isThisIdentifier, modifiersToFlags, Mutable, nodeIsSynthesized, + objectAllocator, pseudoBigIntToString, setEachParent, setParent, setTextRangePosEnd, setTextRangePosWidth, + skipParentheses, +} from "../utilities"; +import { + escapeLeadingUnderscores, getNameOfDeclaration, idText, isAssignmentPattern, isCallChain, isElementAccessChain, + isEntityName, isGeneratedIdentifier, isNamedDeclaration, isNodeArray, isNodeKind, isNonNullChain, isParseTreeNode, + isPropertyAccessChain, isPropertyName, isStatement, isStatementOrBlock, +} from "../utilitiesPublic"; +import { visitNode } from "../visitorPublic"; +import { BaseNodeFactory, createBaseNodeFactory } from "./baseNodeFactory"; +import { getAllUnscopedEmitHelpers } from "./emitHelpers"; +import { + getCommentRange, getSourceMapRange, getSyntheticLeadingComments, getSyntheticTrailingComments, setEmitFlags, +} from "./emitNode"; +import { createNodeConverters, nullNodeConverters } from "./nodeConverters"; +import { + isArrayLiteralExpression, isArrowFunction, isBinaryExpression, isClassDeclaration, isClassExpression, + isCommaListExpression, isCommaToken, isComputedPropertyName, isConstructorDeclaration, isElementAccessExpression, + isEnumDeclaration, isExclamationToken, isExportAssignment, isExportDeclaration, isExternalModuleReference, + isFunctionDeclaration, isFunctionExpression, isGetAccessorDeclaration, isIdentifier, isImportDeclaration, + isImportEqualsDeclaration, isImportKeyword, isIndexSignatureDeclaration, isInterfaceDeclaration, isLabeledStatement, + isMethodDeclaration, isMethodSignature, isModuleDeclaration, isNotEmittedStatement, isObjectLiteralExpression, + isOmittedExpression, isParameter, isParenthesizedExpression, isPrivateIdentifier, isPropertyAccessExpression, + isPropertyDeclaration, isPropertySignature, isQuestionToken, isSetAccessorDeclaration, isSourceFile, + isStringLiteral, isSuperKeyword, isTypeAliasDeclaration, isVariableDeclaration, isVariableStatement, +} from "./nodeTests"; +import { createParenthesizerRules, nullParenthesizerRules } from "./parenthesizerRules"; +import { + findUseStrictPrologue, getElementsOfBindingOrAssignmentPattern, getJSDocTypeAliasName, + getTargetOfBindingOrAssignmentElement, isLocalName, isOuterExpression, skipOuterExpressions, startOnNewLine, +} from "./utilities"; +import { setTextRange } from "./utilitiesPublic"; let nextAutoGenerateId = 0; @@ -21,28 +121,28 @@ export const enum NodeFactoryFlags { * @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, @@ -160,11 +260,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN createObjectLiteralExpression, updateObjectLiteralExpression, createPropertyAccessExpression: flags & NodeFactoryFlags.NoIndentationOnFreshPropertyAccess ? - (expression, name) => ts.setEmitFlags(createPropertyAccessExpression(expression, name), ts.EmitFlags.NoIndentation) : + (expression, name) => setEmitFlags(createPropertyAccessExpression(expression, name), EmitFlags.NoIndentation) : createPropertyAccessExpression, updatePropertyAccessExpression, createPropertyAccessChain: flags & NodeFactoryFlags.NoIndentationOnFreshPropertyAccess ? - (expression, questionDotToken, name) => ts.setEmitFlags(createPropertyAccessChain(expression, questionDotToken, name), ts.EmitFlags.NoIndentation) : + (expression, questionDotToken, name) => setEmitFlags(createPropertyAccessChain(expression, questionDotToken, name), EmitFlags.NoIndentation) : createPropertyAccessChain, updatePropertyAccessChain, createElementAccessExpression, @@ -320,18 +420,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, @@ -367,30 +467,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, @@ -459,38 +559,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, @@ -536,29 +636,29 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN 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; } @@ -566,22 +666,22 @@ 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"], - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined ) { const node = createBaseNode(kind); node.decorators = asNodeArray(decorators); @@ -598,11 +698,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return node; } - function createBaseNamedDeclaration( + function createBaseNamedDeclaration( kind: T["kind"], - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: ts.Identifier | ts.PrivateIdentifier | ts.StringLiteralLike | ts.NumericLiteral | ts.ComputedPropertyName | ts.BindingPattern | string | undefined + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined ) { const node = createBaseDeclaration( kind, @@ -617,12 +717,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; } @@ -635,12 +735,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return node; } - function createBaseGenericNamedDeclaration }>( + function createBaseGenericNamedDeclaration }>( kind: T["kind"], - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: ts.Identifier | ts.PrivateIdentifier | ts.StringLiteralLike | ts.NumericLiteral | ts.ComputedPropertyName | ts.BindingPattern | string | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined ) { const node = createBaseNamedDeclaration( kind, @@ -650,18 +750,18 @@ 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"], - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | 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 + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | 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, @@ -675,24 +775,24 @@ 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; return node; } - function updateBaseSignatureDeclaration(updated: ts.Mutable, original: T) { + function updateBaseSignatureDeclaration(updated: Mutable, original: T) { // copy children used only for error reporting if (original.typeArguments) updated.typeArguments = original.typeArguments; return update(updated, original); } - function createBaseFunctionLikeDeclaration( + function createBaseFunctionLikeDeclaration( kind: T["kind"], - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | 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, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | 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( @@ -705,25 +805,25 @@ 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 updateBaseFunctionLikeDeclaration(updated: ts.Mutable, original: T) { + function updateBaseFunctionLikeDeclaration(updated: Mutable, original: T) { // copy children used only for error reporting if (original.exclamationToken) updated.exclamationToken = original.exclamationToken; if (original.typeArguments) updated.typeArguments = original.typeArguments; return updateBaseSignatureDeclaration(updated, original); } - function createBaseInterfaceOrClassLikeDeclaration( + function createBaseInterfaceOrClassLikeDeclaration( kind: T["kind"], - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.Identifier | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - heritageClauses: readonly ts.HeritageClause[] | undefined + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined ) { const node = createBaseGenericNamedDeclaration( kind, @@ -737,14 +837,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return node; } - function createBaseClassLikeDeclaration( + function createBaseClassLikeDeclaration( kind: T["kind"], - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.Identifier | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - heritageClauses: readonly ts.HeritageClause[] | undefined, - members: readonly ts.ClassElement[] + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[] ) { const node = createBaseInterfaceOrClassLikeDeclaration( kind, @@ -759,12 +859,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return node; } - function createBaseBindingLikeDeclaration( + function createBaseBindingLikeDeclaration( kind: T["kind"], - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, name: string | T["name"] | undefined, - initializer: ts.Expression | undefined + initializer: Expression | undefined ) { const node = createBaseNamedDeclaration( kind, @@ -777,13 +877,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return node; } - function createBaseVariableLikeDeclaration( + function createBaseVariableLikeDeclaration( kind: T["kind"], - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, name: string | T["name"] | undefined, - type: ts.TypeNode | undefined, - initializer: ts.Expression | undefined + type: TypeNode | undefined, + initializer: Expression | undefined ) { const node = createBaseBindingLikeDeclaration( kind, @@ -794,7 +894,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; } @@ -802,7 +902,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // Literals // - function createBaseLiteral( + function createBaseLiteral( kind: T["kind"], text: string ) { @@ -812,57 +912,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.StringLiteral { - const node = createBaseStringLiteral(ts.getTextOfIdentifierOrLiteral(sourceNode), /*isSingleQuote*/ undefined); + function createStringLiteralFromNode(sourceNode: PropertyNameLiteral): 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; } } @@ -870,21 +970,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) { - const node = createBaseIdentifier(text, /*originalKeywordKind*/ undefined) as ts.Mutable; + function createBaseGeneratedIdentifier(text: string, autoGenerateFlags: GeneratedIdentifierFlags) { + const node = createBaseIdentifier(text, /*originalKeywordKind*/ undefined) as Mutable; node.autoGenerateFlags = autoGenerateFlags; node.autoGenerateId = nextAutoGenerateId; nextAutoGenerateId++; @@ -892,29 +992,29 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createIdentifier(text: string, typeArguments?: readonly (ts.TypeNode | ts.TypeParameterDeclaration)[], originalKeywordKind?: ts.SyntaxKind): ts.Identifier { + function createIdentifier(text: string, typeArguments?: readonly (TypeNode | TypeParameterDeclaration)[], originalKeywordKind?: SyntaxKind): 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; } 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): ts.GeneratedIdentifier { - let flags = ts.GeneratedIdentifierFlags.Auto; - if (reservedInNestedScopes) flags |= ts.GeneratedIdentifierFlags.ReservedInNestedScopes; + function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean): GeneratedIdentifier { + let flags = GeneratedIdentifierFlags.Auto; + if (reservedInNestedScopes) flags |= GeneratedIdentifierFlags.ReservedInNestedScopes; const name = createBaseGeneratedIdentifier("", flags); if (recordTempVariable) { recordTempVariable(name); @@ -924,35 +1024,35 @@ 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); } /** Create a unique name based on the supplied text. */ // @api - function createUniqueName(text: string, flags: ts.GeneratedIdentifierFlags = ts.GeneratedIdentifierFlags.None): 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); + function createUniqueName(text: string, flags: GeneratedIdentifierFlags = GeneratedIdentifierFlags.None): 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); } /** Create a unique name generated for a node. */ // @api - function getGeneratedNameForNode(node: ts.Node | undefined, flags: ts.GeneratedIdentifierFlags = 0): ts.Identifier { - ts.Debug.assert(!(flags & ts.GeneratedIdentifierFlags.KindMask), "Argument out of range: flags"); - const name = createBaseGeneratedIdentifier(node && ts.isIdentifier(node) ? ts.idText(node) : "", ts.GeneratedIdentifierFlags.Node | flags); + function getGeneratedNameForNode(node: Node | undefined, flags: GeneratedIdentifierFlags = 0): Identifier { + Debug.assert(!(flags & GeneratedIdentifierFlags.KindMask), "Argument out of range: flags"); + const name = createBaseGeneratedIdentifier(node && isIdentifier(node) ? idText(node) : "", GeneratedIdentifierFlags.Node | flags); name.original = node; return name; } // @api - function createPrivateIdentifier(text: string): ts.PrivateIdentifier { - if (!ts.startsWith(text, "#")) ts.Debug.fail("First character of private identifier must be #: " + text); - const node = baseFactory.createBasePrivateIdentifierNode(ts.SyntaxKind.PrivateIdentifier) as ts.Mutable; - node.escapedText = ts.escapeLeadingUnderscores(text); - node.transformFlags |= ts.TransformFlags.ContainsClassFields; + function createPrivateIdentifier(text: string): PrivateIdentifier { + if (!startsWith(text, "#")) Debug.fail("First character of private identifier must be #: " + text); + const node = baseFactory.createBasePrivateIdentifierNode(SyntaxKind.PrivateIdentifier) as Mutable; + node.escapedText = escapeLeadingUnderscores(text); + node.transformFlags |= TransformFlags.ContainsClassFields; return node; } @@ -960,69 +1060,69 @@ 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.ThisKeyword: + case SyntaxKind.ThisKeyword: // 'this' indicates a lexical 'this' - transformFlags = ts.TransformFlags.ContainsLexicalThis; + transformFlags = TransformFlags.ContainsLexicalThis; break; } if (transformFlags) { @@ -1037,27 +1137,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); } // @@ -1065,27 +1165,27 @@ 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.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.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; } @@ -1094,8 +1194,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 |= @@ -1105,7 +1205,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) @@ -1113,18 +1213,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; @@ -1135,52 +1235,52 @@ 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; + function createTypeParameterDeclaration(modifiers: readonly Modifier[] | undefined, name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode): TypeParameterDeclaration; /** @deprecated */ - function createTypeParameterDeclaration(name: string | ts.Identifier, constraint?: ts.TypeNode, defaultType?: ts.TypeNode): ts.TypeParameterDeclaration; - function createTypeParameterDeclaration(modifiersOrName: readonly ts.Modifier[] | string | ts.Identifier | undefined , nameOrConstraint?: string | ts.Identifier | ts.TypeNode, constraintOrDefault?: ts.TypeNode, defaultType?: ts.TypeNode) { + function createTypeParameterDeclaration(name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode): TypeParameterDeclaration; + function createTypeParameterDeclaration(modifiersOrName: readonly Modifier[] | string | Identifier | undefined , nameOrConstraint?: string | Identifier | TypeNode, constraintOrDefault?: TypeNode, defaultType?: TypeNode) { let name; let modifiers; let constraint; - if (modifiersOrName === undefined || ts.isArray(modifiersOrName)) { + if (modifiersOrName === undefined || isArray(modifiersOrName)) { modifiers = modifiersOrName; - name = nameOrConstraint as string | ts.Identifier; + name = nameOrConstraint as string | Identifier; constraint = constraintOrDefault; } else { modifiers = undefined; name = modifiersOrName; - constraint = nameOrConstraint as ts.TypeNode | undefined; + constraint = nameOrConstraint as TypeNode | undefined; } - const node = createBaseNamedDeclaration( - ts.SyntaxKind.TypeParameter, + const node = createBaseNamedDeclaration( + SyntaxKind.TypeParameter, /*decorators*/ undefined, 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; /** @deprecated */ - function updateTypeParameterDeclaration(node: ts.TypeParameterDeclaration, name: ts.Identifier, constraint: ts.TypeNode | undefined, defaultType: ts.TypeNode | undefined): ts.TypeParameterDeclaration; - function updateTypeParameterDeclaration(node: ts.TypeParameterDeclaration, modifiersOrName: readonly ts.Modifier[] | ts.Identifier | undefined, nameOrConstraint: ts.Identifier | ts.TypeNode | undefined, constraintOrDefault: ts.TypeNode | undefined, defaultType?: ts.TypeNode | undefined) { + function updateTypeParameterDeclaration(node: TypeParameterDeclaration, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined): TypeParameterDeclaration; + function updateTypeParameterDeclaration(node: TypeParameterDeclaration, modifiersOrName: readonly Modifier[] | Identifier | undefined, nameOrConstraint: Identifier | TypeNode | undefined, constraintOrDefault: TypeNode | undefined, defaultType?: TypeNode | undefined) { let name; let modifiers; let constraint; - if (modifiersOrName === undefined || ts.isArray(modifiersOrName)) { + if (modifiersOrName === undefined || isArray(modifiersOrName)) { modifiers = modifiersOrName; - name = nameOrConstraint as ts.Identifier; + name = nameOrConstraint as Identifier; constraint = constraintOrDefault; } else { modifiers = undefined; name = modifiersOrName; - constraint = nameOrConstraint as ts.TypeNode | undefined; + constraint = nameOrConstraint as TypeNode | undefined; } return node.modifiers !== modifiers || node.name !== name @@ -1192,16 +1292,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createParameterDeclaration( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - dotDotDotToken: ts.DotDotDotToken | undefined, - name: string | ts.BindingName, - questionToken?: ts.QuestionToken, - type?: ts.TypeNode, - initializer?: ts.Expression + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + dotDotDotToken: DotDotDotToken | undefined, + name: string | BindingName, + questionToken?: QuestionToken, + type?: TypeNode, + initializer?: Expression ) { - const node = createBaseVariableLikeDeclaration( - ts.SyntaxKind.Parameter, + const node = createBaseVariableLikeDeclaration( + SyntaxKind.Parameter, decorators, modifiers, name, @@ -1210,30 +1310,30 @@ 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, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - dotDotDotToken: ts.DotDotDotToken | undefined, - name: string | ts.BindingName, - questionToken: ts.QuestionToken | undefined, - type: ts.TypeNode | undefined, - initializer: ts.Expression | undefined + node: ParameterDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + dotDotDotToken: DotDotDotToken | undefined, + name: string | BindingName, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined ) { return node.decorators !== decorators || node.modifiers !== modifiers @@ -1247,18 +1347,18 @@ 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); node.transformFlags |= propagateChildFlags(node.expression) | - ts.TransformFlags.ContainsTypeScript | - ts.TransformFlags.ContainsTypeScriptClassSyntax; + TransformFlags.ContainsTypeScript | + TransformFlags.ContainsTypeScriptClassSyntax; 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; @@ -1270,30 +1370,30 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createPropertySignature( - modifiers: readonly ts.Modifier[] | undefined, - name: ts.PropertyName | string, - questionToken: ts.QuestionToken | undefined, - type: ts.TypeNode | undefined - ): ts.PropertySignature { - const node = createBaseNamedDeclaration( - ts.SyntaxKind.PropertySignature, + modifiers: readonly Modifier[] | undefined, + name: PropertyName | string, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined + ): PropertySignature { + const node = createBaseNamedDeclaration( + SyntaxKind.PropertySignature, /*decorators*/ undefined, modifiers, name ); node.type = type; node.questionToken = questionToken; - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api function updatePropertySignature( - node: ts.PropertySignature, - modifiers: readonly ts.Modifier[] | undefined, - name: ts.PropertyName, - questionToken: ts.QuestionToken | undefined, - type: ts.TypeNode | undefined + node: PropertySignature, + modifiers: readonly Modifier[] | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined ) { return node.modifiers !== modifiers || node.name !== name @@ -1305,51 +1405,51 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createPropertyDeclaration( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.PropertyName, - questionOrExclamationToken: ts.QuestionToken | ts.ExclamationToken | undefined, - type: ts.TypeNode | undefined, - initializer: ts.Expression | undefined + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | 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, decorators, 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, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.PropertyName, - questionOrExclamationToken: ts.QuestionToken | ts.ExclamationToken | undefined, - type: ts.TypeNode | undefined, - initializer: ts.Expression | undefined + node: PropertyDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | PropertyName, + questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined ) { return node.decorators !== decorators || 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(decorators, modifiers, name, questionOrExclamationToken, type, initializer), node) @@ -1358,15 +1458,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createMethodSignature( - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.PropertyName, - questionToken: ts.QuestionToken | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined + modifiers: readonly Modifier[] | 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, /*decorators*/ undefined, modifiers, name, @@ -1375,19 +1475,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.Modifier[] | undefined, - name: ts.PropertyName, - questionToken: ts.QuestionToken | undefined, - typeParameters: ts.NodeArray | undefined, - parameters: ts.NodeArray, - type: ts.TypeNode | undefined + node: MethodSignature, + modifiers: readonly Modifier[] | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined ) { return node.modifiers !== modifiers || node.name !== name @@ -1401,18 +1501,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createMethodDeclaration( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | 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 + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | 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, decorators, modifiers, name, @@ -1426,36 +1526,36 @@ 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; } return node; } // @api function updateMethodDeclaration( - node: ts.MethodDeclaration, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | 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, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined ) { return node.decorators !== decorators || node.modifiers !== modifiers @@ -1472,29 +1572,29 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createClassStaticBlockDeclaration( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - body: ts.Block - ): ts.ClassStaticBlockDeclaration { - const node = createBaseGenericNamedDeclaration( - ts.SyntaxKind.ClassStaticBlockDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + body: Block + ): ClassStaticBlockDeclaration { + const node = createBaseGenericNamedDeclaration( + SyntaxKind.ClassStaticBlockDeclaration, decorators, modifiers, /*name*/ undefined, /*typeParameters*/ undefined ); node.body = body; - node.transformFlags = propagateChildFlags(body) | ts.TransformFlags.ContainsClassFields; + node.transformFlags = propagateChildFlags(body) | TransformFlags.ContainsClassFields; return node; } // @api function updateClassStaticBlockDeclaration( - node: ts.ClassStaticBlockDeclaration, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - body: ts.Block - ): ts.ClassStaticBlockDeclaration { + node: ClassStaticBlockDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + body: Block + ): ClassStaticBlockDeclaration { return node.decorators !== decorators || node.modifier !== modifiers || node.body !== body @@ -1504,13 +1604,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createConstructorDeclaration( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - body: ts.Block | undefined + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + parameters: readonly ParameterDeclaration[], + body: Block | undefined ) { - const node = createBaseFunctionLikeDeclaration( - ts.SyntaxKind.Constructor, + const node = createBaseFunctionLikeDeclaration( + SyntaxKind.Constructor, decorators, modifiers, /*name*/ undefined, @@ -1519,17 +1619,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN /*type*/ undefined, body ); - node.transformFlags |= ts.TransformFlags.ContainsES2015; + node.transformFlags |= TransformFlags.ContainsES2015; return node; } // @api function updateConstructorDeclaration( - node: ts.ConstructorDeclaration, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - body: ts.Block | undefined + node: ConstructorDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + parameters: readonly ParameterDeclaration[], + body: Block | undefined ) { return node.decorators !== decorators || node.modifiers !== modifiers @@ -1541,15 +1641,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createGetAccessorDeclaration( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.PropertyName, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined, - body: ts.Block | undefined + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | PropertyName, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined ) { - return createBaseFunctionLikeDeclaration( - ts.SyntaxKind.GetAccessor, + return createBaseFunctionLikeDeclaration( + SyntaxKind.GetAccessor, decorators, modifiers, name, @@ -1562,13 +1662,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateGetAccessorDeclaration( - node: ts.GetAccessorDeclaration, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: ts.PropertyName, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined, - body: ts.Block | undefined + node: GetAccessorDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: PropertyName, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined ) { return node.decorators !== decorators || node.modifiers !== modifiers @@ -1582,14 +1682,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createSetAccessorDeclaration( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.PropertyName, - parameters: readonly ts.ParameterDeclaration[], - body: ts.Block | undefined + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | PropertyName, + parameters: readonly ParameterDeclaration[], + body: Block | undefined ) { - return createBaseFunctionLikeDeclaration( - ts.SyntaxKind.SetAccessor, + return createBaseFunctionLikeDeclaration( + SyntaxKind.SetAccessor, decorators, modifiers, name, @@ -1602,12 +1702,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateSetAccessorDeclaration( - node: ts.SetAccessorDeclaration, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: ts.PropertyName, - parameters: readonly ts.ParameterDeclaration[], - body: ts.Block | undefined + node: SetAccessorDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: PropertyName, + parameters: readonly ParameterDeclaration[], + body: Block | undefined ) { return node.decorators !== decorators || node.modifiers !== modifiers @@ -1620,12 +1720,12 @@ 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, /*decorators*/ undefined, /*modifiers*/ undefined, /*name*/ undefined, @@ -1633,16 +1733,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN 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 @@ -1653,12 +1753,12 @@ 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, /*decorators*/ undefined, /*modifiers*/ undefined, /*name*/ undefined, @@ -1666,16 +1766,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN 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 @@ -1686,13 +1786,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createIndexSignature( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined - ): ts.IndexSignatureDeclaration { - const node = createBaseSignatureDeclaration( - ts.SyntaxKind.IndexSignature, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined + ): IndexSignatureDeclaration { + const node = createBaseSignatureDeclaration( + SyntaxKind.IndexSignature, decorators, modifiers, /*name*/ undefined, @@ -1700,17 +1800,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN parameters, type ); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api function updateIndexSignature( - node: ts.IndexSignatureDeclaration, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode + node: IndexSignatureDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode ) { return node.parameters !== parameters || node.type !== type @@ -1721,16 +1821,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) @@ -1742,22 +1842,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 @@ -1766,16 +1866,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) @@ -1784,12 +1884,12 @@ 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, /*decorators*/ undefined, /*modifiers*/ undefined, /*name*/ undefined, @@ -1797,16 +1897,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN parameters, type ); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @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 @@ -1819,17 +1919,17 @@ 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, /*decorators*/ undefined, modifiers, /*name*/ undefined, @@ -1837,16 +1937,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN 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); } @@ -1854,15 +1954,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 @@ -1874,25 +1974,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) @@ -1900,63 +2000,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 @@ -1966,81 +2066,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 @@ -2050,31 +2150,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) @@ -2082,46 +2182,46 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createImportTypeNode(argument: ts.TypeNode, qualifier?: ts.EntityName, typeArguments?: readonly ts.TypeNode[], isTypeOf?: boolean): ts.ImportTypeNode; - function createImportTypeNode(argument: ts.TypeNode, assertions?: ts.ImportTypeAssertionContainer, qualifier?: ts.EntityName, typeArguments?: readonly ts.TypeNode[], isTypeOf?: boolean): ts.ImportTypeNode; + function createImportTypeNode(argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean): ImportTypeNode; + function createImportTypeNode(argument: TypeNode, assertions?: ImportTypeAssertionContainer, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf?: boolean): ImportTypeNode; function createImportTypeNode( - argument: ts.TypeNode, - qualifierOrAssertions?: ts.EntityName | ts.ImportTypeAssertionContainer, - typeArgumentsOrQualifier?: readonly ts.TypeNode[] | ts.EntityName, - isTypeOfOrTypeArguments?: boolean | readonly ts.TypeNode[], + argument: TypeNode, + qualifierOrAssertions?: EntityName | ImportTypeAssertionContainer, + typeArgumentsOrQualifier?: readonly TypeNode[] | EntityName, + isTypeOfOrTypeArguments?: boolean | readonly TypeNode[], isTypeOf?: boolean ) { - const assertion = qualifierOrAssertions && qualifierOrAssertions.kind === ts.SyntaxKind.ImportTypeAssertionContainer ? qualifierOrAssertions : undefined; - const qualifier = qualifierOrAssertions && ts.isEntityName(qualifierOrAssertions) ? qualifierOrAssertions - : typeArgumentsOrQualifier && !ts.isArray(typeArgumentsOrQualifier) ? typeArgumentsOrQualifier : undefined; - const typeArguments = ts.isArray(typeArgumentsOrQualifier) ? typeArgumentsOrQualifier : ts.isArray(isTypeOfOrTypeArguments) ? isTypeOfOrTypeArguments : undefined; + const assertion = qualifierOrAssertions && qualifierOrAssertions.kind === SyntaxKind.ImportTypeAssertionContainer ? qualifierOrAssertions : undefined; + const qualifier = qualifierOrAssertions && isEntityName(qualifierOrAssertions) ? qualifierOrAssertions + : typeArgumentsOrQualifier && !isArray(typeArgumentsOrQualifier) ? typeArgumentsOrQualifier : undefined; + const typeArguments = isArray(typeArgumentsOrQualifier) ? typeArgumentsOrQualifier : isArray(isTypeOfOrTypeArguments) ? isTypeOfOrTypeArguments : undefined; isTypeOf = typeof isTypeOfOrTypeArguments === "boolean" ? isTypeOfOrTypeArguments : typeof isTypeOf === "boolean" ? isTypeOf : false; - const node = createBaseNode(ts.SyntaxKind.ImportType); + const node = createBaseNode(SyntaxKind.ImportType); node.argument = argument; node.assertions = assertion; 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, qualifier: ts.EntityName | undefined, typeArguments: readonly ts.TypeNode[] | undefined, isTypeOf?: boolean | undefined): ts.ImportTypeNode; - function updateImportTypeNode(node: ts.ImportTypeNode, argument: ts.TypeNode, assertions: ts.ImportTypeAssertionContainer | undefined, qualifier: ts.EntityName | undefined, typeArguments: readonly ts.TypeNode[] | undefined, isTypeOf?: boolean | undefined): ts.ImportTypeNode; + function updateImportTypeNode(node: ImportTypeNode, argument: TypeNode, qualifier: EntityName | undefined, typeArguments: readonly TypeNode[] | undefined, isTypeOf?: boolean | undefined): ImportTypeNode; + function updateImportTypeNode(node: ImportTypeNode, argument: TypeNode, assertions: ImportTypeAssertionContainer | undefined, qualifier: EntityName | undefined, typeArguments: readonly TypeNode[] | undefined, isTypeOf?: boolean | undefined): ImportTypeNode; function updateImportTypeNode( - node: ts.ImportTypeNode, - argument: ts.TypeNode, - qualifierOrAssertions: ts.EntityName | ts.ImportTypeAssertionContainer | undefined, - typeArgumentsOrQualifier: readonly ts.TypeNode[] | ts.EntityName | undefined, - isTypeOfOrTypeArguments: boolean | readonly ts.TypeNode[] | undefined, + node: ImportTypeNode, + argument: TypeNode, + qualifierOrAssertions: EntityName | ImportTypeAssertionContainer | undefined, + typeArgumentsOrQualifier: readonly TypeNode[] | EntityName | undefined, + isTypeOfOrTypeArguments: boolean | readonly TypeNode[] | undefined, isTypeOf?: boolean | undefined ) { - const assertion = qualifierOrAssertions && qualifierOrAssertions.kind === ts.SyntaxKind.ImportTypeAssertionContainer ? qualifierOrAssertions : undefined; - const qualifier = qualifierOrAssertions && ts.isEntityName(qualifierOrAssertions) ? qualifierOrAssertions - : typeArgumentsOrQualifier && !ts.isArray(typeArgumentsOrQualifier) ? typeArgumentsOrQualifier : undefined; - const typeArguments = ts.isArray(typeArgumentsOrQualifier) ? typeArgumentsOrQualifier : ts.isArray(isTypeOfOrTypeArguments) ? isTypeOfOrTypeArguments : undefined; + const assertion = qualifierOrAssertions && qualifierOrAssertions.kind === SyntaxKind.ImportTypeAssertionContainer ? qualifierOrAssertions : undefined; + const qualifier = qualifierOrAssertions && isEntityName(qualifierOrAssertions) ? qualifierOrAssertions + : typeArgumentsOrQualifier && !isArray(typeArgumentsOrQualifier) ? typeArgumentsOrQualifier : undefined; + const typeArguments = isArray(typeArgumentsOrQualifier) ? typeArgumentsOrQualifier : isArray(isTypeOfOrTypeArguments) ? isTypeOfOrTypeArguments : undefined; isTypeOf = typeof isTypeOfOrTypeArguments === "boolean" ? isTypeOfOrTypeArguments : typeof isTypeOf === "boolean" ? isTypeOf : node.isTypeOf; return node.argument !== argument @@ -2134,15 +2234,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; @@ -2150,40 +2250,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) @@ -2191,20 +2291,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 @@ -2216,15 +2316,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; @@ -2235,50 +2335,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, /*decorators*/ undefined, /*modifiers*/ undefined, name, @@ -2288,18 +2388,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 @@ -2312,20 +2412,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); @@ -2333,15 +2433,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); @@ -2349,36 +2449,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); node.name = asName(name); node.transformFlags = propagateChildFlags(node.expression) | - (ts.isIdentifier(node.name) ? + (isIdentifier(node.name) ? propagateIdentifierNameFlags(node.name) : propagateChildFlags(node.name)); - 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 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 @@ -2387,25 +2487,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); 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)); 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 @@ -2416,26 +2516,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); 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 @@ -2445,9 +2545,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); node.questionDotToken = questionDotToken; node.argumentExpression = asExpression(index); @@ -2455,13 +2555,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 @@ -2472,8 +2572,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); node.typeArguments = asNodeArray(typeArguments); node.arguments = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray)); @@ -2482,20 +2582,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 @@ -2506,9 +2606,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); node.questionDotToken = questionDotToken; node.typeArguments = asNodeArray(typeArguments); @@ -2518,19 +2618,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 @@ -2540,8 +2640,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; @@ -2549,15 +2649,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 @@ -2566,8 +2666,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); node.typeArguments = asNodeArray(typeArguments); node.template = template; @@ -2575,18 +2675,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 @@ -2595,19 +2695,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) @@ -2615,15 +2715,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; @@ -2631,16 +2731,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createFunctionExpression( - modifiers: readonly ts.Modifier[] | 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 Modifier[] | 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, /*decorators*/ undefined, modifiers, name, @@ -2652,32 +2752,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.Modifier[] | 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 Modifier[] | 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 @@ -2692,15 +2792,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createArrowFunction( - modifiers: readonly ts.Modifier[] | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined, - equalsGreaterThanToken: ts.EqualsGreaterThanToken | undefined, - body: ts.ConciseBody + modifiers: readonly Modifier[] | 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, /*decorators*/ undefined, modifiers, /*name*/ undefined, @@ -2709,26 +2809,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.Modifier[] | 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 Modifier[] | 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 @@ -2740,119 +2840,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); @@ -2862,56 +2962,56 @@ 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; } 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 @@ -2920,12 +3020,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) | @@ -2938,13 +3038,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 @@ -2955,98 +3055,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) @@ -3054,18 +3154,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; @@ -3073,15 +3173,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createClassExpression( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.Identifier | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - heritageClauses: readonly ts.HeritageClause[] | undefined, - members: readonly ts.ClassElement[] + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | 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, decorators, modifiers, name, @@ -3089,19 +3189,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN heritageClauses, members ); - node.transformFlags |= ts.TransformFlags.ContainsES2015; + node.transformFlags |= TransformFlags.ContainsES2015; return node; } // @api function updateClassExpression( - node: ts.ClassExpression, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: ts.Identifier | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - heritageClauses: readonly ts.HeritageClause[] | undefined, - members: readonly ts.ClassElement[] + node: ClassExpression, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[] ) { return node.decorators !== decorators || node.modifiers !== modifiers @@ -3115,23 +3215,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); 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) @@ -3139,19 +3239,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) @@ -3159,18 +3259,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); 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 @@ -3179,45 +3279,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); 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; @@ -3228,19 +3328,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) @@ -3249,8 +3349,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; } @@ -3259,8 +3359,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); @@ -3268,26 +3368,26 @@ 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, /*decorators*/ undefined, modifiers); - node.declarationList = ts.isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList; + function createVariableStatement(modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]) { + const node = createBaseDeclaration(SyntaxKind.VariableStatement, /*decorators*/ undefined, modifiers); + node.declarationList = isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList; node.transformFlags |= 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) @@ -3296,27 +3396,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); @@ -3328,7 +3428,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 @@ -3337,8 +3437,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 |= @@ -3348,7 +3448,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) @@ -3356,8 +3456,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 |= @@ -3367,7 +3467,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) @@ -3375,8 +3475,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; @@ -3390,7 +3490,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 @@ -3400,8 +3500,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); @@ -3413,7 +3513,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 @@ -3422,8 +3522,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); @@ -3433,13 +3533,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 @@ -3449,61 +3549,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 |= @@ -3513,7 +3613,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) @@ -3521,8 +3621,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 |= @@ -3532,7 +3632,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) @@ -3540,8 +3640,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 |= @@ -3551,7 +3651,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) @@ -3559,23 +3659,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; @@ -3587,7 +3687,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 @@ -3597,13 +3697,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, /*decorators*/ undefined, /*modifiers*/ undefined, name, @@ -3613,13 +3713,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 @@ -3629,23 +3729,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; @@ -3653,17 +3753,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createFunctionDeclaration( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | 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 + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | 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, decorators, modifiers, name, @@ -3673,23 +3773,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; } } return node; @@ -3697,15 +3797,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateFunctionDeclaration( - node: ts.FunctionDeclaration, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | 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, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined ) { return node.decorators !== decorators || node.modifiers !== modifiers @@ -3721,15 +3821,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createClassDeclaration( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.Identifier | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - heritageClauses: readonly ts.HeritageClause[] | undefined, - members: readonly ts.ClassElement[] + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | 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, decorators, modifiers, name, @@ -3737,13 +3837,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN 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; @@ -3751,13 +3851,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateClassDeclaration( - node: ts.ClassDeclaration, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: ts.Identifier | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - heritageClauses: readonly ts.HeritageClause[] | undefined, - members: readonly ts.ClassElement[] + node: ClassDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[] ) { return node.decorators !== decorators || node.modifiers !== modifiers @@ -3771,15 +3871,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createInterfaceDeclaration( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.Identifier, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - heritageClauses: readonly ts.HeritageClause[] | undefined, - members: readonly ts.TypeElement[] + decorators: readonly Decorator[] | undefined, + 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, decorators, modifiers, name, @@ -3787,19 +3887,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN heritageClauses ); node.members = createNodeArray(members); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api function updateInterfaceDeclaration( - node: ts.InterfaceDeclaration, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: ts.Identifier, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - heritageClauses: readonly ts.HeritageClause[] | undefined, - members: readonly ts.TypeElement[] + node: InterfaceDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly TypeElement[] ) { return node.decorators !== decorators || node.modifiers !== modifiers @@ -3813,32 +3913,32 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createTypeAliasDeclaration( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.Identifier, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - type: ts.TypeNode + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + type: TypeNode ) { - const node = createBaseGenericNamedDeclaration( - ts.SyntaxKind.TypeAliasDeclaration, + const node = createBaseGenericNamedDeclaration( + SyntaxKind.TypeAliasDeclaration, decorators, modifiers, name, typeParameters ); node.type = type; - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api function updateTypeAliasDeclaration( - node: ts.TypeAliasDeclaration, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: ts.Identifier, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - type: ts.TypeNode + node: TypeAliasDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + type: TypeNode ) { return node.decorators !== decorators || node.modifiers !== modifiers @@ -3851,13 +3951,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createEnumDeclaration( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.Identifier, - members: readonly ts.EnumMember[] + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: string | Identifier, + members: readonly EnumMember[] ) { - const node = createBaseNamedDeclaration( - ts.SyntaxKind.EnumDeclaration, + const node = createBaseNamedDeclaration( + SyntaxKind.EnumDeclaration, decorators, modifiers, name @@ -3865,18 +3965,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN 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` return node; } // @api function updateEnumDeclaration( - node: ts.EnumDeclaration, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: ts.Identifier, - members: readonly ts.EnumMember[]) { + node: EnumDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: Identifier, + members: readonly EnumMember[]) { return node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name @@ -3887,40 +3987,40 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createModuleDeclaration( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: ts.ModuleName, - body: ts.ModuleBody | undefined, - flags = ts.NodeFlags.None + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: ModuleName, + body: ModuleBody | undefined, + flags = NodeFlags.None ) { - const node = createBaseDeclaration( - ts.SyntaxKind.ModuleDeclaration, + const node = createBaseDeclaration( + SyntaxKind.ModuleDeclaration, decorators, 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 |= 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`. return node; } // @api function updateModuleDeclaration( - node: ts.ModuleDeclaration, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - name: ts.ModuleName, - body: ts.ModuleBody | undefined + node: ModuleDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + name: ModuleName, + body: ModuleBody | undefined ) { return node.decorators !== decorators || node.modifiers !== modifiers @@ -3931,49 +4031,49 @@ 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, /*decorators*/ undefined, /*modifiers*/ undefined, name ); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateNamespaceExportDeclaration(node: ts.NamespaceExportDeclaration, name: ts.Identifier) { + function updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier) { return node.name !== name ? update(createNamespaceExportDeclaration(name), node) : node; @@ -3981,14 +4081,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createImportEqualsDeclaration( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, + decorators: readonly Decorator[] | 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, decorators, modifiers, name @@ -3996,19 +4096,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN 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 return node; } // @api function updateImportEqualsDeclaration( - node: ts.ImportEqualsDeclaration, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, + node: ImportEqualsDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, isTypeOnly: boolean, - name: ts.Identifier, - moduleReference: ts.ModuleReference + name: Identifier, + moduleReference: ModuleReference ) { return node.decorators !== decorators || node.modifiers !== modifiers @@ -4021,14 +4121,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createImportDeclaration( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - importClause: ts.ImportClause | undefined, - moduleSpecifier: ts.Expression, - assertClause: ts.AssertClause | undefined - ): ts.ImportDeclaration { - const node = createBaseDeclaration( - ts.SyntaxKind.ImportDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + importClause: ImportClause | undefined, + moduleSpecifier: Expression, + assertClause: AssertClause | undefined + ): ImportDeclaration { + const node = createBaseDeclaration( + SyntaxKind.ImportDeclaration, decorators, modifiers ); @@ -4038,18 +4138,18 @@ 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 return node; } // @api function updateImportDeclaration( - node: ts.ImportDeclaration, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - importClause: ts.ImportClause | undefined, - moduleSpecifier: ts.Expression, - assertClause: ts.AssertClause | undefined + node: ImportDeclaration, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + importClause: ImportClause | undefined, + moduleSpecifier: Expression, + assertClause: AssertClause | undefined ) { return node.decorators !== decorators || node.modifiers !== modifiers @@ -4061,8 +4161,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; @@ -4070,14 +4170,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 @@ -4086,16 +4186,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) @@ -4103,16 +4203,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) @@ -4120,15 +4220,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) @@ -4136,70 +4236,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 @@ -4209,31 +4309,31 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createExportAssignment( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, isExportEquals: boolean | undefined, - expression: ts.Expression + expression: Expression ) { - const node = createBaseDeclaration( - ts.SyntaxKind.ExportAssignment, + const node = createBaseDeclaration( + SyntaxKind.ExportAssignment, decorators, 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 |= 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 updateExportAssignment( - node: ts.ExportAssignment, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, - expression: ts.Expression + node: ExportAssignment, + decorators: readonly Decorator[] | undefined, + modifiers: readonly Modifier[] | undefined, + expression: Expression ) { return node.decorators !== decorators || node.modifiers !== modifiers @@ -4244,15 +4344,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createExportDeclaration( - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, + decorators: readonly Decorator[] | 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, decorators, modifiers ); @@ -4263,19 +4363,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN node.transformFlags |= 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 return node; } // @api function updateExportDeclaration( - node: ts.ExportDeclaration, - decorators: readonly ts.Decorator[] | undefined, - modifiers: readonly ts.Modifier[] | undefined, + node: ExportDeclaration, + decorators: readonly Decorator[] | undefined, + 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.decorators !== decorators || node.modifiers !== modifiers @@ -4288,36 +4388,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 @@ -4327,8 +4427,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createMissingDeclaration() { - const node = createBaseDeclaration( - ts.SyntaxKind.MissingDeclaration, + const node = createBaseDeclaration( + SyntaxKind.MissingDeclaration, /*decorators*/ undefined, /*modifiers*/ undefined ); @@ -4340,16 +4440,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; @@ -4362,18 +4462,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; } @@ -4382,7 +4482,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; @@ -4391,7 +4491,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; @@ -4401,16 +4501,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, /*decorators*/ undefined, /*modifiers*/ undefined, /*name*/ undefined, @@ -4422,7 +4522,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) @@ -4430,15 +4530,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) @@ -4446,22 +4546,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; @@ -4469,7 +4569,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 @@ -4477,15 +4577,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; @@ -4493,15 +4593,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 @@ -4511,16 +4611,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 @@ -4530,8 +4630,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; @@ -4540,7 +4640,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 @@ -4552,8 +4652,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; @@ -4562,7 +4662,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 @@ -4574,16 +4674,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 @@ -4593,14 +4693,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 @@ -4609,21 +4709,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 @@ -4632,22 +4732,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 |= @@ -4657,7 +4757,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) @@ -4665,52 +4765,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 @@ -4726,7 +4826,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; } @@ -4739,7 +4839,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) : @@ -4751,7 +4851,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; @@ -4762,7 +4862,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 @@ -4771,13 +4871,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) @@ -4785,29 +4885,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) @@ -4819,8 +4919,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; @@ -4828,12 +4928,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 @@ -4842,8 +4942,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; @@ -4851,15 +4951,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 @@ -4868,8 +4968,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; @@ -4877,15 +4977,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 @@ -4894,25 +4994,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; @@ -4920,12 +5020,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 @@ -4935,15 +5035,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) @@ -4952,32 +5052,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) @@ -4985,53 +5085,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; @@ -5042,8 +5142,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 |= @@ -5053,7 +5153,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) @@ -5061,50 +5161,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, @@ -5117,12 +5217,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) @@ -5134,9 +5234,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, /*decorators*/ undefined, /*modifiers*/ undefined, name @@ -5148,7 +5248,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return node; } - function finishUpdatePropertyAssignment(updated: ts.Mutable, original: ts.PropertyAssignment) { + function finishUpdatePropertyAssignment(updated: Mutable, original: PropertyAssignment) { // copy children used only for error reporting if (original.decorators) updated.decorators = original.decorators; if (original.modifiers) updated.modifiers = original.modifiers; @@ -5158,7 +5258,7 @@ 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) @@ -5166,9 +5266,9 @@ 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, /*decorators*/ undefined, /*modifiers*/ undefined, name @@ -5176,11 +5276,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN node.objectAssignmentInitializer = objectAssignmentInitializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(objectAssignmentInitializer); node.transformFlags |= propagateChildFlags(node.objectAssignmentInitializer) | - ts.TransformFlags.ContainsES2015; + TransformFlags.ContainsES2015; return node; } - function finishUpdateShorthandPropertyAssignment(updated: ts.Mutable, original: ts.ShorthandPropertyAssignment) { + function finishUpdateShorthandPropertyAssignment(updated: Mutable, original: ShorthandPropertyAssignment) { // copy children used only for error reporting if (original.decorators) updated.decorators = original.decorators; if (original.modifiers) updated.modifiers = original.modifiers; @@ -5191,7 +5291,7 @@ 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) @@ -5199,18 +5299,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; @@ -5221,19 +5321,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) @@ -5246,11 +5346,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; @@ -5268,17 +5368,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; @@ -5298,8 +5398,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, @@ -5317,15 +5417,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) @@ -5333,53 +5433,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; @@ -5390,8 +5490,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; @@ -5399,8 +5499,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; } @@ -5416,10 +5516,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; } @@ -5431,30 +5531,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]; } } @@ -5462,15 +5562,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; @@ -5481,9 +5581,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; } @@ -5493,16 +5593,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 |= @@ -5512,7 +5612,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) @@ -5520,8 +5620,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). @@ -5530,14 +5630,14 @@ 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) { @@ -5552,9 +5652,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, @@ -5570,9 +5670,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, @@ -5591,7 +5691,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return createVoidExpression(createNumericLiteral("0")); } - function createExportDefault(expression: ts.Expression) { + function createExportDefault(expression: Expression) { return createExportAssignment( /*decorators*/ undefined, /*modifiers*/ undefined, @@ -5599,7 +5699,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN expression); } - function createExternalModuleExport(exportName: ts.Identifier) { + function createExternalModuleExport(exportName: Identifier) { return createExportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, @@ -5614,15 +5714,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, @@ -5637,43 +5737,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; @@ -5681,8 +5781,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)); @@ -5692,17 +5792,17 @@ 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.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.NonNullExpression: return updateNonNullExpression(outerExpression, expression); + case SyntaxKind.PartiallyEmittedExpression: return updatePartiallyEmittedExpression(outerExpression, expression); } } @@ -5720,17 +5820,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) @@ -5739,14 +5839,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 ); @@ -5756,53 +5856,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); } - 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 @@ -5811,19 +5911,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 @@ -5832,7 +5932,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN ), callee.argumentExpression ); - ts.setTextRange(target, callee); + setTextRange(target, callee); } else { thisArg = callee.expression; @@ -5848,7 +5948,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( @@ -5876,23 +5976,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); @@ -5909,8 +6009,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); } /** @@ -5923,8 +6023,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); } /** @@ -5937,8 +6037,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); } /** @@ -5948,7 +6048,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); } @@ -5960,13 +6060,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; } @@ -5981,8 +6081,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); @@ -5995,17 +6095,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; } /** @@ -6016,13 +6116,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; } @@ -6046,14 +6146,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; @@ -6068,11 +6168,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; @@ -6083,9 +6183,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) { @@ -6096,10 +6196,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; } @@ -6133,20 +6233,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) { @@ -6169,13 +6269,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); } @@ -6183,15 +6283,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); @@ -6199,127 +6299,127 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN else { modifierArray = modifiers; } - return ts.isParameter(node) ? updateParameterDeclaration(node, node.decorators, modifierArray, node.dotDotDotToken, node.name, node.questionToken, node.type, node.initializer) : - ts.isPropertySignature(node) ? updatePropertySignature(node, modifierArray, node.name, node.questionToken, node.type) : - ts.isPropertyDeclaration(node) ? updatePropertyDeclaration(node, node.decorators, 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, node.decorators, modifierArray, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, node.type, node.body) : - ts.isConstructorDeclaration(node) ? updateConstructorDeclaration(node, node.decorators, modifierArray, node.parameters, node.body) : - ts.isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, node.decorators, modifierArray, node.name, node.parameters, node.type, node.body) : - ts.isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, node.decorators, modifierArray, node.name, node.parameters, node.body) : - ts.isIndexSignatureDeclaration(node) ? updateIndexSignature(node, node.decorators, 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, node.decorators, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) : - ts.isVariableStatement(node) ? updateVariableStatement(node, modifierArray, node.declarationList) : - ts.isFunctionDeclaration(node) ? updateFunctionDeclaration(node, node.decorators, modifierArray, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) : - ts.isClassDeclaration(node) ? updateClassDeclaration(node, node.decorators, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) : - ts.isInterfaceDeclaration(node) ? updateInterfaceDeclaration(node, node.decorators, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) : - ts.isTypeAliasDeclaration(node) ? updateTypeAliasDeclaration(node, node.decorators, modifierArray, node.name, node.typeParameters, node.type) : - ts.isEnumDeclaration(node) ? updateEnumDeclaration(node, node.decorators, modifierArray, node.name, node.members) : - ts.isModuleDeclaration(node) ? updateModuleDeclaration(node, node.decorators, modifierArray, node.name, node.body) : - ts.isImportEqualsDeclaration(node) ? updateImportEqualsDeclaration(node, node.decorators, modifierArray, node.isTypeOnly, node.name, node.moduleReference) : - ts.isImportDeclaration(node) ? updateImportDeclaration(node, node.decorators, modifierArray, node.importClause, node.moduleSpecifier, node.assertClause) : - ts.isExportAssignment(node) ? updateExportAssignment(node, node.decorators, modifierArray, node.expression) : - ts.isExportDeclaration(node) ? updateExportDeclaration(node, node.decorators, 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 isParameter(node) ? updateParameterDeclaration(node, node.decorators, modifierArray, node.dotDotDotToken, node.name, node.questionToken, node.type, node.initializer) : + isPropertySignature(node) ? updatePropertySignature(node, modifierArray, node.name, node.questionToken, node.type) : + isPropertyDeclaration(node) ? updatePropertyDeclaration(node, node.decorators, 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, node.decorators, modifierArray, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, node.type, node.body) : + isConstructorDeclaration(node) ? updateConstructorDeclaration(node, node.decorators, modifierArray, node.parameters, node.body) : + isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, node.decorators, modifierArray, node.name, node.parameters, node.type, node.body) : + isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, node.decorators, modifierArray, node.name, node.parameters, node.body) : + isIndexSignatureDeclaration(node) ? updateIndexSignature(node, node.decorators, 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, node.decorators, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) : + isVariableStatement(node) ? updateVariableStatement(node, modifierArray, node.declarationList) : + isFunctionDeclaration(node) ? updateFunctionDeclaration(node, node.decorators, modifierArray, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) : + isClassDeclaration(node) ? updateClassDeclaration(node, node.decorators, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) : + isInterfaceDeclaration(node) ? updateInterfaceDeclaration(node, node.decorators, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) : + isTypeAliasDeclaration(node) ? updateTypeAliasDeclaration(node, node.decorators, modifierArray, node.name, node.typeParameters, node.type) : + isEnumDeclaration(node) ? updateEnumDeclaration(node, node.decorators, modifierArray, node.name, node.members) : + isModuleDeclaration(node) ? updateModuleDeclaration(node, node.decorators, modifierArray, node.name, node.body) : + isImportEqualsDeclaration(node) ? updateImportEqualsDeclaration(node, node.decorators, modifierArray, node.isTypeOnly, node.name, node.moduleReference) : + isImportDeclaration(node) ? updateImportDeclaration(node, node.decorators, modifierArray, node.importClause, node.moduleSpecifier, node.assertClause) : + isExportAssignment(node) ? updateExportAssignment(node, node.decorators, modifierArray, node.expression) : + isExportDeclaration(node) ? updateExportDeclaration(node, node.decorators, 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: T, original: T): T { +function updateWithoutOriginal(updated: T, original: T): T { if (updated !== original) { - ts.setTextRange(updated, original); + setTextRange(updated, original); } return updated; } -function updateWithOriginal(updated: T, original: T): T { +function updateWithOriginal(updated: T, 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: // tslint:disable-next-line no-invalid-template-strings rawTextScanner.setText("`" + rawText + "${"); break; - case ts.SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateMiddle: // tslint:disable-next-line no-invalid-template-strings 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); } @@ -6330,15 +6430,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; } @@ -6347,27 +6447,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); } @@ -6378,85 +6478,85 @@ 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.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.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)), @@ -6466,12 +6566,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); @@ -6481,15 +6581,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; @@ -6503,7 +6603,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; @@ -6513,7 +6613,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; } @@ -6521,119 +6621,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; } @@ -6641,7 +6741,7 @@ function parseOldFileOfCurrentEmit(bundleFileInfo: ts.BundleFileInfo) { export function createInputFiles( javascriptText: string, declarationText: string -): ts.InputFiles; +): InputFiles; export function createInputFiles( readFileText: (path: string) => string | undefined, javascriptPath: string, @@ -6649,7 +6749,7 @@ export function createInputFiles( declarationPath: string, declarationMapPath: string | undefined, buildInfoPath: string | undefined -): ts.InputFiles; +): InputFiles; export function createInputFiles( javascriptText: string, declarationText: string, @@ -6657,7 +6757,7 @@ export function createInputFiles( javascriptMapText: string | undefined, declarationMapPath: string | undefined, declarationMapText: string | undefined -): ts.InputFiles; +): InputFiles; /*@internal*/ export function createInputFiles( javascriptText: string, @@ -6669,9 +6769,9 @@ export function createInputFiles( javascriptPath: string | undefined, declarationPath: string | undefined, buildInfoPath?: string | undefined, - buildInfo?: ts.BuildInfo, + buildInfo?: BuildInfo, oldFileOfCurrentEmit?: boolean -): ts.InputFiles; +): InputFiles; export function createInputFiles( javascriptTextOrReadFileText: string | ((path: string) => string | undefined), declarationTextOrJavascriptPath: string, @@ -6682,12 +6782,12 @@ export function createInputFiles( javascriptPath?: string | undefined, declarationPath?: string | undefined, buildInfoPath?: string | undefined, - buildInfo?: ts.BuildInfo, + buildInfo?: BuildInfo, oldFileOfCurrentEmit?: boolean -): ts.InputFiles { - const node = ts.parseNodeFactory.createInputFiles(); - if (!ts.isString(javascriptTextOrReadFileText)) { - const cache = new ts.Map(); +): InputFiles { + const node = parseNodeFactory.createInputFiles(); + if (!isString(javascriptTextOrReadFileText)) { + const cache = new Map(); const textGetter = (path: string | undefined) => { if (path === undefined) return undefined; let value = cache.get(path); @@ -6701,23 +6801,23 @@ export function createInputFiles( 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 = (getText: () => string | undefined) => { if (buildInfo === undefined) { const result = getText(); - buildInfo = result !== undefined ? ts.getBuildInfo(result) : false; + buildInfo = result !== undefined ? getBuildInfo(result) : false; } return buildInfo || undefined; }; node.javascriptPath = declarationTextOrJavascriptPath; node.javascriptMapPath = javascriptMapPath; - node.declarationPath = ts.Debug.checkDefined(javascriptMapTextOrDeclarationPath); + node.declarationPath = Debug.checkDefined(javascriptMapTextOrDeclarationPath); node.declarationMapPath = declarationMapPath; node.buildInfoPath = declarationMapTextOrBuildInfoPath; Object.defineProperties(node, { javascriptText: { get() { return definedTextGetter(declarationTextOrJavascriptPath); } }, javascriptMapText: { get() { return textGetter(javascriptMapPath); } }, // TODO:: if there is inline sourceMap in jsFile, use that - declarationText: { get() { return definedTextGetter(ts.Debug.checkDefined(javascriptMapTextOrDeclarationPath)); } }, + declarationText: { get() { return definedTextGetter(Debug.checkDefined(javascriptMapTextOrDeclarationPath)); } }, declarationMapText: { get() { return textGetter(declarationMapPath); } }, // TODO:: if there is inline sourceMap in dtsFile, use that buildInfo: { get() { return getAndCacheBuildInfo(() => textGetter(declarationMapTextOrBuildInfoPath)); } } }); @@ -6739,18 +6839,18 @@ export function createInputFiles( } // tslint:disable-next-line variable-name -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; @@ -6759,7 +6859,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, @@ -6771,25 +6871,25 @@ function mergeEmitNode(sourceEmitNode: ts.EmitNode, destEmitNode: ts.EmitNode | helpers, startsOnNewLine, } = 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; 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 8d86f37b140f1..17e22f40d12c1 100644 --- a/src/compiler/factory/nodeTests.ts +++ b/src/compiler/factory/nodeTests.ts @@ -1,762 +1,800 @@ -import * as ts from "../_namespaces/ts"; +import { + AbstractKeyword, 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, + 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, ParameterDeclaration, ParenthesizedExpression, ParenthesizedTypeNode, + PartiallyEmittedExpression, PlusToken, PostfixUnaryExpression, PrefixUnaryExpression, PrivateIdentifier, + PropertyAccessExpression, PropertyAssignment, PropertyDeclaration, PropertySignature, QualifiedName, + QuestionDotToken, QuestionToken, ReadonlyKeyword, RegularExpressionLiteral, RestTypeNode, ReturnStatement, + 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 "../types"; // 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 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 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 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 @@ -764,179 +802,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 aa522e540c476..e9c290aa88a7f 100644 --- a/src/compiler/factory/parenthesizerRules.ts +++ b/src/compiler/factory/parenthesizerRules.ts @@ -1,13 +1,33 @@ -import * as ts from "../_namespaces/ts"; +import { cast, compareValues, identity, last, sameMap, some } from "../core"; +import { Comparison, ESMap, Map } from "../corePublic"; +import { + BinaryExpression, BinaryOperator, ConciseBody, Expression, LeftHandSideExpression, NamedTupleMember, NewExpression, + NodeArray, NodeFactory, OuterExpressionKinds, ParenthesizerRules, SyntaxKind, TypeNode, UnaryExpression, +} from "../types"; +import { + Associativity, getExpressionAssociativity, getExpressionPrecedence, getLeftmostExpression, getOperatorAssociativity, + getOperatorPrecedence, OperatorPrecedence, +} from "../utilities"; +import { + isFunctionOrConstructorTypeNode, isLeftHandSideExpression, isLiteralKind, isNodeArray, isUnaryExpression, + skipPartiallyEmittedExpressions, +} from "../utilitiesPublic"; +import { + isBinaryExpression, isBlock, isCallExpression, isConditionalTypeNode, isConstructorTypeNode, isFunctionTypeNode, + isInferTypeNode, isIntersectionTypeNode, isJSDocNullableType, isNamedTupleMember, isTypeOperatorNode, + isUnionTypeNode, +} from "./nodeTests"; +import { isCommaSequence } from "./utilities"; +import { setTextRange } from "./utilitiesPublic"; /* @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 +62,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 +72,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 +90,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 +108,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 +143,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 +164,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 +181,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 +192,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 @@ -181,10 +201,10 @@ 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; + return binaryOperator === SyntaxKind.AsteriskToken + || binaryOperator === SyntaxKind.BarToken + || binaryOperator === SyntaxKind.AmpersandToken + || binaryOperator === SyntaxKind.CaretToken; } /** @@ -193,29 +213,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; } /** @@ -227,11 +247,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; } @@ -241,34 +261,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; } @@ -284,13 +304,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; } } @@ -301,16 +321,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); @@ -320,79 +340,79 @@ 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): ts.LeftHandSideExpression { + function parenthesizeLeftSideOfAccess(expression: Expression): 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)) { + const emittedExpression = skipPartiallyEmittedExpressions(expression); + if (isLeftHandSideExpression(emittedExpression) + && (emittedExpression.kind !== SyntaxKind.NewExpression || (emittedExpression as NewExpression).arguments)) { // 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; @@ -409,19 +429,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; @@ -432,17 +452,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] : @@ -450,17 +470,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] : @@ -470,17 +490,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); @@ -499,11 +519,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); @@ -539,27 +559,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); } @@ -585,51 +605,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 c6cb5832b18de..f36b0148da722 100644 --- a/src/compiler/factory/utilities.ts +++ b/src/compiler/factory/utilities.ts @@ -1,54 +1,97 @@ -import * as ts from "../_namespaces/ts"; +import { + AssertionLevel, compareStringsCaseSensitive, first, firstOrUndefined, map, or, pushIfUnique, some, +} from "../core"; +import { Debug } from "../debug"; +import { parseNodeFactory } from "../parser"; +import { + AccessorDeclaration, AdditiveOperator, AdditiveOperatorOrHigher, AssignmentOperatorOrHigher, BinaryExpression, + BinaryOperator, BinaryOperatorToken, BindingOrAssignmentElement, BindingOrAssignmentElementRestIndicator, + BindingOrAssignmentElementTarget, BindingOrAssignmentPattern, BitwiseOperator, BitwiseOperatorOrHigher, + BooleanLiteral, CommaListExpression, CompilerOptions, Declaration, EmitFlags, EmitHost, EmitResolver, EntityName, + EqualityOperator, EqualityOperatorOrHigher, ExclamationToken, ExponentiationOperator, ExportDeclaration, Expression, + ExpressionStatement, ForInitializer, HasModifiers, Identifier, ImportCall, ImportDeclaration, + ImportEqualsDeclaration, JSDocNamespaceBody, JSDocTypeAssertion, JsxOpeningFragment, JsxOpeningLikeElement, + LeftHandSideExpression, LiteralExpression, LogicalOperator, LogicalOperatorOrHigher, MemberExpression, + MethodDeclaration, MinusToken, ModuleKind, ModuleName, MultiplicativeOperator, MultiplicativeOperatorOrHigher, + NamedImportBindings, Node, NodeArray, NodeFactory, NullLiteral, NumericLiteral, ObjectLiteralElementLike, + ObjectLiteralExpression, OuterExpression, OuterExpressionKinds, PlusToken, PostfixUnaryExpression, + PrefixUnaryExpression, PrivateIdentifier, PropertyAssignment, PropertyName, QuestionToken, ReadonlyKeyword, + RelationalOperator, RelationalOperatorOrHigher, ShiftOperator, ShiftOperatorOrHigher, ShorthandPropertyAssignment, + SourceFile, Statement, StringLiteral, SyntaxKind, TextRange, ThisTypeNode, Token, TypeNode, + TypeParameterDeclaration, +} from "../types"; +import { + externalHelpersModuleNameText, getAllAccessorDeclarations, getEmitFlags, getEmitModuleKind, getESModuleInterop, + getExternalModuleName, getExternalModuleNameFromPath, getNamespaceDeclarationNode, + getSourceTextOfNodeFromSourceFile, isAssignmentExpression, isAssignmentOperator, isDefaultImport, + isEffectiveExternalModule, isExportNamespaceAsDefaultDeclaration, isFileLevelUniqueName, isInJSFile, + isPrologueDirective, Mutable, outFile, setParent, +} from "../utilities"; +import { + getJSDocType, getJSDocTypeTag, getOriginalNode, getParseTreeNode, idText, isDeclarationBindingElement, + isGeneratedIdentifier, isLiteralExpression, isMemberName, isObjectLiteralElementLike, isPropertyName, isTypeNode, +} from "../utilitiesPublic"; +import { EmitHelperFactory } from "./emitHelpers"; +import { addEmitFlags, getEmitHelpers, getOrCreateEmitNode, setStartsOnNewLine } from "./emitNode"; +import { setOriginalNode } from "./nodeFactory"; +import { + isBlock, isComputedPropertyName, isExclamationToken, isIdentifier, isMinusToken, isParenthesizedExpression, + isPlusToken, isPostfixUnaryExpression, isPrefixUnaryExpression, isPrivateIdentifier, isPropertyAssignment, + isQualifiedName, isQuestionToken, isReadonlyKeyword, isShorthandPropertyAssignment, isSourceFile, + isSpreadAssignment, isSpreadElement, isStringLiteral, isThisTypeNode, isTypeParameterDeclaration, + isVariableDeclarationList, +} from "./nodeTests"; +import { setTextRange } from "./utilitiesPublic"; // Compound nodes /* @internal */ -export function createEmptyExports(factory: ts.NodeFactory) { +export function createEmptyExports(factory: NodeFactory) { return factory.createExportDeclaration(/*decorators*/ undefined, /*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 +100,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 +110,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 +132,7 @@ export function createExpressionForJsxElement(factory: ts.NodeFactory, callee: t } } - return ts.setTextRange( + return setTextRange( factory.createCallExpression( callee, /*typeArguments*/ undefined, @@ -100,7 +143,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 +159,7 @@ export function createExpressionForJsxFragment(factory: ts.NodeFactory, jsxFacto } } - return ts.setTextRange( + return setTextRange( factory.createCallExpression( createJsxFactoryExpression(factory, jsxFactoryEntity, reactNamespace, parentElement), /*typeArguments*/ undefined, @@ -129,9 +172,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 +182,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 +191,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,46 +207,46 @@ 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( getAccessor.modifiers, /*asteriskToken*/ undefined, @@ -217,8 +260,8 @@ function createExpressionForAccessorDeclaration(factory: ts.NodeFactory, propert ), getAccessor ), - set: setAccessor && ts.setTextRange( - ts.setOriginalNode( + set: setAccessor && setTextRange( + setOriginalNode( factory.createFunctionExpression( setAccessor.modifiers, /*asteriskToken*/ undefined, @@ -241,9 +284,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 +297,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,13 +310,13 @@ 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( method.modifiers, method.asteriskToken, @@ -295,19 +338,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 +388,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 +421,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 +438,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,58 +462,58 @@ 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: - 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: + 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; } @@ -478,63 +521,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 +594,29 @@ export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: ts.N /*decorators*/ undefined, /*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 +628,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 +639,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 +663,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 +678,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 +691,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 +712,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 +724,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 +756,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 +777,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 +790,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 +832,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 +852,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,157 +948,157 @@ export function getJSDocTypeAliasName(fullName: ts.JSDocNamespaceBody | undefine } /* @internal */ -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.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.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.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.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; } /* @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 { /** @@ -1064,9 +1107,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; @@ -1078,9 +1121,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) { @@ -1096,9 +1139,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; @@ -1110,9 +1153,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) { @@ -1128,8 +1171,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) { @@ -1149,8 +1192,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; } @@ -1168,11 +1211,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; @@ -1180,10 +1223,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--; } } @@ -1195,11 +1238,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, ) { } @@ -1216,13 +1259,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. @@ -1234,35 +1277,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; } } diff --git a/src/compiler/factory/utilitiesPublic.ts b/src/compiler/factory/utilitiesPublic.ts index 47fbbd85dd68a..e8a8ddff12849 100644 --- a/src/compiler/factory/utilitiesPublic.ts +++ b/src/compiler/factory/utilitiesPublic.ts @@ -1,5 +1,6 @@ -import * as ts from "../_namespaces/ts"; +import { TextRange } from "../types"; +import { setTextRangePosEnd } from "../utilities"; -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; } \ No newline at end of file diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index aa2aa5d7e0004..2b8f139a4bad4 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -1,24 +1,57 @@ -import * as ts from "./_namespaces/ts"; +import { DiagnosticReporter } from "./commandLineParser"; +import { + append, appendIfUnique, arrayFrom, contains, createGetCanonicalFileName, emptyArray, endsWith, every, filter, + firstDefined, forEach, GetCanonicalFileName, getOwnKeys, hasProperty, isArray, isString, lastOrUndefined, length, + matchedText, noop, Pattern, patternText, removePrefix, some, sort, startsWith, stringContains, +} from "./core"; +import { Comparison, ESMap, Map, MapLike, Push, version, versionMajorMinor } from "./corePublic"; +import { Debug } from "./debug"; +import { Diagnostics } from "./diagnosticInformationMap.generated"; +import { getCommonSourceDirectory } from "./emitter"; +import { + changeAnyExtension, combinePaths, comparePaths, containsPath, directorySeparator, ensureTrailingDirectorySeparator, + fileExtensionIs, fileExtensionIsOneOf, forEachAncestorDirectory, getBaseFileName, getDirectoryPath, + getNormalizedAbsolutePath, getPathComponents, getPathFromPathComponents, getRelativePathFromDirectory, + getRootLength, hasTrailingDirectorySeparator, isRootedDiskPath, normalizePath, normalizeSlashes, pathIsRelative, + toPath, +} from "./path"; +import { perfLogger } from "./perfLogger"; +import { getModeForResolutionAtIndex } from "./program"; +import { Version, VersionRange } from "./semver"; +import { + CharacterCodes, CompilerOptions, Diagnostic, DiagnosticMessage, Extension, FileReference, GetEffectiveTypeRootsHost, + MatchingKeys, ModuleKind, ModuleResolutionHost, ModuleResolutionKind, PackageId, ParsedCommandLine, Path, + ResolvedModuleWithFailedLookupLocations, ResolvedProjectReference, ResolvedTypeReferenceDirective, + ResolvedTypeReferenceDirectiveWithFailedLookupLocations, SourceFile, +} from "./types"; +import { + createCompilerDiagnostic, directoryProbablyExists, extensionIsTS, formatMessage, getEmitModuleKind, + getEmitModuleResolutionKind, getPathsBasePath, getPossibleOriginalInputExtensionForExtension, hasJSFileExtension, + hasTSFileExtension, hostGetCanonicalFileName, matchPatternOrExact, optionsHaveModuleResolutionChanges, + packageIdToString, readJson, removeExtension, removeFileExtension, supportedTSExtensionsFlat, tryExtractTSExtension, + tryGetExtensionFromPath, tryParsePatterns, tryRemoveExtension, +} from "./utilities"; +import { isExternalModuleNameRelative } from "./utilitiesPublic"; /* @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.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 +65,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 +73,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 +91,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,18 +109,18 @@ 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 }; } -function createResolvedModuleWithFailedLookupLocations(resolved: Resolved | undefined, isExternalLibraryImport: boolean | undefined, failedLookupLocations: string[], diagnostics: ts.Diagnostic[], resultFromCache: ts.ResolvedModuleWithFailedLookupLocations | undefined): ts.ResolvedModuleWithFailedLookupLocations { +function createResolvedModuleWithFailedLookupLocations(resolved: Resolved | undefined, isExternalLibraryImport: boolean | undefined, failedLookupLocations: string[], diagnostics: Diagnostic[], resultFromCache: ResolvedModuleWithFailedLookupLocations | undefined): ResolvedModuleWithFailedLookupLocations { if (resultFromCache) { resultFromCache.failedLookupLocations.push(...failedLookupLocations); return resultFromCache; @@ -101,16 +134,16 @@ function createResolvedModuleWithFailedLookupLocations(resolved: Resolved | unde /*@internal*/ interface ModuleResolutionState { - host: ts.ModuleResolutionHost; - compilerOptions: ts.CompilerOptions; + host: ModuleResolutionHost; + compilerOptions: CompilerOptions; traceEnabled: boolean; - failedLookupLocations: ts.Push; - resultFromCache?: ts.ResolvedModuleWithFailedLookupLocations; + failedLookupLocations: Push; + resultFromCache?: ResolvedModuleWithFailedLookupLocations; packageJsonInfoCache: PackageJsonInfoCache | undefined; features: NodeResolutionFeatures; conditions: string[]; requestContainingDirectory: string | undefined; - reportDiagnostic: ts.DiagnosticReporter; + reportDiagnostic: DiagnosticReporter; } /** Just the fields that we use for module resolution. */ @@ -118,7 +151,7 @@ interface ModuleResolutionState { interface PackageJsonPathFields { typings?: string; types?: string; - typesVersions?: ts.MapLike>; + typesVersions?: MapLike>; main?: string; tsconfig?: string; type?: string; @@ -132,12 +165,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; } @@ -145,7 +178,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; } @@ -159,13 +192,13 @@ function readPackageJsonPathField; + paths: MapLike; } function readPackageJsonTypesVersionPaths(jsonContent: PackageJson, state: ModuleResolutionState): VersionPaths | undefined { @@ -206,8 +239,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); } } } @@ -215,7 +248,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; } @@ -223,7 +256,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; } @@ -231,16 +264,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; } @@ -252,14 +285,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); } @@ -290,11 +323,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; } /** @@ -302,21 +335,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; @@ -326,22 +359,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); } } @@ -354,11 +387,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, @@ -377,7 +410,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); @@ -394,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); } } @@ -410,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, @@ -426,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; } @@ -452,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; } @@ -471,8 +504,8 @@ 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: ModuleResolutionState = { @@ -481,16 +514,16 @@ export function resolvePackageNameToPackageJson( traceEnabled: isTraceEnabled(options, host), failedLookupLocations: [], packageJsonInfoCache: cache?.getPackageJsonInfoCache(), - conditions: ts.emptyArray, + conditions: emptyArray, features: NodeResolutionFeatures.None, requestContainingDirectory: containingDirectory, - reportDiagnostic: ts.noop + reportDiagnostic: noop }; - 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); } }); @@ -504,7 +537,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; @@ -518,17 +551,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); } @@ -541,15 +574,15 @@ export function getAutomaticTypeDirectiveNames(options: ts.CompilerOptions, host return result; } -export interface TypeReferenceDirectiveResolutionCache extends PerDirectoryResolutionCache, PackageJsonInfoCache { +export interface TypeReferenceDirectiveResolutionCache extends PerDirectoryResolutionCache, PackageJsonInfoCache { } 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; } @@ -558,16 +591,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; } @@ -576,35 +609,35 @@ export interface ModuleResolutionCache extends PerDirectoryResolutionCache { - 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, @@ -618,15 +651,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; } @@ -634,7 +667,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; @@ -647,24 +680,24 @@ 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 }; 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 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) { @@ -675,25 +708,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)); @@ -702,7 +735,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, @@ -713,20 +746,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) { @@ -755,7 +788,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; @@ -763,14 +796,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; @@ -779,21 +812,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 preDirectoryResolutionCache = createPerDirectoryResolutionCache(currentDirectory, getCanonicalFileName, directoryToModuleNameMap ||= createCacheWithRedirects(options)); @@ -815,22 +848,22 @@ export function createModuleResolutionCache( packageJsonInfoCache.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)); } /** @@ -844,8 +877,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; @@ -863,7 +896,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; } @@ -872,8 +905,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; @@ -881,14 +914,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; } @@ -900,23 +933,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 preDirectoryResolutionCache = createPerDirectoryResolutionCache(currentDirectory, getCanonicalFileName, directoryToModuleNameMap ||= createCacheWithRedirects(options)); packageJsonInfoCache ||= createPackageJsonInfoCache(currentDirectory, getCanonicalFileName); @@ -933,83 +966,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); } @@ -1019,14 +1052,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); } } @@ -1109,7 +1142,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 { @@ -1119,15 +1152,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); } } @@ -1140,10 +1173,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; @@ -1151,16 +1184,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) { @@ -1170,21 +1203,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) { @@ -1192,18 +1225,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; @@ -1215,13 +1248,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); } /** @@ -1230,7 +1263,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(", ")}`); @@ -1259,9 +1292,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, @@ -1274,9 +1307,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, @@ -1289,11 +1322,11 @@ function nodeNextModuleNameResolver(moduleName: string, containingFile: string, ); } -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; return nodeModuleNameResolverWorker(features | esmMode, moduleName, containingDirectory, compilerOptions, host, cache, compilerOptions.resolveJsonModule ? tsPlusJsonExtensions : tsExtensions, redirectedReference); } @@ -1301,13 +1334,13 @@ const jsOnlyExtensions = [Extensions.JavaScript]; const tsExtensions = [Extensions.TypeScript, Extensions.JavaScript]; const tsPlusJsonExtensions = [...tsExtensions, Extensions.Json]; const tsconfigExtensions = [Extensions.TSConfig]; -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; @@ -1320,10 +1353,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[] = []; @@ -1334,7 +1367,7 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa conditions.pop(); } - const diagnostics: ts.Diagnostic[] = []; + const diagnostics: Diagnostic[] = []; const state: ModuleResolutionState = { compilerOptions, host, @@ -1347,7 +1380,7 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa reportDiagnostic: diag => void diagnostics.push(diag), }; - const result = ts.forEach(extensions, ext => tryResolve(ext)); + const result = forEach(extensions, ext => tryResolve(ext)); return createResolvedModuleWithFailedLookupLocations(result?.value?.resolved, result?.value?.isExternalLibraryImport, failedLookupLocations, diagnostics, state.resultFromCache); function tryResolve(extensions: Extensions): SearchResult<{ resolved: Resolved, isExternalLibraryImport: boolean }> { @@ -1357,9 +1390,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) { @@ -1367,7 +1400,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); } @@ -1386,7 +1419,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") }); } } @@ -1398,36 +1431,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; } @@ -1440,10 +1473,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; } @@ -1461,7 +1494,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); } /** @@ -1476,7 +1509,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; @@ -1484,14 +1517,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; } @@ -1505,7 +1538,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); } @@ -1525,20 +1558,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); @@ -1548,67 +1581,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 }; } @@ -1620,22 +1653,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); } } } @@ -1653,8 +1686,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 { @@ -1676,7 +1709,7 @@ export function getEntrypointsFromPackageJsonInfo( conditions: ["node", "require", "types"], features, requestContainingDirectory: packageJsonInfo.packageDirectory, - reportDiagnostic: ts.noop + reportDiagnostic: noop }; const requireResolution = loadNodeModuleFromDirectoryWorker( extensions, @@ -1685,7 +1718,7 @@ export function getEntrypointsFromPackageJsonInfo( requireState, packageJsonInfo.packageJsonContent, packageJsonInfo.versionPaths); - entrypoints = ts.append(entrypoints, requireResolution?.path); + entrypoints = append(entrypoints, requireResolution?.path); if (features & NodeResolutionFeatures.Exports && packageJsonInfo.packageJsonContent.exports) { for (const conditions of [["node", "import", "types"], ["node", "require", "types"]]) { @@ -1697,7 +1730,7 @@ export function getEntrypointsFromPackageJsonInfo( extensions); if (exportResolutions) { for (const resolution of exportResolutions) { - entrypoints = ts.appendIfUnique(entrypoints, resolution.path); + entrypoints = appendIfUnique(entrypoints, resolution.path); } } } @@ -1713,15 +1746,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 { @@ -1730,16 +1763,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; } } @@ -1753,9 +1786,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; } }); @@ -1776,18 +1809,18 @@ interface PackageJsonInfo { * A function for locating the package.json scope for a given path */ /*@internal*/ - export function getPackageScopeForPath(fileName: ts.Path, packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ts.ModuleResolutionHost, options: ts.CompilerOptions): PackageJsonInfo | undefined { + export function getPackageScopeForPath(fileName: Path, packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions): PackageJsonInfo | undefined { const state: { - host: ts.ModuleResolutionHost; - compilerOptions: ts.CompilerOptions; + host: ModuleResolutionHost; + compilerOptions: CompilerOptions; traceEnabled: boolean; - failedLookupLocations: ts.Push; - resultFromCache?: ts.ResolvedModuleWithFailedLookupLocations; + failedLookupLocations: Push; + resultFromCache?: ResolvedModuleWithFailedLookupLocations; packageJsonInfoCache: PackageJsonInfoCache | undefined; features: number; conditions: never[]; requestContainingDirectory: string | undefined; - reportDiagnostic: ts.DiagnosticReporter + reportDiagnostic: DiagnosticReporter } = { host, compilerOptions: options, @@ -1797,12 +1830,12 @@ interface PackageJsonInfo { features: 0, conditions: [], requestContainingDirectory: undefined, - reportDiagnostic: ts.noop + reportDiagnostic: noop }; - 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; } @@ -1814,7 +1847,7 @@ interface PackageJsonInfo { /*@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; @@ -1823,20 +1856,20 @@ 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); return existing; } 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 = { packageDirectory, packageJsonContent, versionPaths, resolvedEntrypoints: undefined }; @@ -1845,7 +1878,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 @@ -1873,7 +1906,7 @@ function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: st packageFile = readPackageJsonTSConfigField(jsonContent, candidate, state); break; default: - return ts.Debug.assertNever(extensions); + return Debug.assertNever(extensions); } } @@ -1885,7 +1918,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); } } @@ -1905,14 +1938,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) { @@ -1932,48 +1965,48 @@ 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 { +function loadModuleFromSelfNameReference(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult { const useCaseSensitiveFileNames = typeof state.host.useCaseSensitiveFileNames === "function" ? state.host.useCaseSensitiveFileNames() : state.host.useCaseSensitiveFileNames; - const directoryPath = ts.toPath(ts.combinePaths(directory, "dummy"), state.host.getCurrentDirectory?.(), ts.createGetCanonicalFileName(useCaseSensitiveFileNames === undefined ? true : useCaseSensitiveFileNames)); + const directoryPath = toPath(combinePaths(directory, "dummy"), state.host.getCurrentDirectory?.(), createGetCanonicalFileName(useCaseSensitiveFileNames === undefined ? true : useCaseSensitiveFileNames)); const scope = getPackageScopeForPath(directoryPath, state.packageJsonInfoCache, state.host, state.compilerOptions); if (!scope || !scope.packageJsonContent.exports) { return undefined; @@ -1981,37 +2014,37 @@ function loadModuleFromSelfNameReference(extensions: Extensions, moduleName: str if (typeof scope.packageJsonContent.name !== "string") { return undefined; } - const parts = ts.getPathComponents(moduleName); // unrooted paths should have `""` as their 0th entry - const nameParts = ts.getPathComponents(scope.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.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.packageJsonContent.exports) { return undefined; } if (subpath === ".") { let mainExport; - if (typeof scope.packageJsonContent.exports === "string" || Array.isArray(scope.packageJsonContent.exports) || (typeof scope.packageJsonContent.exports === "object" && noKeyStartsWithDot(scope.packageJsonContent.exports as ts.MapLike))) { + if (typeof scope.packageJsonContent.exports === "string" || Array.isArray(scope.packageJsonContent.exports) || (typeof scope.packageJsonContent.exports === "object" && noKeyStartsWithDot(scope.packageJsonContent.exports as MapLike))) { mainExport = scope.packageJsonContent.exports; } - else if (ts.hasProperty(scope.packageJsonContent.exports as ts.MapLike, ".")) { - mainExport = (scope.packageJsonContent.exports as ts.MapLike)["."]; + else if (hasProperty(scope.packageJsonContent.exports as MapLike, ".")) { + mainExport = (scope.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.packageJsonContent.exports as ts.MapLike)) { + else if (allKeysStartWithDot(scope.packageJsonContent.exports as MapLike)) { if (typeof scope.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); } @@ -2022,30 +2055,30 @@ 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 useCaseSensitiveFileNames = typeof state.host.useCaseSensitiveFileNames === "function" ? state.host.useCaseSensitiveFileNames() : state.host.useCaseSensitiveFileNames; - const directoryPath = ts.toPath(ts.combinePaths(directory, "dummy"), state.host.getCurrentDirectory?.(), ts.createGetCanonicalFileName(useCaseSensitiveFileNames === undefined ? true : useCaseSensitiveFileNames)); + const directoryPath = toPath(combinePaths(directory, "dummy"), state.host.getCurrentDirectory?.(), createGetCanonicalFileName(useCaseSensitiveFileNames === undefined ? true : useCaseSensitiveFileNames)); const scope = getPackageScopeForPath(directoryPath, state.packageJsonInfoCache, state.host, state.compilerOptions); 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.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); } @@ -2056,19 +2089,19 @@ 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); } -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); } - const expandingKeys = ts.sort(ts.filter(ts.getOwnKeys(lookupTable as ts.MapLike), k => k.indexOf("*") !== -1 || ts.endsWith(k, "/")), (a, b) => a.length - b.length); + const expandingKeys = sort(filter(getOwnKeys(lookupTable as MapLike), k => k.indexOf("*") !== -1 || endsWith(k, "/")), (a, b) => a.length - b.length); for (const potentialTarget of expandingKeys) { if (state.features & NodeResolutionFeatures.ExportsPatternTrailers && matchesPatternWithTrailer(potentialTarget, moduleName)) { const target = (lookupTable as {[idx: string]: unknown})[potentialTarget]; @@ -2076,12 +2109,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); } - 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); } - 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); @@ -2089,65 +2122,65 @@ 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): 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; 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); } 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 key of ts.getOwnKeys(target as ts.MapLike)) { + for (const key of getOwnKeys(target as MapLike)) { if (key === "default" || state.conditions.indexOf(key) >= 0 || isApplicableVersionedTypesKey(state.conditions, key)) { - const subTarget = (target as ts.MapLike)[key]; + const subTarget = (target as MapLike)[key]; const result = loadModuleFromTargetImportOrExport(subTarget, subpath, pattern); if (result) { return result; @@ -2157,9 +2190,9 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo 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); } @@ -2173,12 +2206,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); @@ -2186,11 +2219,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.hostGetCanonicalFileName({ useCaseSensitiveFileNames })(ts.getNormalizedAbsolutePath(path, state.host.getCurrentDirectory?.())); + return hostGetCanonicalFileName({ useCaseSensitiveFileNames })(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() { @@ -2208,18 +2241,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.startsWith(toAbsolutePath(state.compilerOptions.configFile.fileName), scope.packageDirectory) : true) + && (state.compilerOptions.configFile ? startsWith(toAbsolutePath(state.compilerOptions.configFile.fileName), scope.packageDirectory) : 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) { @@ -2237,7 +2270,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 @@ -2245,23 +2278,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 )); @@ -2269,18 +2302,18 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo for (const commonSourceDirGuess of commonSourceDirGuesses) { const candidateDirectories = getOutputDirectoriesForBaseDirectory(commonSourceDirGuess); for (const candidateDir of candidateDirectories) { - if (ts.startsWith(finalPath, candidateDir)) { + if (startsWith(finalPath, candidateDir)) { // 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)) { @@ -2315,13 +2348,13 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo /* @internal */ export function isApplicableVersionedTypesKey(conditions: 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); } @@ -2330,10 +2363,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; @@ -2343,11 +2376,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); @@ -2355,11 +2388,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; } @@ -2367,8 +2400,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); @@ -2396,7 +2429,7 @@ function loadModuleFromSpecificNodeModulesDirectory(extensions: Extensions, modu const loader: ResolutionKindSpecificLoader = (extensions, candidate, onlyRecordFailures, state) => { // package exports are higher priority than file/directory lookups (and, if there's exports present, blocks them) if (packageInfo && packageInfo.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; } let pathAndExtension = loadModuleFromFile(extensions, candidate, onlyRecordFailures, state) || @@ -2416,21 +2449,21 @@ 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); }; if (rest !== "") { // If "rest" is empty, we just did this search above. - const packageDirectory = ts.combinePaths(nodeModulesDirectory, packageName); + const packageDirectory = combinePaths(nodeModulesDirectory, packageName); // Don't use a "types" or "main" from here because we're not loading the root, but a subdirectory -- just here for the packageId and path mappings. packageInfo = getPackageJsonInfo(packageDirectory, !nodeModulesDirectoryExists, state); if (packageInfo && packageInfo.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.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.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.versionPaths.paths, /*pathPatterns*/ undefined, loader, !packageDirectoryExists, state); if (fromPaths) { return fromPaths.value; @@ -2441,31 +2474,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 }; } @@ -2478,7 +2511,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; } @@ -2490,8 +2523,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 "@" } @@ -2501,7 +2534,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); } @@ -2510,8 +2543,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; } @@ -2519,18 +2552,18 @@ 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 containingDirectory = ts.getDirectoryPath(containingFile); - const diagnostics: ts.Diagnostic[] = []; + const containingDirectory = getDirectoryPath(containingFile); + const diagnostics: Diagnostic[] = []; const state: ModuleResolutionState = { compilerOptions, host, traceEnabled, failedLookupLocations, packageJsonInfoCache: cache, features: NodeResolutionFeatures.None, conditions: [], requestContainingDirectory: containingDirectory, reportDiagnostic: diag => void diagnostics.push(diag) }; const resolved = tryResolve(Extensions.TypeScript) || tryResolve(Extensions.JavaScript); @@ -2543,15 +2576,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) { @@ -2563,7 +2596,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)); } } @@ -2574,13 +2607,13 @@ 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 diagnostics: ts.Diagnostic[] = []; + const diagnostics: Diagnostic[] = []; const state: ModuleResolutionState = { compilerOptions, host, traceEnabled, failedLookupLocations, packageJsonInfoCache, features: NodeResolutionFeatures.None, conditions: [], requestContainingDirectory: undefined, reportDiagnostic: diag => void diagnostics.push(diag) }; const resolved = loadModuleFromImmediateNodeModulesDirectory(Extensions.DtsOnly, moduleName, globalCache, state, /*typesScopeOnly*/ false, /*cache*/ undefined, /*redirectedReference*/ undefined); return createResolvedModuleWithFailedLookupLocations(resolved, /*isExternalLibraryImport*/ true, failedLookupLocations, diagnostics, state.resultFromCache); diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index 1a3416e7f3f4f..c98ce7c6801b3 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -1,4 +1,36 @@ -import * as ts from "./_namespaces/ts"; +import { + append, arrayFrom, compareBooleans, createGetCanonicalFileName, emptyArray, endsWith, every, firstDefined, flatten, + forEach, GetCanonicalFileName, getOwnKeys, isString, mapDefined, removeSuffix, some, startsWith, stringContains, +} from "./core"; +import { Comparison, Map, MapLike } from "./corePublic"; +import { Debug } from "./debug"; +import { isModuleBlock, isModuleDeclaration, isSourceFile } from "./factory/nodeTests"; +import { + allKeysStartWithDot, getPackageJsonTypesVersionsPaths, getPackageNameFromTypesPackageName, + isApplicableVersionedTypesKey, pathContainsNodeModules, +} from "./moduleNameResolver"; +import { + combinePaths, comparePaths, containsPath, directorySeparator, ensurePathIsNonModuleName, + ensureTrailingDirectorySeparator, fileExtensionIsOneOf, forEachAncestorDirectory, getDirectoryPath, + getNormalizedAbsolutePath, getRelativePathFromDirectory, getRelativePathToDirectoryOrUrl, isRootedDiskPath, + normalizePath, pathIsBareSpecifier, pathIsRelative, removeTrailingDirectorySeparator, resolvePath, + startsWithDirectory, toPath, +} from "./path"; +import { getImpliedNodeFormatForFile, getModeForResolutionAtIndex, getModuleNameStringLiteralAt } from "./program"; +import { + __String, AmbientModuleDeclaration, CharacterCodes, CompilerOptions, ExportAssignment, Extension, FileIncludeKind, + Identifier, JsxEmit, ModuleDeclaration, ModuleKind, ModulePath, ModuleResolutionHost, ModuleResolutionKind, + ModuleSpecifierCache, ModuleSpecifierOptions, ModuleSpecifierResolutionHost, NodeFlags, Path, + PropertyAccessExpression, ScriptKind, SourceFile, StringLiteral, Symbol, SymbolFlags, TypeChecker, UserPreferences, +} from "./types"; +import { + compareNumberOfDirectorySeparators, containsIgnoredPath, extensionFromPath, getEmitModuleResolutionKind, + getNodeModulePathParts, getPathsBasePath, getSourceFileOfModule, getSupportedExtensions, + getTextOfIdentifierOrLiteral, hasJSFileExtension, hasTSFileExtension, hostGetCanonicalFileName, isAmbientModule, + isExternalModuleAugmentation, isNonGlobalAmbientModule, NodeModulePathParts, removeFileExtension, + tryGetExtensionFromPath, +} from "./utilities"; +import { isExternalModuleNameRelative } from "./utilitiesPublic"; // Used by importFixes, getEditsForFileRename, and declaration emit to synthesize import module specifiers. @@ -12,7 +44,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 +59,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 +98,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 +119,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, 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 +177,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 +196,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 +217,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 +238,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 +248,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 +276,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 +288,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 +297,8 @@ function computeModuleSpecifiers( if (!specifier && !modulePath.isRedirect) { const local = getLocalModuleSpecifier(modulePath.path, info, compilerOptions, host, 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,45 +310,45 @@ 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, { ending, relativePreference }: Preferences): string { +function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOptions: CompilerOptions, host: ModuleSpecifierResolutionHost, { 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; } const importRelativeToBaseUrl = removeExtensionAndIndexPostFix(relativeToBaseUrl, ending, compilerOptions); - const fromPaths = paths && tryGetModuleNameFromPaths(ts.removeFileExtension(relativeToBaseUrl), importRelativeToBaseUrl, paths); + const fromPaths = paths && tryGetModuleNameFromPaths(removeFileExtension(relativeToBaseUrl), importRelativeToBaseUrl, paths); const nonRelative = fromPaths === undefined && baseUrl !== undefined ? importRelativeToBaseUrl : fromPaths; if (!nonRelative) { return relativePath; @@ -328,11 +360,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. // @@ -345,7 +377,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. @@ -363,7 +395,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; @@ -372,26 +404,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; }); } @@ -399,45 +431,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; @@ -445,7 +477,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); } @@ -454,13 +486,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); @@ -473,9 +505,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, @@ -483,7 +515,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 @@ -491,15 +523,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); } @@ -510,12 +542,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); } @@ -523,10 +555,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; } @@ -541,45 +573,45 @@ 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 tryGetModuleNameFromPaths(relativeToBaseUrlWithIndex: string, relativeToBaseUrl: string, paths: ts.MapLike): string | undefined { +function tryGetModuleNameFromPaths(relativeToBaseUrlWithIndex: string, relativeToBaseUrl: string, paths: MapLike): string | undefined { for (const key in paths) { for (const patternText of paths[key]) { - const pattern = ts.removeFileExtension(ts.normalizePath(patternText)); + const pattern = removeFileExtension(normalizePath(patternText)); const indexOfStar = pattern.indexOf("*"); if (indexOfStar !== -1) { const prefix = pattern.substr(0, indexOfStar); const suffix = pattern.substr(indexOfStar + 1); if (relativeToBaseUrl.length >= prefix.length + suffix.length && - ts.startsWith(relativeToBaseUrl, prefix) && - ts.endsWith(relativeToBaseUrl, suffix) || - !suffix && relativeToBaseUrl === ts.removeTrailingDirectorySeparator(prefix)) { + startsWith(relativeToBaseUrl, prefix) && + endsWith(relativeToBaseUrl, suffix) || + !suffix && relativeToBaseUrl === removeTrailingDirectorySeparator(prefix)) { const matchedStar = relativeToBaseUrl.substr(prefix.length, relativeToBaseUrl.length - suffix.length - prefix.length); return key.replace("*", matchedStar); } @@ -597,31 +629,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) }; } @@ -629,28 +661,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; @@ -662,24 +694,24 @@ 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 normalizedTargetPath = getPathRelativeToRootDirs(moduleFileName, rootDirs, getCanonicalFileName); if (normalizedTargetPath === undefined) { return undefined; } const normalizedSourcePath = getPathRelativeToRootDirs(sourceDirectory, rootDirs, getCanonicalFileName); - const relativePath = normalizedSourcePath !== undefined ? ts.ensurePathIsNonModuleName(ts.getRelativePathFromDirectory(normalizedSourcePath, normalizedTargetPath, getCanonicalFileName)) : normalizedTargetPath; - return ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.NodeJs + const relativePath = normalizedSourcePath !== undefined ? ensurePathIsNonModuleName(getRelativePathFromDirectory(normalizedSourcePath, normalizedTargetPath, getCanonicalFileName)) : normalizedTargetPath; + return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeJs ? removeExtensionAndIndexPostFix(relativePath, ending, compilerOptions) - : ts.removeFileExtension(relativePath); + : removeFileExtension(relativePath); } -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; } @@ -695,7 +727,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 } @@ -711,7 +743,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; @@ -727,36 +759,36 @@ 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; const cachedPackageJson = host.getPackageJsonInfoCache?.()?.getPackageJsonInfo(packageJsonPath); if (typeof cachedPackageJson === "object" || cachedPackageJson === undefined && host.fileExists(packageJsonPath)) { const packageJsonContent = cachedPackageJson?.packageJsonContent || JSON.parse(host.readFile!(packageJsonPath)!); - if (ts.getEmitModuleResolutionKind(options) === ts.ModuleResolutionKind.Node16 || ts.getEmitModuleResolutionKind(options) === ts.ModuleResolutionKind.NodeNext) { + if (getEmitModuleResolutionKind(options) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeNext) { // `conditions` *could* be made to go against `importingSourceFile.impliedNodeFormat` if something wanted to generate // an ImportEqualsDeclaration in an ESM-implied file or an ImportCall in a CJS-implied file. But since this function is // usually called to conjure an import out of thin air, we don't have an existing usage to call `getModeForUsageAtIndex` // with, so for now we just stick with the mode of the file. - const conditions = ["node", overrideMode || importingSourceFile.impliedNodeFormat === ts.ModuleKind.ESNext ? "import" : "require", "types"]; + const conditions = ["node", overrideMode || importingSourceFile.impliedNodeFormat === 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) { @@ -764,24 +796,24 @@ 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); const fromPaths = tryGetModuleNameFromPaths( - ts.removeFileExtension(subModuleName), + removeFileExtension(subModuleName), removeExtensionAndIndexPostFix(subModuleName, Ending.Minimal, options), versionPaths.paths ); if (fromPaths !== undefined) { - 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)) { - const mainExportFile = ts.toPath(mainFileRelative, packageRootPath, getCanonicalFileName); - if (ts.removeFileExtension(mainExportFile) === ts.removeFileExtension(getCanonicalFileName(moduleFileToTry))) { + if (isString(mainFileRelative)) { + const mainExportFile = toPath(mainFileRelative, packageRootPath, getCanonicalFileName); + if (removeFileExtension(mainExportFile) === removeFileExtension(getCanonicalFileName(moduleFileToTry))) { return { packageRootPath, moduleFileToTry }; } } @@ -797,10 +829,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)) { @@ -809,21 +841,21 @@ function tryGetAnyFileFromPath(host: ts.ModuleSpecifierResolutionHost, path: str } } -function getPathRelativeToRootDirs(path: string, rootDirs: readonly string[], getCanonicalFileName: ts.GetCanonicalFileName): string | undefined { - return ts.firstDefined(rootDirs, rootDir => { +function getPathRelativeToRootDirs(path: string, rootDirs: readonly string[], getCanonicalFileName: GetCanonicalFileName): string | undefined { + return firstDefined(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? @@ -835,45 +867,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 2cd696c855170..e7e2b39881339 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1,4 +1,88 @@ import * as ts from "./_namespaces/ts"; +import { convertToObjectWorker } from "./commandLineParser"; +import { + addRange, append, AssertionLevel, concatenate, emptyArray, emptyMap, findIndex, forEach, getSpellingSuggestion, + isArray, lastOrUndefined, map, mapDefined, noop, some, startsWith, toArray, trimString, +} from "./core"; +import { ESMap, Map, Set } from "./corePublic"; +import { Debug } from "./debug"; +import { Diagnostics } from "./diagnosticInformationMap.generated"; +import { BaseNodeFactory } from "./factory/baseNodeFactory"; +import { createNodeFactory, NodeFactoryFlags } from "./factory/nodeFactory"; +import { + isAsyncModifier, isExportAssignment, isExportDeclaration, isExportModifier, isExternalModuleReference, + isFunctionTypeNode, isImportDeclaration, isImportEqualsDeclaration, isJSDocFunctionType, isJSDocNullableType, + isJSDocReturnTag, isJSDocTypeTag, isJsxOpeningElement, isJsxOpeningFragment, isMetaProperty, isNonNullExpression, + isPrivateIdentifier, isTaggedTemplateExpression, isTypeReferenceNode, +} from "./factory/nodeTests"; +import { setTextRange } from "./factory/utilitiesPublic"; +import { fileExtensionIsOneOf, normalizePath } from "./path"; +import { perfLogger } from "./perfLogger"; +import { mark, measure } from "./performance"; +import { + createScanner, getLeadingCommentRanges, isIdentifierText, skipTrivia, textToKeywordObj, tokenIsIdentifierOrKeyword, + tokenIsIdentifierOrKeywordOrGreaterThan, tokenToString, +} from "./scanner"; +import { tracing } from "./tracing"; +import { + AccessorDeclaration, AmdDependency, ArrayBindingElement, ArrayBindingPattern, ArrayLiteralExpression, ArrayTypeNode, + ArrowFunction, AsExpression, AssertClause, AssertEntry, AsteriskToken, AwaitExpression, BinaryExpression, + BinaryOperatorToken, BindingElement, BindingName, BindingPattern, Block, BooleanLiteral, BreakOrContinueStatement, + CallExpression, CallSignatureDeclaration, CaseBlock, CaseClause, CaseOrDefaultClause, CatchClause, CharacterCodes, + CheckJsDirective, ClassDeclaration, ClassElement, ClassExpression, ClassLikeDeclaration, + ClassStaticBlockDeclaration, CommaListExpression, CommentDirective, commentPragmas, CommentRange, + ComputedPropertyName, ConditionalExpression, ConditionalTypeNode, ConstructorDeclaration, + ConstructSignatureDeclaration, Decorator, DefaultClause, DeleteExpression, Diagnostic, DiagnosticMessage, + DiagnosticWithDetachedLocation, DoStatement, DotDotDotToken, ElementAccessExpression, EndOfFileToken, EntityName, + EnumDeclaration, EnumMember, ExclamationToken, ExportAssignment, ExportDeclaration, ExportSpecifier, Expression, + ExpressionStatement, ExpressionWithTypeArguments, ExternalModuleReference, FileReference, ForInOrOfStatement, + ForInStatement, ForOfStatement, ForStatement, FunctionDeclaration, FunctionExpression, FunctionLikeDeclaration, + FunctionOrConstructorTypeNode, HasJSDoc, HeritageClause, Identifier, IfStatement, ImportClause, ImportDeclaration, + ImportEqualsDeclaration, ImportOrExportSpecifier, ImportSpecifier, ImportTypeAssertionContainer, ImportTypeNode, + IndexedAccessTypeNode, IndexSignatureDeclaration, InferTypeNode, InterfaceDeclaration, IterationStatement, JSDoc, + JSDocAllType, JSDocAugmentsTag, JSDocAuthorTag, JSDocCallbackTag, JSDocComment, JSDocContainer, JSDocEnumTag, + JSDocFunctionType, JSDocImplementsTag, JSDocLink, JSDocLinkCode, JSDocLinkPlain, JSDocMemberName, + JSDocNameReference, JSDocNamespaceDeclaration, JSDocNullableType, JSDocOptionalType, JSDocParameterTag, + JSDocPropertyLikeTag, JSDocPropertyTag, JSDocReturnTag, JSDocSeeTag, JSDocSignature, JSDocSyntaxKind, JSDocTag, + JSDocTemplateTag, JSDocText, JSDocThisTag, JSDocTypedefTag, JSDocTypeExpression, JSDocTypeLiteral, + JSDocTypeReferencingNode, JSDocTypeTag, JSDocUnknownType, JsonMinusNumericLiteral, JsonObjectExpressionStatement, + JsonSourceFile, JsxAttribute, JsxAttributes, JsxAttributeValue, JsxChild, JsxClosingElement, JsxClosingFragment, + JsxElement, JsxExpression, JsxFragment, JsxOpeningElement, JsxOpeningFragment, JsxOpeningLikeElement, + JsxSelfClosingElement, JsxSpreadAttribute, JsxTagNameExpression, JsxTagNamePropertyAccess, JsxText, + JsxTokenSyntaxKind, LabeledStatement, LanguageVariant, LeftHandSideExpression, LiteralExpression, LiteralLikeNode, + LiteralTypeNode, MappedTypeNode, MemberExpression, MetaProperty, MethodDeclaration, MethodSignature, MinusToken, + MissingDeclaration, Modifier, ModifierFlags, ModifiersArray, ModuleBlock, ModuleDeclaration, ModuleKind, + NamedExportBindings, NamedExports, NamedImports, NamedImportsOrExports, NamedTupleMember, NamespaceDeclaration, + NamespaceExport, NamespaceExportDeclaration, NamespaceImport, NewExpression, Node, NodeArray, NodeFlags, + NonNullExpression, NoSubstitutionTemplateLiteral, NullLiteral, NumericLiteral, ObjectBindingPattern, + ObjectLiteralElementLike, ObjectLiteralExpression, OptionalTypeNode, ParameterDeclaration, ParenthesizedExpression, + ParenthesizedTypeNode, PartiallyEmittedExpression, 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, ScriptKind, ScriptTarget, SetAccessorDeclaration, ShorthandPropertyAssignment, + SignatureDeclaration, SourceFile, SpreadAssignment, SpreadElement, Statement, StringLiteral, SwitchStatement, + SyntaxKind, TaggedTemplateExpression, TemplateExpression, TemplateHead, TemplateLiteralToken, + TemplateLiteralTypeNode, TemplateLiteralTypeSpan, TemplateMiddle, TemplateSpan, TemplateTail, TextChangeRange, + TextRange, ThisExpression, ThisTypeNode, ThrowStatement, Token, TokenFlags, TransformFlags, TryStatement, + TupleTypeNode, TypeAliasDeclaration, TypeAssertion, TypeElement, TypeLiteralNode, TypeNode, TypeOfExpression, + TypeOperatorNode, TypeParameterDeclaration, TypePredicateNode, TypeQueryNode, TypeReferenceNode, UnaryExpression, + UnionOrIntersectionTypeNode, UpdateExpression, VariableDeclaration, VariableDeclarationList, VariableStatement, + VoidExpression, WhileStatement, WithStatement, YieldExpression, +} from "./types"; +import { + addRelatedInfo, attachFileToDiagnostics, containsParseError, createDetachedDiagnostic, ensureScriptKind, + getBinaryOperatorPrecedence, getFullWidth, getJSDocCommentRanges, getLanguageVariant, getLastChild, + getTextOfNodeFromSourceText, isAssignmentOperator, isKeyword, isStringOrNumericLiteralLike, modifiersToFlags, + Mutable, nodeIsMissing, nodeIsPresent, objectAllocator, OperatorPrecedence, setParent, setParentRecursive, + setTextRangePos, setTextRangePosEnd, setTextRangePosWidth, supportedDeclarationExtensions, +} from "./utilities"; +import { + createTextChangeRange, createTextSpanFromBounds, hasJSDocNodes, idText, isClassMemberModifier, + isLeftHandSideExpression, isLiteralKind, isModifierKind, isTemplateLiteralKind, textChangeRangeIsUnchanged, + textChangeRangeNewSpan, textSpanEnd, +} from "./utilitiesPublic"; const enum SignatureFlags { None = 0, @@ -15,32 +99,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,44 +140,44 @@ 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 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 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.Node, kind: ts.SyntaxKind) { - return ts.some(node.modifiers, m => m.kind === kind); +function hasModifierOfKind(node: Node, 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"; } /** @@ -109,510 +193,510 @@ function isImportMeta(node: ts.Node): boolean { * @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 || node.kind <= ts.SyntaxKind.LastToken) { +export function forEachChild(node: Node, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + if (!node || node.kind <= SyntaxKind.LastToken) { return; } switch (node.kind) { - case ts.SyntaxKind.QualifiedName: - return visitNode(cbNode, (node as ts.QualifiedName).left) || - visitNode(cbNode, (node as ts.QualifiedName).right); - case ts.SyntaxKind.TypeParameter: + case SyntaxKind.QualifiedName: + return visitNode(cbNode, (node as QualifiedName).left) || + visitNode(cbNode, (node as QualifiedName).right); + case SyntaxKind.TypeParameter: return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.TypeParameterDeclaration).name) || - visitNode(cbNode, (node as ts.TypeParameterDeclaration).constraint) || - visitNode(cbNode, (node as ts.TypeParameterDeclaration).default) || - visitNode(cbNode, (node as ts.TypeParameterDeclaration).expression); - case ts.SyntaxKind.ShorthandPropertyAssignment: + visitNode(cbNode, (node as TypeParameterDeclaration).name) || + visitNode(cbNode, (node as TypeParameterDeclaration).constraint) || + visitNode(cbNode, (node as TypeParameterDeclaration).default) || + visitNode(cbNode, (node as TypeParameterDeclaration).expression); + case SyntaxKind.ShorthandPropertyAssignment: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.ShorthandPropertyAssignment).name) || - visitNode(cbNode, (node as ts.ShorthandPropertyAssignment).questionToken) || - visitNode(cbNode, (node as ts.ShorthandPropertyAssignment).exclamationToken) || - visitNode(cbNode, (node as ts.ShorthandPropertyAssignment).equalsToken) || - visitNode(cbNode, (node as ts.ShorthandPropertyAssignment).objectAssignmentInitializer); - case ts.SyntaxKind.SpreadAssignment: - return visitNode(cbNode, (node as ts.SpreadAssignment).expression); - case ts.SyntaxKind.Parameter: + visitNode(cbNode, (node as ShorthandPropertyAssignment).name) || + visitNode(cbNode, (node as ShorthandPropertyAssignment).questionToken) || + visitNode(cbNode, (node as ShorthandPropertyAssignment).exclamationToken) || + visitNode(cbNode, (node as ShorthandPropertyAssignment).equalsToken) || + visitNode(cbNode, (node as ShorthandPropertyAssignment).objectAssignmentInitializer); + case SyntaxKind.SpreadAssignment: + return visitNode(cbNode, (node as SpreadAssignment).expression); + case SyntaxKind.Parameter: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.ParameterDeclaration).dotDotDotToken) || - visitNode(cbNode, (node as ts.ParameterDeclaration).name) || - visitNode(cbNode, (node as ts.ParameterDeclaration).questionToken) || - visitNode(cbNode, (node as ts.ParameterDeclaration).type) || - visitNode(cbNode, (node as ts.ParameterDeclaration).initializer); - case ts.SyntaxKind.PropertyDeclaration: + visitNode(cbNode, (node as ParameterDeclaration).dotDotDotToken) || + visitNode(cbNode, (node as ParameterDeclaration).name) || + visitNode(cbNode, (node as ParameterDeclaration).questionToken) || + visitNode(cbNode, (node as ParameterDeclaration).type) || + visitNode(cbNode, (node as ParameterDeclaration).initializer); + case SyntaxKind.PropertyDeclaration: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.PropertyDeclaration).name) || - visitNode(cbNode, (node as ts.PropertyDeclaration).questionToken) || - visitNode(cbNode, (node as ts.PropertyDeclaration).exclamationToken) || - visitNode(cbNode, (node as ts.PropertyDeclaration).type) || - visitNode(cbNode, (node as ts.PropertyDeclaration).initializer); - case ts.SyntaxKind.PropertySignature: + visitNode(cbNode, (node as PropertyDeclaration).name) || + visitNode(cbNode, (node as PropertyDeclaration).questionToken) || + visitNode(cbNode, (node as PropertyDeclaration).exclamationToken) || + visitNode(cbNode, (node as PropertyDeclaration).type) || + visitNode(cbNode, (node as PropertyDeclaration).initializer); + case SyntaxKind.PropertySignature: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.PropertySignature).name) || - visitNode(cbNode, (node as ts.PropertySignature).questionToken) || - visitNode(cbNode, (node as ts.PropertySignature).type) || - visitNode(cbNode, (node as ts.PropertySignature).initializer); - case ts.SyntaxKind.PropertyAssignment: + visitNode(cbNode, (node as PropertySignature).name) || + visitNode(cbNode, (node as PropertySignature).questionToken) || + visitNode(cbNode, (node as PropertySignature).type) || + visitNode(cbNode, (node as PropertySignature).initializer); + case SyntaxKind.PropertyAssignment: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.PropertyAssignment).name) || - visitNode(cbNode, (node as ts.PropertyAssignment).questionToken) || - visitNode(cbNode, (node as ts.PropertyAssignment).initializer); - case ts.SyntaxKind.VariableDeclaration: + visitNode(cbNode, (node as PropertyAssignment).name) || + visitNode(cbNode, (node as PropertyAssignment).questionToken) || + visitNode(cbNode, (node as PropertyAssignment).initializer); + case SyntaxKind.VariableDeclaration: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.VariableDeclaration).name) || - visitNode(cbNode, (node as ts.VariableDeclaration).exclamationToken) || - visitNode(cbNode, (node as ts.VariableDeclaration).type) || - visitNode(cbNode, (node as ts.VariableDeclaration).initializer); - case ts.SyntaxKind.BindingElement: + visitNode(cbNode, (node as VariableDeclaration).name) || + visitNode(cbNode, (node as VariableDeclaration).exclamationToken) || + visitNode(cbNode, (node as VariableDeclaration).type) || + visitNode(cbNode, (node as VariableDeclaration).initializer); + case SyntaxKind.BindingElement: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.BindingElement).dotDotDotToken) || - visitNode(cbNode, (node as ts.BindingElement).propertyName) || - visitNode(cbNode, (node as ts.BindingElement).name) || - visitNode(cbNode, (node as ts.BindingElement).initializer); - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.ConstructorType: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.IndexSignature: + visitNode(cbNode, (node as BindingElement).dotDotDotToken) || + visitNode(cbNode, (node as BindingElement).propertyName) || + visitNode(cbNode, (node as BindingElement).name) || + visitNode(cbNode, (node as BindingElement).initializer); + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.IndexSignature: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNodes(cbNode, cbNodes, (node as ts.SignatureDeclaration).typeParameters) || - visitNodes(cbNode, cbNodes, (node as ts.SignatureDeclaration).parameters) || - visitNode(cbNode, (node as ts.SignatureDeclaration).type); - case ts.SyntaxKind.MethodDeclaration: - 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: + visitNodes(cbNode, cbNodes, (node as SignatureDeclaration).typeParameters) || + visitNodes(cbNode, cbNodes, (node as SignatureDeclaration).parameters) || + visitNode(cbNode, (node as SignatureDeclaration).type); + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ArrowFunction: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.FunctionLikeDeclaration).asteriskToken) || - visitNode(cbNode, (node as ts.FunctionLikeDeclaration).name) || - visitNode(cbNode, (node as ts.FunctionLikeDeclaration).questionToken) || - visitNode(cbNode, (node as ts.FunctionLikeDeclaration).exclamationToken) || - visitNodes(cbNode, cbNodes, (node as ts.FunctionLikeDeclaration).typeParameters) || - visitNodes(cbNode, cbNodes, (node as ts.FunctionLikeDeclaration).parameters) || - visitNode(cbNode, (node as ts.FunctionLikeDeclaration).type) || - visitNode(cbNode, (node as ts.ArrowFunction).equalsGreaterThanToken) || - visitNode(cbNode, (node as ts.FunctionLikeDeclaration).body); - case ts.SyntaxKind.ClassStaticBlockDeclaration: + visitNode(cbNode, (node as FunctionLikeDeclaration).asteriskToken) || + visitNode(cbNode, (node as FunctionLikeDeclaration).name) || + visitNode(cbNode, (node as FunctionLikeDeclaration).questionToken) || + visitNode(cbNode, (node as FunctionLikeDeclaration).exclamationToken) || + visitNodes(cbNode, cbNodes, (node as FunctionLikeDeclaration).typeParameters) || + visitNodes(cbNode, cbNodes, (node as FunctionLikeDeclaration).parameters) || + visitNode(cbNode, (node as FunctionLikeDeclaration).type) || + visitNode(cbNode, (node as ArrowFunction).equalsGreaterThanToken) || + visitNode(cbNode, (node as FunctionLikeDeclaration).body); + case SyntaxKind.ClassStaticBlockDeclaration: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.ClassStaticBlockDeclaration).body); - case ts.SyntaxKind.TypeReference: - return visitNode(cbNode, (node as ts.TypeReferenceNode).typeName) || - visitNodes(cbNode, cbNodes, (node as ts.TypeReferenceNode).typeArguments); - case ts.SyntaxKind.TypePredicate: - return visitNode(cbNode, (node as ts.TypePredicateNode).assertsModifier) || - visitNode(cbNode, (node as ts.TypePredicateNode).parameterName) || - visitNode(cbNode, (node as ts.TypePredicateNode).type); - case ts.SyntaxKind.TypeQuery: - return visitNode(cbNode, (node as ts.TypeQueryNode).exprName) || - visitNodes(cbNode, cbNodes, (node as ts.TypeQueryNode).typeArguments); - case ts.SyntaxKind.TypeLiteral: - return visitNodes(cbNode, cbNodes, (node as ts.TypeLiteralNode).members); - case ts.SyntaxKind.ArrayType: - return visitNode(cbNode, (node as ts.ArrayTypeNode).elementType); - case ts.SyntaxKind.TupleType: - return visitNodes(cbNode, cbNodes, (node as ts.TupleTypeNode).elements); - case ts.SyntaxKind.UnionType: - case ts.SyntaxKind.IntersectionType: - return visitNodes(cbNode, cbNodes, (node as ts.UnionOrIntersectionTypeNode).types); - case ts.SyntaxKind.ConditionalType: - return visitNode(cbNode, (node as ts.ConditionalTypeNode).checkType) || - visitNode(cbNode, (node as ts.ConditionalTypeNode).extendsType) || - visitNode(cbNode, (node as ts.ConditionalTypeNode).trueType) || - visitNode(cbNode, (node as ts.ConditionalTypeNode).falseType); - case ts.SyntaxKind.InferType: - return visitNode(cbNode, (node as ts.InferTypeNode).typeParameter); - case ts.SyntaxKind.ImportType: - return visitNode(cbNode, (node as ts.ImportTypeNode).argument) || - visitNode(cbNode, (node as ts.ImportTypeNode).assertions) || - visitNode(cbNode, (node as ts.ImportTypeNode).qualifier) || - visitNodes(cbNode, cbNodes, (node as ts.ImportTypeNode).typeArguments); - case ts.SyntaxKind.ImportTypeAssertionContainer: - return visitNode(cbNode, (node as ts.ImportTypeAssertionContainer).assertClause); - case ts.SyntaxKind.ParenthesizedType: - case ts.SyntaxKind.TypeOperator: - return visitNode(cbNode, (node as ts.ParenthesizedTypeNode | ts.TypeOperatorNode).type); - case ts.SyntaxKind.IndexedAccessType: - return visitNode(cbNode, (node as ts.IndexedAccessTypeNode).objectType) || - visitNode(cbNode, (node as ts.IndexedAccessTypeNode).indexType); - case ts.SyntaxKind.MappedType: - return visitNode(cbNode, (node as ts.MappedTypeNode).readonlyToken) || - visitNode(cbNode, (node as ts.MappedTypeNode).typeParameter) || - visitNode(cbNode, (node as ts.MappedTypeNode).nameType) || - visitNode(cbNode, (node as ts.MappedTypeNode).questionToken) || - visitNode(cbNode, (node as ts.MappedTypeNode).type) || - visitNodes(cbNode, cbNodes, (node as ts.MappedTypeNode).members); - case ts.SyntaxKind.LiteralType: - return visitNode(cbNode, (node as ts.LiteralTypeNode).literal); - case ts.SyntaxKind.NamedTupleMember: - return visitNode(cbNode, (node as ts.NamedTupleMember).dotDotDotToken) || - visitNode(cbNode, (node as ts.NamedTupleMember).name) || - visitNode(cbNode, (node as ts.NamedTupleMember).questionToken) || - visitNode(cbNode, (node as ts.NamedTupleMember).type); - case ts.SyntaxKind.ObjectBindingPattern: - case ts.SyntaxKind.ArrayBindingPattern: - return visitNodes(cbNode, cbNodes, (node as ts.BindingPattern).elements); - case ts.SyntaxKind.ArrayLiteralExpression: - return visitNodes(cbNode, cbNodes, (node as ts.ArrayLiteralExpression).elements); - case ts.SyntaxKind.ObjectLiteralExpression: - return visitNodes(cbNode, cbNodes, (node as ts.ObjectLiteralExpression).properties); - case ts.SyntaxKind.PropertyAccessExpression: - return visitNode(cbNode, (node as ts.PropertyAccessExpression).expression) || - visitNode(cbNode, (node as ts.PropertyAccessExpression).questionDotToken) || - visitNode(cbNode, (node as ts.PropertyAccessExpression).name); - case ts.SyntaxKind.ElementAccessExpression: - return visitNode(cbNode, (node as ts.ElementAccessExpression).expression) || - visitNode(cbNode, (node as ts.ElementAccessExpression).questionDotToken) || - visitNode(cbNode, (node as ts.ElementAccessExpression).argumentExpression); - case ts.SyntaxKind.CallExpression: - case ts.SyntaxKind.NewExpression: - return visitNode(cbNode, (node as ts.CallExpression).expression) || - visitNode(cbNode, (node as ts.CallExpression).questionDotToken) || - visitNodes(cbNode, cbNodes, (node as ts.CallExpression).typeArguments) || - visitNodes(cbNode, cbNodes, (node as ts.CallExpression).arguments); - case ts.SyntaxKind.TaggedTemplateExpression: - return visitNode(cbNode, (node as ts.TaggedTemplateExpression).tag) || - visitNode(cbNode, (node as ts.TaggedTemplateExpression).questionDotToken) || - visitNodes(cbNode, cbNodes, (node as ts.TaggedTemplateExpression).typeArguments) || - visitNode(cbNode, (node as ts.TaggedTemplateExpression).template); - case ts.SyntaxKind.TypeAssertionExpression: - return visitNode(cbNode, (node as ts.TypeAssertion).type) || - visitNode(cbNode, (node as ts.TypeAssertion).expression); - case ts.SyntaxKind.ParenthesizedExpression: - return visitNode(cbNode, (node as ts.ParenthesizedExpression).expression); - case ts.SyntaxKind.DeleteExpression: - return visitNode(cbNode, (node as ts.DeleteExpression).expression); - case ts.SyntaxKind.TypeOfExpression: - return visitNode(cbNode, (node as ts.TypeOfExpression).expression); - case ts.SyntaxKind.VoidExpression: - return visitNode(cbNode, (node as ts.VoidExpression).expression); - case ts.SyntaxKind.PrefixUnaryExpression: - return visitNode(cbNode, (node as ts.PrefixUnaryExpression).operand); - case ts.SyntaxKind.YieldExpression: - return visitNode(cbNode, (node as ts.YieldExpression).asteriskToken) || - visitNode(cbNode, (node as ts.YieldExpression).expression); - case ts.SyntaxKind.AwaitExpression: - return visitNode(cbNode, (node as ts.AwaitExpression).expression); - case ts.SyntaxKind.PostfixUnaryExpression: - return visitNode(cbNode, (node as ts.PostfixUnaryExpression).operand); - case ts.SyntaxKind.BinaryExpression: - return visitNode(cbNode, (node as ts.BinaryExpression).left) || - visitNode(cbNode, (node as ts.BinaryExpression).operatorToken) || - visitNode(cbNode, (node as ts.BinaryExpression).right); - case ts.SyntaxKind.AsExpression: - return visitNode(cbNode, (node as ts.AsExpression).expression) || - visitNode(cbNode, (node as ts.AsExpression).type); - case ts.SyntaxKind.NonNullExpression: - return visitNode(cbNode, (node as ts.NonNullExpression).expression); - case ts.SyntaxKind.MetaProperty: - return visitNode(cbNode, (node as ts.MetaProperty).name); - case ts.SyntaxKind.ConditionalExpression: - return visitNode(cbNode, (node as ts.ConditionalExpression).condition) || - visitNode(cbNode, (node as ts.ConditionalExpression).questionToken) || - visitNode(cbNode, (node as ts.ConditionalExpression).whenTrue) || - visitNode(cbNode, (node as ts.ConditionalExpression).colonToken) || - visitNode(cbNode, (node as ts.ConditionalExpression).whenFalse); - case ts.SyntaxKind.SpreadElement: - return visitNode(cbNode, (node as ts.SpreadElement).expression); - case ts.SyntaxKind.Block: - case ts.SyntaxKind.ModuleBlock: - return visitNodes(cbNode, cbNodes, (node as ts.Block).statements); - case ts.SyntaxKind.SourceFile: - return visitNodes(cbNode, cbNodes, (node as ts.SourceFile).statements) || - visitNode(cbNode, (node as ts.SourceFile).endOfFileToken); - case ts.SyntaxKind.VariableStatement: + visitNode(cbNode, (node as ClassStaticBlockDeclaration).body); + case SyntaxKind.TypeReference: + return visitNode(cbNode, (node as TypeReferenceNode).typeName) || + visitNodes(cbNode, cbNodes, (node as TypeReferenceNode).typeArguments); + case SyntaxKind.TypePredicate: + return visitNode(cbNode, (node as TypePredicateNode).assertsModifier) || + visitNode(cbNode, (node as TypePredicateNode).parameterName) || + visitNode(cbNode, (node as TypePredicateNode).type); + case SyntaxKind.TypeQuery: + return visitNode(cbNode, (node as TypeQueryNode).exprName) || + visitNodes(cbNode, cbNodes, (node as TypeQueryNode).typeArguments); + case SyntaxKind.TypeLiteral: + return visitNodes(cbNode, cbNodes, (node as TypeLiteralNode).members); + case SyntaxKind.ArrayType: + return visitNode(cbNode, (node as ArrayTypeNode).elementType); + case SyntaxKind.TupleType: + return visitNodes(cbNode, cbNodes, (node as TupleTypeNode).elements); + case SyntaxKind.UnionType: + case SyntaxKind.IntersectionType: + return visitNodes(cbNode, cbNodes, (node as UnionOrIntersectionTypeNode).types); + case SyntaxKind.ConditionalType: + return visitNode(cbNode, (node as ConditionalTypeNode).checkType) || + visitNode(cbNode, (node as ConditionalTypeNode).extendsType) || + visitNode(cbNode, (node as ConditionalTypeNode).trueType) || + visitNode(cbNode, (node as ConditionalTypeNode).falseType); + case SyntaxKind.InferType: + return visitNode(cbNode, (node as InferTypeNode).typeParameter); + case SyntaxKind.ImportType: + return visitNode(cbNode, (node as ImportTypeNode).argument) || + visitNode(cbNode, (node as ImportTypeNode).assertions) || + visitNode(cbNode, (node as ImportTypeNode).qualifier) || + visitNodes(cbNode, cbNodes, (node as ImportTypeNode).typeArguments); + case SyntaxKind.ImportTypeAssertionContainer: + return visitNode(cbNode, (node as ImportTypeAssertionContainer).assertClause); + case SyntaxKind.ParenthesizedType: + case SyntaxKind.TypeOperator: + return visitNode(cbNode, (node as ParenthesizedTypeNode | TypeOperatorNode).type); + case SyntaxKind.IndexedAccessType: + return visitNode(cbNode, (node as IndexedAccessTypeNode).objectType) || + visitNode(cbNode, (node as IndexedAccessTypeNode).indexType); + case SyntaxKind.MappedType: + return visitNode(cbNode, (node as MappedTypeNode).readonlyToken) || + visitNode(cbNode, (node as MappedTypeNode).typeParameter) || + visitNode(cbNode, (node as MappedTypeNode).nameType) || + visitNode(cbNode, (node as MappedTypeNode).questionToken) || + visitNode(cbNode, (node as MappedTypeNode).type) || + visitNodes(cbNode, cbNodes, (node as MappedTypeNode).members); + case SyntaxKind.LiteralType: + return visitNode(cbNode, (node as LiteralTypeNode).literal); + case SyntaxKind.NamedTupleMember: + return visitNode(cbNode, (node as NamedTupleMember).dotDotDotToken) || + visitNode(cbNode, (node as NamedTupleMember).name) || + visitNode(cbNode, (node as NamedTupleMember).questionToken) || + visitNode(cbNode, (node as NamedTupleMember).type); + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + return visitNodes(cbNode, cbNodes, (node as BindingPattern).elements); + case SyntaxKind.ArrayLiteralExpression: + return visitNodes(cbNode, cbNodes, (node as ArrayLiteralExpression).elements); + case SyntaxKind.ObjectLiteralExpression: + return visitNodes(cbNode, cbNodes, (node as ObjectLiteralExpression).properties); + case SyntaxKind.PropertyAccessExpression: + return visitNode(cbNode, (node as PropertyAccessExpression).expression) || + visitNode(cbNode, (node as PropertyAccessExpression).questionDotToken) || + visitNode(cbNode, (node as PropertyAccessExpression).name); + case SyntaxKind.ElementAccessExpression: + return visitNode(cbNode, (node as ElementAccessExpression).expression) || + visitNode(cbNode, (node as ElementAccessExpression).questionDotToken) || + visitNode(cbNode, (node as ElementAccessExpression).argumentExpression); + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + return visitNode(cbNode, (node as CallExpression).expression) || + visitNode(cbNode, (node as CallExpression).questionDotToken) || + visitNodes(cbNode, cbNodes, (node as CallExpression).typeArguments) || + visitNodes(cbNode, cbNodes, (node as CallExpression).arguments); + case SyntaxKind.TaggedTemplateExpression: + return visitNode(cbNode, (node as TaggedTemplateExpression).tag) || + visitNode(cbNode, (node as TaggedTemplateExpression).questionDotToken) || + visitNodes(cbNode, cbNodes, (node as TaggedTemplateExpression).typeArguments) || + visitNode(cbNode, (node as TaggedTemplateExpression).template); + case SyntaxKind.TypeAssertionExpression: + return visitNode(cbNode, (node as TypeAssertion).type) || + visitNode(cbNode, (node as TypeAssertion).expression); + case SyntaxKind.ParenthesizedExpression: + return visitNode(cbNode, (node as ParenthesizedExpression).expression); + case SyntaxKind.DeleteExpression: + return visitNode(cbNode, (node as DeleteExpression).expression); + case SyntaxKind.TypeOfExpression: + return visitNode(cbNode, (node as TypeOfExpression).expression); + case SyntaxKind.VoidExpression: + return visitNode(cbNode, (node as VoidExpression).expression); + case SyntaxKind.PrefixUnaryExpression: + return visitNode(cbNode, (node as PrefixUnaryExpression).operand); + case SyntaxKind.YieldExpression: + return visitNode(cbNode, (node as YieldExpression).asteriskToken) || + visitNode(cbNode, (node as YieldExpression).expression); + case SyntaxKind.AwaitExpression: + return visitNode(cbNode, (node as AwaitExpression).expression); + case SyntaxKind.PostfixUnaryExpression: + return visitNode(cbNode, (node as PostfixUnaryExpression).operand); + case SyntaxKind.BinaryExpression: + return visitNode(cbNode, (node as BinaryExpression).left) || + visitNode(cbNode, (node as BinaryExpression).operatorToken) || + visitNode(cbNode, (node as BinaryExpression).right); + case SyntaxKind.AsExpression: + return visitNode(cbNode, (node as AsExpression).expression) || + visitNode(cbNode, (node as AsExpression).type); + case SyntaxKind.NonNullExpression: + return visitNode(cbNode, (node as NonNullExpression).expression); + case SyntaxKind.MetaProperty: + return visitNode(cbNode, (node as MetaProperty).name); + case SyntaxKind.ConditionalExpression: + return visitNode(cbNode, (node as ConditionalExpression).condition) || + visitNode(cbNode, (node as ConditionalExpression).questionToken) || + visitNode(cbNode, (node as ConditionalExpression).whenTrue) || + visitNode(cbNode, (node as ConditionalExpression).colonToken) || + visitNode(cbNode, (node as ConditionalExpression).whenFalse); + case SyntaxKind.SpreadElement: + return visitNode(cbNode, (node as SpreadElement).expression); + case SyntaxKind.Block: + case SyntaxKind.ModuleBlock: + return visitNodes(cbNode, cbNodes, (node as Block).statements); + case SyntaxKind.SourceFile: + return visitNodes(cbNode, cbNodes, (node as SourceFile).statements) || + visitNode(cbNode, (node as SourceFile).endOfFileToken); + case SyntaxKind.VariableStatement: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.VariableStatement).declarationList); - case ts.SyntaxKind.VariableDeclarationList: - return visitNodes(cbNode, cbNodes, (node as ts.VariableDeclarationList).declarations); - case ts.SyntaxKind.ExpressionStatement: - return visitNode(cbNode, (node as ts.ExpressionStatement).expression); - case ts.SyntaxKind.IfStatement: - return visitNode(cbNode, (node as ts.IfStatement).expression) || - visitNode(cbNode, (node as ts.IfStatement).thenStatement) || - visitNode(cbNode, (node as ts.IfStatement).elseStatement); - case ts.SyntaxKind.DoStatement: - return visitNode(cbNode, (node as ts.DoStatement).statement) || - visitNode(cbNode, (node as ts.DoStatement).expression); - case ts.SyntaxKind.WhileStatement: - return visitNode(cbNode, (node as ts.WhileStatement).expression) || - visitNode(cbNode, (node as ts.WhileStatement).statement); - case ts.SyntaxKind.ForStatement: - return visitNode(cbNode, (node as ts.ForStatement).initializer) || - visitNode(cbNode, (node as ts.ForStatement).condition) || - visitNode(cbNode, (node as ts.ForStatement).incrementor) || - visitNode(cbNode, (node as ts.ForStatement).statement); - case ts.SyntaxKind.ForInStatement: - return visitNode(cbNode, (node as ts.ForInStatement).initializer) || - visitNode(cbNode, (node as ts.ForInStatement).expression) || - visitNode(cbNode, (node as ts.ForInStatement).statement); - case ts.SyntaxKind.ForOfStatement: - return visitNode(cbNode, (node as ts.ForOfStatement).awaitModifier) || - visitNode(cbNode, (node as ts.ForOfStatement).initializer) || - visitNode(cbNode, (node as ts.ForOfStatement).expression) || - visitNode(cbNode, (node as ts.ForOfStatement).statement); - case ts.SyntaxKind.ContinueStatement: - case ts.SyntaxKind.BreakStatement: - return visitNode(cbNode, (node as ts.BreakOrContinueStatement).label); - case ts.SyntaxKind.ReturnStatement: - return visitNode(cbNode, (node as ts.ReturnStatement).expression); - case ts.SyntaxKind.WithStatement: - return visitNode(cbNode, (node as ts.WithStatement).expression) || - visitNode(cbNode, (node as ts.WithStatement).statement); - case ts.SyntaxKind.SwitchStatement: - return visitNode(cbNode, (node as ts.SwitchStatement).expression) || - visitNode(cbNode, (node as ts.SwitchStatement).caseBlock); - case ts.SyntaxKind.CaseBlock: - return visitNodes(cbNode, cbNodes, (node as ts.CaseBlock).clauses); - case ts.SyntaxKind.CaseClause: - return visitNode(cbNode, (node as ts.CaseClause).expression) || - visitNodes(cbNode, cbNodes, (node as ts.CaseClause).statements); - case ts.SyntaxKind.DefaultClause: - return visitNodes(cbNode, cbNodes, (node as ts.DefaultClause).statements); - case ts.SyntaxKind.LabeledStatement: - return visitNode(cbNode, (node as ts.LabeledStatement).label) || - visitNode(cbNode, (node as ts.LabeledStatement).statement); - case ts.SyntaxKind.ThrowStatement: - return visitNode(cbNode, (node as ts.ThrowStatement).expression); - case ts.SyntaxKind.TryStatement: - return visitNode(cbNode, (node as ts.TryStatement).tryBlock) || - visitNode(cbNode, (node as ts.TryStatement).catchClause) || - visitNode(cbNode, (node as ts.TryStatement).finallyBlock); - case ts.SyntaxKind.CatchClause: - return visitNode(cbNode, (node as ts.CatchClause).variableDeclaration) || - visitNode(cbNode, (node as ts.CatchClause).block); - case ts.SyntaxKind.Decorator: - return visitNode(cbNode, (node as ts.Decorator).expression); - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: + visitNode(cbNode, (node as VariableStatement).declarationList); + case SyntaxKind.VariableDeclarationList: + return visitNodes(cbNode, cbNodes, (node as VariableDeclarationList).declarations); + case SyntaxKind.ExpressionStatement: + return visitNode(cbNode, (node as ExpressionStatement).expression); + case SyntaxKind.IfStatement: + return visitNode(cbNode, (node as IfStatement).expression) || + visitNode(cbNode, (node as IfStatement).thenStatement) || + visitNode(cbNode, (node as IfStatement).elseStatement); + case SyntaxKind.DoStatement: + return visitNode(cbNode, (node as DoStatement).statement) || + visitNode(cbNode, (node as DoStatement).expression); + case SyntaxKind.WhileStatement: + return visitNode(cbNode, (node as WhileStatement).expression) || + visitNode(cbNode, (node as WhileStatement).statement); + case SyntaxKind.ForStatement: + return visitNode(cbNode, (node as ForStatement).initializer) || + visitNode(cbNode, (node as ForStatement).condition) || + visitNode(cbNode, (node as ForStatement).incrementor) || + visitNode(cbNode, (node as ForStatement).statement); + case SyntaxKind.ForInStatement: + return visitNode(cbNode, (node as ForInStatement).initializer) || + visitNode(cbNode, (node as ForInStatement).expression) || + visitNode(cbNode, (node as ForInStatement).statement); + case SyntaxKind.ForOfStatement: + return visitNode(cbNode, (node as ForOfStatement).awaitModifier) || + visitNode(cbNode, (node as ForOfStatement).initializer) || + visitNode(cbNode, (node as ForOfStatement).expression) || + visitNode(cbNode, (node as ForOfStatement).statement); + case SyntaxKind.ContinueStatement: + case SyntaxKind.BreakStatement: + return visitNode(cbNode, (node as BreakOrContinueStatement).label); + case SyntaxKind.ReturnStatement: + return visitNode(cbNode, (node as ReturnStatement).expression); + case SyntaxKind.WithStatement: + return visitNode(cbNode, (node as WithStatement).expression) || + visitNode(cbNode, (node as WithStatement).statement); + case SyntaxKind.SwitchStatement: + return visitNode(cbNode, (node as SwitchStatement).expression) || + visitNode(cbNode, (node as SwitchStatement).caseBlock); + case SyntaxKind.CaseBlock: + return visitNodes(cbNode, cbNodes, (node as CaseBlock).clauses); + case SyntaxKind.CaseClause: + return visitNode(cbNode, (node as CaseClause).expression) || + visitNodes(cbNode, cbNodes, (node as CaseClause).statements); + case SyntaxKind.DefaultClause: + return visitNodes(cbNode, cbNodes, (node as DefaultClause).statements); + case SyntaxKind.LabeledStatement: + return visitNode(cbNode, (node as LabeledStatement).label) || + visitNode(cbNode, (node as LabeledStatement).statement); + case SyntaxKind.ThrowStatement: + return visitNode(cbNode, (node as ThrowStatement).expression); + case SyntaxKind.TryStatement: + return visitNode(cbNode, (node as TryStatement).tryBlock) || + visitNode(cbNode, (node as TryStatement).catchClause) || + visitNode(cbNode, (node as TryStatement).finallyBlock); + case SyntaxKind.CatchClause: + return visitNode(cbNode, (node as CatchClause).variableDeclaration) || + visitNode(cbNode, (node as CatchClause).block); + case SyntaxKind.Decorator: + return visitNode(cbNode, (node as Decorator).expression); + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.ClassLikeDeclaration).name) || - visitNodes(cbNode, cbNodes, (node as ts.ClassLikeDeclaration).typeParameters) || - visitNodes(cbNode, cbNodes, (node as ts.ClassLikeDeclaration).heritageClauses) || - visitNodes(cbNode, cbNodes, (node as ts.ClassLikeDeclaration).members); - case ts.SyntaxKind.InterfaceDeclaration: + visitNode(cbNode, (node as ClassLikeDeclaration).name) || + visitNodes(cbNode, cbNodes, (node as ClassLikeDeclaration).typeParameters) || + visitNodes(cbNode, cbNodes, (node as ClassLikeDeclaration).heritageClauses) || + visitNodes(cbNode, cbNodes, (node as ClassLikeDeclaration).members); + case SyntaxKind.InterfaceDeclaration: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.InterfaceDeclaration).name) || - visitNodes(cbNode, cbNodes, (node as ts.InterfaceDeclaration).typeParameters) || - visitNodes(cbNode, cbNodes, (node as ts.ClassDeclaration).heritageClauses) || - visitNodes(cbNode, cbNodes, (node as ts.InterfaceDeclaration).members); - case ts.SyntaxKind.TypeAliasDeclaration: + visitNode(cbNode, (node as InterfaceDeclaration).name) || + visitNodes(cbNode, cbNodes, (node as InterfaceDeclaration).typeParameters) || + visitNodes(cbNode, cbNodes, (node as ClassDeclaration).heritageClauses) || + visitNodes(cbNode, cbNodes, (node as InterfaceDeclaration).members); + case SyntaxKind.TypeAliasDeclaration: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.TypeAliasDeclaration).name) || - visitNodes(cbNode, cbNodes, (node as ts.TypeAliasDeclaration).typeParameters) || - visitNode(cbNode, (node as ts.TypeAliasDeclaration).type); - case ts.SyntaxKind.EnumDeclaration: + visitNode(cbNode, (node as TypeAliasDeclaration).name) || + visitNodes(cbNode, cbNodes, (node as TypeAliasDeclaration).typeParameters) || + visitNode(cbNode, (node as TypeAliasDeclaration).type); + case SyntaxKind.EnumDeclaration: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.EnumDeclaration).name) || - visitNodes(cbNode, cbNodes, (node as ts.EnumDeclaration).members); - case ts.SyntaxKind.EnumMember: - return visitNode(cbNode, (node as ts.EnumMember).name) || - visitNode(cbNode, (node as ts.EnumMember).initializer); - case ts.SyntaxKind.ModuleDeclaration: + visitNode(cbNode, (node as EnumDeclaration).name) || + visitNodes(cbNode, cbNodes, (node as EnumDeclaration).members); + case SyntaxKind.EnumMember: + return visitNode(cbNode, (node as EnumMember).name) || + visitNode(cbNode, (node as EnumMember).initializer); + case SyntaxKind.ModuleDeclaration: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.ModuleDeclaration).name) || - visitNode(cbNode, (node as ts.ModuleDeclaration).body); - case ts.SyntaxKind.ImportEqualsDeclaration: + visitNode(cbNode, (node as ModuleDeclaration).name) || + visitNode(cbNode, (node as ModuleDeclaration).body); + case SyntaxKind.ImportEqualsDeclaration: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.ImportEqualsDeclaration).name) || - visitNode(cbNode, (node as ts.ImportEqualsDeclaration).moduleReference); - case ts.SyntaxKind.ImportDeclaration: + visitNode(cbNode, (node as ImportEqualsDeclaration).name) || + visitNode(cbNode, (node as ImportEqualsDeclaration).moduleReference); + case SyntaxKind.ImportDeclaration: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.ImportDeclaration).importClause) || - visitNode(cbNode, (node as ts.ImportDeclaration).moduleSpecifier) || - visitNode(cbNode, (node as ts.ImportDeclaration).assertClause); - case ts.SyntaxKind.ImportClause: - return visitNode(cbNode, (node as ts.ImportClause).name) || - visitNode(cbNode, (node as ts.ImportClause).namedBindings); - case ts.SyntaxKind.AssertClause: - return visitNodes(cbNode, cbNodes, (node as ts.AssertClause).elements); - case ts.SyntaxKind.AssertEntry: - return visitNode(cbNode, (node as ts.AssertEntry).name) || - visitNode(cbNode, (node as ts.AssertEntry).value); - case ts.SyntaxKind.NamespaceExportDeclaration: - return visitNode(cbNode, (node as ts.NamespaceExportDeclaration).name); - case ts.SyntaxKind.NamespaceImport: - return visitNode(cbNode, (node as ts.NamespaceImport).name); - case ts.SyntaxKind.NamespaceExport: - return visitNode(cbNode, (node as ts.NamespaceExport).name); - case ts.SyntaxKind.NamedImports: - case ts.SyntaxKind.NamedExports: - return visitNodes(cbNode, cbNodes, (node as ts.NamedImportsOrExports).elements); - case ts.SyntaxKind.ExportDeclaration: + visitNode(cbNode, (node as ImportDeclaration).importClause) || + visitNode(cbNode, (node as ImportDeclaration).moduleSpecifier) || + visitNode(cbNode, (node as ImportDeclaration).assertClause); + case SyntaxKind.ImportClause: + return visitNode(cbNode, (node as ImportClause).name) || + visitNode(cbNode, (node as ImportClause).namedBindings); + case SyntaxKind.AssertClause: + return visitNodes(cbNode, cbNodes, (node as AssertClause).elements); + case SyntaxKind.AssertEntry: + return visitNode(cbNode, (node as AssertEntry).name) || + visitNode(cbNode, (node as AssertEntry).value); + case SyntaxKind.NamespaceExportDeclaration: + return visitNode(cbNode, (node as NamespaceExportDeclaration).name); + case SyntaxKind.NamespaceImport: + return visitNode(cbNode, (node as NamespaceImport).name); + case SyntaxKind.NamespaceExport: + return visitNode(cbNode, (node as NamespaceExport).name); + case SyntaxKind.NamedImports: + case SyntaxKind.NamedExports: + return visitNodes(cbNode, cbNodes, (node as NamedImportsOrExports).elements); + case SyntaxKind.ExportDeclaration: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.ExportDeclaration).exportClause) || - visitNode(cbNode, (node as ts.ExportDeclaration).moduleSpecifier) || - visitNode(cbNode, (node as ts.ExportDeclaration).assertClause); - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.ExportSpecifier: - return visitNode(cbNode, (node as ts.ImportOrExportSpecifier).propertyName) || - visitNode(cbNode, (node as ts.ImportOrExportSpecifier).name); - case ts.SyntaxKind.ExportAssignment: + visitNode(cbNode, (node as ExportDeclaration).exportClause) || + visitNode(cbNode, (node as ExportDeclaration).moduleSpecifier) || + visitNode(cbNode, (node as ExportDeclaration).assertClause); + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ExportSpecifier: + return visitNode(cbNode, (node as ImportOrExportSpecifier).propertyName) || + visitNode(cbNode, (node as ImportOrExportSpecifier).name); + case SyntaxKind.ExportAssignment: return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, (node as ts.ExportAssignment).expression); - case ts.SyntaxKind.TemplateExpression: - return visitNode(cbNode, (node as ts.TemplateExpression).head) || visitNodes(cbNode, cbNodes, (node as ts.TemplateExpression).templateSpans); - case ts.SyntaxKind.TemplateSpan: - return visitNode(cbNode, (node as ts.TemplateSpan).expression) || visitNode(cbNode, (node as ts.TemplateSpan).literal); - case ts.SyntaxKind.TemplateLiteralType: - return visitNode(cbNode, (node as ts.TemplateLiteralTypeNode).head) || visitNodes(cbNode, cbNodes, (node as ts.TemplateLiteralTypeNode).templateSpans); - case ts.SyntaxKind.TemplateLiteralTypeSpan: - return visitNode(cbNode, (node as ts.TemplateLiteralTypeSpan).type) || visitNode(cbNode, (node as ts.TemplateLiteralTypeSpan).literal); - case ts.SyntaxKind.ComputedPropertyName: - return visitNode(cbNode, (node as ts.ComputedPropertyName).expression); - case ts.SyntaxKind.HeritageClause: - return visitNodes(cbNode, cbNodes, (node as ts.HeritageClause).types); - case ts.SyntaxKind.ExpressionWithTypeArguments: - return visitNode(cbNode, (node as ts.ExpressionWithTypeArguments).expression) || - visitNodes(cbNode, cbNodes, (node as ts.ExpressionWithTypeArguments).typeArguments); - case ts.SyntaxKind.ExternalModuleReference: - return visitNode(cbNode, (node as ts.ExternalModuleReference).expression); - case ts.SyntaxKind.MissingDeclaration: + visitNode(cbNode, (node as ExportAssignment).expression); + case SyntaxKind.TemplateExpression: + return visitNode(cbNode, (node as TemplateExpression).head) || visitNodes(cbNode, cbNodes, (node as TemplateExpression).templateSpans); + case SyntaxKind.TemplateSpan: + return visitNode(cbNode, (node as TemplateSpan).expression) || visitNode(cbNode, (node as TemplateSpan).literal); + case SyntaxKind.TemplateLiteralType: + return visitNode(cbNode, (node as TemplateLiteralTypeNode).head) || visitNodes(cbNode, cbNodes, (node as TemplateLiteralTypeNode).templateSpans); + case SyntaxKind.TemplateLiteralTypeSpan: + return visitNode(cbNode, (node as TemplateLiteralTypeSpan).type) || visitNode(cbNode, (node as TemplateLiteralTypeSpan).literal); + case SyntaxKind.ComputedPropertyName: + return visitNode(cbNode, (node as ComputedPropertyName).expression); + case SyntaxKind.HeritageClause: + return visitNodes(cbNode, cbNodes, (node as HeritageClause).types); + case SyntaxKind.ExpressionWithTypeArguments: + return visitNode(cbNode, (node as ExpressionWithTypeArguments).expression) || + visitNodes(cbNode, cbNodes, (node as ExpressionWithTypeArguments).typeArguments); + case SyntaxKind.ExternalModuleReference: + return visitNode(cbNode, (node as ExternalModuleReference).expression); + case SyntaxKind.MissingDeclaration: return visitNodes(cbNode, cbNodes, node.decorators); - case ts.SyntaxKind.CommaListExpression: - return visitNodes(cbNode, cbNodes, (node as ts.CommaListExpression).elements); - - case ts.SyntaxKind.JsxElement: - return visitNode(cbNode, (node as ts.JsxElement).openingElement) || - visitNodes(cbNode, cbNodes, (node as ts.JsxElement).children) || - visitNode(cbNode, (node as ts.JsxElement).closingElement); - case ts.SyntaxKind.JsxFragment: - return visitNode(cbNode, (node as ts.JsxFragment).openingFragment) || - visitNodes(cbNode, cbNodes, (node as ts.JsxFragment).children) || - visitNode(cbNode, (node as ts.JsxFragment).closingFragment); - case ts.SyntaxKind.JsxSelfClosingElement: - case ts.SyntaxKind.JsxOpeningElement: - return visitNode(cbNode, (node as ts.JsxOpeningLikeElement).tagName) || - visitNodes(cbNode, cbNodes, (node as ts.JsxOpeningLikeElement).typeArguments) || - visitNode(cbNode, (node as ts.JsxOpeningLikeElement).attributes); - case ts.SyntaxKind.JsxAttributes: - return visitNodes(cbNode, cbNodes, (node as ts.JsxAttributes).properties); - case ts.SyntaxKind.JsxAttribute: - return visitNode(cbNode, (node as ts.JsxAttribute).name) || - visitNode(cbNode, (node as ts.JsxAttribute).initializer); - case ts.SyntaxKind.JsxSpreadAttribute: - return visitNode(cbNode, (node as ts.JsxSpreadAttribute).expression); - case ts.SyntaxKind.JsxExpression: - return visitNode(cbNode, (node as ts.JsxExpression).dotDotDotToken) || - visitNode(cbNode, (node as ts.JsxExpression).expression); - case ts.SyntaxKind.JsxClosingElement: - return visitNode(cbNode, (node as ts.JsxClosingElement).tagName); - - case ts.SyntaxKind.OptionalType: - case ts.SyntaxKind.RestType: - case ts.SyntaxKind.JSDocTypeExpression: - case ts.SyntaxKind.JSDocNonNullableType: - case ts.SyntaxKind.JSDocNullableType: - case ts.SyntaxKind.JSDocOptionalType: - case ts.SyntaxKind.JSDocVariadicType: - return visitNode(cbNode, (node as ts.OptionalTypeNode | ts.RestTypeNode | ts.JSDocTypeExpression | ts.JSDocTypeReferencingNode).type); - case ts.SyntaxKind.JSDocFunctionType: - return visitNodes(cbNode, cbNodes, (node as ts.JSDocFunctionType).parameters) || - visitNode(cbNode, (node as ts.JSDocFunctionType).type); - case ts.SyntaxKind.JSDoc: - return (typeof (node as ts.JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as ts.JSDoc).comment as ts.NodeArray | undefined)) - || visitNodes(cbNode, cbNodes, (node as ts.JSDoc).tags); - case ts.SyntaxKind.JSDocSeeTag: - return visitNode(cbNode, (node as ts.JSDocSeeTag).tagName) || - visitNode(cbNode, (node as ts.JSDocSeeTag).name) || - (typeof (node as ts.JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as ts.JSDoc).comment as ts.NodeArray | undefined)); - case ts.SyntaxKind.JSDocNameReference: - return visitNode(cbNode, (node as ts.JSDocNameReference).name); - case ts.SyntaxKind.JSDocMemberName: - return visitNode(cbNode, (node as ts.JSDocMemberName).left) || - visitNode(cbNode, (node as ts.JSDocMemberName).right); - case ts.SyntaxKind.JSDocParameterTag: - case ts.SyntaxKind.JSDocPropertyTag: - return visitNode(cbNode, (node as ts.JSDocTag).tagName) || - ((node as ts.JSDocPropertyLikeTag).isNameFirst - ? visitNode(cbNode, (node as ts.JSDocPropertyLikeTag).name) || - visitNode(cbNode, (node as ts.JSDocPropertyLikeTag).typeExpression) || - (typeof (node as ts.JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as ts.JSDoc).comment as ts.NodeArray | undefined)) - : visitNode(cbNode, (node as ts.JSDocPropertyLikeTag).typeExpression) || - visitNode(cbNode, (node as ts.JSDocPropertyLikeTag).name) || - (typeof (node as ts.JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as ts.JSDoc).comment as ts.NodeArray | undefined))); - case ts.SyntaxKind.JSDocAuthorTag: - return visitNode(cbNode, (node as ts.JSDocTag).tagName) || - (typeof (node as ts.JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as ts.JSDoc).comment as ts.NodeArray | undefined)); - case ts.SyntaxKind.JSDocImplementsTag: - return visitNode(cbNode, (node as ts.JSDocTag).tagName) || - visitNode(cbNode, (node as ts.JSDocImplementsTag).class) || - (typeof (node as ts.JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as ts.JSDoc).comment as ts.NodeArray | undefined)); - case ts.SyntaxKind.JSDocAugmentsTag: - return visitNode(cbNode, (node as ts.JSDocTag).tagName) || - visitNode(cbNode, (node as ts.JSDocAugmentsTag).class) || - (typeof (node as ts.JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as ts.JSDoc).comment as ts.NodeArray | undefined)); - case ts.SyntaxKind.JSDocTemplateTag: - return visitNode(cbNode, (node as ts.JSDocTag).tagName) || - visitNode(cbNode, (node as ts.JSDocTemplateTag).constraint) || - visitNodes(cbNode, cbNodes, (node as ts.JSDocTemplateTag).typeParameters) || - (typeof (node as ts.JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as ts.JSDoc).comment as ts.NodeArray | undefined)); - case ts.SyntaxKind.JSDocTypedefTag: - return visitNode(cbNode, (node as ts.JSDocTag).tagName) || - ((node as ts.JSDocTypedefTag).typeExpression && - (node as ts.JSDocTypedefTag).typeExpression!.kind === ts.SyntaxKind.JSDocTypeExpression - ? visitNode(cbNode, (node as ts.JSDocTypedefTag).typeExpression) || - visitNode(cbNode, (node as ts.JSDocTypedefTag).fullName) || - (typeof (node as ts.JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as ts.JSDoc).comment as ts.NodeArray | undefined)) - : visitNode(cbNode, (node as ts.JSDocTypedefTag).fullName) || - visitNode(cbNode, (node as ts.JSDocTypedefTag).typeExpression) || - (typeof (node as ts.JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as ts.JSDoc).comment as ts.NodeArray | undefined))); - case ts.SyntaxKind.JSDocCallbackTag: - return visitNode(cbNode, (node as ts.JSDocTag).tagName) || - visitNode(cbNode, (node as ts.JSDocCallbackTag).fullName) || - visitNode(cbNode, (node as ts.JSDocCallbackTag).typeExpression) || - (typeof (node as ts.JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as ts.JSDoc).comment as ts.NodeArray | undefined)); - case ts.SyntaxKind.JSDocReturnTag: - case ts.SyntaxKind.JSDocTypeTag: - case ts.SyntaxKind.JSDocThisTag: - case ts.SyntaxKind.JSDocEnumTag: - return visitNode(cbNode, (node as ts.JSDocTag).tagName) || - visitNode(cbNode, (node as ts.JSDocReturnTag | ts.JSDocTypeTag | ts.JSDocThisTag | ts.JSDocEnumTag).typeExpression) || - (typeof (node as ts.JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as ts.JSDoc).comment as ts.NodeArray | undefined)); - case ts.SyntaxKind.JSDocSignature: - return ts.forEach((node as ts.JSDocSignature).typeParameters, cbNode) || - ts.forEach((node as ts.JSDocSignature).parameters, cbNode) || - visitNode(cbNode, (node as ts.JSDocSignature).type); - case ts.SyntaxKind.JSDocLink: - case ts.SyntaxKind.JSDocLinkCode: - case ts.SyntaxKind.JSDocLinkPlain: - return visitNode(cbNode, (node as ts.JSDocLink | ts.JSDocLinkCode | ts.JSDocLinkPlain).name); - case ts.SyntaxKind.JSDocTypeLiteral: - return ts.forEach((node as ts.JSDocTypeLiteral).jsDocPropertyTags, cbNode); - case ts.SyntaxKind.JSDocTag: - case ts.SyntaxKind.JSDocClassTag: - case ts.SyntaxKind.JSDocPublicTag: - case ts.SyntaxKind.JSDocPrivateTag: - case ts.SyntaxKind.JSDocProtectedTag: - case ts.SyntaxKind.JSDocReadonlyTag: - case ts.SyntaxKind.JSDocDeprecatedTag: - return visitNode(cbNode, (node as ts.JSDocTag).tagName) - || (typeof (node as ts.JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as ts.JSDoc).comment as ts.NodeArray | undefined)); - case ts.SyntaxKind.PartiallyEmittedExpression: - return visitNode(cbNode, (node as ts.PartiallyEmittedExpression).expression); + case SyntaxKind.CommaListExpression: + return visitNodes(cbNode, cbNodes, (node as CommaListExpression).elements); + + case SyntaxKind.JsxElement: + return visitNode(cbNode, (node as JsxElement).openingElement) || + visitNodes(cbNode, cbNodes, (node as JsxElement).children) || + visitNode(cbNode, (node as JsxElement).closingElement); + case SyntaxKind.JsxFragment: + return visitNode(cbNode, (node as JsxFragment).openingFragment) || + visitNodes(cbNode, cbNodes, (node as JsxFragment).children) || + visitNode(cbNode, (node as JsxFragment).closingFragment); + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxOpeningElement: + return visitNode(cbNode, (node as JsxOpeningLikeElement).tagName) || + visitNodes(cbNode, cbNodes, (node as JsxOpeningLikeElement).typeArguments) || + visitNode(cbNode, (node as JsxOpeningLikeElement).attributes); + case SyntaxKind.JsxAttributes: + return visitNodes(cbNode, cbNodes, (node as JsxAttributes).properties); + case SyntaxKind.JsxAttribute: + return visitNode(cbNode, (node as JsxAttribute).name) || + visitNode(cbNode, (node as JsxAttribute).initializer); + case SyntaxKind.JsxSpreadAttribute: + return visitNode(cbNode, (node as JsxSpreadAttribute).expression); + case SyntaxKind.JsxExpression: + return visitNode(cbNode, (node as JsxExpression).dotDotDotToken) || + visitNode(cbNode, (node as JsxExpression).expression); + case SyntaxKind.JsxClosingElement: + return visitNode(cbNode, (node as JsxClosingElement).tagName); + + case SyntaxKind.OptionalType: + case SyntaxKind.RestType: + case SyntaxKind.JSDocTypeExpression: + case SyntaxKind.JSDocNonNullableType: + case SyntaxKind.JSDocNullableType: + case SyntaxKind.JSDocOptionalType: + case SyntaxKind.JSDocVariadicType: + return visitNode(cbNode, (node as OptionalTypeNode | RestTypeNode | JSDocTypeExpression | JSDocTypeReferencingNode).type); + case SyntaxKind.JSDocFunctionType: + return visitNodes(cbNode, cbNodes, (node as JSDocFunctionType).parameters) || + visitNode(cbNode, (node as JSDocFunctionType).type); + case SyntaxKind.JSDoc: + return (typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray | undefined)) + || visitNodes(cbNode, cbNodes, (node as JSDoc).tags); + case SyntaxKind.JSDocSeeTag: + return visitNode(cbNode, (node as JSDocSeeTag).tagName) || + visitNode(cbNode, (node as JSDocSeeTag).name) || + (typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray | undefined)); + case SyntaxKind.JSDocNameReference: + return visitNode(cbNode, (node as JSDocNameReference).name); + case SyntaxKind.JSDocMemberName: + return visitNode(cbNode, (node as JSDocMemberName).left) || + visitNode(cbNode, (node as JSDocMemberName).right); + case SyntaxKind.JSDocParameterTag: + case SyntaxKind.JSDocPropertyTag: + return visitNode(cbNode, (node as JSDocTag).tagName) || + ((node as JSDocPropertyLikeTag).isNameFirst + ? visitNode(cbNode, (node as JSDocPropertyLikeTag).name) || + visitNode(cbNode, (node as JSDocPropertyLikeTag).typeExpression) || + (typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray | undefined)) + : visitNode(cbNode, (node as JSDocPropertyLikeTag).typeExpression) || + visitNode(cbNode, (node as JSDocPropertyLikeTag).name) || + (typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray | undefined))); + case SyntaxKind.JSDocAuthorTag: + return visitNode(cbNode, (node as JSDocTag).tagName) || + (typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray | undefined)); + case SyntaxKind.JSDocImplementsTag: + return visitNode(cbNode, (node as JSDocTag).tagName) || + visitNode(cbNode, (node as JSDocImplementsTag).class) || + (typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray | undefined)); + case SyntaxKind.JSDocAugmentsTag: + return visitNode(cbNode, (node as JSDocTag).tagName) || + visitNode(cbNode, (node as JSDocAugmentsTag).class) || + (typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray | undefined)); + case SyntaxKind.JSDocTemplateTag: + return visitNode(cbNode, (node as JSDocTag).tagName) || + visitNode(cbNode, (node as JSDocTemplateTag).constraint) || + visitNodes(cbNode, cbNodes, (node as JSDocTemplateTag).typeParameters) || + (typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray | undefined)); + case SyntaxKind.JSDocTypedefTag: + return visitNode(cbNode, (node as JSDocTag).tagName) || + ((node as JSDocTypedefTag).typeExpression && + (node as JSDocTypedefTag).typeExpression!.kind === SyntaxKind.JSDocTypeExpression + ? visitNode(cbNode, (node as JSDocTypedefTag).typeExpression) || + visitNode(cbNode, (node as JSDocTypedefTag).fullName) || + (typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray | undefined)) + : visitNode(cbNode, (node as JSDocTypedefTag).fullName) || + visitNode(cbNode, (node as JSDocTypedefTag).typeExpression) || + (typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray | undefined))); + case SyntaxKind.JSDocCallbackTag: + return visitNode(cbNode, (node as JSDocTag).tagName) || + visitNode(cbNode, (node as JSDocCallbackTag).fullName) || + visitNode(cbNode, (node as JSDocCallbackTag).typeExpression) || + (typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray | undefined)); + case SyntaxKind.JSDocReturnTag: + case SyntaxKind.JSDocTypeTag: + case SyntaxKind.JSDocThisTag: + case SyntaxKind.JSDocEnumTag: + return visitNode(cbNode, (node as JSDocTag).tagName) || + visitNode(cbNode, (node as JSDocReturnTag | JSDocTypeTag | JSDocThisTag | JSDocEnumTag).typeExpression) || + (typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray | undefined)); + case SyntaxKind.JSDocSignature: + return forEach((node as JSDocSignature).typeParameters, cbNode) || + forEach((node as JSDocSignature).parameters, cbNode) || + visitNode(cbNode, (node as JSDocSignature).type); + case SyntaxKind.JSDocLink: + case SyntaxKind.JSDocLinkCode: + case SyntaxKind.JSDocLinkPlain: + return visitNode(cbNode, (node as JSDocLink | JSDocLinkCode | JSDocLinkPlain).name); + case SyntaxKind.JSDocTypeLiteral: + return forEach((node as JSDocTypeLiteral).jsDocPropertyTags, cbNode); + case SyntaxKind.JSDocTag: + case SyntaxKind.JSDocClassTag: + case SyntaxKind.JSDocPublicTag: + case SyntaxKind.JSDocPrivateTag: + case SyntaxKind.JSDocProtectedTag: + case SyntaxKind.JSDocReadonlyTag: + case SyntaxKind.JSDocDeprecatedTag: + return visitNode(cbNode, (node as JSDocTag).tagName) + || (typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray | undefined)); + case SyntaxKind.PartiallyEmittedExpression: + return visitNode(cbNode, (node as PartiallyEmittedExpression).expression); } } @@ -630,16 +714,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) { @@ -658,7 +742,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); @@ -669,66 +753,66 @@ 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; } -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); - ts.performance.mark("beforeParse"); - let result: ts.SourceFile; +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); + mark("beforeParse"); + 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(); + mark("afterParse"); + measure("Parse", "beforeParse", "afterParse"); + 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); } @@ -737,12 +821,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; } @@ -755,11 +839,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; } @@ -787,27 +871,27 @@ 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 // tslint:disable variable-name - 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; // tslint:enable variable-name - 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)), @@ -815,27 +899,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 @@ -883,7 +967,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; @@ -917,17 +1001,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; } @@ -940,56 +1024,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 @@ -999,7 +1083,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) { @@ -1007,21 +1091,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); @@ -1030,49 +1114,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; @@ -1105,10 +1189,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; @@ -1117,8 +1201,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); @@ -1130,9 +1214,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) { @@ -1141,33 +1225,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 = []; @@ -1178,24 +1262,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); @@ -1226,24 +1310,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; @@ -1252,7 +1336,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; @@ -1271,44 +1355,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; @@ -1317,7 +1401,7 @@ namespace Parser { } } - function setContextFlag(val: boolean, flag: ts.NodeFlags) { + function setContextFlag(val: boolean, flag: NodeFlags) { if (val) { contextFlags |= flag; } @@ -1327,22 +1411,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 @@ -1363,7 +1447,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 @@ -1385,79 +1469,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); } @@ -1467,15 +1551,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); } @@ -1493,7 +1577,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; } @@ -1506,52 +1590,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(); } @@ -1575,7 +1659,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. @@ -1608,36 +1692,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(); @@ -1650,12 +1734,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 @@ -1663,30 +1747,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": @@ -1694,37 +1778,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); } /** @@ -1734,7 +1818,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); } @@ -1745,7 +1829,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)}`; } } @@ -1753,24 +1837,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; } @@ -1780,40 +1864,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; @@ -1821,42 +1905,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(); @@ -1865,12 +1949,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() { @@ -1878,7 +1962,7 @@ namespace Parser { return false; } - if (token() === ts.SyntaxKind.SemicolonToken) { + if (token() === SyntaxKind.SemicolonToken) { // consume the semicolon if it was explicitly provided. nextToken(); } @@ -1887,19 +1971,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 @@ -1907,15 +1991,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); } @@ -1925,11 +2009,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; } @@ -1945,7 +2029,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(); @@ -1956,83 +2040,83 @@ namespace Parser { return finishNode(factory.createIdentifier(text, /*typeArguments*/ undefined, originalKeywordKind), 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); } @@ -2044,14 +2128,14 @@ namespace Parser { return privateIdentifier; } - function parsePrivateIdentifier(): ts.PrivateIdentifier { + function parsePrivateIdentifier(): PrivateIdentifier { const pos = getNodePos(); const node = factory.createPrivateIdentifier(internPrivateIdentifier(scanner.getTokenText())); nextToken(); return finishNode(node, pos); } - function parseContextualModifier(t: ts.SyntaxKind): boolean { + function parseContextualModifier(t: SyntaxKind): boolean { return token() === t && tryParse(nextTokenCanFollowModifier); } @@ -2065,23 +2149,23 @@ 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.StaticKeyword: - case ts.SyntaxKind.GetKeyword: - case ts.SyntaxKind.SetKeyword: + case SyntaxKind.StaticKeyword: + case SyntaxKind.GetKeyword: + case SyntaxKind.SetKeyword: nextToken(); return canFollowModifier(); default: @@ -2090,9 +2174,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(); } @@ -2102,23 +2186,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 @@ -2138,9 +2222,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: @@ -2148,17 +2232,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(); @@ -2166,13 +2250,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); } @@ -2188,41 +2272,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: // @@ -2232,7 +2316,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; @@ -2245,17 +2329,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); } @@ -2275,7 +2359,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; } @@ -2290,37 +2374,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; } @@ -2343,7 +2427,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; } @@ -2365,7 +2449,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 = []; @@ -2387,7 +2471,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; @@ -2396,7 +2480,7 @@ namespace Parser { return parseElement(); } - function currentNode(parsingContext: ParsingContext): ts.Node | undefined { + function currentNode(parsingContext: ParsingContext): 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 @@ -2416,7 +2500,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; } @@ -2431,7 +2515,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; } @@ -2442,15 +2526,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(); @@ -2474,7 +2558,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); @@ -2553,23 +2637,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; } @@ -2578,11 +2662,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; } } @@ -2590,38 +2674,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; } } @@ -2629,18 +2713,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; } } @@ -2648,8 +2732,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; } @@ -2667,17 +2751,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; } @@ -2695,46 +2779,46 @@ 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); + 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); default: return [undefined!]; // TODO: GH#18217 `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 = []; @@ -2752,7 +2836,7 @@ namespace Parser { list.push(result as NonNullable); 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; } @@ -2764,14 +2848,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()) { @@ -2804,24 +2888,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); @@ -2831,12 +2915,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; @@ -2845,7 +2929,7 @@ namespace Parser { entity = finishNode( factory.createQualifiedName( entity, - parseRightSideOfDot(allowReservedWords, /* allowPrivateIdentifiers */ false) as ts.Identifier + parseRightSideOfDot(allowReservedWords, /* allowPrivateIdentifiers */ false) as Identifier ), pos ); @@ -2853,11 +2937,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. @@ -2877,20 +2961,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(); @@ -2899,16 +2983,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( @@ -2919,7 +3003,7 @@ namespace Parser { ); } - function parseTemplateType(): ts.TemplateLiteralTypeNode { + function parseTemplateType(): TemplateLiteralTypeNode { const pos = getNodePos(); return finishNode( factory.createTemplateLiteralType( @@ -2933,16 +3017,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( @@ -2954,17 +3038,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( @@ -2975,45 +3059,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; @@ -3030,16 +3114,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( @@ -3051,46 +3135,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(); @@ -3105,12 +3189,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 { @@ -3118,24 +3202,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( @@ -3152,18 +3236,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(); @@ -3174,35 +3258,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 @@ -3222,31 +3306,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.ModifiersArray | undefined) { + function parseNameOfParameter(modifiers: ModifiersArray | 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) @@ -3264,20 +3348,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(); @@ -3287,7 +3371,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) : parseDecorators(); - if (token() === ts.SyntaxKind.ThisKeyword) { + if (token() === SyntaxKind.ThisKeyword) { const node = factory.createParameterDeclaration( decorators, /*modifiers*/ undefined, @@ -3299,7 +3383,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); @@ -3309,7 +3393,7 @@ namespace Parser { topLevel = false; const modifiers = parseModifiers(); - const dotDotDotToken = parseOptionalToken(ts.SyntaxKind.DotDotDotToken); + const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); if (!allowAmbiguity && !isParameterNameStart()) { return undefined; @@ -3322,7 +3406,7 @@ namespace Parser { modifiers, dotDotDotToken, parseNameOfParameter(modifiers), - parseOptionalToken(ts.SyntaxKind.QuestionToken), + parseOptionalToken(SyntaxKind.QuestionToken), parseTypeAnnotation(), parseInitializer() ), @@ -3334,34 +3418,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] @@ -3391,7 +3475,7 @@ namespace Parser { return parameters; } - function parseParameters(flags: SignatureFlags): ts.NodeArray { + function parseParameters(flags: SignatureFlags): NodeArray { // FormalParameters [Yield,Await]: (modified) // [empty] // FormalParameterList[?Yield,Await] @@ -3405,19 +3489,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; } @@ -3425,25 +3509,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() { @@ -3464,11 +3548,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; @@ -3485,40 +3569,40 @@ 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(decorators, modifiers, parameters, type); 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 { @@ -3527,7 +3611,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.initializer = parseInitializer(); + if (token() === SyntaxKind.EqualsToken) node.initializer = parseInitializer(); } parseTypeMemberSemicolon(); return withJSDoc(finishNode(node, pos), hasJSDoc); @@ -3535,20 +3619,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 @@ -3559,32 +3643,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); + if (parseContextualModifier(SyntaxKind.GetKeyword)) { + return parseAccessorDeclaration(pos, hasJSDoc, /*decorators*/ undefined, modifiers, SyntaxKind.GetAccessor); } - if (parseContextualModifier(ts.SyntaxKind.SetKeyword)) { - return parseAccessorDeclaration(pos, hasJSDoc, /*decorators*/ undefined, modifiers, ts.SyntaxKind.SetAccessor); + if (parseContextualModifier(SyntaxKind.SetKeyword)) { + return parseAccessorDeclaration(pos, hasJSDoc, /*decorators*/ undefined, modifiers, SyntaxKind.SetAccessor); } if (isIndexSignature()) { @@ -3595,36 +3679,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; @@ -3632,85 +3716,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); @@ -3718,181 +3802,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(); @@ -3901,48 +3985,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); @@ -3953,19 +4037,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; @@ -3973,15 +4057,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; @@ -3992,22 +4076,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); @@ -4015,20 +4099,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); @@ -4036,22 +4120,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); @@ -4061,12 +4145,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(); @@ -4080,40 +4164,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(); @@ -4124,7 +4208,7 @@ namespace Parser { function isUnambiguouslyStartOfFunctionType() { nextToken(); - if (token() === ts.SyntaxKind.CloseParenToken || token() === ts.SyntaxKind.DotDotDotToken) { + if (token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.DotDotDotToken) { // ( ) // ( ... return true; @@ -4132,17 +4216,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; } @@ -4151,7 +4235,7 @@ namespace Parser { return false; } - function parseTypeOrTypePredicate(): ts.TypeNode { + function parseTypeOrTypePredicate(): TypeNode { const pos = getNodePos(); const typePredicateVariable = isIdentifier() && tryParse(parseTypePredicatePrefix); const type = parseType(); @@ -4165,23 +4249,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()) { @@ -4189,46 +4273,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(); @@ -4241,19 +4325,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. @@ -4273,14 +4357,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] @@ -4293,8 +4377,8 @@ namespace Parser { const pos = getNodePos(); let expr = parseAssignmentExpressionOrHigher(); - let operatorToken: ts.BinaryOperatorToken; - while ((operatorToken = parseOptionalToken(ts.SyntaxKind.CommaToken))) { + let operatorToken: BinaryOperatorToken; + while ((operatorToken = parseOptionalToken(SyntaxKind.CommaToken))) { expr = makeBinaryExpression(expr, operatorToken, parseAssignmentExpressionOrHigher(), pos); } @@ -4304,11 +4388,11 @@ namespace Parser { return expr; } - function parseInitializer(): ts.Expression | undefined { - return parseOptional(ts.SyntaxKind.EqualsToken) ? parseAssignmentExpressionOrHigher() : undefined; + function parseInitializer(): Expression | undefined { + return parseOptional(SyntaxKind.EqualsToken) ? parseAssignmentExpressionOrHigher() : undefined; } - function parseAssignmentExpressionOrHigher(): ts.Expression { + function parseAssignmentExpressionOrHigher(): Expression { // AssignmentExpression[in,yield]: // 1) ConditionalExpression[?in,?yield] // 2) LeftHandSideExpression = AssignmentExpression[?in,?yield] @@ -4351,13 +4435,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, /*asyncModifier*/ undefined); + if (expr.kind === SyntaxKind.Identifier && token() === SyntaxKind.EqualsGreaterThanToken) { + return parseSimpleArrowFunctionExpression(pos, expr as Identifier, /*asyncModifier*/ undefined); } // Now see if we might be in cases '2' or '3'. @@ -4366,7 +4450,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(), pos); } @@ -4375,7 +4459,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()) { @@ -4407,7 +4491,7 @@ namespace Parser { return !scanner.hasPrecedingLineBreak() && isIdentifier(); } - function parseYieldExpression(): ts.YieldExpression { + function parseYieldExpression(): YieldExpression { const pos = getNodePos(); // YieldExpression[In] : @@ -4417,10 +4501,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() ), pos @@ -4433,8 +4517,8 @@ namespace Parser { } } - function parseSimpleArrowFunctionExpression(pos: number, identifier: ts.Identifier, 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, asyncModifier?: NodeArray | undefined): ArrowFunction { + Debug.assert(token() === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>"); const parameter = factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, @@ -4446,14 +4530,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); const node = factory.createArrowFunction(asyncModifier, /*typeParameters*/ undefined, parameters, /*type*/ undefined, equalsGreaterThanToken, body); return addJSDocComment(finishNode(node, pos)); } - function tryParseParenthesizedArrowFunctionExpression(): ts.Expression | undefined { + function tryParseParenthesizedArrowFunctionExpression(): Expression | undefined { const triState = isParenthesizedArrowFunctionExpression(); if (triState === Tristate.False) { // It's definitely not a parenthesized arrow function expression. @@ -4474,11 +4558,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. @@ -4489,12 +4573,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; } } @@ -4502,17 +4586,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; @@ -4525,21 +4609,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; } @@ -4549,26 +4633,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; } @@ -4576,7 +4660,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. @@ -4585,20 +4669,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; @@ -4616,7 +4700,7 @@ namespace Parser { } } - function parsePossibleParenthesizedArrowFunctionExpression(): ts.ArrowFunction | undefined { + function parsePossibleParenthesizedArrowFunctionExpression(): ArrowFunction | undefined { const tokenPos = scanner.getTokenPos(); if (notParenthesizedArrow?.has(tokenPos)) { return undefined; @@ -4624,20 +4708,20 @@ namespace Parser { const result = parseParenthesizedArrowFunctionExpression(/*allowAmbiguity*/ false); if (!result) { - (notParenthesizedArrow || (notParenthesizedArrow = new ts.Set())).add(tokenPos); + (notParenthesizedArrow || (notParenthesizedArrow = new Set())).add(tokenPos); } return result; } - function tryParseAsyncSimpleArrowFunctionExpression(): ts.ArrowFunction | undefined { + function tryParseAsyncSimpleArrowFunctionExpression(): 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, asyncModifier); + const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest); + return parseSimpleArrowFunctionExpression(pos, expr as Identifier, asyncModifier); } } return undefined; @@ -4647,16 +4731,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; } } @@ -4664,11 +4748,11 @@ namespace Parser { return Tristate.False; } - function parseParenthesizedArrowFunctionExpression(allowAmbiguity: boolean): ts.ArrowFunction | undefined { + function parseParenthesizedArrowFunctionExpression(allowAmbiguity: 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 @@ -4678,12 +4762,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) { @@ -4696,12 +4780,12 @@ namespace Parser { else { parameters = parseParametersWorker(isAsync, allowAmbiguity); } - if (!parseExpected(ts.SyntaxKind.CloseParenToken) && !allowAmbiguity) { + if (!parseExpected(SyntaxKind.CloseParenToken) && !allowAmbiguity) { return undefined; } } - const type = parseReturnType(ts.SyntaxKind.ColonToken, /*isType*/ false); + const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false); if (type && !allowAmbiguity && typeHasArrowFunctionBlockingParseError(type)) { return undefined; } @@ -4718,12 +4802,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; } @@ -4731,23 +4815,23 @@ 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)) + const equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken); + const body = (lastToken === SyntaxKind.EqualsGreaterThanToken || lastToken === SyntaxKind.OpenBraceToken) + ? parseArrowFunctionExpressionBody(some(modifiers, isAsyncModifier)) : parseIdentifier(); const node = factory.createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body); return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseArrowFunctionExpressionBody(isAsync: boolean): ts.Block | ts.Expression { - if (token() === ts.SyntaxKind.OpenBraceToken) { + function parseArrowFunctionExpressionBody(isAsync: 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) @@ -4776,9 +4860,9 @@ namespace Parser { return node; } - function parseConditionalExpressionRest(leftOperand: ts.Expression, pos: number): ts.Expression { + function parseConditionalExpressionRest(leftOperand: Expression, pos: number): 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; } @@ -4791,32 +4875,32 @@ namespace Parser { leftOperand, questionToken, doOutsideOfContext(disallowInAndDecoratorContext, parseAssignmentExpressionOrHigher), - colonToken = parseExpectedToken(ts.SyntaxKind.ColonToken), - ts.nodeIsPresent(colonToken) + colonToken = parseExpectedToken(SyntaxKind.ColonToken), + nodeIsPresent(colonToken) ? parseAssignmentExpressionOrHigher() - : 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, @@ -4839,7 +4923,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; @@ -4847,11 +4931,11 @@ namespace Parser { break; } - if (token() === ts.SyntaxKind.InKeyword && inDisallowInContext()) { + if (token() === SyntaxKind.InKeyword && inDisallowInContext()) { break; } - if (token() === ts.SyntaxKind.AsKeyword) { + if (token() === SyntaxKind.AsKeyword) { // Make sure we *do* perform ASI for constructs like this: // var x = foo // as (Bar) @@ -4874,24 +4958,24 @@ 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 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() { @@ -4910,7 +4994,7 @@ namespace Parser { } function isAwaitExpression(): boolean { - if (token() === ts.SyntaxKind.AwaitKeyword) { + if (token() === SyntaxKind.AwaitKeyword) { if (inAwaitContext()) { return true; } @@ -4935,7 +5019,7 @@ namespace Parser { * 2) UpdateExpression[?Yield] ** ExponentiationExpression[?Yield] * */ - function parseUnaryExpressionOrHigher(): ts.UnaryExpression | ts.BinaryExpression { + function parseUnaryExpressionOrHigher(): UnaryExpression | BinaryExpression { /** * ES7 UpdateExpression: * 1) LeftHandSideExpression[?Yield] @@ -4947,8 +5031,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; } @@ -4965,14 +5049,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; @@ -4992,25 +5076,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(); } @@ -5034,18 +5118,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. @@ -5066,21 +5150,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); } @@ -5088,7 +5172,7 @@ namespace Parser { return expression; } - function parseLeftHandSideExpressionOrHigher(): ts.LeftHandSideExpression { + function parseLeftHandSideExpressionOrHigher(): LeftHandSideExpression { // Original Ecma: // LeftHandSideExpression: See 11.2 // NewExpression @@ -5121,30 +5205,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 @@ -5153,7 +5237,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: @@ -5206,38 +5290,38 @@ namespace Parser { return parseMemberExpressionRest(pos, expression, /*allowOptionalChain*/ true); } - function parseSuperExpression(): ts.MemberExpression { + function parseSuperExpression(): MemberExpression { const pos = getNodePos(); - const expression = parseTokenNode(); - if (token() === ts.SyntaxKind.LessThanToken) { + const 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 (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, @@ -5257,23 +5341,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; } @@ -5285,59 +5369,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; @@ -5347,8 +5431,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 @@ -5360,28 +5444,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 @@ -5389,8 +5473,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(); @@ -5405,7 +5489,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 @@ -5413,34 +5497,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(); } } @@ -5448,8 +5532,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(); } @@ -5458,36 +5542,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(); @@ -5499,13 +5583,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(); @@ -5517,41 +5601,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; @@ -5560,32 +5644,32 @@ 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); } 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) : @@ -5593,16 +5677,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) { @@ -5611,21 +5695,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; @@ -5637,34 +5721,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()) { @@ -5672,11 +5756,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) ? @@ -5687,7 +5771,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; @@ -5696,25 +5780,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 (!parseExpected(ts.SyntaxKind.GreaterThanToken)) { + if (!parseExpected(SyntaxKind.GreaterThanToken)) { // If it doesn't have the closing `>` then it's definitely not an type argument list. return undefined; } @@ -5729,35 +5813,35 @@ 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; } // Consider something a type argument list only if the following token can't start an expression. return !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. @@ -5766,68 +5850,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(); 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(); } - 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(); return withJSDoc(finishNode(factory.createSpreadAssignment(expression), pos), hasJSDoc); } @@ -5835,22 +5919,22 @@ namespace Parser { const decorators = parseDecorators(); const modifiers = parseModifiers(); - if (parseContextualModifier(ts.SyntaxKind.GetKeyword)) { - return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, ts.SyntaxKind.GetAccessor); + if (parseContextualModifier(SyntaxKind.GetKeyword)) { + return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.GetAccessor); } - if (parseContextualModifier(ts.SyntaxKind.SetKeyword)) { - return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, ts.SyntaxKind.SetAccessor); + if (parseContextualModifier(SyntaxKind.SetKeyword)) { + return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.SetAccessor); } - 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); } @@ -5859,18 +5943,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) : 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); node = factory.createPropertyAssignment(name, initializer); } @@ -5882,17 +5966,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 } // @@ -5904,10 +5988,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) : @@ -5915,7 +5999,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); @@ -5924,54 +6008,54 @@ 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; } - 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)); @@ -6001,67 +6085,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 { @@ -6069,116 +6153,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); - 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' @@ -6197,33 +6281,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. @@ -6234,24 +6318,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 { @@ -6269,33 +6353,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; @@ -6319,19 +6403,19 @@ 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.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.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()) { @@ -6339,27 +6423,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: @@ -6374,55 +6458,55 @@ 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.PublicKeyword: - case ts.SyntaxKind.PrivateKeyword: - case ts.SyntaxKind.ProtectedKeyword: - case ts.SyntaxKind.StaticKeyword: - case ts.SyntaxKind.ReadonlyKeyword: + 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); @@ -6434,7 +6518,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() { @@ -6443,70 +6527,70 @@ 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.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.StaticKeyword: + case SyntaxKind.ReadonlyKeyword: + case SyntaxKind.GlobalKeyword: if (isStartOfDeclaration()) { return parseDeclaration(); } @@ -6515,18 +6599,18 @@ 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 { // TODO: Can we hold onto the parsed decorators/modifiers and advance the scanner // if we can't reuse the declaration, so that we don't do this work twice? // // `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. - const isAmbient = ts.some(lookAhead(() => (parseDecorators(), parseModifiers())), isDeclareModifier); + const isAmbient = some(lookAhead(() => (parseDecorators(), parseModifiers())), isDeclareModifier); if (isAmbient) { const node = tryReuseAmbientDeclaration(); if (node) { @@ -6540,53 +6624,53 @@ namespace Parser { const modifiers = parseModifiers(); 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, () => parseDeclarationWorker(pos, hasJSDoc, decorators, modifiers)); + return doInsideOfContext(NodeFlags.Ambient, () => parseDeclarationWorker(pos, hasJSDoc, decorators, modifiers)); } else { return parseDeclarationWorker(pos, hasJSDoc, decorators, modifiers); } } - function tryReuseAmbientDeclaration(): ts.Statement | undefined { - return doInsideOfContext(ts.NodeFlags.Ambient, () => { + function tryReuseAmbientDeclaration(): Statement | undefined { + return doInsideOfContext(NodeFlags.Ambient, () => { const node = currentNode(parsingContext); 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); @@ -6595,8 +6679,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.decorators = decorators; missing.modifiers = modifiers; return missing; @@ -6607,11 +6691,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 && canParseSemicolon()) { + function parseFunctionBlockOrSemicolon(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block | undefined { + if (token() !== SyntaxKind.OpenBraceToken && canParseSemicolon()) { parseSemicolon(); return; } @@ -6621,63 +6705,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); @@ -6687,14 +6771,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(); @@ -6702,21 +6786,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(); @@ -6730,9 +6814,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(); @@ -6748,10 +6832,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); @@ -6760,31 +6844,31 @@ 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(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body); 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; @@ -6792,13 +6876,13 @@ 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(decorators, modifiers, parameters, body); // Attach `typeParameters` and `type` if they exist so that we can report them in the grammar checker. node.typeParameters = typeParameters; @@ -6811,19 +6895,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( decorators, @@ -6844,14 +6928,14 @@ namespace Parser { 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(decorators, modifiers, name, questionToken || exclamationToken, type, initializer); return withJSDoc(finishNode(node, pos), hasJSDoc); @@ -6860,44 +6944,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"]): ts.AccessorDeclaration { + function parseAccessorDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined, kind: AccessorDeclaration["kind"]): 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(SignatureFlags.None); - const node = kind === ts.SyntaxKind.GetAccessor + const node = kind === SyntaxKind.GetAccessor ? factory.createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, body) : factory.createSetAccessorDeclaration(decorators, modifiers, name, parameters, body); // Keep track of `typeParameters` (for both) and `type` (for setters) if they were parsed those indicate grammar errors node.typeParameters = typeParameters; - if (type && node.kind === ts.SyntaxKind.SetAccessor) (node as ts.Mutable).type = type; + if (type && node.kind === SyntaxKind.SetAccessor) (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 @@ -6905,14 +6989,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; } @@ -6924,26 +7008,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 @@ -6958,8 +7042,8 @@ 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(); return withJSDoc(finishNode(factory.createClassStaticBlockDeclaration(decorators, modifiers, body), pos), hasJSDoc); } @@ -6980,11 +7064,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); @@ -6992,39 +7076,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 { @@ -7033,7 +7117,7 @@ namespace Parser { } } - return finishNode(factory.createToken(kind as ts.Modifier["kind"]), pos); + return finishNode(factory.createToken(kind as Modifier["kind"]), pos); } /* @@ -7043,30 +7127,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); } @@ -7074,19 +7158,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); + if (parseContextualModifier(SyntaxKind.GetKeyword)) { + return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.GetAccessor); } - if (parseContextualModifier(ts.SyntaxKind.SetKeyword)) { - return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, ts.SyntaxKind.SetAccessor); + if (parseContextualModifier(SyntaxKind.SetKeyword)) { + return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.SetAccessor); } - 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; @@ -7099,17 +7183,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); @@ -7118,50 +7202,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(decorators, modifiers, name, typeParameters, heritageClauses, members) : factory.createClassExpression(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 @@ -7173,10 +7257,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 } @@ -7187,40 +7271,40 @@ 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(); @@ -7229,12 +7313,12 @@ namespace Parser { 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(decorators, modifiers, name, typeParameters, type); return withJSDoc(finishNode(node, pos), hasJSDoc); @@ -7244,7 +7328,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(); @@ -7252,60 +7336,60 @@ 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(decorators, modifiers, name, members); 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(decorators, modifiers, name, body, flags); 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 { @@ -7315,18 +7399,18 @@ namespace Parser { 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); } } @@ -7334,25 +7418,25 @@ 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); @@ -7362,19 +7446,19 @@ namespace Parser { 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()) ) { @@ -7389,18 +7473,18 @@ 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(); } @@ -7411,8 +7495,8 @@ namespace Parser { 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(); return finishNode(factory.createAssertEntry(name, value), pos); } @@ -7420,18 +7504,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, "{", "}") ); } } @@ -7444,17 +7528,17 @@ 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(decorators, modifiers, isTypeOnly, identifier, moduleReference); @@ -7462,7 +7546,7 @@ namespace Parser { return finished; } - function parseImportClause(identifier: ts.Identifier | undefined, pos: number, isTypeOnly: boolean) { + function parseImportClause(identifier: Identifier | undefined, pos: number, isTypeOnly: boolean) { // ImportClause: // ImportedDefaultBinding // NameSpaceImport @@ -7472,10 +7556,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); @@ -7489,15 +7573,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; @@ -7510,19 +7594,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: @@ -7533,22 +7617,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 @@ -7556,11 +7640,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") { @@ -7571,13 +7655,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; @@ -7591,7 +7675,7 @@ namespace Parser { canParseAsKeyword = false; } } - else if (ts.tokenIsIdentifierOrKeyword(token())) { + else if (tokenIsIdentifierOrKeyword(token())) { // { type as something } propertyName = name; canParseAsKeyword = false; @@ -7603,64 +7687,64 @@ 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(); @@ -7669,15 +7753,15 @@ namespace Parser { 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(); parseSemicolon(); @@ -7722,16 +7806,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(); @@ -7740,12 +7824,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); @@ -7753,18 +7837,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); @@ -7772,26 +7856,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 = []; } @@ -7816,27 +7900,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, () => { @@ -7856,14 +7940,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(); @@ -7878,12 +7962,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 @@ -7896,7 +7980,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) { @@ -7907,9 +7991,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; @@ -7939,7 +8023,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); }); @@ -7960,28 +8044,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 } @@ -7990,14 +8074,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(); @@ -8006,14 +8090,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); @@ -8092,10 +8176,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; @@ -8114,16 +8198,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 @@ -8132,10 +8216,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()); } @@ -8148,7 +8232,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; @@ -8163,7 +8247,7 @@ namespace Parser { pushComment(scanner.getTokenText()); } break; - case ts.SyntaxKind.BacktickToken: + case SyntaxKind.BacktickToken: if (state === JSDocState.SavingBackticks) { state = JSDocState.SavingComments; } @@ -8172,7 +8256,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; @@ -8188,7 +8272,7 @@ namespace Parser { pushComment(scanner.getTokenText()); break; } - previousWhitespace = token() === ts.SyntaxKind.WhitespaceTrivia; + previousWhitespace = token() === SyntaxKind.WhitespaceTrivia; tok = nextTokenJSDoc(); } @@ -8207,7 +8291,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) { @@ -8219,18 +8303,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(); } @@ -8242,9 +8326,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; } @@ -8254,11 +8338,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; } @@ -8272,48 +8356,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(); @@ -8338,35 +8422,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); @@ -8374,15 +8458,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(); @@ -8391,23 +8475,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; @@ -8419,57 +8503,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(); @@ -8478,17 +8562,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; } @@ -8497,11 +8581,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 : @@ -8525,19 +8609,19 @@ 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( /*decorators*/ undefined, /*modifiers*/ undefined, typeNameOrNamespaceName, body, - nested ? ts.NodeFlags.NestedNamespace : undefined - ) as ts.JSDocNamespaceDeclaration; + nested ? NodeFlags.NestedNamespace : undefined + ) as JSDocNamespaceDeclaration; return finishNode(jsDocNamespaceNode, pos); } @@ -8550,24 +8634,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; } } }); @@ -8579,7 +8663,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; @@ -8593,18 +8677,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; @@ -8613,27 +8697,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(); @@ -8663,21 +8747,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); @@ -8693,11 +8777,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 @@ -8709,12 +8793,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; @@ -8722,27 +8806,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++; @@ -8759,11 +8843,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; } @@ -8780,8 +8864,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; @@ -8794,14 +8878,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 @@ -8823,7 +8907,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 @@ -8840,7 +8924,7 @@ namespace IncrementalParser { sourceFile.commentDirectives, result.commentDirectives, changeRange.span.start, - ts.textSpanEnd(changeRange.span), + textSpanEnd(changeRange.span), delta, oldText, newText, @@ -8851,35 +8935,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 @@ -8920,16 +9004,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); @@ -8937,7 +9021,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); @@ -8945,11 +9029,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; } @@ -8957,9 +9041,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 @@ -9021,29 +9105,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); } } @@ -9061,7 +9145,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. @@ -9080,9 +9164,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); @@ -9090,11 +9174,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. @@ -9119,11 +9203,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() { /; } // @@ -9143,21 +9227,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); @@ -9170,9 +9254,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; } @@ -9182,8 +9266,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; @@ -9213,7 +9297,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) // @@ -9231,7 +9315,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. @@ -9240,35 +9324,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; } @@ -9279,11 +9363,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; @@ -9317,7 +9401,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; } }; @@ -9335,7 +9419,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); @@ -9348,7 +9432,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. @@ -9387,46 +9471,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); @@ -9443,7 +9527,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 { @@ -9461,7 +9545,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; @@ -9477,14 +9561,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; } @@ -9493,20 +9577,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", @@ -9522,12 +9606,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)!; @@ -9539,12 +9623,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) { @@ -9570,46 +9654,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]; @@ -9617,7 +9701,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]; } @@ -9625,22 +9709,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 eac5dc3a14914..01cf8c2eac2a3 100644 --- a/src/compiler/path.ts +++ b/src/compiler/path.ts @@ -1,4 +1,11 @@ -import * as ts from "./_namespaces/ts"; +import { + compareStringsCaseInsensitive, compareStringsCaseSensitive, compareValues, endsWith, equateStringsCaseInsensitive, + equateStringsCaseSensitive, GetCanonicalFileName, getStringComparer, identity, lastOrUndefined, some, startsWith, + stringContains, +} from "./core"; +import { Comparison } from "./corePublic"; +import { Debug } from "./debug"; +import { CharacterCodes, Path } from "./types"; /* @internal */ /** @@ -19,7 +26,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 +94,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 +124,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 +147,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 +178,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 +251,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 +359,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 +407,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 +420,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]; } @@ -492,7 +499,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]; @@ -558,7 +565,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 */ @@ -612,11 +619,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 @@ -630,7 +637,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 */ @@ -651,7 +658,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 */ @@ -702,7 +709,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 @@ -710,17 +717,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; } @@ -739,11 +746,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 */ @@ -751,7 +758,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 */ @@ -759,16 +766,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") { @@ -778,7 +785,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 */ @@ -805,9 +812,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; } @@ -823,16 +830,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)); @@ -840,7 +847,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; } @@ -865,13 +872,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); } @@ -883,16 +890,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 ); @@ -911,11 +918,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) { @@ -932,6 +939,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 aa962fdae2b0f..162bb087bfdbf 100644 --- a/src/compiler/perfLogger.ts +++ b/src/compiler/perfLogger.ts @@ -1,27 +1,27 @@ -import * as ts from "./_namespaces/ts"; +import { noop } from "./core"; 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 b4a3d4c13afd3..7c09faa665bb2 100644 --- a/src/compiler/performance.ts +++ b/src/compiler/performance.ts @@ -1,9 +1,13 @@ -import * as ts from "./_namespaces/ts"; +import { noop } from "./core"; +import { Map } from "./corePublic"; +import { Debug } from "./debug"; +import { Performance, PerformanceHooks, timestamp, tryGetNativePerformanceHooks } from "./performanceCore"; +import { sys, System } from "./sys"; -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 { @@ -36,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 */ /** @@ -60,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); } } @@ -77,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)); @@ -125,10 +129,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 96135f01688e7..80561e4b5b330 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 "./semver"; // The following definitions provide the minimum compatible support for the Web Performance User Timings API // between browsers and NodeJS: @@ -86,8 +86,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 e51bc343e5cdd..07250f8584631 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1,24 +1,121 @@ import * as ts from "./_namespaces/ts"; +import { BuilderProgram } from "./builderPublic"; +import { createTypeChecker } from "./checker"; +import { + DiagnosticReporter, inverseJsxOptionMap, libMap, libs, ParseConfigFileHost, parseJsonSourceFileConfigFileContent, + sourceFileAffectingCompilerOptions, targetOptionDeclaration, +} from "./commandLineParser"; +import { + addRange, append, arrayFrom, arrayIsEqualTo, clone, compareValues, concatenate, contains, + createGetCanonicalFileName, createMultiMap, emptyArray, equateStringsCaseInsensitive, equateStringsCaseSensitive, + filter, find, firstDefined, firstDefinedIterator, flatMap, flatten, forEach, GetCanonicalFileName, + getSpellingSuggestion, hasProperty, identity, isArray, isString, length, mapDefined, mapDefinedIterator, maybeBind, + memoize, noop, padLeft, removePrefix, removeSuffix, returnFalse, returnUndefined, some, stableSort, startsWith, + stringContains, toFileNameLowerCase, trimStringEnd, +} from "./core"; +import { Comparison, ESMap, Map, Set, SortedReadonlyArray } from "./corePublic"; +import { Debug } from "./debug"; +import { Diagnostics } from "./diagnosticInformationMap.generated"; +import { + emitFiles, forEachEmittedFile, getCommonSourceDirectoryOfConfig, getOutputDeclarationFileName, + getOutputPathsForBundle, getTsBuildInfoEmitOutputFilePath, isBuildInfoFile, notImplementedResolver, +} from "./emitter"; +import { addEmitFlags } from "./factory/emitNode"; +import { createInputFiles, factory } from "./factory/nodeFactory"; +import { + isArrayLiteralExpression, isExportDeclaration, isImportDeclaration, isImportEqualsDeclaration, isImportSpecifier, + isImportTypeNode, isModuleDeclaration, isObjectLiteralExpression, isStringLiteral, +} from "./factory/nodeTests"; +import { + createModeAwareCache, createModuleResolutionCache, createTypeReferenceDirectiveResolutionCache, + getAutomaticTypeDirectiveNames, getPackageScopeForPath, isTraceEnabled, ModuleResolutionCache, nodeModulesPathPart, + PackageJsonInfoCache, resolveModuleName, resolveModuleNameFromCache, resolveTypeReferenceDirective, trace, + TypeReferenceDirectiveResolutionCache, zipToModeAwareCache, +} from "./moduleNameResolver"; +import { + createSourceFile, CreateSourceFileOptions, forEachChild, forEachChildRecursively, isDeclarationFileName, + isExternalModule, parseIsolatedEntityName, +} from "./parser"; +import { + combinePaths, comparePaths, containsPath, convertToRelativePath, directorySeparator, + ensureTrailingDirectorySeparator, fileExtensionIs, fileExtensionIsOneOf, forEachAncestorDirectory, getBaseFileName, + getDirectoryPath, getNormalizedAbsolutePath, getNormalizedAbsolutePathWithoutRoot, getNormalizedPathComponents, + getPathFromPathComponents, getRootLength, hasExtension, isRootedDiskPath, normalizePath, pathIsAbsolute, + pathIsRelative, +} from "./path"; +import { mark, measure } from "./performance"; +import { + computeLineAndCharacterOfPosition, getLineAndCharacterOfPosition, getLineStarts, getPositionOfLineAndCharacter, + isIdentifierText, skipTrivia, tokenToString, +} from "./scanner"; +import { generateDjb2Hash, missingFileModifiedTime, sys } from "./sys"; +import { tracing } from "./tracing"; +import { getTransformers, noTransformers } from "./transformer"; +import { resolveConfigFileProjectName } from "./tsbuild"; +import { + __String, AsExpression, AssertClause, CancellationToken, CommentDirective, CommentDirectivesMap, CompilerHost, + CompilerOptions, CreateProgramOptions, CustomTransformers, DeclarationWithTypeParameterChildren, Diagnostic, + DiagnosticCategory, diagnosticCategoryName, DiagnosticMessage, DiagnosticMessageChain, DiagnosticWithLocation, + EmitFlags, EmitHost, EmitResult, ExportAssignment, ExportDeclaration, Extension, FileIncludeKind, FileIncludeReason, + FilePreprocessingDiagnostics, FilePreprocessingDiagnosticsKind, FileReference, FunctionLikeDeclaration, + HasChangedAutomaticTypeDirectiveNames, HasInvalidatedResolution, HeritageClause, Identifier, ImportClause, + ImportDeclaration, ImportOrExportSpecifier, InputFiles, JsonSourceFile, JsxEmit, MethodDeclaration, Modifier, + ModifierFlags, ModuleBlock, ModuleDeclaration, ModuleKind, ModuleResolutionHost, ModuleResolutionKind, Node, + NodeArray, NodeFlags, NodeWithTypeArguments, ObjectLiteralExpression, OperationCanceledException, PackageId, + ParameterDeclaration, ParsedCommandLine, Path, Program, ProjectReference, ProjectReferenceFile, PropertyDeclaration, + ReferencedFile, ResolvedConfigFileName, ResolvedModuleFull, ResolvedModuleWithFailedLookupLocations, + ResolvedProjectReference, ResolvedTypeReferenceDirective, ScriptKind, ScriptTarget, SourceFile, + SourceOfProjectReferenceRedirect, Statement, StringLiteral, StringLiteralLike, StructureIsReused, SyntaxKind, + TsConfigSourceFile, TypeChecker, UnparsedSource, VariableDeclaration, WriteFileCallback, WriteFileCallbackData, +} from "./types"; +import { + chainDiagnosticMessages, changeExtension, changesAffectingProgramStructure, changesAffectModuleResolution, + compareDataObjects, containsIgnoredPath, createCommentDirectivesMap, createCompilerDiagnostic, + createCompilerDiagnosticFromMessageChain, createDiagnosticCollection, createDiagnosticForNodeInSourceFile, + createDiagnosticForRange, createFileDiagnostic, createFileDiagnosticFromMessageChain, createSymlinkCache, + extensionFromPath, externalHelpersModuleNameText, forEachEntry, forEachKey, getAllowJSCompilerOption, + getEmitDeclarations, getEmitModuleKind, getEmitModuleResolutionKind, getEmitScriptTarget, getErrorSpanForNode, + getExternalModuleName, getJSXImplicitImportBase, getJSXRuntimeImport, getNewLineCharacter, + getPropertyArrayElementValue, getPropertyAssignment, getResolvedModule, getSetExternalModuleIndicator, + getStrictOptionValue, getSupportedExtensions, getSupportedExtensionsWithJsonIfResolveJsonModule, + getTextOfIdentifierOrLiteral, getTsConfigObjectLiteralExpression, getTsConfigPropArray, + getTsConfigPropArrayElementValue, hasChangesInResolutions, hasJSFileExtension, hasJsonModuleEmitEnabled, + hasSyntacticModifier, hasZeroOrOneAsteriskCharacter, isAmbientModule, isAnyImportOrReExport, + isCheckJsEnabledForFile, isImportCall, isIncrementalCompilation, isInJSFile, isLiteralImportTypeNode, isPlainJsFile, + isRequireCall, isSourceFileJS, isWatchSet, moduleResolutionIsEqualTo, Mutable, optionsHaveChanges, outFile, + packageIdToPackageName, packageIdToString, projectReferenceIsEqualTo, removeFileExtension, + resolutionExtensionIsTSOrJson, setParent, setParentRecursive, setResolvedModule, setResolvedTypeReferenceDirective, + skipTypeChecking, sourceFileMayBeEmitted, supportedJSExtensionsFlat, SymlinkCache, typeDirectiveIsEqualTo, + walkUpParenthesizedExpressions, writeFileEnsuringDirectories, +} from "./utilities"; +import { + getDefaultLibFileName, hasJSDocNodes, isExternalModuleNameRelative, isStringLiteralLike, + sortAndDeduplicateDiagnostics, +} from "./utilitiesPublic"; +import { + explainIfFileIsRedirect, fileIncludeReasonToDiagnostics, getMatchedFileSpec, getMatchedIncludeSpec, +} from "./watch"; +import { DirectoryStructureHost } from "./watchUtilities"; 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,7 +153,7 @@ export function computeCommonSourceDirectoryOfFilenames(fileNames: readonly stri return currentDirectory; } - return ts.getPathFromPathComponents(commonPathComponents); + return getPathFromPathComponents(commonPathComponents); } interface OutputFingerprint { @@ -65,23 +162,23 @@ interface OutputFingerprint { mtime: Date; } -export function createCompilerHost(options: ts.CompilerOptions, setParentNodes?: boolean): ts.CompilerHost { +export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost { return createCompilerHostWorker(options, setParentNodes); } /*@internal*/ // TODO(shkamat): update this after reworking ts build API -export function createCompilerHostWorker(options: ts.CompilerOptions, setParentNodes?: boolean, system = ts.sys): ts.CompilerHost { - const existingDirectories = new ts.Map(); - const getCanonicalFileName = ts.createGetCanonicalFileName(system.useCaseSensitiveFileNames); - const computeHash = ts.maybeBind(system, system.createHash) || ts.generateDjb2Hash; - function getSourceFile(fileName: string, languageVersionOrOptions: ts.ScriptTarget | ts.CreateSourceFileOptions, onError?: (message: string) => void): ts.SourceFile | undefined { +export function createCompilerHostWorker(options: CompilerOptions, setParentNodes?: boolean, system = sys): CompilerHost { + const existingDirectories = new Map(); + const getCanonicalFileName = createGetCanonicalFileName(system.useCaseSensitiveFileNames); + const computeHash = maybeBind(system, system.createHash) || generateDjb2Hash; + function getSourceFile(fileName: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void): SourceFile | undefined { let text: string | undefined; try { - ts.performance.mark("beforeIORead"); + mark("beforeIORead"); text = compilerHost.readFile(fileName); - ts.performance.mark("afterIORead"); - ts.performance.measure("I/O Read", "beforeIORead", "afterIORead"); + mark("afterIORead"); + measure("I/O Read", "beforeIORead", "afterIORead"); } catch (e) { if (onError) { @@ -89,7 +186,7 @@ export function createCompilerHostWorker(options: ts.CompilerOptions, setParentN } text = ""; } - return text !== undefined ? ts.createSourceFile(fileName, text, languageVersionOrOptions, setParentNodes) : undefined; + return text !== undefined ? createSourceFile(fileName, text, languageVersionOrOptions, setParentNodes) : undefined; } function directoryExists(directoryPath: string): boolean { @@ -105,12 +202,12 @@ export function createCompilerHostWorker(options: ts.CompilerOptions, setParentN function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) { try { - ts.performance.mark("beforeIOWrite"); + mark("beforeIOWrite"); // 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, @@ -118,8 +215,8 @@ export function createCompilerHostWorker(options: ts.CompilerOptions, setParentN path => (compilerHost.createDirectory || system.createDirectory)(path), path => directoryExists(path)); - ts.performance.mark("afterIOWrite"); - ts.performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite"); + mark("afterIOWrite"); + measure("I/O Write", "beforeIOWrite", "afterIOWrite"); } catch (e) { if (onError) { @@ -128,15 +225,15 @@ export function createCompilerHostWorker(options: ts.CompilerOptions, setParentN } } - let outputFingerprints: ts.ESMap; + let outputFingerprints: ESMap; function writeFileWorker(fileName: string, data: string, writeByteOrderMark: boolean) { - if (!ts.isWatchSet(options) || !system.getModifiedTime) { + if (!isWatchSet(options) || !system.getModifiedTime) { system.writeFile(fileName, data, writeByteOrderMark); return; } if (!outputFingerprints) { - outputFingerprints = new ts.Map(); + outputFingerprints = new Map(); } const hash = computeHash(data); @@ -155,7 +252,7 @@ export function createCompilerHostWorker(options: ts.CompilerOptions, setParentN system.writeFile(fileName, data, writeByteOrderMark); - const mtimeAfter = system.getModifiedTime(fileName) || ts.missingFileModifiedTime; + const mtimeAfter = system.getModifiedTime(fileName) || missingFileModifiedTime; outputFingerprints.set(fileName, { hash, @@ -165,17 +262,17 @@ 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, getDefaultLibLocation, - getDefaultLibFileName: options => ts.combinePaths(getDefaultLibLocation(), ts.getDefaultLibFileName(options)), + getDefaultLibFileName: options => combinePaths(getDefaultLibLocation(), getDefaultLibFileName(options)), writeFile, - getCurrentDirectory: ts.memoize(() => system.getCurrentDirectory()), + getCurrentDirectory: memoize(() => system.getCurrentDirectory()), useCaseSensitiveFileNames: () => system.useCaseSensitiveFileNames, getCanonicalFileName, getNewLine: () => newLine, @@ -188,7 +285,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; } @@ -199,24 +296,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); @@ -224,7 +321,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; @@ -234,20 +331,20 @@ 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, languageVersion, onError, shouldCreateNewSourceFile) => { + const getSourceFileWithCache: CompilerHost["getSourceFile"] | undefined = getSourceFile ? (fileName, languageVersion, onError, shouldCreateNewSourceFile) => { const key = toPath(fileName); const value = sourceFileCache.get(key); if (value) return value; const sourceFile = getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile); - if (sourceFile && (ts.isDeclarationFileName(fileName) || ts.fileExtensionIs(fileName, ts.Extension.Json))) { + if (sourceFile && (isDeclarationFileName(fileName) || fileExtensionIs(fileName, Extension.Json))) { sourceFileCache.set(key, sourceFile); } return sourceFile; @@ -310,21 +407,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 { @@ -333,7 +430,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) { @@ -342,13 +439,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; } @@ -369,12 +466,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; } } @@ -383,10 +480,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; @@ -400,22 +497,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. @@ -438,9 +535,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); @@ -451,7 +548,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) { @@ -460,7 +557,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()); @@ -485,8 +582,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) { @@ -511,17 +608,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)!; @@ -536,14 +633,14 @@ export function loadWithTypeDirectiveCache(names: string[] | readonly ts.File /* @internal */ interface SourceFileImportsList { - imports: ts.SourceFile["imports"]; - moduleAugmentations: ts.SourceFile["moduleAugmentations"]; - impliedNodeFormat?: ts.SourceFile["impliedNodeFormat"]; + imports: SourceFile["imports"]; + moduleAugmentations: SourceFile["moduleAugmentations"]; + impliedNodeFormat?: SourceFile["impliedNodeFormat"]; }; /* @internal */ -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; } /* @internal */ @@ -555,8 +652,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) { @@ -566,9 +663,9 @@ export function isExclusivelyTypeOnlyImportOrExport(decl: ts.ImportDeclaration | } /* @internal */ -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); @@ -577,50 +674,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; @@ -640,26 +737,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 @@ -668,7 +765,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; @@ -677,7 +774,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); }); } @@ -686,18 +783,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; @@ -706,16 +803,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; } @@ -725,30 +822,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 }; } @@ -758,26 +855,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, - hasInvalidatedResolution: ts.HasInvalidatedResolution, - hasChangedAutomaticTypeDirectiveNames: ts.HasChangedAutomaticTypeDirectiveNames | undefined, - getParsedCommandLine: (fileName: string) => ts.ParsedCommandLine | undefined, - projectReferences: readonly ts.ProjectReference[] | undefined + hasInvalidatedResolution: HasInvalidatedResolution, + 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; @@ -787,7 +884,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 @@ -795,24 +892,24 @@ export function isProgramUptoDate( return true; - function sourceFileNotUptoDate(sourceFile: ts.SourceFile) { + function sourceFileNotUptoDate(sourceFile: SourceFile) { return !sourceFileVersionUptoDate(sourceFile) || hasInvalidatedResolution(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); @@ -824,13 +921,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])); } @@ -841,7 +938,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; @@ -857,129 +954,129 @@ 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 { - 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() : +export function getImpliedNodeFormatForFile(fileName: Path, packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions): ModuleKind.ESNext | ModuleKind.CommonJS | undefined { + 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(): ts.ModuleKind.ESNext | ts.ModuleKind.CommonJS { - const scope = ts.getPackageScopeForPath(fileName, packageJsonInfoCache, host, options); - return scope?.packageJsonContent.type === "module" ? ts.ModuleKind.ESNext : ts.ModuleKind.CommonJS; + function lookupFromPackageJson(): ModuleKind.ESNext | ModuleKind.CommonJS { + const scope = getPackageScopeForPath(fileName, packageJsonInfoCache, host, options); + return scope?.packageJsonContent.type === "module" ? ModuleKind.ESNext : ModuleKind.CommonJS; } } /** @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, + 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, ]); /** * 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, @@ -999,7 +1096,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. @@ -1014,26 +1111,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: @@ -1047,58 +1144,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); - ts.performance.mark("beforeProgram"); + tracing?.push(tracing.Phase.Program, "createProgram", { configFilePath: options.configFilePath, rootDir: options.rootDir }, /*separateBeginAndEnd*/ true); + 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 hasInvalidatedResolution = host.hasInvalidatedResolution || ts.returnFalse; + let moduleResolutionCache: ModuleResolutionCache | undefined; + let typeReferenceDirectiveResolutionCache: TypeReferenceDirectiveResolutionCache | undefined; + let actualResolveModuleNamesWorker: (moduleNames: string[], containingFile: SourceFile, containingFileName: string, reusedNames?: string[], redirectedReference?: ResolvedProjectReference) => ResolvedModuleFull[]; + const hasInvalidatedResolution = host.hasInvalidatedResolution || 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, @@ -1107,17 +1204,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; /** @@ -1126,17 +1223,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; @@ -1151,16 +1248,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 = []; @@ -1171,23 +1268,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 }); } } } @@ -1196,24 +1293,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: @@ -1225,22 +1322,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. @@ -1283,7 +1380,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, @@ -1348,35 +1445,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(); + mark("afterProgram"); + measure("Program", "beforeProgram", "afterProgram"); + 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) { @@ -1389,43 +1486,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 }); - ts.performance.mark("beforeResolveModule"); + tracing?.push(tracing.Phase.Program, "resolveModuleNamesWorker", { containingFileName }); + mark("beforeResolveModule"); const result = actualResolveModuleNamesWorker(moduleNames, containingFile, containingFileName, reusedNames, redirectedReference); - ts.performance.mark("afterResolveModule"); - ts.performance.measure("ResolveModule", "beforeResolveModule", "afterResolveModule"); - ts.tracing?.pop(); + mark("afterResolveModule"); + measure("ResolveModule", "beforeResolveModule", "afterResolveModule"); + 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 }); - ts.performance.mark("beforeResolveTypeReference"); + 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 }); + mark("beforeResolveTypeReference"); const result = actualResolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames, containingFileName, redirectedReference, containingFileMode); - ts.performance.mark("afterResolveTypeReference"); - ts.performance.measure("ResolveTypeReference", "beforeResolveTypeReference", "afterResolveTypeReference"); - ts.tracing?.pop(); + mark("afterResolveTypeReference"); + measure("ResolveTypeReference", "beforeResolveTypeReference", "afterResolveTypeReference"); + 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 @@ -1436,52 +1533,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) @@ -1494,7 +1591,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)); @@ -1504,8 +1601,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP return classifiableNames; } - function resolveModuleNamesReusingOldState(moduleNames: string[], file: ts.SourceFile): readonly ts.ResolvedModuleFull[] { - if (structureIsReused === ts.StructureIsReused.Not && !file.ambientModuleNames.length) { + function resolveModuleNamesReusingOldState(moduleNames: string[], file: SourceFile): readonly ResolvedModuleFull[] { + 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); @@ -1521,7 +1618,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[] = []; + const result: ResolvedModuleFull[] = []; let i = 0; for (const moduleName of moduleNames) { const resolvedModule = file.resolvedModules.get(moduleName, getModeForResolutionAtIndex(file, i))!; @@ -1546,26 +1643,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; + let result: ResolvedModuleFull[] | 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 && !hasInvalidatedResolution(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; @@ -1578,10 +1675,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 { @@ -1599,12 +1696,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; } @@ -1622,15 +1719,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 @@ -1647,8 +1744,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; } @@ -1665,7 +1762,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 @@ -1675,52 +1772,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) { let newSourceFile = host.getSourceFileByPath @@ -1728,10 +1825,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP : host.getSourceFile(oldSourceFile.fileName, getCreateSourceFileOptions(oldSourceFile.fileName, moduleResolutionCache, host, options), /*onError*/ undefined, shouldCreateNewSourceFile); // TODO: GH#18217 if (!newSourceFile) { - return ts.StructureIsReused.Not; + return StructureIsReused.Not; } - 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) { @@ -1739,7 +1836,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. @@ -1747,7 +1844,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; } @@ -1768,7 +1865,7 @@ 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); } @@ -1776,41 +1873,41 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP if (fileChanged) { // The `newSourceFile` object was created for the new program. - if (!ts.arrayIsEqualTo(oldSourceFile.libReferenceDirectives, newSourceFile.libReferenceDirectives, fileReferenceIsEqualTo)) { + if (!arrayIsEqualTo(oldSourceFile.libReferenceDirectives, newSourceFile.libReferenceDirectives, fileReferenceIsEqualTo)) { // 'lib' references has changed. Matches behavior in changesAffectModuleResolution - structureIsReused = ts.StructureIsReused.SafeModules; + structureIsReused = StructureIsReused.SafeModules; } 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 - if (!ts.arrayIsEqualTo(oldSourceFile.referencedFiles, newSourceFile.referencedFiles, fileReferenceIsEqualTo)) { + if (!arrayIsEqualTo(oldSourceFile.referencedFiles, newSourceFile.referencedFiles, fileReferenceIsEqualTo)) { // tripleslash references has changed - structureIsReused = ts.StructureIsReused.SafeModules; + structureIsReused = StructureIsReused.SafeModules; } // 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; } - if (!ts.arrayIsEqualTo(oldSourceFile.moduleAugmentations, newSourceFile.moduleAugmentations, moduleNameIsEqualTo)) { + if (!arrayIsEqualTo(oldSourceFile.moduleAugmentations, newSourceFile.moduleAugmentations, moduleNameIsEqualTo)) { // moduleAugmentations has changed - structureIsReused = ts.StructureIsReused.SafeModules; + structureIsReused = StructureIsReused.SafeModules; } - if ((oldSourceFile.flags & ts.NodeFlags.PermanentlySetIncrementalFlags) !== (newSourceFile.flags & ts.NodeFlags.PermanentlySetIncrementalFlags)) { + if ((oldSourceFile.flags & NodeFlags.PermanentlySetIncrementalFlags) !== (newSourceFile.flags & NodeFlags.PermanentlySetIncrementalFlags)) { // dynamicImport has changed - structureIsReused = ts.StructureIsReused.SafeModules; + structureIsReused = StructureIsReused.SafeModules; } - if (!ts.arrayIsEqualTo(oldSourceFile.typeReferenceDirectives, newSourceFile.typeReferenceDirectives, fileReferenceIsEqualTo)) { + if (!arrayIsEqualTo(oldSourceFile.typeReferenceDirectives, newSourceFile.typeReferenceDirectives, fileReferenceIsEqualTo)) { // 'types' references has changed - structureIsReused = ts.StructureIsReused.SafeModules; + structureIsReused = StructureIsReused.SafeModules; } // tentatively approve the file @@ -1818,7 +1915,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } else if (hasInvalidatedResolution(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 }); @@ -1828,13 +1925,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); } @@ -1845,10 +1942,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; @@ -1856,28 +1953,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); } @@ -1906,10 +2003,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, @@ -1933,7 +2030,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); }, @@ -1950,28 +2047,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); - ts.performance.mark("beforeEmit"); - const emitResult = ts.emitFiles( - ts.notImplementedResolver, + function emitBuildInfo(writeFileCallback?: WriteFileCallback): EmitResult { + Debug.assert(!outFile(options)); + tracing?.push(tracing.Phase.Emit, "emitBuildInfo", {}, /*separateBeginAndEnd*/ true); + mark("beforeEmit"); + 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(); + mark("afterEmit"); + measure("Emit", "beforeEmit", "afterEmit"); + tracing?.pop(); return emitResult; } @@ -1995,11 +2092,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; } @@ -2014,23 +2111,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, emitOnlyDtsFiles?: boolean, 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, emitOnlyDtsFiles?: boolean, transformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult { + tracing?.push(tracing.Phase.Emit, "emit", { path: sourceFile?.path }, /*separateBeginAndEnd*/ true); const result = runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles, transformers, forceDtsEmit)); - ts.tracing?.pop(); + tracing?.pop(); return result; } @@ -2038,7 +2135,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, emitOnlyDtsFiles?: boolean, customTransformers?: ts.CustomTransformers, forceDtsEmit?: boolean): ts.EmitResult { + function emitWorker(program: Program, sourceFile: SourceFile | undefined, writeFileCallback: WriteFileCallback | undefined, cancellationToken: CancellationToken | undefined, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult { if (!forceDtsEmit) { const result = handleNoEmitOptions(program, sourceFile, writeFileCallback, cancellationToken); if (result) return result; @@ -2052,41 +2149,41 @@ 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"); + mark("beforeEmit"); - const emitResult = ts.emitFiles( + const emitResult = emitFiles( emitResolver, getEmitHost(writeFileCallback), sourceFile, - ts.getTransformers(options, customTransformers, emitOnlyDtsFiles), + getTransformers(options, customTransformers, emitOnlyDtsFiles), emitOnlyDtsFiles, /*onlyBuildInfo*/ false, forceDtsEmit ); - ts.performance.mark("afterEmit"); - ts.performance.measure("Emit", "beforeEmit", "afterEmit"); + mark("afterEmit"); + measure("Emit", "beforeEmit", "afterEmit"); 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(); } @@ -2094,27 +2191,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); @@ -2125,10 +2222,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 { @@ -2136,14 +2233,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; } @@ -2153,7 +2250,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!; @@ -2163,51 +2260,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; } @@ -2215,7 +2312,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; @@ -2225,16 +2322,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); }); @@ -2243,15 +2340,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)) { @@ -2270,227 +2367,227 @@ 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.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) { + function walkArray(nodes: NodeArray, parent: Node) { if (parent.decorators === nodes && !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)); + 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.modifiers) { - checkModifiers(parent.modifiers, parent.kind === ts.SyntaxKind.VariableStatement); + checkModifiers(parent.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 (modifier.kind !== ts.SyntaxKind.StaticKeyword) { - 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 (modifier.kind !== SyntaxKind.StaticKeyword) { + 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) { - diagnostics.push(createDiagnosticForNodeArray(nodes, ts.Diagnostics.Parameter_modifiers_can_only_be_used_in_TypeScript_files)); + if (nodes === (parent as ParameterDeclaration).modifiers) { + 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 SyntaxKind.StaticKeyword: + case SyntaxKind.ExportKeyword: + case SyntaxKind.DefaultKeyword: } } } - 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 @@ -2502,7 +2599,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; @@ -2510,72 +2607,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(/*decorators*/ undefined, /*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(/*decorators*/ undefined, /*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 @@ -2584,9 +2681,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)); @@ -2596,40 +2693,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) { @@ -2643,7 +2740,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); @@ -2654,36 +2751,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; } @@ -2692,34 +2789,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; @@ -2730,14 +2827,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; @@ -2747,19 +2844,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 @@ -2768,22 +2865,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): ts.SourceFile { - const redirect: ts.SourceFile = Object.create(redirectTarget); + function createRedirectSourceFile(redirectTarget: SourceFile, unredirected: SourceFile, fileName: string, path: Path, resolvedPath: Path, originalFileName: string): SourceFile { + const redirect: SourceFile = Object.create(redirectTarget); redirect.fileName = fileName; redirect.path = path; redirect.resolvedPath = resolvedPath; @@ -2792,42 +2889,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) { + function getCreateSourceFileOptions(fileName: string, moduleResolutionCache: ModuleResolutionCache | undefined, host: CompilerHost, options: CompilerOptions) { // 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 impliedNodeFormat = getImpliedNodeFormatForFile(toPath(fileName), moduleResolutionCache?.getPackageJsonInfoCache(), host, options); return { - languageVersion: ts.getEmitScriptTarget(options), + languageVersion: getEmitScriptTarget(options), impliedNodeFormat, - setExternalModuleIndicator: ts.getSetExternalModuleIndicator(options) + setExternalModuleIndicator: getSetExternalModuleIndicator(options) }; } - 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); @@ -2838,13 +2935,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); @@ -2864,8 +2961,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); } @@ -2897,11 +2994,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; } @@ -2920,12 +3017,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP const file = host.getSourceFile( fileName, getCreateSourceFileOptions(fileName, moduleResolutionCache, host, options), - 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 ); 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. @@ -2934,14 +3031,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); @@ -2955,7 +3052,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) { @@ -2990,11 +3087,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); @@ -3011,7 +3108,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; } @@ -3021,11 +3118,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()); } /** @@ -3033,7 +3130,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) { @@ -3048,27 +3145,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); } }); @@ -3082,7 +3179,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; } @@ -3090,19 +3187,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; @@ -3113,32 +3210,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_modes_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_modes_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: !!resolveModuleNamesReusingOldState, refKind: reason.kind, refPath: isReferencedFile(reason) ? reason.file : undefined }); + tracing?.push(tracing.Phase.Program, "processTypeReferenceDirective", { directive: typeReferenceDirective, hasResolved: !!resolveModuleNamesReusingOldState, 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 @@ -3166,7 +3263,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] ); } @@ -3183,7 +3280,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) { @@ -3202,29 +3299,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] }); @@ -3236,24 +3333,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; @@ -3274,8 +3371,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); @@ -3285,7 +3382,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, ); } @@ -3301,16 +3398,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; @@ -3321,9 +3418,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) @@ -3334,8 +3431,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) { @@ -3343,27 +3440,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); @@ -3372,62 +3469,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 || ""] ); } @@ -3436,123 +3533,123 @@ 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"); } - const firstNonExternalModuleSourceFile = ts.find(files, f => !ts.isExternalModule(f) && !ts.isSourceFileJS(f) && !f.isDeclarationFile && f.scriptKind !== ts.ScriptKind.JSON); + const firstNonExternalModuleSourceFile = find(files, f => !isExternalModule(f) && !isSourceFileJS(f) && !f.isDeclarationFile && f.scriptKind !== ScriptKind.JSON); if (firstNonExternalModuleSourceFile) { - const span = ts.getErrorSpanForNode(firstNonExternalModuleSourceFile, firstNonExternalModuleSourceFile); - programDiagnostics.add(ts.createFileDiagnostic(firstNonExternalModuleSourceFile, 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(firstNonExternalModuleSourceFile.fileName))); + const span = getErrorSpanForNode(firstNonExternalModuleSourceFile, firstNonExternalModuleSourceFile); + programDiagnostics.add(createFileDiagnostic(firstNonExternalModuleSourceFile, 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(firstNonExternalModuleSourceFile.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"); } } @@ -3567,82 +3664,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); } @@ -3651,25 +3748,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); @@ -3678,39 +3775,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.explainIfFileIsRedirect(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 && explainIfFileIsRedirect(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, @@ -3718,31 +3815,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, @@ -3751,62 +3848,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, @@ -3814,12 +3911,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; @@ -3827,37 +3924,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; } } @@ -3865,15 +3962,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)) { @@ -3881,65 +3978,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; } @@ -3949,15 +4046,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); } @@ -3974,40 +4071,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); @@ -4017,23 +4114,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; @@ -4051,11 +4148,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 @@ -4102,7 +4199,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); @@ -4111,43 +4208,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 }); } @@ -4164,18 +4261,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"), "")}` @@ -4188,20 +4285,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); } @@ -4210,20 +4307,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; @@ -4232,8 +4329,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*/ @@ -4244,21 +4341,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 }; } @@ -4269,33 +4366,33 @@ export function parseConfigHostFromCompilerHostLike(host: CompilerHostLike, dire } /* @internal */ -export function createPrependNodes(projectReferences: readonly ts.ProjectReference[] | undefined, getCommandLine: (ref: ts.ProjectReference, index: number) => ts.ParsedCommandLine | undefined, readFile: (path: string) => string | undefined) { - if (!projectReferences) return ts.emptyArray; - let nodes: ts.InputFiles[] | undefined; +export function createPrependNodes(projectReferences: readonly ProjectReference[] | undefined, getCommandLine: (ref: ProjectReference, index: number) => ParsedCommandLine | undefined, readFile: (path: string) => string | 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.createInputFiles(readFile, jsFilePath!, sourceMapFilePath, declarationFilePath!, declarationMapPath, buildInfoPath); + const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath } = getOutputPathsForBundle(resolvedRefOpts.options, /*forceDtsPaths*/ true); + const node = createInputFiles(readFile, jsFilePath!, sourceMapFilePath, declarationFilePath!, declarationMapPath, buildInfoPath); (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 */ @@ -4304,37 +4401,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`. @@ -4343,15 +4440,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 f9b90d0aba501..5b79bdcbb1de9 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -1,23 +1,52 @@ import * as ts from "./_namespaces/ts"; +import { + arrayToMap, contains, createMultiMap, emptyIterator, endsWith, firstDefinedIterator, GetCanonicalFileName, isString, + length, memoize, removeSuffix, returnTrue, some, startsWith, stringContains, unorderedRemoveItem, +} from "./core"; +import { ESMap, Map, ReadonlyESMap, Set } from "./corePublic"; +import { Debug } from "./debug"; +import { Diagnostics } from "./diagnosticInformationMap.generated"; +import { + CacheWithRedirects, createCacheWithRedirects, createModeAwareCache, createModuleResolutionCache, + createTypeReferenceDirectiveResolutionCache, getEffectiveTypeRoots, isTraceEnabled, loadModuleFromGlobalCache, + ModeAwareCache, ModuleResolutionCache, parseNodeModuleFromPath, pathContainsNodeModules, PerModuleNameCache, trace, +} from "./moduleNameResolver"; +import { + directorySeparator, fileExtensionIs, fileExtensionIsOneOf, getDirectoryPath, getNormalizedAbsolutePath, + getRootLength, isNodeModulesDirectory, isRootedDiskPath, normalizePath, removeTrailingDirectorySeparator, +} from "./path"; +import { getModeForFileReference, getModeForResolutionAtIndex, inferredTypesContainingFile } from "./program"; +import { DirectoryWatcherCallback, FileWatcher, ignoredPaths } from "./sys"; +import { + CharacterCodes, CompilerOptions, Extension, FileReference, HasInvalidatedResolution, MinimalResolutionCacheHost, + ModuleKind, ModuleResolutionHost, PackageId, Path, Program, ResolvedModuleFull, + ResolvedModuleWithFailedLookupLocations, ResolvedProjectReference, ResolvedTypeReferenceDirective, + ResolvedTypeReferenceDirectiveWithFailedLookupLocations, SourceFile, WatchDirectoryFlags, +} from "./types"; +import { + clearMap, closeFileWatcher, extensionIsTS, mutateMap, packageIdToString, resolutionExtensionIsTSOrJson, +} from "./utilities"; +import { isExternalModuleNameRelative } from "./utilitiesPublic"; +import { CachedDirectoryStructureHost, closeFileWatcherOf, isEmittedFileOfProgram } from "./watchUtilities"; /* @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; - createHasInvalidatedResolution(forceAllFilesAsInvalidated?: boolean): ts.HasInvalidatedResolution; + invalidateResolutionOfFile(filePath: Path): void; + removeResolutionsOfFile(filePath: Path): void; + removeResolutionsFromProjectReferenceRedirects(filePath: Path): void; + setFilesWithInvalidatedNonRelativeUnresolvedImports(filesWithUnresolvedImports: ESMap): void; + createHasInvalidatedResolution(forceAllFilesAsInvalidated?: boolean): HasInvalidatedResolution; hasChangedAutomaticTypeDirectiveNames(): boolean; - isFileWithInvalidatedNonRelativeUnresolvedImports(path: ts.Path): boolean; + isFileWithInvalidatedNonRelativeUnresolvedImports(path: Path): boolean; startCachingPerDirectoryResolution(): void; @@ -26,7 +55,7 @@ export interface ResolutionCache { updateTypeRootsWatch(): void; closeTypeRootsWatch(): void; - getModuleResolutionCache(): ts.ModuleResolutionCache; + getModuleResolutionCache(): ModuleResolutionCache; clear(): void; } @@ -36,43 +65,43 @@ 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; +export interface ResolutionCacheHost extends MinimalResolutionCacheHost { + toPath(fileName: string): Path; + getCanonicalFileName: GetCanonicalFileName; + getCompilationSettings(): CompilerOptions; + watchDirectoryOfFailedLookupLocation(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): 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 DirectoryWatchesOfFailedLookup { /** watcher for the directory of failed lookup */ - watcher: ts.FileWatcher; + watcher: FileWatcher; /** ref count keeping this directory watch alive */ refCount: number; /** is the directory watched being non recursive */ @@ -81,18 +110,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; } @@ -104,25 +133,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 canWatchDirectory(dirPath: ts.Path) { - const rootLength = ts.getRootLength(dirPath); +export function canWatchDirectory(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; @@ -138,7 +167,7 @@ export function canWatchDirectory(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; @@ -152,29 +181,29 @@ 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 resolvedFileToResolution = ts.createMultiMap(); + const resolvedFileToResolution = createMultiMap(); let hasChangedAutomaticTypeDirectiveNames = false; - let failedLookupChecks: ts.Path[] | undefined; - let startsWithPathChecks: ts.Set | undefined; - let isInDirectoryChecks: ts.Path[] | undefined; + let failedLookupChecks: Path[] | undefined; + let startsWithPathChecks: Set | undefined; + let isInDirectoryChecks: Path[] | 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, @@ -182,9 +211,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, @@ -198,16 +227,16 @@ 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 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 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, @@ -241,15 +270,15 @@ 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); + clearMap(directoryWatchesOfFailedLookups, closeFileWatcherOf); customFailedLookupPaths.clear(); nonRelativeExternalModuleResolutions.clear(); closeTypeRootsWatch(); @@ -276,7 +305,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD return collected; } - function isFileWithInvalidatedNonRelativeUnresolvedImports(path: ts.Path): boolean { + function isFileWithInvalidatedNonRelativeUnresolvedImports(path: Path): boolean { if (!filesWithInvalidatedNonRelativeUnresolvedImports) { return false; } @@ -286,13 +315,13 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD return !!value && !!value.length; } - function createHasInvalidatedResolution(forceAllFilesAsInvalidated?: boolean): ts.HasInvalidatedResolution { + function createHasInvalidatedResolution(forceAllFilesAsInvalidated?: boolean): HasInvalidatedResolution { // Ensure pending resolutions are applied invalidateResolutionsOfFailedLookupLocations(); if (forceAllFilesAsInvalidated) { // Any file asked would have invalidated resolution filesWithInvalidatedResolutions = undefined; - return ts.returnTrue; + return returnTrue; } const collected = filesWithInvalidatedResolutions; filesWithInvalidatedResolutions = undefined; @@ -319,7 +348,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) { @@ -328,11 +357,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 } = ts.loadModuleFromGlobalCache( - ts.Debug.checkDefined(resolutionHost.globalCacheResolutionModuleName)(moduleName), + const { resolvedModule, failedLookupLocations } = loadModuleFromGlobalCache( + Debug.checkDefined(resolutionHost.globalCacheResolutionModuleName)(moduleName), resolutionHost.projectName, compilerOptions, host, @@ -351,23 +380,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, @@ -376,12 +405,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)[] = []; @@ -395,49 +424,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) ); } } @@ -462,36 +491,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); } @@ -518,8 +547,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, @@ -532,8 +561,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, @@ -541,35 +570,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 { @@ -583,29 +612,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 canWatchDirectory(ts.getDirectoryPath(dirPath)) ? { dir, dirPath } : undefined; + if (isNodeModulesDirectory(dirPath)) { + return canWatchDirectory(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; } @@ -613,31 +642,31 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD subDirectoryPath = dirPath; subDirectory = dir; dirPath = parentPath; - dir = ts.getDirectoryPath(dir); + dir = getDirectoryPath(dir); } } return canWatchDirectory(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 { @@ -652,7 +681,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } function watchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) { - ts.Debug.assert(!!resolution.refCount); + Debug.assert(!!resolution.refCount); const { failedLookupLocations } = resolution; if (!failedLookupLocations.length) return; @@ -671,7 +700,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 { @@ -693,10 +722,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 { @@ -706,10 +735,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; @@ -719,7 +748,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD resolvedFileToResolution.remove(resolutionHost.toPath(resolved.resolvedFileName), resolution); } - if (!ts.unorderedRemoveItem(resolutionsWithFailedLookups, resolution)) { + if (!unorderedRemoveItem(resolutionsWithFailedLookups, resolution)) { // If not watching failed lookups, it wont be there in resolutionsWithFailedLookups return; } @@ -737,7 +766,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); } } @@ -761,7 +790,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) { @@ -770,12 +799,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 @@ -786,8 +815,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; @@ -800,7 +829,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); } @@ -811,32 +840,32 @@ 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 || (filesWithInvalidatedResolutions = new ts.Set())).add(containingFilePath); + for (const containingFilePath of Debug.checkDefined(resolution.files)) { + (filesWithInvalidatedResolutions || (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 @@ -855,19 +884,19 @@ 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 ||= []).push(fileOrDirectoryPath); - (startsWithPathChecks ||= new ts.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 @@ -876,8 +905,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD // 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(); @@ -898,17 +927,17 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD function canInvalidateFailedLookupResolution(resolution: ResolutionWithFailedLookupLocations) { return resolution.failedLookupLocations.some(location => { const locationPath = resolutionHost.toPath(location); - return ts.contains(failedLookupChecks, locationPath) || - ts.firstDefinedIterator(startsWithPathChecks?.keys() || ts.emptyIterator, fileOrDirectoryPath => ts.startsWith(locationPath, fileOrDirectoryPath) ? true : undefined) || + return contains(failedLookupChecks, locationPath) || + firstDefinedIterator(startsWithPathChecks?.keys() || emptyIterator, fileOrDirectoryPath => startsWith(locationPath, fileOrDirectoryPath) ? true : undefined) || isInDirectoryChecks?.some(fileOrDirectoryPath => isInDirectoryPath(fileOrDirectoryPath, locationPath)); }); } 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; } @@ -916,7 +945,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); @@ -937,7 +966,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD if (dirPath) { scheduleInvalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath, dirPath === fileOrDirectoryPath); } - }, ts.WatchDirectoryFlags.Recursive); + }, WatchDirectoryFlags.Recursive); } /** @@ -955,14 +984,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 } ); } @@ -977,7 +1006,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 || canWatchDirectory(dirPath); } @@ -985,7 +1014,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 df41276987287..3b553b94748ae 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -1,20 +1,29 @@ -import * as ts from "./_namespaces/ts"; - -export type ErrorCallback = (message: ts.DiagnosticMessage, length: number) => void; +import { append, arraysEqual, binarySearch, compareValues, getEntries, identity, trimStringStart } from "./core"; +import { ESMap, Map, MapLike } from "./corePublic"; +import { Debug } from "./debug"; +import { Diagnostics } from "./diagnosticInformationMap.generated"; +import { + CharacterCodes, CommentDirective, CommentDirectiveType, CommentKind, CommentRange, DiagnosticMessage, + JSDocSyntaxKind, JsxTokenSyntaxKind, KeywordSyntaxKind, LanguageVariant, LineAndCharacter, ScriptTarget, + SourceFileLike, SyntaxKind, TokenFlags, +} from "./types"; +import { parsePseudoBigInt, positionIsSynthesized } from "./utilities"; + +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 +37,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 +66,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,154 +88,154 @@ export interface Scanner { } /** @internal */ -export const textToKeywordObj: ts.MapLike = { - abstract: ts.SyntaxKind.AbstractKeyword, - 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, - 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, + 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, + 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, })); /* @@ -326,21 +335,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; @@ -349,12 +358,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); } @@ -367,17 +376,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; } @@ -388,10 +397,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); @@ -405,7 +414,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"}`); } } @@ -417,21 +426,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, @@ -444,7 +453,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 @@ -454,13 +463,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); @@ -471,7 +480,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); } @@ -483,18 +492,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 { @@ -509,18 +518,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 { @@ -529,39 +538,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; } @@ -570,29 +579,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))) { @@ -603,10 +612,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; } @@ -617,10 +626,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; @@ -628,7 +637,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; @@ -636,7 +645,7 @@ export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boole } break; - case ts.CharacterCodes.asterisk: + case CharacterCodes.asterisk: if (canConsumeStar) { pos++; canConsumeStar = false; @@ -645,7 +654,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; } @@ -660,7 +669,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))) { @@ -673,34 +682,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; } @@ -716,7 +725,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); } @@ -747,10 +756,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; @@ -765,12 +774,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; @@ -782,20 +791,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; @@ -806,7 +815,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; } @@ -834,7 +843,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; } @@ -852,27 +861,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 = []; } @@ -881,11 +890,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); } @@ -897,22 +906,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; @@ -928,9 +937,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, @@ -951,11 +960,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); @@ -967,15 +976,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, @@ -1006,7 +1015,7 @@ export function createScanner(languageVersion: ts.ScriptTarget, scanRange, }; - if (ts.Debug.isDebugging) { + if (Debug.isDebugging) { Object.defineProperty(scanner, "__debugShowCurrentPositionInText", { get: () => { const text = scanner.getText(); @@ -1017,9 +1026,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; @@ -1035,18 +1044,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; @@ -1060,30 +1069,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; @@ -1091,7 +1100,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; @@ -1104,10 +1113,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 }; } @@ -1129,14 +1138,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; } } @@ -1172,27 +1181,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; } @@ -1203,8 +1212,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); } @@ -1217,8 +1226,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); @@ -1227,7 +1236,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; @@ -1235,8 +1244,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++; @@ -1248,43 +1257,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; @@ -1293,11 +1302,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++; } @@ -1309,7 +1318,7 @@ export function createScanner(languageVersion: ts.ScriptTarget, pos++; } - ts.Debug.assert(resultingToken !== undefined); + Debug.assert(resultingToken !== undefined); tokenValue = contents; return resultingToken; @@ -1319,54 +1328,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); } @@ -1376,31 +1385,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); } } @@ -1409,14 +1418,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); @@ -1430,7 +1439,7 @@ export function createScanner(languageVersion: ts.ScriptTarget, return String.fromCharCode(escapedValue); } else { - error(ts.Diagnostics.Hexadecimal_digit_expected); + error(Diagnostics.Hexadecimal_digit_expected); return ""; } } @@ -1442,24 +1451,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; } @@ -1473,7 +1482,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); @@ -1485,7 +1494,7 @@ export function createScanner(languageVersion: ts.ScriptTarget, function peekExtendedUnicodeEscape(): number { - if (languageVersion >= ts.ScriptTarget.ES2015 && codePointAt(text, pos + 1) === ts.CharacterCodes.u && codePointAt(text, pos + 2) === ts.CharacterCodes.openBrace) { + if (languageVersion >= ScriptTarget.ES2015 && codePointAt(text, pos + 1) === CharacterCodes.u && codePointAt(text, pos + 2) === CharacterCodes.openBrace) { const start = pos; pos += 3; const escapedValueString = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ false); @@ -1504,11 +1513,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; @@ -1517,7 +1526,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 @@ -1532,19 +1541,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 { @@ -1556,120 +1565,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; @@ -1678,98 +1687,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) { @@ -1790,14 +1799,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; @@ -1805,7 +1814,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; @@ -1815,14 +1824,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) { @@ -1830,205 +1839,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(); } @@ -2036,19 +2045,19 @@ 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; } if (isIdentifierStart(codePointAt(text, pos + 1), languageVersion)) { @@ -2057,9 +2066,9 @@ export function createScanner(languageVersion: ts.ScriptTarget, } else { tokenValue = String.fromCharCode(codePointAt(text, pos)); - 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) { @@ -2070,24 +2079,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; } @@ -2095,50 +2104,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; @@ -2146,15 +2155,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; } @@ -2163,19 +2172,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++; @@ -2186,23 +2195,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 }, @@ -2219,10 +2228,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; @@ -2231,64 +2240,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. @@ -2299,21 +2308,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. @@ -2339,12 +2348,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 @@ -2353,16 +2362,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; @@ -2381,83 +2390,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(); } @@ -2465,25 +2474,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; } } @@ -2560,22 +2569,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) { @@ -2614,7 +2623,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 78371d20fc53f..409a42593b6e4 100644 --- a/src/compiler/semver.ts +++ b/src/compiler/semver.ts @@ -1,4 +1,6 @@ -import * as ts from "./_namespaces/ts"; +import { compareStringsCaseSensitive, compareValues, emptyArray, map, some, trimString } from "./core"; +import { Comparison } from "./corePublic"; +import { Debug } from "./debug"; // 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 @@ -43,20 +45,20 @@ export class Version { constructor(major: number, minor?: number, patch?: number, prerelease?: string, build?: string); constructor(major: number | string, minor = 0, patch = 0, prerelease = "", build = "") { 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"); - ts.Debug.assert(!prerelease || prereleaseRegExp.test(prerelease), "Invalid argument: prerelease"); - ts.Debug.assert(!build || buildRegExp.test(build), "Invalid argument: build"); + Debug.assert(major >= 0, "Invalid argument: major"); + Debug.assert(minor >= 0, "Invalid argument: minor"); + Debug.assert(patch >= 0, "Invalid argument: patch"); + Debug.assert(!prerelease || prereleaseRegExp.test(prerelease), "Invalid argument: prerelease"); + Debug.assert(!build || buildRegExp.test(build), "Invalid argument: build"); this.major = major; this.minor = minor; this.patch = patch; - this.prerelease = prerelease ? prerelease.split(".") : ts.emptyArray; - this.build = build ? build.split(".") : ts.emptyArray; + this.prerelease = prerelease ? prerelease.split(".") : emptyArray; + this.build = build ? build.split(".") : emptyArray; } static tryParse(text: string) { @@ -80,11 +82,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); } @@ -93,14 +95,14 @@ 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); } } 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; } } @@ -125,9 +127,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 @@ -144,17 +146,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; } } @@ -162,7 +164,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 */ @@ -173,7 +175,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) { @@ -236,17 +238,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; } } @@ -376,16 +378,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 ade8044c0f493..2229e98f014dc 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -1,4 +1,16 @@ -import * as ts from "./_namespaces/ts"; +import { + arrayFrom, binarySearchKey, compareValues, emptyArray, every, identity, isArray, isString, some, sortAndDeduplicate, + trimStringEnd, +} from "./core"; +import { ESMap, Iterator, Map, SortedReadonlyArray } from "./corePublic"; +import { Debug } from "./debug"; +import { combinePaths, getDirectoryPath, getNormalizedAbsolutePath, getRelativePathToDirectoryOrUrl } from "./path"; +import { createTimer, nullTimer } from "./performance"; +import { getPositionOfLineAndCharacter } from "./scanner"; +import { + CharacterCodes, DocumentPosition, DocumentPositionMapper, DocumentPositionMapperHost, EmitHost, LineAndCharacter, + RawSourceMap, SourceMapGenerator, +} from "./types"; /* @internal */ export interface SourceMapGeneratorOptions { @@ -6,19 +18,19 @@ 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; + ? createTimer("Source Map", "beforeSourcemap", "afterSourcemap") + : nullTimer; // 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 +66,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 +99,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 +126,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 +156,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 +187,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 +245,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 +253,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 +295,7 @@ export function createSourceMapGenerator(host: ts.EmitHost, file: string, source } } - function toJSON(): ts.RawSourceMap { + function toJSON(): RawSourceMap { commitPendingMapping(); flushMappingBuffer(); return { @@ -351,7 +363,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)) { @@ -366,16 +378,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 */ @@ -395,7 +407,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; @@ -437,7 +449,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; @@ -445,7 +457,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; @@ -527,8 +539,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 { @@ -585,20 +597,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; } @@ -630,12 +642,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) { @@ -647,16 +659,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, @@ -665,7 +677,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; @@ -673,7 +685,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 { @@ -688,12 +700,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; @@ -711,7 +723,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]; } @@ -722,19 +734,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; @@ -748,11 +760,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; @@ -768,7 +780,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 59187e7261691..3fb3e0b3fd891 100644 --- a/src/compiler/symbolWalker.ts +++ b/src/compiler/symbolWalker.ts @@ -1,48 +1,54 @@ -import * as ts from "./_namespaces/ts"; +import { getSymbolId } from "./checker"; +import { clear, forEach, getOwnValues } from "./core"; +import { + EntityNameOrEntityNameExpression, Identifier, IndexedAccessType, IndexType, InterfaceType, MappedType, Node, + ObjectFlags, ObjectType, ResolvedType, Signature, Symbol, SymbolWalker, SyntaxKind, Type, TypeFlags, TypeParameter, + TypePredicate, TypeQueryNode, TypeReference, UnionOrIntersectionType, +} from "./types"; /* @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; } @@ -58,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); @@ -132,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); @@ -156,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; } @@ -173,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 52d5a5537c27c..a8628245acde8 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -1,4 +1,24 @@ import * as ts from "./_namespaces/ts"; +import { matchesExclude } from "./commandLineParser"; +import { + AssertionLevel, contains, createGetCanonicalFileName, createMultiMap, emptyArray, enumerateInsertsAndDeletes, + forEach, getStringComparer, isArray, isString, mapDefined, memoize, noop, some, startsWith, stringContains, + unorderedRemoveItem, +} from "./core"; +import { Comparison, ESMap, Map } from "./corePublic"; +import { Debug } from "./debug"; +import { resolveJSModule } from "./moduleNameResolver"; +import { + combinePaths, containsPath, directorySeparator, getDirectoryPath, getNormalizedAbsolutePath, + getRelativePathToDirectoryOrUrl, getRootLength, normalizePath, normalizeSlashes, +} from "./path"; +import { perfLogger } from "./perfLogger"; +import { timestamp } from "./performanceCore"; +import { Path, PollingWatchKind, RequireResult, WatchDirectoryKind, WatchFileKind, WatchOptions } from "./types"; +import { + closeFileWatcher, emptyFileSystemEntries, FileSystemEntries, matchFiles, writeFileEnsuringDirectories, +} from "./utilities"; +import { closeFileWatcherOf, getFallbackOptions } from "./watchUtilities"; declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any; declare function clearTimeout(handle: any): void; @@ -51,9 +71,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 @@ -227,7 +247,7 @@ export 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 } }; @@ -248,7 +268,7 @@ export function createDynamicPriorityPollingWatchFile(host: { scheduleNextPoll(queue.pollingInterval); } else { - ts.Debug.assert(queue.pollIndex === 0); + Debug.assert(queue.pollIndex === 0); queue.pollScheduled = false; } } @@ -335,17 +355,17 @@ export 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: () => { @@ -361,14 +381,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) => { // 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) { @@ -407,7 +427,7 @@ function createFixedChunkSizePollingWatchFile(host: { return { close: () => { file.isClosed = true; - ts.unorderedRemoveItem(watchedFiles, file); + unorderedRemoveItem(watchedFiles, file); } }; } @@ -433,9 +453,9 @@ export function createSingleFileWatcherPerName( watcher: FileWatcher; refCount: number; } - const cache = new ts.Map(); - const callbacksCache = ts.createMultiMap(); - const toCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); + const cache = new Map(); + const callbacksCache = createMultiMap(); + const toCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames); return (fileName, callback, pollingInterval, options) => { const path = toCanonicalFileName(fileName); @@ -447,7 +467,7 @@ export function createSingleFileWatcherPerName( cache.set(path, { watcher: watchFile( fileName, - (fileName, eventKind) => ts.forEach( + (fileName, eventKind) => forEach( callbacksCache.get(path), cb => cb(fileName, eventKind) ), @@ -461,12 +481,12 @@ export function createSingleFileWatcherPerName( return { close: () => { - const watcher = ts.Debug.checkDefined(cache.get(path)); + const watcher = Debug.checkDefined(cache.get(path)); callbacksCache.remove(path, callback); watcher.refCount--; if (watcher.refCount) return; cache.delete(path); - ts.closeFileWatcherOf(watcher); + closeFileWatcherOf(watcher); } }; }; @@ -500,7 +520,7 @@ export function getFileWatcherEventKind(oldTime: number, newTime: number) { /*@internal*/ export const ignoredPaths = ["/node_modules/.", "/.git", "/.#"]; -let curSysLog: (s: string) => 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) { @@ -550,13 +570,13 @@ export 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) : @@ -565,8 +585,8 @@ export 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++; @@ -588,7 +608,7 @@ export function createDirectoryWatcherSupportingRecursive({ } }, /*recursive*/ false, options), refCount: 1, - childWatches: ts.emptyArray + childWatches: emptyArray }; cache.set(dirPath, directoryWatcher); updateChildWatches(dirName, dirPath, options); @@ -602,26 +622,26 @@ export 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 { @@ -630,7 +650,7 @@ export 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); @@ -652,7 +672,7 @@ export 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 && directoryExists(dirName)) { @@ -666,7 +686,7 @@ export 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); @@ -684,12 +704,12 @@ export 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 @@ -698,12 +718,12 @@ export 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 { @@ -713,39 +733,39 @@ export 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( - directoryExists(parentDir) ? ts.mapDefined(getAccessibleSortedChildDirectories(parentDir), child => { - const childFullName = ts.getNormalizedAbsolutePath(child, parentDir); + const hasChanges = enumerateInsertsAndDeletes( + directoryExists(parentDir) ? 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; /** @@ -764,22 +784,22 @@ export 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) => 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 const enum FileSystemEntryKind { @@ -810,20 +830,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 { @@ -833,7 +853,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); } @@ -893,34 +913,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, fileExists), /*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); } } @@ -932,38 +952,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 do not use fixed polling interval - { watchFile: defaultWatchFileKind?.() || ts.WatchFileKind.FixedPollingInterval }; + { watchFile: defaultWatchFileKind?.() || WatchFileKind.FixedPollingInterval }; } } 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, @@ -973,7 +993,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, @@ -981,7 +1001,7 @@ export function createSystemWatchFunctions({ createFsWatchCallbackForDirectoryWatcherCallback(directoryName, callback, options, useCaseSensitiveFileNames, getCurrentDirectory), recursive, PollingInterval.Medium, - ts.getFallbackOptions(options) + getFallbackOptions(options) ); } @@ -1000,59 +1020,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 @@ -1069,7 +1089,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, @@ -1176,8 +1196,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; @@ -1211,8 +1231,8 @@ 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*/ defaultWatchFileKind?(): ts.WatchFileKind | undefined; + /*@internal*/ require?(baseDir: string, moduleName: string): RequireResult; + /*@internal*/ defaultWatchFileKind?(): WatchFileKind | undefined; // For testing /*@internal*/ now?(): Date; @@ -1289,7 +1309,7 @@ export let sys: System = (() => { const realpathSync = _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({ pollingWatchFile: createSingleFileWatcherPerName(fsWatchFileWorker, useCaseSensitiveFileNames), getModifiedTime, @@ -1380,9 +1400,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(); @@ -1406,7 +1426,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) { @@ -1459,15 +1479,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)!; @@ -1575,14 +1595,14 @@ export let sys: System = (() => { callback: FsWatchCallback, recursive: boolean, fallbackPollingInterval: PollingInterval, - fallbackOptions: ts.WatchOptions | undefined + fallbackOptions: WatchOptions | undefined ): FileWatcher { let options: any; let lastDirectoryPartWithDirectorySeparator: string | undefined; let lastDirectoryPart: string | undefined; if (isLinuxOrMacOs) { - lastDirectoryPartWithDirectorySeparator = fileOrDirectory.substr(fileOrDirectory.lastIndexOf(ts.directorySeparator)); - lastDirectoryPart = lastDirectoryPartWithDirectorySeparator.slice(ts.directorySeparator.length); + lastDirectoryPartWithDirectorySeparator = fileOrDirectory.substr(fileOrDirectory.lastIndexOf(directorySeparator)); + lastDirectoryPart = lastDirectoryPartWithDirectorySeparator.slice(directorySeparator.length); } /** Watcher for the file system entry depending on whether it is missing or present */ let watcher = !fileSystemEntryExists(fileOrDirectory, entryKind) ? @@ -1733,14 +1753,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; @@ -1759,8 +1779,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[] = []; @@ -1777,7 +1797,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); @@ -1805,12 +1825,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 { @@ -1913,10 +1933,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 76594b0e8992b..a08e28251039a 100644 --- a/src/compiler/tracing.ts +++ b/src/compiler/tracing.ts @@ -1,4 +1,15 @@ -import * as ts from "./_namespaces/ts"; +import { Map } from "./corePublic"; +import { Debug } from "./debug"; +import { combinePaths } from "./path"; +import { mark, measure } from "./performance"; +import { timestamp } from "./performanceCore"; +import { getLineAndCharacterOfPosition } from "./scanner"; +import { + ConditionalType, EvolvingArrayType, IndexedAccessType, IndexType, IntersectionType, LineAndCharacter, Node, + ObjectFlags, Path, ReverseMappedType, SubstitutionType, Type, TypeFlags, TypeReference, UnionType, +} from "./types"; +import { getSourceFileOfNode } from "./utilities"; +import { unescapeLeadingUnderscores } from "./utilitiesPublic"; /* Tracing events for the compiler. */ @@ -19,7 +30,7 @@ namespace tracingEnabled { // eslint-disable-line 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 +42,7 @@ namespace tracingEnabled { // eslint-disable-line 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 +57,7 @@ namespace tracingEnabled { // eslint-disable-line 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 +69,8 @@ namespace tracingEnabled { // eslint-disable-line 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 +82,7 @@ namespace tracingEnabled { // eslint-disable-line 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 +93,8 @@ namespace tracingEnabled { // eslint-disable-line 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 +110,7 @@ namespace tracingEnabled { // eslint-disable-line 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 +142,15 @@ namespace tracingEnabled { // eslint-disable-line 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() { - ts.Debug.assert(eventStack.length > 0); - writeStackEvent(eventStack.length - 1, 1000 * ts.timestamp()); + Debug.assert(eventStack.length > 0); + writeStackEvent(eventStack.length - 1, 1000 * timestamp()); 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); } @@ -159,31 +170,31 @@ namespace tracingEnabled { // eslint-disable-line 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; - ts.performance.mark("beginTracing"); + mark("beginTracing"); fs.writeSync(traceFd, `,\n{"pid":1,"tid":1,"ph":"${eventType}","cat":"${phase}","ts":${time},"name":"${name}"`); if (extras) fs.writeSync(traceFd, `,${extras}`); if (args) fs.writeSync(traceFd, `,"args":${JSON.stringify(args)}`); fs.writeSync(traceFd, `}`); - ts.performance.mark("endTracing"); - ts.performance.measure("Tracing", "beginTracing", "endTracing"); + mark("endTracing"); + 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, @@ -191,13 +202,13 @@ namespace tracingEnabled { // eslint-disable-line one-namespace-per-file } } - function dumpTypes(types: readonly ts.Type[]) { - ts.performance.mark("beginDumpTypes"); + function dumpTypes(types: readonly Type[]) { + 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, "["); @@ -210,7 +221,7 @@ namespace tracingEnabled { // eslint-disable-line 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); } @@ -220,8 +231,8 @@ namespace tracingEnabled { // eslint-disable-line 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, @@ -229,8 +240,8 @@ namespace tracingEnabled { // eslint-disable-line 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), @@ -239,8 +250,8 @@ namespace tracingEnabled { // eslint-disable-line 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, @@ -250,8 +261,8 @@ namespace tracingEnabled { // eslint-disable-line 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, substituteType: substitutionType.substitute?.id, @@ -259,8 +270,8 @@ namespace tracingEnabled { // eslint-disable-line 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, @@ -269,8 +280,8 @@ namespace tracingEnabled { // eslint-disable-line 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, @@ -292,13 +303,13 @@ namespace tracingEnabled { // eslint-disable-line 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, @@ -307,7 +318,7 @@ namespace tracingEnabled { // eslint-disable-line 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, }; @@ -321,8 +332,8 @@ namespace tracingEnabled { // eslint-disable-line one-namespace-per-file fs.closeSync(typesFd); - ts.performance.mark("endDumpTypes"); - ts.performance.measure("Dump types", "beginDumpTypes", "endDumpTypes"); + mark("endDumpTypes"); + measure("Dump types", "beginDumpTypes", "endDumpTypes"); } export function dumpLegend() { @@ -348,5 +359,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 5e6585354e823..ae563019cdd5b 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -1,19 +1,55 @@ -import * as ts from "./_namespaces/ts"; - -function getModuleTransformer(moduleKind: ts.ModuleKind): ts.TransformerFactory { +import { addRange, append, emptyArray, map, memoize, noop, notImplemented, returnUndefined, some } from "./core"; +import { Debug } from "./debug"; +import { createEmitHelperFactory } from "./factory/emitHelpers"; +import { disposeEmitNodes, setEmitFlags } from "./factory/emitNode"; +import { factory } from "./factory/nodeFactory"; +import { isBundle, isSourceFile } from "./factory/nodeTests"; +import { mark, measure } from "./performance"; +import { tracing } from "./tracing"; +import { transformClassFields } from "./transformers/classFields"; +import { transformDeclarations } from "./transformers/declarations"; +import { transformES2015 } from "./transformers/es2015"; +import { transformES2016 } from "./transformers/es2016"; +import { transformES2017 } from "./transformers/es2017"; +import { transformES2018 } from "./transformers/es2018"; +import { transformES2019 } from "./transformers/es2019"; +import { transformES2020 } from "./transformers/es2020"; +import { transformES2021 } from "./transformers/es2021"; +import { transformES5 } from "./transformers/es5"; +import { transformESNext } from "./transformers/esnext"; +import { transformGenerators } from "./transformers/generators"; +import { transformJsx } from "./transformers/jsx"; +import { transformECMAScriptModule } from "./transformers/module/esnextAnd2015"; +import { transformModule } from "./transformers/module/module"; +import { transformNodeModule } from "./transformers/module/node"; +import { transformSystemModule } from "./transformers/module/system"; +import { transformTypeScript } from "./transformers/ts"; +import { chainBundle } from "./transformers/utilities"; +import { + Bundle, CompilerOptions, CustomTransformer, CustomTransformerFactory, CustomTransformers, DiagnosticWithLocation, + EmitFlags, EmitHelper, EmitHint, EmitHost, EmitResolver, EmitTransformers, FunctionDeclaration, Identifier, + LexicalEnvironmentFlags, ModuleKind, Node, NodeFactory, NodeFlags, ScriptTarget, SourceFile, Statement, SyntaxKind, + TransformationContext, TransformationResult, Transformer, TransformerFactory, VariableDeclaration, +} from "./types"; +import { + getEmitFlags, getEmitModuleKind, getEmitScriptTarget, getJSXTransformEnabled, getSourceFileOfNode, +} from "./utilities"; +import { getParseTreeNode } from "./utilitiesPublic"; + +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,95 +66,95 @@ 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, emitOnlyDtsFiles?: boolean): ts.EmitTransformers { +export function getTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnlyDtsFiles?: boolean): EmitTransformers { return { scriptTransformers: getScriptTransformers(compilerOptions, customTransformers, emitOnlyDtsFiles), declarationTransformers: getDeclarationTransformers(customTransformers), }; } -function getScriptTransformers(compilerOptions: ts.CompilerOptions, customTransformers?: ts.CustomTransformers, emitOnlyDtsFiles?: boolean) { - if (emitOnlyDtsFiles) return ts.emptyArray; +function getScriptTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnlyDtsFiles?: boolean) { + if (emitOnlyDtsFiles) 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.transformClassFields); + transformers.push(transformTypeScript); + 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" @@ -127,21 +163,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); } @@ -156,35 +192,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, @@ -205,14 +241,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) { @@ -222,10 +258,10 @@ 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"); + mark("beforeTransform"); // Chain together and initialize each transformer. const transformersWithContext = transformers.map(t => t(context)); @@ -242,16 +278,16 @@ 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. state = TransformationState.Completed; - ts.performance.mark("afterTransform"); - ts.performance.measure("transformTime", "beforeTransform", "afterTransform"); + mark("afterTransform"); + measure("transformTime", "beforeTransform", "afterTransform"); return { transformed, @@ -263,23 +299,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; } /** @@ -289,16 +325,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; } @@ -306,9 +342,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; } /** @@ -318,8 +354,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) @@ -335,28 +371,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]; } @@ -368,10 +404,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]; } @@ -385,9 +421,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 @@ -401,22 +437,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; } @@ -424,12 +460,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) { @@ -443,7 +479,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]; @@ -478,13 +514,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; } @@ -492,8 +528,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!; @@ -503,15 +539,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; @@ -523,26 +559,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; @@ -552,7 +588,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. @@ -571,31 +607,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 714818e23adbf..a5349c9425d75 100644 --- a/src/compiler/transformers/classFields.ts +++ b/src/compiler/transformers/classFields.ts @@ -1,4 +1,56 @@ -import * as ts from "../_namespaces/ts"; +import { addRange, compact, filter, forEach, map, some } from "../core"; +import { Map } from "../corePublic"; +import { Debug } from "../debug"; +import { + addEmitFlags, addEmitHelpers, setCommentRange, setEmitFlags, setSourceMapRange, setSyntheticLeadingComments, + setSyntheticTrailingComments, +} from "../factory/emitNode"; +import { factory, setOriginalNode } from "../factory/nodeFactory"; +import { + isArrayLiteralExpression, isArrowFunction, isClassDeclaration, isClassStaticBlockDeclaration, + isComputedPropertyName, isConstructorDeclaration, isDecorator, isElementAccessExpression, isGetAccessorDeclaration, + isHeritageClause, isIdentifier, isMethodDeclaration, isPrefixUnaryExpression, isPrivateIdentifier, + isPropertyAccessExpression, isPropertyAssignment, isPropertyDeclaration, isSetAccessorDeclaration, + isShorthandPropertyAssignment, isSpreadAssignment, isSpreadElement, isStaticModifier, +} from "../factory/nodeTests"; +import { + createMemberAccessForPropertyName, expandPreOrPostfixIncrementOrDecrementExpression, + getInitializerOfBindingOrAssignmentElement, getTargetOfBindingOrAssignmentElement, skipOuterExpressions, + startOnNewLine, +} from "../factory/utilities"; +import { setTextRange } from "../factory/utilitiesPublic"; +import { + AccessorDeclaration, AssignmentOperator, AssignmentPattern, BinaryExpression, BindingOrAssignmentElement, + CallExpression, ClassDeclaration, ClassElement, ClassExpression, ClassLikeDeclaration, ClassStaticBlockDeclaration, + ComputedPropertyName, ConstructorDeclaration, ElementAccessExpression, EmitFlags, EmitHint, Expression, + ExpressionStatement, ExpressionWithTypeArguments, ForStatement, GeneratedIdentifier, GeneratedIdentifierFlags, + Identifier, LeftHandSideExpression, MethodDeclaration, ModifierFlags, Node, NodeCheckFlags, + ObjectLiteralElementLike, PostfixUnaryExpression, PrefixUnaryExpression, PrivateClassElementDeclaration, + PrivateIdentifier, PrivateIdentifierPropertyAccessExpression, PropertyAccessExpression, PropertyDeclaration, + PropertyName, ScriptTarget, SourceFile, Statement, SuperProperty, SyntaxKind, TaggedTemplateExpression, + ThisExpression, TransformationContext, TransformFlags, UnderscoreEscapedMap, VariableStatement, VisitResult, +} from "../types"; +import { + classOrConstructorParameterIsDecorated, getEffectiveBaseTypeNode, getEmitFlags, getEmitScriptTarget, + getFirstConstructorWithBody, getTextOfPropertyName, getUseDefineForClassFields, hasStaticModifier, + hasSyntacticModifier, isAssignmentExpression, isDestructuringAssignment, isStatic, isSuperProperty, isThisProperty, + moveRangePastModifiers, moveRangePos, nodeIsSynthesized, +} from "../utilities"; +import { + getNameOfDeclaration, getOriginalNode, idText, isAccessor, isCallChain, isClassElement, isExpression, + isForInitializer, isGeneratedIdentifier, isGetAccessor, isModifier, isObjectBindingOrAssignmentElement, + isObjectLiteralElementLike, isParameterPropertyDeclaration, isPrivateIdentifierClassElementDeclaration, + isPrivateIdentifierPropertyAccessExpression, isPropertyName, isSetAccessor, isStatement, isTemplateLiteral, + skipPartiallyEmittedExpressions, unescapeLeadingUnderscores, +} from "../utilitiesPublic"; +import { + visitEachChild, visitFunctionBody, visitIterationBody, visitNode, visitNodes, visitParameterList, +} from "../visitorPublic"; +import { + chainBundle, findSuperStatementIndex, getNonAssignmentOperatorForCompoundAssignment, getOriginalNodeId, + getProperties, getStaticPropertiesAndClassStaticBlock, isCompoundAssignment, isInitializedProperty, + isNonStaticMethodOrAccessorWithPrivateName, isSimpleCopiableExpression, isSimpleInlineableExpression, +} from "./utilities"; const enum ClassPropertySubstitutionFlags { /** @@ -25,7 +77,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 */ @@ -41,18 +93,18 @@ 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 { kind: PrivateIdentifierKind.Method; /** * Identifier for a variable that will contain the private method implementation. */ - methodName: ts.Identifier; + methodName: Identifier; } interface PrivateIdentifierInstanceFieldInfo extends PrivateIdentifierInfoBase { kind: PrivateIdentifierKind.Field; @@ -68,7 +120,7 @@ interface PrivateIdentifierStaticFieldInfo extends PrivateIdentifierInfoBase { /** * Contains the variable that will server as the storage for the field. */ - variableName: ts.Identifier; + variableName: Identifier; } type PrivateIdentifierInfo = @@ -85,11 +137,11 @@ interface PrivateIdentifierEnvironment { /** * 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 } interface ClassLexicalEnvironment { @@ -97,11 +149,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; } @@ -121,7 +173,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, @@ -132,18 +184,18 @@ 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); - const shouldTransformPrivateElementsOrClassStaticBlocks = languageVersion < ts.ScriptTarget.ES2022; + const shouldTransformPrivateElementsOrClassStaticBlocks = languageVersion < ScriptTarget.ES2022; // We need to transform `this` in a static initializer into a reference to the class // when targeting < 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 targeting ES5, ES3 because // the es2015 transformation handles those. - const shouldTransformSuperInStaticInitializers = shouldTransformThisInStaticInitializers && languageVersion >= ts.ScriptTarget.ES2015; + const shouldTransformSuperInStaticInitializers = shouldTransformThisInStaticInitializers && languageVersion >= ScriptTarget.ES2015; const previousOnSubstituteNode = context.onSubstituteNode; context.onSubstituteNode = onSubstituteNode; @@ -152,118 +204,118 @@ 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 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) { const options = context.getCompilerOptions(); if (node.isDeclarationFile - || useDefineForClassFields && ts.getEmitScriptTarget(options) >= ts.ScriptTarget.ES2022) { + || useDefineForClassFields && getEmitScriptTarget(options) >= ScriptTarget.ES2022) { 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 visitorWorker(node: ts.Node, valueIsDiscarded: boolean): ts.VisitResult { - if (node.transformFlags & ts.TransformFlags.ContainsClassFields) { + function visitorWorker(node: Node, valueIsDiscarded: boolean): VisitResult { + if (node.transformFlags & TransformFlags.ContainsClassFields) { switch (node.kind) { - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.ClassDeclaration: - return visitClassLike(node as ts.ClassLikeDeclaration); - 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.ClassStaticBlockDeclaration: - return visitClassStaticBlockDeclaration(node as ts.ClassStaticBlockDeclaration); + case SyntaxKind.ClassExpression: + case SyntaxKind.ClassDeclaration: + return visitClassLike(node as ClassLikeDeclaration); + 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.ClassStaticBlockDeclaration: + return visitClassStaticBlockDeclaration(node as ClassStaticBlockDeclaration); } } - if (node.transformFlags & ts.TransformFlags.ContainsClassFields || - node.transformFlags & ts.TransformFlags.ContainsLexicalSuper && + if (node.transformFlags & TransformFlags.ContainsClassFields || + node.transformFlags & TransformFlags.ContainsLexicalSuper && shouldTransformSuperInStaticInitializers && currentStaticPropertyDeclarationOrStaticBlock && currentClassLexicalEnvironment) { switch (node.kind) { - case ts.SyntaxKind.PrefixUnaryExpression: - case ts.SyntaxKind.PostfixUnaryExpression: - return visitPreOrPostfixUnaryExpression(node as ts.PrefixUnaryExpression | ts.PostfixUnaryExpression, valueIsDiscarded); - case ts.SyntaxKind.BinaryExpression: - return visitBinaryExpression(node as ts.BinaryExpression, valueIsDiscarded); - case ts.SyntaxKind.CallExpression: - return visitCallExpression(node as ts.CallExpression); - case ts.SyntaxKind.TaggedTemplateExpression: - return visitTaggedTemplateExpression(node as ts.TaggedTemplateExpression); - case ts.SyntaxKind.PropertyAccessExpression: - return visitPropertyAccessExpression(node as ts.PropertyAccessExpression); - case ts.SyntaxKind.ElementAccessExpression: - return visitElementAccessExpression(node as ts.ElementAccessExpression); - case ts.SyntaxKind.ExpressionStatement: - return visitExpressionStatement(node as ts.ExpressionStatement); - 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.PrefixUnaryExpression: + case SyntaxKind.PostfixUnaryExpression: + return visitPreOrPostfixUnaryExpression(node as PrefixUnaryExpression | PostfixUnaryExpression, valueIsDiscarded); + case SyntaxKind.BinaryExpression: + return visitBinaryExpression(node as BinaryExpression, valueIsDiscarded); + case SyntaxKind.CallExpression: + return visitCallExpression(node as CallExpression); + case SyntaxKind.TaggedTemplateExpression: + return visitTaggedTemplateExpression(node as TaggedTemplateExpression); + case SyntaxKind.PropertyAccessExpression: + return visitPropertyAccessExpression(node as PropertyAccessExpression); + case SyntaxKind.ElementAccessExpression: + return visitElementAccessExpression(node as ElementAccessExpression); + case SyntaxKind.ExpressionStatement: + return visitExpressionStatement(node as ExpressionStatement); + 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: { const savedCurrentStaticPropertyDeclarationOrStaticBlock = currentStaticPropertyDeclarationOrStaticBlock; currentStaticPropertyDeclarationOrStaticBlock = undefined; - const result = ts.visitEachChild(node, visitor, context); + const result = visitEachChild(node, visitor, context); currentStaticPropertyDeclarationOrStaticBlock = savedCurrentStaticPropertyDeclarationOrStaticBlock; return result; } } } - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); } - function discardedValueVisitor(node: ts.Node): ts.VisitResult { + function discardedValueVisitor(node: Node): VisitResult { return visitorWorker(node, /*valueIsDiscarded*/ true); } - function visitor(node: ts.Node): ts.VisitResult { + function visitor(node: Node): VisitResult { return visitorWorker(node, /*valueIsDiscarded*/ false); } - 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 visitExpressionWithTypeArguments(node as ts.ExpressionWithTypeArguments); + case SyntaxKind.HeritageClause: + return visitEachChild(node, heritageClauseVisitor, context); + case SyntaxKind.ExpressionWithTypeArguments: + return visitExpressionWithTypeArguments(node as ExpressionWithTypeArguments); } return visitor(node); } - function visitorDestructuringTarget(node: ts.Node): ts.VisitResult { + function visitorDestructuringTarget(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); } @@ -275,38 +327,38 @@ 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); } /** * Visits `#id in expr` */ - function visitPrivateIdentifierInInExpression(node: ts.BinaryExpression) { + function visitPrivateIdentifierInInExpression(node: BinaryExpression) { if (!shouldTransformPrivateElementsOrClassStaticBlocks) { return node; } const privId = node.left; - ts.Debug.assertNode(privId, ts.isPrivateIdentifier); - ts.Debug.assert(node.operatorToken.kind === ts.SyntaxKind.InKeyword); + Debug.assertNode(privId, isPrivateIdentifier); + Debug.assert(node.operatorToken.kind === SyntaxKind.InKeyword); const info = accessPrivateIdentifier(privId); 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); } /** @@ -314,25 +366,25 @@ export function transformClassFields(context: ts.TransformationContext) { * * @param node The node to visit. */ - function classElementVisitor(node: ts.Node): ts.VisitResult { + function classElementVisitor(node: Node): VisitResult { switch (node.kind) { - case ts.SyntaxKind.Constructor: + case SyntaxKind.Constructor: // Constructors for classes using class fields are transformed in // `visitClassDeclaration` or `visitClassExpression`. return undefined; - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.MethodDeclaration: - return visitMethodOrAccessorDeclaration(node as ts.MethodDeclaration | ts.AccessorDeclaration); + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.MethodDeclaration: + return visitMethodOrAccessorDeclaration(node as MethodDeclaration | AccessorDeclaration); - case ts.SyntaxKind.PropertyDeclaration: - return visitPropertyDeclaration(node as ts.PropertyDeclaration); + case SyntaxKind.PropertyDeclaration: + return visitPropertyDeclaration(node as PropertyDeclaration); - case ts.SyntaxKind.ComputedPropertyName: - return visitComputedPropertyName(node as ts.ComputedPropertyName); + case SyntaxKind.ComputedPropertyName: + return visitComputedPropertyName(node as ComputedPropertyName); - case ts.SyntaxKind.SemicolonClassElement: + case SyntaxKind.SemicolonClassElement: return node; default: @@ -340,12 +392,12 @@ export function transformClassFields(context: ts.TransformationContext) { } } - 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; @@ -353,9 +405,9 @@ export function transformClassFields(context: ts.TransformationContext) { return statement; } - function visitComputedPropertyName(name: ts.ComputedPropertyName) { - let node = ts.visitEachChild(name, visitor, context); - if (ts.some(pendingExpressions)) { + function visitComputedPropertyName(name: ComputedPropertyName) { + let node = visitEachChild(name, visitor, context); + if (some(pendingExpressions)) { const expressions = pendingExpressions; expressions.push(node.expression); pendingExpressions = []; @@ -367,16 +419,16 @@ export function transformClassFields(context: ts.TransformationContext) { return node; } - function visitMethodOrAccessorDeclaration(node: ts.MethodDeclaration | ts.AccessorDeclaration) { - ts.Debug.assert(!ts.some(node.decorators)); + function visitMethodOrAccessorDeclaration(node: MethodDeclaration | AccessorDeclaration) { + Debug.assert(!some(node.decorators)); - 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; } @@ -387,13 +439,13 @@ export function transformClassFields(context: ts.TransformationContext) { factory.createAssignment( functionName, factory.createFunctionExpression( - ts.filter(node.modifiers, m => !ts.isStaticModifier(m)), + filter(node.modifiers, m => !isStaticModifier(m)), node.asteriskToken, functionName, /* typeParameters */ undefined, - ts.visitParameterList(node.parameters, classElementVisitor, context), + visitParameterList(node.parameters, classElementVisitor, context), /* type */ undefined, - ts.visitFunctionBody(node.body!, classElementVisitor, context) + visitFunctionBody(node.body!, classElementVisitor, context) ) ) ); @@ -403,40 +455,40 @@ export function transformClassFields(context: ts.TransformationContext) { return undefined; } - 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 visitPropertyDeclaration(node: ts.PropertyDeclaration) { - ts.Debug.assert(!ts.some(node.decorators)); + function visitPropertyDeclaration(node: PropertyDeclaration) { + Debug.assert(!some(node.decorators)); - if (ts.isPrivateIdentifier(node.name)) { + if (isPrivateIdentifier(node.name)) { if (!shouldTransformPrivateElementsOrClassStaticBlocks) { - if (ts.isStatic(node)) { + if (isStatic(node)) { // static fields are left as is - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); } // Initializer is elided as the field is initialized in transformConstructor. return factory.updatePropertyDeclaration( node, /*decorators*/ undefined, - ts.visitNodes(node.modifiers, visitor, ts.isModifier), + visitNodes(node.modifiers, visitor, isModifier), node.name, /*questionOrExclamationToken*/ undefined, /*type*/ undefined, @@ -446,7 +498,7 @@ export function transformClassFields(context: ts.TransformationContext) { // 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; } @@ -455,11 +507,11 @@ export function transformClassFields(context: ts.TransformationContext) { // If it's not inlineable, then we emit an expression after the class which assigns // the property name to the temporary variable. const expr = getPropertyNameExpressionIfNeeded(node.name, !!node.initializer || useDefineForClassFields); - if (expr && !ts.isSimpleInlineableExpression(expr)) { + if (expr && !isSimpleInlineableExpression(expr)) { getPendingExpressions().push(expr); } - if (ts.isStatic(node) && !shouldTransformPrivateElementsOrClassStaticBlocks && !useDefineForClassFields) { + if (isStatic(node) && !shouldTransformPrivateElementsOrClassStaticBlocks && !useDefineForClassFields) { const initializerStatement = transformPropertyOrClassStaticBlock(node, factory.createThis()); if (initializerStatement) { const staticBlock = factory.createClassStaticBlockDeclaration( @@ -468,14 +520,14 @@ export function transformClassFields(context: ts.TransformationContext) { 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; } } @@ -483,12 +535,12 @@ export function transformClassFields(context: ts.TransformationContext) { return undefined; } - 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: @@ -513,16 +565,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 ), @@ -531,8 +583,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; @@ -546,17 +598,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; @@ -568,45 +620,45 @@ 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) { - if (shouldTransformPrivateElementsOrClassStaticBlocks && ts.isPrivateIdentifierPropertyAccessExpression(node.operand)) { + function visitPreOrPostfixUnaryExpression(node: PrefixUnaryExpression | PostfixUnaryExpression, valueIsDiscarded: boolean) { + if (node.operator === SyntaxKind.PlusPlusToken || node.operator === SyntaxKind.MinusMinusToken) { + if (shouldTransformPrivateElementsOrClassStaticBlocks && isPrivateIdentifierPropertyAccessExpression(node.operand)) { let info: PrivateIdentifierInfo | undefined; if (info = accessPrivateIdentifier(node.operand.name)) { - const receiver = ts.visitNode(node.operand.expression, visitor, ts.isExpression); + const receiver = visitNode(node.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(node.operand) && + isSuperProperty(node.operand) && currentStaticPropertyDeclarationOrStaticBlock && currentClassLexicalEnvironment) { // converts `++super.a` into `(Reflect.set(_baseTemp, "a", (_a = Reflect.get(_baseTemp, "a", _classTemp), _b = ++_a), _classTemp), _b)` @@ -620,68 +672,68 @@ export function transformClassFields(context: ts.TransformationContext) { const { classConstructor, superClassReference, facts } = currentClassLexicalEnvironment; if (facts & ClassFacts.ClassWasDecorated) { const operand = visitInvalidSuperProperty(node.operand); - return ts.isPrefixUnaryExpression(node) ? + return isPrefixUnaryExpression(node) ? factory.updatePrefixUnaryExpression(node, operand) : factory.updatePostfixUnaryExpression(node, operand); } if (classConstructor && superClassReference) { - let setterName: ts.Expression | undefined; - let getterName: ts.Expression | undefined; - if (ts.isPropertyAccessExpression(node.operand)) { - if (ts.isIdentifier(node.operand.name)) { + let setterName: Expression | undefined; + let getterName: Expression | undefined; + if (isPropertyAccessExpression(node.operand)) { + if (isIdentifier(node.operand.name)) { getterName = setterName = factory.createStringLiteralFromNode(node.operand.name); } } else { - if (ts.isSimpleInlineableExpression(node.operand.argumentExpression)) { + if (isSimpleInlineableExpression(node.operand.argumentExpression)) { getterName = setterName = node.operand.argumentExpression; } else { getterName = factory.createTempVariable(hoistVariableDeclaration); - setterName = factory.createAssignment(getterName, ts.visitNode(node.operand.argumentExpression, visitor, ts.isExpression)); + setterName = factory.createAssignment(getterName, visitNode(node.operand.argumentExpression, visitor, isExpression)); } } if (setterName && getterName) { - let expression: ts.Expression = factory.createReflectGetCall(superClassReference, getterName, classConstructor); - ts.setTextRange(expression, node.operand); + let expression: Expression = factory.createReflectGetCall(superClassReference, getterName, classConstructor); + setTextRange(expression, node.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); @@ -689,127 +741,127 @@ export function transformClassFields(context: ts.TransformationContext) { return { readExpression, initializeExpression }; } - function visitCallExpression(node: ts.CallExpression) { - if (shouldTransformPrivateElementsOrClassStaticBlocks && ts.isPrivateIdentifierPropertyAccessExpression(node.expression)) { + function visitCallExpression(node: CallExpression) { + if (shouldTransformPrivateElementsOrClassStaticBlocks && isPrivateIdentifierPropertyAccessExpression(node.expression)) { // 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) { // 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) { - if (shouldTransformPrivateElementsOrClassStaticBlocks && ts.isPrivateIdentifierPropertyAccessExpression(node.tag)) { + function visitTaggedTemplateExpression(node: TaggedTemplateExpression) { + if (shouldTransformPrivateElementsOrClassStaticBlocks && 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(); const savedCurrentStaticPropertyDeclarationOrStaticBlock = currentStaticPropertyDeclarationOrStaticBlock; currentStaticPropertyDeclarationOrStaticBlock = node; - let statements = ts.visitNodes(node.body.statements, visitor, ts.isStatement); + let statements = visitNodes(node.body.statements, visitor, isStatement); statements = factory.mergeLexicalEnvironment(statements, endLexicalEnvironment()); currentStaticPropertyDeclarationOrStaticBlock = savedCurrentStaticPropertyDeclarationOrStaticBlock; 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)) { const savedPendingExpressions = pendingExpressions; pendingExpressions = undefined; node = factory.updateBinaryExpression( node, - ts.visitNode(node.left, visitorDestructuringTarget), + visitNode(node.left, visitorDestructuringTarget), 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 (shouldTransformPrivateElementsOrClassStaticBlocks && ts.isPrivateIdentifierPropertyAccessExpression(node.left)) { + if (isAssignmentExpression(node)) { + if (shouldTransformPrivateElementsOrClassStaticBlocks && isPrivateIdentifierPropertyAccessExpression(node.left)) { 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 ), @@ -818,7 +870,7 @@ export function transformClassFields(context: ts.TransformationContext) { } } else if (shouldTransformSuperInStaticInitializers && - ts.isSuperProperty(node.left) && + isSuperProperty(node.left) && currentStaticPropertyDeclarationOrStaticBlock && currentClassLexicalEnvironment) { const { classConstructor, superClassReference, facts } = currentClassLexicalEnvironment; @@ -827,12 +879,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)` @@ -840,10 +892,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); } @@ -852,21 +904,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( @@ -875,12 +927,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; @@ -888,27 +940,27 @@ export function transformClassFields(context: ts.TransformationContext) { } } } - if (node.operatorToken.kind === ts.SyntaxKind.InKeyword && ts.isPrivateIdentifier(node.left)) { + if (node.operatorToken.kind === SyntaxKind.InKeyword && isPrivateIdentifier(node.left)) { return visitPrivateIdentifierInInExpression(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: @@ -936,16 +988,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"); } } /** * Set up the environment for a class. */ - function visitClassLike(node: ts.ClassLikeDeclaration) { - if (!ts.forEach(node.members, doesClassElementNeedTransform)) { - return ts.visitEachChild(node, visitor, context); + function visitClassLike(node: ClassLikeDeclaration) { + if (!forEach(node.members, doesClassElementNeedTransform)) { + return visitEachChild(node, visitor, context); } const savedPendingExpressions = pendingExpressions; @@ -953,13 +1005,13 @@ export function transformClassFields(context: ts.TransformationContext) { startClassLexicalEnvironment(); if (shouldTransformPrivateElementsOrClassStaticBlocks) { - const name = ts.getNameOfDeclaration(node); - if (name && ts.isIdentifier(name)) { - getPrivateIdentifierEnvironment().className = ts.idText(name); + const name = getNameOfDeclaration(node); + if (name && isIdentifier(name)) { + getPrivateIdentifierEnvironment().className = idText(name); } const privateInstanceMethodsAndAccessors = getPrivateInstanceMethodsAndAccessors(node); - if (ts.some(privateInstanceMethodsAndAccessors)) { + if (some(privateInstanceMethodsAndAccessors)) { getPrivateIdentifierEnvironment().weakSetName = createHoistedVariableForClass( "instances", privateInstanceMethodsAndAccessors[0].name @@ -967,7 +1019,7 @@ export function transformClassFields(context: ts.TransformationContext) { } } - const result = ts.isClassDeclaration(node) ? + const result = isClassDeclaration(node) ? visitClassDeclaration(node) : visitClassExpression(node); @@ -976,33 +1028,33 @@ export function transformClassFields(context: ts.TransformationContext) { return result; } - function doesClassElementNeedTransform(node: ts.ClassElement) { - return ts.isPropertyDeclaration(node) || ts.isClassStaticBlockDeclaration(node) || (shouldTransformPrivateElementsOrClassStaticBlocks && node.name && ts.isPrivateIdentifier(node.name)); + function doesClassElementNeedTransform(node: ClassElement) { + return isPropertyDeclaration(node) || isClassStaticBlockDeclaration(node) || (shouldTransformPrivateElementsOrClassStaticBlocks && node.name && isPrivateIdentifier(node.name)); } - 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) && shouldTransformPrivateElementsOrClassStaticBlocks) { + if (!isStatic(member)) continue; + if (member.name && isPrivateIdentifier(member.name) && 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; } @@ -1012,7 +1064,7 @@ export function transformClassFields(context: ts.TransformationContext) { return facts; } - function visitExpressionWithTypeArguments(node: ts.ExpressionWithTypeArguments) { + function visitExpressionWithTypeArguments(node: ExpressionWithTypeArguments) { const facts = currentClassLexicalEnvironment?.facts || ClassFacts.None; if (facts & ClassFacts.NeedsClassSuperReference) { const temp = factory.createTempVariable(hoistVariableDeclaration, /*reserveInNestedScopes*/ true); @@ -1021,15 +1073,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 visitClassDeclaration(node: ts.ClassDeclaration) { + function visitClassDeclaration(node: ClassDeclaration) { const facts = getClassFacts(node); if (facts) { getClassLexicalEnvironment().facts = facts; @@ -1040,24 +1092,24 @@ export function transformClassFields(context: ts.TransformationContext) { // 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 extendsClauseElement = ts.getEffectiveBaseTypeNode(node); - const isDerivedClass = !!(extendsClauseElement && ts.skipOuterExpressions(extendsClauseElement.expression).kind !== ts.SyntaxKind.NullKeyword); + const extendsClauseElement = getEffectiveBaseTypeNode(node); + const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword); - const statements: ts.Statement[] = [ + const statements: Statement[] = [ factory.updateClassDeclaration( node, /*decorators*/ undefined, node.modifiers, node.name, /*typeParameters*/ undefined, - ts.visitNodes(node.heritageClauses, heritageClauseVisitor, ts.isHeritageClause), + visitNodes(node.heritageClauses, heritageClauseVisitor, isHeritageClause), transformClassMembers(node, isDerivedClass) ) ]; @@ -1067,7 +1119,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))); } @@ -1077,15 +1129,15 @@ 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)); } return statements; } - function visitClassExpression(node: ts.ClassExpression): ts.Expression { + function visitClassExpression(node: ClassExpression): Expression { const facts = getClassFacts(node); if (facts) { getClassLexicalEnvironment().facts = facts; @@ -1104,17 +1156,17 @@ 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 extendsClauseElement = ts.getEffectiveBaseTypeNode(node); - const isDerivedClass = !!(extendsClauseElement && ts.skipOuterExpressions(extendsClauseElement.expression).kind !== ts.SyntaxKind.NullKeyword); + const extendsClauseElement = getEffectiveBaseTypeNode(node); + const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword); - 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); } @@ -1125,25 +1177,25 @@ export function transformClassFields(context: ts.TransformationContext) { const classExpression = factory.updateClassExpression( node, - ts.visitNodes(node.decorators, visitor, ts.isDecorator), + visitNodes(node.decorators, visitor, isDecorator), node.modifiers, node.name, /*typeParameters*/ undefined, - ts.visitNodes(node.heritageClauses, heritageClauseVisitor, ts.isHeritageClause), + visitNodes(node.heritageClauses, heritageClauseVisitor, isHeritageClause), transformClassMembers(node, isDerivedClass) ); - const hasTransformableStatics = shouldTransformPrivateElementsOrClassStaticBlocks && ts.some(staticPropertiesOrClassStaticBlocks, p => ts.isClassStaticBlockDeclaration(p) || !!p.initializer || ts.isPrivateIdentifier(p.name)); - if (hasTransformableStatics || ts.some(pendingExpressions)) { + const hasTransformableStatics = shouldTransformPrivateElementsOrClassStaticBlocks && some(staticPropertiesOrClassStaticBlocks, p => isClassStaticBlockDeclaration(p) || !!p.initializer || isPrivateIdentifier(p.name)); + 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) { @@ -1152,24 +1204,24 @@ export function transformClassFields(context: ts.TransformationContext) { return classExpression; } else { - const expressions: ts.Expression[] = []; + const expressions: Expression[] = []; temp ||= createClassTempVar(); 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)); return factory.inlineExpressions(expressions); } @@ -1178,37 +1230,37 @@ export function transformClassFields(context: ts.TransformationContext) { return classExpression; } - function visitClassStaticBlockDeclaration(node: ts.ClassStaticBlockDeclaration) { + function visitClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration) { if (!shouldTransformPrivateElementsOrClassStaticBlocks) { - return ts.visitEachChild(node, classElementVisitor, context); + return visitEachChild(node, classElementVisitor, context); } // ClassStaticBlockDeclaration for classes are transformed in `visitClassDeclaration` or `visitClassExpression`. return undefined; } - function transformClassMembers(node: ts.ClassDeclaration | ts.ClassExpression, isDerivedClass: boolean) { - const members: ts.ClassElement[] = []; + function transformClassMembers(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { + const members: ClassElement[] = []; if (shouldTransformPrivateElementsOrClassStaticBlocks) { // Declare private names. for (const member of node.members) { - if (ts.isPrivateIdentifierClassElementDeclaration(member)) { + if (isPrivateIdentifierClassElementDeclaration(member)) { addPrivateIdentifierToEnvironment(member); } } - if (ts.some(getPrivateInstanceMethodsAndAccessors(node))) { + if (some(getPrivateInstanceMethodsAndAccessors(node))) { createBrandCheckWeakSetForPrivateMethods(); } } const constructor = transformConstructor(node, isDerivedClass); - const visitedMembers = ts.visitNodes(node.members, classElementVisitor, ts.isClassElement); + const visitedMembers = visitNodes(node.members, classElementVisitor, isClassElement); if (constructor) { members.push(constructor); } - if (!shouldTransformPrivateElementsOrClassStaticBlocks && ts.some(pendingExpressions)) { + if (!shouldTransformPrivateElementsOrClassStaticBlocks && some(pendingExpressions)) { members.push(factory.createClassStaticBlockDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, @@ -1219,14 +1271,14 @@ export function transformClassFields(context: ts.TransformationContext) { pendingExpressions = undefined; } - ts.addRange(members, visitedMembers); + addRange(members, visitedMembers); - return ts.setTextRange(factory.createNodeArray(members), /*location*/ node.members); + return setTextRange(factory.createNodeArray(members), /*location*/ node.members); } 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( @@ -1240,32 +1292,32 @@ export function transformClassFields(context: ts.TransformationContext) { ); } - function isClassElementThatRequiresConstructorStatement(member: ts.ClassElement) { - if (ts.isStatic(member) || ts.hasSyntacticModifier(ts.getOriginalNode(member), ts.ModifierFlags.Abstract)) { + function isClassElementThatRequiresConstructorStatement(member: ClassElement) { + if (isStatic(member) || hasSyntacticModifier(getOriginalNode(member), ModifierFlags.Abstract)) { return false; } if (useDefineForClassFields) { // If we are using define semantics and targeting ESNext or higher, // then we don't need to transform any class properties. - return languageVersion < ts.ScriptTarget.ES2022; + return languageVersion < ScriptTarget.ES2022; } - return ts.isInitializedProperty(member) || shouldTransformPrivateElementsOrClassStaticBlocks && ts.isPrivateIdentifierClassElementDeclaration(member); + return isInitializedProperty(member) || shouldTransformPrivateElementsOrClassStaticBlocks && isPrivateIdentifierClassElementDeclaration(member); } - function transformConstructor(node: ts.ClassDeclaration | ts.ClassExpression, isDerivedClass: boolean) { - const constructor = ts.visitNode(ts.getFirstConstructorWithBody(node), visitor, ts.isConstructorDeclaration); + function transformConstructor(node: ClassDeclaration | ClassExpression, isDerivedClass: boolean) { + const constructor = visitNode(getFirstConstructorWithBody(node), visitor, isConstructorDeclaration); const elements = node.members.filter(isClassElementThatRequiresConstructorStatement); - if (!ts.some(elements)) { + if (!some(elements)) { return constructor; } - const parameters = ts.visitParameterList(constructor ? constructor.parameters : undefined, visitor, context); + const parameters = visitParameterList(constructor ? constructor.parameters : undefined, visitor, context); const body = transformConstructorBody(node, constructor, isDerivedClass); if (!body) { return undefined; } - return ts.startOnNewLine( - ts.setOriginalNode( - ts.setTextRange( + return startOnNewLine( + setOriginalNode( + setTextRange( factory.createConstructorDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, @@ -1279,18 +1331,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)); + properties = filter(properties, property => !!property.initializer || isPrivateIdentifier(property.name)); } 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(); @@ -1299,18 +1351,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), ]; } @@ -1350,20 +1402,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 @@ -1389,14 +1441,14 @@ 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()); - return ts.setTextRange( + return setTextRange( factory.createBlock( - ts.setTextRange( + setTextRange( factory.createNodeArray(statements), /*location*/ constructor ? constructor.body!.statements : node.members ), @@ -1405,8 +1457,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; } @@ -1420,9 +1472,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; } @@ -1435,8 +1487,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) { @@ -1444,15 +1496,15 @@ export function transformClassFields(context: ts.TransformationContext) { } const statement = factory.createExpressionStatement(expression); - ts.setSourceMapRange(statement, ts.moveRangePastModifiers(property)); - ts.setCommentRange(statement, property); - ts.setOriginalNode(statement, property); + setSourceMapRange(statement, moveRangePastModifiers(property)); + setCommentRange(statement, property); + setOriginalNode(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; } @@ -1463,17 +1515,17 @@ 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.setSourceMapRange(expression, ts.moveRangePastModifiers(property)); - ts.setCommentRange(expression, property); - ts.setOriginalNode(expression, property); + startOnNewLine(expression); + setSourceMapRange(expression, moveRangePastModifiers(property)); + setCommentRange(expression, property); + setOriginalNode(expression, property); expressions.push(expression); } @@ -1486,45 +1538,45 @@ 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.isComputedPropertyName(property.name) && !ts.isSimpleInlineableExpression(property.name.expression) + const propertyName = 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) ); } } @@ -1533,29 +1585,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); @@ -1568,7 +1620,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 = []; @@ -1580,22 +1632,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); } } @@ -1606,13 +1658,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)[], receiver: ts.LeftHandSideExpression) { - if (!shouldTransformPrivateElementsOrClassStaticBlocks || !ts.some(methods)) { + function addMethodStatements(statements: Statement[], methods: readonly (MethodDeclaration | AccessorDeclaration)[], 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) @@ -1620,8 +1672,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(), @@ -1629,11 +1681,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) { @@ -1649,14 +1701,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; @@ -1667,10 +1719,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; @@ -1680,7 +1732,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; @@ -1700,33 +1752,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, ), @@ -1737,13 +1789,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. @@ -1754,8 +1806,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; } } @@ -1770,15 +1822,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 { @@ -1786,7 +1838,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; } } @@ -1812,7 +1864,7 @@ export function transformClassFields(context: ts.TransformationContext) { const lex = getClassLexicalEnvironment(); lex.privateIdentifierEnvironment ||= { className: "", - identifiers: new ts.Map() + identifiers: new Map() }; return lex.privateIdentifierEnvironment; } @@ -1821,23 +1873,23 @@ export function transformClassFields(context: ts.TransformationContext) { return pendingExpressions || (pendingExpressions = []); } - function addPrivateIdentifierToEnvironment(node: ts.PrivateClassElementDeclaration) { - const text = ts.getTextOfPropertyName(node.name) as string; + function addPrivateIdentifierToEnvironment(node: PrivateClassElementDeclaration) { + const text = getTextOfPropertyName(node.name) as string; const lex = getClassLexicalEnvironment(); const { classConstructor } = lex; const privateEnv = getPrivateIdentifierEnvironment(); const { weakSetName } = privateEnv; - const assignmentExpressions: ts.Expression[] = []; + const assignmentExpressions: Expression[] = []; const privateName = node.name.escapedText; const previousInfo = privateEnv.identifiers.get(privateName); const isValid = !isReservedPrivateName(node.name) && previousInfo === undefined; - if (ts.hasStaticModifier(node)) { - ts.Debug.assert(classConstructor, "weakSetName should be set in private identifier environment"); - if (ts.isPropertyDeclaration(node)) { + if (hasStaticModifier(node)) { + Debug.assert(classConstructor, "weakSetName should be set in private identifier environment"); + if (isPropertyDeclaration(node)) { const variableName = createHoistedVariableForPrivateName(text, node); privateEnv.identifiers.set(privateName, { kind: PrivateIdentifierKind.Field, @@ -1847,7 +1899,7 @@ export function transformClassFields(context: ts.TransformationContext) { isValid, }); } - else if (ts.isMethodDeclaration(node)) { + else if (isMethodDeclaration(node)) { const functionName = createHoistedVariableForPrivateName(text, node); privateEnv.identifiers.set(privateName, { kind: PrivateIdentifierKind.Method, @@ -1857,7 +1909,7 @@ export function transformClassFields(context: ts.TransformationContext) { isValid, }); } - else if (ts.isGetAccessorDeclaration(node)) { + else if (isGetAccessorDeclaration(node)) { const getterName = createHoistedVariableForPrivateName(text + "_get", node); if (previousInfo?.kind === PrivateIdentifierKind.Accessor && previousInfo.isStatic && !previousInfo.getterName) { previousInfo.getterName = getterName; @@ -1873,7 +1925,7 @@ export function transformClassFields(context: ts.TransformationContext) { }); } } - else if (ts.isSetAccessorDeclaration(node)) { + else if (isSetAccessorDeclaration(node)) { const setterName = createHoistedVariableForPrivateName(text + "_set", node); if (previousInfo?.kind === PrivateIdentifierKind.Accessor && previousInfo.isStatic && !previousInfo.setterName) { previousInfo.setterName = setterName; @@ -1890,10 +1942,10 @@ export function transformClassFields(context: ts.TransformationContext) { } } else { - ts.Debug.assertNever(node, "Unknown class element type."); + Debug.assertNever(node, "Unknown class element type."); } } - else if (ts.isPropertyDeclaration(node)) { + else if (isPropertyDeclaration(node)) { const weakMapName = createHoistedVariableForPrivateName(text, node); privateEnv.identifiers.set(privateName, { kind: PrivateIdentifierKind.Field, @@ -1912,8 +1964,8 @@ export function transformClassFields(context: ts.TransformationContext) { ) )); } - else if (ts.isMethodDeclaration(node)) { - ts.Debug.assert(weakSetName, "weakSetName should be set in private identifier environment"); + else if (isMethodDeclaration(node)) { + Debug.assert(weakSetName, "weakSetName should be set in private identifier environment"); privateEnv.identifiers.set(privateName, { kind: PrivateIdentifierKind.Method, @@ -1923,10 +1975,10 @@ export function transformClassFields(context: ts.TransformationContext) { isValid, }); } - else if (ts.isAccessor(node)) { - ts.Debug.assert(weakSetName, "weakSetName should be set in private identifier environment"); + else if (isAccessor(node)) { + Debug.assert(weakSetName, "weakSetName should be set in private identifier environment"); - if (ts.isGetAccessor(node)) { + if (isGetAccessor(node)) { const getterName = createHoistedVariableForPrivateName(text + "_get", node); if (previousInfo?.kind === PrivateIdentifierKind.Accessor && !previousInfo.isStatic && !previousInfo.getterName) { @@ -1962,18 +2014,18 @@ export function transformClassFields(context: ts.TransformationContext) { } } else { - ts.Debug.assertNever(node, "Unknown class element type."); + Debug.assertNever(node, "Unknown class element type."); } getPendingExpressions().push(...assignmentExpressions); } - function createHoistedVariableForClass(name: string, node: ts.PrivateIdentifier | ts.ClassStaticBlockDeclaration): ts.Identifier { + function createHoistedVariableForClass(name: string, node: PrivateIdentifier | ClassStaticBlockDeclaration): Identifier { const { className } = getPrivateIdentifierEnvironment(); const prefix = className ? `_${className}` : ""; - const identifier = factory.createUniqueName(`${prefix}_${name}`, ts.GeneratedIdentifierFlags.Optimistic); + const identifier = factory.createUniqueName(`${prefix}_${name}`, GeneratedIdentifierFlags.Optimistic); - if (resolver.getNodeCheckFlags(node) & ts.NodeCheckFlags.BlockScopedBindingInLoop) { + if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.BlockScopedBindingInLoop) { addBlockScopedVariable(identifier); } else { @@ -1983,11 +2035,11 @@ export function transformClassFields(context: ts.TransformationContext) { return identifier; } - function createHoistedVariableForPrivateName(privateName: string, node: ts.PrivateClassElementDeclaration): ts.Identifier { + function createHoistedVariableForPrivateName(privateName: string, node: PrivateClassElementDeclaration): Identifier { return createHoistedVariableForClass(privateName.substring(1), node.name); } - function accessPrivateIdentifier(name: ts.PrivateIdentifier) { + function accessPrivateIdentifier(name: PrivateIdentifier) { if (currentClassLexicalEnvironment?.privateIdentifierEnvironment) { const info = currentClassLexicalEnvironment.privateIdentifierEnvironment.identifiers.get(name.escapedText); if (info) { @@ -2007,18 +2059,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, @@ -2026,20 +2078,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; @@ -2048,8 +2100,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); @@ -2066,15 +2118,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 { @@ -2082,19 +2134,19 @@ export function transformClassFields(context: ts.TransformationContext) { } } } - return ts.visitNode(node, visitorDestructuringTarget); + return visitNode(node, visitorDestructuringTarget); } - 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; @@ -2103,8 +2155,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); @@ -2121,29 +2173,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, visitorDestructuringTarget, ts.isExpression) + initializer ? factory.createAssignment(wrapped, visitNode(initializer, visitor)) : wrapped : + visitNode(node.initializer, visitorDestructuringTarget, isExpression) ); } - if (ts.isSpreadAssignment(node)) { + if (isSpreadAssignment(node)) { return factory.updateSpreadAssignment( node, - wrapped || ts.visitNode(node.expression, visitorDestructuringTarget, ts.isExpression) + wrapped || visitNode(node.expression, visitorDestructuringTarget, 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. // @@ -2154,7 +2206,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 { @@ -2168,37 +2220,37 @@ 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) { +function isReservedPrivateName(node: PrivateIdentifier) { return node.escapedText === "#constructor"; } diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index cf16827bc5531..641496e5de3e1 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -1,49 +1,115 @@ import * as ts from "../_namespaces/ts"; +import { + append, arrayFrom, compact, concatenate, contains, emptyArray, filter, flatMap, flatten, forEach, isArray, last, + length, map, mapDefined, orderedRemoveItem, pushIfUnique, some, startsWith, stringContains, toFileNameLowerCase, +} from "../core"; +import { ESMap, Map, Set } from "../corePublic"; +import { Debug } from "../debug"; +import { Diagnostics } from "../diagnosticInformationMap.generated"; +import { getOutputPathsFor } from "../emitter"; +import { getCommentRange, removeAllComments, setCommentRange, setEmitFlags } from "../factory/emitNode"; +import { createUnparsedSourceFile, factory, setOriginalNode } from "../factory/nodeFactory"; +import { + isClassDeclaration, isExportAssignment, isExportDeclaration, isExternalModuleReference, isFunctionDeclaration, + isImportDeclaration, isImportEqualsDeclaration, isIndexSignatureDeclaration, isInterfaceDeclaration, + isMappedTypeNode, isMethodDeclaration, isMethodSignature, isModuleDeclaration, isOmittedExpression, + isPrivateIdentifier, isPropertyAccessExpression, isSemicolonClassElement, isSetAccessorDeclaration, isSourceFile, + isStringLiteral, isTupleTypeNode, isTypeAliasDeclaration, isTypeParameterDeclaration, isTypeQueryNode, + isUnparsedSource, +} from "../factory/nodeTests"; +import { canHaveModifiers, createEmptyExports } from "../factory/utilities"; +import { setTextRange } from "../factory/utilitiesPublic"; +import { pathContainsNodeModules } from "../moduleNameResolver"; +import { getModuleSpecifier } from "../moduleSpecifiers"; +import { isExternalModule, parseNodeFactory } from "../parser"; +import { + getDirectoryPath, getRelativePathToDirectoryOrUrl, hasExtension, normalizeSlashes, pathIsRelative, toPath, +} from "../path"; +import { getResolutionModeOverrideForClause } from "../program"; +import { + getLeadingCommentRanges, getLineAndCharacterOfPosition, getTrailingCommentRanges, skipTrivia, +} from "../scanner"; +import { transformNodes } from "../transformer"; +import { + AccessorDeclaration, AllAccessorDeclarations, AnyImportSyntax, ArrayBindingElement, AssertClause, BindingElement, + BindingName, BindingPattern, Bundle, CallSignatureDeclaration, ClassDeclaration, CommentRange, ConditionalTypeNode, + ConstructorDeclaration, ConstructorTypeNode, ConstructSignatureDeclaration, Declaration, DeclarationName, + DiagnosticWithLocation, EmitFlags, EmitHost, EmitResolver, EntityNameOrEntityNameExpression, EnumDeclaration, + ExportAssignment, ExportDeclaration, ExpressionWithTypeArguments, FileReference, FunctionDeclaration, + FunctionTypeNode, GeneratedIdentifierFlags, GetAccessorDeclaration, HeritageClause, Identifier, ImportDeclaration, + ImportEqualsDeclaration, ImportTypeNode, IndexSignatureDeclaration, InterfaceDeclaration, LateBoundDeclaration, + LateVisibilityPaintedStatement, MethodDeclaration, MethodSignature, Modifier, ModifierFlags, ModuleBody, + ModuleDeclaration, NamedDeclaration, NamespaceDeclaration, Node, NodeArray, NodeBuilderFlags, NodeFlags, NodeId, + OmittedExpression, ParameterDeclaration, PropertyDeclaration, PropertySignature, SetAccessorDeclaration, + SignatureDeclaration, SourceFile, Statement, StringLiteral, Symbol, SymbolAccessibility, SymbolAccessibilityResult, + SymbolFlags, SymbolTracker, SyntaxKind, TransformationContext, TypeAliasDeclaration, TypeNode, + TypeParameterDeclaration, TypeReferenceNode, UnparsedSource, VariableDeclaration, VariableStatement, VisitResult, +} from "../types"; +import { + addRelatedInfo, createDiagnosticForNode, createSymbolTable, declarationNameToString, getEffectiveBaseTypeNode, + getEffectiveModifierFlags, getExternalModuleImportEqualsDeclarationExpression, getExternalModuleNameFromDeclaration, + getFirstConstructorWithBody, getLeadingCommentRangesOfNode, getResolvedExternalModuleName, + getSetAccessorValueParameter, getSourceFileOfNode, getTextOfNode, getThisParameter, hasDynamicName, + hasEffectiveModifier, hasSyntacticModifier, isAnyImportSyntax, isEntityNameExpression, isExternalModuleAugmentation, + isExternalOrCommonJsModule, isGlobalScopeAugmentation, isJsonSourceFile, isLateVisibilityPaintedStatement, + isLiteralImportTypeNode, isNightly, isSourceFileJS, isSourceFileNotJson, isStringANonContextualKeyword, setParent, +} from "../utilities"; +import { + getNameOfDeclaration, getParseTreeNode, hasJSDocNodes, isBindingPattern, isDeclaration, isEntityName, + isExternalModuleIndicator, isFunctionLike, isStringLiteralLike, isTypeNode, needsScopeMarker, + unescapeLeadingUnderscores, +} from "../utilitiesPublic"; +import { visitEachChild, visitNode, visitNodes } from "../visitorPublic"; +import { + canProduceDiagnostics, createGetSymbolAccessibilityDiagnosticForNode, + createGetSymbolAccessibilityDiagnosticForNodeName, DeclarationDiagnosticProducing, GetSymbolAccessibilityDiagnostic, +} from "./declarations/diagnostics"; +import { getOriginalNodeId } from "./utilities"; /* @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 +118,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, @@ -83,41 +149,41 @@ export function transformDeclarations(context: ts.TransformationContext) { reportNonlocalAugmentation, reportNonSerializableProperty }; - 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) { @@ -125,7 +191,7 @@ export function transformDeclarations(context: ts.TransformationContext) { } else { for (const ref of symbolAccessibilityResult.aliasesToMakeVisible) { - ts.pushIfUnique(lateMarkedStatements, ref); + pushIfUnique(lateMarkedStatements, ref); } } } @@ -137,14 +203,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)); @@ -155,14 +221,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; @@ -171,20 +237,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")); } @@ -192,14 +258,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")); } @@ -207,7 +273,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)); } @@ -215,18 +281,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 (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) )); } } @@ -234,16 +300,16 @@ 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 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); @@ -251,20 +317,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; @@ -272,34 +338,34 @@ 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; } @@ -309,8 +375,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; } @@ -326,26 +392,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()); @@ -353,24 +419,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; } } @@ -378,27 +444,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 = 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 @@ -406,20 +472,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; } @@ -429,54 +495,54 @@ 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 filterBindingPatternInitializers(name: ts.BindingName) { - if (name.kind === ts.SyntaxKind.Identifier) { + function filterBindingPatternInitializers(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; } return factory.updateBindingElement(elem, elem.dotDotDotToken, elem.propertyName, filterBindingPatternInitializers(elem.name), shouldPrintWithInitializer(elem) ? elem.initializer : undefined); } } - 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, @@ -484,7 +550,7 @@ export function transformDeclarations(context: ts.TransformationContext) { maskModifiers(p, modifierMask), p.dotDotDotToken, filterBindingPatternInitializers(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) ); @@ -494,33 +560,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; } @@ -528,116 +594,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 (node.kind === SyntaxKind.Parameter + || node.kind === SyntaxKind.PropertyDeclaration + || node.kind === SyntaxKind.PropertySignature) { if (!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); @@ -651,45 +717,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); } @@ -704,11 +770,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, /*decorators*/ undefined, @@ -720,14 +786,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( @@ -750,7 +816,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, /*decorators*/ undefined, decl.modifiers, factory.updateImportClause( @@ -761,7 +827,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, @@ -791,18 +857,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: @@ -817,34 +883,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 as any).SyntaxKind ? (ts as any).SyntaxKind[(i as any).kind] : (i as any).kind}`); + if (!isLateVisibilityPaintedStatement(i)) { + return Debug.fail(`Late replaced statement was found which is not handled by the declaration transformer!: ${(ts as any).SyntaxKind ? (ts as any).SyntaxKind[(i as any).kind] : (i as any).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; } } @@ -855,47 +921,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(/*decorators*/ undefined, 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); } @@ -906,37 +972,37 @@ 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( /*decorators*/ undefined, /*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( @@ -952,8 +1018,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)); @@ -962,12 +1028,12 @@ export function transformDeclarations(context: ts.TransformationContext) { /*decorators*/ undefined, 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( @@ -975,11 +1041,11 @@ export function transformDeclarations(context: ts.TransformationContext) { /*decorators*/ undefined, 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( @@ -991,8 +1057,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( @@ -1002,8 +1068,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( @@ -1016,7 +1082,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), @@ -1024,70 +1090,70 @@ export function transformDeclarations(context: ts.TransformationContext) { ensureType(input, input.type) )); } - case ts.SyntaxKind.IndexSignature: { + case SyntaxKind.IndexSignature: { return cleanup(factory.updateIndexSignature( input, /*decorators*/ undefined, 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 as any).SyntaxKind[(input as any).kind]}`); + default: Debug.assertNever(input, `Attempted to process unhandled node kind: ${(ts as any).SyntaxKind[(input as any).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)) { @@ -1102,15 +1168,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; @@ -1118,8 +1184,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; @@ -1132,31 +1198,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.decorators, input.modifiers, newId)]; } } @@ -1164,63 +1230,63 @@ 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: // Type aliases get `declare`d if need be (for legacy support), but that's all + case SyntaxKind.TypeAliasDeclaration: // Type aliases get `declare`d if need be (for legacy support), but that's all return cleanup(factory.updateTypeAliasDeclaration( input, /*decorators*/ undefined, 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) )); - case ts.SyntaxKind.InterfaceDeclaration: { + case SyntaxKind.InterfaceDeclaration: { return cleanup(factory.updateInterfaceDeclaration( input, /*decorators*/ undefined, @@ -1228,10 +1294,10 @@ export function transformDeclarations(context: ts.TransformationContext) { 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, @@ -1247,46 +1313,46 @@ 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(/*decorators*/ undefined, /*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(/*decorators*/ undefined, /*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( /*decorators*/ undefined, /*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(/*decorators*/ undefined, ensureModifiers(input), input.name!, factory.createModuleBlock(declarations), ts.NodeFlags.Namespace); - if (!ts.hasEffectiveModifier(clean, ts.ModifierFlags.Default)) { + const namespaceDecl = factory.createModuleDeclaration(/*decorators*/ undefined, 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, /*decorators*/ undefined, @@ -1314,7 +1380,7 @@ export function transformDeclarations(context: ts.TransformationContext) { namespaceDecl.name ); - if (ts.isSourceFile(input.parent)) { + if (isSourceFile(input.parent)) { resultHasExternalModuleIndicator = true; } resultHasScopeMarker = true; @@ -1325,29 +1391,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); @@ -1359,7 +1425,7 @@ export function transformDeclarations(context: ts.TransformationContext) { input, /*decorators*/ undefined, mods, - ts.isExternalModuleAugmentation(input) ? rewriteModuleSpecifier(input, input.name) : input.name, + isExternalModuleAugmentation(input) ? rewriteModuleSpecifier(input, input.name) : input.name, body )); } @@ -1367,9 +1433,9 @@ 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( @@ -1377,23 +1443,23 @@ export function transformDeclarations(context: ts.TransformationContext) { /*decorators*/ undefined, 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( /*decorators*/ undefined, ensureModifiers(param), @@ -1407,18 +1473,18 @@ 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( /*decorators*/ undefined, ensureModifiers(param), - elem.name as ts.Identifier, + elem.name as Identifier, /*questionToken*/ undefined, ensureType(elem, /*type*/ undefined), /*initializer*/ undefined @@ -1430,7 +1496,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 ? [ @@ -1443,31 +1509,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, @@ -1492,11 +1558,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, /*decorators*/ undefined, factory.createNodeArray(ensureModifiers(input)), input.name, factory.createNodeArray(ts.mapDefined(input.members, m => { + case SyntaxKind.EnumDeclaration: { + return cleanup(factory.updateEnumDeclaration(input, /*decorators*/ undefined, 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); @@ -1505,45 +1571,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 as any).SyntaxKind[(input as any).kind]}`); + return Debug.assertNever(input, `Unhandled top-level node in declaration emit: ${(ts as any).SyntaxKind[(input as any).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 { @@ -1552,15 +1618,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) { @@ -1569,20 +1635,20 @@ 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: ts.Node): readonly ts.Modifier[] | undefined { - const currentFlags = ts.getEffectiveModifierFlags(node); + function ensureModifiers(node: Node): readonly Modifier[] | undefined { + const currentFlags = getEffectiveModifierFlags(node); const newFlags = ensureModifierFlags(node); if (currentFlags === newFlags) { return node.modifiers; @@ -1590,67 +1656,67 @@ export function transformDeclarations(context: ts.TransformationContext) { 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 @@ -1658,90 +1724,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 5884ea424e4c1..a821217498f13 100644 --- a/src/compiler/transformers/declarations/diagnostics.ts +++ b/src/compiler/transformers/declarations/diagnostics.ts @@ -1,496 +1,518 @@ import * as ts from "../../_namespaces/ts"; +import { Debug } from "../../debug"; +import { Diagnostics } from "../../diagnosticInformationMap.generated"; +import { + isBindingElement, isCallSignatureDeclaration, isClassDeclaration, isConstructorDeclaration, + isConstructSignatureDeclaration, isExpressionWithTypeArguments, isFunctionDeclaration, isHeritageClause, + isImportEqualsDeclaration, isIndexSignatureDeclaration, isMethodDeclaration, isMethodSignature, isParameter, + isPropertyAccessExpression, isPropertyDeclaration, isPropertySignature, isTypeAliasDeclaration, + isTypeParameterDeclaration, isVariableDeclaration, +} from "../../factory/nodeTests"; +import { + BindingElement, CallSignatureDeclaration, ConstructorDeclaration, ConstructSignatureDeclaration, Declaration, + DeclarationName, DiagnosticMessage, ExpressionWithTypeArguments, FunctionDeclaration, GetAccessorDeclaration, + ImportEqualsDeclaration, IndexSignatureDeclaration, JSDocCallbackTag, JSDocEnumTag, JSDocTypedefTag, + MethodDeclaration, MethodSignature, ModifierFlags, NamedDeclaration, Node, ParameterDeclaration, + PropertyAccessExpression, PropertyDeclaration, PropertySignature, QualifiedName, SetAccessorDeclaration, + SymbolAccessibility, SymbolAccessibilityResult, SyntaxKind, TypeAliasDeclaration, TypeParameterDeclaration, + VariableDeclaration, +} from "../../types"; +import { hasSyntacticModifier, isJSDocTypeAlias, isStatic } from "../../utilities"; +import { + getNameOfDeclaration, isGetAccessor, isParameterPropertyDeclaration, isSetAccessor, +} from "../../utilitiesPublic"; /* @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 as any).SyntaxKind[(node as any).kind]}`); + return Debug.assertNever(node, `Attempted to set a declaration diagnostic context for unhandled node kind: ${(ts as any).SyntaxKind[(node as any).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 as any).SyntaxKind[node.parent.kind]}`); + return Debug.fail(`Unknown parent for parameter: ${(ts as any).SyntaxKind[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 70f1ead7f7bab..9e7f9255d4c1c 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -1,17 +1,45 @@ -import * as ts from "../_namespaces/ts"; +import { addRange, append, every, forEach, last, map, some } from "../core"; +import { Debug } from "../debug"; +import { factory } from "../factory/nodeFactory"; +import { + isBindingElement, isComputedPropertyName, isIdentifier, isOmittedExpression, isVariableDeclaration, +} from "../factory/nodeTests"; +import { + getElementsOfBindingOrAssignmentPattern, getInitializerOfBindingOrAssignmentElement, + getPropertyNameOfBindingOrAssignmentElement, getRestIndicatorOfBindingOrAssignmentElement, + getTargetOfBindingOrAssignmentElement, tryGetPropertyNameOfBindingOrAssignmentElement, +} from "../factory/utilities"; +import { setTextRange } from "../factory/utilitiesPublic"; +import { + __String, ArrayBindingElement, ArrayBindingOrAssignmentPattern, BindingElement, BindingName, + BindingOrAssignmentElement, BindingOrAssignmentElementTarget, BindingOrAssignmentPattern, DestructuringAssignment, + ElementAccessExpression, Expression, Identifier, LeftHandSideExpression, Node, NodeFactory, + ObjectBindingOrAssignmentPattern, ParameterDeclaration, PropertyName, TextRange, TransformationContext, + TransformFlags, VariableDeclaration, VisitResult, +} from "../types"; +import { + isDestructuringAssignment, isEmptyArrayLiteral, isEmptyObjectLiteral, isPropertyNameLiteral, + isStringOrNumericLiteralLike, nodeIsSynthesized, +} from "../utilities"; +import { + idText, isArrayBindingElement, isArrayBindingOrAssignmentPattern, isBindingName, isBindingOrAssignmentPattern, + isDeclarationBindingElement, isExpression, isLiteralExpression, isObjectBindingOrAssignmentPattern, +} from "../utilitiesPublic"; +import { visitNode } from "../visitorPublic"; +import { isSimpleInlineableExpression } from "./utilities"; 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 +61,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 +97,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 +114,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 +125,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 +137,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 +154,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 +175,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 +201,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 +224,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 +245,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 +259,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 +293,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 +318,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 +338,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 +367,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 +396,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 +417,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 +470,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 +489,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 +504,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 +530,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 +547,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 da39fff4349f4..22be69b7c5842 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -1,4 +1,61 @@ -import * as ts from "../_namespaces/ts"; +import { + addRange, append, arrayIsEqualTo, cast, concatenate, elementAt, emptyArray, filter, first, firstOrUndefined, + flatMap, flatten, last, lastOrUndefined, map, singleOrMany, singleOrUndefined, some, spanMap, takeWhile, tryCast, +} from "../core"; +import { ESMap, Map } from "../corePublic"; +import { Debug } from "../debug"; +import { isCallToHelper } from "../factory/emitHelpers"; +import { + addEmitHelpers, addSyntheticLeadingComment, getCommentRange, getSourceMapRange, moveSyntheticComments, + setCommentRange, setEmitFlags, setSourceMapRange, setTokenSourceMapRange, +} from "../factory/emitNode"; +import { setOriginalNode } from "../factory/nodeFactory"; +import { + isArrayLiteralExpression, isArrowFunction, isBinaryExpression, isBlock, isCallExpression, isCaseBlock, isCaseClause, + isCatchClause, isComputedPropertyName, isDefaultClause, isExpressionStatement, isForStatement, isFunctionExpression, + isIdentifier, isIfStatement, isLabeledStatement, isOmittedExpression, isPrivateIdentifier, isPropertyDeclaration, + isReturnStatement, isSpreadElement, isSwitchStatement, isTryStatement, isVariableDeclarationList, + isVariableStatement, isWithStatement, +} from "../factory/nodeTests"; +import { + createExpressionForPropertyName, createMemberAccessForPropertyName, isInternalName, skipOuterExpressions, + startOnNewLine, +} from "../factory/utilities"; +import { setTextRange } from "../factory/utilitiesPublic"; +import { skipTrivia } from "../scanner"; +import { + __String, AccessorDeclaration, AllAccessorDeclarations, ArrayLiteralExpression, ArrowFunction, BinaryExpression, + BindingElement, BindingPattern, Block, BreakOrContinueStatement, CallExpression, CaseBlock, CaseClause, CatchClause, + ClassDeclaration, ClassElement, ClassExpression, ClassLikeDeclaration, CommaListExpression, ComputedPropertyName, + ConstructorDeclaration, Declaration, DoStatement, EmitFlags, EmitHint, Expression, ExpressionStatement, + ExpressionWithTypeArguments, ForInStatement, ForOfStatement, ForStatement, FunctionBody, FunctionDeclaration, + FunctionExpression, FunctionLikeDeclaration, GeneratedIdentifierFlags, Identifier, IfStatement, IterationStatement, + LabeledStatement, LeftHandSideExpression, LiteralExpression, MetaProperty, MethodDeclaration, ModifierFlags, + NamedDeclaration, NewExpression, Node, NodeArray, NodeCheckFlags, NodeFlags, NumericLiteral, + ObjectLiteralElementLike, ObjectLiteralExpression, ParameterDeclaration, ParenthesizedExpression, PrimaryExpression, + PropertyAssignment, ReturnStatement, SemicolonClassElement, ShorthandPropertyAssignment, SourceFile, SpreadElement, + Statement, StringLiteral, SwitchStatement, SyntaxKind, TaggedTemplateExpression, TemplateExpression, TextRange, + TokenFlags, TransformationContext, TransformFlags, VariableDeclaration, VariableDeclarationList, VariableStatement, + VisitResult, VoidExpression, WhileStatement, YieldExpression, +} from "../types"; +import { + createRange, createTokenRange, getAllAccessorDeclarations, getClassExtendsHeritageElement, getEmitFlags, + getEnclosingBlockScopeContainer, getFirstConstructorWithBody, getUseDefineForClassFields, hasStaticModifier, + hasSyntacticModifier, insertStatementAfterCustomPrologue, insertStatementsAfterCustomPrologue, + insertStatementsAfterStandardPrologue, isAssignmentExpression, isDestructuringAssignment, isHoistedFunction, + isHoistedVariableStatement, isIdentifierANonContextualKeyword, isPackedArrayLiteral, isPrologueDirective, isStatic, + isSuperProperty, moveRangeEnd, moveRangePos, nodeIsSynthesized, rangeEndIsOnSameLineAsRangeStart, setParent, + setTextRangeEnd, setTextRangePos, unwrapInnermostStatementOfLabel, +} from "../utilities"; +import { + getCombinedNodeFlags, getNameOfDeclaration, getOriginalNode, getParseTreeNode, idText, isBindingPattern, + isClassElement, isClassLike, isExpression, isForInitializer, isFunctionLike, isIterationStatement, isModifier, + isObjectLiteralElementLike, isPropertyName, isStatement, unescapeLeadingUnderscores, +} from "../utilitiesPublic"; +import { visitEachChild, visitNode, visitNodes, visitParameterList } from "../visitorPublic"; +import { flattenDestructuringAssignment, flattenDestructuringBinding, FlattenLevel } from "./destructuring"; +import { ProcessLevel, processTaggedTemplateExpression } from "./taggedTemplate"; +import { chainBundle, getSuperCallFromStatement } from "./utilities"; const enum ES2015SubstitutionFlags { /** Enables substitutions for captured `this` */ @@ -47,8 +104,8 @@ const enum ES2015SubstitutionFlags { */ interface LoopOutParameter { flags: LoopOutParameterFlags; - originalName: ts.Identifier; - outParamName: ts.Identifier; + originalName: Identifier; + outParamName: Identifier; } const enum LoopOutParameterFlags { @@ -72,15 +129,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: 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 a23ac6e43761a..25a2467732c1a 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1,4 +1,105 @@ -import * as ts from "./_namespaces/ts"; +import { getSymbolId } from "../compiler/checker"; +import { + append, cast, compareStringsCaseSensitiveUI, compareTextSpans, concatenate, createSortedArray, every, filter, find, + first, firstDefined, flatMap, insertSorted, isString, last, lastOrUndefined, length, mapDefined, maybeBind, memoize, + memoizeOne, or, singleElementArray, some, stableSort, startsWith, tryCast, +} from "../compiler/core"; +import { Comparison, Map, Set, SortedArray } from "../compiler/corePublic"; +import { Debug } from "../compiler/debug"; +import { Diagnostics } from "../compiler/diagnosticInformationMap.generated"; +import { createPrinter } from "../compiler/emitter"; +import { setSnippetElement } from "../compiler/factory/emitNode"; +import { factory } from "../compiler/factory/nodeFactory"; +import { + isArrowFunction, isBigIntLiteral, isBinaryExpression, isBindingElement, isCallExpression, isCaseClause, + isClassStaticBlockDeclaration, isComputedPropertyName, isConstructorDeclaration, isExportAssignment, + isExportDeclaration, isExternalModuleReference, isFunctionTypeNode, isIdentifier, isImportDeclaration, + isImportEqualsDeclaration, isImportKeyword, isImportSpecifier, isIntersectionTypeNode, isJSDoc, isJSDocParameterTag, + isJSDocTemplateTag, isJsxAttribute, isJsxClosingElement, isJsxElement, isJsxExpression, isJsxFragment, + isJsxSpreadAttribute, isLabeledStatement, isMethodDeclaration, isModuleDeclaration, isNamedExports, isNamedImports, + isNamespaceImport, isObjectBindingPattern, isObjectLiteralExpression, isParameter, isPrivateIdentifier, + isPropertyAccessExpression, isPropertyDeclaration, isRegularExpressionLiteral, isShorthandPropertyAssignment, + isSourceFile, isSpreadAssignment, isSyntaxList, isTypeLiteralNode, isTypeOfExpression, isVariableDeclaration, +} from "../compiler/factory/nodeTests"; +import { timestamp } from "../compiler/performanceCore"; +import { getLineAndCharacterOfPosition, isIdentifierText, stringToToken, tokenToString } from "../compiler/scanner"; +import { isInitializedProperty } from "../compiler/transformers/utilities"; +import { + __String, BinaryExpression, BreakOrContinueStatement, CancellationToken, CharacterCodes, ClassElement, + CompilerOptions, ConstructorDeclaration, ContextFlags, Declaration, EmitHint, EmitTextWriter, Expression, + FunctionLikeDeclaration, Identifier, ImportDeclaration, ImportEqualsDeclaration, ImportOrExportSpecifier, + ImportSpecifier, ImportTypeNode, InternalSymbolName, JSDocParameterTag, JSDocPropertyTag, JSDocReturnTag, JSDocTag, + JSDocTemplateTag, JSDocTypedefTag, JSDocTypeExpression, JSDocTypeTag, JsxAttribute, JsxAttributes, + JsxClosingElement, JsxElement, JsxOpeningLikeElement, JsxSpreadAttribute, LanguageVariant, ListFormat, + MemberOverrideStatus, MethodDeclaration, ModifierFlags, ModifierSyntaxKind, ModuleDeclaration, ModuleReference, + NamedImportBindings, Node, NodeArray, NodeBuilderFlags, NodeFlags, ObjectBindingPattern, ObjectLiteralExpression, + ObjectType, ObjectTypeDeclaration, PrinterOptions, Program, PropertyAccessExpression, PropertyDeclaration, + PropertyName, PseudoBigInt, QualifiedName, ScriptTarget, SignatureKind, SnippetKind, SourceFile, SpreadAssignment, + Symbol, SymbolFlags, SymbolId, SyntaxKind, TextSpan, Token, TokenSyntaxKind, Type, TypeChecker, TypeElement, + TypeFlags, TypeLiteralNode, TypeOnlyAliasDeclaration, UnionReduction, UnionType, UserPreferences, + VariableDeclaration, +} from "../compiler/types"; +import { + addToSeen, compareNumberOfDirectorySeparators, escapeSnippetText, getAllSuperTypeNodes, getAncestor, + getCombinedLocalAndExportSymbolFlags, getContainingClass, getDeclarationModifierFlagsFromSymbol, + getEffectiveBaseTypeNode, getEffectiveModifierFlags, getEffectiveTypeAnnotationNode, getEmitModuleResolutionKind, + getEmitScriptTarget, getEscapedTextOfIdentifierOrLiteral, getLanguageVariant, getLeftmostAccessExpression, + getLocalSymbolForExportDefault, getNewLineCharacter, getPropertyNameForPropertyNameNode, getRootDeclaration, + getSourceFileOfModule, hasEffectiveModifier, isAbstractConstructorSymbol, isCheckJsEnabledForFile, + isContextualKeyword, isDeclarationName, isFunctionBlock, isInJSFile, isKeyword, isKnownSymbol, + isLiteralImportTypeNode, isNamedImportsOrExports, isObjectTypeDeclaration, isPartOfTypeNode, isPropertyNameLiteral, + isSingleOrDoubleQuote, isSourceFileJS, isStatic, isStringANonContextualKeyword, isValidTypeOnlyAliasUseSite, + isVariableLike, modifiersToFlags, modifierToFlag, nodeIsMissing, positionsAreOnSameLine, pseudoBigIntToString, + rangeIsOnSingleLine, skipAlias, stripQuotes, tryGetImportFromModuleSpecifier, typeHasCallOrConstructSignatures, + walkUpParenthesizedExpressions, +} from "../compiler/utilities"; +import { + createTextSpanFromBounds, findAncestor, getNameOfDeclaration, hasInitializer, hasType, isAssertionExpression, + isBindingPattern, isBreakOrContinueStatement, isClassElement, isClassLike, isClassMemberModifier, + isClassOrTypeElement, isEntityName, isExpression, isExternalModuleNameRelative, isFunctionLike, + isFunctionLikeDeclaration, isFunctionLikeKind, isJSDocTag, isJsxOpeningLikeElement, isMemberName, isModifier, + isModifierKind, isParameterPropertyModifier, isPrivateIdentifierClassElementDeclaration, isStatement, + isStringLiteralLike, isStringTextContainingNode, isTypeNode, isTypeOnlyImportOrExportDeclaration, + isTypeReferenceType, unescapeLeadingUnderscores, +} from "../compiler/utilitiesPublic"; +import { nodeCoreModules } from "../jsTyping/jsTyping"; +import { + addNewNodeForMemberSymbol, getNoopSymbolTrackerWithResolver, PreserveOptionalFlags, +} from "./codefixes/helpers"; +import { + createImportAdder, getImportCompletionAction, getImportKind, getModuleSpecifierForBestExportInfo, + getPromoteTypeOnlyCompletionAction, ImportAdder, +} from "./codefixes/importFixes"; +import { ExportKind, getExportInfoMap, ImportKind, isImportableFile, SymbolExportInfo } from "./exportInfoMap"; +import { FormatContext, formatNodeGivenIndentation } from "./formatting/formatting"; +import { + getJSDocParameterNameCompletionDetails, getJSDocParameterNameCompletions, getJSDocTagCompletionDetails, + getJSDocTagCompletions, getJSDocTagNameCompletionDetails, getJSDocTagNameCompletions, +} from "./jsDoc"; +import { getNameTable } from "./services"; +import { getArgumentInfoForCompletions } from "./signatureHelp"; +import { getStringLiteralCompletionDetails, getStringLiteralCompletions } from "./stringCompletions"; +import { getSymbolDisplayPartsDocumentationAndSymbolKind, getSymbolKind, getSymbolModifiers } from "./symbolDisplay"; +import { applyChanges, assignPositionsToNode, ChangeTracker, createWriter } from "./textChanges"; +import { + CodeAction, CompletionEntry, CompletionEntryData, CompletionEntryDataAutoImport, CompletionEntryDataResolved, + CompletionEntryDataUnresolved, CompletionEntryDetails, CompletionEntryLabelDetails, CompletionInfo, + CompletionInfoFlags, CompletionsTriggerCharacter, CompletionTriggerKind, IncompleteCompletionsCache, JSDocTagInfo, + LanguageServiceHost, ScriptElementKind, ScriptElementKindModifier, SymbolDisplayPart, SymbolDisplayPartKind, + TextChange, +} from "./types"; +import { + compilerOptionsIndicateEsModules, createModuleSpecifierResolutionHost, createPackageJsonImportFilter, + createTextRangeFromSpan, createTextSpanFromNode, diagnosticToString, displayPart, findChildOfKind, + findPrecedingToken, getContextualTypeFromParent, getFormatCodeSettingsForWriting, getLineStartPositionForPosition, + getNameForExportedSymbol, getNewLineKind, getQuotePreference, getReplacementSpanForContextToken, getSwitchedType, + getSynthesizedDeepClone, getTokenAtPosition, getTouchingPropertyName, hasDocComment, isDeprecatedDeclaration, + isEqualityOperatorKind, isExternalModuleSymbol, isInComment, isInRightSideOfInternalImportEqualsDeclaration, + isInString, isPossiblyTypeArgumentPosition, isStringLiteralOrTemplate, isTypeKeyword, + isTypeKeywordTokenOrIdentifier, moduleResolutionRespectsExports, positionBelongsToNode, positionIsASICandidate, + probablyUsesSemicolons, programContainsModules, quote, QuotePreference, rangeContainsPosition, + rangeContainsPositionExclusive, SemanticMeaning, shouldUseUriStyleNodeCoreModules, textPart, +} from "./utilities"; // Exported only for tests /* @internal */ @@ -84,7 +185,7 @@ interface SymbolOriginInfo { interface SymbolOriginInfoExport extends SymbolOriginInfo { symbolName: string; - moduleSymbol: ts.Symbol; + moduleSymbol: Symbol; isDefaultExport: boolean; exportName: string; exportMapKey: string; @@ -92,18 +193,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,36 +277,36 @@ 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, - program: ts.Program, - sourceFile: ts.SourceFile, + host: LanguageServiceHost, + program: Program, + sourceFile: SourceFile, position: number, - preferences: ts.UserPreferences, + preferences: UserPreferences, isForImportStatementCompletion: boolean, isValidTypeOnlyUseSite: boolean, cb: (context: ModuleSpecifierResolutioContext) => TReturn, ): TReturn { - const start = ts.timestamp(); - const packageJsonImportFilter = ts.createPackageJsonImportFilter(sourceFile, preferences, host); + const start = timestamp(); + const packageJsonImportFilter = createPackageJsonImportFilter(sourceFile, preferences, host); // 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; @@ -222,12 +323,12 @@ 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 = ts.codefix.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, sourceFile, program, host, preferences); + const result = getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, sourceFile, program, host, preferences); if (result) { ambientCount++; } @@ -236,7 +337,7 @@ function resolvingModuleSpecifiers( const shouldResolveModuleSpecifier = needsFullResolution || preferences.allowIncompleteCompletions && resolvedCount < moduleSpecifierResolutionLimit; const shouldGetModuleSpecifierFromCache = !shouldResolveModuleSpecifier && preferences.allowIncompleteCompletions && cacheAttemptCount < moduleSpecifierResolutionCacheAttemptLimit; const result = (shouldResolveModuleSpecifier || shouldGetModuleSpecifierFromCache) - ? ts.codefix.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, sourceFile, program, host, preferences, packageJsonImportFilter, shouldGetModuleSpecifierFromCache) + ? getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, sourceFile, program, host, preferences, packageJsonImportFilter, shouldGetModuleSpecifierFromCache) : undefined; if (!shouldResolveModuleSpecifier && !shouldGetModuleSpecifierFromCache || shouldGetModuleSpecifierFromCache && !result) { @@ -255,19 +356,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?: 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; } @@ -284,7 +385,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; @@ -294,13 +395,13 @@ export function getCompletionsAtPosition( incompleteCompletionsCache?.clear(); } - const stringCompletions = ts.Completions.StringCompletions.getStringLiteralCompletions(sourceFile, position, previousToken, compilerOptions, host, program, log, preferences); + const 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); } @@ -318,16 +419,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(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(getJSDocTagCompletions()); case CompletionDataKind.JsDocParameterName: - return jsdocCompletionInfo(ts.JsDoc.getJSDocParameterNameCompletions(completionData.tag)); + return jsdocCompletionInfo(getJSDocParameterNameCompletions(completionData.tag)); case CompletionDataKind.Keywords: return specificKeywordCompletionInfo(completionData.keywordCompletions, completionData.isNewIdentifierLocation); default: - return ts.Debug.assertNever(completionData); + return Debug.assertNever(completionData); } } @@ -338,43 +439,43 @@ 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, cancellationToken); + const exportMap = getExportInfoMap(file, host, program, cancellationToken); const newEntries = resolvingModuleSpecifiers( "continuePreviousIncompleteResponse", host, @@ -383,9 +484,9 @@ function continuePreviousIncompleteResponse( 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; @@ -395,10 +496,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}'`); @@ -414,7 +515,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; }); @@ -427,24 +528,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, @@ -461,29 +562,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: FormatContext | undefined, position: number -): ts.CompletionInfo | undefined { +): CompletionInfo | undefined { const { symbols, contextToken, @@ -507,14 +608,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(); if (isUncheckedFile(sourceFile, compilerOptions)) { const uniqueNames = getCompletionEntriesFromSymbols( @@ -526,7 +627,7 @@ function completionInfoFromData( sourceFile, host, program, - ts.getEmitScriptTarget(compilerOptions), + getEmitScriptTarget(compilerOptions), log, completionKind, preferences, @@ -543,7 +644,7 @@ function completionInfoFromData( isJsxIdentifierExpected, isRightOfOpenTag, ); - getJSCompletionEntries(sourceFile, location.pos, uniqueNames, ts.getEmitScriptTarget(compilerOptions), entries); + getJSCompletionEntries(sourceFile, location.pos, uniqueNames, getEmitScriptTarget(compilerOptions), entries); } else { if (!isNewIdentifierLocation && (!symbols || symbols.length === 0) && keywordFilters === KeywordCompletionFilters.None) { @@ -559,7 +660,7 @@ function completionInfoFromData( sourceFile, host, program, - ts.getEmitScriptTarget(compilerOptions), + getEmitScriptTarget(compilerOptions), log, completionKind, preferences, @@ -579,23 +680,23 @@ function completionInfoFromData( } if (keywordFilters !== KeywordCompletionFilters.None) { - const entryNames = new ts.Set(entries.map(e => e.name)); - for (const keywordEntry of getKeywordCompletions(keywordFilters, !insideJsDocTagTypeExpression && ts.isSourceFileJS(sourceFile))) { - if (isTypeOnlyLocation && ts.isTypeKeyword(ts.stringToToken(keywordEntry.name)!) || !entryNames.has(keywordEntry.name)) { - ts.insertSorted(entries, keywordEntry, compareCompletionEntries, /*allowDuplicates*/ true); + const entryNames = new Set(entries.map(e => e.name)); + for (const keywordEntry of getKeywordCompletions(keywordFilters, !insideJsDocTagTypeExpression && isSourceFileJS(sourceFile))) { + if (isTypeOnlyLocation && isTypeKeyword(stringToToken(keywordEntry.name)!) || !entryNames.has(keywordEntry.name)) { + insertSorted(entries, keywordEntry, compareCompletionEntries, /*allowDuplicates*/ true); } } } - const entryNames = new ts.Set(entries.map(e => e.name)); + const entryNames = new Set(entries.map(e => e.name)); for (const keywordEntry of getContextualKeywords(contextToken, position)) { if (!entryNames.has(keywordEntry.name)) { - ts.insertSorted(entries, keywordEntry, compareCompletionEntries, /*allowDuplicates*/ true); + insertSorted(entries, keywordEntry, compareCompletionEntries, /*allowDuplicates*/ true); } } for (const literal of literals) { - ts.insertSorted(entries, createCompletionEntryForLiteral(sourceFile, preferences, literal), compareCompletionEntries, /*allowDuplicates*/ true); + insertSorted(entries, createCompletionEntryForLiteral(sourceFile, preferences, literal), compareCompletionEntries, /*allowDuplicates*/ true); } return { @@ -609,8 +710,8 @@ function completionInfoFromData( }; } -function isUncheckedFile(sourceFile: ts.SourceFile, compilerOptions: ts.CompilerOptions): boolean { - return ts.isSourceFileJS(sourceFile) && !ts.isCheckJsEnabledForFile(sourceFile, compilerOptions); +function isUncheckedFile(sourceFile: SourceFile, compilerOptions: CompilerOptions): boolean { + return isSourceFileJS(sourceFile) && !isCheckJsEnabledForFile(sourceFile, compilerOptions); } function isMemberCompletionKind(kind: CompletionKind): boolean { @@ -624,21 +725,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, @@ -653,15 +754,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, }; @@ -671,22 +772,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 @@ -695,42 +796,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, - importCompletionNode: ts.Node | undefined, + importCompletionNode: Node | undefined, useSemicolons: boolean, - options: ts.CompilerOptions, - preferences: ts.UserPreferences, + options: CompilerOptions, + preferences: UserPreferences, completionKind: CompletionKind, - formatContext: ts.formatting.FormatContext | undefined, + formatContext: 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; @@ -753,38 +854,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 (importCompletionNode) { ({ insertText, replacementSpan } = getInsertTextAndReplacementSpanForImportCompletion(name, importCompletionNode, contextToken, origin, useSemicolons, options, preferences)); isSnippet = preferences.includeCompletionsWithSnippetText ? true : undefined; @@ -824,12 +925,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 { @@ -839,7 +940,7 @@ function createCompletionEntry( } if (useBraces) { - insertText = `${ts.escapeSnippetText(name)}={$1}`; + insertText = `${escapeSnippetText(name)}={$1}`; isSnippet = true; } } @@ -863,8 +964,8 @@ function createCompletionEntry( // entries (like JavaScript identifier entries). return { name, - kind: ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, location), - kindModifiers: ts.SymbolDisplay.getSymbolModifiers(typeChecker, symbol), + kind: getSymbolKind(typeChecker, symbol, location), + kindModifiers: getSymbolModifiers(typeChecker, symbol), sortText, source, hasAction: hasAction ? true : undefined, @@ -880,16 +981,16 @@ function createCompletionEntry( }; } -function isClassLikeMemberCompletion(symbol: ts.Symbol, location: ts.Node): boolean { +function isClassLikeMemberCompletion(symbol: Symbol, location: Node): 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 { | @@ -912,40 +1013,40 @@ function isClassLikeMemberCompletion(symbol: ts.Symbol, location: ts.Node): bool */ 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 && - 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: FormatContext | undefined, +): { insertText: string, isSnippet?: true, importAdder?: 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(); @@ -955,9 +1056,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 = createImportAdder(sourceFile, program, preferences, host); // Create empty body for possible method implementation. let body; @@ -966,21 +1067,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[] = []; + addNewNodeForMemberSymbol( symbol, classLikeDeclaration, sourceFile, @@ -995,13 +1096,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) { @@ -1011,29 +1112,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, + 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); } } @@ -1041,11 +1142,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; /* @@ -1068,36 +1169,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); - span = ts.createTextSpanFromNode(contextToken.parent); + if (isPropertyDeclaration(contextToken.parent)) { + modifiers |= modifiersToFlags(contextToken.parent.modifiers); + 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: FormatContext | undefined, +): { insertText: string, isSnippet?: true, labelDetails: CompletionEntryLabelDetails } | undefined { const isSnippet = preferences.includeCompletionsWithSnippetText || undefined; let insertText: string = name; @@ -1113,16 +1214,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, @@ -1130,49 +1231,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 = quotePreference === ts.QuotePreference.Single ? ts.NodeBuilderFlags.UseSingleQuotesForStringLiteralType : undefined; + const quotePreference = getQuotePreference(sourceFile, preferences); + const builderFlags = quotePreference === QuotePreference.Single ? NodeBuilderFlags.UseSingleQuotesForStringLiteralType : undefined; 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]; } @@ -1180,28 +1281,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, 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( /*decorators*/ undefined, /*modifiers*/ undefined, typedParam.dotDotDotToken, @@ -1210,7 +1311,7 @@ function createObjectLiteralMethod( /*type*/ undefined, typedParam.initializer, )); - return ts.factory.createMethodDeclaration( + return factory.createMethodDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*asteriskToken*/ undefined, @@ -1227,12 +1328,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 = createWriter(getNewLineCharacter(printerOptions)); + const printer = createPrinter(printerOptions, baseWriter); + const writer: EmitTextWriter = { ...baseWriter, write: s => escapingWrite(s, () => baseWriter.write(s)), nonEscapingWrite: baseWriter.write, @@ -1254,12 +1355,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(); @@ -1268,18 +1369,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 ? 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(); @@ -1288,10 +1389,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: FormatContext, ): string { const syntheticFile = { text: printUnescapedSnippetList( @@ -1299,14 +1400,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 = assignPositionsToNode(node); + return formatNodeGivenIndentation( nodeWithPos, syntheticFile, sourceFile.languageVariant, @@ -1316,17 +1417,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 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, @@ -1335,18 +1436,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 = { @@ -1374,45 +1475,45 @@ function completionEntryDataToSymbolOriginInfo(data: ts.CompletionEntryData, com return unresolvedOrigin; } -function getInsertTextAndReplacementSpanForImportCompletion(name: string, importCompletionNode: ts.Node, contextToken: ts.Node | undefined, origin: SymbolOriginInfoResolvedExport, useSemicolons: boolean, options: ts.CompilerOptions, preferences: ts.UserPreferences) { +function getInsertTextAndReplacementSpanForImportCompletion(name: string, importCompletionNode: Node, contextToken: Node | undefined, origin: SymbolOriginInfoResolvedExport, useSemicolons: boolean, options: CompilerOptions, preferences: UserPreferences) { const sourceFile = importCompletionNode.getSourceFile(); - const replacementSpan = ts.createTextSpanFromNode(ts.findAncestor(importCompletionNode, ts.or(ts.isImportDeclaration, ts.isImportEqualsDeclaration)) || importCompletionNode, sourceFile); - const quotedModuleSpecifier = ts.quote(sourceFile, preferences, origin.moduleSpecifier); + const replacementSpan = createTextSpanFromNode(findAncestor(importCompletionNode, or(isImportDeclaration, isImportEqualsDeclaration)) || importCompletionNode, sourceFile); + 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 isTopLevelTypeOnly = ts.tryCast(importCompletionNode, ts.isImportDeclaration)?.importClause?.isTypeOnly || ts.tryCast(importCompletionNode, ts.isImportEqualsDeclaration)?.isTypeOnly; + const importKind = getImportKind(sourceFile, exportKind, options, /*forceImportKeyword*/ true); + const isTopLevelTypeOnly = tryCast(importCompletionNode, isImportDeclaration)?.importClause?.isTypeOnly || tryCast(importCompletionNode, isImportEqualsDeclaration)?.isTypeOnly; const isImportSpecifierTypeOnly = couldBeTypeOnlyImportSpecifier(importCompletionNode, contextToken); - const topLevelTypeOnlyText = isTopLevelTypeOnly ? ` ${ts.tokenToString(ts.SyntaxKind.TypeKeyword)} ` : " "; - const importSpecifierTypeOnlyText = isImportSpecifierTypeOnly ? `${ts.tokenToString(ts.SyntaxKind.TypeKeyword)} ` : ""; + const topLevelTypeOnlyText = 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; @@ -1427,40 +1528,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: FormatContext | undefined, isTypeOnlyLocation?: boolean, - propertyAccessToConvert?: ts.PropertyAccessExpression, + propertyAccessToConvert?: PropertyAccessExpression, jsxIdentifierExpected?: boolean, isJsxInitializer?: IsJsxInitializer, - importCompletionNode?: ts.Node, - recommendedCompletion?: ts.Symbol, + importCompletionNode?: Node, + 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]; @@ -1470,7 +1571,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, @@ -1501,12 +1602,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 @@ -1516,11 +1617,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 @@ -1534,22 +1635,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) { @@ -1559,34 +1660,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 }); } @@ -1598,23 +1699,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) { @@ -1622,7 +1723,7 @@ function getSymbolCompletionFromEntryId( return { type: "symbol", symbol: autoImport.symbol, - location: ts.getTouchingPropertyName(sourceFile, position), + location: getTouchingPropertyName(sourceFile, position), previousToken, contextToken, isJsxInitializer: false, @@ -1643,19 +1744,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; @@ -1666,28 +1767,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: 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 getStringLiteralCompletionDetails(name, sourceFile, position, contextToken, typeChecker, compilerOptions, host, cancellationToken, preferences); } // Compute all the completion symbols again. @@ -1697,15 +1798,15 @@ export function getCompletionEntryDetails( const { request } = symbolCompletion; switch (request.kind) { case CompletionDataKind.JsDocTagName: - return ts.JsDoc.getJSDocTagNameCompletionDetails(name); + return getJSDocTagNameCompletionDetails(name); case CompletionDataKind.JsDocTag: - return ts.JsDoc.getJSDocTagCompletionDetails(name); + return getJSDocTagCompletionDetails(name); case CompletionDataKind.JsDocParameterName: - return ts.JsDoc.getJSDocParameterNameCompletionDetails(name); + return 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": { @@ -1715,59 +1816,59 @@ 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) + 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, 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: FormatContext, + preferences: UserPreferences, + data: CompletionEntryData | undefined, source: string | undefined, ): CodeActionsAndSourceDisplay { if (data?.moduleSpecifier) { if (previousToken && getImportStatementCompletionInfo(contextToken || previousToken).replacementNode) { // Import statement completion: 'import c|' - return { codeActions: undefined, sourceDisplay: [ts.textPart(data.moduleSpecifier)] }; + return { codeActions: undefined, sourceDisplay: [textPart(data.moduleSpecifier)] }; } } @@ -1783,21 +1884,21 @@ function getCompletionEntryCodeActionsAndSourceDisplay( contextToken, formatContext); if (importAdder) { - const changes = ts.textChanges.ChangeTracker.with( + const changes = 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 = getPromoteTypeOnlyCompletionAction( sourceFile, origin.declaration.name, program, @@ -1805,7 +1906,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 }; } @@ -1815,55 +1916,55 @@ 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 } = 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); - 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; @@ -1871,14 +1972,14 @@ interface CompletionData { /** In JSX tag name and attribute names, identifiers like "my-tag" or "aria-name" is valid identifier. */ readonly isJsxIdentifierExpected: boolean; readonly isRightOfOpenTag: boolean; - readonly importCompletionNode?: ts.Node; + readonly importCompletionNode?: Node; 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 { @@ -1890,91 +1991,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 = 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: FormatContext | undefined, + cancellationToken?: CancellationToken, ): CompletionData | Request | undefined { const typeChecker = program.getTypeChecker(); const inUncheckedFile = isUncheckedFile(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 }; @@ -1996,7 +2097,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 }; } @@ -2013,16 +2114,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 }; } } @@ -2035,31 +2136,31 @@ 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; let isStartingCloseTag = false; let isJsxInitializer: IsJsxInitializer = false; let isJsxIdentifierExpected = false; - let importCompletionNode: ts.Node | undefined; - let location = ts.getTouchingPropertyName(sourceFile, position); + let importCompletionNode: Node | undefined; + let location = getTouchingPropertyName(sourceFile, position); let keywordFilters = KeywordCompletionFilters.None; let isNewIdentifierLocation = false; - let flags = ts.CompletionInfoFlags.None; + let flags = CompletionInfoFlags.None; if (contextToken) { const importStatementCompletion = getImportStatementCompletionInfo(contextToken); @@ -2080,7 +2181,7 @@ function getCompletionData( // 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. importCompletionNode = importStatementCompletion.replacementNode; - flags |= ts.CompletionInfoFlags.IsImportStatementCompletion; + flags |= CompletionInfoFlags.IsImportStatementCompletion; } // Bail out if this is a known invalid completion location if (!importCompletionNode && isCompletionListBlocker(contextToken)) { @@ -2091,19 +2192,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 (./**/) {} @@ -2111,18 +2212,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 @@ -2130,11 +2231,11 @@ function getCompletionData( return undefined; } } - else if (!importCompletionNode && sourceFile.languageVariant === ts.LanguageVariant.JSX) { + else if (!importCompletionNode && sourceFile.languageVariant === LanguageVariant.JSX) { // // 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; } @@ -2142,14 +2243,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; @@ -2157,56 +2258,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; @@ -2214,18 +2315,18 @@ 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 symbols: Symbol[] = []; 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) { @@ -2233,13 +2334,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]; @@ -2258,12 +2359,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 { @@ -2291,27 +2392,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; } @@ -2321,28 +2422,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) : @@ -2356,7 +2457,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()) { @@ -2372,7 +2473,7 @@ function getCompletionData( } } } - addTypeProperties(type, !!(node.flags & ts.NodeFlags.AwaitContext), insertQuestionDot); + addTypeProperties(type, !!(node.flags & NodeFlags.AwaitContext), insertQuestionDot); } return; @@ -2401,24 +2502,24 @@ 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 (inUncheckedFile) { // In javascript files, for union types, we don't just get the members that // the individual types have in common, we also include all the members that // 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))); } else { for (const symbol of type.getApparentProperties()) { @@ -2440,36 +2541,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 } = ts.codefix.getModuleSpecifierForBestExportInfo([{ - exportKind: ts.ExportKind.Named, + const fileName = isExternalModuleNameRelative(stripQuotes(moduleSymbol.name)) ? getSourceFileOfModule(moduleSymbol)?.fileName : undefined; + const { moduleSpecifier } = getModuleSpecifierForBestExportInfo([{ + exportKind: ExportKind.Named, moduleFileName: fileName, isFromPackageJson: false, moduleSymbol, symbol: firstAccessibleSymbol, - targetFlags: ts.skipAlias(firstAccessibleSymbol, typeChecker).flags, - }], firstAccessibleSymbol.name, position, ts.isValidTypeOnlyAliasUseSite(location), sourceFile, program, host, preferences) || {}; + targetFlags: skipAlias(firstAccessibleSymbol, typeChecker).flags, + }], firstAccessibleSymbol.name, position, isValidTypeOnlyAliasUseSite(location), sourceFile, program, host, preferences) || {}; if (moduleSpecifier) { const origin: SymbolOriginInfoResolvedExport = { @@ -2497,15 +2598,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) { @@ -2520,8 +2621,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 { @@ -2553,8 +2654,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; @@ -2576,7 +2677,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' @@ -2610,19 +2711,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; @@ -2631,19 +2732,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) { + if (preferences.includeCompletionsWithInsertText && scopeNode.kind !== SyntaxKind.SourceFile) { const thisType = typeChecker.tryGetThisTypeAt(scopeNode, /*includeGlobalThis*/ false); 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; } @@ -2659,62 +2760,62 @@ 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 - || !!importCompletionNode && ts.isTypeOnlyImportOrExportDeclaration(location.parent) + || !!importCompletionNode && 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; } } return false; @@ -2723,13 +2824,13 @@ 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 && importCompletionNode @@ -2737,13 +2838,13 @@ function getCompletionData( 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, cancellationToken); + const exportInfo = getExportInfoMap(sourceFile, host, program, 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, @@ -2752,25 +2853,25 @@ function getCompletionData( position, preferences, !!importCompletionNode, - 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 && !importCompletionNode && !(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 && !importCompletionNode && !(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; } @@ -2779,7 +2880,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; } @@ -2802,15 +2903,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, @@ -2820,23 +2921,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 (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, @@ -2847,8 +2948,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; @@ -2859,9 +2960,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 => { @@ -2870,7 +2971,7 @@ function getCompletionData( } const displayName = getCompletionEntryDisplayNameForSymbol( member, - ts.getEmitScriptTarget(compilerOptions), + getEmitScriptTarget(compilerOptions), /*origin*/ undefined, CompletionKind.ObjectPropertyDeclaration, /*jsxIdentifierExpected*/ false); @@ -2891,13 +2992,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 = { @@ -2907,7 +3008,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; @@ -2917,50 +3018,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; @@ -2972,55 +3073,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)) { @@ -3031,21 +3132,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); @@ -3056,10 +3157,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; @@ -3081,21 +3182,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; @@ -3111,25 +3212,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) { @@ -3144,10 +3245,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); @@ -3176,21 +3277,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) { @@ -3201,9 +3302,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; @@ -3221,21 +3322,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; @@ -3253,151 +3354,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; @@ -3409,96 +3510,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 @@ -3512,8 +3613,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; } @@ -3521,71 +3622,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) === "."; } @@ -3593,9 +3694,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); } /** @@ -3604,22 +3705,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; } @@ -3628,14 +3729,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; } } @@ -3643,8 +3744,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) { @@ -3658,11 +3759,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); @@ -3673,21 +3774,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; } } } @@ -3695,9 +3796,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, @@ -3717,14 +3818,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; } @@ -3734,16 +3835,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); } @@ -3752,8 +3853,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))); } /** @@ -3762,19 +3863,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); } } @@ -3785,7 +3886,7 @@ function getCompletionData( return filteredSymbols; } - function isCurrentlyEditingNode(node: ts.Node): boolean { + function isCurrentlyEditingNode(node: Node): boolean { return node.getStart(sourceFile) <= position && position <= node.getEnd(); } } @@ -3794,20 +3895,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; } } @@ -3815,30 +3916,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) }; } @@ -3847,8 +3948,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, @@ -3857,14 +3958,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) { @@ -3876,54 +3977,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: @@ -3931,88 +4032,88 @@ 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.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.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 - || !ts.isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind); +function isFunctionLikeBodyKeyword(kind: SyntaxKind) { + return kind === SyntaxKind.AsyncKeyword + || kind === SyntaxKind.AwaitKeyword + || kind === SyntaxKind.AsKeyword + || !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: @@ -4027,13 +4128,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, }); } @@ -4042,81 +4143,81 @@ 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: { + case SyntaxKind.Identifier: { // 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); } } } @@ -4124,54 +4225,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; @@ -4180,10 +4281,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); } @@ -4191,21 +4292,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 "@": @@ -4214,61 +4315,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); } @@ -4277,47 +4378,47 @@ function tryGetObjectLiteralContextualType(node: ts.ObjectLiteralExpression, typ interface ImportStatementCompletionInfo { isKeywordOnlyCompletion: boolean; - keywordCompletion: ts.TokenSyntaxKind | undefined; + keywordCompletion: TokenSyntaxKind | undefined; isNewIdentifierLocation: boolean; - replacementNode: ts.ImportEqualsDeclaration | ts.ImportDeclaration | ts.ImportSpecifier | ts.Token | undefined; + replacementNode: ImportEqualsDeclaration | ImportDeclaration | ImportSpecifier | Token | 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), - replacementNode: candidate && ts.rangeIsOnSingleLine(candidate, candidate.getSourceFile()) + isNewIdentifierLocation: !!(candidate || keywordCompletion === SyntaxKind.TypeKeyword), + replacementNode: candidate && rangeIsOnSingleLine(candidate, candidate.getSourceFile()) ? candidate : undefined }; 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; @@ -4325,65 +4426,65 @@ 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 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) { return isModuleSpecifierMissingOrEmpty(namedBindings.parent.parent.moduleSpecifier) - && (ts.isNamespaceImport(namedBindings) || namedBindings.elements.length < 2) + && (isNamespaceImport(namedBindings) || namedBindings.elements.length < 2) && !namedBindings.parent.name; } -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); } /** @@ -4417,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++; } @@ -4434,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..0238cd424b636 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -1,16 +1,44 @@ -import * as ts from "./_namespaces/ts"; +import { + arrayFrom, arrayToMultiMap, cast, concatenate, contains, createGetCanonicalFileName, find, forEach, mapDefined, + toArray, +} from "../compiler/core"; +import { Push, Set } from "../compiler/corePublic"; +import { Debug } from "../compiler/debug"; +import { + isAwaitExpression, isBlock, isCaseClause, isClassDeclaration, isConstructorDeclaration, isDefaultClause, + isIfStatement, isInterfaceDeclaration, isJsxClosingElement, isJsxOpeningElement, isLabeledStatement, + isModuleDeclaration, isReturnStatement, isSwitchStatement, isThrowStatement, isTryStatement, isTypeAliasDeclaration, + isVariableStatement, isYieldExpression, +} from "../compiler/factory/nodeTests"; +import { forEachChild } from "../compiler/parser"; +import { toPath } from "../compiler/path"; +import { isWhiteSpaceSingleLine } from "../compiler/scanner"; +import { + __String, Block, BreakOrContinueStatement, CancellationToken, CaseClause, ConstructorDeclaration, DefaultClause, + FunctionDeclaration, FunctionLikeDeclaration, IfStatement, IterationStatement, MethodDeclaration, Modifier, + ModifierFlags, ModuleBlock, Node, ObjectLiteralExpression, ObjectTypeDeclaration, Program, ReturnStatement, + SourceFile, SwitchStatement, SyntaxKind, ThrowStatement, TryStatement, +} from "../compiler/types"; +import { forEachReturnStatement, getContainingFunction, isFunctionBlock, modifierToFlag } from "../compiler/utilities"; +import { + createTextSpanFromBounds, findAncestor, isAccessor, isBreakOrContinueStatement, isClassLike, isDeclaration, + isFunctionLike, isIterationStatement, isModifierKind, isTypeNode, +} from "../compiler/utilitiesPublic"; +import { getReferenceEntriesForNode, toHighlightSpan } from "./findAllReferences"; +import { HighlightSpan, HighlightSpanKind } from "./types"; +import { createTextSpanFromNode, findChildOfKind, findModifier, getTouchingPropertyName } from "./utilities"; 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 +48,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 = 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(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 +148,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 +167,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 +189,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 +293,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 +338,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 +357,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 +443,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 +463,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 +485,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 +494,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 +509,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 +543,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 1f11c9429e5c2..2dc2d26fe35b2 100644 --- a/src/services/documentRegistry.ts +++ b/src/services/documentRegistry.ts @@ -1,4 +1,22 @@ +import { sourceFileAffectingCompilerOptions } from "../compiler/commandLineParser"; +import { + arrayFrom, createGetCanonicalFileName, firstDefinedIterator, getOrUpdate, identity, isArray, map, +} from "../compiler/core"; +import { ESMap, Map } from "../compiler/corePublic"; +import { Debug } from "../compiler/debug"; +import { CreateSourceFileOptions, isDeclarationFileName } from "../compiler/parser"; +import { toPath } from "../compiler/path"; +import { getImpliedNodeFormatForFile } from "../compiler/program"; +import { tracing } from "../compiler/tracing"; +import { + CompilerOptions, MinimalResolutionCacheHost, Path, ScriptKind, ScriptTarget, SourceFile, +} from "../compiler/types"; +import { + ensureScriptKind, forEachEntry, getCompilerOptionValue, getEmitScriptTarget, getSetExternalModuleIndicator, +} from "../compiler/utilities"; import * as ts from "./_namespaces/ts"; +import { createLanguageServiceSourceFile, updateLanguageServiceSourceFile } from "./services"; +import { IScriptSnapshot } from "./types"; /** * The document registry represents a store of SourceFile objects that can be shared between @@ -35,19 +53,19 @@ export interface DocumentRegistry { */ acquireDocument( fileName: string, - compilationSettingsOrHost: ts.CompilerOptions | ts.MinimalResolutionCacheHost, - scriptSnapshot: ts.IScriptSnapshot, + compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, + scriptSnapshot: IScriptSnapshot, version: string, - scriptKind?: ts.ScriptKind): ts.SourceFile; + scriptKind?: ScriptKind): 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): ts.SourceFile; + scriptKind?: ScriptKind): SourceFile; /** * Request an updated version of an already existing SourceFile with a given fileName @@ -66,21 +84,21 @@ export interface DocumentRegistry { */ updateDocument( fileName: string, - compilationSettingsOrHost: ts.CompilerOptions | ts.MinimalResolutionCacheHost, - scriptSnapshot: ts.IScriptSnapshot, + compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, + scriptSnapshot: IScriptSnapshot, version: string, - scriptKind?: ts.ScriptKind): ts.SourceFile; + scriptKind?: ScriptKind): 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): ts.SourceFile; + scriptKind?: ScriptKind): SourceFile; - getKeyForCompilationSettings(settings: ts.CompilerOptions): DocumentRegistryBucketKey; + getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey; /** * Informs the DocumentRegistry that a file is not needed any longer. * @@ -91,7 +109,7 @@ export interface DocumentRegistry { * @param compilationSettings The compilation settings used to acquire the file */ /**@deprecated pass scriptKind for correctness */ - releaseDocument(fileName: string, compilationSettings: ts.CompilerOptions): void; + releaseDocument(fileName: string, compilationSettings: CompilerOptions): void; /** * Informs the DocumentRegistry that a file is not needed any longer. * @@ -102,28 +120,28 @@ export interface DocumentRegistry { * @param compilationSettings The compilation settings used to acquire the file * @param scriptKind The script kind of the file to be released */ - releaseDocument(fileName: string, compilationSettings: ts.CompilerOptions, scriptKind: ts.ScriptKind): void; // eslint-disable-line @typescript-eslint/unified-signatures + releaseDocument(fileName: string, compilationSettings: CompilerOptions, scriptKind: ScriptKind): void; // eslint-disable-line @typescript-eslint/unified-signatures /** * @deprecated pass scriptKind for correctness */ - releaseDocumentWithKey(path: ts.Path, key: DocumentRegistryBucketKey): void; - releaseDocumentWithKey(path: ts.Path, key: DocumentRegistryBucketKey, scriptKind: ts.ScriptKind): void; // eslint-disable-line @typescript-eslint/unified-signatures + releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey): void; + releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey, scriptKind: ScriptKind): 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: DocumentRegistryBucketKey, path: ts.Path, sourceFile: ts.SourceFile): void; - getDocument(key: DocumentRegistryBucketKey, path: ts.Path): ts.SourceFile | undefined; + setDocument(key: DocumentRegistryBucketKey, path: Path, sourceFile: SourceFile): void; + getDocument(key: DocumentRegistryBucketKey, 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 @@ -131,7 +149,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; } @@ -144,13 +162,13 @@ export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, curr 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({ @@ -172,75 +190,75 @@ 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): ts.SourceFile { - const path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); + function acquireDocument(fileName: string, compilationSettings: CompilerOptions | MinimalResolutionCacheHost, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile { + const path = toPath(fileName, currentDirectory, getCanonicalFileName); const key = getKeyForCompilationSettings(getCompilationSettings(compilationSettings)); return acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind); } - function acquireDocumentWithKey(fileName: string, path: ts.Path, compilationSettings: ts.CompilerOptions | ts.MinimalResolutionCacheHost, key: DocumentRegistryBucketKey, scriptSnapshot: ts.IScriptSnapshot, version: string, scriptKind?: ts.ScriptKind): ts.SourceFile { + function acquireDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions | MinimalResolutionCacheHost, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile { return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ true, scriptKind); } - function updateDocument(fileName: string, compilationSettings: ts.CompilerOptions | ts.MinimalResolutionCacheHost, scriptSnapshot: ts.IScriptSnapshot, version: string, scriptKind?: ts.ScriptKind): ts.SourceFile { - const path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); + function updateDocument(fileName: string, compilationSettings: CompilerOptions | MinimalResolutionCacheHost, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile { + const path = toPath(fileName, currentDirectory, getCanonicalFileName); const key = getKeyForCompilationSettings(getCompilationSettings(compilationSettings)); return updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind); } - function updateDocumentWithKey(fileName: string, path: ts.Path, compilationSettings: ts.CompilerOptions | ts.MinimalResolutionCacheHost, key: DocumentRegistryBucketKey, scriptSnapshot: ts.IScriptSnapshot, version: string, scriptKind?: ts.ScriptKind): ts.SourceFile { + function updateDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions | MinimalResolutionCacheHost, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile { return acquireOrUpdateDocument(fileName, path, getCompilationSettings(compilationSettings), key, scriptSnapshot, version, /*acquiring*/ false, scriptKind); } - 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): ts.SourceFile { - scriptKind = ts.ensureScriptKind(fileName, scriptKind); + scriptKind?: ScriptKind): 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 = { + const host: MinimalResolutionCacheHost | undefined = compilationSettingsOrHost === compilationSettings ? undefined : compilationSettingsOrHost as MinimalResolutionCacheHost; + const scriptTarget = scriptKind === ScriptKind.JSON ? ScriptTarget.JSON : getEmitScriptTarget(compilationSettings); + const sourceFileOptions: CreateSourceFileOptions = { 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) }; const oldBucketCount = buckets.size; - const bucket = ts.getOrUpdate(buckets, key, () => new ts.Map()); - if (ts.tracing) { + const bucket = getOrUpdate(buckets, key, () => 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 }); + tracing.instant(tracing.Phase.Session, "createdDocumentRegistryBucket", { configFilePath: compilationSettings.configFilePath, key }); } // 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 !== key && bucket.has(path) && bucketKey); + const otherBucketKey = !isDeclarationFileName(path) && + forEachEntry(buckets, (bucket, bucketKey) => bucketKey !== key && bucket.has(path) && bucketKey); if (otherBucketKey) { - ts.tracing.instant(ts.tracing.Phase.Session, "documentRegistryBucketOverlap", { path, key1: otherBucketKey, key2: key }); + tracing.instant(tracing.Phase.Session, "documentRegistryBucketOverlap", { path, key1: otherBucketKey, key2: key }); } } @@ -249,7 +267,7 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole if (!entry && externalCache) { const sourceFile = externalCache.getDocument(key, path); if (sourceFile) { - ts.Debug.assert(acquiring); + Debug.assert(acquiring); entry = { sourceFile, languageServiceRefCount: 0 @@ -260,7 +278,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(key, path, sourceFile); } @@ -275,7 +293,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(key, path, entry.sourceFile); @@ -291,7 +309,7 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole entry.languageServiceRefCount++; } } - ts.Debug.assert(entry.languageServiceRefCount !== 0); + Debug.assert(entry.languageServiceRefCount !== 0); return entry.sourceFile; @@ -300,7 +318,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); @@ -311,19 +329,19 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole } } - function releaseDocument(fileName: string, compilationSettings: ts.CompilerOptions, scriptKind?: ts.ScriptKind): void { - const path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); + function releaseDocument(fileName: string, compilationSettings: CompilerOptions, scriptKind?: ScriptKind): void { + const path = toPath(fileName, currentDirectory, getCanonicalFileName); const key = getKeyForCompilationSettings(compilationSettings); return releaseDocumentWithKey(path, key, scriptKind); } - function releaseDocumentWithKey(path: ts.Path, key: DocumentRegistryBucketKey, scriptKind?: ts.ScriptKind): void { - const bucket = ts.Debug.checkDefined(buckets.get(key)); + function releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey, scriptKind?: ScriptKind): void { + const bucket = Debug.checkDefined(buckets.get(key)); 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); @@ -331,14 +349,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]; @@ -362,8 +380,8 @@ 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) { @@ -374,6 +392,6 @@ function compilerOptionValueToString(value: unknown): string { 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; } diff --git a/src/services/exportInfoMap.ts b/src/services/exportInfoMap.ts index 60680dba04efe..fa3da91a7271f 100644 --- a/src/services/exportInfoMap.ts +++ b/src/services/exportInfoMap.ts @@ -1,4 +1,34 @@ -import * as ts from "./_namespaces/ts"; +import { getSymbolId } from "../compiler/checker"; +import { + arrayIsEqualTo, createMultiMap, emptyArray, findIndex, firstDefined, GetCanonicalFileName, startsWith, + stringContains, tryCast, +} from "../compiler/core"; +import { Map } from "../compiler/corePublic"; +import { Debug } from "../compiler/debug"; +import { isExportAssignment, isExportSpecifier, isIdentifier } from "../compiler/factory/nodeTests"; +import { skipOuterExpressions } from "../compiler/factory/utilities"; +import { + getPackageNameFromTypesPackageName, nodeModulesPathPart, unmangleScopedPackageName, +} from "../compiler/moduleNameResolver"; +import { forEachFileNameOfModule } from "../compiler/moduleSpecifiers"; +import { forEachAncestorDirectory, getBaseFileName, getDirectoryPath } from "../compiler/path"; +import { timestamp } from "../compiler/performanceCore"; +import { + __String, CancellationToken, CompilerOptions, InternalSymbolName, ModuleSpecifierCache, + ModuleSpecifierResolutionHost, Path, Program, SourceFile, Statement, Symbol, SymbolFlags, TypeChecker, + UserPreferences, +} from "../compiler/types"; +import { + addToSeen, getLocalSymbolForExportDefault, getNodeModulePathParts, hostGetCanonicalFileName, + isExternalOrCommonJsModule, isKnownSymbol, isNonGlobalAmbientModule, isPrivateIdentifierSymbol, skipAlias, + stripQuotes, +} from "../compiler/utilities"; +import { isExternalModuleNameRelative, unescapeLeadingUnderscores } from "../compiler/utilitiesPublic"; +import { LanguageServiceHost } from "./types"; +import { + consumesNodeCoreModules, getNameForExportedSymbol, getNamesForExportedSymbol, isExternalModuleSymbol, + PackageJsonImportFilter, +} from "./utilities"; /* @internal */ export const enum ImportKind { @@ -18,12 +48,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 +63,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) => void): void; + 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) => void): void; 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 +112,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 +130,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 +151,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 +159,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, @@ -181,7 +211,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; @@ -190,11 +220,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(); @@ -204,7 +234,7 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): return false; }, }; - if (ts.Debug.isDebugging) { + if (Debug.isDebugging) { Object.defineProperty(cache, "__cache", { get: () => exportInfo }); } return cache; @@ -212,7 +242,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, @@ -226,12 +256,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 { @@ -244,9 +274,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) { @@ -256,20 +286,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; } @@ -280,21 +310,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, {}); @@ -302,9 +332,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 = !!forEachFileNameOfModule( from.fileName, to.fileName, moduleSpecifierResolutionHost, @@ -331,47 +361,47 @@ 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, + program: Program, + host: LanguageServiceHost, 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, ) { forEachExternalModule(program.getTypeChecker(), program.getSourceFiles(), (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(), (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[], cb: (module: ts.Symbol, sourceFile: ts.SourceFile | undefined) => void) { +function forEachExternalModule(checker: TypeChecker, allSourceFiles: readonly SourceFile[], cb: (module: Symbol, sourceFile: SourceFile | undefined) => void) { for (const ambient of checker.getAmbientModules()) { - if (!ts.stringContains(ambient.name, "*")) { + if (!stringContains(ambient.name, "*")) { cb(ambient, /*sourceFile*/ undefined); } } for (const sourceFile of allSourceFiles) { - if (ts.isExternalOrCommonJsModule(sourceFile)) { + if (isExternalOrCommonJsModule(sourceFile)) { cb(checker.getMergedSymbol(sourceFile.symbol), sourceFile); } } } /* @internal */ -export function getExportInfoMap(importingFile: ts.SourceFile, host: ts.LanguageServiceHost, program: ts.Program, cancellationToken: ts.CancellationToken | undefined): ExportInfoMap { - const start = ts.timestamp(); +export function getExportInfoMap(importingFile: SourceFile, host: LanguageServiceHost, program: Program, 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. @@ -393,7 +423,7 @@ export function getExportInfoMap(importingFile: ts.SourceFile, host: ts.Language try { forEachExternalModuleToImportFrom(program, host, /*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 @@ -402,7 +432,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, @@ -410,7 +440,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, @@ -430,12 +460,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; @@ -443,25 +473,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, @@ -472,20 +502,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 8b792d1be5172..7f4101cad44cb 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -1,4 +1,76 @@ -import * as ts from "./_namespaces/ts"; +import { getNodeId, getSymbolId } from "../compiler/checker"; +import { + append, cast, compareValues, contains, emptyArray, filter, find, findIndex, first, firstDefined, firstOrUndefined, + flatMap, map, mapDefined, MultiMap, some, tryAddToSet, tryCast, +} from "../compiler/core"; +import { ESMap, Map, Push, ReadonlySet, Set } from "../compiler/corePublic"; +import { Debug } from "../compiler/debug"; +import { + isBinaryExpression, isBindingElement, isCallExpression, isCatchClause, isClassStaticBlockDeclaration, + isComputedPropertyName, isConstructorDeclaration, isExportAssignment, isExportSpecifier, isExpressionStatement, + isExpressionWithTypeArguments, isFunctionExpression, isIdentifier, isImportSpecifier, isImportTypeNode, + isInterfaceDeclaration, isJSDocMemberName, isJsxClosingElement, isJsxOpeningElement, isJsxSelfClosingElement, + isLabeledStatement, isLiteralTypeNode, isModuleDeclaration, isNamespaceExportDeclaration, + isNoSubstitutionTemplateLiteral, isObjectLiteralExpression, isParameter, isPropertyAccessExpression, + isQualifiedName, isShorthandPropertyAssignment, isSourceFile, isStaticModifier, isTypeAliasDeclaration, + isTypeLiteralNode, isTypeOperatorNode, isUnionTypeNode, isVariableDeclarationList, isVariableStatement, + isVoidExpression, +} from "../compiler/factory/nodeTests"; +import { forEachChild, isExternalModule } from "../compiler/parser"; +import { + getModeForUsageLocation, getReferencedFileLocation, isReferencedFile, isReferenceFileLocation, +} from "../compiler/program"; +import { isIdentifierPart, tokenToString } from "../compiler/scanner"; +import { + __String, AssignmentDeclarationKind, BinaryExpression, BindingElement, Block, CallExpression, CancellationToken, + CheckFlags, ClassLikeDeclaration, ConstructorDeclaration, Declaration, ExportSpecifier, Expression, + FileIncludeReason, FileReference, ForInOrOfStatement, FunctionDeclaration, FunctionExpression, + FunctionLikeDeclaration, GetAccessorDeclaration, Identifier, InterfaceDeclaration, InternalSymbolName, JSDocTag, + MethodDeclaration, ModifierFlags, ModuleDeclaration, NamedDeclaration, Node, NodeFlags, NumericLiteral, + ParameterDeclaration, ParenthesizedExpression, Path, PrivateIdentifier, Program, PropertyAccessExpression, + PropertyAssignment, PropertyDeclaration, ScriptTarget, SetAccessorDeclaration, SignatureDeclaration, SourceFile, + Statement, StringLiteral, StringLiteralLike, Symbol, SymbolFlags, SymbolId, SyntaxKind, TextSpan, TypeChecker, + VariableDeclaration, +} from "../compiler/types"; +import { + addToSeen, forEachReturnStatement, getAllSuperTypeNodes, getAncestor, getAssignmentDeclarationKind, getCheckFlags, + getDeclarationFromName, getDeclarationOfKind, getEffectiveModifierFlags, getLocalSymbolForExportDefault, + getNextJSDocCommentLocation, getSuperContainer, getSyntacticModifierFlags, getTextOfNode, getThisContainer, + hasEffectiveModifier, hasSyntacticModifier, isAccessExpression, isBindableObjectDefinePropertyCall, + isDeclarationName, isExternalOrCommonJsModule, isImportMeta, isInJSFile, isLiteralComputedPropertyDeclarationName, + isModuleExportsAccessExpression, isObjectLiteralMethod, isStatic, isSuperProperty, + isVariableDeclarationInitializedToBareOrAccessedRequire, isVariableLike, isWriteAccess, rangeIsOnSingleLine, + skipAlias, stripQuotes, tryGetClassExtendingExpressionWithTypeArguments, tryGetImportFromModuleSpecifier, +} from "../compiler/utilities"; +import { + createTextSpan, createTextSpanFromBounds, escapeLeadingUnderscores, findAncestor, getNameOfDeclaration, + hasInitializer, hasType, isAssertionExpression, isBreakOrContinueStatement, isClassLike, isDeclaration, + isForInOrOfStatement, isFunctionLike, isFunctionLikeDeclaration, isImportOrExportSpecifier, isJSDocTag, + isMethodOrAccessor, isModuleOrEnumDeclaration, isParameterPropertyDeclaration, + isPrivateIdentifierClassElementDeclaration, isStatement, isStringLiteralLike, isTypeElement, isTypeNode, symbolName, +} from "../compiler/utilitiesPublic"; +import { getReferenceAtPosition } from "./goToDefinition"; +import { + createImportTracker, ExportInfo, ExportKind, findModuleReferences, getExportInfo, getImportOrExportSymbol, + ImportExport, ImportsResult, ImportTracker, ModuleReference, +} from "./importTracker"; +import { getContainingObjectLiteralElement, getNameTable, getPropertySymbolsFromContextualType } from "./services"; +import { getSymbolDisplayPartsDocumentationAndSymbolKind } from "./symbolDisplay"; +import { + DocumentSpan, emptyOptions, HighlightSpan, HighlightSpanKind, ImplementationLocation, ReferencedSymbol, + ReferencedSymbolDefinitionInfo, ReferencedSymbolEntry, ReferenceEntry, RenameLocation, ScriptElementKind, + SymbolDisplayPart, SymbolDisplayPartKind, +} from "./types"; +import { + climbPastPropertyAccess, createTextSpanFromRange, displayPart, findChildOfKind, getAdjustedReferenceLocation, + getAdjustedRenameLocation, getContainerNode, getContextualTypeFromParentOrAncestorTypeNode, + getMeaningFromDeclaration, getMeaningFromLocation, getNodeKind, getPropertySymbolFromBindingElement, getTargetLabel, + getTouchingPropertyName, isArrayLiteralOrObjectLiteralDestructuringPattern, isCallExpressionTarget, + isExpressionOfExternalModuleImportEqualsDeclaration, isExternalModuleSymbol, isInNonReferenceComment, isInString, + isJumpStatementTarget, isLabelOfLabeledStatement, isLiteralNameOfPropertyDeclarationOrIndexAccess, + isModuleSpecifierLike, isNameOfModuleDeclaration, isNewExpressionTarget, isObjectBindingElementWithoutPropertyName, + isRightSideOfPropertyAccess, isThis, isTypeKeyword, nodeSeenTracker, punctuationPart, SemanticMeaning, textPart, +} from "./utilities"; /* @internal */ export interface SymbolAndEntries { @@ -10,12 +82,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 +97,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 +195,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 +249,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 +293,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 +309,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 { const queue = entries && [...entries]; - const seenNodes = new ts.Map(); + const seenNodes = new Map(); while (queue && queue.length) { const entry = queue.shift() 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.push(...entries); @@ -274,23 +346,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 +376,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 +421,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 && 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 +471,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); + 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 +502,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 +515,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 +531,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 +551,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 +562,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 +575,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 +588,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,20 +655,20 @@ 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); } /** Whether a reference, `node`, is a definition of the `target` symbol */ -function isDeclarationOfSymbol(node: ts.Node, target: ts.Symbol | undefined): boolean { +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)); } @@ -604,60 +676,60 @@ function isDeclarationOfSymbol(node: ts.Node, target: ts.Symbol | undefined): bo * 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); } } @@ -665,10 +737,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 = getReferenceAtPosition(node, position, program); if (!resolvedRef?.file) { return undefined; } @@ -682,7 +754,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 }]; } @@ -695,18 +767,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 @@ -717,12 +789,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; } @@ -734,38 +806,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) }); } } @@ -773,8 +845,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) { @@ -784,23 +856,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; @@ -814,7 +886,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) { @@ -829,14 +901,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); }) }; } @@ -844,21 +916,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; } @@ -870,7 +942,7 @@ export namespace Core { return { kind: EntryKind.Span, fileName: reference.referencingFile.fileName, - textSpan: ts.createTextSpanFromRange(reference.ref), + textSpan: createTextSpanFromRange(reference.ref), }; } }); @@ -878,56 +950,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 @@ -936,34 +1008,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); } @@ -971,22 +1043,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] }); @@ -996,12 +1068,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 @@ -1012,14 +1084,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 @@ -1029,20 +1101,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; }); @@ -1054,20 +1126,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 { @@ -1076,9 +1148,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; } @@ -1088,7 +1160,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: @@ -1097,7 +1169,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. @@ -1110,43 +1182,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[][] = []; @@ -1154,8 +1226,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] = []; @@ -1165,7 +1237,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 }] @@ -1173,22 +1245,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. @@ -1201,20 +1273,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) { @@ -1226,22 +1298,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); } } @@ -1249,44 +1321,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; } @@ -1298,11 +1370,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; } @@ -1311,10 +1383,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; @@ -1322,7 +1394,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; } @@ -1333,29 +1405,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; } } @@ -1370,32 +1442,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; } @@ -1404,12 +1476,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; @@ -1417,20 +1489,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)) { @@ -1442,11 +1514,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 @@ -1470,8 +1542,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); } @@ -1481,36 +1553,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: @@ -1518,12 +1590,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); } }); @@ -1531,10 +1603,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); } @@ -1543,7 +1615,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); } @@ -1553,7 +1625,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; } @@ -1563,23 +1635,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; @@ -1593,14 +1665,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; } @@ -1621,13 +1693,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)) { + if (isInJSFile(referenceLocation) + && referenceLocation.parent.kind === SyntaxKind.BindingElement + && isVariableDeclarationInitializedToBareOrAccessedRequire(referenceLocation.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. @@ -1638,15 +1710,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; @@ -1657,7 +1729,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(); } } @@ -1669,7 +1741,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 { @@ -1680,18 +1752,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); } @@ -1701,13 +1773,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; @@ -1719,13 +1791,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); } @@ -1735,9 +1807,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 @@ -1745,16 +1817,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 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; } @@ -1768,15 +1840,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()); } @@ -1790,22 +1862,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); } }); @@ -1817,12 +1889,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); } } @@ -1830,11 +1902,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); } }); @@ -1844,23 +1916,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); } }); @@ -1868,29 +1940,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); } @@ -1904,16 +1976,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); }); } @@ -1921,33 +1993,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; @@ -1973,12 +2045,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; @@ -1988,7 +2060,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); })); @@ -1996,23 +2068,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: @@ -2020,56 +2092,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. @@ -2077,53 +2149,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); } } @@ -2138,8 +2210,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. @@ -2159,14 +2231,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 @@ -2189,8 +2261,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; @@ -2215,14 +2287,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) { @@ -2234,9 +2306,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); @@ -2244,7 +2316,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; @@ -2254,25 +2326,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); } } } @@ -2285,38 +2357,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, @@ -2330,7 +2402,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 => @@ -2346,11 +2418,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 @@ -2361,7 +2433,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; @@ -2373,28 +2445,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); } @@ -2403,8 +2475,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); } /** @@ -2413,11 +2485,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 01e580e504acd..0ffad167e47fe 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -1,19 +1,47 @@ -import * as ts from "../_namespaces/ts"; +import { concatenate, find, forEachRight } from "../../compiler/core"; +import { Debug } from "../../compiler/debug"; +import { isJSDoc } from "../../compiler/factory/nodeTests"; +import { forEachChild } from "../../compiler/parser"; +import { getTrailingCommentRanges, isLineBreak, isWhiteSpaceSingleLine } from "../../compiler/scanner"; +import { + Block, CallExpression, CatchClause, CharacterCodes, CommentRange, Declaration, Diagnostic, FunctionDeclaration, + InterfaceDeclaration, LanguageVariant, LineAndCharacter, MethodDeclaration, ModuleDeclaration, Node, NodeArray, + SourceFile, SourceFileLike, SyntaxKind, TextRange, TriviaSyntaxKind, TypeReferenceNode, +} from "../../compiler/types"; +import { + getEndLinePosition, getLeadingCommentRangesOfNode, getNonDecoratorTokenPosOfNode, getStartPositionOfLine, + nodeIsMissing, +} from "../../compiler/utilities"; +import { + findAncestor, getNameOfDeclaration, isCallLikeExpression, isNodeArray, isToken, +} from "../../compiler/utilitiesPublic"; +import { EditorSettings, FormatCodeSettings, FormattingHost, TextChange } from "../types"; +import { + createTextChangeFromStartLength, findPrecedingToken, getLineStartPositionForPosition, getNewLineOrDefaultFromHost, + getTokenAtPosition, isComment, isStringOrRegularExpressionOrTemplateLiteral, rangeContainsPositionExclusive, + rangeContainsRange, rangeContainsStartEnd, rangeOverlapsWithStartEnd, repeatString, startEndContainsRange, + startEndOverlapsWithStartEnd, +} from "../utilities"; +import { FormattingContext, FormattingRequestKind } from "./formattingContext"; +import { FormattingScanner, getFormattingScanner } from "./formattingScanner"; +import { Rule, RuleAction, RuleFlags } from "./rule"; +import { RulesMap } from "./rulesMap"; +import { SmartIndenter } from "./smartIndenter"; /* @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 +51,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 +76,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 +104,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 +118,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 +164,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 +222,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 +236,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 +276,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 +307,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 +326,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 +362,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 +383,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 +421,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,26 +431,26 @@ 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 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(); @@ -430,14 +458,14 @@ function formatSpanWorker( const startLine = sourceFile.getLineAndCharacterOfPosition(enclosingNode.getStart(sourceFile)).line; let undecoratedStartLine = startLine; if (enclosingNode.decorators) { - undecoratedStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(enclosingNode, sourceFile)).line; + 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(); @@ -457,7 +485,7 @@ function formatSpanWorker( undefined; if (tokenInfo) { - 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, @@ -484,11 +512,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; @@ -496,12 +524,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; } } @@ -513,11 +541,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 @@ -529,15 +557,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 }; } @@ -550,33 +578,33 @@ function formatSpanWorker( } } - function getFirstNonDecoratorTokenOfNode(node: ts.Node) { + function getFirstNonDecoratorTokenOfNode(node: Node) { if (node.modifiers && node.modifiers.length) { return node.modifiers[0].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) { @@ -584,9 +612,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; @@ -606,36 +634,36 @@ 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 ts.SyntaxKind.ExpressionWithTypeArguments: + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxClosingElement: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.ExpressionWithTypeArguments: 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; @@ -648,12 +676,12 @@ function formatSpanWorker( 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; } @@ -675,7 +703,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); @@ -694,16 +722,16 @@ 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 { - if (ts.nodeIsMissing(child)) { + if (nodeIsMissing(child)) { return inheritedIndentation; } @@ -713,13 +741,13 @@ function formatSpanWorker( let undecoratedChildStartLine = childStartLine; if (child.decorators) { - undecoratedChildStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(child, sourceFile)).line; + 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; @@ -727,7 +755,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); } @@ -759,50 +787,50 @@ 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)); + Debug.assert(isNodeArray(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); @@ -825,8 +853,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 @@ -845,9 +873,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 && ts.isCallLikeExpression(parent)) { + if (tokenInfo.token.kind === SyntaxKind.CommaToken && isCallLikeExpression(parent)) { const commaTokenLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line; if (startLine !== commaTokenLine) { formattingScanner.advance(); @@ -859,15 +887,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; @@ -877,7 +905,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) { @@ -935,21 +963,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; } @@ -957,9 +985,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); } @@ -967,9 +995,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); @@ -995,11 +1023,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); @@ -1011,7 +1039,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) { @@ -1031,16 +1059,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) { @@ -1060,7 +1088,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); } @@ -1070,7 +1098,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 { @@ -1084,7 +1112,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; @@ -1096,12 +1124,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) { @@ -1110,10 +1138,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) { @@ -1124,11 +1152,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); @@ -1142,17 +1170,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); } } @@ -1164,7 +1192,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) { @@ -1177,10 +1205,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); } @@ -1203,23 +1231,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, @@ -1227,47 +1255,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; @@ -1281,12 +1309,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()) { @@ -1294,14 +1322,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): // @@ -1315,56 +1343,56 @@ 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: - 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: + 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.TypeReference: - if ((node as ts.TypeReferenceNode).typeArguments === list) { - return ts.SyntaxKind.LessThanToken; + case SyntaxKind.TypeReference: + 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; }; @@ -1372,7 +1400,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); @@ -1392,13 +1420,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; @@ -1409,13 +1437,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 91eaf1b34d97a..305221f9c73d4 100644 --- a/src/services/formatting/formattingContext.ts +++ b/src/services/formatting/formattingContext.ts @@ -1,4 +1,8 @@ -import * as ts from "../_namespaces/ts"; +import { Debug } from "../../compiler/debug"; +import { Node, SourceFileLike, SyntaxKind } from "../../compiler/types"; +import { FormatCodeSettings } from "../types"; +import { findChildOfKind } from "../utilities"; +import { TextRangeWithKind } from "./formatting"; /* @internal */ export const enum FormattingRequestKind { @@ -12,11 +16,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 +28,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 +88,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 2824d74f2b940..36a4555c6c128 100644 --- a/src/services/formatting/formattingScanner.ts +++ b/src/services/formatting/formattingScanner.ts @@ -1,7 +1,14 @@ -import * as ts from "../_namespaces/ts"; - -const standardScanner = ts.createScanner(ts.ScriptTarget.Latest, /*skipTrivia*/ false, ts.LanguageVariant.Standard); -const jsxScanner = ts.createScanner(ts.ScriptTarget.Latest, /*skipTrivia*/ false, ts.LanguageVariant.JSX); +import { append, last } from "../../compiler/core"; +import { Debug } from "../../compiler/debug"; +import { isJsxAttribute, isJsxText } from "../../compiler/factory/nodeTests"; +import { createScanner } from "../../compiler/scanner"; +import { LanguageVariant, Node, NodeArray, ScriptTarget, SyntaxKind } from "../../compiler/types"; +import { isKeyword, isTrivia } from "../../compiler/utilities"; +import { isToken } from "../../compiler/utilitiesPublic"; +import { createTextRangeWithKind, TextRangeWithKind, TextRangeWithTriviaKind, TokenInfo } from "./formatting"; + +const standardScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, LanguageVariant.Standard); +const jsxScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, LanguageVariant.JSX); /* @internal */ export interface FormattingScanner { @@ -9,12 +16,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 +35,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 +72,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 +86,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 +100,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); + function shouldRescanJsxText(node: Node): boolean { + return isJsxText(node); } - 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 +179,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 +187,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 +199,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 +214,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 +226,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 +242,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 +264,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 +305,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 7677710bcb0ff..2840551b4aa29 100644 --- a/src/services/formatting/rule.ts +++ b/src/services/formatting/rule.ts @@ -1,4 +1,6 @@ -import * as ts from "../_namespaces/ts"; +import { emptyArray } from "../../compiler/core"; +import { SyntaxKind } from "../../compiler/types"; +import { FormattingContext } from "./formattingContext"; /* @internal */ export interface Rule { @@ -10,9 +12,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 +39,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 3fc858034d84b..cdf1e6b65b876 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -1,358 +1,367 @@ -import * as ts from "../_namespaces/ts"; +import { contains, isArray } from "../../compiler/core"; +import { isPropertyDeclaration, isPropertySignature } from "../../compiler/factory/nodeTests"; +import { BinaryExpression, Node, SyntaxKind, YieldExpression } from "../../compiler/types"; +import { isExpressionNode, isTrivia } from "../../compiler/utilities"; +import { findAncestor, isFunctionLikeKind } from "../../compiler/utilitiesPublic"; +import { FormatCodeSettings, SemicolonPreference } from "../types"; +import { findNextToken, positionIsASICandidate, typeKeywords } from "../utilities"; +import { TextRangeWithKind } from "./formatting"; +import { FormattingContext, FormattingRequestKind } from "./formattingContext"; +import { anyContext, ContextPredicate, Rule, RuleAction, RuleFlags, TokenRange } from "./rule"; /* @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], 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], 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.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.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 [ @@ -376,27 +385,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); } } @@ -407,226 +416,226 @@ 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 { +function isOptionEnabled(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { return (context) => context.options && context.options.hasOwnProperty(optionName) && !!context.options[optionName]; } -function isOptionDisabled(optionName: keyof ts.FormatCodeSettings): (context: ts.formatting.FormattingContext) => boolean { +function isOptionDisabled(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { return (context) => context.options && context.options.hasOwnProperty(optionName) && !context.options[optionName]; } -function isOptionDisabledOrUndefined(optionName: keyof ts.FormatCodeSettings): (context: ts.formatting.FormattingContext) => boolean { +function isOptionDisabledOrUndefined(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { return (context) => !context.options || !context.options.hasOwnProperty(optionName) || !context.options[optionName]; } -function isOptionDisabledOrUndefinedOrTokensOnSameLine(optionName: keyof ts.FormatCodeSettings): (context: ts.formatting.FormattingContext) => boolean { +function isOptionDisabledOrUndefinedOrTokensOnSameLine(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { return (context) => !context.options || !context.options.hasOwnProperty(optionName) || !context.options[optionName] || context.TokensAreOnSameLine(); } -function isOptionEnabledOrUndefined(optionName: keyof ts.FormatCodeSettings): (context: ts.formatting.FormattingContext) => boolean { +function isOptionEnabledOrUndefined(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { return (context) => !context.options || !context.options.hasOwnProperty(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 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: 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; } } @@ -634,21 +643,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: @@ -656,130 +665,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() && !!context.contextNode.decorators && nodeIsInDecoratorContext(context.currentTokenParent) && !nodeIsInDecoratorContext(context.nextTokenParent); } -function nodeIsInDecoratorContext(node: ts.Node): boolean { - while (ts.isExpressionNode(node)) { +function nodeIsInDecoratorContext(node: Node): boolean { + while (isExpressionNode(node)) { node = node.parent; } - return node.kind === ts.SyntaxKind.Decorator; + return 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; @@ -787,39 +796,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: @@ -827,14 +836,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) { @@ -847,18 +856,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: // @@ -866,31 +875,31 @@ 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); + 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); } diff --git a/src/services/formatting/rulesMap.ts b/src/services/formatting/rulesMap.ts index bd5c261bbdc29..256d950d8122e 100644 --- a/src/services/formatting/rulesMap.ts +++ b/src/services/formatting/rulesMap.ts @@ -1,7 +1,14 @@ -import * as ts from "../_namespaces/ts"; +import { every } from "../../compiler/core"; +import { Debug } from "../../compiler/debug"; +import { SyntaxKind } from "../../compiler/types"; +import { FormatCodeSettings, FormattingHost } from "../types"; +import { FormatContext } from "./formatting"; +import { FormattingContext } from "./formattingContext"; +import { anyContext, Rule, RuleAction } from "./rule"; +import { getAllRules, RuleSpec } from "./rules"; /* @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 +16,7 @@ let rulesMapCache: RulesMap | undefined; function getRulesMap(): RulesMap { if (rulesMapCache === undefined) { - rulesMapCache = createRulesMap(ts.formatting.getAllRules()); + rulesMapCache = createRulesMap(getAllRules()); } return rulesMapCache; } @@ -18,35 +25,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 +65,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 +88,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 +120,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 +143,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 dcb2fd9db384c..9b0b506080375 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -1,4 +1,25 @@ -import * as ts from "../_namespaces/ts"; +import { contains, find } from "../../compiler/core"; +import { Debug } from "../../compiler/debug"; +import { isCallExpression, isConditionalExpression } from "../../compiler/factory/nodeTests"; +import { + getLineAndCharacterOfPosition, isWhiteSpaceLike, isWhiteSpaceSingleLine, skipTrivia, +} from "../../compiler/scanner"; +import { + ArrayBindingPattern, ArrayLiteralExpression, CallExpression, CharacterCodes, ClassDeclaration, ClassExpression, + CommentRange, GetAccessorDeclaration, IfStatement, ImportClause, InterfaceDeclaration, JSDocTemplateTag, + LineAndCharacter, NamedImportsOrExports, Node, NodeArray, ObjectBindingPattern, ObjectLiteralExpression, + SignatureDeclaration, SourceFile, SourceFileLike, SyntaxKind, TextRange, TypeAliasDeclaration, TypeLiteralNode, + TypeReferenceNode, VariableDeclarationList, +} from "../../compiler/types"; +import { getStartPositionOfLine } from "../../compiler/utilities"; +import { isCallOrNewExpression, isDeclaration, isStatementButNotDeclaration } from "../../compiler/utilitiesPublic"; +import { EditorSettings, FormatCodeSettings, IndentStyle } from "../types"; +import { + findChildOfKind, findListItemInfo, findNextToken, findPrecedingToken, getLineStartPositionForPosition, + getTokenAtPosition, isStringOrRegularExpressionOrTemplateLiteral, positionBelongsToNode, rangeContainsRange, + rangeContainsStartEnd, +} from "../utilities"; +import { getRangeOfEnclosingComment, TextRangeWithKind } from "./formatting"; /* @internal */ export namespace SmartIndenter { @@ -22,22 +43,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 +67,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 +77,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 +98,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 +113,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 +122,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 +140,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 +192,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 +283,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 +292,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 +307,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 +334,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 +361,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 +408,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 +423,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 +450,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 +514,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 +540,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 +562,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 +574,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 +595,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 +701,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 +717,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 dcfa4e80fa9c0..8ce8e62ba584f 100644 --- a/src/services/getEditsForFileRename.ts +++ b/src/services/getEditsForFileRename.ts @@ -1,20 +1,48 @@ -import * as ts from "./_namespaces/ts"; +import { getOptionFromName } from "../compiler/commandLineParser"; +import { + createGetCanonicalFileName, emptyArray, endsWith, find, forEach, GetCanonicalFileName, last, mapDefined, +} from "../compiler/core"; +import { Debug } from "../compiler/debug"; +import { factory } from "../compiler/factory/nodeFactory"; +import { + isArrayLiteralExpression, isObjectLiteralExpression, isPropertyAssignment, isSourceFile, isStringLiteral, +} from "../compiler/factory/nodeTests"; +import { resolveModuleName } from "../compiler/moduleNameResolver"; +import { updateModuleSpecifier } from "../compiler/moduleSpecifiers"; +import { + combinePaths, ensurePathIsNonModuleName, getDirectoryPath, getRelativePathFromDirectory, getRelativePathFromFile, + normalizePath, pathIsRelative, +} from "../compiler/path"; +import { getModeForUsageLocation } from "../compiler/program"; +import { + Expression, ModuleResolutionHost, Path, Program, PropertyAssignment, ResolvedModuleWithFailedLookupLocations, + SourceFile, SourceFileLike, StringLiteralLike, Symbol, TextRange, UserPreferences, +} from "../compiler/types"; +import { + createRange, getFileMatcherPatterns, getRegexFromPattern, getTsConfigObjectLiteralExpression, + hostUsesCaseSensitiveFileNames, isAmbientModule, tryRemoveDirectoryPrefix, +} from "../compiler/utilities"; +import { FormatContext } from "./formatting/formatting"; +import { SourceMapper } from "./sourcemaps"; +import { ChangeTracker } from "./textChanges"; +import { FileTextChanges, LanguageServiceHost } from "./types"; +import { createModuleSpecifierResolutionHost } from "./utilities"; /* @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: 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 ChangeTracker.with({ host, formatContext, preferences }, changeTracker => { updateTsconfigFiles(program, changeTracker, oldToNew, oldFileOrDirPath, newFileOrDirPath, host.getCurrentDirectory(), useCaseSensitiveFileNames); updateImports(program, changeTracker, oldToNew, newToOld, host, getCanonicalFileName); }); @@ -24,7 +52,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 +64,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: 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 +89,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 +119,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 +128,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 +141,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: 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))) + ? 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 +205,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 +227,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 +239,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 +250,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 +264,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: 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 +276,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 982f39b82e1fd..f3abf6e812b16 100644 --- a/src/services/globalThisShim.ts +++ b/src/services/globalThisShim.ts @@ -1,4 +1,5 @@ -import * as ts from "./_namespaces/ts"; +import { versionMajorMinor } from "../compiler/corePublic"; +import { TypeScriptServicesFactory } from "./shims"; // 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,13 +56,13 @@ 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; } export { }; diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 48fa49da29e3c..de60863d68457 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -1,15 +1,50 @@ -import * as ts from "./_namespaces/ts"; +import { + concatenate, emptyArray, every, filter, find, first, flatMap, forEach, last, map, mapDefined, some, tryCast, +} from "../compiler/core"; +import { Debug } from "../compiler/debug"; +import { + isBindingElement, isClassStaticBlockDeclaration, isConstructorDeclaration, isFunctionTypeNode, isJSDocOverrideTag, + isObjectBindingPattern, isStaticModifier, isVariableDeclaration, +} from "../compiler/factory/nodeTests"; +import { isDeclarationFileName } from "../compiler/parser"; +import { getDirectoryPath, resolvePath } from "../compiler/path"; +import { getModeForUsageLocation } from "../compiler/program"; +import { skipTrivia } from "../compiler/scanner"; +import { + AssignmentDeclarationKind, AssignmentExpression, AssignmentOperatorToken, CallLikeExpression, Declaration, + FileReference, FunctionLikeDeclaration, ModifierFlags, Node, NodeFlags, Program, SignatureDeclaration, SourceFile, + Symbol, SymbolFlags, SyntaxKind, TextSpan, Type, TypeChecker, TypeFlags, +} from "../compiler/types"; +import { + getAssignmentDeclarationKind, getEffectiveBaseTypeNode, getInvokedExpression, getTextOfPropertyName, + hasEffectiveModifier, hasStaticModifier, isAnyImportOrBareOrAccessedRequire, isAssignmentDeclaration, + isAssignmentExpression, isImportMeta, moveRangePastModifiers, skipAlias, tryGetModuleSpecifierFromDeclaration, +} from "../compiler/utilities"; +import { + createTextSpan, createTextSpanFromBounds, findAncestor, getNameOfDeclaration, hasInitializer, isCallLikeExpression, + isClassElement, isClassLike, isExternalModuleNameRelative, isFunctionLike, isJsxOpeningLikeElement, isPropertyName, + textRangeContainsPositionInclusive, unescapeLeadingUnderscores, +} from "../compiler/utilitiesPublic"; +import { getContextNode, toContextSpan } from "./findAllReferences"; +import { getContainingObjectLiteralElement, getPropertySymbolsFromContextualType } from "./services"; +import { getSymbolKind } from "./symbolDisplay"; +import { DefinitionInfo, DefinitionInfoAndBoundSpan, ScriptElementKind } from "./types"; +import { + createTextSpanFromNode, createTextSpanFromRange, getNameFromPropertyName, getTargetLabel, getTouchingPropertyName, + getTouchingToken, isCallOrNewExpressionTarget, isJumpStatementTarget, isModuleSpecifierLike, + isNameOfFunctionDeclaration, isNewExpressionTarget, isRightSideOfPropertyAccess, rangeContainsPosition, +} from "./utilities"; /* @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,27 +52,27 @@ export function getDefinitionAtPosition(program: ts.Program, sourceFile: ts.Sour const { parent } = node; const typeChecker = program.getTypeChecker(); - if (node.kind === ts.SyntaxKind.OverrideKeyword || (ts.isJSDocOverrideTag(node) && ts.rangeContainsPosition(node.tagName, position))) { - return getDefinitionFromOverriddenMember(typeChecker, node) || ts.emptyArray; + if (node.kind === SyntaxKind.OverrideKeyword || (isJSDocOverrideTag(node) && rangeContainsPosition(node.tagName, position))) { + 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 (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 }); }); } @@ -46,28 +81,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, }]; } @@ -76,14 +111,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. @@ -91,9 +126,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]; } } @@ -102,10 +137,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 @@ -119,17 +154,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)); } /** @@ -137,11 +172,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 @@ -153,30 +188,30 @@ 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); const baseType = baseTypeNode ? typeChecker.getTypeAtLocation(baseTypeNode) : undefined; if (!baseType) 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.getTypeOfSymbolAtLocation(baseType.symbol, baseDeclaration), name) : typeChecker.getPropertyOfType(baseType, name); if (!symbol) return; @@ -185,7 +220,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); @@ -206,10 +241,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, @@ -228,13 +263,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); } @@ -247,29 +282,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) { @@ -282,28 +317,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 }; @@ -320,14 +355,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; @@ -350,68 +385,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 = 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, @@ -420,63 +455,63 @@ function createDefinitionInfoFromName(checker: ts.TypeChecker, declaration: ts.D name: symbolName, containerKind: undefined!, // TODO: GH#18217 containerName, - ...ts.FindAllReferences.toContextSpan( + ...toContextSpan( textSpan, sourceFile, - ts.FindAllReferences.getContextNode(declaration) + 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 @@ -485,24 +520,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 a530ecf080ff3..b6bdb7812eb3a 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -1,22 +1,45 @@ -import * as ts from "./_namespaces/ts"; +import { getSymbolId } from "../compiler/checker"; +import { cast, forEach, some } from "../compiler/core"; +import { ESMap, Map, ReadonlySet } from "../compiler/corePublic"; +import { Debug } from "../compiler/debug"; +import { + isBinaryExpression, isBindingElement, isCatchClause, isExportAssignment, isExportDeclaration, isExportSpecifier, + isImportEqualsDeclaration, isImportTypeNode, isJSDocTypedefTag, isNamedExports, isNamespaceExport, + isPrivateIdentifier, isPropertyAccessExpression, isShorthandPropertyAssignment, isSourceFile, isStringLiteral, + isVariableDeclaration, isVariableStatement, +} from "../compiler/factory/nodeTests"; +import { + __String, AnyImportOrReExport, AssignmentDeclarationKind, BinaryExpression, BindingElement, CallExpression, + CancellationToken, ExportAssignment, ExportDeclaration, FileReference, Identifier, ImportCall, ImportClause, + ImportDeclaration, ImportEqualsDeclaration, ImportSpecifier, InternalSymbolName, ModifierFlags, ModuleBlock, + ModuleDeclaration, NamedImportsOrExports, NamespaceImport, Node, Program, SourceFile, Statement, StringLiteral, + StringLiteralLike, Symbol, SymbolFlags, SyntaxKind, TypeChecker, ValidImportTypeNode, VariableDeclaration, +} from "../compiler/types"; +import { + getAssignmentDeclarationKind, getFirstIdentifier, getNameOfAccessExpression, getSourceFileOfNode, + hasSyntacticModifier, importFromModuleSpecifier, isAccessExpression, isDefaultImport, isExternalModuleAugmentation, + isImportCall, isInJSFile, isModuleExportsAccessExpression, isVariableDeclarationInitializedToBareOrAccessedRequire, +} from "../compiler/utilities"; +import { findAncestor, symbolName, walkUpBindingElementsAndPatterns } from "../compiler/utilitiesPublic"; +import { isExternalModuleSymbol, nodeSeenTracker, symbolEscapedNameNoDefault } from "./utilities"; /* 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 +50,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 +60,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 +85,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 +94,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 +115,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 +132,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 +165,7 @@ function getImportersForExport( } break; - case ts.SyntaxKind.ImportType: + case SyntaxKind.ImportType: // Only check for typeof import('xyz') if (direct.isTypeOf && !direct.qualifier && isExported(direct)) { addIndirectUser(direct.getSourceFile(), /** addTransitiveDependencies */ true); @@ -151,32 +174,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.some(node.modifiers, mod => mod.kind === ts.SyntaxKind.ExportKeyword); + return some(node.modifiers, mod => mod.kind === SyntaxKind.ExportKeyword); }); } - 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 +211,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 +219,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 +240,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 +256,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 +282,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 +297,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 +325,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 +354,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 +362,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 +383,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 +400,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 +417,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 +439,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 +478,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 +495,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 +515,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 +529,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); } } @@ -572,97 +595,97 @@ 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 { - if (importedSymbol.flags & ts.SymbolFlags.Alias) { - return ts.Debug.checkDefined(checker.getImmediateAliasedSymbol(importedSymbol)); +function getExportEqualsLocalSymbol(importedSymbol: Symbol, checker: TypeChecker): Symbol { + if (importedSymbol.flags & SymbolFlags.Alias) { + return Debug.checkDefined(checker.getImmediateAliasedSymbol(importedSymbol)); } - const decl = ts.Debug.checkDefined(importedSymbol.valueDeclaration); - if (ts.isExportAssignment(decl)) { // `export = class {}` - return ts.Debug.checkDefined(decl.expression.symbol); + const decl = Debug.checkDefined(importedSymbol.valueDeclaration); + if (isExportAssignment(decl)) { // `export = class {}` + return Debug.checkDefined(decl.expression.symbol); } - else if (ts.isBinaryExpression(decl)) { // `module.exports = class {}` - return ts.Debug.checkDefined(decl.right.symbol); + else if (isBinaryExpression(decl)) { // `module.exports = class {}` + return Debug.checkDefined(decl.right.symbol); } - else if (ts.isSourceFile(decl)) { // json module - return ts.Debug.checkDefined(decl.symbol); + else if (isSourceFile(decl)) { // json module + return Debug.checkDefined(decl.symbol); } - return ts.Debug.fail(); + return Debug.fail(); } // 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); + case SyntaxKind.BindingElement: + return isInJSFile(node) && isVariableDeclarationInitializedToBareOrAccessedRequire(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)!; } } @@ -670,27 +693,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 9e8020c5e842e..3f3150c9c3925 100644 --- a/src/services/inlayHints.ts +++ b/src/services/inlayHints.ts @@ -1,4 +1,29 @@ -import * as ts from "./_namespaces/ts"; +import { some } from "../compiler/core"; +import { Debug } from "../compiler/debug"; +import { createPrinter } from "../compiler/emitter"; +import { + isArrowFunction, isCallExpression, isEnumMember, isFunctionDeclaration, isFunctionExpression, + isGetAccessorDeclaration, isIdentifier, isMethodDeclaration, isNewExpression, isParameter, + isPropertyAccessExpression, isPropertyDeclaration, isVariableDeclaration, +} from "../compiler/factory/nodeTests"; +import { forEachChild } from "../compiler/parser"; +import { getLeadingCommentRanges, isIdentifierText } from "../compiler/scanner"; +import { + __String, ArrowFunction, CallExpression, EmitHint, EnumMember, Expression, FunctionDeclaration, FunctionExpression, + FunctionLikeDeclaration, GetAccessorDeclaration, Identifier, MethodDeclaration, NewExpression, Node, + NodeBuilderFlags, PrefixUnaryExpression, PrinterOptions, PropertyDeclaration, Signature, Symbol, SymbolFlags, + SyntaxKind, Type, TypeFormatFlags, UserPreferences, VariableDeclaration, +} from "../compiler/types"; +import { + getEffectiveReturnTypeNode, getEffectiveTypeAnnotationNode, getLanguageVariant, hasContextSensitiveParameters, + isInfinityOrNaNString, skipParentheses, usingSingleLineStringWriter, +} from "../compiler/utilities"; +import { + isBindingPattern, isFunctionLikeDeclaration, isLiteralExpression, isTypeNode, textSpanIntersectsWith, + unescapeLeadingUnderscores, +} from "../compiler/utilitiesPublic"; +import { InlayHint, InlayHintKind, InlayHintsContext } from "./types"; +import { findChildOfKind } from "./utilities"; const maxHintsLength = 30; @@ -6,83 +31,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)) { + if (isTypeNode(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 +116,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 +125,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 +141,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)) { + function visitVariableLikeDeclaration(decl: VariableDeclaration | PropertyDeclaration) { + if (!decl.initializer || isBindingPattern(decl.name)) { return; } - const effectiveTypeAnnotation = ts.getEffectiveTypeAnnotationNode(decl); + const effectiveTypeAnnotation = getEffectiveTypeAnnotationNode(decl); if (effectiveTypeAnnotation) { return; } @@ -141,13 +166,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; @@ -155,7 +180,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; } @@ -168,7 +193,7 @@ export function provideInlayHints(context: ts.InlayHintsContext): ts.InlayHint[] continue; } - const name = ts.unescapeLeadingUnderscores(parameterName); + const name = unescapeLeadingUnderscores(parameterName); if (leadingCommentsContainsParameterName(arg, name)) { continue; } @@ -178,58 +203,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; } @@ -252,15 +277,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; @@ -268,7 +293,7 @@ export function provideInlayHints(context: ts.InlayHintsContext): ts.InlayHint[] for (let i = 0; i < node.parameters.length && i < signature.parameters.length; ++i) { const param = node.parameters[i]; - const effectiveTypeAnnotation = ts.getEffectiveTypeAnnotationNode(param); + const effectiveTypeAnnotation = getEffectiveTypeAnnotationNode(param); if (effectiveTypeAnnotation) { continue; @@ -283,9 +308,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; } @@ -304,19 +329,19 @@ 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"; } } diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index f5d79530284a7..7b90bc81e1130 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -1,4 +1,35 @@ -import * as ts from "./_namespaces/ts"; +import { + arraysEqual, contains, emptyArray, find, flatMap, flatten, forEach, intersperse, lastOrUndefined, length, map, + mapDefined, startsWith, +} from "../compiler/core"; +import { + isArrowFunction, isBlock, isConstructorDeclaration, isFunctionExpression, isIdentifier, isJSDoc, + isJSDocParameterTag, +} from "../compiler/factory/nodeTests"; +import { isWhiteSpaceSingleLine } from "../compiler/scanner"; +import { + ArrowFunction, AssignmentDeclarationKind, BinaryExpression, ClassExpression, ConstructorDeclaration, Declaration, + Expression, ExpressionStatement, FunctionDeclaration, FunctionExpression, JSDoc, JSDocAugmentsTag, JSDocCallbackTag, + JSDocComment, JSDocImplementsTag, JSDocParameterTag, JSDocPropertyTag, JSDocSeeTag, JSDocTag, JSDocTemplateTag, + JSDocTypedefTag, JSDocTypeTag, MethodDeclaration, MethodSignature, Node, ParameterDeclaration, + ParenthesizedExpression, PropertyAssignment, PropertyDeclaration, SourceFile, SyntaxKind, TypeChecker, + VariableStatement, +} from "../compiler/types"; +import { + forEachAncestor, forEachReturnStatement, getAssignmentDeclarationKind, getJSDocCommentsAndTags, hasJSFileExtension, +} from "../compiler/utilities"; +import { + findAncestor, getJSDocTags, hasJSDocNodes, isExpression, isFunctionLike, isFunctionLikeDeclaration, +} from "../compiler/utilitiesPublic"; +import { SortText } from "./completions"; +import { + CompletionEntry, CompletionEntryDetails, DocCommentTemplateOptions, JSDocTagInfo, ScriptElementKind, + SymbolDisplayPart, TextInsertion, +} from "./types"; +import { + buildLinkParts, forEachUnique, getLineStartPositionForPosition, getTokenAtPosition, lineBreakPart, + parameterNamePart, propertyNamePart, punctuationPart, spacePart, textPart, typeAliasNamePart, typeParameterNamePart, +} from "./utilities"; const jsDocTagNames = [ "abstract", @@ -80,73 +111,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 +187,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 +242,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: SortText.LocationPriority, }; })); } @@ -262,61 +293,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: 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: 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 +377,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,13 +397,13 @@ export function getDocCommentTemplateAtPosition(newLine: string, sourceFile: ts. } const { commentOwner, parameters, hasReturn } = commentOwnerInfo; - const commentOwnerJSDoc = ts.hasJSDocNodes(commentOwner) && commentOwner.jsDoc ? ts.lastOrUndefined(commentOwner.jsDoc) : undefined; + const commentOwnerJSDoc = hasJSDocNodes(commentOwner) && commentOwner.jsDoc ? lastOrUndefined(commentOwner.jsDoc) : undefined; if (commentOwner.getStart(sourceFile) < position || commentOwnerJSDoc && commentOwnerJSDoc !== existingDocComment) { return undefined; } 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) : ""); @@ -396,17 +427,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(""); @@ -417,37 +448,37 @@ 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.PropertySignature: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.EnumMember: - case ts.SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.EnumMember: + case SyntaxKind.TypeAliasDeclaration: return { 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) @@ -457,50 +488,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.isArrowFunction(node) && ts.isExpression(node.body) - || ts.isFunctionLikeDeclaration(node) && node.body && ts.isBlock(node.body) && !!ts.forEachReturnStatement(node.body, n => n)); + (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 86dc479f63368..56b556c3dd4d8 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -1,17 +1,28 @@ -import * as ts from "./_namespaces/ts"; +import { compareStringsCaseSensitiveUI, compareValues, emptyArray } from "../compiler/core"; +import { Push } from "../compiler/corePublic"; +import { isPropertyAccessExpression } from "../compiler/factory/nodeTests"; +import { + CancellationToken, Declaration, Expression, Identifier, ImportClause, ImportEqualsDeclaration, ImportSpecifier, + Node, SourceFile, SyntaxKind, TypeChecker, +} from "../compiler/types"; +import { getTextOfIdentifierOrLiteral, isPropertyNameLiteral } from "../compiler/utilities"; +import { getNameOfDeclaration } from "../compiler/utilitiesPublic"; +import { createPatternMatcher, PatternMatcher, PatternMatchKind } from "./patternMatcher"; +import { NavigateToItem, ScriptElementKind } from "./types"; +import { createTextSpanFromNode, getContainerNode, getNodeKind, getNodeModifiers } from "./utilities"; 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 +42,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 +66,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 +79,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 +124,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 e0d6b6bf27142..cf494adb564f5 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -1,4 +1,41 @@ -import * as ts from "./_namespaces/ts"; +import { + compareStringsCaseSensitiveUI, compareValues, concatenate, contains, filterMutate, forEach, lastOrUndefined, map, + mapDefined, +} from "../compiler/core"; +import { ESMap, Map } from "../compiler/corePublic"; +import { Debug } from "../compiler/debug"; +import { factory } from "../compiler/factory/nodeFactory"; +import { + isArrowFunction, isBinaryExpression, isCallExpression, isClassDeclaration, isElementAccessExpression, + isExportAssignment, isFunctionDeclaration, isFunctionExpression, isIdentifier, isModuleBlock, isModuleDeclaration, + isObjectLiteralExpression, isPrivateIdentifier, isPropertyAccessExpression, isPropertyAssignment, + isVariableDeclaration, +} from "../compiler/factory/nodeTests"; +import { setTextRange } from "../compiler/factory/utilitiesPublic"; +import { forEachChild, isExternalModule } from "../compiler/parser"; +import { getBaseFileName, normalizePath } from "../compiler/path"; +import { + ArrowFunction, AssignmentDeclarationKind, BinaryExpression, BindableElementAccessExpression, + BindableObjectDefinePropertyCall, BindableStaticNameExpression, BindingElement, CallExpression, CancellationToken, + ClassElement, ClassExpression, ClassLikeDeclaration, ConstructorDeclaration, Declaration, DeclarationName, + EntityNameExpression, EnumDeclaration, EnumMember, ExportAssignment, Expression, FunctionDeclaration, + FunctionExpression, FunctionLikeDeclaration, Identifier, ImportClause, InterfaceDeclaration, InternalSymbolName, + ModifierFlags, ModuleDeclaration, Node, NodeFlags, PropertyAccessExpression, PropertyAssignment, + PropertyDeclaration, PropertyNameLiteral, ShorthandPropertyAssignment, SourceFile, SpreadAssignment, SyntaxKind, + TextSpan, TypeElement, VariableDeclaration, +} from "../compiler/types"; +import { + declarationNameToString, escapeString, getAssignmentDeclarationKind, getElementOrPropertyAccessName, getFullWidth, + getNameOrArgument, getPropertyNameForPropertyNameNode, getSyntacticModifierFlags, getTextOfIdentifierOrLiteral, + getTextOfNode, hasDynamicName, isAmbientModule, isBindableStaticAccessExpression, isJSDocTypeAlias, + isPropertyNameLiteral, isStatic, removeFileExtension, +} from "../compiler/utilities"; +import { + getNameOfDeclaration, hasJSDocNodes, idText, isBindingPattern, isClassLike, isDeclaration, isExpression, + isParameterPropertyDeclaration, isPropertyName, isStringLiteralLike, isToken, unescapeLeadingUnderscores, +} from "../compiler/utilitiesPublic"; +import { NavigationBarItem, NavigationTree } from "./types"; +import { createTextSpanFromNode, createTextSpanFromRange, getNodeKind, getNodeModifiers } from "./utilities"; /** * Matches all whitespace characters in a string. Eg: @@ -22,8 +59,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 +70,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 +102,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 +121,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 +138,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 +167,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 +195,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 +216,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 +238,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 +303,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 +314,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 +334,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 +357,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 +385,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 +444,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 +540,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 +584,17 @@ function tryMergeEs5Class(a: NavigationBarNode, b: NavigationBarNode, bIndex: nu undefined; if (ctorFunction !== undefined) { - const ctorNode = ts.setTextRange( - ts.factory.createConstructorDeclaration(/* decorators */ undefined, /* modifiers */ undefined, [], /* body */ undefined), + const ctorNode = setTextRange( + factory.createConstructorDeclaration(/* decorators */ undefined, /* 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,17 +602,17 @@ function tryMergeEs5Class(a: NavigationBarNode, b: NavigationBarNode, bIndex: nu } } - lastANode = a.node = ts.setTextRange(ts.factory.createClassDeclaration( + lastANode = a.node = setTextRange(factory.createClassDeclaration( /* decorators */ undefined, /* 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); } @@ -589,14 +626,14 @@ 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( /* decorators */ undefined, /* modifiers */ undefined, - a.name as ts.Identifier || ts.factory.createIdentifier("__class__"), + a.name as Identifier || factory.createIdentifier("__class__"), /* typeParameters */ undefined, /* heritageClauses */ undefined, [] @@ -604,7 +641,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 { @@ -620,42 +657,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. */ @@ -666,7 +703,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); @@ -679,8 +716,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)); } /** @@ -688,34 +725,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); @@ -723,33 +760,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 ""; @@ -784,35 +821,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; @@ -821,34 +858,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, @@ -858,7 +895,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) { @@ -868,21 +905,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("."); } @@ -891,50 +928,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); @@ -943,7 +980,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`; } } @@ -951,11 +988,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}`; @@ -965,11 +1002,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 0de452c93bed6..dc0d5384c0680 100644 --- a/src/services/organizeImports.ts +++ b/src/services/organizeImports.ts @@ -1,4 +1,26 @@ -import * as ts from "./_namespaces/ts"; +import { + arrayIsSorted, binarySearch, compareBooleans, compareStringsCaseInsensitive, compareValues, emptyArray, flatMap, + group, identity, isString, length, map, some, stableSort, tryCast, +} from "../compiler/core"; +import { SortedReadonlyArray } from "../compiler/corePublic"; +import { factory } from "../compiler/factory/nodeFactory"; +import { + isExportDeclaration, isExternalModuleReference, isImportDeclaration, isNamedExports, isNamedImports, + isNamespaceImport, isStringLiteral, +} from "../compiler/factory/nodeTests"; +import { createScanner, Scanner } from "../compiler/scanner"; +import { + AnyImportOrRequireStatement, ExportDeclaration, ExportSpecifier, Expression, Identifier, ImportDeclaration, + ImportOrExportSpecifier, ImportSpecifier, NamedImportBindings, NamedImports, NamespaceImport, Program, SourceFile, + SyntaxKind, TransformFlags, UserPreferences, +} from "../compiler/types"; +import { isAmbientModule } from "../compiler/utilities"; +import { isExternalModuleNameRelative, isStringLiteralLike } from "../compiler/utilitiesPublic"; +import { Core } from "./findAllReferences"; +import { FormatContext } from "./formatting/formatting"; +import { ChangeTracker, LeadingTriviaOption, TrailingTriviaOption } from "./textChanges"; +import { LanguageServiceHost } from "./types"; +import { getNewLineOrDefaultFromHost, jsxModeNeedsExplicitImport, suppressLeadingTrivia } from "./utilities"; /* @internal */ /** @@ -8,44 +30,44 @@ 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, + sourceFile: SourceFile, + formatContext: FormatContext, + host: LanguageServiceHost, + program: Program, + preferences: UserPreferences, skipDestructiveCodeActions?: boolean ) { - const changeTracker = ts.textChanges.ChangeTracker.fromContext({ host, formatContext, preferences }); + const changeTracker = ChangeTracker.fromContext({ host, formatContext, preferences }); - const coalesceAndOrganizeImports = (importGroup: readonly ts.ImportDeclaration[]) => ts.stableSort( + const coalesceAndOrganizeImports = (importGroup: readonly ImportDeclaration[]) => stableSort( coalesceImports(removeUnusedImports(importGroup, sourceFile, program, skipDestructiveCodeActions)), (s1, s2) => compareImportsOrRequireStatements(s1, s2)); // 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, coalesceAndOrganizeImports)); // 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, coalesceAndOrganizeImports)); - const ambientModuleExportDecls = ambientModule.body.statements.filter(ts.isExportDeclaration); + 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; } @@ -54,11 +76,11 @@ 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 = ts.group(oldImportDecls, importDecl => getExternalModuleName(importDecl.moduleSpecifier!)!); - const sortedImportGroups = ts.stableSort(oldImportGroups, (group1, group2) => compareModuleSpecifiers(group1[0].moduleSpecifier, group2[0].moduleSpecifier)); - const newImportDecls = ts.flatMap(sortedImportGroups, importGroup => + const oldImportGroups = group(oldImportDecls, importDecl => getExternalModuleName(importDecl.moduleSpecifier!)!); + const sortedImportGroups = stableSort(oldImportGroups, (group1, group2) => compareModuleSpecifiers(group1[0].moduleSpecifier, group2[0].moduleSpecifier)); + const newImportDecls = flatMap(sortedImportGroups, importGroup => getExternalModuleName(importGroup[0].moduleSpecifier!) ? coalesce(importGroup) : importGroup); @@ -68,28 +90,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: 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: LeadingTriviaOption.Exclude, // Leave header comment in place + trailingTriviaOption: 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: 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)) { @@ -108,7 +130,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); @@ -117,7 +139,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) { @@ -129,7 +151,7 @@ function isNewGroup(sourceFile: ts.SourceFile, topLevelImportDecl: ts.ImportDecl return false; } -function removeUnusedImports(oldImports: readonly ts.ImportDeclaration[], sourceFile: ts.SourceFile, program: ts.Program, skipDestructiveCodeActions: boolean | undefined) { +function removeUnusedImports(oldImports: readonly ImportDeclaration[], sourceFile: SourceFile, program: Program, skipDestructiveCodeActions: boolean | undefined) { // As a precaution, consider unused import detection to be destructive (GH #43051) if (skipDestructiveCodeActions) { return oldImports; @@ -139,9 +161,9 @@ function removeUnusedImports(oldImports: readonly ts.ImportDeclaration[], source 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; @@ -160,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; @@ -171,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; } } @@ -184,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.decorators, importDecl.modifiers, /*importClause*/ undefined, @@ -202,22 +224,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) || + 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; } @@ -227,14 +249,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); @@ -254,8 +276,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 @@ -267,15 +289,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 } } @@ -289,10 +311,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 @@ -314,9 +336,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[]; } /* @@ -326,8 +348,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: [] }; @@ -347,7 +369,7 @@ function getCategorizedImports(importGroup: readonly ts.ImportDeclaration[]) { } if (namedBindings) { - if (ts.isNamespaceImport(namedBindings)) { + if (isNamespaceImport(namedBindings)) { group.namespaceImports.push(importDeclaration); } else { @@ -368,14 +390,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); @@ -385,22 +407,22 @@ 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.decorators, 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)); @@ -413,10 +435,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) { @@ -441,84 +463,84 @@ 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.decorators, 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 @@ -528,33 +550,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 3e4002a220e49..161351c2e4954 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -1,53 +1,72 @@ -import * as ts from "./_namespaces/ts"; +import { startsWith, trimString, trimStringStart } from "../compiler/core"; +import { Push } from "../compiler/corePublic"; +import { Debug } from "../compiler/debug"; +import { + isArrayLiteralExpression, isBinaryExpression, isBindingElement, isBlock, isCallExpression, isIfStatement, + isInterfaceDeclaration, isJsxText, isModuleBlock, isParenthesizedExpression, isPropertyAccessExpression, + isReturnStatement, isTupleTypeNode, isVariableStatement, +} from "../compiler/factory/nodeTests"; +import { getLeadingCommentRanges } from "../compiler/scanner"; +import { + ArrowFunction, Block, CallExpression, CancellationToken, CaseClause, DefaultClause, JsxAttributes, JsxElement, + JsxFragment, JsxOpeningLikeElement, Node, NodeArray, NoSubstitutionTemplateLiteral, ParenthesizedExpression, + SignatureDeclaration, SourceFile, SyntaxKind, TemplateExpression, TextSpan, TryStatement, +} from "../compiler/types"; +import { isAnyImportSyntax, isNodeArrayMultiLine, positionsAreOnSameLine } from "../compiler/utilities"; +import { + createTextSpanFromBounds, isCallOrNewExpression, isClassLike, isDeclaration, isFunctionLike, +} from "../compiler/utilitiesPublic"; +import { OutliningSpan, OutliningSpanKind } from "./types"; +import { createTextSpanFromNode, createTextSpanFromRange, findChildOfKind, isInComment } from "./utilities"; /* @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 +74,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 +96,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 +126,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 +145,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 +162,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 +176,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 23c44c7f3384d..5c1388398453d 100644 --- a/src/services/patternMatcher.ts +++ b/src/services/patternMatcher.ts @@ -1,4 +1,8 @@ -import * as ts from "./_namespaces/ts"; +import { compareBooleans, compareValues, last, min, startsWith } from "../compiler/core"; +import { Comparison, ESMap, Map } from "../compiler/corePublic"; +import { isUnicodeIdentifierStart } from "../compiler/scanner"; +import { CharacterCodes, ScriptTarget, TextSpan } from "../compiler/types"; +import { createTextSpan } from "../compiler/utilitiesPublic"; // Note(cyrusn): this enum is ordered from strongest match type to weakest match type. /* @internal */ @@ -90,7 +94,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 +110,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 +118,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 +149,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 +157,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 +209,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 +217,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 +267,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 +283,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 +339,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 +364,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 +380,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 +409,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 +424,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 +470,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 +497,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 +505,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 +513,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 +543,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 dfdea804be30b..8c27469b7c0e5 100644 --- a/src/services/preProcess.ts +++ b/src/services/preProcess.ts @@ -1,8 +1,13 @@ -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 { lastOrUndefined, length, noop } from "../compiler/core"; +import { PragmaContext, processCommentPragmas, processPragmasIntoFields } from "../compiler/parser"; +import { FileReference, ScriptTarget, SyntaxKind } from "../compiler/types"; +import { isKeyword } from "../compiler/utilities"; +import { PreProcessedFileInfo } from "./types"; +import { scanner } from "./utilities"; + +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 +17,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 +28,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 +67,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 +87,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 +122,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 +147,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 +167,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 +193,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 +227,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 +266,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 +283,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 +304,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 +326,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 +347,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()]; - let token = ts.scanner.scan(); - loop: while (ts.length(stack)) { + if (scanner.getToken() === SyntaxKind.TemplateHead) { + const stack = [scanner.getToken()]; + let token = scanner.scan(); + loop: while (length(stack)) { 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(); } } @@ -377,7 +382,7 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec } break; } - token = ts.scanner.scan(); + token = scanner.scan(); } nextToken(); } @@ -397,14 +402,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 037425966833f..36272d562c2ba 100644 --- a/src/services/refactorProvider.ts +++ b/src/services/refactorProvider.ts @@ -1,25 +1,28 @@ -import * as ts from "./_namespaces/ts"; +import { arrayFrom, flatMapIterator } from "../compiler/core"; +import { Map } from "../compiler/corePublic"; +import { refactorKindBeginsWith } from "./refactors/helpers"; +import { ApplicableRefactorInfo, Refactor, RefactorContext, RefactorEditInfo } from "./types"; // 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 021bff343ee5c..8947a1c55bf55 100644 --- a/src/services/refactors/addOrRemoveBracesToArrowFunction.ts +++ b/src/services/refactors/addOrRemoveBracesToArrowFunction.ts @@ -1,37 +1,52 @@ -import * as ts from "../_namespaces/ts"; +import { emptyArray, first } from "../../compiler/core"; +import { Debug } from "../../compiler/debug"; +import { Diagnostics } from "../../compiler/diagnosticInformationMap.generated"; +import { factory } from "../../compiler/factory/nodeFactory"; +import { isArrowFunction, isBlock, isReturnStatement } from "../../compiler/factory/nodeTests"; +import { ArrowFunction, ConciseBody, Expression, ReturnStatement, SourceFile, SyntaxKind } from "../../compiler/types"; +import { getContainingFunction, getLocaleSpecificMessage } from "../../compiler/utilities"; +import { isExpression } from "../../compiler/utilitiesPublic"; +import { registerRefactor } from "../refactorProvider"; +import { ChangeTracker } from "../textChanges"; +import { ApplicableRefactorInfo, RefactorContext, RefactorEditInfo } from "../types"; +import { + copyLeadingComments, copyTrailingAsLeadingComments, copyTrailingComments, getTokenAtPosition, needsParentheses, + rangeContainsRange, +} from "../utilities"; +import { isRefactorErrorInfo, RefactorErrorInfo, refactorKindBeginsWith } from "./helpers"; 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 +67,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 = 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 a8181c115282a..3cf997e2bf686 100644 --- a/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts +++ b/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts @@ -1,24 +1,52 @@ -import * as ts from "../_namespaces/ts"; +import { emptyArray, first, length } from "../../compiler/core"; +import { Debug } from "../../compiler/debug"; +import { Diagnostics } from "../../compiler/diagnosticInformationMap.generated"; +import { factory } from "../../compiler/factory/nodeFactory"; +import { + isArrowFunction, isFunctionDeclaration, isFunctionExpression, isIdentifier, isReturnStatement, + isVariableDeclaration, isVariableDeclarationList, isVariableStatement, +} from "../../compiler/factory/nodeTests"; +import { forEachChild } from "../../compiler/parser"; +import { + ArrowFunction, Block, ConciseBody, FunctionExpression, Identifier, ModifierFlags, Node, Program, ReturnStatement, + SourceFile, Statement, SyntaxKind, TypeChecker, VariableDeclaration, VariableDeclarationList, VariableStatement, +} from "../../compiler/types"; +import { + getContainingFunction, getEffectiveModifierFlags, getLocaleSpecificMessage, + isVariableDeclarationInVariableStatement, +} from "../../compiler/utilities"; +import { getCombinedModifierFlags, isClassLike, isExpression } from "../../compiler/utilitiesPublic"; +import { Core } from "../findAllReferences"; +import { registerRefactor } from "../refactorProvider"; +import { ChangeTracker } from "../textChanges"; +import { + ApplicableRefactorInfo, FileTextChanges, RefactorActionInfo, RefactorContext, RefactorEditInfo, +} from "../types"; +import { + copyComments, copyTrailingAsLeadingComments, getTokenAtPosition, isThis, rangeContainsRange, + suppressLeadingAndTrailingTrivia, suppressLeadingTrivia, +} from "../utilities"; +import { refactorKindBeginsWith } from "./helpers"; 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 +58,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 +87,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 +98,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 +116,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,151 +137,151 @@ 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 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(func.decorators, 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(func.decorators, 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 ChangeTracker.with(context, t => t.replaceNode(file, statement, newNode)); } else { - return ts.textChanges.ChangeTracker.with(context, t => { + return 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 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 && Core.isSymbolReferencedInFile(node.name, typeChecker, sourceFile); } export { }; diff --git a/src/services/refactors/convertExport.ts b/src/services/refactors/convertExport.ts index 38538651be89d..8bd0443bb1db3 100644 --- a/src/services/refactors/convertExport.ts +++ b/src/services/refactors/convertExport.ts @@ -1,170 +1,192 @@ -import * as ts from "../_namespaces/ts"; +import { emptyArray, first } from "../../compiler/core"; +import { Debug } from "../../compiler/debug"; +import { Diagnostics } from "../../compiler/diagnosticInformationMap.generated"; +import { factory } from "../../compiler/factory/nodeFactory"; +import { + isExportAssignment, isIdentifier, isModuleBlock, isSourceFile, isStringLiteral, +} from "../../compiler/factory/nodeTests"; +import { + CancellationToken, ClassDeclaration, EnumDeclaration, ExportAssignment, ExportSpecifier, FunctionDeclaration, + Identifier, ImportClause, ImportSpecifier, ImportTypeNode, InterfaceDeclaration, InternalSymbolName, ModifierFlags, + NamespaceDeclaration, Node, NodeFlags, Program, PropertyAccessExpression, SourceFile, Symbol, SyntaxKind, + TypeAliasDeclaration, TypeChecker, VariableStatement, +} from "../../compiler/types"; +import { getLocaleSpecificMessage, getSyntacticModifierFlags, isAmbientModule } from "../../compiler/utilities"; +import { Core } from "../findAllReferences"; +import { registerRefactor } from "../refactorProvider"; +import { ChangeTracker } from "../textChanges"; +import { ApplicableRefactorInfo, RefactorContext, RefactorEditInfo } from "../types"; +import { + findModifier, getParentNodeInSpan, getRefactorContextSpan, getTokenAtPosition, makeImport, QuotePreference, + quotePreferenceFromString, +} from "../utilities"; +import { isRefactorErrorInfo, RefactorErrorInfo } from "./helpers"; 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 = 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 exportingModuleSymbol = ts.isSourceFile(exportNode.parent) ? exportNode.parent.symbol : exportNode.parent.parent.symbol; + const exportingModuleSymbol = isSourceFile(exportNode.parent) ? exportNode.parent.symbol : exportNode.parent.parent.symbol; - 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 checker = program.getTypeChecker(); - 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: 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: 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(/*decorators*/ undefined, /*modifiers*/ undefined, /*isTypeOnly*/ false, ts.factory.createNamedExports([spec]))); + changes.replaceNode(exportingSourceFile, exportNode, factory.createExportDeclaration(/*decorators*/ undefined, /*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 (!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: 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"); + Core.eachExportReference(program.getSourceFiles(), checker, cancellationToken, exportSymbol, exportingModuleSymbol, exportName.text, wasDefault, ref => { const importingSourceFile = ref.getSourceFile(); if (wasDefault) { changeDefaultToNamedImport(importingSourceFile, ref, changes, exportName.text); @@ -175,34 +197,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: 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 +234,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, ts.factory.createIdentifier(exportName), importTypeNode.typeArguments, importTypeNode.isTypeOf)); + case SyntaxKind.ImportType: + const importTypeNode = parent as ImportTypeNode; + changes.replaceNode(importingSourceFile, parent, factory.createImportTypeNode(importTypeNode.argument, 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: 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 +263,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,17 +272,17 @@ 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)); } export { }; diff --git a/src/services/refactors/convertImport.ts b/src/services/refactors/convertImport.ts index 322ae28fe9576..490cc7e5ecf9f 100644 --- a/src/services/refactors/convertImport.ts +++ b/src/services/refactors/convertImport.ts @@ -1,141 +1,164 @@ -import * as ts from "../_namespaces/ts"; +import { arrayFrom, emptyArray, getOwnValues, some } from "../../compiler/core"; +import { Map, Set } from "../../compiler/corePublic"; +import { Debug } from "../../compiler/debug"; +import { Diagnostics } from "../../compiler/diagnosticInformationMap.generated"; +import { factory } from "../../compiler/factory/nodeFactory"; +import { + isExportSpecifier, isImportDeclaration, isPropertyAccessExpression, isShorthandPropertyAssignment, isStringLiteral, +} from "../../compiler/factory/nodeTests"; +import { + Expression, Identifier, ImportClause, ImportDeclaration, ImportSpecifier, NamedImports, NamespaceImport, Program, + PropertyAccessExpression, QualifiedName, ScriptTarget, SourceFile, Symbol, SymbolFlags, SyntaxKind, TypeChecker, +} from "../../compiler/types"; +import { getAllowSyntheticDefaultImports, getLocaleSpecificMessage } from "../../compiler/utilities"; +import { findAncestor, isPropertyAccessOrQualifiedName } from "../../compiler/utilitiesPublic"; +import { moduleSpecifierToValidIdentifier } from "../codefixes/importFixes"; +import { ImportKind } from "../exportInfoMap"; +import { Core } from "../findAllReferences"; +import { registerRefactor } from "../refactorProvider"; +import { ChangeTracker } from "../textChanges"; +import { ApplicableRefactorInfo, RefactorContext, RefactorEditInfo } from "../types"; +import { + findNextToken, getParentNodeInSpan, getRefactorContextSpan, getTokenAtPosition, getUniqueName, +} from "../utilities"; +import { isRefactorErrorInfo, RefactorErrorInfo } from "./helpers"; 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 = 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: 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: 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)) { + 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 +167,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: 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) ? 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 !!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 +210,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)); + 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 +233,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(/*decorators*/ undefined, /*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(/*decorators*/ undefined, /*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 9545fae295178..5bca70c738717 100644 --- a/src/services/refactors/convertOverloadListToSingleSignature.ts +++ b/src/services/refactors/convertOverloadListToSingleSignature.ts @@ -1,23 +1,43 @@ -import * as ts from "../_namespaces/ts"; +import { emptyArray, every, length, map, mapDefined, some } from "../../compiler/core"; +import { Debug } from "../../compiler/debug"; +import { Diagnostics } from "../../compiler/diagnosticInformationMap.generated"; +import { + getSyntheticLeadingComments, setEmitFlags, setSyntheticLeadingComments, +} from "../../compiler/factory/emitNode"; +import { factory } from "../../compiler/factory/nodeFactory"; +import { isIdentifier } from "../../compiler/factory/nodeTests"; +import { setTextRange } from "../../compiler/factory/utilitiesPublic"; +import { + CallSignatureDeclaration, ConstructorDeclaration, ConstructSignatureDeclaration, EmitFlags, FunctionDeclaration, + MethodDeclaration, MethodSignature, NamedTupleMember, Node, NodeArray, ParameterDeclaration, Program, SourceFile, + SyntaxKind, TupleTypeNode, +} from "../../compiler/types"; +import { getSourceFileOfNode } from "../../compiler/utilities"; +import { findAncestor, isFunctionLikeDeclaration } from "../../compiler/utilitiesPublic"; +import { registerRefactor } from "../refactorProvider"; +import { displayPartsToString } from "../services"; +import { ChangeTracker } from "../textChanges"; +import { ApplicableRefactorInfo, RefactorContext, RefactorEditInfo } from "../types"; +import { getTokenAtPosition } from "../utilities"; 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 +46,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 +56,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 +68,8 @@ function getRefactorEditsToConvertOverloadsToOneSignature(context: ts.RefactorCo ); break; } - case ts.SyntaxKind.MethodDeclaration: { - updated = ts.factory.updateMethodDeclaration( + case SyntaxKind.MethodDeclaration: { + updated = factory.updateMethodDeclaration( lastDeclaration, lastDeclaration.decorators, lastDeclaration.modifiers, @@ -63,8 +83,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), @@ -72,8 +92,8 @@ function getRefactorEditsToConvertOverloadsToOneSignature(context: ts.RefactorCo ); break; } - case ts.SyntaxKind.Constructor: { - updated = ts.factory.updateConstructorDeclaration( + case SyntaxKind.Constructor: { + updated = factory.updateConstructorDeclaration( lastDeclaration, lastDeclaration.decorators, lastDeclaration.modifiers, @@ -82,8 +102,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), @@ -91,8 +111,8 @@ function getRefactorEditsToConvertOverloadsToOneSignature(context: ts.RefactorCo ); break; } - case ts.SyntaxKind.FunctionDeclaration: { - updated = ts.factory.updateFunctionDeclaration( + case SyntaxKind.FunctionDeclaration: { + updated = factory.updateFunctionDeclaration( lastDeclaration, lastDeclaration.decorators, lastDeclaration.modifiers, @@ -105,59 +125,59 @@ 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 = 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( /*decorators*/ undefined, /*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, @@ -170,22 +190,22 @@ ${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; } @@ -195,29 +215,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.decorators || !!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.decorators || !!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 2ebab5974f8e3..7a4a772872b95 100644 --- a/src/services/refactors/convertParamsToDestructuredObject.ts +++ b/src/services/refactors/convertParamsToDestructuredObject.ts @@ -1,26 +1,64 @@ -import * as ts from "../_namespaces/ts"; +import { + compareValues, contains, deduplicate, emptyArray, equateValues, every, first, flatMap, last, map, + sortAndDeduplicate, tryCast, +} from "../../compiler/core"; +import { Debug } from "../../compiler/debug"; +import { Diagnostics } from "../../compiler/diagnosticInformationMap.generated"; +import { addEmitFlags } from "../../compiler/factory/emitNode"; +import { factory } from "../../compiler/factory/nodeFactory"; +import { + isClassDeclaration, isConstructorDeclaration, isElementAccessExpression, isExportAssignment, isExportSpecifier, + isIdentifier, isImportClause, isImportEqualsDeclaration, isImportSpecifier, isInterfaceDeclaration, + isMethodSignature, isNamespaceImport, isObjectLiteralExpression, isPropertyAccessExpression, isPropertyAssignment, + isTypeLiteralNode, isVariableDeclaration, +} from "../../compiler/factory/nodeTests"; +import { + ArrowFunction, BindingElement, CallExpression, CancellationToken, CheckFlags, ClassDeclaration, ClassExpression, + ConstructorDeclaration, ElementAccessExpression, EmitFlags, Expression, FunctionBody, FunctionDeclaration, + FunctionExpression, FunctionLikeDeclaration, Identifier, MethodDeclaration, MethodSignature, Modifier, + NewExpression, Node, NodeArray, ObjectLiteralElementLike, ObjectLiteralExpression, ParameterDeclaration, Program, + PropertyAccessExpression, PropertyAssignment, PropertySignature, ShorthandPropertyAssignment, SourceFile, Symbol, + SyntaxKind, TypeChecker, TypeLiteralNode, TypeNode, VariableDeclaration, +} from "../../compiler/types"; +import { + getCheckFlags, getContainingFunctionDeclaration, getLocaleSpecificMessage, getSourceFileOfNode, + getTextOfIdentifierOrLiteral, isExpressionWithTypeArgumentsInClassExtendsClause, isSourceFileJS, isVarConst, +} from "../../compiler/utilities"; +import { + findAncestor, isCallOrNewExpression, isDeclaration, isFunctionLikeDeclaration, isJSDocNode, isRestParameter, +} from "../../compiler/utilitiesPublic"; +import { Entry, EntryKind, getReferenceEntriesForNode, NodeEntry } from "../findAllReferences"; +import { registerRefactor } from "../refactorProvider"; +import { getContainingObjectLiteralElement } from "../services"; +import { ChangeTracker, LeadingTriviaOption, TrailingTriviaOption } from "../textChanges"; +import { ApplicableRefactorInfo, LanguageServiceHost, RefactorContext, RefactorEditInfo } from "../types"; +import { + copyComments, findChildOfKind, findModifier, getMeaningFromLocation, getSymbolTarget, getSynthesizedDeepClone, + getTouchingToken, getTypeNodeIfAccessible, isNewExpressionTarget, isThis, rangeContainsRange, SemanticMeaning, + suppressLeadingAndTrailingTrivia, +} from "../utilities"; 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 +67,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 = ChangeTracker.with(context, t => doChange(file, program, host, t, functionDeclaration, groupedReferences)); return { renameFilename: undefined, renameLocation: undefined, edits }; } @@ -45,75 +83,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: 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: LeadingTriviaOption.IncludeAll, trailingTriviaOption: 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: LeadingTriviaOption.IncludeAll, + trailingTriviaOption: 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 => 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 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 === EntryKind.Span) { groupedReferences.valid = false; continue; } @@ -124,7 +162,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 +175,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 +194,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 +212,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 +232,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 +246,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: 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: 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: 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 +327,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: 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 +351,167 @@ function entryToAccessExpression(entry: ts.FindAllReferences.NodeEntry): ts.Elem return undefined; } -function entryToType(entry: ts.FindAllReferences.NodeEntry): ts.Node | undefined { +function entryToType(entry: 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 && !parameterDeclaration.decorators && ts.isIdentifier(parameterDeclaration.name); + return !parameterDeclaration.modifiers && !parameterDeclaration.decorators && 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( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, @@ -484,7 +522,7 @@ function createNewParameters(functionDeclaration: ValidFunctionDeclaration | Val if (hasThisParameter(functionDeclaration.parameters)) { const thisParameter = functionDeclaration.parameters[0]; - const newThisParameter = ts.factory.createParameterDeclaration( + const newThisParameter = factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, @@ -492,65 +530,65 @@ function createNewParameters(functionDeclaration: ValidFunctionDeclaration | Val /*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); } @@ -559,21 +597,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; @@ -582,92 +620,92 @@ 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; decorators: 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[]; } export { }; diff --git a/src/services/refactors/convertStringOrTemplateLiteral.ts b/src/services/refactors/convertStringOrTemplateLiteral.ts index c08ae686f55e3..8519d84cb1655 100644 --- a/src/services/refactors/convertStringOrTemplateLiteral.ts +++ b/src/services/refactors/convertStringOrTemplateLiteral.ts @@ -1,54 +1,72 @@ -import * as ts from "../_namespaces/ts"; +import { emptyArray, map } from "../../compiler/core"; +import { Debug } from "../../compiler/debug"; +import { Diagnostics } from "../../compiler/diagnosticInformationMap.generated"; +import { factory } from "../../compiler/factory/nodeFactory"; +import { + isBinaryExpression, isNoSubstitutionTemplateLiteral, isParenthesizedExpression, isStringLiteral, + isTemplateExpression, isTemplateHead, isTemplateMiddle, +} from "../../compiler/factory/nodeTests"; +import { getTrailingCommentRanges } from "../../compiler/scanner"; +import { + BinaryExpression, BinaryOperator, Expression, Node, ParenthesizedExpression, SourceFile, SyntaxKind, TemplateHead, + TemplateMiddle, TemplateSpan, TemplateTail, Token, +} from "../../compiler/types"; +import { getLocaleSpecificMessage, getTextOfNode } from "../../compiler/utilities"; +import { findAncestor, isStringLiteralLike } from "../../compiler/utilitiesPublic"; +import { registerRefactor } from "../refactorProvider"; +import { ChangeTracker } from "../textChanges"; +import { ApplicableRefactorInfo, RefactorContext, RefactorEditInfo } from "../types"; +import { copyTrailingAsLeadingComments, copyTrailingComments, getTokenAtPosition } from "../utilities"; 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 +74,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 +91,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 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 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 +148,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 +175,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 +204,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 +227,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 0680ddc3f534e..9acfb7adcefc9 100644 --- a/src/services/refactors/convertToOptionalChainExpression.ts +++ b/src/services/refactors/convertToOptionalChainExpression.ts @@ -1,24 +1,45 @@ -import * as ts from "../_namespaces/ts"; +import { emptyArray } from "../../compiler/core"; +import { Debug } from "../../compiler/debug"; +import { Diagnostics } from "../../compiler/diagnosticInformationMap.generated"; +import { factory } from "../../compiler/factory/nodeFactory"; +import { + isBinaryExpression, isCallExpression, isConditionalExpression, isElementAccessExpression, isExpressionStatement, + isIdentifier, isPropertyAccessExpression, isReturnStatement, isVariableStatement, +} from "../../compiler/factory/nodeTests"; +import { + BinaryExpression, CallExpression, ConditionalExpression, ElementAccessExpression, Expression, ExpressionStatement, + Identifier, Node, PropertyAccessExpression, ReturnStatement, SourceFile, SyntaxKind, TextSpan, TypeChecker, + VariableStatement, +} from "../../compiler/types"; +import { + getLocaleSpecificMessage, getSingleVariableOfVariableStatement, isStringOrNumericLiteralLike, skipParentheses, +} from "../../compiler/utilities"; +import { createTextSpanFromBounds, isOptionalChain } from "../../compiler/utilitiesPublic"; +import { registerRefactor } from "../refactorProvider"; +import { ChangeTracker } from "../textChanges"; +import { ApplicableRefactorInfo, RefactorContext, RefactorEditInfo } from "../types"; +import { findTokenOnLeftOfPosition, getRefactorContextSpan, getTokenAtPosition } from "../utilities"; +import { isRefactorErrorInfo, RefactorErrorInfo } from "./helpers"; 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 +54,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 = 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 +79,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 +174,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 +184,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 +217,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 +230,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 +247,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 +261,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 +278,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: 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 9b95139949fab..1221ed59a8a7a 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -1,18 +1,70 @@ -import * as ts from "../_namespaces/ts"; +import { getNodeId, getSymbolId } from "../../compiler/checker"; +import { + arrayFrom, assertType, compareProperties, compareStringsCaseSensitive, compareValues, contains, emptyArray, find, + first, firstOrUndefined, isArray, last, map, singleOrUndefined, +} from "../../compiler/core"; +import { ESMap, Map, ReadonlyESMap } from "../../compiler/corePublic"; +import { Debug } from "../../compiler/debug"; +import { Diagnostics } from "../../compiler/diagnosticInformationMap.generated"; +import { setEmitFlags } from "../../compiler/factory/emitNode"; +import { factory } from "../../compiler/factory/nodeFactory"; +import { + isArrowFunction, isBinaryExpression, isBlock, isCaseClause, isConstructorDeclaration, isElementAccessExpression, + isExpressionStatement, isFunctionExpression, isIdentifier, isJsxAttribute, isJsxElement, isJsxFragment, + isJsxSelfClosingElement, isModuleBlock, isParenthesizedTypeNode, isPrivateIdentifier, isPropertyAccessExpression, + isPropertyDeclaration, isQualifiedName, isReturnStatement, isShorthandPropertyAssignment, isSourceFile, + isStringLiteral, isSwitchStatement, isUnionTypeNode, isVariableDeclaration, isVariableDeclarationList, + isVariableStatement, +} from "../../compiler/factory/nodeTests"; +import { forEachChild } from "../../compiler/parser"; +import { nullTransformationContext } from "../../compiler/transformer"; +import { + __String, BindingElement, Block, BlockLike, BreakStatement, CancellationToken, CharacterCodes, ClassElement, + ClassLikeDeclaration, ContinueStatement, Declaration, Diagnostic, DiagnosticCategory, DiagnosticMessage, EmitFlags, + EntityName, Expression, ExpressionStatement, FunctionDeclaration, FunctionLikeDeclaration, Identifier, + LabeledStatement, MethodDeclaration, Modifier, ModifierFlags, ModuleBlock, NamedDeclaration, Node, NodeBuilderFlags, + NodeFlags, ObjectLiteralElementLike, ParameterDeclaration, PropertyAccessExpression, ShorthandPropertyAssignment, + SignatureKind, SourceFile, Statement, StringLiteral, Symbol, SymbolFlags, SyntaxKind, TextRange, TextSpan, + TryStatement, Type, TypeChecker, TypeElement, TypeFlags, TypeLiteralNode, TypeNode, TypeParameter, + TypeParameterDeclaration, VariableDeclaration, VisitResult, +} from "../../compiler/types"; +import { + createDiagnosticForNode, createFileDiagnostic, formatStringFromArgs, getContainingClass, getContainingFunction, + getEmitScriptTarget, getEnclosingBlockScopeContainer, getLocaleSpecificMessage, getThisContainer, + hasEffectiveModifier, hasSyntacticModifier, isAssignmentExpression, isBlockScope, isDeclarationWithTypeParameters, + isExpressionNode, isInJSFile, isKeyword, isPartOfTypeNode, isStatic, positionIsSynthesized, skipParentheses, +} from "../../compiler/utilities"; +import { + findAncestor, getEffectiveTypeParameterDeclarations, isClassLike, isDeclaration, isExpression, isFunctionBody, + isFunctionLike, isFunctionLikeDeclaration, isIterationStatement, isStatement, isUnaryExpressionWithWrite, + textSpanEnd, +} from "../../compiler/utilitiesPublic"; +import { visitEachChild, visitNode, visitNodes } from "../../compiler/visitorPublic"; +import { typeToAutoImportableTypeNode } from "../codefixes/helpers"; +import { createImportAdder } from "../codefixes/importFixes"; +import { registerRefactor } from "../refactorProvider"; +import { ChangeTracker } from "../textChanges"; +import { ApplicableRefactorInfo, RefactorActionInfo, RefactorContext, RefactorEditInfo } from "../types"; +import { + ANONYMOUS, findFirstNonJsxWhitespaceToken, findTokenOnLeftOfPosition, getParentNodeInSpan, getRefactorContextSpan, + getRenameLocation, getSynthesizedDeepClone, getUniqueName, isThis, rangeContainsStartEnd, + suppressLeadingAndTrailingTrivia, +} from "../utilities"; +import { refactorKindBeginsWith } from "./helpers"; 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 +78,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,21 +109,21 @@ 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) { const description = functionExtraction.description; - if (ts.refactor.refactorKindBeginsWith(extractFunctionAction.kind, requestedRefactor)) { + if (refactorKindBeginsWith(extractFunctionAction.kind, requestedRefactor)) { if (functionExtraction.errors.length === 0) { // Don't issue refactorings with duplicated names. // Scopes come back in "innermost first" order, so extractions will @@ -95,7 +147,7 @@ export function getRefactorActionsToExtractSymbol(context: ts.RefactorContext): } } - if (ts.refactor.refactorKindBeginsWith(extractConstantAction.kind, requestedRefactor)) { + if (refactorKindBeginsWith(extractConstantAction.kind, requestedRefactor)) { if (constantExtraction.errors.length === 0) { // Don't issue refactorings with duplicated names. // Scopes come back in "innermost first" order, so extractions will @@ -125,19 +177,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 +197,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 +222,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,17 +292,17 @@ 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; /** * A list of symbols that are declared in the selected range which are visible in the containing lexical scope * Used to ensure we don't turn something used outside the range free (or worse, resolve to a different entity). */ - readonly declarations: ts.Symbol[]; + readonly declarations: Symbol[]; /** * 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; } /** @@ -258,7 +310,7 @@ interface TargetRange { */ type RangeToExtract = { readonly targetRange?: never; - readonly errors: readonly ts.Diagnostic[]; + readonly errors: readonly Diagnostic[]; } | { readonly targetRange: TargetRange; readonly errors?: never; @@ -267,7 +319,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 */ /** @@ -277,15 +329,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. */ @@ -293,39 +345,39 @@ 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); - const declarations: ts.Symbol[] = []; + const declarations: Symbol[] = []; // 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); @@ -345,15 +397,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, declarations, 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) @@ -369,16 +421,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++; @@ -390,7 +442,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; } @@ -398,31 +450,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; } } @@ -431,7 +483,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, @@ -440,37 +492,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; } @@ -478,19 +530,19 @@ 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; } declarations.push(node.symbol); @@ -498,20 +550,20 @@ export function getRangeToExtract(sourceFile: ts.SourceFile, span: ts.TextSpan, // 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; } } @@ -520,60 +572,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.None; 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; } @@ -581,51 +633,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; } @@ -638,25 +690,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; @@ -664,9 +716,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); } /** @@ -675,12 +727,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]; @@ -691,9 +743,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. @@ -703,34 +755,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 { @@ -743,37 +795,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 { @@ -790,7 +842,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); @@ -806,45 +858,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; } @@ -859,38 +911,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 = 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 = typeToAutoImportableTypeNode(checker, importAdder, type, scope, scriptTarget, NodeBuilderFlags.NoTruncation); } - const paramDecl = ts.factory.createParameterDeclaration( + const paramDecl = factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, @@ -902,49 +954,49 @@ 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( /*decorators*/ undefined, 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, @@ -956,7 +1008,7 @@ function extractFunctionInScope( else { if (callThis) { parameters.unshift( - ts.factory.createParameterDeclaration( + factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, @@ -965,16 +1017,16 @@ function extractFunctionInScope( checker.typeToTypeNode( checker.getTypeAtLocation(range.thisNode!), scope, - ts.NodeBuilderFlags.NoTruncation + NodeBuilderFlags.NoTruncation ), /*initializer*/ undefined, ) ); } - newFunction = ts.factory.createFunctionDeclaration( + newFunction = factory.createFunctionDeclaration( /*decorators*/ undefined, - range.facts & RangeFacts.IsAsyncFunction ? [ts.factory.createToken(ts.SyntaxKind.AsyncKeyword)] : undefined, - range.facts & RangeFacts.IsGenerator ? ts.factory.createToken(ts.SyntaxKind.AsteriskToken) : undefined, + range.facts & RangeFacts.IsAsyncFunction ? [factory.createToken(SyntaxKind.AsyncKeyword)] : undefined, + range.facts & RangeFacts.IsGenerator ? factory.createToken(SyntaxKind.AsteriskToken) : undefined, functionName, typeParameters, parameters, @@ -983,8 +1035,8 @@ function extractFunctionInScope( ); } - const changeTracker = ts.textChanges.ChangeTracker.fromContext(context); - const minInsertionPos = (isReadonlyArray(range.range) ? ts.last(range.range) : range.range).end; + const changeTracker = 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); @@ -994,67 +1046,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)], // TODO (acasey): test binding patterns + factory.createVariableDeclarationList( + [factory.createVariableDeclaration(getSynthesizedDeepClone(variableDeclaration.name), /*exclamationToken*/ undefined, /*type*/ getSynthesizedDeepClone(variableDeclaration.type), /*initializer*/ call)], // TODO (acasey): test binding patterns 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, @@ -1063,16 +1115,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)], @@ -1083,61 +1135,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); @@ -1145,32 +1197,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)]); } } @@ -1179,43 +1231,43 @@ 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 = 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( /*decorators*/ undefined, modifiers, localNameText, @@ -1223,14 +1275,14 @@ function extractConstantInScope( 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 @@ -1242,7 +1294,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). @@ -1255,21 +1307,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); @@ -1281,16 +1333,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); } @@ -1300,16 +1352,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 }; @@ -1317,7 +1369,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) { @@ -1327,9 +1379,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.decorators, 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. @@ -1337,46 +1389,46 @@ 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, node.modifiers, initializer.typeParameters, + if (isArrowFunction(initializer)) { + initializer = factory.updateArrowFunction(initializer, node.modifiers, 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( /* decorators */ undefined, /* 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, node.modifiers, initializer.asteriskToken, + initializer = factory.updateFunctionExpression(initializer, node.modifiers, 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; @@ -1387,7 +1439,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; @@ -1403,134 +1455,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) { @@ -1542,12 +1594,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) { @@ -1558,7 +1610,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; @@ -1566,26 +1618,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 @@ -1596,7 +1648,7 @@ function getPropertyAssignmentsForWritesAndVariableDeclarations( } function isReadonlyArray(v: any): v is readonly any[] { - return ts.isArray(v); + return isArray(v); } /** @@ -1608,9 +1660,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; } @@ -1623,62 +1675,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([]); @@ -1686,20 +1738,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); @@ -1707,16 +1759,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) => { @@ -1727,9 +1779,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); } @@ -1740,16 +1792,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++) { @@ -1759,41 +1811,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); } @@ -1801,11 +1853,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. @@ -1819,65 +1871,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 @@ -1903,18 +1955,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); } @@ -1936,8 +1988,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); } @@ -1950,20 +2002,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); @@ -1978,40 +2030,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)); } /** @@ -2021,48 +2073,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 85f4a7c054d7c..920f77bf41e18 100644 --- a/src/services/refactors/extractType.ts +++ b/src/services/refactors/extractType.ts @@ -1,46 +1,75 @@ -import * as ts from "../_namespaces/ts"; +import { addRange, append, cast, concatenate, emptyArray, forEach, pushIfUnique } from "../../compiler/core"; +import { Map } from "../../compiler/corePublic"; +import { Debug } from "../../compiler/debug"; +import { Diagnostics } from "../../compiler/diagnosticInformationMap.generated"; +import { ignoreSourceNewlines, setEmitFlags } from "../../compiler/factory/emitNode"; +import { factory } from "../../compiler/factory/nodeFactory"; +import { + isConditionalTypeNode, isIdentifier, isInferTypeNode, isIntersectionTypeNode, isJSDocTypeExpression, + isParenthesizedTypeNode, isThisTypeNode, isTupleTypeNode, isTypeLiteralNode, isTypeParameterDeclaration, + isTypePredicateNode, isTypeQueryNode, isTypeReferenceNode, +} from "../../compiler/factory/nodeTests"; +import { setTextRange } from "../../compiler/factory/utilitiesPublic"; +import { forEachChild } from "../../compiler/parser"; +import { getLineAndCharacterOfPosition, skipTrivia } from "../../compiler/scanner"; +import { + EmitFlags, JSDocTag, JSDocTemplateTag, Node, SourceFile, Statement, SymbolFlags, TextRange, TypeChecker, + TypeElement, TypeNode, TypeParameterDeclaration, +} from "../../compiler/types"; +import { addToSeen, getLocaleSpecificMessage, isSourceFileJS, isThisIdentifier } from "../../compiler/utilities"; +import { + findAncestor, getEffectiveConstraintOfTypeParameter, isFunctionLike, isStatement, isTypeNode, +} from "../../compiler/utilitiesPublic"; +import { registerRefactor } from "../refactorProvider"; +import { ChangeTracker, LeadingTriviaOption, TrailingTriviaOption } from "../textChanges"; +import { ApplicableRefactorInfo, RefactorContext, RefactorEditInfo } from "../types"; +import { + createTextRangeFromSpan, getNameFromPropertyName, getRefactorContextSpan, getRenameLocation, getTokenAtPosition, + getUniqueName, nodeOverlapsWithStartEnd, rangeContainsStartEnd, +} from "../utilities"; +import { isRefactorErrorInfo, RefactorErrorInfo } from "./helpers"; 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 +78,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 = 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,65 +184,65 @@ 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: ChangeTracker, file: SourceFile, name: string, info: TypeAliasInfo) { const { firstStatement, selection, typeParameters } = info; - const newTypeNode = ts.factory.createTypeAliasDeclaration( + const newTypeNode = factory.createTypeAliasDeclaration( /* decorators */ undefined, /* 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: LeadingTriviaOption.Exclude, trailingTriviaOption: TrailingTriviaOption.ExcludeWhitespace }); } -function doInterfaceChange(changes: ts.textChanges.ChangeTracker, file: ts.SourceFile, name: string, info: InterfaceInfo) { +function doInterfaceChange(changes: ChangeTracker, file: SourceFile, name: string, info: InterfaceInfo) { const { firstStatement, selection, typeParameters, typeElements } = info; - const newTypeNode = ts.factory.createInterfaceDeclaration( + const newTypeNode = factory.createInterfaceDeclaration( /* decorators */ undefined, /* modifiers */ undefined, name, @@ -221,35 +250,35 @@ function doInterfaceChange(changes: ts.textChanges.ChangeTracker, file: ts.Sourc /* 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: LeadingTriviaOption.Exclude, trailingTriviaOption: TrailingTriviaOption.ExcludeWhitespace }); } -function doTypedefChange(changes: ts.textChanges.ChangeTracker, file: ts.SourceFile, name: string, info: ExtractInfo) { +function doTypedefChange(changes: 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)))); } export { }; diff --git a/src/services/refactors/generateGetAccessorAndSetAccessor.ts b/src/services/refactors/generateGetAccessorAndSetAccessor.ts index 8b6d7c078d0d9..501ee9b53b843 100644 --- a/src/services/refactors/generateGetAccessorAndSetAccessor.ts +++ b/src/services/refactors/generateGetAccessorAndSetAccessor.ts @@ -1,35 +1,43 @@ -import * as ts from "../_namespaces/ts"; +import { emptyArray } from "../../compiler/core"; +import { Debug } from "../../compiler/debug"; +import { Diagnostics } from "../../compiler/diagnosticInformationMap.generated"; +import { isIdentifier, isParameter } from "../../compiler/factory/nodeTests"; +import { generateAccessorFromProperty, getAccessorConvertiblePropertyAtPosition } from "../codefixes/generateAccessors"; +import { registerRefactor } from "../refactorProvider"; +import { ApplicableRefactorInfo, RefactorContext } from "../types"; +import { getRenameLocation } from "../utilities"; +import { isRefactorErrorInfo } from "./helpers"; 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 = getAccessorConvertiblePropertyAtPosition(context.file, context.program, context.startPosition, context.endPosition); + Debug.assert(info && !isRefactorErrorInfo(info), "Expected applicable refactor info"); + const edits = 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 = 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,7 +53,7 @@ ts.refactor.registerRefactor(actionName, { }]; } - return ts.emptyArray; + return emptyArray; } }); diff --git a/src/services/refactors/inferFunctionReturnType.ts b/src/services/refactors/inferFunctionReturnType.ts index 5632aa7a36397..ae41e58e4d121 100644 --- a/src/services/refactors/inferFunctionReturnType.ts +++ b/src/services/refactors/inferFunctionReturnType.ts @@ -1,32 +1,46 @@ -import * as ts from "../_namespaces/ts"; +import { emptyArray, first, mapDefined } from "../../compiler/core"; +import { Diagnostics } from "../../compiler/diagnosticInformationMap.generated"; +import { factory } from "../../compiler/factory/nodeFactory"; +import { isArrowFunction, isBlock } from "../../compiler/factory/nodeTests"; +import { + ArrowFunction, FunctionDeclaration, FunctionExpression, MethodDeclaration, Node, NodeBuilderFlags, SourceFile, + SyntaxKind, Type, TypeChecker, TypeNode, +} from "../../compiler/types"; +import { getLocaleSpecificMessage, isInJSFile } from "../../compiler/utilities"; +import { findAncestor } from "../../compiler/utilitiesPublic"; +import { registerRefactor } from "../refactorProvider"; +import { ChangeTracker } from "../textChanges"; +import { ApplicableRefactorInfo, RefactorContext, RefactorEditInfo } from "../types"; +import { findChildOfKind, getTokenAtPosition } from "../utilities"; +import { isRefactorErrorInfo, RefactorErrorInfo, refactorKindBeginsWith } from "./helpers"; 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 = 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 +54,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: 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 471b14828639e..4feb86665e615 100644 --- a/src/services/refactors/moveToNewFile.ts +++ b/src/services/refactors/moveToNewFile.ts @@ -1,52 +1,95 @@ -import * as ts from "../_namespaces/ts"; +import { getSymbolId } from "../../compiler/checker"; +import { + append, cast, concatenate, contains, emptyArray, find, findIndex, firstDefined, flatMap, GetCanonicalFileName, + getRangesWhere, last, mapDefined, some, takeWhile, tryCast, +} from "../../compiler/core"; +import { Map } from "../../compiler/corePublic"; +import { Debug } from "../../compiler/debug"; +import { Diagnostics } from "../../compiler/diagnosticInformationMap.generated"; +import { factory } from "../../compiler/factory/nodeFactory"; +import { + isArrayLiteralExpression, isBinaryExpression, isBindingElement, isExpressionStatement, isExternalModuleReference, + isIdentifier, isImportDeclaration, isImportEqualsDeclaration, isObjectLiteralExpression, isOmittedExpression, + isPropertyAccessExpression, isPropertyAssignment, isSourceFile, isStringLiteral, isVariableDeclaration, + isVariableDeclarationList, isVariableStatement, +} from "../../compiler/factory/nodeTests"; +import { + combinePaths, ensurePathIsNonModuleName, getBaseFileName, getDirectoryPath, getRelativePathFromFile, normalizePath, +} from "../../compiler/path"; +import { + AnyImportOrRequireStatement, AssignmentDeclarationKind, BinaryExpression, BindingElement, BindingName, + CallExpression, ClassDeclaration, Declaration, DeclarationStatement, EnumDeclaration, Expression, + ExpressionStatement, ExternalModuleReference, FunctionDeclaration, Identifier, ImportDeclaration, + ImportEqualsDeclaration, InterfaceDeclaration, InternalSymbolName, ModifierFlags, ModuleDeclaration, + NamedImportBindings, Node, NodeFlags, Program, PropertyAccessExpression, PropertyAssignment, RequireOrImportCall, + RequireVariableStatement, ScriptTarget, SourceFile, Statement, StringLiteralLike, Symbol, SymbolFlags, SyntaxKind, + TransformFlags, TypeAliasDeclaration, TypeChecker, TypeNode, UserPreferences, VariableDeclaration, + VariableDeclarationList, VariableStatement, +} from "../../compiler/types"; +import { + copyEntries, extensionFromPath, forEachEntry, getAssignmentDeclarationKind, getLocaleSpecificMessage, + hasSyntacticModifier, hostGetCanonicalFileName, isDeclarationName, isPrologueDirective, isRequireCall, + removeFileExtension, skipAlias, +} from "../../compiler/utilities"; +import { escapeLeadingUnderscores, isNamedDeclaration, isStringLiteralLike } from "../../compiler/utilitiesPublic"; +import { moduleSpecifierToValidIdentifier } from "../codefixes/importFixes"; +import { Core } from "../findAllReferences"; +import { registerRefactor } from "../refactorProvider"; +import { ChangeTracker } from "../textChanges"; +import { ApplicableRefactorInfo, LanguageServiceHost, RefactorContext, RefactorEditInfo } from "../types"; +import { + createTextRangeFromSpan, getPropertySymbolFromBindingElement, getQuotePreference, getRefactorContextSpan, + getUniqueName, insertImports, makeImportIfNecessary, nodeSeenTracker, ObjectBindingElementWithoutPropertyName, + QuotePreference, rangeContainsRange, symbolNameNoDefault, +} from "../utilities"; 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 = 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 +99,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: 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.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: 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: 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 && !oldFile.commonJsModuleIndicator) { 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 +198,7 @@ function getNewStatementsAndRemoveFromOldFile( return [ ...prologueDirectives, ...imports, - ts.SyntaxKind.NewLineTrivia as const, + SyntaxKind.NewLineTrivia as const, ...body ]; } @@ -167,20 +210,20 @@ function getNewStatementsAndRemoveFromOldFile( ]; } -function deleteMovedStatements(sourceFile: ts.SourceFile, moved: readonly StatementRange[], changes: ts.textChanges.ChangeTracker) { +function deleteMovedStatements(sourceFile: SourceFile, moved: readonly StatementRange[], changes: 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: 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: 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 +231,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 +249,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: 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 = 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[] = []; + 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( /*decorators*/ undefined, /*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(/*decorators*/ undefined, /*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(/*decorators*/ undefined, /*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 +337,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 +359,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 +394,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: 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: 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 +429,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,24 +440,24 @@ 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: ChangeTracker, isUnused: (name: Identifier) => boolean) { const { name } = varDecl; switch (name.kind) { - case ts.SyntaxKind.Identifier: + case SyntaxKind.Identifier: if (isUnused(name)) { 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); } } @@ -424,25 +467,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: 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; @@ -456,7 +499,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 { @@ -465,21 +508,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(movedSymbols: ReadonlySymbolSet): string { - return movedSymbols.forEachEntry(ts.symbolNameNoDefault) || "newFile"; + return movedSymbols.forEachEntry(symbolNameNoDefault) || "newFile"; } interface UsageInfo { @@ -495,12 +538,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); @@ -508,7 +551,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) { @@ -529,10 +572,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); } @@ -544,7 +587,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; } @@ -554,9 +597,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; } @@ -564,73 +607,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(/*decorators*/ undefined, /*modifiers*/ undefined, ts.factory.createImportClause(/*isTypeOnly*/ false, defaultImport, namedBindings), moduleSpecifier, /*assertClause*/ undefined) + ? factory.createImportDeclaration(/*decorators*/ undefined, /*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); } @@ -641,129 +684,129 @@ function forEachReference(node: ts.Node, checker: ts.TypeChecker, onReference: ( } interface ReadonlySymbolSet { - 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; } } -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: 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); @@ -771,71 +814,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 getNamesToExportInCommonJS(decl).some(name => sourceFile.symbol.exports!.has(ts.escapeLeadingUnderscores(name))); + return 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.concatenate([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], d.modifiers); + const modifiers = concatenate([factory.createModifier(SyntaxKind.ExportKeyword)], d.modifiers); switch (d.kind) { - case ts.SyntaxKind.FunctionDeclaration: - return ts.factory.updateFunctionDeclaration(d, d.decorators, modifiers, d.asteriskToken, d.name, d.typeParameters, d.parameters, d.type, d.body); - case ts.SyntaxKind.ClassDeclaration: - return ts.factory.updateClassDeclaration(d, d.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, d.decorators, modifiers, d.name, d.body); - case ts.SyntaxKind.EnumDeclaration: - return ts.factory.updateEnumDeclaration(d, d.decorators, modifiers, d.name, d.members); - case ts.SyntaxKind.TypeAliasDeclaration: - return ts.factory.updateTypeAliasDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.type); - case ts.SyntaxKind.InterfaceDeclaration: - return ts.factory.updateInterfaceDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.heritageClauses, d.members); - case ts.SyntaxKind.ImportEqualsDeclaration: - return ts.factory.updateImportEqualsDeclaration(d, d.decorators, 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, d.decorators, modifiers, d.asteriskToken, d.name, d.typeParameters, d.parameters, d.type, d.body); + case SyntaxKind.ClassDeclaration: + return factory.updateClassDeclaration(d, d.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, d.decorators, modifiers, d.name, d.body); + case SyntaxKind.EnumDeclaration: + return factory.updateEnumDeclaration(d, d.decorators, modifiers, d.name, d.members); + case SyntaxKind.TypeAliasDeclaration: + return factory.updateTypeAliasDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.type); + case SyntaxKind.InterfaceDeclaration: + return factory.updateInterfaceDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.heritageClauses, d.members); + case SyntaxKind.ImportEqualsDeclaration: + return factory.updateImportEqualsDeclaration(d, d.decorators, 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))); } export { }; diff --git a/src/services/rename.ts b/src/services/rename.ts index 4b6af946b1db0..f39d437e13a44 100644 --- a/src/services/rename.ts +++ b/src/services/rename.ts @@ -1,31 +1,51 @@ -import * as ts from "./_namespaces/ts"; +import { endsWith, every, find, tryRemoveSuffix } from "../compiler/core"; +import { Diagnostics } from "../compiler/diagnosticInformationMap.generated"; +import { isIdentifier, isSourceFile } from "../compiler/factory/nodeTests"; +import { fileExtensionIs } from "../compiler/path"; +import { + DiagnosticMessage, Extension, Node, NumericLiteral, Program, SourceFile, StringLiteralLike, Symbol, SymbolFlags, + SyntaxKind, TypeChecker, TypeFlags, UnionType, +} from "../compiler/types"; +import { + getLocaleSpecificMessage, getTextOfIdentifierOrLiteral, getTextOfNode, isStringOrNumericLiteralLike, + removeFileExtension, stripQuotes, tryGetImportFromModuleSpecifier, +} from "../compiler/utilities"; +import { createTextSpan, isExternalModuleNameRelative, isStringLiteralLike } from "../compiler/utilitiesPublic"; +import { getSymbolKind, getSymbolModifiers } from "./symbolDisplay"; +import { + RenameInfo, RenameInfoFailure, RenameInfoOptions, RenameInfoSuccess, ScriptElementKind, ScriptElementKindModifier, +} from "./types"; +import { + getAdjustedRenameLocation, getContextualTypeFromParentOrAncestorTypeNode, getTouchingPropertyName, + isImportOrExportSpecifierName, isLabelName, isLiteralNameOfPropertyDeclarationOrIndexAccess, +} from "./utilities"; /* @internal */ -export function getRenameInfo(program: ts.Program, sourceFile: ts.SourceFile, position: number, options?: ts.RenameInfoOptions): ts.RenameInfo { - const node = ts.getAdjustedRenameLocation(ts.getTouchingPropertyName(sourceFile, position)); +export function getRenameInfo(program: Program, sourceFile: SourceFile, position: number, options?: RenameInfoOptions): RenameInfo { + const node = getAdjustedRenameLocation(getTouchingPropertyName(sourceFile, position)); if (nodeIsEligibleForRename(node)) { const renameInfo = getRenameInfoForNode(node, program.getTypeChecker(), sourceFile, program, options); 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, options?: ts.RenameInfoOptions): ts.RenameInfo | undefined { +function getRenameInfoForNode(node: Node, typeChecker: TypeChecker, sourceFile: SourceFile, program: Program, options?: RenameInfoOptions): 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; } @@ -35,57 +55,57 @@ function getRenameInfoForNode(node: ts.Node, typeChecker: ts.TypeChecker, source // 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 options && options.allowRenameOfImportPath ? getRenameInfoForModule(node, sourceFile, symbol) : undefined; } - 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 = 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, 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 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, @@ -97,32 +117,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 9cf8b9ddb0ec7..4ceaa56443a31 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1,53 +1,155 @@ +import { getFileEmitOutput } from "../compiler/builderState"; +import { ParseConfigFileHost, parseJsonSourceFileConfigFileContent } from "../compiler/commandLineParser"; +import { + compareValues, createGetCanonicalFileName, createMultiMap, deduplicate, emptyArray, equateValues, filter, find, + first, firstDefined, flatMap, forEach, GetCanonicalFileName, getEntries, hasProperty, identity, insertSorted, + isArray, isString, lastOrUndefined, map, mapDefined, maybeBind, noop, returnFalse, singleElementArray, + stringContains, +} from "../compiler/core"; +import { ESMap, Map, MapLike, Push, Set, SortedArray } from "../compiler/corePublic"; +import { Debug } from "../compiler/debug"; +import { + isComputedPropertyName, isIdentifier, isJsxAttributes, isJsxClosingElement, isJsxElement, isJsxFragment, + isJsxOpeningElement, isJsxOpeningFragment, isJsxText, isNamedExports, isNamedTupleMember, isNewExpression, + isObjectLiteralExpression, isPrivateIdentifier, isPropertyAccessExpression, +} from "../compiler/factory/nodeTests"; +import { ModeAwareCache } from "../compiler/moduleNameResolver"; +import { + createSourceFile, CreateSourceFileOptions, forEachChild, tagNamesAreEquivalent, updateSourceFile, +} from "../compiler/parser"; +import { combinePaths, getDirectoryPath, getNormalizedAbsolutePath, normalizePath, toPath } from "../compiler/path"; +import { timestamp } from "../compiler/performanceCore"; +import { createProgram, getImpliedNodeFormatForFile, isProgramUptoDate } from "../compiler/program"; +import { computePositionOfLineAndCharacter, getLineAndCharacterOfPosition, getLineStarts } from "../compiler/scanner"; +import { tracing } from "../compiler/tracing"; +import { + __String, AssignmentDeclarationKind, BaseType, BinaryExpression, CancellationToken, CharacterCodes, + CheckJsDirective, CompilerHost, CompilerOptions, CreateProgramOptions, Declaration, Diagnostic, + DiagnosticWithLocation, ElementAccessExpression, EmitTextWriter, EndOfFileToken, EntityName, ExportDeclaration, + FileReference, FunctionLikeDeclaration, GeneratedIdentifierFlags, HasInvalidatedResolution, Identifier, + ImportDeclaration, IndexKind, IndexType, InterfaceType, IntersectionType, JSDoc, JSDocContainer, JsonSourceFile, + JsxAttributes, JsxElement, JsxEmit, JsxFragment, LanguageVariant, LineAndCharacter, LiteralType, ModifierFlags, + ModuleDeclaration, Node, NodeArray, NodeFlags, NumberLiteralType, NumericLiteral, ObjectFlags, ObjectLiteralElement, + ObjectLiteralExpression, OperationCanceledException, ParsedCommandLine, Path, PragmaMap, PrivateIdentifier, Program, + PropertyName, ResolvedModuleFull, ResolvedProjectReference, ResolvedTypeReferenceDirective, ScriptKind, + ScriptTarget, Signature, SignatureDeclaration, SignatureFlags, SignatureKind, SourceFile, SourceFileLike, + SourceMapSource, Statement, StringLiteral, StringLiteralLike, StringLiteralType, Symbol, SymbolFlags, SyntaxKind, + SyntaxList, TextChangeRange, TextRange, TextSpan, Token, TransformFlags, TransientSymbol, Type, TypeChecker, + TypeFlags, TypeNode, TypeParameter, TypePredicate, TypeReference, UnderscoreEscapedMap, UnionOrIntersectionType, + UnionType, UserPreferences, VariableDeclaration, +} from "../compiler/types"; +import { + directoryProbablyExists, getAllSuperTypeNodes, getAssignmentDeclarationKind, getEmitDeclarations, + getEscapedTextOfIdentifierOrLiteral, getNewLineCharacter, getObjectFlags, getSetExternalModuleIndicator, + getSourceFileOfNode, getTokenPosOfNode, hasStaticModifier, hasSyntacticModifier, hostGetCanonicalFileName, + hostUsesCaseSensitiveFileNames, isDeclarationName, isImportMeta, isIntrinsicJsxName, + isLiteralComputedPropertyDeclarationName, isStringOrNumericLiteralLike, isThisTypeParameter, + maybeSetLocalizedDiagnosticMessages, ObjectAllocator, positionIsSynthesized, setObjectAllocator, +} from "../compiler/utilities"; +import { + createTextSpanFromBounds, getDefaultLibFileName, getJSDocTags, getNonAssignedNameOfDeclaration, hasJSDocNodes, + idText, isBindingPattern, isConstTypeReference, isGetAccessor, isJSDocCommentContainingNode, isNodeKind, + isObjectLiteralElement, isPropertyName, isSetAccessor, symbolName, textSpanEnd, +} from "../compiler/utilitiesPublic"; import * as ts from "./_namespaces/ts"; +import { + Completions, GoToDefinition, InlayHints, JsDoc, NavigateTo, NavigationBar, OrganizeImports, refactor, Rename, + SignatureHelp, SmartSelectionRange, +} from "./_namespaces/ts"; +import { v2020 } from "./_namespaces/ts.classifier"; +import { spanInSourceFileAtLocation } from "./breakpoints"; +import { + createCallHierarchyItem, getIncomingCalls, getOutgoingCalls, resolveCallHierarchyDeclaration, +} from "./callHierarchy"; +import { getAllFixes, getFixes, getSupportedErrorCodes } from "./codeFixProvider"; +import { DocumentHighlights } from "./documentHighlights"; +import { createDocumentRegistry, DocumentRegistry } from "./documentRegistry"; +import { + Core, findReferencedSymbols, findReferenceOrRenameEntries, FindReferencesUse, getImplementationsAtPosition, Options, + toContextSpan, toReferenceEntry, ToReferenceOrRenameEntry, toRenameLocation, +} from "./findAllReferences"; +import { + formatDocument, formatOnClosingCurly, formatOnEnter, formatOnOpeningCurly, formatOnSemicolon, formatSelection, + getRangeOfEnclosingComment, +} from "./formatting/formatting"; +import { getFormatContext } from "./formatting/rulesMap"; +import { SmartIndenter } from "./formatting/smartIndenter"; +import { getJsDocCommentsFromDeclarations, getJsDocTagsFromDeclarations } from "./jsDoc"; +import { collectElements } from "./outliningElementsCollector"; +import { nodeIsEligibleForRename } from "./rename"; +import { getSourceMapper } from "./sourcemaps"; +import { computeSuggestionDiagnostics } from "./suggestionDiagnostics"; +import { getSymbolDisplayPartsDocumentationAndSymbolKind, getSymbolModifiers } from "./symbolDisplay"; +import { + ApplicableRefactorInfo, ApplyCodeActionCommandResult, CallHierarchyIncomingCall, CallHierarchyItem, + CallHierarchyOutgoingCall, Classifications, ClassifiedSpan, ClassifiedSpan2020, CodeActionCommand, CodeFixAction, + CombinedCodeActions, CombinedCodeFixScope, CompletionEntryData, CompletionEntryDetails, CompletionInfo, + DefinitionInfo, DefinitionInfoAndBoundSpan, DocCommentTemplateOptions, EditorOptions, EditorSettings, emptyOptions, + FileTextChanges, FormatCodeOptions, FormatCodeSettings, GetCompletionsAtPositionOptions, HighlightSpanKind, + HostCancellationToken, ImplementationLocation, InlayHint, InlayHintsContext, IScriptSnapshot, JSDocTagInfo, + JsxClosingTagInfo, LanguageService, LanguageServiceHost, LanguageServiceMode, NavigateToItem, NavigationBarItem, + NavigationTree, OrganizeImportsArgs, OutliningSpan, QuickInfo, RefactorContext, RefactorEditInfo, + RefactorTriggerReason, ReferencedSymbol, ReferenceEntry, RenameInfo, RenameInfoOptions, RenameLocation, + ScriptElementKind, ScriptElementKindModifier, SelectionRange, SemanticClassificationFormat, SignatureHelpItems, + SignatureHelpItemsOptions, SymbolDisplayPart, TextChange, TextInsertion, TodoComment, TodoCommentDescriptor, +} from "./types"; +import { + createTextSpanFromNode, createTextSpanFromRange, findChildOfKind, findPrecedingToken, firstOrOnly, + getAdjustedRenameLocation, getContainerNode, getNameFromPropertyName, getNewLineOrDefaultFromHost, getScriptKind, + getSnapshotText, getTouchingPropertyName, getTouchingToken, isInComment, isInsideJsxElement, + isInsideJsxElementOrAttribute, isInString, isInTemplateString, isLabelName, isNameOfModuleDeclaration, + isRightSideOfPropertyAccess, isRightSideOfQualifiedName, isTagName, isTextWhiteSpaceLike, lineBreakPart, + mapOneOrMany, PossibleProgramFileInfo, scanner, typeToDisplayParts, +} from "./utilities"; /** 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 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 +162,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 +172,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 +190,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 +248,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 +303,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 +340,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 +348,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 +367,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 +388,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 +426,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,16 +445,16 @@ 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[] { switch (context?.kind) { - case ts.SyntaxKind.GetAccessor: + case SyntaxKind.GetAccessor: if (!this.contextualGetAccessorDocumentationComment) { - this.contextualGetAccessorDocumentationComment = getDocumentationComment(ts.filter(this.declarations, ts.isGetAccessor), checker); + this.contextualGetAccessorDocumentationComment = getDocumentationComment(filter(this.declarations, isGetAccessor), checker); } return this.contextualGetAccessorDocumentationComment; - case ts.SyntaxKind.SetAccessor: + case SyntaxKind.SetAccessor: if (!this.contextualSetAccessorDocumentationComment) { - this.contextualSetAccessorDocumentationComment = getDocumentationComment(ts.filter(this.declarations, ts.isSetAccessor), checker); + this.contextualSetAccessorDocumentationComment = getDocumentationComment(filter(this.declarations, isSetAccessor), checker); } return this.contextualSetAccessorDocumentationComment; default: @@ -360,7 +462,7 @@ class SymbolObject implements ts.Symbol { } } - getJsDocTags(checker?: ts.TypeChecker): ts.JSDocTagInfo[] { + getJsDocTags(checker?: TypeChecker): JSDocTagInfo[] { if (this.tags === undefined) { this.tags = getJsDocTagsOfDeclarations(this.declarations, checker); } @@ -368,16 +470,16 @@ 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[] { switch (context?.kind) { - case ts.SyntaxKind.GetAccessor: + case SyntaxKind.GetAccessor: if (!this.contextualGetAccessorTags) { - this.contextualGetAccessorTags = getJsDocTagsOfDeclarations(ts.filter(this.declarations, ts.isGetAccessor), checker); + this.contextualGetAccessorTags = getJsDocTagsOfDeclarations(filter(this.declarations, isGetAccessor), checker); } return this.contextualGetAccessorTags; - case ts.SyntaxKind.SetAccessor: + case SyntaxKind.SetAccessor: if (!this.contextualSetAccessorTags) { - this.contextualSetAccessorTags = getJsDocTagsOfDeclarations(ts.filter(this.declarations, ts.isSetAccessor), checker); + this.contextualSetAccessorTags = getJsDocTagsOfDeclarations(filter(this.declarations, isSetAccessor), checker); } return this.contextualSetAccessorTags; default: @@ -386,7 +488,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) { @@ -395,10 +497,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; @@ -406,170 +508,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.StringOrNumberLiteral); + isLiteral(): this is LiteralType { + return !!(this.flags & TypeFlags.StringOrNumberLiteral); } - 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); @@ -578,12 +680,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)); } } @@ -592,21 +694,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 = 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; @@ -620,113 +722,113 @@ 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 = 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 symbol = isStaticMember - ? ts.find(checker.getExportsOfModule(baseType.symbol), s => s.escapedName === declaration.symbol.name) + ? find(checker.getExportsOfModule(baseType.symbol), s => s.escapedName === declaration.symbol.name) : checker.getPropertyOfType(baseType, declaration.symbol.name); return symbol ? cb(symbol) : undefined; }); } -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 { @@ -746,7 +848,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(); } @@ -754,14 +856,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); @@ -776,30 +878,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; } } @@ -807,39 +909,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) { @@ -847,19 +949,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); @@ -867,8 +969,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"; @@ -880,39 +982,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, @@ -933,22 +1035,22 @@ function getServicesObjectAllocator(): ts.ObjectAllocator { interface HostFileInformation { hostFileName: string; version: string; - scriptSnapshot: ts.IScriptSnapshot; - scriptKind: ts.ScriptKind; + scriptSnapshot: IScriptSnapshot; + scriptKind: ScriptKind; } /* @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; } @@ -956,9 +1058,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]; } @@ -970,24 +1072,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 getSupportedErrorCodes(); } // Either it will be file name if host doesnt have file or it will be the host's file information @@ -997,24 +1099,24 @@ type CachedHostFileInformation = HostFileInformation | string; // at each language service public entry point, since we don't know when // the set of scripts handled by the host changes. class HostCache { - private fileNameToEntry: ts.ESMap; + private fileNameToEntry: ESMap; private currentDirectory: string; - constructor(private host: ts.LanguageServiceHost, getCanonicalFileName: ts.GetCanonicalFileName) { + constructor(private host: LanguageServiceHost, getCanonicalFileName: GetCanonicalFileName) { // script id => script index this.currentDirectory = host.getCurrentDirectory(); - this.fileNameToEntry = new ts.Map(); + this.fileNameToEntry = new Map(); // Initialize the list with the root file names const rootFileNames = host.getScriptFileNames(); - ts.tracing?.push(ts.tracing.Phase.Session, "initializeHostCache", { count: rootFileNames.length }); + tracing?.push(tracing.Phase.Session, "initializeHostCache", { count: rootFileNames.length }); for (const fileName of rootFileNames) { - this.createEntry(fileName, ts.toPath(fileName, this.currentDirectory, getCanonicalFileName)); + this.createEntry(fileName, toPath(fileName, this.currentDirectory, getCanonicalFileName)); } - ts.tracing?.pop(); + tracing?.pop(); } - private createEntry(fileName: string, path: ts.Path) { + private createEntry(fileName: string, path: Path) { let entry: CachedHostFileInformation; const scriptSnapshot = this.host.getScriptSnapshot(fileName); if (scriptSnapshot) { @@ -1022,7 +1124,7 @@ class HostCache { hostFileName: fileName, version: this.host.getScriptVersion(fileName), scriptSnapshot, - scriptKind: ts.getScriptKind(fileName, this.host) + scriptKind: getScriptKind(fileName, this.host) }; } else { @@ -1033,24 +1135,24 @@ class HostCache { return entry; } - public getEntryByPath(path: ts.Path): CachedHostFileInformation | undefined { + public getEntryByPath(path: Path): CachedHostFileInformation | undefined { return this.fileNameToEntry.get(path); } - public getHostFileInformation(path: ts.Path): HostFileInformation | undefined { + public getHostFileInformation(path: Path): HostFileInformation | undefined { const entry = this.fileNameToEntry.get(path); - return !ts.isString(entry) ? entry : undefined; + return !isString(entry) ? entry : undefined; } - public getOrCreateEntryByPath(fileName: string, path: ts.Path): HostFileInformation { + public getOrCreateEntryByPath(fileName: string, path: Path): HostFileInformation { const info = this.getEntryByPath(path) || this.createEntry(fileName, path); - return ts.isString(info) ? undefined! : info; // TODO: GH#18217 + return isString(info) ? undefined! : info; // TODO: GH#18217 } public getRootFileNames(): string[] { const names: string[] = []; this.fileNameToEntry.forEach(entry => { - if (ts.isString(entry)) { + if (isString(entry)) { names.push(entry); } else { @@ -1060,7 +1162,7 @@ class HostCache { return names; } - public getScriptSnapshot(path: ts.Path): ts.IScriptSnapshot { + public getScriptSnapshot(path: Path): IScriptSnapshot { const file = this.getHostFileInformation(path); return (file && file.scriptSnapshot)!; // TODO: GH#18217 } @@ -1071,34 +1173,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); } @@ -1120,18 +1222,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) { @@ -1144,8 +1246,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) { @@ -1163,7 +1265,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 @@ -1182,7 +1284,7 @@ export function updateLanguageServiceSourceFile(sourceFile: ts.SourceFile, scrip } } - const options: ts.CreateSourceFileOptions = { + const options: CreateSourceFileOptions = { languageVersion: sourceFile.languageVersion, impliedNodeFormat: sourceFile.impliedNodeFormat, setExternalModuleIndicator: sourceFile.setExternalModuleIndicator, @@ -1191,13 +1293,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 { @@ -1206,25 +1308,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 @@ -1237,13 +1339,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", @@ -1263,7 +1365,7 @@ const invalidOperationsInPartialSemanticMode: readonly (keyof ts.LanguageService "provideInlayHints" ]; -const invalidOperationsInSyntacticMode: readonly (keyof ts.LanguageService)[] = [ +const invalidOperationsInSyntacticMode: readonly (keyof LanguageService)[] = [ ...invalidOperationsInPartialSemanticMode, "getCompletionsAtPosition", "getCompletionEntryDetails", @@ -1284,24 +1386,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; @@ -1312,7 +1414,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) { @@ -1320,24 +1422,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. @@ -1349,7 +1451,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(); @@ -1373,22 +1475,22 @@ export function createLanguageService( let hostCache: HostCache | undefined = new HostCache(host, getCanonicalFileName); const rootFileNames = hostCache.getRootFileNames(); const newSettings = host.getCompilationSettings() || getDefaultCompilerOptions(); - const hasInvalidatedResolution: ts.HasInvalidatedResolution = host.hasInvalidatedResolution || ts.returnFalse; - const hasChangedAutomaticTypeDirectiveNames = ts.maybeBind(host, host.hasChangedAutomaticTypeDirectiveNames); + const hasInvalidatedResolution: HasInvalidatedResolution = host.hasInvalidatedResolution || returnFalse; + const hasChangedAutomaticTypeDirectiveNames = maybeBind(host, host.hasChangedAutomaticTypeDirectiveNames); const projectReferences = host.getProjectReferences?.(); - let parsedCommandLines: ts.ESMap | undefined; - const parseConfigHost: ts.ParseConfigFileHost = { + let parsedCommandLines: ESMap | undefined; + const parseConfigHost: ParseConfigFileHost = { useCaseSensitiveFileNames, fileExists, readFile, readDirectory, - trace: ts.maybeBind(host, host.trace), + trace: maybeBind(host, host.trace), getCurrentDirectory: () => currentDirectory, - onUnRecoverableConfigFileDiagnostic: ts.noop, + onUnRecoverableConfigFileDiagnostic: noop, }; // If the program is already up-to-date, we can reuse it - if (ts.isProgramUptoDate(program, rootFileNames, newSettings, (_path, fileName) => host.getScriptVersion(fileName), fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { + if (isProgramUptoDate(program, rootFileNames, newSettings, (_path, fileName) => host.getScriptVersion(fileName), fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { return; } @@ -1399,22 +1501,22 @@ export function createLanguageService( // incremental parsing. // Now create a new compiler - const compilerHost: ts.CompilerHost = { + const compilerHost: CompilerHost = { 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, readFile, - 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) : []; @@ -1425,23 +1527,23 @@ export function createLanguageService( hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, trace: parseConfigHost.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), + resolveModuleNames: maybeBind(host, host.resolveModuleNames), + getModuleResolutionCache: maybeBind(host, host.getModuleResolutionCache), + resolveTypeReferenceDirectives: maybeBind(host, host.resolveTypeReferenceDirectives), + useSourceOfProjectReferenceRedirect: maybeBind(host, host.useSourceOfProjectReferenceRedirect), getParsedCommandLine, }; host.setCompilerHost?.(compilerHost); const documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings); - const options: ts.CreateProgramOptions = { + const options: CreateProgramOptions = { rootNames: rootFileNames, options: newSettings, host: compilerHost, oldProgram: program, projectReferences }; - program = ts.createProgram(options); + program = createProgram(options); // hostCache is captured in the closure for 'getOrCreateSourceFile' but it should not be used past this point. // It needs to be cleared to allow all collected snapshots to be released @@ -1458,34 +1560,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); } @@ -1495,41 +1597,41 @@ export function createLanguageService( } function fileExists(fileName: string): boolean { - const path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); + const path = toPath(fileName, currentDirectory, getCanonicalFileName); const entry = hostCache && hostCache.getEntryByPath(path); return entry ? - !ts.isString(entry) : + !isString(entry) : (!!host.fileExists && host.fileExists(fileName)); } function readFile(fileName: string) { // stub missing host functionality - const path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); + const path = toPath(fileName, currentDirectory, getCanonicalFileName); const entry = hostCache && hostCache.getEntryByPath(path); if (entry) { - return ts.isString(entry) ? undefined : ts.getSnapshotText(entry.scriptSnapshot); + return isString(entry) ? undefined : getSnapshotText(entry.scriptSnapshot); } return host.readFile && host.readFile(fileName); } function 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); } // 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); } - function getOrCreateSourceFile(fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): ts.SourceFile | undefined { - return getOrCreateSourceFileByPath(fileName, ts.toPath(fileName, currentDirectory, getCanonicalFileName), languageVersion, onError, shouldCreateNewSourceFile); + function getOrCreateSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined { + return getOrCreateSourceFileByPath(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), languageVersion, onError, shouldCreateNewSourceFile); } - function getOrCreateSourceFileByPath(fileName: string, path: ts.Path, _languageVersion: ts.ScriptTarget, _onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): ts.SourceFile | undefined { - ts.Debug.assert(hostCache !== undefined, "getOrCreateSourceFileByPath called after typical CompilerHost lifetime, check the callstack something with a reference to an old host."); + function getOrCreateSourceFileByPath(fileName: string, path: Path, _languageVersion: ScriptTarget, _onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined { + Debug.assert(hostCache !== undefined, "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. @@ -1588,9 +1690,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; } @@ -1599,7 +1701,7 @@ export function createLanguageService( return program; } - function getAutoImportProvider(): ts.Program | undefined { + function getAutoImportProvider(): Program | undefined { return host.getPackageJsonAutoImportProvider?.(); } @@ -1611,7 +1713,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)); program = undefined!; // TODO: GH#18217 } @@ -1619,7 +1721,7 @@ export function createLanguageService( } /// Diagnostics - function getSyntacticDiagnostics(fileName: string): ts.DiagnosticWithLocation[] { + function getSyntacticDiagnostics(fileName: string): DiagnosticWithLocation[] { synchronizeHostData(); return program.getSyntacticDiagnostics(getValidSourceFile(fileName), cancellationToken).slice(); @@ -1629,7 +1731,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); @@ -1638,7 +1740,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(); } @@ -1647,9 +1749,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() { @@ -1657,15 +1759,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, @@ -1675,34 +1777,34 @@ export function createLanguageService( options.triggerCharacter, options.triggerKind, cancellationToken, - formattingSettings && ts.formatting.getFormatContext(formattingSettings, host)); + formattingSettings && 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 && 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; @@ -1715,159 +1817,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) + getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, getContainerNode(nodeForQuickInfo), nodeForQuickInfo) ); return { kind: symbolKind, - kindModifiers: ts.SymbolDisplay.getSymbolModifiers(typeChecker, symbol), - textSpan: ts.createTextSpanFromNode(nodeForQuickInfo, sourceFile), + kindModifiers: 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 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 (!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) + ...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: FindReferencesUse.Rename }, + (entry, originalNode, checker) => 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: FindReferencesUse.References }, 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: Options, cb: 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 === FindReferencesUse.Rename ? program.getSourceFiles().filter(sourceFile => !program.isSourceFileDefaultLibrary(sourceFile)) : program.getSourceFiles(); - return ts.FindAllReferences.findReferenceOrRenameEntries(program, cancellationToken, sourceFiles, node, position, options, cb); + return 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 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 Core.getReferencesForFileName(fileName, program, program.getSourceFiles()).map(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) { @@ -1875,47 +1977,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 @@ -1925,18 +2027,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 @@ -1949,179 +2051,179 @@ 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 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 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 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 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 = 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 formatSelection(start, end, sourceFile, 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 formatDocument(syntaxTreeCache.getCurrentSourceFile(fileName), 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 = getFormatContext(toEditorSettings(options), host); - if (!ts.isInComment(sourceFile, position)) { + if (!isInComment(sourceFile, position)) { switch (key) { case "{": - return ts.formatting.formatOnOpeningCurly(position, sourceFile, formatContext); + return formatOnOpeningCurly(position, sourceFile, formatContext); case "}": - return ts.formatting.formatOnClosingCurly(position, sourceFile, formatContext); + return formatOnClosingCurly(position, sourceFile, formatContext); case ";": - return ts.formatting.formatOnSemicolon(position, sourceFile, formatContext); + return formatOnSemicolon(position, sourceFile, formatContext); case "\n": - return ts.formatting.formatOnEnter(position, sourceFile, formatContext); + return 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 = 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 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 = getFormatContext(formatOptions, host); - return ts.codefix.getAllFixes({ fixId, sourceFile, program, host, cancellationToken, formatContext, preferences }); + return 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 = getFormatContext(formatOptions, host); - return ts.OrganizeImports.organizeImports(sourceFile, formatContext, host, program, preferences, args.skipDestructiveCodeActions); + return OrganizeImports.organizeImports(sourceFile, formatContext, host, program, preferences, args.skipDestructiveCodeActions); } - 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, 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 { @@ -2131,52 +2233,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, @@ -2184,16 +2286,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. @@ -2250,17 +2352,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 ? "*/}" : "*/"; @@ -2271,7 +2373,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) { @@ -2282,7 +2384,7 @@ export function createLanguageService( } positions.push(commentRange.pos); - if (commentRange.kind === ts.SyntaxKind.MultiLineCommentTrivia) { + if (commentRange.kind === SyntaxKind.MultiLineCommentTrivia) { positions.push(commentRange.end); } @@ -2294,7 +2396,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; } } @@ -2302,10 +2404,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]; @@ -2371,7 +2473,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); @@ -2381,26 +2483,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)); } @@ -2411,22 +2513,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 = 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 @@ -2440,7 +2542,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)) { @@ -2468,24 +2570,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. @@ -2537,7 +2639,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 */). @@ -2563,22 +2665,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, options?: ts.RenameInfoOptions): ts.RenameInfo { + function getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo { synchronizeHostData(); - return ts.Rename.getRenameInfo(program, getValidSourceFile(fileName), position, options); + return Rename.getRenameInfo(program, getValidSourceFile(fileName), position, options); } - 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, @@ -2586,7 +2688,7 @@ export function createLanguageService( endPosition, program: getProgram()!, host, - formatContext: ts.formatting.getFormatContext(formatOptions!, host), // TODO: GH#18217 + formatContext: getFormatContext(formatOptions!, host), // TODO: GH#18217 cancellationToken, preferences, triggerReason, @@ -2594,7 +2696,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()!, @@ -2605,30 +2707,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 @@ -2639,33 +2741,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 = resolveCallHierarchyDeclaration(program, getTouchingPropertyName(getValidSourceFile(fileName), position)); + return declarations && mapOneOrMany(declarations, declaration => 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(resolveCallHierarchyDeclaration(program, position === 0 ? sourceFile : getTouchingPropertyName(sourceFile, position))); + return declaration ? 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(resolveCallHierarchyDeclaration(program, position === 0 ? sourceFile : getTouchingPropertyName(sourceFile, position))); + return declaration ? 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, @@ -2734,16 +2836,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`); @@ -2751,14 +2853,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); } @@ -2766,22 +2868,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); } } }); @@ -2793,49 +2895,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); @@ -2843,31 +2945,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 @@ -2878,13 +2980,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 2c487d71f2dac..005975ab313ff 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -1,4 +1,36 @@ -import * as ts from "./_namespaces/ts"; +import { EmitOutput } from "../compiler/builderStatePublic"; +import { parseJsonSourceFileConfigFileContent } from "../compiler/commandLineParser"; +import { + clear, createGetCanonicalFileName, filter, getProperty, isString, map, toFileNameLowerCase, +} from "../compiler/core"; +import { ESMap, MapLike, ReadonlyESMap } from "../compiler/corePublic"; +import { + getAutomaticTypeDirectiveNames, resolveModuleName, resolveTypeReferenceDirective, +} from "../compiler/moduleNameResolver"; +import { parseJsonText } from "../compiler/parser"; +import { getDirectoryPath, normalizeSlashes, toPath } from "../compiler/path"; +import { timestamp } from "../compiler/performanceCore"; +import { flattenDiagnosticMessageText } from "../compiler/program"; +import { + CompilerOptions, Diagnostic, diagnosticCategoryName, Extension, FileReference, ModuleResolutionHost, + OperationCanceledException, ParseConfigHost, ResolvedModuleFull, ResolvedTypeReferenceDirective, ScriptKind, + TextChangeRange, TextRange, TextSpan, TypeAcquisition, UserPreferences, +} from "../compiler/types"; +import { extensionFromPath, getFileMatcherPatterns } from "../compiler/utilities"; +import { createTextChangeRange, createTextSpan } from "../compiler/utilitiesPublic"; +import { CachedTyping, discoverTypings, loadSafeList, SafeList, TypingResolutionHost } from "../jsTyping/jsTyping"; +import { createClassifier } from "./classifier"; +import { createDocumentRegistry, DocumentRegistry } from "./documentRegistry"; +import { preProcessFile } from "./preProcess"; +import { + createLanguageService, getDefaultCompilerOptions, servicesVersion, ThrottledCancellationToken, +} from "./services"; +import { + Classifications, Classifier, CompletionEntryData, DocCommentTemplateOptions, EditorOptions, EndOfLineState, + FormatCodeOptions, FormatCodeSettings, GetCompletionsAtPositionOptions, HostCancellationToken, IScriptSnapshot, + LanguageService, LanguageServiceHost, RenameInfoOptions, SemanticClassificationFormat, SignatureHelpItemsOptions, +} from "./types"; +import { getNewLineOrDefaultFromHost, getSnapshotText } from "./utilities"; // // Copyright (c) Microsoft Corporation. All rights reserved. @@ -27,11 +59,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 +100,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 +173,7 @@ export interface Shim { /* @internal */ export interface LanguageServiceShim extends Shim { - languageService: ts.LanguageService; + languageService: LanguageService; dispose(_dummy: {}): void; @@ -155,25 +187,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, options?: ts.RenameInfoOptions): string; + getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): string; getSmartSelectionRange(fileName: string, position: number): string; /** @@ -273,7 +305,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 +322,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 +353,7 @@ function logInternalError(logger: Logger, err: Error) { } } -class ScriptSnapshotShimAdapter implements ts.IScriptSnapshot { +class ScriptSnapshotShimAdapter implements IScriptSnapshot { constructor(private scriptSnapshotShim: ScriptSnapshotShim) { } @@ -333,7 +365,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 +375,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 +389,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 +402,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 +414,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 +456,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 +473,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 +508,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 +521,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 +549,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, TypingResolutionHost { public directoryExists: (directoryName: string) => boolean; public realpath: (path: string) => string; @@ -540,7 +572,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 +602,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 +632,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 +662,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 +684,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 +736,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 +760,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 +769,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 +844,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 +901,7 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim ); } - public getRenameInfo(fileName: string, position: number, options?: ts.RenameInfoOptions): string { + public getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): string { return this.forwardJSONCall( `getRenameInfo('${fileName}', ${position})`, () => this.languageService.getRenameInfo(fileName, position, options) @@ -917,7 +949,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 +990,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 +1002,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 +1010,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 +1024,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 +1033,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 +1042,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 +1115,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 +1133,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 +1171,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 +1205,7 @@ class ClassifierShimObject extends ShimBase implements ClassifierShim { class CoreServicesShimObject extends ShimBase implements CoreServicesShim { private logPerformance = false; - private safeList: ts.JsTyping.SafeList | undefined; + private safeList: SafeList | undefined; constructor(factory: ShimFactory, public readonly logger: Logger, private readonly host: CoreServicesShimHostAdapter) { super(factory); @@ -1185,10 +1217,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; } @@ -1201,8 +1233,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, @@ -1211,12 +1243,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), @@ -1232,20 +1264,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 }); @@ -1253,13 +1285,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, @@ -1274,22 +1306,22 @@ 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 = loadSafeList(this.host, toPath(info.safeListPath, info.safeListPath, getCanonicalFileName)); } - return ts.JsTyping.discoverTypings( + return 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, @@ -1302,22 +1334,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) { @@ -1349,7 +1381,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 88a110f234c1f..cf9795e368585 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -1,31 +1,61 @@ -import * as ts from "./_namespaces/ts"; +import { + contains, countWhere, emptyArray, findIndex, first, firstDefined, flatMapToMutable, identity, last, lastOrUndefined, + map, +} from "../compiler/core"; +import { Debug } from "../compiler/debug"; +import { createPrinter } from "../compiler/emitter"; +import { factory } from "../compiler/factory/nodeFactory"; +import { + isBinaryExpression, isBlock, isFunctionTypeNode, isIdentifier, isMethodDeclaration, isNoSubstitutionTemplateLiteral, + isPropertyAccessExpression, isSourceFile, isTaggedTemplateExpression, isTemplateHead, isTemplateSpan, + isTemplateTail, +} from "../compiler/factory/nodeTests"; +import { skipTrivia } from "../compiler/scanner"; +import { + ArrowFunction, BinaryExpression, CallLikeExpression, CancellationToken, CheckFlags, EmitHint, Expression, + FunctionExpression, Identifier, InternalSymbolName, ListFormat, Node, NodeBuilderFlags, ParameterDeclaration, + ParenthesizedExpression, Printer, Program, Signature, SourceFile, Symbol, SyntaxKind, TaggedTemplateExpression, + TemplateExpression, TextSpan, TransientSymbol, Type, TypeChecker, TypeParameter, +} from "../compiler/types"; +import { getInvokedExpression, isSourceFileJS } from "../compiler/utilities"; +import { + createTextSpan, createTextSpanFromBounds, isCallOrNewExpression, isJsxOpeningLikeElement, isTemplateLiteralToken, +} from "../compiler/utilitiesPublic"; +import { + SignatureHelpItem, SignatureHelpItems, SignatureHelpParameter, SignatureHelpTriggerReason, SymbolDisplayPart, +} from "./types"; +import { + createTextSpanFromNode, findContainingList, findPrecedingToken, findTokenOnLeftOfPosition, + getPossibleGenericSignatures, getPossibleTypeArgumentsInfo, isInComment, isInsideTemplateLiteral, isInString, + mapToDisplayParts, punctuationPart, rangeContainsRange, spacePart, symbolToDisplayParts, +} from "./utilities"; 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 +65,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 +82,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 +94,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 +126,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 +171,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 +227,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 +236,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 +261,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 +292,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 +400,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 +408,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 +422,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 +431,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 +445,9 @@ function getArgumentIndexForTemplatePiece(spanIndex: number, node: ts.Node, posi // ^ ^ ^ ^ ^ ^ ^ ^ ^ // Case: 1 1 3 2 1 3 2 2 1 /* eslint-enable 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 +455,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 +470,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 +480,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 +497,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 +520,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 +574,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 +591,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 +627,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 +641,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 1f19be90f01f0..cbb9e46f2d4a2 100644 --- a/src/services/smartSelection.ts +++ b/src/services/smartSelection.ts @@ -1,26 +1,43 @@ -import * as ts from "./_namespaces/ts"; +import { compact, contains, findIndex, first, last, or, singleOrUndefined } from "../compiler/core"; +import { Debug } from "../compiler/debug"; +import { + isBindingElement, isBlock, isImportDeclaration, isImportEqualsDeclaration, isJSDocSignature, isJSDocTypeExpression, + isJSDocTypeLiteral, isMappedTypeNode, isParameter, isPropertySignature, isSourceFile, isStringLiteral, isSyntaxList, + isTemplateHead, isTemplateSpan, isTemplateTail, isVariableDeclaration, isVariableDeclarationList, + isVariableStatement, +} from "../compiler/factory/nodeTests"; +import { parseNodeFactory } from "../compiler/parser"; +import { getTrailingCommentRanges } from "../compiler/scanner"; +import { CharacterCodes, Node, SourceFile, SyntaxKind, SyntaxList } from "../compiler/types"; +import { getTokenPosOfNode, positionsAreOnSameLine, setTextRangePosEnd } from "../compiler/utilities"; +import { + createTextSpanFromBounds, hasJSDocNodes, isTemplateLiteral, isTemplateMiddleOrTemplateTail, + textSpanIntersectsWithPosition, +} from "../compiler/utilitiesPublic"; +import { SelectionRange } from "./types"; +import { getTouchingPropertyName, textSpansEqual } from "./utilities"; /* @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); } @@ -31,19 +48,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); @@ -51,19 +68,19 @@ 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); const 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); } 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); } @@ -85,12 +102,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 } }; } @@ -101,7 +118,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); @@ -117,22 +134,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, @@ -142,9 +159,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); } @@ -158,48 +175,48 @@ 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)); - return splitChildren(children, ({ kind }) => kind === ts.SyntaxKind.ColonToken); + child === node.name || contains(node.modifiers, child)); + return splitChildren(children, ({ kind }) => kind === SyntaxKind.ColonToken); } // 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(); @@ -209,9 +226,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 || []; @@ -245,20 +262,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, @@ -266,34 +283,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 aa9ab5f663c01..4e85c1465c9ce 100644 --- a/src/services/sourcemaps.ts +++ b/src/services/sourcemaps.ts @@ -1,12 +1,29 @@ +import { createGetCanonicalFileName, isString } from "../compiler/core"; +import { Map } from "../compiler/corePublic"; +import { isDeclarationFileName } from "../compiler/parser"; +import { getDirectoryPath, getNormalizedAbsolutePath } from "../compiler/path"; +import { computeLineAndCharacterOfPosition, getLineStarts } from "../compiler/scanner"; +import { + createDocumentPositionMapper, getLineInfo, identitySourceMapConsumer, LineInfo, tryGetSourceMappingURL, + tryParseRawSourceMap, +} from "../compiler/sourcemap"; +import { sys } from "../compiler/sys"; +import { + DocumentPosition, DocumentPositionMapper, DocumentPositionMapperHost, Extension, LineAndCharacter, Program, + SourceFileLike, +} from "../compiler/types"; +import { + base64decode, getDeclarationEmitOutputFilePathWorker, outFile, removeFileExtension, +} from "../compiler/utilities"; import * as ts 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 +31,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 +56,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 +65,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 +83,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 +96,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 +117,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 +141,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 +157,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 +182,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 +196,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 26036097ebcef..7934bafe6554c 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -1,21 +1,76 @@ -import * as ts from "./_namespaces/ts"; +import { signatureHasRestParameter } from "../compiler/checker"; +import { + compareStringsCaseSensitive, contains, createSortedArray, deduplicate, emptyArray, endsWith, + equateStringsCaseSensitive, filter, find, firstDefined, firstOrUndefined, flatMap, flatten, forEach, getOwnKeys, + hasProperty, isString, mapDefined, removePrefix, startsWith, stringContains, tryRemovePrefix, +} from "../compiler/core"; +import { Comparison, Map, MapLike } from "../compiler/corePublic"; +import { Debug } from "../compiler/debug"; +import { + isCallExpression, isIdentifier, isJsxAttribute, isLiteralTypeNode, isObjectLiteralExpression, isStringLiteral, + isTypeReferenceNode, +} from "../compiler/factory/nodeTests"; +import { + getEffectiveTypeRoots, getPackageJsonTypesVersionsPaths, unmangleScopedPackageName, +} from "../compiler/moduleNameResolver"; +import { tryGetJSExtensionForFile } from "../compiler/moduleSpecifiers"; +import { + altDirectorySeparator, combinePaths, comparePaths, containsPath, directorySeparator, + ensureTrailingDirectorySeparator, fileExtensionIsOneOf, forEachAncestorDirectory, getBaseFileName, getDirectoryPath, + getPathComponents, hasTrailingDirectorySeparator, isRootedDiskPath, isUrl, normalizePath, normalizeSlashes, + resolvePath, +} from "../compiler/path"; +import { getModeForUsageLocation } from "../compiler/program"; +import { getLeadingCommentRanges, isIdentifierText } from "../compiler/scanner"; +import { + CallLikeExpression, CancellationToken, CharacterCodes, CompilerOptions, ContextFlags, ElementAccessExpression, + Extension, IndexedAccessTypeNode, JsxAttribute, LiteralExpression, LiteralTypeNode, ModuleKind, + ModuleResolutionKind, Node, ObjectLiteralExpression, Path, Program, PropertyAssignment, ScriptTarget, Signature, + SourceFile, StringLiteralLike, StringLiteralType, Symbol, SyntaxKind, TextSpan, Type, TypeChecker, TypeFlags, + TypeReferenceNode, UnionTypeNode, UserPreferences, +} from "../compiler/types"; +import { + addToSeen, changeExtension, getEmitModuleResolutionKind, getSupportedExtensions, + getSupportedExtensionsWithJsonIfResolveJsonModule, hostGetCanonicalFileName, isImportCall, readJson, + removeFileExtension, skipParentheses, stripQuotes, tryGetExtensionFromPath, tryParsePattern, + tryRemoveDirectoryPrefix, walkUpParenthesizedExpressions, walkUpParenthesizedTypes, +} from "../compiler/utilities"; +import { + createTextSpan, findAncestor, isJsxOpeningLikeElement, isPrivateIdentifierClassElementDeclaration, + isStringLiteralLike, +} from "../compiler/utilitiesPublic"; +import { + CompletionKind, createCompletionDetails, createCompletionDetailsForSymbol, getCompletionEntriesFromSymbols, + getPropertiesForObjectExpression, Log, SortText, +} from "./completions"; +import { ArgumentInfoForCompletions, getArgumentInfoForCompletions } from "./signatureHelp"; +import { + CompletionEntry, CompletionEntryDetails, CompletionInfo, LanguageServiceHost, ScriptElementKind, + ScriptElementKindModifier, +} from "./types"; +import { + createTextSpanFromStringLiteralLikeContent, findPackageJson, findPackageJsons, getContextualTypeFromParent, + getReplacementSpanForContextToken, getTokenAtPosition, hasIndexSignature, isInReferenceComment, isInString, + rangeContainsPosition, skipConstraint, textPart, tryAndIgnoreErrors, tryDirectoryExists, tryFileExists, + tryGetDirectories, tryReadDirectory, +} from "./utilities"; /* @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); } @@ -23,25 +78,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, @@ -50,9 +105,9 @@ function convertStringLiteralCompletions( sourceFile, host, program, - ts.ScriptTarget.ESNext, + ScriptTarget.ESNext, log, - ts.Completions.CompletionKind.String, + CompletionKind.String, preferences, options, /*formatContext*/ undefined, @@ -62,124 +117,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.TypeReference: { - const typeReference = grandParent as ts.TypeReferenceNode; - const typeArgument = ts.findAncestor(parent, n => n.parent === typeReference) as ts.LiteralTypeNode; + case SyntaxKind.TypeReference: { + const typeReference = grandParent as TypeReferenceNode; + const typeArgument = findAncestor(parent, n => n.parent === typeReference) 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 @@ -196,9 +251,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 @@ -210,11 +265,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 = 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*/") @@ -222,9 +277,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*/"); @@ -240,62 +295,62 @@ 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 { +function getStringLiteralCompletionsFromSignature(call: CallLikeExpression, arg: StringLiteralLike, argumentInfo: ArgumentInfoForCompletions, checker: TypeChecker): StringLiteralCompletionsFromTypes { 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 { kind: StringLiteralCompletionKind.Types, types, isNewIdentifier }; } -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, @@ -305,68 +360,68 @@ 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); +function getStringLiteralCompletionsFromModuleNamesWorker(sourceFile: SourceFile, node: LiteralExpression, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker, preferences: UserPreferences): readonly NameAndKind[] { + const literalValue = normalizeSlashes(node.text); 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, compilerOptions, host, 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( @@ -377,21 +432,21 @@ function getCompletionEntriesForRelativeModules(literalValue: string, scriptDire } } -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; } @@ -401,24 +456,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 => getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensionOptions, host, exclude)); + return flatMap(baseDirectories, baseDirectory => getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensionOptions, host, exclude)); } const enum IncludeExtensionsOption { @@ -429,36 +484,36 @@ const enum IncludeExtensionsOption { /** * Given a path ending at a directory, gets the completions for the path, and filters for those entries containing the basename. */ -function getCompletionEntriesForDirectoryFragment(fragment: string, scriptPath: string, { extensions, includeExtensionsOption }: ExtensionOptions, host: ts.LanguageServiceHost, exclude?: string, result: NameAndKind[] = []): NameAndKind[] { +function getCompletionEntriesForDirectoryFragment(fragment: string, scriptPath: string, { extensions, includeExtensionsOption }: ExtensionOptions, host: LanguageServiceHost, exclude?: string, result: NameAndKind[] = []): NameAndKind[] { if (fragment === undefined) { 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 = normalizeAndPreserveTrailingSlash(isRootedDiskPath(fragment) ? fragment : combinePaths(scriptPath, fragment)); // TODO(rbuckton): should use resolvePaths - 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); 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, extensions, /*exclude*/ undefined, /*include*/ ["./*"]); + const files = tryReadDirectory(host, baseDirectory, extensions, /*exclude*/ undefined, /*include*/ ["./*"]); if (files) { /** @@ -467,40 +522,40 @@ function getCompletionEntriesForDirectoryFragment(fragment: string, scriptPath: * * both foo.ts and foo.tsx become foo */ - const foundFiles = new ts.Map(); // maps file to its extension + const foundFiles = new Map(); // maps file to its extension 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; } let foundFileName: string; - const outputExtension = ts.moduleSpecifiers.tryGetJSExtensionForFile(filePath, host.getCompilationSettings()); - if (includeExtensionsOption === IncludeExtensionsOption.Exclude && !ts.fileExtensionIsOneOf(filePath, [ts.Extension.Json, ts.Extension.Mts, ts.Extension.Cts, ts.Extension.Dmts, ts.Extension.Dcts, ts.Extension.Mjs, ts.Extension.Cjs])) { - foundFileName = ts.removeFileExtension(ts.getBaseFileName(filePath)); - foundFiles.set(foundFileName, ts.tryGetExtensionFromPath(filePath)); + const outputExtension = tryGetJSExtensionForFile(filePath, host.getCompilationSettings()); + if (includeExtensionsOption === IncludeExtensionsOption.Exclude && !fileExtensionIsOneOf(filePath, [Extension.Json, Extension.Mts, Extension.Cts, Extension.Dmts, Extension.Dcts, Extension.Mjs, Extension.Cjs])) { + foundFileName = removeFileExtension(getBaseFileName(filePath)); + foundFiles.set(foundFileName, tryGetExtensionFromPath(filePath)); } - else if ((ts.fileExtensionIsOneOf(filePath, [ts.Extension.Mts, ts.Extension.Cts, ts.Extension.Dmts, ts.Extension.Dcts, ts.Extension.Mjs, ts.Extension.Cjs]) || includeExtensionsOption === IncludeExtensionsOption.ModuleSpecifierCompletion) && outputExtension) { - foundFileName = ts.changeExtension(ts.getBaseFileName(filePath), outputExtension); + else if ((fileExtensionIsOneOf(filePath, [Extension.Mts, Extension.Cts, Extension.Dmts, Extension.Dcts, Extension.Mjs, Extension.Cjs]) || includeExtensionsOption === IncludeExtensionsOption.ModuleSpecifierCompletion) && outputExtension) { + foundFileName = changeExtension(getBaseFileName(filePath), outputExtension); foundFiles.set(foundFileName, outputExtension); } else { - foundFileName = ts.getBaseFileName(filePath); - foundFiles.set(foundFileName, ts.tryGetExtensionFromPath(filePath)); + foundFileName = getBaseFileName(filePath); + foundFiles.set(foundFileName, tryGetExtensionFromPath(filePath)); } } foundFiles.forEach((ext, foundFile) => { - result.push(nameAndKind(foundFile, ts.ScriptElementKind.scriptElement, ext)); + result.push(nameAndKind(foundFile, ScriptElementKind.scriptElement, ext)); }); } // 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.push(directoryResult(directoryName)); } @@ -508,14 +563,14 @@ function getCompletionEntriesForDirectoryFragment(fragment: string, scriptPath: } // 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 versionResult = ts.getPackageJsonTypesVersionsPaths(typesVersions); + const versionResult = getPackageJsonTypesVersionsPaths(typesVersions); const versionPaths = versionResult && versionResult.paths; - const rest = absolutePath.slice(ts.ensureTrailingDirectorySeparator(baseDirectory).length); + const rest = absolutePath.slice(ensureTrailingDirectorySeparator(baseDirectory).length); if (versionPaths) { addCompletionEntriesFromPaths(result, rest, baseDirectory, extensions, versionPaths, host); } @@ -525,9 +580,9 @@ function getCompletionEntriesForDirectoryFragment(fragment: string, scriptPath: return result; } -function addCompletionEntriesFromPaths(result: NameAndKind[], fragment: string, baseDirectory: string, fileExtensions: readonly string[], paths: ts.MapLike, host: ts.LanguageServiceHost) { +function addCompletionEntriesFromPaths(result: NameAndKind[], fragment: string, baseDirectory: string, fileExtensions: readonly string[], paths: MapLike, host: LanguageServiceHost) { for (const path in paths) { - if (!ts.hasProperty(paths, path)) continue; + if (!hasProperty(paths, path)) continue; const patterns = paths[path]; if (patterns) { for (const { name, kind, extension } of getCompletionsForPathMapping(path, patterns, fragment, baseDirectory, fileExtensions, host)) { @@ -547,7 +602,7 @@ function addCompletionEntriesFromPaths(result: NameAndKind[], fragment: string, * Modules from node_modules (i.e. those listed in package.json) * This includes all files that are found in node_modules/moduleName/ with acceptable file extensions */ -function getCompletionEntriesForNonRelativeModules(fragment: string, scriptPath: string, compilerOptions: ts.CompilerOptions, host: ts.LanguageServiceHost, typeChecker: ts.TypeChecker): readonly NameAndKind[] { +function getCompletionEntriesForNonRelativeModules(fragment: string, scriptPath: string, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker): readonly NameAndKind[] { const { baseUrl, paths } = compilerOptions; const result: NameAndKind[] = []; @@ -555,7 +610,7 @@ function getCompletionEntriesForNonRelativeModules(fragment: string, scriptPath: const extensionOptions = getExtensionOptions(compilerOptions); 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.extensions, paths, host); @@ -564,7 +619,7 @@ function getCompletionEntriesForNonRelativeModules(fragment: string, scriptPath: const fragmentDirectory = getFragmentDirectory(fragment); for (const ambientName of getAmbientModuleCompletions(fragment, fragmentDirectory, typeChecker)) { - result.push(nameAndKind(ambientName, ts.ScriptElementKind.externalModuleName, /*extension*/ undefined)); + result.push(nameAndKind(ambientName, ScriptElementKind.externalModuleName, /*extension*/ undefined)); } getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, fragmentDirectory, extensionOptions, result); @@ -577,50 +632,50 @@ function getCompletionEntriesForNonRelativeModules(fragment: string, scriptPath: for (const moduleName of enumerateNodeModulesVisibleToScript(host, scriptPath)) { if (!result.some(entry => entry.name === moduleName)) { foundGlobal = true; - result.push(nameAndKind(moduleName, ts.ScriptElementKind.externalModuleName, /*extension*/ undefined)); + result.push(nameAndKind(moduleName, ScriptElementKind.externalModuleName, /*extension*/ undefined)); } } } 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 packageFile = ts.combinePaths(ancestor, "node_modules", packagePath, "package.json"); - if (ts.tryFileExists(host, packageFile)) { - const packageJson = ts.readJson(packageFile, host as { readFile: (filename: string) => string | undefined }); + const packageFile = combinePaths(ancestor, "node_modules", packagePath, "package.json"); + if (tryFileExists(host, packageFile)) { + const packageJson = readJson(packageFile, host as { readFile: (filename: string) => string | undefined }); 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 keys = getOwnKeys(exports); const fragmentSubpath = components.join("/"); - const processedKeys = ts.mapDefined(keys, k => { + const processedKeys = mapDefined(keys, k => { if (k === ".") return undefined; - if (!ts.startsWith(k, "./")) return undefined; + if (!startsWith(k, "./")) return undefined; const subpath = k.substring(2); - if (!ts.startsWith(subpath, fragmentSubpath)) return undefined; + if (!startsWith(subpath, fragmentSubpath)) return undefined; // subpath is a valid export (barring conditions, which we don't currently check here) - if (!ts.stringContains(subpath, "*")) { + if (!stringContains(subpath, "*")) { return subpath; } // pattern export - only return everything up to the `*`, so the user can autocomplete, then @@ -629,9 +684,9 @@ function getCompletionEntriesForNonRelativeModules(fragment: string, scriptPath: // options for the `*`. return subpath.slice(0, subpath.indexOf("*")); }); - ts.forEach(processedKeys, k => { + forEach(processedKeys, k => { if (k) { - result.push(nameAndKind(k, ts.ScriptElementKind.externalModuleName, /*extension*/ undefined)); + result.push(nameAndKind(k, ScriptElementKind.externalModuleName, /*extension*/ undefined)); } }); return; @@ -640,7 +695,7 @@ function getCompletionEntriesForNonRelativeModules(fragment: string, scriptPath: return nodeModulesDirectoryLookup(ancestor); }; } - ts.forEachAncestorDirectory(scriptPath, ancestorLookup); + forEachAncestorDirectory(scriptPath, ancestorLookup); } } @@ -648,103 +703,103 @@ function getCompletionEntriesForNonRelativeModules(fragment: string, scriptPath: } 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( - path: string, patterns: readonly string[], fragment: string, baseUrl: string, fileExtensions: readonly string[], host: ts.LanguageServiceHost, + path: string, patterns: readonly string[], fragment: string, baseUrl: string, fileExtensions: readonly string[], 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.emptyArray; + return !stringContains(path, "*") ? justPathMappingName(path) : emptyArray; } const pathPrefix = path.slice(0, path.length - 1); - const remainingFragment = ts.tryRemovePrefix(fragment, pathPrefix); - return remainingFragment === undefined ? justPathMappingName(pathPrefix) : ts.flatMap(patterns, pattern => + const remainingFragment = tryRemovePrefix(fragment, pathPrefix); + return remainingFragment === undefined ? justPathMappingName(pathPrefix) : flatMap(patterns, pattern => getModulesForPathsPattern(remainingFragment, baseUrl, pattern, fileExtensions, host)); function justPathMappingName(name: string): readonly NameAndKind[] { - return ts.startsWith(name, fragment) ? [directoryResult(name)] : ts.emptyArray; + return startsWith(name, fragment) ? [directoryResult(name)] : emptyArray; } } -function getModulesForPathsPattern(fragment: string, baseUrl: string, pattern: string, fileExtensions: readonly string[], host: ts.LanguageServiceHost): readonly NameAndKind[] | undefined { +function getModulesForPathsPattern(fragment: string, baseUrl: string, pattern: string, fileExtensions: readonly string[], 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(baseUrl, expandedPrefixDirectory)); - const completePrefix = fragmentHasPath ? baseDirectory : ts.ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase; + const baseDirectory = normalizePath(combinePaths(baseUrl, expandedPrefixDirectory)); + const completePrefix = fragmentHasPath ? baseDirectory : ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase; // If we have a suffix, then we need to read the directory all the way down. We could create a glob // that encodes the suffix, but we would have to escape the character "?" which readDirectory // doesn't support. For now, this is safer but slower const includeGlob = normalizedSuffix ? "**/*" : "./*"; - const matches = ts.mapDefined(ts.tryReadDirectory(host, baseDirectory, fileExtensions, /*exclude*/ undefined, [includeGlob]), match => { - const extension = ts.tryGetExtensionFromPath(match); + const matches = mapDefined(tryReadDirectory(host, baseDirectory, fileExtensions, /*exclude*/ undefined, [includeGlob]), match => { + const extension = tryGetExtensionFromPath(match); const name = trimPrefixAndSuffix(match); - return name === undefined ? undefined : nameAndKind(ts.removeFileExtension(name), ts.ScriptElementKind.scriptElement, extension); + return name === undefined ? undefined : nameAndKind(removeFileExtension(name), ScriptElementKind.scriptElement, extension); }); - const directories = ts.mapDefined(ts.tryGetDirectories(host, baseDirectory).map(d => ts.combinePaths(baseDirectory, d)), dir => { + const directories = mapDefined(tryGetDirectories(host, baseDirectory).map(d => combinePaths(baseDirectory, d)), dir => { const name = trimPrefixAndSuffix(dir); return name === undefined ? undefined : directoryResult(name); }); 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; } @@ -755,47 +810,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(); + : Debug.fail(); return addReplacementSpans(toComplete, range.pos + prefix.length, names); } -function getCompletionEntriesFromTypings(host: ts.LanguageServiceHost, options: ts.CompilerOptions, scriptPath: string, fragmentDirectory: string | undefined, extensionOptions: ExtensionOptions, result: NameAndKind[] = []): readonly NameAndKind[] { +function getCompletionEntriesFromTypings(host: LanguageServiceHost, options: CompilerOptions, scriptPath: string, fragmentDirectory: string | undefined, extensionOptions: ExtensionOptions, result: NameAndKind[] = []): readonly NameAndKind[] { // 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.push(nameAndKind(packageName, ts.ScriptElementKind.externalModuleName, /*extension*/ undefined)); + result.push(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); } @@ -804,18 +859,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 (dependencies.hasOwnProperty(dep) && !ts.startsWith(dep, "@types/")) { + if (dependencies.hasOwnProperty(dep) && !startsWith(dep, "@types/")) { result.push(dep); } } @@ -825,20 +880,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; } @@ -860,7 +915,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 (parameterShouldGetTypeFromJSDoc(node)) { + diags.push(createDiagnosticForNode(node.name || node, Diagnostics.JSDoc_types_may_be_moved_to_TypeScript_types)); } } @@ -68,17 +92,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 +110,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 +175,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 +189,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 +249,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 +257,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 737200759ff07..48def2c309375 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -1,78 +1,113 @@ -import * as ts from "./_namespaces/ts"; - -const symbolDisplayNodeBuilderFlags = ts.NodeBuilderFlags.OmitParameterModifiers | ts.NodeBuilderFlags.IgnoreErrors | ts.NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope; +import { + addRange, arrayFrom, contains, emptyArray, find, first, firstDefined, forEach, length, some, +} from "../compiler/core"; +import { Set } from "../compiler/corePublic"; +import { Debug } from "../compiler/debug"; +import { createPrinter } from "../compiler/emitter"; +import { + isArrowFunction, isBindingElement, isCallExpression, isClassExpression, isEnumDeclaration, isFunctionExpression, + isIdentifier, isObjectBindingPattern, isTaggedTemplateExpression, +} from "../compiler/factory/nodeTests"; +import { + BinaryExpression, CallExpression, CheckFlags, EmitHint, EnumMember, ExportAssignment, GetAccessorDeclaration, + ImportEqualsDeclaration, JsxOpeningLikeElement, ListFormat, ModifierFlags, ModuleDeclaration, NewExpression, Node, + NodeBuilderFlags, ObjectFlags, Printer, PropertyAccessExpression, SetAccessorDeclaration, Signature, + SignatureDeclaration, SignatureFlags, SourceFile, Symbol, SymbolFlags, SymbolFormatFlags, SyntaxKind, + TaggedTemplateExpression, TransientSymbol, Type, TypeChecker, TypeFormatFlags, TypeParameter, VariableDeclaration, +} from "../compiler/types"; +import { + getCombinedLocalAndExportSymbolFlags, getDeclarationOfKind, getExternalModuleImportEqualsDeclarationExpression, + getObjectFlags, getSourceFileOfNode, getTextOfConstantValue, getTextOfIdentifierOrLiteral, getTextOfNode, + hasSyntacticModifier, isEnumConst, isExternalModuleImportEqualsDeclaration, isFunctionBlock, isInExpressionContext, + isLet, isModuleWithStringLiteralName, isThisInTypeQuery, isVarConst, +} from "../compiler/utilities"; +import { + getNameOfDeclaration, getParseTreeNode, idText, isCallOrNewExpression, isConstTypeReference, isExpression, + isFunctionLike, isFunctionLikeKind, isJsxOpeningLikeElement, +} from "../compiler/utilitiesPublic"; +import { + JSDocTagInfo, ScriptElementKind, ScriptElementKindModifier, SymbolDisplayPart, SymbolDisplayPartKind, +} from "./types"; +import { + displayPart, getMeaningFromLocation, getNodeModifiers, isCallExpressionTarget, isDeprecatedDeclaration, + isFirstDeclarationOfSymbolParameter, isNameOfFunctionDeclaration, isNewExpressionTarget, keywordPart, lineBreakPart, + mapToDisplayParts, operatorPart, punctuationPart, SemanticMeaning, signatureToDisplayParts, spacePart, + symbolToDisplayParts, textOrKeywordPart, textPart, typeToDisplayParts, +} from "./utilities"; + +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 & 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 & ts.SymbolFlags.Property) { - if (flags & ts.SymbolFlags.Transient && (symbol as ts.TransientSymbol).checkFlags & ts.CheckFlags.Synthetic) { + 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) { @@ -80,27 +115,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(","); } @@ -109,81 +144,81 @@ 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)[]), declaration => declaration.name === location); + if (symbolKind === ScriptElementKind.memberGetAccessorElement || symbolKind === ScriptElementKind.memberSetAccessorElement) { + const declaration = find(symbol.declarations as ((GetAccessorDeclaration | SetAccessorDeclaration)[]), 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; 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; @@ -191,47 +226,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); } @@ -240,29 +275,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: @@ -273,16 +308,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 } @@ -290,15 +325,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); @@ -308,64 +343,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 @@ -375,74 +410,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; } @@ -455,43 +490,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); } } @@ -500,52 +535,52 @@ 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.memberGetAccessorElement || - symbolKind === ts.ScriptElementKind.memberSetAccessorElement || - symbolKind === ts.ScriptElementKind.jsxAttribute || - symbolFlags & ts.SymbolFlags.Variable || - symbolKind === ts.ScriptElementKind.localVariableElement || + if (symbolKind === ScriptElementKind.memberVariableElement || + symbolKind === ScriptElementKind.memberGetAccessorElement || + symbolKind === ScriptElementKind.memberSetAccessorElement || + symbolKind === ScriptElementKind.jsxAttribute || + symbolFlags & SymbolFlags.Variable || + symbolKind === ScriptElementKind.localVariableElement || 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) { - 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) { + 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); @@ -563,17 +598,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; } @@ -587,16 +622,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; } } @@ -616,50 +651,50 @@ 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) { if (alias && symbolToDisplay === symbol) { symbolToDisplay = alias; } - const fullSymbolDisplayParts = ts.symbolToDisplayParts(typeChecker, symbolToDisplay, enclosingDeclaration || sourceFile, /*meaning*/ undefined, - ts.SymbolFormatFlags.WriteTypeParametersOrArguments | ts.SymbolFormatFlags.UseOnlyExternalAliasing | ts.SymbolFormatFlags.AllowAnyNodeKind); - ts.addRange(displayParts, fullSymbolDisplayParts); + const fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbolToDisplay, enclosingDeclaration || sourceFile, /*meaning*/ undefined, + SymbolFormatFlags.WriteTypeParametersOrArguments | SymbolFormatFlags.UseOnlyExternalAliasing | SymbolFormatFlags.AllowAnyNodeKind); + addRange(displayParts, fullSymbolDisplayParts); - if (symbol.flags & ts.SymbolFlags.Optional) { - displayParts.push(ts.punctuationPart(ts.SyntaxKind.QuestionToken)); + 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); } } @@ -667,31 +702,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(); @@ -702,34 +737,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 d0af1c43bb429..dbabde13a63a6 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -1,28 +1,80 @@ -import * as ts from "./_namespaces/ts"; +import { getNodeId } from "../compiler/checker"; +import { + concatenate, contains, endsWith, filter, find, findLastIndex, first, firstOrUndefined, flatMap, flatMapToMutable, + group, intersperse, isArray, isString, last, lastOrUndefined, length, mapDefined, removeSuffix, singleOrUndefined, + stableSort, +} from "../compiler/core"; +import { Map, Set } from "../compiler/corePublic"; +import { Debug } from "../compiler/debug"; +import { createPrinter } from "../compiler/emitter"; +import { createNodeFactory, factory, NodeFactoryFlags } from "../compiler/factory/nodeFactory"; +import { + isArrowFunction, isCallExpression, isExpressionStatement, isFunctionDeclaration, isFunctionExpression, isIdentifier, + isImportClause, isImportDeclaration, isImportSpecifier, isNamedImports, isObjectLiteralExpression, isParameter, + isPropertyDeclaration, isPropertySignature, isStringLiteral, isVariableDeclaration, +} from "../compiler/factory/nodeTests"; +import { createSourceFile } from "../compiler/parser"; +import { + getLeadingCommentRanges, getLineAndCharacterOfPosition, getShebang, getTrailingCommentRanges, isLineBreak, + isWhiteSpaceLike, isWhiteSpaceSingleLine, skipTrivia, tokenToString, +} from "../compiler/scanner"; +import { nullTransformationContext } from "../compiler/transformer"; +import { + ArrowFunction, BindingElement, CharacterCodes, ClassElement, ClassExpression, ClassLikeDeclaration, CommentRange, + ConstructorDeclaration, DeclarationStatement, EmitHint, EmitTextWriter, Expression, FunctionDeclaration, + FunctionExpression, HasJSDoc, ImportClause, ImportSpecifier, InterfaceDeclaration, JSDoc, JSDocComment, + JSDocParameterTag, JSDocReturnTag, JSDocTag, JSDocTypeTag, MethodSignature, Modifier, NamedImportBindings, + NamedImports, NamespaceImport, Node, NodeArray, ObjectLiteralElementLike, ObjectLiteralExpression, + ParameterDeclaration, PrintHandlers, PrologueDirective, PropertyAssignment, PropertyDeclaration, PropertySignature, + ScriptKind, ScriptTarget, SignatureDeclaration, SourceFile, SourceFileLike, Statement, Symbol, SyntaxKind, + TextRange, Token, TransformationContext, TypeLiteralNode, TypeNode, TypeParameterDeclaration, UserPreferences, + VariableDeclaration, VariableStatement, Visitor, +} from "../compiler/types"; +import { + addToSeen, createRange, createTextWriter, getAncestor, getJSDocCommentRanges, getLineOfLocalPosition, + getScriptKindFromFileName, getStartPositionOfLine, indexOfNode, isAnyImportSyntax, isJsonSourceFile, + isPinnedComment, isPrologueDirective, isRecognizedTripleSlashComment, isSuperCall, nodeIsSynthesized, + positionsAreOnSameLine, rangeOfNode, rangeOfTypeParameters, rangeStartPositionsAreOnSameLine, setTextRangePosEnd, +} from "../compiler/utilities"; +import { + createTextSpan, hasJSDocNodes, isClassElement, isClassOrTypeElement, isFunctionLike, isStatement, + isStatementButNotDeclaration, textSpanEnd, +} from "../compiler/utilitiesPublic"; +import { visitEachChild, visitNodes } from "../compiler/visitorPublic"; +import { FormatContext, formatDocument, formatNodeGivenIndentation } from "./formatting/formatting"; +import { SmartIndenter } from "./formatting/smartIndenter"; +import { FileTextChanges, LanguageServiceHost, TextChange } from "./types"; +import { + createTextChange, createTextRangeFromSpan, createTextSpanFromRange, findChildOfKind, findNextToken, + findPrecedingToken, getFirstNonSpaceCharacterPosition, getFormatCodeSettingsForWriting, + getLineStartPositionForPosition, getNewLineKind, getNewLineOrDefaultFromHost, getPrecedingNonSpaceCharacterPosition, + getTokenAtPosition, getTouchingToken, isInComment, isInJSXText, isInString, isInTemplateString, + rangeContainsPosition, rangeContainsRangeExclusive, stringContainsAt, +} from "./utilities"; /** * 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 +118,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 +190,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 +210,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 +219,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 +244,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 +261,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 +307,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 +327,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 +337,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: 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: 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 +416,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 +504,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 +514,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 +577,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 +650,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 +660,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 +670,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 +699,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 = SmartIndenter.findFirstNonWhitespaceColumn(getLineStartPositionForPosition(memberStart, sourceFile), memberStart, sourceFile, this.formatContext.options); if (indentation === undefined) { indentation = memberIndentation; } @@ -669,13 +721,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 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,9 +740,9 @@ 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, @@ -698,105 +750,105 @@ export class ChangeTracker { }; } - 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 +858,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 +867,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 = 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 +880,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 +902,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 +921,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 +937,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 = 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 +963,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 +976,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 +990,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 = 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 +1006,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,107 +1016,107 @@ 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 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: 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: 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: 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: 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 = 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: FormatContext, validate: ValidateNonFormattedText | undefined): string { if (change.kind === ChangeKind.Remove) { return ""; } @@ -1073,129 +1125,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: 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); + : 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 = 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 = 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); } @@ -1205,7 +1257,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 @@ -1252,7 +1304,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); } @@ -1331,10 +1383,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 { @@ -1350,26 +1402,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; } @@ -1402,10 +1454,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++; } } @@ -1414,23 +1466,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`). @@ -1442,18 +1494,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); } @@ -1462,16 +1514,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); } @@ -1480,21 +1532,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: @@ -1502,10 +1554,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 { @@ -1514,7 +1566,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); @@ -1522,10 +1574,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 { @@ -1534,29 +1586,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; } @@ -1567,21 +1619,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); } } } @@ -1589,16 +1641,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(SmartIndenter.getContainingList(node, sourceFile)); + const index = indexOfNode(containingList, node); + Debug.assert(index !== -1); if (containingList.length === 1) { deleteNode(changes, sourceFile, node); return; @@ -1606,7 +1658,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..851b688375900 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -1,17 +1,34 @@ -import * as ts from "./_namespaces/ts"; +import { + createCompilerDiagnosticForInvalidCustomType, optionDeclarations, parseCustomTypeOption, + transpileOptionValueCompilerOptions, +} from "../compiler/commandLineParser"; +import { addRange, filter, getEntries, hasProperty, isString } from "../compiler/core"; +import { Map, MapLike } from "../compiler/corePublic"; +import { Debug } from "../compiler/debug"; +import { createSourceFile } from "../compiler/parser"; +import { fileExtensionIs, normalizePath, toPath } from "../compiler/path"; +import { createProgram, getImpliedNodeFormatForFile } from "../compiler/program"; +import { + CommandLineOptionOfCustomType, CompilerHost, CompilerOptions, CustomTransformers, Diagnostic, +} from "../compiler/types"; +import { + forEachEntry, getEmitScriptTarget, getNewLineCharacter, getSetExternalModuleIndicator, +} from "../compiler/utilities"; +import { getDefaultCompilerOptions } from "./services"; +import { cloneCompilerOptions } from "./utilities"; 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 +42,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 +64,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 +91,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 +105,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 +129,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 c34b6e4b1c6e8..d62bfe2565c2b 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -1,32 +1,47 @@ -import * as ts from "./_namespaces/ts"; +import { EmitOutput } from "../compiler/builderStatePublic"; +import { ESMap } from "../compiler/corePublic"; +import { ModuleResolutionCache } from "../compiler/moduleNameResolver"; +import { + CancellationToken, CompilerHost, CompilerOptions, CustomTransformers, Diagnostic, DiagnosticWithLocation, + DocumentPositionMapper, FileReference, GetEffectiveTypeRootsHost, HasChangedAutomaticTypeDirectiveNames, + HasInvalidatedResolution, LineAndCharacter, MinimalResolutionCacheHost, ModuleKind, ModuleSpecifierCache, + ParsedCommandLine, Path, Program, ProjectReference, ResolvedModule, ResolvedModuleWithFailedLookupLocations, + ResolvedProjectReference, ResolvedTypeReferenceDirective, ScriptKind, SourceFile, SourceFileLike, Symbol, + TextChangeRange, TextRange, TextSpan, UserPreferences, +} from "../compiler/types"; +import { SymlinkCache } from "../compiler/utilities"; +import { DocumentHighlights } from "./documentHighlights"; +import { ExportInfoMap } from "./exportInfoMap"; +import { SourceMapper } from "./sourcemaps"; +import { TextChangesContext } from "./textChanges"; 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 +63,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 +133,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 +181,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 +203,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 +216,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 +229,7 @@ export interface HostCancellationToken { } export interface InstallPackageOptions { - fileName: ts.Path; + fileName: Path; packageName: string; } @@ -231,10 +246,10 @@ export const enum PackageJsonDependencyGroup { export interface PackageJsonInfo { 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 +286,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 +330,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 */ hasInvalidatedResolution?: ts.HasInvalidatedResolution; - /* @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 */ hasInvalidatedResolution?: HasInvalidatedResolution; + /* @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 +349,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 PackageJsonInfo[]; /* @internal */ getNearestAncestorDirectoryWithPackageJson?(fileName: string): string | undefined; /* @internal */ getPackageJsonsForAutoImport?(rootDir?: string): readonly PackageJsonInfo[]; - /* @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 +406,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 +423,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 +432,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 +440,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 +462,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 +492,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,9 +507,9 @@ 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; @@ -516,7 +531,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 */ @@ -530,11 +545,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[]; @@ -550,16 +565,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; @@ -571,22 +586,22 @@ 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; + getProgram(): Program | undefined; - /* @internal */ getNonBoundSourceFile(fileName: string): ts.SourceFile; - /* @internal */ getAutoImportProvider(): ts.Program | undefined; + /* @internal */ getNonBoundSourceFile(fileName: string): SourceFile; + /* @internal */ getAutoImportProvider(): Program | undefined; - 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; } @@ -614,7 +629,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. @@ -684,12 +699,12 @@ export interface Classifications { } export interface ClassifiedSpan { - textSpan: ts.TextSpan; + textSpan: TextSpan; classificationType: ClassificationTypeNames; } export interface ClassifiedSpan2020 { - textSpan: ts.TextSpan; + textSpan: TextSpan; classificationType: number; } @@ -703,7 +718,7 @@ export interface NavigationBarItem { text: string; kind: ScriptElementKind; kindModifiers: string; - spans: ts.TextSpan[]; + spans: TextSpan[]; childItems: NavigationBarItem[]; indent: number; bolded: boolean; @@ -724,8 +739,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[]; } @@ -735,19 +750,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 { @@ -776,7 +791,7 @@ export interface TodoComment { } export interface TextChange { - span: ts.TextSpan; + span: TextSpan; newText: string; } @@ -898,22 +913,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 { @@ -941,8 +956,8 @@ export const enum HighlightSpanKind { export interface HighlightSpan { fileName?: string; isInString?: true; - textSpan: ts.TextSpan; - contextSpan?: ts.TextSpan; + textSpan: TextSpan; + contextSpan?: TextSpan; kind: HighlightSpanKind; } @@ -953,7 +968,7 @@ export interface NavigateToItem { matchKind: "exact" | "prefix" | "substring" | "camelCase"; isCaseSensitive: boolean; fileName: string; - textSpan: ts.TextSpan; + textSpan: TextSpan; containerName: string; containerKind: ScriptElementKind; } @@ -1075,7 +1090,7 @@ export interface DefinitionInfo extends DocumentSpan { export interface DefinitionInfoAndBoundSpan { definitions?: readonly DefinitionInfo[]; - textSpan: ts.TextSpan; + textSpan: TextSpan; } export interface ReferencedSymbolDefinitionInfo extends DefinitionInfo { @@ -1136,7 +1151,7 @@ export interface JSDocTagInfo { export interface QuickInfo { kind: ScriptElementKind; kindModifiers: string; - textSpan: ts.TextSpan; + textSpan: TextSpan; displayParts?: SymbolDisplayPart[]; documentation?: SymbolDisplayPart[]; tags?: JSDocTagInfo[]; @@ -1154,7 +1169,7 @@ export interface RenameInfoSuccess { fullDisplayName: string; kind: ScriptElementKind; kindModifiers: string; - triggerSpan: ts.TextSpan; + triggerSpan: TextSpan; } export interface RenameInfoFailure { canRename: false; @@ -1178,7 +1193,7 @@ export interface SignatureHelpParameter { } export interface SelectionRange { - textSpan: ts.TextSpan; + textSpan: TextSpan; parent?: SelectionRange; } @@ -1204,7 +1219,7 @@ export interface SignatureHelpItem { */ export interface SignatureHelpItems { items: SignatureHelpItem[]; - applicableSpan: ts.TextSpan; + applicableSpan: TextSpan; selectedItemIndex: number; argumentIndex: number; argumentCount: number; @@ -1232,7 +1247,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 */ @@ -1283,7 +1298,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[]; @@ -1323,10 +1338,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; @@ -1627,11 +1642,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 TextChangesContext { + sourceFile: SourceFile; + program: Program; + cancellationToken: CancellationToken; + preferences: UserPreferences; } /** @internal */ @@ -1642,7 +1657,7 @@ export interface CodeFixAllContext extends CodeFixContextBase { /** @internal */ export interface CodeFixContext extends CodeFixContextBase { errorCode: number; - span: ts.TextSpan; + span: TextSpan; } /** @internal */ @@ -1659,22 +1674,22 @@ export interface Refactor { } /** @internal */ -export interface RefactorContext extends ts.textChanges.TextChangesContext { - file: ts.SourceFile; +export interface RefactorContext extends 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 138f72bc72142..9faf0a9a1d49c 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1,4 +1,99 @@ -import * as ts from "./_namespaces/ts"; +import { getModuleInstanceState, ModuleInstanceState } from "../compiler/binder"; +import { getNodeId, getSymbolId } from "../compiler/checker"; +import { setConfigFileInOptions } from "../compiler/commandLineParser"; +import { + assertType, binarySearchKey, cast, clone, compareTextSpans, compareValues, contains, emptyArray, filter, find, + first, firstDefined, firstOrUndefined, identity, isArray, last, lastOrUndefined, map, maybeBind, noop, + notImplemented, or, singleOrUndefined, some, stableSort, startsWith, stringContains, tryCast, +} from "../compiler/core"; +import { Comparison, Map } from "../compiler/corePublic"; +import { Debug } from "../compiler/debug"; +import { createPrinter } from "../compiler/emitter"; +import { addEmitFlags, addSyntheticLeadingComment, addSyntheticTrailingComment } from "../compiler/factory/emitNode"; +import { factory, setOriginalNode } from "../compiler/factory/nodeFactory"; +import { + isArrayBindingPattern, isArrayTypeNode, isAsExpression, isAwaitExpression, isBinaryExpression, isBindingElement, + isCallExpression, isClassDeclaration, isClassExpression, isClassStaticBlockDeclaration, isConditionalTypeNode, + isDecorator, isDeleteExpression, isElementAccessExpression, isEnumDeclaration, isExportAssignment, + isExportDeclaration, isExportSpecifier, isExternalModuleReference, isForInStatement, isForOfStatement, + isFunctionDeclaration, isFunctionExpression, isGetAccessorDeclaration, isHeritageClause, isIdentifier, + isImportClause, isImportDeclaration, isImportEqualsDeclaration, isImportSpecifier, isInferTypeNode, + isInterfaceDeclaration, isJSDoc, isJSDocLink, isJSDocLinkCode, isJSDocMemberName, isJSDocNameReference, + isJSDocTemplateTag, isJsxElement, isJsxExpression, isJsxText, isLabeledStatement, isLiteralTypeNode, + isMappedTypeNode, isModuleBlock, isModuleDeclaration, isNamedExports, isNamedImports, isNamespaceExport, + isNamespaceImport, isNewExpression, isNumericLiteral, isObjectBindingPattern, isObjectLiteralExpression, + isParameter, isPrivateIdentifier, isPropertyAccessExpression, isQualifiedName, isSetAccessorDeclaration, + isSourceFile, isStringLiteral, isSyntaxList, isTaggedTemplateExpression, isTypeAliasDeclaration, isTypeOfExpression, + isTypeOperatorNode, isTypeParameterDeclaration, isTypeReferenceNode, isVariableDeclarationList, isVoidExpression, + isYieldExpression, +} from "../compiler/factory/nodeTests"; +import { skipOuterExpressions } from "../compiler/factory/utilities"; +import { setTextRange } from "../compiler/factory/utilitiesPublic"; +import { getPackageNameFromTypesPackageName, getTypesPackageName } from "../compiler/moduleNameResolver"; +import { getNodeModulesPackageName } from "../compiler/moduleSpecifiers"; +import { forEachChild, isExternalModule } from "../compiler/parser"; +import { + combinePaths, forEachAncestorDirectory, getDirectoryPath, getPathComponents, isRootedDiskPath, pathIsRelative, +} from "../compiler/path"; +import { findConfigFile } from "../compiler/program"; +import { + createScanner, forEachLeadingCommentRange, forEachTrailingCommentRange, getLineAndCharacterOfPosition, + getLineStarts, isWhiteSpaceLike, isWhiteSpaceSingleLine, Scanner, stringToToken, tokenToString, +} from "../compiler/scanner"; +import { nullTransformationContext } from "../compiler/transformer"; +import { + __String, AnyImportOrRequireStatement, AssignmentDeclarationKind, BinaryExpression, BindingElement, + BreakOrContinueStatement, CallExpression, CaseClause, CatchClause, CharacterCodes, ClassDeclaration, + ClassExpression, CommentKind, CommentRange, CompilerOptions, ConditionalExpression, Declaration, Decorator, + DeleteExpression, Diagnostic, DiagnosticMessage, DiagnosticWithLocation, DoStatement, ElementAccessExpression, + EmitFlags, EmitHint, EndOfFileToken, EqualityOperator, ExportAssignment, ExportDeclaration, Expression, + ExpressionStatement, ForOfStatement, FunctionDeclaration, FunctionExpression, FunctionLikeDeclaration, + HeritageClause, Identifier, IfStatement, ImportClause, ImportDeclaration, ImportSpecifier, ImportTypeNode, + IndexSignatureDeclaration, InternalSymbolName, IterationStatement, JSDocLink, JSDocLinkCode, JSDocLinkPlain, + JSDocTypedefTag, JsxEmit, JsxOpeningLikeElement, LabeledStatement, LiteralExpression, Modifier, ModifierFlags, + ModuleDeclaration, ModuleResolutionKind, ModuleSpecifierResolutionHost, NewExpression, NewLineKind, Node, NodeArray, + NodeBuilderFlags, NodeFlags, NoSubstitutionTemplateLiteral, NumericLiteral, PrefixUnaryExpression, Program, + PropertyAccessExpression, PropertyAssignment, PropertyName, QualifiedName, ScriptKind, ScriptTarget, Signature, + SignatureDeclaration, SourceFile, SourceFileLike, SpreadElement, StringLiteral, StringLiteralLike, Symbol, + SymbolAccessibility, SymbolFlags, SymbolFormatFlags, SymbolTracker, SyntaxKind, SyntaxList, + TaggedTemplateExpression, TemplateExpression, TemplateLiteralToken, TemplateSpan, TextRange, TextSpan, Token, + TransientSymbol, Type, TypeChecker, TypeFormatFlags, TypeNode, TypeOfExpression, TypeQueryNode, UserPreferences, + VariableDeclaration, VoidExpression, YieldExpression, +} from "../compiler/types"; +import { + createRange, defaultMaximumTruncationLength, directoryProbablyExists, ensureScriptKind, formatStringFromArgs, + getAssignmentDeclarationKind, getEmitScriptTarget, getExternalModuleImportEqualsDeclarationExpression, + getIndentString, getLastChild, getLocaleSpecificMessage, getRootDeclaration, getSourceFileOfNode, + getSpanOfTokenAtPosition, getTextOfIdentifierOrLiteral, getTextOfNode, hasSyntacticModifier, + identifierIsThisKeyword, indexOfNode, isAmbientModule, isAnyImportSyntax, isDeclarationName, isExpressionNode, + isExternalModuleImportEqualsDeclaration, isFileLevelUniqueName, isFunctionBlock, isGlobalScopeAugmentation, + isImportCall, isInJSFile, isInternalModuleImportEqualsDeclaration, isJSDocTypeAlias, isKeyword, isLet, + isPartOfTypeNode, isPropertyNameLiteral, isRequireCall, isRequireVariableStatement, + isRightSideOfQualifiedNameOrPropertyAccess, isSourceFileJS, isStringDoubleQuoted, isStringOrNumericLiteralLike, + isVarConst, Mutable, nodeIsMissing, nodeIsPresent, nodeIsSynthesized, skipAlias, stripQuotes, +} from "../compiler/utilities"; +import { + createTextSpan, createTextSpanFromBounds, findAncestor, getCombinedNodeFlagsAlwaysIncludeJSDoc, getJSDocEnumTag, + getNameOfDeclaration, idText, isBreakOrContinueStatement, isCallOrNewExpression, isDeclaration, isEntityName, + isExpression, isFunctionLike, isImportOrExportSpecifier, isJSDocCommentContainingNode, isJSDocLinkLike, isJSDocTag, + isJsxOpeningLikeElement, isModifier, isNamedDeclaration, isOptionalChain, isOptionalChainRoot, isStringLiteralLike, + isStringTextContainingNode, isTemplateLiteralKind, isToken, isTypeElement, isTypeNode, textSpanContainsPosition, + textSpanContainsTextSpan, textSpanEnd, unescapeLeadingUnderscores, +} from "../compiler/utilitiesPublic"; +import { visitEachChild } from "../compiler/visitorPublic"; +import { nodeCoreModules } from "../jsTyping/jsTyping"; +import { moduleSymbolToValidIdentifier } from "./codefixes/importFixes"; +import { FormatContext, getRangeOfEnclosingComment } from "./formatting/formatting"; +import { + compareImportsOrRequireStatements, getImportDeclarationInsertionIndex, importsAreSorted, +} from "./organizeImports"; +import { DisplayPartsSymbolWriter } from "./services"; +import { ChangeTracker, LeadingTriviaOption } from "./textChanges"; +import { + DocumentSpan, FileTextChanges, FormatCodeSettings, FormattingHost, IScriptSnapshot, JSDocLinkDisplayPart, + LanguageServiceHost, PackageJsonDependencyGroup, PackageJsonInfo, RefactorContext, ScriptElementKind, + ScriptElementKindModifier, SemicolonPreference, SymbolDisplayPart, SymbolDisplayPartKind, TextChange, +} from "./types"; /* @internal */ // Don't expose that we use this // Based on lib.es6.d.ts @@ -21,7 +116,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 +128,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 +194,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 +223,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 +236,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 +386,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 +395,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 +484,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 +618,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 +679,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 +823,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 +838,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 +850,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,86 +859,86 @@ 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 { +export function getContextualTypeFromParentOrAncestorTypeNode(node: Expression, checker: TypeChecker): Type | undefined { const contextualType = getContextualTypeFromParent(node, checker); if (contextualType) return contextualType; @@ -851,25 +946,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 @@ -889,15 +984,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; } } @@ -910,7 +1005,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|] } ... @@ -918,15 +1013,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; } } @@ -937,7 +1032,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) { @@ -948,7 +1043,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|] ... @@ -957,35 +1052,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.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) ? 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; @@ -995,7 +1090,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; @@ -1006,14 +1101,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; } } @@ -1022,18 +1117,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; @@ -1042,17 +1137,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|] ... @@ -1060,38 +1155,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) { @@ -1105,30 +1200,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; @@ -1139,7 +1234,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); } @@ -1147,7 +1242,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); } @@ -1156,8 +1251,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 */ @@ -1165,25 +1260,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 @@ -1208,7 +1303,7 @@ function getTokenAtPositionWorker(sourceFile: ts.SourceFile, position: number, a 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 @@ -1216,17 +1311,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) { @@ -1240,14 +1335,14 @@ function getTokenAtPositionWorker(sourceFile: ts.SourceFile, position: number, a return current; } - function nodeContainsPosition(node: ts.Node) { + function nodeContainsPosition(node: Node) { const start = allowPositionInLeadingTrivia ? node.getFullStart() : node.getStart(sourceFile, /*includeJsDoc*/ true); if (start > position) { // If this child begins after position, then all subsequent children will as well. return false; } const end = node.getEnd(); - 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) { @@ -1266,7 +1361,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); @@ -1285,11 +1380,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; } @@ -1297,15 +1392,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) || @@ -1321,22 +1416,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 @@ -1344,11 +1439,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]; @@ -1376,7 +1471,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. @@ -1387,11 +1482,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; } @@ -1408,13 +1503,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)) { @@ -1424,8 +1519,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(); @@ -1438,7 +1533,7 @@ export function isInString(sourceFile: ts.SourceFile, position: number, previous } if (position === end) { - return !!(previousToken as ts.LiteralExpression).isUnterminated; + return !!(previousToken as LiteralExpression).isUnterminated; } } @@ -1449,82 +1544,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; @@ -1541,9 +1636,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. @@ -1581,34 +1676,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; } @@ -1619,7 +1714,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 @@ -1627,7 +1722,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, @@ -1637,79 +1732,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; } @@ -1730,87 +1825,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 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; } @@ -1818,28 +1913,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; } @@ -1847,7 +1942,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; } } @@ -1856,127 +1951,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()); } @@ -1990,54 +2085,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(), @@ -2045,54 +2140,54 @@ 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( /*decorators*/ undefined, /*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; } } @@ -2102,60 +2197,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; } @@ -2163,32 +2258,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 node.modifiers && ts.find(node.modifiers, m => m.kind === kind); +export function findModifier(node: Node, kind: Modifier["kind"]): Modifier | undefined { + return node.modifiers && find(node.modifiers, m => m.kind === kind); } /* @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: 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, compareImportsOrRequireStatements) : [imports]; if (!existingImportStatements.length) { changes.insertNodesAtTopOfFile(sourceFile, sortedNewImports, blankLineBetween); } - else if (existingImportStatements && ts.OrganizeImports.importsAreSorted(existingImportStatements)) { + else if (existingImportStatements && importsAreSorted(existingImportStatements)) { for (const newImport of sortedNewImports) { - const insertionIndex = ts.OrganizeImports.getImportDeclarationInsertionIndex(existingImportStatements, newImport); + const insertionIndex = 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: LeadingTriviaOption.Exclude } : {}; changes.insertNodeBefore(sourceFile, existingImportStatements[0], newImport, /*blankLineBetween*/ false, options); } else { @@ -2198,7 +2293,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); } @@ -2209,17 +2304,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); } @@ -2246,7 +2341,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; } } @@ -2259,42 +2354,42 @@ export function isTextWhiteSpaceLike(text: string, startPos: number, endPos: num // 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, @@ -2306,37 +2401,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; @@ -2359,71 +2454,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); @@ -2431,31 +2526,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), }, }; @@ -2463,13 +2558,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) { @@ -2480,7 +2575,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) { @@ -2497,8 +2592,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; @@ -2523,7 +2618,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; @@ -2531,11 +2626,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(); @@ -2546,78 +2641,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; @@ -2625,7 +2720,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; @@ -2638,21 +2733,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 as NonNullable); 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); @@ -2662,55 +2757,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); } @@ -2719,20 +2814,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)) { @@ -2744,29 +2839,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; @@ -2778,11 +2873,11 @@ 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, name); @@ -2799,20 +2894,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 */ @@ -2823,13 +2918,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 */ @@ -2844,7 +2939,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); @@ -2853,46 +2948,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; @@ -2900,12 +2995,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; @@ -2913,12 +3008,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); } @@ -2926,13 +3021,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, @@ -2943,72 +3038,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; } } @@ -3017,13 +3112,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; } @@ -3033,8 +3128,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"; } @@ -3045,14 +3140,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 { @@ -3061,12 +3156,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) { @@ -3079,7 +3174,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 @@ -3093,23 +3188,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 */ @@ -3128,13 +3223,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); } @@ -3143,11 +3238,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 } @@ -3156,14 +3251,14 @@ export function findPackageJson(directory: string, host: ts.LanguageServiceHost) } /* @internal */ -export function getPackageJsonsVisibleToFile(fileName: string, host: ts.LanguageServiceHost): readonly ts.PackageJsonInfo[] { +export function getPackageJsonsVisibleToFile(fileName: string, host: LanguageServiceHost): readonly PackageJsonInfo[] { if (!host.fileExists) { return []; } - const packageJsons: ts.PackageJsonInfo[] = []; - ts.forEachAncestorDirectory(ts.getDirectoryPath(fileName), ancestor => { - const packageJsonFileName = ts.combinePaths(ancestor, "package.json"); + const packageJsons: PackageJsonInfo[] = []; + forEachAncestorDirectory(getDirectoryPath(fileName), ancestor => { + const packageJsonFileName = combinePaths(ancestor, "package.json"); if (host.fileExists(packageJsonFileName)) { const info = createPackageJsonInfo(packageJsonFileName, host); if (info) { @@ -3176,7 +3271,7 @@ export function getPackageJsonsVisibleToFile(fileName: string, host: ts.Language } /* @internal */ -export function createPackageJsonInfo(fileName: string, host: { readFile?(fileName: string): string | undefined }): ts.PackageJsonInfo | undefined { +export function createPackageJsonInfo(fileName: string, host: { readFile?(fileName: string): string | undefined }): PackageJsonInfo | undefined { if (!host.readFile) { return undefined; } @@ -3185,14 +3280,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]); } @@ -3201,10 +3296,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 { @@ -3217,7 +3312,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); @@ -3231,8 +3326,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 @@ -3242,7 +3337,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); @@ -3253,14 +3348,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; } @@ -3271,7 +3366,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; } @@ -3280,7 +3375,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; } @@ -3297,7 +3392,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); @@ -3308,7 +3403,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) && nodeCoreModules.has(moduleSpecifier)) { if (usesNodeCoreModules === undefined) { usesNodeCoreModules = consumesNodeCoreModules(fromFile); } @@ -3319,11 +3414,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 = getNodeModulesPackageName( host.getCompilationSettings(), fromFile, importedFileName, @@ -3336,15 +3431,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]; @@ -3361,34 +3456,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 }) => 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; } @@ -3396,14 +3491,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++; @@ -3413,22 +3508,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; } @@ -3446,8 +3541,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 */ @@ -3455,16 +3550,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 = moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, /*preferCapitalized*/ false); + const capitalized = moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, /*preferCapitalized*/ true); if (fileNameCase === capitalized) return fileNameCase; return [fileNameCase, capitalized]; } @@ -3472,33 +3567,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); + || 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(", ")}.`); } @@ -3534,68 +3629,68 @@ 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 (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 }: 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; } diff --git a/src/testRunner/compilerRunner.ts b/src/testRunner/compilerRunner.ts index 3f65f298094e2..0c3f1ee5b2708 100644 --- a/src/testRunner/compilerRunner.ts +++ b/src/testRunner/compilerRunner.ts @@ -1,7 +1,17 @@ -import * as compiler from "./_namespaces/compiler"; -import * as Harness from "./_namespaces/Harness"; -import * as ts from "./_namespaces/ts"; -import * as Utils from "./_namespaces/Utils"; +import { identity, length, some } from "../compiler/core"; +import { + combinePaths, fileExtensionIs, getDirectoryPath, getNormalizedAbsolutePath, isRootedDiskPath, toPath, +} from "../compiler/path"; +import { CompilerOptions, Extension } from "../compiler/types"; +import { CompilationResult } from "../harness/compilerImpl"; +import { + Baseline, Compiler, FileBasedTest, FileBasedTestConfiguration, getFileBasedTestConfigurationDescription, + getFileBasedTestConfigurations, IO, TestCaseParser, +} from "../harness/harnessIO"; +import { RunnerBase, TestRunnerKind } from "../harness/runnerbase"; +import { removeTestPathPrefixes, sanitizeTraceResolutionLogEntry } from "../harness/util"; +import { basename, normalizeSeparators } from "../harness/vpathUtil"; +import { cloneCompilerOptions } from "../services/utilities"; import * as vpath from "./_namespaces/vpath"; export const enum CompilerTestType { @@ -10,13 +20,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,18 +65,18 @@ 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); + this.checkTestCodeOutput(normalizeSeparators(file), typeof test === "string" ? CompilerTest.getConfigurations(test) : test); }); }); } public checkTestCodeOutput(fileName: string, test?: CompilerFileBasedTest) { - if (test && ts.some(test.configurations)) { + if (test && 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,15 +88,15 @@ 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; before(() => { 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); + const rootDir = test.file.indexOf("conformance") === -1 ? "tests/cases/compiler/" : getDirectoryPath(test.file) + "/"; + payload = TestCaseParser.makeUnitsFromTest(test.content, test.file, rootDir); } compilerTest = new CompilerTest(fileName, payload, configuration); }); @@ -151,20 +161,20 @@ 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 result: CompilationResult; + private options: CompilerOptions; + 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.justName = basename(fileName); this.configuredName = this.justName; if (configurationOverrides) { let configuredName = ""; @@ -184,10 +194,10 @@ class CompilerTest { } } - const rootDir = fileName.indexOf("conformance") === -1 ? "tests/cases/compiler/" : ts.getDirectoryPath(fileName) + "/"; + const rootDir = fileName.indexOf("conformance") === -1 ? "tests/cases/compiler/" : 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) { @@ -196,24 +206,24 @@ class CompilerTest { const units = testCaseContent.testUnitData; this.harnessSettings = testCaseContent.settings; - let tsConfigOptions: ts.CompilerOptions | undefined; + let tsConfigOptions: CompilerOptions | undefined; this.tsConfigFiles = []; if (testCaseContent.tsConfig) { assert.equal(testCaseContent.tsConfig.fileNames.length, 0, `list of files in tsconfig is not currently supported`); assert.equal(testCaseContent.tsConfig.raw.exclude, undefined, `exclude in tsconfig is not currently supported`); - tsConfigOptions = ts.cloneCompilerOptions(testCaseContent.tsConfig.options); - this.tsConfigFiles.push(this.createHarnessTestFile(testCaseContent.tsConfigFileUnitData!, rootDir, ts.combinePaths(rootDir, tsConfigOptions.configFilePath))); + tsConfigOptions = cloneCompilerOptions(testCaseContent.tsConfig.options); + this.tsConfigFiles.push(this.createHarnessTestFile(testCaseContent.tsConfigFileUnitData!, rootDir, combinePaths(rootDir, tsConfigOptions.configFilePath))); } else { const baseUrl = this.harnessSettings.baseUrl; - if (baseUrl !== undefined && !ts.isRootedDiskPath(baseUrl)) { - this.harnessSettings.baseUrl = ts.getNormalizedAbsolutePath(baseUrl, rootDir); + if (baseUrl !== undefined && !isRootedDiskPath(baseUrl)) { + this.harnessSettings.baseUrl = getNormalizedAbsolutePath(baseUrl, rootDir); } } this.lastUnit = units[units.length - 1]; - this.hasNonDtsFiles = units.some(unit => !ts.fileExtensionIs(unit.name, ts.Extension.Dts)); + this.hasNonDtsFiles = units.some(unit => !fileExtensionIs(unit.name, Extension.Dts)); // We need to assemble the list of input files for the compiler and other related files on the 'filesystem' (ie in a multi-file test) // If the last file in a test uses require or a triple slash reference we'll assume all other files will be brought in via references, // otherwise, assume all files are just meant to be in the same compilation session without explicit references to one another. @@ -235,11 +245,11 @@ class CompilerTest { } if (tsConfigOptions && tsConfigOptions.configFilePath !== undefined) { - tsConfigOptions.configFilePath = ts.combinePaths(rootDir, tsConfigOptions.configFilePath); + tsConfigOptions.configFilePath = combinePaths(rootDir, tsConfigOptions.configFilePath); tsConfigOptions.configFile!.fileName = tsConfigOptions.configFilePath; } - this.result = Harness.Compiler.compileFiles( + this.result = Compiler.compileFiles( this.toBeCompiled, this.otherFiles, this.harnessSettings, @@ -253,15 +263,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, @@ -270,25 +280,25 @@ class CompilerTest { public verifyModuleResolution() { if (this.options.traceResolution) { - Harness.Baseline.runBaseline(this.configuredName.replace(/\.tsx?$/, ".trace.json"), - JSON.stringify(this.result.traces.map(Utils.sanitizeTraceResolutionLogEntry), undefined, 4)); + Baseline.runBaseline(this.configuredName.replace(/\.tsx?$/, ".trace.json"), + JSON.stringify(this.result.traces.map(sanitizeTraceResolutionLogEntry), undefined, 4)); } } public verifySourceMapRecord() { if (this.options.sourceMap || this.options.inlineSourceMap || this.options.declarationMap) { - const record = Utils.removeTestPathPrefixes(this.result.getSourceMapRecord()!); + const record = removeTestPathPrefixes(this.result.getSourceMapRecord()!); const baseline = (this.options.noEmitOnError && this.result.diagnostics.length !== 0) || record === undefined // 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, @@ -301,7 +311,7 @@ class CompilerTest { } public verifySourceMapOutput() { - Harness.Compiler.doSourcemapBaseline( + Compiler.doSourcemapBaseline( this.configuredName, this.options, this.result, @@ -320,7 +330,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)), @@ -328,17 +338,17 @@ class CompilerTest { /*multifile*/ undefined, /*skipTypeBaselines*/ undefined, /*skipSymbolBaselines*/ undefined, - !!ts.length(this.result.diagnostics) + !!length(this.result.diagnostics) ); } private makeUnitName(name: string, root: string) { - const path = ts.toPath(name, root, ts.identity); - const pathStart = ts.toPath(Harness.IO.getCurrentDirectory(), "", ts.identity); + const path = toPath(name, root, identity); + const pathStart = toPath(IO.getCurrentDirectory(), "", 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 3bc4529d217b1..cff64f9d2cf35 100644 --- a/src/testRunner/externalCompileRunner.ts +++ b/src/testRunner/externalCompileRunner.ts @@ -1,5 +1,10 @@ -import * as Harness from "./_namespaces/Harness"; -import * as ts from "./_namespaces/ts"; +import { compareStringsCaseSensitive, compareValues, flatten, stringContains } from "../compiler/core"; +import { Debug } from "../compiler/debug"; +import { comparePathsCaseSensitive } from "../compiler/path"; +import { Version } from "../compiler/semver"; +import { Baseline, IO } from "../harness/harnessIO"; +import { RunnerBase, TestRunnerKind } from "../harness/runnerbase"; +import { isWorker } from "./runner"; const fs: typeof import("fs") = require("fs"); const path: typeof import("path") = require("path"); @@ -18,11 +23,11 @@ interface UserConfig { path?: string; } -abstract class ExternalCompileRunnerBase extends Harness.RunnerBase { +abstract class ExternalCompileRunnerBase extends RunnerBase { abstract testDir: string; abstract report(result: ExecResult, cwd: string): 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,14 +54,14 @@ 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; - ts.Debug.assert(!!config.types, "Bad format from test.json: Types field must be present."); - ts.Debug.assert(!!config.cloneUrl, "Bad format from test.json: cloneUrl field must be present."); + Debug.assert(!!config.types, "Bad format from test.json: Types field must be present."); + Debug.assert(!!config.cloneUrl, "Bad format from test.json: cloneUrl field must be present."); const submoduleDir = path.join(cwd, directoryName); if (!fs.existsSync(submoduleDir)) { exec("git", ["--work-tree", submoduleDir, "clone", "-b", config.branch || "master", config.cloneUrl, path.join(submoduleDir, ".git")], { cwd }); @@ -73,7 +78,7 @@ abstract class ExternalCompileRunnerBase extends Harness.RunnerBase { cwd = config.path ? path.join(cwd, config.path) : submoduleDir; } const npmVersionText = exec("npm", ["--version"], { cwd, stdio: "pipe" })?.trim(); - const npmVersion = npmVersionText ? ts.Version.tryParse(npmVersionText.trim()) : undefined; + const npmVersion = npmVersionText ? Version.tryParse(npmVersionText.trim()) : undefined; const isV7OrLater = !!npmVersion && npmVersion.major >= 7; if (fs.existsSync(path.join(cwd, "package.json"))) { if (fs.existsSync(path.join(cwd, "package-lock.json"))) { @@ -84,7 +89,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 +98,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 }), cwd)); + Baseline.runBaseline(`${cls.kind()}/${directoryName}.log`, cls.report(cp.spawnSync(`node`, args, { cwd, timeout, shell: true }), cwd)); 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 +114,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 +131,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 +143,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 +161,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 +250,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 '"/`) @@ -253,13 +258,13 @@ function stripAbsoluteImportPaths(result: string) { } function sortErrors(result: string) { - return ts.flatten(splitBy(result.split("\n"), s => /^\S+/.test(s)).sort(compareErrorStrings)).join("\n"); + return flatten(splitBy(result.split("\n"), s => /^\S+/.test(s)).sort(compareErrorStrings)).join("\n"); } const errorRegexp = /^(.+\.[tj]sx?)\((\d+),(\d+)\)(: error TS.*)/; function compareErrorStrings(a: string[], b: string[]) { - ts.Debug.assertGreaterThanOrEqual(a.length, 1); - ts.Debug.assertGreaterThanOrEqual(b.length, 1); + Debug.assertGreaterThanOrEqual(a.length, 1); + Debug.assertGreaterThanOrEqual(b.length, 1); const matchA = a[0].match(errorRegexp); if (!matchA) { return -1; @@ -270,17 +275,17 @@ function compareErrorStrings(a: string[], b: string[]) { } const [, errorFileA, lineNumberStringA, columnNumberStringA, remainderA] = matchA; const [, errorFileB, lineNumberStringB, columnNumberStringB, remainderB] = matchB; - return ts.comparePathsCaseSensitive(errorFileA, errorFileB) || - ts.compareValues(parseInt(lineNumberStringA), parseInt(lineNumberStringB)) || - ts.compareValues(parseInt(columnNumberStringA), parseInt(columnNumberStringB)) || - ts.compareStringsCaseSensitive(remainderA, remainderB) || - ts.compareStringsCaseSensitive(a.slice(1).join("\n"), b.slice(1).join("\n")); + return comparePathsCaseSensitive(errorFileA, errorFileB) || + compareValues(parseInt(lineNumberStringA), parseInt(lineNumberStringB)) || + compareValues(parseInt(columnNumberStringA), parseInt(columnNumberStringB)) || + compareStringsCaseSensitive(remainderA, remainderB) || + compareStringsCaseSensitive(a.slice(1).join("\n"), b.slice(1).join("\n")); } export class DefinitelyTypedRunner extends ExternalCompileRunnerBase { readonly testDir = "../DefinitelyTyped/types/"; workingDirectory = this.testDir; - kind(): Harness.TestRunnerKind { + kind(): TestRunnerKind { return "dt"; } report(result: ExecResult, cwd: string) { @@ -299,7 +304,7 @@ ${stderr.replace(/\r\n/g, "\n")}`; } function removeExpectedErrors(errors: string, cwd: string): string { - return ts.flatten(splitBy(errors.split("\n"), s => /^\S+/.test(s)).filter(isUnexpectedError(cwd))).join("\n"); + return flatten(splitBy(errors.split("\n"), s => /^\S+/.test(s)).filter(isUnexpectedError(cwd))).join("\n"); } /** * Returns true if the line that caused the error contains '$ExpectError', @@ -309,7 +314,7 @@ function removeExpectedErrors(errors: string, cwd: string): string { */ function isUnexpectedError(cwd: string) { return (error: string[]) => { - ts.Debug.assertGreaterThanOrEqual(error.length, 1); + Debug.assertGreaterThanOrEqual(error.length, 1); const match = error[0].match(/(.+\.tsx?)\((\d+),\d+\): error TS/); if (!match) { return true; @@ -317,10 +322,10 @@ function isUnexpectedError(cwd: string) { const [, errorFile, lineNumberString] = match; const lines = fs.readFileSync(path.join(cwd, errorFile), { encoding: "utf8" }).split("\n"); const lineNumber = parseInt(lineNumberString) - 1; - ts.Debug.assertGreaterThanOrEqual(lineNumber, 0); - ts.Debug.assertLessThan(lineNumber, lines.length); + Debug.assertGreaterThanOrEqual(lineNumber, 0); + Debug.assertLessThan(lineNumber, lines.length); const previousLine = lineNumber - 1 > 0 ? lines[lineNumber - 1] : ""; - return !ts.stringContains(lines[lineNumber], "$ExpectError") && !ts.stringContains(previousLine, "$ExpectError"); + return !stringContains(lines[lineNumber], "$ExpectError") && !stringContains(previousLine, "$ExpectError"); }; } /** diff --git a/src/testRunner/fourslashRunner.ts b/src/testRunner/fourslashRunner.ts index 357a745deab11..22fe777fa13c8 100644 --- a/src/testRunner/fourslashRunner.ts +++ b/src/testRunner/fourslashRunner.ts @@ -1,32 +1,34 @@ -import * as FourSlash from "./_namespaces/FourSlash"; -import * as Harness from "./_namespaces/Harness"; -import * as ts from "./_namespaces/ts"; +import { Debug } from "../compiler/debug"; +import { normalizeSlashes } from "../compiler/path"; +import { FourSlashTestType, runFourSlashTest } from "../harness/fourslashImpl"; +import { IO } from "../harness/harnessIO"; +import { RunnerBase, TestRunnerKind } from "../harness/runnerbase"; -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) { + constructor(private testType: FourSlashTestType) { super(); switch (testType) { - case FourSlash.FourSlashTestType.Native: + case FourSlashTestType.Native: this.basePath = "tests/cases/fourslash"; this.testSuiteName = "fourslash"; break; - case FourSlash.FourSlashTestType.Shims: + case FourSlashTestType.Shims: this.basePath = "tests/cases/fourslash/shims"; this.testSuiteName = "fourslash-shims"; break; - case FourSlash.FourSlashTestType.ShimsWithPreprocess: + case FourSlashTestType.ShimsWithPreprocess: this.basePath = "tests/cases/fourslash/shims-pp"; this.testSuiteName = "fourslash-shims-pp"; break; - case FourSlash.FourSlashTestType.Server: + case FourSlashTestType.Server: this.basePath = "tests/cases/fourslash/server"; this.testSuiteName = "fourslash-server"; break; default: - throw ts.Debug.assertNever(testType); + throw Debug.assertNever(testType); } } @@ -41,14 +43,14 @@ 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", () => { this.tests.forEach(test => { const file = typeof test === "string" ? test : test.file; describe(file, () => { - let fn = ts.normalizeSlashes(file); + let fn = normalizeSlashes(file); const justName = fn.replace(/^.*[\\\/]/, ""); // Convert to relative path @@ -57,7 +59,7 @@ export class FourSlashRunner extends Harness.RunnerBase { if (justName !== "fourslash.ts") { it(this.testSuiteName + " test " + justName + " runs correctly", () => { - FourSlash.runFourSlashTest(this.basePath, this.testType, fn); + runFourSlashTest(this.basePath, this.testType, fn); }); } }); @@ -67,7 +69,7 @@ export class FourSlashRunner extends Harness.RunnerBase { } export class GeneratedFourslashRunner extends FourSlashRunner { - constructor(testType: FourSlash.FourSlashTestType) { + constructor(testType: FourSlashTestType) { super(testType); this.basePath += "/generated/"; } diff --git a/src/testRunner/parallel/host.ts b/src/testRunner/parallel/host.ts index a99f3c7130197..7b859c96fc553 100644 --- a/src/testRunner/parallel/host.ts +++ b/src/testRunner/parallel/host.ts @@ -1,6 +1,16 @@ -import * as Harness from "../_namespaces/Harness"; -import * as ts from "../_namespaces/ts"; -import * as Utils from "../_namespaces/Utils"; +import { Map } from "../../compiler/corePublic"; +import { Debug } from "../../compiler/debug"; +import { combinePaths } from "../../compiler/path"; +import { findUpFile } from "../../harness/findUpDir"; +import { IO, lightMode } from "../../harness/harnessIO"; +import { TestRunnerKind } from "../../harness/runnerbase"; +import { + configOption, globalTimeout, keepFailed, noColors, runners, runUnitTests, stackTraceLimit, taskConfigsFolder, + TestConfig, workerCount, +} from "../runner"; +import { + ErrorInfo, ParallelClientMessage, ParallelHostMessage, shimNoopTestInterface, Task, TaskTimeout, TestInfo, +} from "./shared"; export function start() { const Mocha = require("mocha") as typeof import("mocha"); @@ -17,17 +27,17 @@ export function start() { const { statSync } = require("fs") as typeof import("fs"); // NOTE: paths for module and types for FailedTestReporter _do not_ line up due to our use of --outFile for run.js - const FailedTestReporter = require(Utils.findUpFile("scripts/failed-tests.js")) as typeof import("../../../scripts/failed-tests"); + const FailedTestReporter = require(findUpFile("scripts/failed-tests.js")) as typeof import("../../../scripts/failed-tests"); 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; class RemoteSuite extends Mocha.Suite { - suiteMap = new ts.Map(); + suiteMap = new Map(); constructor(title: string) { super(title); this.pending = false; @@ -44,8 +54,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 no-in-operator @@ -178,14 +188,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 +203,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 +214,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 +238,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 +261,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 = 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 +278,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 +295,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 +347,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 +359,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 +374,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; } @@ -410,14 +420,14 @@ export function start() { } else { // Out of batches, send off just one test const payload = tasks.pop()!; - ts.Debug.assert(!!payload); // The reserve kept above should ensure there is always an initial task available, even in suboptimal scenarios + Debug.assert(!!payload); // The reserve kept above should ensure there is always an initial task available, even in suboptimal scenarios worker.currentTasks = [payload]; worker.process.send({ type: "test", payload }); } } } 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 +447,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 +491,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 +505,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 +562,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 +608,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 +630,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..bd87896fe50e2 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 { noop } from "../../compiler/core"; +import { TestRunnerKind } from "../../harness/runnerbase"; export interface RunnerTask { - runner: Harness.TestRunnerKind; + runner: TestRunnerKind; file: string; size: number; } @@ -76,14 +76,14 @@ export interface ParallelTimeoutChangeMessage { export type ParallelClientMessage = ParallelErrorMessage | ParallelResultMessage | ParallelBatchProgressMessage | ParallelTimeoutChangeMessage; export function shimNoopTestInterface(global: Mocha.MochaGlobals) { - global.before = ts.noop; - global.after = ts.noop; - global.beforeEach = ts.noop; - global.afterEach = ts.noop; + global.before = noop; + global.after = noop; + global.beforeEach = noop; + global.afterEach = noop; global.describe = global.context = ((_: any, __: any) => { /*empty*/ }) as Mocha.SuiteFunction; - global.describe.skip = global.xdescribe = global.xcontext = ts.noop as Mocha.PendingSuiteFunction; - global.describe.only = ts.noop as Mocha.ExclusiveSuiteFunction; + global.describe.skip = global.xdescribe = global.xcontext = noop as Mocha.PendingSuiteFunction; + global.describe.only = noop as Mocha.ExclusiveSuiteFunction; global.it = global.specify = ((_: any, __: any) => { /*empty*/ }) as Mocha.TestFunction; - global.it.skip = global.xit = global.xspecify = ts.noop as Mocha.PendingTestFunction; - global.it.only = ts.noop as Mocha.ExclusiveTestFunction; + global.it.skip = global.xit = global.xspecify = noop as Mocha.PendingTestFunction; + global.it.only = noop as Mocha.ExclusiveTestFunction; } diff --git a/src/testRunner/parallel/worker.ts b/src/testRunner/parallel/worker.ts index 5c07637a5efd5..c74088b1a9310 100644 --- a/src/testRunner/parallel/worker.ts +++ b/src/testRunner/parallel/worker.ts @@ -1,5 +1,10 @@ -import * as Harness from "../_namespaces/Harness"; -import * as ts from "../_namespaces/ts"; +import { ESMap, Map } from "../../compiler/corePublic"; +import { RunnerBase } from "../../harness/runnerbase"; +import { createRunner, globalTimeout, runUnitTests } from "../runner"; +import { + ErrorInfo, ParallelClientMessage, ParallelHostMessage, RunnerTask, shimNoopTestInterface, Task, TaskResult, + TestInfo, UnitTestTask, +} from "./shared"; export function start() { function hookUncaughtExceptions() { @@ -137,7 +142,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,15 +151,15 @@ 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(); + unitTestSuiteMap = new Map(); for (const suite of unitTestSuite.suites) { unitTestSuiteMap.set(suite.title, suite); } } if (!unitTestTestMap && unitTestSuite.tests.length) { - unitTestTestMap = new ts.Map(); + unitTestTestMap = new Map(); for (const test of unitTestSuite.tests) { unitTestTestMap.set(test.title, test); } @@ -171,7 +176,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 +198,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 +212,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 +240,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 +252,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 +276,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,27 +297,27 @@ 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 Map(); // The root suite for all unit tests. let unitTestSuite: Suite; - let unitTestSuiteMap: ts.ESMap; + let unitTestSuiteMap: ESMap; // (Unit) Tests directly within the root suite - let unitTestTestMap: ts.ESMap; + let unitTestTestMap: 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/projectsRunner.ts b/src/testRunner/projectsRunner.ts index cadb19b5dd46a..9a3b4c5c578f3 100644 --- a/src/testRunner/projectsRunner.ts +++ b/src/testRunner/projectsRunner.ts @@ -1,10 +1,26 @@ -import * as documents from "./_namespaces/documents"; -import * as fakes from "./_namespaces/fakes"; -import * as Harness from "./_namespaces/Harness"; +import { + optionDeclarations, parseJsonSourceFileConfigFileContent, readJsonConfigFile, +} from "../compiler/commandLineParser"; +import { arrayToMap, concatenate, contains, forEach, isString } from "../compiler/core"; +import { + combinePaths, getDirectoryPath, getNormalizedAbsolutePath, isRootedDiskPath, normalizePath, normalizeSlashes, +} from "../compiler/path"; +import { createProgram, findConfigFile, getPreEmitDiagnostics } from "../compiler/program"; +import { + CharacterCodes, CompilerOptions, Diagnostic, Extension, ModuleKind, ModuleResolutionKind, NewLineKind, Program, + SourceFile, SourceMapEmitResult, +} from "../compiler/types"; +import { removeFileExtension } from "../compiler/utilities"; +import { TextDocument } from "../harness/documentsUtil"; +import { CompilerHost, ParseConfigHost, System } from "../harness/fakesHosts"; +import { Baseline, Compiler, IO, isDefaultLibraryFile } from "../harness/harnessIO"; +import { RunnerBase, shardId, shards, TestRunnerKind } from "../harness/runnerbase"; +import { removeTestPathPrefixes } from "../harness/util"; +import { + builtFolder, createFromFileSystem, createResolver, FileSystem, srcFolder, testLibFolder, +} from "../harness/vfsUtil"; +import { beneath, combine, extname, isAbsolute, isDefaultLibrary, relative, resolve } from "../harness/vpathUtil"; import * as ts from "./_namespaces/ts"; -import * as Utils from "./_namespaces/Utils"; -import * as vfs from "./_namespaces/vfs"; -import * as vpath from "./_namespaces/vpath"; // Test case is json of below type in tests/cases/project/ interface ProjectRunnerTestCase { @@ -25,28 +41,28 @@ interface ProjectRunnerTestCaseResolutionInfo extends ProjectRunnerTestCase { } interface CompileProjectFilesResult { - configFileSourceFiles: readonly ts.SourceFile[]; - moduleKind: ts.ModuleKind; - program?: ts.Program; - compilerOptions?: ts.CompilerOptions; - errors: readonly ts.Diagnostic[]; - sourceMapData?: readonly ts.SourceMapEmitResult[]; + configFileSourceFiles: readonly SourceFile[]; + moduleKind: ModuleKind; + program?: Program; + compilerOptions?: CompilerOptions; + errors: readonly Diagnostic[]; + sourceMapData?: readonly SourceMapEmitResult[]; } interface BatchCompileProjectTestCaseResult extends CompileProjectFilesResult { - outputFiles?: readonly documents.TextDocument[]; + outputFiles?: readonly TextDocument[]; } -export class ProjectRunner extends Harness.RunnerBase { +export class ProjectRunner extends RunnerBase { public enumerateTestFiles() { const all = this.enumerateFiles("tests/cases/project", /\.json$/, { recursive: true }); - if (Harness.shards === 1) { + if (shards === 1) { return all; } - return all.filter((_val, idx) => idx % Harness.shards === (Harness.shardId - 1)); + return all.filter((_val, idx) => idx % shards === (shardId - 1)); } - public kind(): Harness.TestRunnerKind { + public kind(): TestRunnerKind { return "project"; } @@ -80,38 +96,38 @@ export class ProjectRunner extends Harness.RunnerBase { } } -class ProjectCompilerHost extends fakes.CompilerHost { - private _testCase: ProjectRunnerTestCase & ts.CompilerOptions; +class ProjectCompilerHost extends CompilerHost { + private _testCase: ProjectRunnerTestCase & CompilerOptions; private _projectParseConfigHost: ProjectParseConfigHost | undefined; - constructor(sys: fakes.System | vfs.FileSystem, compilerOptions: ts.CompilerOptions, _testCaseJustName: string, testCase: ProjectRunnerTestCase & ts.CompilerOptions, _moduleKind: ts.ModuleKind) { + constructor(sys: System | FileSystem, compilerOptions: CompilerOptions, _testCaseJustName: string, testCase: ProjectRunnerTestCase & CompilerOptions, _moduleKind: ModuleKind) { super(sys, compilerOptions); this._testCase = testCase; } - public get parseConfigHost(): fakes.ParseConfigHost { + public get parseConfigHost(): ParseConfigHost { return this._projectParseConfigHost || (this._projectParseConfigHost = new ProjectParseConfigHost(this.sys, this._testCase)); } - public getDefaultLibFileName(_options: ts.CompilerOptions) { - return vpath.resolve(this.getDefaultLibLocation(), "lib.es5.d.ts"); + public getDefaultLibFileName(_options: CompilerOptions) { + return resolve(this.getDefaultLibLocation(), "lib.es5.d.ts"); } } -class ProjectParseConfigHost extends fakes.ParseConfigHost { - private _testCase: ProjectRunnerTestCase & ts.CompilerOptions; +class ProjectParseConfigHost extends ParseConfigHost { + private _testCase: ProjectRunnerTestCase & CompilerOptions; - constructor(sys: fakes.System, testCase: ProjectRunnerTestCase & ts.CompilerOptions) { + constructor(sys: System, testCase: ProjectRunnerTestCase & CompilerOptions) { super(sys); this._testCase = testCase; } public readDirectory(path: string, extensions: string[], excludes: string[], includes: string[], depth: number): string[] { const result = super.readDirectory(path, extensions, excludes, includes, depth); - const projectRoot = vpath.resolve(vfs.srcFolder, this._testCase.projectRoot); - return result.map(item => vpath.relative( + const projectRoot = resolve(srcFolder, this._testCase.projectRoot); + return result.map(item => relative( projectRoot, - vpath.resolve(projectRoot, item), + resolve(projectRoot, item), this.vfs.ignoreCase )); } @@ -123,42 +139,42 @@ interface ProjectTestConfiguration { } interface ProjectTestPayload { - testCase: ProjectRunnerTestCase & ts.CompilerOptions; - moduleKind: ts.ModuleKind; - vfs: vfs.FileSystem; + testCase: ProjectRunnerTestCase & CompilerOptions; + moduleKind: ModuleKind; + vfs: FileSystem; } class ProjectTestCase { - private testCase: ProjectRunnerTestCase & ts.CompilerOptions; + private testCase: ProjectRunnerTestCase & CompilerOptions; private testCaseJustName: string; - private sys: fakes.System; - private compilerOptions: ts.CompilerOptions; + private sys: System; + private compilerOptions: CompilerOptions; private compilerResult: BatchCompileProjectTestCaseResult; constructor(testCaseFileName: string, { testCase, moduleKind, vfs }: ProjectTestPayload) { this.testCase = testCase; this.testCaseJustName = testCaseFileName.replace(/^.*[\\\/]/, "").replace(/\.json/, ""); this.compilerOptions = createCompilerOptions(testCase, moduleKind); - this.sys = new fakes.System(vfs); + this.sys = new System(vfs); let configFileName: string | undefined; let inputFiles = testCase.inputFiles; if (this.compilerOptions.project) { // Parse project - configFileName = ts.normalizePath(ts.combinePaths(this.compilerOptions.project, "tsconfig.json")); + configFileName = normalizePath(combinePaths(this.compilerOptions.project, "tsconfig.json")); assert(!inputFiles || inputFiles.length === 0, "cannot specify input files and project option together"); } else if (!inputFiles || inputFiles.length === 0) { - configFileName = ts.findConfigFile("", path => this.sys.fileExists(path)); + configFileName = findConfigFile("", path => this.sys.fileExists(path)); } - let errors: ts.Diagnostic[] | undefined; - const configFileSourceFiles: ts.SourceFile[] = []; + let errors: Diagnostic[] | undefined; + const configFileSourceFiles: SourceFile[] = []; if (configFileName) { - const result = ts.readJsonConfigFile(configFileName, path => this.sys.readFile(path)); + const result = readJsonConfigFile(configFileName, path => this.sys.readFile(path)); configFileSourceFiles.push(result); const configParseHost = new ProjectParseConfigHost(this.sys, this.testCase); - const configParseResult = ts.parseJsonSourceFileConfigFileContent(result, configParseHost, ts.getDirectoryPath(configFileName), this.compilerOptions); + const configParseResult = parseJsonSourceFileConfigFileContent(result, configParseHost, getDirectoryPath(configFileName), this.compilerOptions); inputFiles = configParseResult.fileNames; this.compilerOptions = configParseResult.options; errors = [...result.parseDiagnostics, ...configParseResult.errors]; @@ -174,7 +190,7 @@ class ProjectTestCase { compilerOptions: this.compilerOptions, sourceMapData: projectCompilerResult.sourceMapData, outputFiles: compilerHost.outputs, - errors: errors ? ts.concatenate(errors, projectCompilerResult.errors) : projectCompilerResult.errors, + errors: errors ? concatenate(errors, projectCompilerResult.errors) : projectCompilerResult.errors, }; } @@ -183,56 +199,56 @@ class ProjectTestCase { } public static getConfigurations(testCaseFileName: string): ProjectTestConfiguration[] { - let testCase: ProjectRunnerTestCase & ts.CompilerOptions; + let testCase: ProjectRunnerTestCase & CompilerOptions; let testFileText: string | undefined; try { - testFileText = Harness.IO.readFile(testCaseFileName); + testFileText = IO.readFile(testCaseFileName); } catch (e) { assert(false, "Unable to open testcase file: " + testCaseFileName + ": " + e.message); } try { - testCase = JSON.parse(testFileText!) as ProjectRunnerTestCase & ts.CompilerOptions; + testCase = JSON.parse(testFileText!) as ProjectRunnerTestCase & CompilerOptions; } catch (e) { throw assert(false, "Testcase: " + testCaseFileName + " does not contain valid json format: " + e.message); } - const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false); - fs.mountSync(vpath.resolve(Harness.IO.getWorkspaceRoot(), "tests"), vpath.combine(vfs.srcFolder, "tests"), vfs.createResolver(Harness.IO)); - fs.mkdirpSync(vpath.combine(vfs.srcFolder, testCase.projectRoot)); - fs.chdir(vpath.combine(vfs.srcFolder, testCase.projectRoot)); + const fs = createFromFileSystem(IO, /*ignoreCase*/ false); + fs.mountSync(resolve(IO.getWorkspaceRoot(), "tests"), combine(srcFolder, "tests"), createResolver(IO)); + fs.mkdirpSync(combine(srcFolder, testCase.projectRoot)); + fs.chdir(combine(srcFolder, testCase.projectRoot)); fs.makeReadonly(); return [ - { name: `@module: commonjs`, payload: { testCase, moduleKind: ts.ModuleKind.CommonJS, vfs: fs } }, - { name: `@module: amd`, payload: { testCase, moduleKind: ts.ModuleKind.AMD, vfs: fs } } + { name: `@module: commonjs`, payload: { testCase, moduleKind: ModuleKind.CommonJS, vfs: fs } }, + { name: `@module: amd`, payload: { testCase, moduleKind: ModuleKind.AMD, vfs: fs } } ]; } public verifyResolution() { const cwd = this.vfs.cwd(); const ignoreCase = this.vfs.ignoreCase; - const resolutionInfo: ProjectRunnerTestCaseResolutionInfo & ts.CompilerOptions = JSON.parse(JSON.stringify(this.testCase)); + const resolutionInfo: ProjectRunnerTestCaseResolutionInfo & CompilerOptions = JSON.parse(JSON.stringify(this.testCase)); resolutionInfo.resolvedInputFiles = this.compilerResult.program!.getSourceFiles() .map(({ fileName: input }) => - vpath.beneath(vfs.builtFolder, input, this.vfs.ignoreCase) || vpath.beneath(vfs.testLibFolder, input, this.vfs.ignoreCase) ? Utils.removeTestPathPrefixes(input) : - vpath.isAbsolute(input) ? vpath.relative(cwd, input, ignoreCase) : + beneath(builtFolder, input, this.vfs.ignoreCase) || beneath(testLibFolder, input, this.vfs.ignoreCase) ? removeTestPathPrefixes(input) : + isAbsolute(input) ? relative(cwd, input, ignoreCase) : input); resolutionInfo.emittedFiles = this.compilerResult.outputFiles! .map(output => output.meta.get("fileName") || output.file) - .map(output => Utils.removeTestPathPrefixes(vpath.isAbsolute(output) ? vpath.relative(cwd, output, ignoreCase) : output)); + .map(output => removeTestPathPrefixes(isAbsolute(output) ? relative(cwd, output, ignoreCase) : output)); const content = JSON.stringify(resolutionInfo, undefined, " "); - Harness.Baseline.runBaseline(this.getBaselineFolder(this.compilerResult.moduleKind) + this.testCaseJustName + ".json", content); + Baseline.runBaseline(this.getBaselineFolder(this.compilerResult.moduleKind) + this.testCaseJustName + ".json", content); } public verifyDiagnostics() { if (this.compilerResult.errors.length) { - Harness.Baseline.runBaseline(this.getBaselineFolder(this.compilerResult.moduleKind) + this.testCaseJustName + ".errors.txt", getErrorsBaseline(this.compilerResult)); + Baseline.runBaseline(this.getBaselineFolder(this.compilerResult.moduleKind) + this.testCaseJustName + ".errors.txt", getErrorsBaseline(this.compilerResult)); } } @@ -245,20 +261,20 @@ class ProjectTestCase { // convert file name to rooted name // if filename is not rooted - concat it with project root and then expand project root relative to current directory const fileName = output.meta.get("fileName") || output.file; - const diskFileName = vpath.isAbsolute(fileName) ? fileName : vpath.resolve(this.vfs.cwd(), fileName); + const diskFileName = isAbsolute(fileName) ? fileName : resolve(this.vfs.cwd(), fileName); // compute file name relative to current directory (expanded project root) - let diskRelativeName = vpath.relative(this.vfs.cwd(), diskFileName, this.vfs.ignoreCase); - if (vpath.isAbsolute(diskRelativeName) || diskRelativeName.startsWith("../")) { + let diskRelativeName = relative(this.vfs.cwd(), diskFileName, this.vfs.ignoreCase); + if (isAbsolute(diskRelativeName) || diskRelativeName.startsWith("../")) { // If the generated output file resides in the parent folder or is rooted path, // we need to instead create files that can live in the project reference folder // but make sure extension of these files matches with the fileName the compiler asked to write - diskRelativeName = `diskFile${nonSubfolderDiskFiles}${vpath.extname(fileName, [".js.map", ".js", ".d.ts"], this.vfs.ignoreCase)}`; + diskRelativeName = `diskFile${nonSubfolderDiskFiles}${extname(fileName, [".js.map", ".js", ".d.ts"], this.vfs.ignoreCase)}`; nonSubfolderDiskFiles++; } - const content = Utils.removeTestPathPrefixes(output.text, /*retainTrailingDirectorySeparator*/ true); - Harness.Baseline.runBaseline(this.getBaselineFolder(this.compilerResult.moduleKind) + diskRelativeName, content as string | null); // TODO: GH#18217 + const content = removeTestPathPrefixes(output.text, /*retainTrailingDirectorySeparator*/ true); + Baseline.runBaseline(this.getBaselineFolder(this.compilerResult.moduleKind) + diskRelativeName, content as string | null); // TODO: GH#18217 } catch (e) { errs.push(e); @@ -285,20 +301,20 @@ class ProjectTestCase { if (!this.compilerResult.errors.length && this.testCase.declaration) { const dTsCompileResult = this.compileDeclarations(this.compilerResult); if (dTsCompileResult && dTsCompileResult.errors.length) { - Harness.Baseline.runBaseline(this.getBaselineFolder(this.compilerResult.moduleKind) + this.testCaseJustName + ".dts.errors.txt", getErrorsBaseline(dTsCompileResult)); + Baseline.runBaseline(this.getBaselineFolder(this.compilerResult.moduleKind) + this.testCaseJustName + ".dts.errors.txt", getErrorsBaseline(dTsCompileResult)); } } } // Project baselines verified go in project/testCaseName/moduleKind/ - private getBaselineFolder(moduleKind: ts.ModuleKind) { + private getBaselineFolder(moduleKind: ModuleKind) { return "project/" + this.testCaseJustName + "/" + moduleNameToString(moduleKind) + "/"; } private cleanProjectUrl(url: string) { - let diskProjectPath = ts.normalizeSlashes(Harness.IO.resolvePath(this.testCase.projectRoot)!); + let diskProjectPath = normalizeSlashes(IO.resolvePath(this.testCase.projectRoot)!); let projectRootUrl = "file:///" + diskProjectPath; - const normalizedProjectRoot = ts.normalizeSlashes(this.testCase.projectRoot); + const normalizedProjectRoot = normalizeSlashes(this.testCase.projectRoot); diskProjectPath = diskProjectPath.substr(0, diskProjectPath.lastIndexOf(normalizedProjectRoot)); projectRootUrl = projectRootUrl.substr(0, projectRootUrl.lastIndexOf(normalizedProjectRoot)); if (url && url.length) { @@ -309,7 +325,7 @@ class ProjectTestCase { else if (url.indexOf(diskProjectPath) === 0) { // Replace the disk specific path into the project root path url = url.substr(diskProjectPath.length); - if (url.charCodeAt(0) !== ts.CharacterCodes.slash) { + if (url.charCodeAt(0) !== CharacterCodes.slash) { url = "/" + url; } } @@ -318,13 +334,13 @@ class ProjectTestCase { return url; } - private compileProjectFiles(moduleKind: ts.ModuleKind, configFileSourceFiles: readonly ts.SourceFile[], + private compileProjectFiles(moduleKind: ModuleKind, configFileSourceFiles: readonly SourceFile[], getInputFiles: () => readonly string[], compilerHost: ts.CompilerHost, - compilerOptions: ts.CompilerOptions): CompileProjectFilesResult { + compilerOptions: CompilerOptions): CompileProjectFilesResult { - const program = ts.createProgram(getInputFiles(), compilerOptions, compilerHost); - const errors = ts.getPreEmitDiagnostics(program); + const program = createProgram(getInputFiles(), compilerOptions, compilerHost); + const errors = getPreEmitDiagnostics(program); const { sourceMaps: sourceMapData, diagnostics: emitDiagnostics } = program.emit(); @@ -343,7 +359,7 @@ class ProjectTestCase { configFileSourceFiles, moduleKind, program, - errors: ts.concatenate(errors, emitDiagnostics), + errors: concatenate(errors, emitDiagnostics), sourceMapData }; } @@ -354,27 +370,27 @@ class ProjectTestCase { } const compilerOptions = compilerResult.program.getCompilerOptions(); - const allInputFiles: documents.TextDocument[] = []; + const allInputFiles: TextDocument[] = []; const rootFiles: string[] = []; - ts.forEach(compilerResult.program.getSourceFiles(), sourceFile => { + forEach(compilerResult.program.getSourceFiles(), sourceFile => { if (sourceFile.isDeclarationFile) { - if (!vpath.isDefaultLibrary(sourceFile.fileName)) { - allInputFiles.unshift(new documents.TextDocument(sourceFile.fileName, sourceFile.text)); + if (!isDefaultLibrary(sourceFile.fileName)) { + allInputFiles.unshift(new TextDocument(sourceFile.fileName, sourceFile.text)); } rootFiles.unshift(sourceFile.fileName); } else if (!(compilerOptions.outFile || compilerOptions.out)) { let emitOutputFilePathWithoutExtension: string | undefined; if (compilerOptions.outDir) { - let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, compilerResult.program!.getCurrentDirectory()); + let sourceFilePath = getNormalizedAbsolutePath(sourceFile.fileName, compilerResult.program!.getCurrentDirectory()); sourceFilePath = sourceFilePath.replace(compilerResult.program!.getCommonSourceDirectory(), ""); - emitOutputFilePathWithoutExtension = ts.removeFileExtension(ts.combinePaths(compilerOptions.outDir, sourceFilePath)); + emitOutputFilePathWithoutExtension = removeFileExtension(combinePaths(compilerOptions.outDir, sourceFilePath)); } else { - emitOutputFilePathWithoutExtension = ts.removeFileExtension(sourceFile.fileName); + emitOutputFilePathWithoutExtension = removeFileExtension(sourceFile.fileName); } - const outputDtsFileName = emitOutputFilePathWithoutExtension + ts.Extension.Dts; + const outputDtsFileName = emitOutputFilePathWithoutExtension + Extension.Dts; const file = findOutputDtsFile(outputDtsFileName); if (file) { allInputFiles.unshift(file); @@ -382,18 +398,18 @@ class ProjectTestCase { } } else { - const outputDtsFileName = ts.removeFileExtension(compilerOptions.outFile || compilerOptions.out!) + ts.Extension.Dts; + const outputDtsFileName = removeFileExtension(compilerOptions.outFile || compilerOptions.out!) + Extension.Dts; const outputDtsFile = findOutputDtsFile(outputDtsFileName)!; - if (!ts.contains(allInputFiles, outputDtsFile)) { + if (!contains(allInputFiles, outputDtsFile)) { allInputFiles.unshift(outputDtsFile); rootFiles.unshift(outputDtsFile.meta.get("fileName") || outputDtsFile.file); } } }); - const _vfs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, { + const _vfs = createFromFileSystem(IO, /*ignoreCase*/ false, { documents: allInputFiles, - cwd: vpath.combine(vfs.srcFolder, this.testCase.projectRoot) + cwd: combine(srcFolder, this.testCase.projectRoot) }); // Dont allow config files since we are compiling existing source options @@ -401,62 +417,62 @@ class ProjectTestCase { return this.compileProjectFiles(compilerResult.moduleKind, compilerResult.configFileSourceFiles, () => rootFiles, compilerHost, compilerResult.compilerOptions!); function findOutputDtsFile(fileName: string) { - return ts.forEach(compilerResult.outputFiles, outputFile => outputFile.meta.get("fileName") === fileName ? outputFile : undefined); + return forEach(compilerResult.outputFiles, outputFile => outputFile.meta.get("fileName") === fileName ? outputFile : undefined); } } } -function moduleNameToString(moduleKind: ts.ModuleKind) { - return moduleKind === ts.ModuleKind.AMD ? "amd" : - moduleKind === ts.ModuleKind.CommonJS ? "node" : "none"; +function moduleNameToString(moduleKind: ModuleKind) { + return moduleKind === ModuleKind.AMD ? "amd" : + moduleKind === ModuleKind.CommonJS ? "node" : "none"; } function getErrorsBaseline(compilerResult: CompileProjectFilesResult) { const inputSourceFiles = compilerResult.configFileSourceFiles.slice(); if (compilerResult.program) { for (const sourceFile of compilerResult.program.getSourceFiles()) { - if (!Harness.isDefaultLibraryFile(sourceFile.fileName)) { + if (!isDefaultLibraryFile(sourceFile.fileName)) { inputSourceFiles.push(sourceFile); } } } - const inputFiles = inputSourceFiles.map(sourceFile => ({ - unitName: ts.isRootedDiskPath(sourceFile.fileName) ? - Harness.RunnerBase.removeFullPaths(sourceFile.fileName) : + const inputFiles = inputSourceFiles.map(sourceFile => ({ + unitName: isRootedDiskPath(sourceFile.fileName) ? + RunnerBase.removeFullPaths(sourceFile.fileName) : sourceFile.fileName, content: sourceFile.text })); - return Harness.Compiler.getErrorBaseline(inputFiles, compilerResult.errors); + return Compiler.getErrorBaseline(inputFiles, compilerResult.errors); } -function createCompilerOptions(testCase: ProjectRunnerTestCase & ts.CompilerOptions, moduleKind: ts.ModuleKind) { +function createCompilerOptions(testCase: ProjectRunnerTestCase & CompilerOptions, moduleKind: ModuleKind) { // Set the special options that depend on other testcase options - const compilerOptions: ts.CompilerOptions = { + const compilerOptions: CompilerOptions = { noErrorTruncation: false, skipDefaultLibCheck: false, - moduleResolution: ts.ModuleResolutionKind.Classic, + moduleResolution: ModuleResolutionKind.Classic, module: moduleKind, - newLine: ts.NewLineKind.CarriageReturnLineFeed, + newLine: NewLineKind.CarriageReturnLineFeed, mapRoot: testCase.resolveMapRoot && testCase.mapRoot - ? vpath.resolve(vfs.srcFolder, testCase.mapRoot) + ? resolve(srcFolder, testCase.mapRoot) : testCase.mapRoot, sourceRoot: testCase.resolveSourceRoot && testCase.sourceRoot - ? vpath.resolve(vfs.srcFolder, testCase.sourceRoot) + ? resolve(srcFolder, testCase.sourceRoot) : testCase.sourceRoot }; // Set the values specified using json - const optionNameMap = ts.arrayToMap(ts.optionDeclarations, option => option.name); + const optionNameMap = arrayToMap(optionDeclarations, option => option.name); for (const name in testCase) { if (name !== "mapRoot" && name !== "sourceRoot") { const option = optionNameMap.get(name); if (option) { const optType = option.type; let value = testCase[name] as any; - if (!ts.isString(optType)) { + if (!isString(optType)) { const key = value.toLowerCase(); const optTypeValue = optType.get(key); if (optTypeValue) { diff --git a/src/testRunner/runner.ts b/src/testRunner/runner.ts index ff829e59f5a1c..be2fc590c42cd 100644 --- a/src/testRunner/runner.ts +++ b/src/testRunner/runner.ts @@ -1,24 +1,32 @@ -import * as FourSlash from "./_namespaces/FourSlash"; -import * as Harness from "./_namespaces/Harness"; -import * as project from "./_namespaces/project"; -import * as RWC from "./_namespaces/RWC"; -import * as ts from "./_namespaces/ts"; -import * as vpath from "./_namespaces/vpath"; +import { forEach, getUILocale, noop, setUILocale } from "../compiler/core"; +import { Debug } from "../compiler/debug"; +import { FourSlashTestType } from "../harness/fourslashImpl"; +import { IO, setLightMode } from "../harness/harnessIO"; +import { RunnerBase, setShardId, setShards, TestRunnerKind } from "../harness/runnerbase"; +import { basename } from "../harness/vpathUtil"; +import { Host } from "./_namespaces/Harness.Parallel"; +import { CompilerBaselineRunner, CompilerTestType } from "./compilerRunner"; +import { DefinitelyTypedRunner, DockerfileRunner, UserCodeRunner } from "./externalCompileRunner"; +import { FourSlashRunner, GeneratedFourslashRunner } from "./fourslashRunner"; +import { start } from "./parallel/worker"; +import { ProjectRunner } from "./projectsRunner"; +import { RWCRunner } from "./rwcRunner"; +import { Test262BaselineRunner } from "./test262Runner"; /* 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(); + const base = basename(full).toLowerCase(); // allow existing dupes in fourslash/shims and fourslash/server if (seen.has(base) && !/fourslash\/(shim|server)/.test(full)) { dupes.push([seen.get(base)!, full]); @@ -39,39 +47,39 @@ ${JSON.stringify(dupes, undefined, 2)}`); function tryGetConfig(args: string[]) { const prefix = "--config="; - const configPath = ts.forEach(args, arg => arg.lastIndexOf(prefix, 0) === 0 && arg.substr(prefix.length)); + const configPath = forEach(args, arg => arg.lastIndexOf(prefix, 0) === 0 && arg.substr(prefix.length)); // strip leading and trailing quotes from the path (necessary on Windows since shell does not do it automatically) 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(FourSlashTestType.Native); case "fourslash-shims": - return new Harness.FourSlashRunner(FourSlash.FourSlashTestType.Shims); + return new FourSlashRunner(FourSlashTestType.Shims); case "fourslash-shims-pp": - return new Harness.FourSlashRunner(FourSlash.FourSlashTestType.ShimsWithPreprocess); + return new FourSlashRunner(FourSlashTestType.ShimsWithPreprocess); case "fourslash-server": - return new Harness.FourSlashRunner(FourSlash.FourSlashTestType.Server); + return new FourSlashRunner(FourSlashTestType.Server); case "project": - return new project.ProjectRunner(); + return new ProjectRunner(); case "rwc": - return new RWC.RWCRunner(); + return new 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}`); + return Debug.fail(`Unknown runner kind ${kind}`); } // users can define tests to run in mytest.config that will override cmd line args, otherwise use cmd line args (test.config), otherwise no options @@ -79,13 +87,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 +119,7 @@ export interface TestConfig { } export interface TaskSet { - runner: Harness.TestRunnerKind; + runner: TestRunnerKind; files: string[]; } @@ -121,7 +129,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 +148,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 +185,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()); + runners.push(new ProjectRunner()); break; case "fourslash": - runners.push(new Harness.FourSlashRunner(FourSlash.FourSlashTestType.Native)); + runners.push(new FourSlashRunner(FourSlashTestType.Native)); break; case "fourslash-shims": - runners.push(new Harness.FourSlashRunner(FourSlash.FourSlashTestType.Shims)); + runners.push(new FourSlashRunner(FourSlashTestType.Shims)); break; case "fourslash-shims-pp": - runners.push(new Harness.FourSlashRunner(FourSlash.FourSlashTestType.ShimsWithPreprocess)); + runners.push(new FourSlashRunner(FourSlashTestType.ShimsWithPreprocess)); break; case "fourslash-server": - runners.push(new Harness.FourSlashRunner(FourSlash.FourSlashTestType.Server)); + runners.push(new FourSlashRunner(FourSlashTestType.Server)); break; case "fourslash-generated": - runners.push(new Harness.GeneratedFourslashRunner(FourSlash.FourSlashTestType.Native)); + runners.push(new GeneratedFourslashRunner(FourSlashTestType.Native)); break; case "rwc": - runners.push(new RWC.RWCRunner()); + runners.push(new 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 +231,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()); + runners.push(new 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(FourSlashTestType.Native)); + runners.push(new FourSlashRunner(FourSlashTestType.Shims)); + runners.push(new FourSlashRunner(FourSlashTestType.ShimsWithPreprocess)); + runners.push(new FourSlashRunner(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) { @@ -248,29 +256,29 @@ function handleTestConfig() { } function beginTests() { - ts.Debug.loggingHost = { + Debug.loggingHost = { log(_level, s) { console.log(s || ""); } }; - if (ts.Debug.isDebugging) { - ts.Debug.enableDebugInfo(); + if (Debug.isDebugging) { + Debug.enableDebugInfo(); } // run tests in en-US by default. let savedUILocale: string | undefined; beforeEach(() => { - savedUILocale = ts.getUILocale(); - ts.setUILocale("en-US"); + savedUILocale = getUILocale(); + setUILocale("en-US"); }); - afterEach(() => ts.setUILocale(savedUILocale)); + afterEach(() => setUILocale(savedUILocale)); runTests(runners); if (!runUnitTests) { // patch `describe` to skip unit tests - (global as any).describe = ts.noop; + (global as any).describe = noop; } } @@ -278,10 +286,10 @@ export let isWorker: boolean; function startTestEnvironment() { isWorker = handleTestConfig(); if (isWorker) { - return Harness.Parallel.Worker.start(); + return start(); } else if (taskConfigsFolder && workerCount && workerCount > 1) { - return Harness.Parallel.Host.start(); + return Host.start(); } beginTests(); } diff --git a/src/testRunner/rwcRunner.ts b/src/testRunner/rwcRunner.ts index d89f689e50c88..8d08130b5cfb1 100644 --- a/src/testRunner/rwcRunner.ts +++ b/src/testRunner/rwcRunner.ts @@ -1,38 +1,46 @@ -import * as compiler from "./_namespaces/compiler"; -import * as Harness from "./_namespaces/Harness"; -import * as Playback from "./_namespaces/Playback"; -import * as ts from "./_namespaces/ts"; -import * as vpath from "./_namespaces/vpath"; +import { + parseCommandLine, parseJsonSourceFileConfigFileContent, setConfigFileInOptions, +} from "../compiler/commandLineParser"; +import { extend, forEach } from "../compiler/core"; +import { Map } from "../compiler/corePublic"; +import { parseJsonText } from "../compiler/parser"; +import { getBaseFileName, getDirectoryPath, normalizeSlashes } from "../compiler/path"; +import { CompilerOptions, ParseConfigHost, ParsedCommandLine } from "../compiler/types"; +import { CompilationResult } from "../harness/compilerImpl"; +import { Baseline, Compiler, IO, isDefaultLibraryFile, setHarnessIO } from "../harness/harnessIO"; +import { RunnerBase, TestRunnerKind } from "../harness/runnerbase"; +import { isTsConfigFile } from "../harness/vpathUtil"; +import { IoLog, newStyleLogIntoOldStyleLog, wrapIO } from "../loggedIO/loggedIO"; // In harness baselines, null is different than undefined. See `generateActual` in `harness.ts`. -function runWithIOLog(ioLog: Playback.IoLog, fn: (oldIO: Harness.IO) => void) { - const oldIO = Harness.IO; +function runWithIOLog(ioLog: IoLog, fn: (oldIO: IO) => void) { + const oldIO = IO; - const wrappedIO = Playback.wrapIO(oldIO); + const wrappedIO = wrapIO(oldIO); wrappedIO.startReplayFromData(ioLog); - Harness.setHarnessIO(wrappedIO); + setHarnessIO(wrappedIO); try { fn(oldIO); } finally { wrappedIO.endReplay(); - Harness.setHarnessIO(oldIO); + setHarnessIO(oldIO); } } export function runRWCTest(jsonPath: string) { describe("Testing a rwc project: " + jsonPath, () => { - let inputFiles: Harness.Compiler.TestFile[] = []; - let otherFiles: Harness.Compiler.TestFile[] = []; - let tsconfigFiles: Harness.Compiler.TestFile[] = []; - let compilerResult: compiler.CompilationResult; - let compilerOptions: ts.CompilerOptions; - const baselineOpts: Harness.Baseline.BaselineOptions = { + let inputFiles: Compiler.TestFile[] = []; + let otherFiles: Compiler.TestFile[] = []; + let tsconfigFiles: Compiler.TestFile[] = []; + let compilerResult: CompilationResult; + let compilerOptions: CompilerOptions; + const baselineOpts: Baseline.BaselineOptions = { Subfolder: "rwc", Baselinefolder: "internal/baselines" }; - const baseName = ts.getBaseFileName(jsonPath); + const baseName = getBaseFileName(jsonPath); let currentDirectory: string; let useCustomLibraryFile: boolean; let caseSensitive: boolean; @@ -54,13 +62,13 @@ export function runRWCTest(jsonPath: string) { it("can compile", function (this: Mocha.Context) { this.timeout(800_000); // Allow long timeouts for RWC compilations - let opts!: ts.ParsedCommandLine; + let opts!: ParsedCommandLine; - const ioLog: Playback.IoLog = Playback.newStyleLogIntoOldStyleLog(JSON.parse(Harness.IO.readFile(`internal/cases/rwc/${jsonPath}/test.json`)!), Harness.IO, `internal/cases/rwc/${baseName}`); + const ioLog: IoLog = newStyleLogIntoOldStyleLog(JSON.parse(IO.readFile(`internal/cases/rwc/${jsonPath}/test.json`)!), IO, `internal/cases/rwc/${baseName}`); currentDirectory = ioLog.currentDirectory; useCustomLibraryFile = !!ioLog.useCustomLibraryFile; runWithIOLog(ioLog, () => { - opts = ts.parseCommandLine(ioLog.arguments, fileName => Harness.IO.readFile(fileName)); + opts = parseCommandLine(ioLog.arguments, fileName => IO.readFile(fileName)); assert.equal(opts.errors.length, 0); // To provide test coverage of output javascript file, @@ -70,28 +78,28 @@ export function runRWCTest(jsonPath: string) { let fileNames = opts.fileNames; runWithIOLog(ioLog, () => { - const tsconfigFile = ts.forEach(ioLog.filesRead, f => vpath.isTsConfigFile(f.path) ? f : undefined); + const tsconfigFile = forEach(ioLog.filesRead, f => isTsConfigFile(f.path) ? f : undefined); if (tsconfigFile) { const tsconfigFileContents = getHarnessCompilerInputUnit(tsconfigFile.path); tsconfigFiles.push({ unitName: tsconfigFile.path, content: tsconfigFileContents.content }); - const parsedTsconfigFileContents = ts.parseJsonText(tsconfigFile.path, tsconfigFileContents.content); - const configParseHost: ts.ParseConfigHost = { - useCaseSensitiveFileNames: Harness.IO.useCaseSensitiveFileNames(), - fileExists: Harness.IO.fileExists, - readDirectory: Harness.IO.readDirectory, - readFile: Harness.IO.readFile + const parsedTsconfigFileContents = parseJsonText(tsconfigFile.path, tsconfigFileContents.content); + const configParseHost: ParseConfigHost = { + useCaseSensitiveFileNames: IO.useCaseSensitiveFileNames(), + fileExists: IO.fileExists, + readDirectory: IO.readDirectory, + readFile: IO.readFile }; - const configParseResult = ts.parseJsonSourceFileConfigFileContent(parsedTsconfigFileContents, configParseHost, ts.getDirectoryPath(tsconfigFile.path)); + const configParseResult = parseJsonSourceFileConfigFileContent(parsedTsconfigFileContents, configParseHost, getDirectoryPath(tsconfigFile.path)); fileNames = configParseResult.fileNames; - opts.options = ts.extend(opts.options, configParseResult.options); - ts.setConfigFileInOptions(opts.options, configParseResult.options.configFile); + opts.options = extend(opts.options, configParseResult.options); + setConfigFileInOptions(opts.options, configParseResult.options.configFile); } // Deduplicate files so they are only printed once in baselines (they are deduplicated within the compiler already) - const uniqueNames = new ts.Map(); + const uniqueNames = new Map(); for (const fileName of fileNames) { // Must maintain order, build result list while checking map - const normalized = ts.normalizeSlashes(Harness.IO.resolvePath(fileName)!); + const normalized = normalizeSlashes(IO.resolvePath(fileName)!); if (!uniqueNames.has(normalized)) { uniqueNames.set(normalized, true); // Load the file @@ -101,12 +109,12 @@ export function runRWCTest(jsonPath: string) { // Add files to compilation for (const fileRead of ioLog.filesRead) { - const unitName = ts.normalizeSlashes(Harness.IO.resolvePath(fileRead.path)!); - if (!uniqueNames.has(unitName) && !Harness.isDefaultLibraryFile(fileRead.path)) { + const unitName = normalizeSlashes(IO.resolvePath(fileRead.path)!); + if (!uniqueNames.has(unitName) && !isDefaultLibraryFile(fileRead.path)) { uniqueNames.set(unitName, true); otherFiles.push(getHarnessCompilerInputUnit(fileRead.path)); } - else if (!opts.options.noLib && Harness.isDefaultLibraryFile(fileRead.path) && !uniqueNames.has(unitName) && useCustomLibraryFile) { + else if (!opts.options.noLib && isDefaultLibraryFile(fileRead.path) && !uniqueNames.has(unitName) && useCustomLibraryFile) { // If useCustomLibraryFile is true, we will use lib.d.ts from json object // otherwise use the lib.d.ts from built/local // Majority of RWC code will be using built/local/lib.d.ts instead of @@ -126,7 +134,7 @@ export function runRWCTest(jsonPath: string) { caseSensitive = ioLog.useCaseSensitiveFileNames || false; // Emit the results - compilerResult = Harness.Compiler.compileFiles( + compilerResult = Compiler.compileFiles( inputFiles, otherFiles, { useCaseSensitiveFileNames: "" + caseSensitive }, @@ -136,14 +144,14 @@ export function runRWCTest(jsonPath: string) { currentDirectory); compilerOptions = compilerResult.options; - function getHarnessCompilerInputUnit(fileName: string): Harness.Compiler.TestFile { - const unitName = ts.normalizeSlashes(Harness.IO.resolvePath(fileName)!); + function getHarnessCompilerInputUnit(fileName: string): Compiler.TestFile { + const unitName = normalizeSlashes(IO.resolvePath(fileName)!); let content: string; try { - content = Harness.IO.readFile(unitName)!; + content = IO.readFile(unitName)!; } catch (e) { - content = Harness.IO.readFile(fileName)!; + content = IO.readFile(fileName)!; } return { unitName, content }; } @@ -152,40 +160,40 @@ export function runRWCTest(jsonPath: string) { it("has the expected emitted code", function (this: Mocha.Context) { this.timeout(100_000); // Allow longer timeouts for RWC js verification - Harness.Baseline.runMultifileBaseline(baseName, "", () => { - return Harness.Compiler.iterateOutputs(compilerResult.js.values()); + Baseline.runMultifileBaseline(baseName, "", () => { + return Compiler.iterateOutputs(compilerResult.js.values()); }, baselineOpts, [".js", ".jsx"]); }); it("has the expected declaration file content", () => { - Harness.Baseline.runMultifileBaseline(baseName, "", () => { + Baseline.runMultifileBaseline(baseName, "", () => { if (!compilerResult.dts.size) { return null; // eslint-disable-line no-null/no-null } - return Harness.Compiler.iterateOutputs(compilerResult.dts.values()); + return Compiler.iterateOutputs(compilerResult.dts.values()); }, baselineOpts, [".d.ts"]); }); it("has the expected source maps", () => { - Harness.Baseline.runMultifileBaseline(baseName, "", () => { + Baseline.runMultifileBaseline(baseName, "", () => { if (!compilerResult.maps.size) { return null; // eslint-disable-line no-null/no-null } - return Harness.Compiler.iterateOutputs(compilerResult.maps.values()); + return Compiler.iterateOutputs(compilerResult.maps.values()); }, baselineOpts, [".map"]); }); it("has the expected errors", () => { - Harness.Baseline.runMultifileBaseline(baseName, ".errors.txt", () => { + Baseline.runMultifileBaseline(baseName, ".errors.txt", () => { if (compilerResult.diagnostics.length === 0) { return null; // eslint-disable-line no-null/no-null } // Do not include the library in the baselines to avoid noise - const baselineFiles = tsconfigFiles.concat(inputFiles, otherFiles).filter(f => !Harness.isDefaultLibraryFile(f.unitName)); - const errors = compilerResult.diagnostics.filter(e => !e.file || !Harness.isDefaultLibraryFile(e.file.fileName)); - return Harness.Compiler.iterateErrorBaseline(baselineFiles, errors, { caseSensitive, currentDirectory }); + const baselineFiles = tsconfigFiles.concat(inputFiles, otherFiles).filter(f => !isDefaultLibraryFile(f.unitName)); + const errors = compilerResult.diagnostics.filter(e => !e.file || !isDefaultLibraryFile(e.file.fileName)); + return Compiler.iterateErrorBaseline(baselineFiles, errors, { caseSensitive, currentDirectory }); }, baselineOpts); }); @@ -193,33 +201,33 @@ export function runRWCTest(jsonPath: string) { // declaration file errors as part of the baseline. it("has the expected errors in generated declaration files", () => { if (compilerOptions.declaration && !compilerResult.diagnostics.length) { - Harness.Baseline.runMultifileBaseline(baseName, ".dts.errors.txt", () => { + Baseline.runMultifileBaseline(baseName, ".dts.errors.txt", () => { if (compilerResult.diagnostics.length === 0) { return null; // eslint-disable-line no-null/no-null } - const declContext = Harness.Compiler.prepareDeclarationCompilationContext( + const declContext = Compiler.prepareDeclarationCompilationContext( inputFiles, otherFiles, compilerResult, /*harnessSettings*/ undefined!, compilerOptions, currentDirectory // TODO: GH#18217 ); // Reset compilerResult before calling into `compileDeclarationFiles` so the memory from the original compilation can be freed const links = compilerResult.symlinks; compilerResult = undefined!; - const declFileCompilationResult = Harness.Compiler.compileDeclarationFiles(declContext, links)!; + const declFileCompilationResult = Compiler.compileDeclarationFiles(declContext, links)!; - return Harness.Compiler.iterateErrorBaseline(tsconfigFiles.concat(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.diagnostics, { caseSensitive, currentDirectory }); + return Compiler.iterateErrorBaseline(tsconfigFiles.concat(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles), declFileCompilationResult.declResult.diagnostics, { caseSensitive, currentDirectory }); }, baselineOpts); } }); }); } -export class RWCRunner extends Harness.RunnerBase { +export class RWCRunner extends RunnerBase { public enumerateTestFiles() { // see also: `enumerateTestFiles` in tests/webTestServer.ts - return Harness.IO.getDirectories("internal/cases/rwc/"); + return IO.getDirectories("internal/cases/rwc/"); } - public kind(): Harness.TestRunnerKind { + public kind(): TestRunnerKind { return "rwc"; } diff --git a/src/testRunner/test262Runner.ts b/src/testRunner/test262Runner.ts index 96d99dac18515..58763fba002d6 100644 --- a/src/testRunner/test262Runner.ts +++ b/src/testRunner/test262Runner.ts @@ -1,23 +1,27 @@ -import * as compiler from "./_namespaces/compiler"; -import * as Harness from "./_namespaces/Harness"; -import * as ts from "./_namespaces/ts"; -import * as Utils from "./_namespaces/Utils"; +import { map } from "../compiler/core"; +import { normalizePath } from "../compiler/path"; +import { CompilerOptions, ModuleKind, ScriptTarget } from "../compiler/types"; +import { removeFileExtension } from "../compiler/utilities"; +import { CompilationResult } from "../harness/compilerImpl"; +import { Baseline, Compiler, IO, TestCaseParser } from "../harness/harnessIO"; +import { assertInvariants, sourceFileToJSON } from "../harness/harnessUtils"; +import { RunnerBase, TestRunnerKind } from "../harness/runnerbase"; // 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 = { + private static readonly options: CompilerOptions = { allowNonTsExtensions: true, - target: ts.ScriptTarget.Latest, - module: ts.ModuleKind.CommonJS + target: ScriptTarget.Latest, + module: ModuleKind.CommonJS }; - private static readonly baselineOptions: Harness.Baseline.BaselineOptions = { + private static readonly baselineOptions: Baseline.BaselineOptions = { Subfolder: "test262", Baselinefolder: "internal/baselines" }; @@ -32,16 +36,16 @@ export class Test262BaselineRunner extends Harness.RunnerBase { // Everything declared here should be cleared out in the "after" callback. let testState: { filename: string; - compilerResult: compiler.CompilationResult; - inputFiles: Harness.Compiler.TestFile[]; + compilerResult: CompilationResult; + inputFiles: Compiler.TestFile[]; }; before(() => { - const content = Harness.IO.readFile(filePath)!; - const testFilename = ts.removeFileExtension(filePath).replace(/\//g, "_") + ".test"; - const testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, testFilename); + const content = IO.readFile(filePath)!; + const testFilename = removeFileExtension(filePath).replace(/\//g, "_") + ".test"; + 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 +57,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,35 +71,35 @@ 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", () => { const sourceFile = testState.compilerResult.program!.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); - Utils.assertInvariants(sourceFile, /*parent:*/ undefined); + assertInvariants(sourceFile, /*parent:*/ undefined); }); 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", sourceFileToJSON(sourceFile), Test262BaselineRunner.baselineOptions); }); }); } - public kind(): Harness.TestRunnerKind { + public kind(): TestRunnerKind { return "test262"; } public enumerateTestFiles() { // see also: `enumerateTestFiles` in tests/webTestServer.ts - return ts.map(this.enumerateFiles(Test262BaselineRunner.basePath, Test262BaselineRunner.testFileExtensionRegex, { recursive: true }), ts.normalizePath); + return map(this.enumerateFiles(Test262BaselineRunner.basePath, Test262BaselineRunner.testFileExtensionRegex, { recursive: true }), normalizePath); } public initializeTests() { diff --git a/src/testRunner/unittests/asserts.ts b/src/testRunner/unittests/asserts.ts index 819ebdb4ce744..c33b8b3c0bcdd 100644 --- a/src/testRunner/unittests/asserts.ts +++ b/src/testRunner/unittests/asserts.ts @@ -1,13 +1,14 @@ -import * as ts from "../_namespaces/ts"; +import { Debug } from "../../compiler/debug"; +import { factory } from "../../compiler/factory/nodeFactory"; describe("unittests:: assert", () => { it("deepEqual", () => { - assert.throws(() => assert.deepEqual(ts.factory.createNodeArray([ts.factory.createIdentifier("A")]), ts.factory.createNodeArray([ts.factory.createIdentifier("B")]))); - assert.throws(() => assert.deepEqual(ts.factory.createNodeArray([], /*hasTrailingComma*/ true), ts.factory.createNodeArray([], /*hasTrailingComma*/ false))); - assert.deepEqual(ts.factory.createNodeArray([ts.factory.createIdentifier("A")], /*hasTrailingComma*/ true), ts.factory.createNodeArray([ts.factory.createIdentifier("A")], /*hasTrailingComma*/ true)); + assert.throws(() => assert.deepEqual(factory.createNodeArray([factory.createIdentifier("A")]), factory.createNodeArray([factory.createIdentifier("B")]))); + assert.throws(() => assert.deepEqual(factory.createNodeArray([], /*hasTrailingComma*/ true), factory.createNodeArray([], /*hasTrailingComma*/ false))); + assert.deepEqual(factory.createNodeArray([factory.createIdentifier("A")], /*hasTrailingComma*/ true), factory.createNodeArray([factory.createIdentifier("A")], /*hasTrailingComma*/ true)); }); it("assertNever on string has correct error", () => { - assert.throws(() => ts.Debug.assertNever("hi" as never), "Debug Failure. Illegal value: \"hi\""); + assert.throws(() => Debug.assertNever("hi" as never), "Debug Failure. Illegal value: \"hi\""); }); }); diff --git a/src/testRunner/unittests/base64.ts b/src/testRunner/unittests/base64.ts index 0f86be72f23c6..46f7c62540c07 100644 --- a/src/testRunner/unittests/base64.ts +++ b/src/testRunner/unittests/base64.ts @@ -1,4 +1,4 @@ -import * as ts from "../_namespaces/ts"; +import { base64decode, convertToBase64 } from "../../compiler/utilities"; describe("unittests:: base64", () => { describe("base64decode", () => { @@ -15,7 +15,7 @@ describe("unittests:: base64", () => { "", ]; for (const test of tests) { - assert.equal(ts.base64decode({}, ts.convertToBase64(test)), test); + assert.equal(base64decode({}, convertToBase64(test)), test); } }); }); diff --git a/src/testRunner/unittests/builder.ts b/src/testRunner/unittests/builder.ts index b4db834792100..901a15abe65aa 100644 --- a/src/testRunner/unittests/builder.ts +++ b/src/testRunner/unittests/builder.ts @@ -1,14 +1,21 @@ -import * as ts from "../_namespaces/ts"; +import { + BuilderProgramHost, createEmitAndSemanticDiagnosticsBuilderProgram, EmitAndSemanticDiagnosticsBuilderProgram, +} from "../../compiler/builderPublic"; +import { returnTrue } from "../../compiler/core"; +import { CancellationToken, OperationCanceledException, Program } from "../../compiler/types"; +import { + NamedSourceText, newProgram, ProgramWithSourceTexts, SourceText, updateProgram, updateProgramText, +} from "./reuseProgramStructure"; describe("unittests:: builder", () => { it("emits dependent files", () => { - const files: ts.NamedSourceText[] = [ - { name: "/a.ts", text: ts.SourceText.New("", 'import { b } from "./b";', "") }, - { name: "/b.ts", text: ts.SourceText.New("", ' import { c } from "./c";', "export const b = c;") }, - { name: "/c.ts", text: ts.SourceText.New("", "", "export const c = 0;") }, + const files: NamedSourceText[] = [ + { name: "/a.ts", text: SourceText.New("", 'import { b } from "./b";', "") }, + { name: "/b.ts", text: SourceText.New("", ' import { c } from "./c";', "export const b = c;") }, + { name: "/c.ts", text: SourceText.New("", "", "export const c = 0;") }, ]; - let program = ts.newProgram(files, ["/a.ts"], {}); + let program = newProgram(files, ["/a.ts"], {}); const assertChanges = makeAssertChanges(() => program); assertChanges(["/c.js", "/b.js", "/a.js"]); @@ -24,12 +31,12 @@ describe("unittests:: builder", () => { }); it("if emitting all files, emits the changed file first", () => { - const files: ts.NamedSourceText[] = [ - { name: "/a.ts", text: ts.SourceText.New("", "", "namespace A { export const x = 0; }") }, - { name: "/b.ts", text: ts.SourceText.New("", "", "namespace B { export const x = 0; }") }, + const files: NamedSourceText[] = [ + { name: "/a.ts", text: SourceText.New("", "", "namespace A { export const x = 0; }") }, + { name: "/b.ts", text: SourceText.New("", "", "namespace B { export const x = 0; }") }, ]; - let program = ts.newProgram(files, ["/a.ts", "/b.ts"], {}); + let program = newProgram(files, ["/a.ts", "/b.ts"], {}); const assertChanges = makeAssertChanges(() => program); assertChanges(["/a.js", "/b.js"]); @@ -42,15 +49,15 @@ describe("unittests:: builder", () => { }); it("keeps the file in affected files if cancellation token throws during the operation", () => { - const files: ts.NamedSourceText[] = [ - { name: "/a.ts", text: ts.SourceText.New("", 'import { b } from "./b";', "") }, - { name: "/b.ts", text: ts.SourceText.New("", ' import { c } from "./c";', "export const b = c;") }, - { name: "/c.ts", text: ts.SourceText.New("", "", "export const c = 0;") }, - { name: "/d.ts", text: ts.SourceText.New("", "", "export const dd = 0;") }, - { name: "/e.ts", text: ts.SourceText.New("", "", "export const ee = 0;") }, + const files: NamedSourceText[] = [ + { name: "/a.ts", text: SourceText.New("", 'import { b } from "./b";', "") }, + { name: "/b.ts", text: SourceText.New("", ' import { c } from "./c";', "export const b = c;") }, + { name: "/c.ts", text: SourceText.New("", "", "export const c = 0;") }, + { name: "/d.ts", text: SourceText.New("", "", "export const dd = 0;") }, + { name: "/e.ts", text: SourceText.New("", "", "export const ee = 0;") }, ]; - let program = ts.newProgram(files, ["/d.ts", "/e.ts", "/a.ts"], {}); + let program = newProgram(files, ["/d.ts", "/e.ts", "/a.ts"], {}); const assertChanges = makeAssertChangesWithCancellationToken(() => program); // No cancellation assertChanges(["/d.js", "/e.js", "/c.js", "/b.js", "/a.js"]); @@ -72,12 +79,12 @@ describe("unittests:: builder", () => { }); }); -function makeAssertChanges(getProgram: () => ts.Program): (fileNames: readonly string[]) => void { - const host: ts.BuilderProgramHost = { useCaseSensitiveFileNames: ts.returnTrue }; - let builderProgram: ts.EmitAndSemanticDiagnosticsBuilderProgram | undefined; +function makeAssertChanges(getProgram: () => Program): (fileNames: readonly string[]) => void { + const host: BuilderProgramHost = { useCaseSensitiveFileNames: returnTrue }; + let builderProgram: EmitAndSemanticDiagnosticsBuilderProgram | undefined; return fileNames => { const program = getProgram(); - builderProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram(program, host, builderProgram); + builderProgram = createEmitAndSemanticDiagnosticsBuilderProgram(program, host, builderProgram); const outputFileNames: string[] = []; // eslint-disable-next-line no-empty while (builderProgram.emitNextAffectedFile(fileName => outputFileNames.push(fileName))) { @@ -86,15 +93,15 @@ function makeAssertChanges(getProgram: () => ts.Program): (fileNames: readonly s }; } -function makeAssertChangesWithCancellationToken(getProgram: () => ts.Program): (fileNames: readonly string[], cancelAfterEmitLength?: number) => void { - const host: ts.BuilderProgramHost = { useCaseSensitiveFileNames: ts.returnTrue }; - let builderProgram: ts.EmitAndSemanticDiagnosticsBuilderProgram | undefined; +function makeAssertChangesWithCancellationToken(getProgram: () => Program): (fileNames: readonly string[], cancelAfterEmitLength?: number) => void { + const host: BuilderProgramHost = { useCaseSensitiveFileNames: returnTrue }; + let builderProgram: EmitAndSemanticDiagnosticsBuilderProgram | undefined; let cancel = false; - const cancellationToken: ts.CancellationToken = { + const cancellationToken: CancellationToken = { isCancellationRequested: () => cancel, throwIfCancellationRequested: () => { if (cancel) { - throw new ts.OperationCanceledException(); + throw new OperationCanceledException(); } }, }; @@ -102,7 +109,7 @@ function makeAssertChangesWithCancellationToken(getProgram: () => ts.Program): ( cancel = false; let operationWasCancelled = false; const program = getProgram(); - builderProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram(program, host, builderProgram); + builderProgram = createEmitAndSemanticDiagnosticsBuilderProgram(program, host, builderProgram); const outputFileNames: string[] = []; try { do { @@ -114,7 +121,7 @@ function makeAssertChangesWithCancellationToken(getProgram: () => ts.Program): ( } catch (e) { assert.isFalse(operationWasCancelled); - assert(e instanceof ts.OperationCanceledException, e.toString()); + assert(e instanceof OperationCanceledException, e.toString()); operationWasCancelled = true; } assert.equal(cancel, operationWasCancelled); @@ -123,9 +130,9 @@ function makeAssertChangesWithCancellationToken(getProgram: () => ts.Program): ( }; } -function updateProgramFile(program: ts.ProgramWithSourceTexts, fileName: string, fileContent: string): ts.ProgramWithSourceTexts { - return ts.updateProgram(program, program.getRootFileNames(), program.getCompilerOptions(), files => { - ts.updateProgramText(files, fileName, fileContent); +function updateProgramFile(program: ProgramWithSourceTexts, fileName: string, fileContent: string): ProgramWithSourceTexts { + return updateProgram(program, program.getRootFileNames(), program.getCompilerOptions(), files => { + updateProgramText(files, fileName, fileContent); }); } diff --git a/src/testRunner/unittests/comments.ts b/src/testRunner/unittests/comments.ts index d37e1e899313d..ef1e9789a4430 100644 --- a/src/testRunner/unittests/comments.ts +++ b/src/testRunner/unittests/comments.ts @@ -1,4 +1,5 @@ -import * as ts from "../_namespaces/ts"; +import { getLeadingCommentRanges } from "../../compiler/scanner"; +import { SyntaxKind } from "../../compiler/types"; describe("comment parsing", () => { const withShebang = `#! node @@ -12,22 +13,22 @@ describe("comment parsing", () => { // another one `; it("skips shebang", () => { - const result = ts.getLeadingCommentRanges(withShebang, 0); + const result = getLeadingCommentRanges(withShebang, 0); assert.isDefined(result); assert.strictEqual(result!.length, 2); }); it("treats all comments at start of file as leading comments", () => { - const result = ts.getLeadingCommentRanges(noShebang, 0); + const result = getLeadingCommentRanges(noShebang, 0); assert.isDefined(result); assert.strictEqual(result!.length, 2); }); it("returns leading comments if position is not 0", () => { - const result = ts.getLeadingCommentRanges(withTrailing, 1); + const result = getLeadingCommentRanges(withTrailing, 1); assert.isDefined(result); assert.strictEqual(result!.length, 1); - assert.strictEqual(result![0].kind, ts.SyntaxKind.SingleLineCommentTrivia); + assert.strictEqual(result![0].kind, SyntaxKind.SingleLineCommentTrivia); }); }); diff --git a/src/testRunner/unittests/compilerCore.ts b/src/testRunner/unittests/compilerCore.ts index ed697ddb55274..12a9cf486e610 100644 --- a/src/testRunner/unittests/compilerCore.ts +++ b/src/testRunner/unittests/compilerCore.ts @@ -1,38 +1,38 @@ -import * as ts from "../_namespaces/ts"; +import { arrayFrom, createSet, equalOwnProperties } from "../../compiler/core"; describe("unittests:: compilerCore", () => { describe("equalOwnProperties", () => { it("correctly equates objects", () => { - assert.isTrue(ts.equalOwnProperties({}, {})); - assert.isTrue(ts.equalOwnProperties({ a: 1 }, { a: 1 })); - assert.isTrue(ts.equalOwnProperties({ a: 1, b: 2 }, { b: 2, a: 1 })); + assert.isTrue(equalOwnProperties({}, {})); + assert.isTrue(equalOwnProperties({ a: 1 }, { a: 1 })); + assert.isTrue(equalOwnProperties({ a: 1, b: 2 }, { b: 2, a: 1 })); }); it("correctly identifies unmatched objects", () => { - assert.isFalse(ts.equalOwnProperties({}, { a: 1 }), "missing left property"); - assert.isFalse(ts.equalOwnProperties({ a: 1 }, {}), "missing right property"); - assert.isFalse(ts.equalOwnProperties({ a: 1 }, { a: 2 }), "differing property"); + assert.isFalse(equalOwnProperties({}, { a: 1 }), "missing left property"); + assert.isFalse(equalOwnProperties({ a: 1 }, {}), "missing right property"); + assert.isFalse(equalOwnProperties({ a: 1 }, { a: 2 }), "differing property"); }); it("correctly identifies undefined vs hasOwnProperty", () => { - assert.isFalse(ts.equalOwnProperties({}, { a: undefined }), "missing left property"); - assert.isFalse(ts.equalOwnProperties({ a: undefined }, {}), "missing right property"); + assert.isFalse(equalOwnProperties({}, { a: undefined }), "missing left property"); + assert.isFalse(equalOwnProperties({ a: undefined }, {}), "missing right property"); }); it("truthiness", () => { const trythyTest = (l: any, r: any) => !!l === !!r; - assert.isFalse(ts.equalOwnProperties({}, { a: 1 }, trythyTest), "missing left truthy property"); - assert.isFalse(ts.equalOwnProperties({}, { a: 0 }, trythyTest), "missing left falsey property"); - assert.isFalse(ts.equalOwnProperties({ a: 1 }, {}, trythyTest), "missing right truthy property"); - assert.isFalse(ts.equalOwnProperties({ a: 0 }, {}, trythyTest), "missing right falsey property"); - assert.isTrue(ts.equalOwnProperties({ a: 1 }, { a: "foo" }, trythyTest), "valid equality"); + assert.isFalse(equalOwnProperties({}, { a: 1 }, trythyTest), "missing left truthy property"); + assert.isFalse(equalOwnProperties({}, { a: 0 }, trythyTest), "missing left falsey property"); + assert.isFalse(equalOwnProperties({ a: 1 }, {}, trythyTest), "missing right truthy property"); + assert.isFalse(equalOwnProperties({ a: 0 }, {}, trythyTest), "missing right falsey property"); + assert.isTrue(equalOwnProperties({ a: 1 }, { a: "foo" }, trythyTest), "valid equality"); }); it("all equal", () => { - assert.isFalse(ts.equalOwnProperties({}, { a: 1 }, () => true), "missing left property"); - assert.isFalse(ts.equalOwnProperties({ a: 1 }, {}, () => true), "missing right property"); - assert.isTrue(ts.equalOwnProperties({ a: 1 }, { a: 2 }, () => true), "valid equality"); + assert.isFalse(equalOwnProperties({}, { a: 1 }, () => true), "missing left property"); + assert.isFalse(equalOwnProperties({ a: 1 }, {}, () => true), "missing right property"); + assert.isTrue(equalOwnProperties({ a: 1 }, { a: 2 }, () => true), "valid equality"); }); }); describe("customSet", () => { it("mutation", () => { - const set = ts.createSet(x => x % 2, (x, y) => (x % 4) === (y % 4)); + const set = createSet(x => x % 2, (x, y) => (x % 4) === (y % 4)); assert.equal(set.size, 0); const newSet = set.add(0); @@ -72,7 +72,7 @@ describe("unittests:: compilerCore", () => { assert.equal(set.size, 0); }); it("resizing", () => { - const set = ts.createSet(x => x % 2, (x, y) => x === y); + const set = createSet(x => x % 2, (x, y) => x === y); const elementCount = 100; for (let i = 0; i < elementCount; i++) { @@ -90,7 +90,7 @@ describe("unittests:: compilerCore", () => { } }); it("clear", () => { - const set = ts.createSet(x => x % 2, (x, y) => (x % 4) === (y % 4)); + const set = createSet(x => x % 2, (x, y) => (x % 4) === (y % 4)); for (let j = 0; j < 2; j++) { for (let i = 0; i < 100; i++) { set.add(i); @@ -103,7 +103,7 @@ describe("unittests:: compilerCore", () => { } }); it("forEach", () => { - const set = ts.createSet(x => x % 2, (x, y) => (x % 4) === (y % 4)); + const set = createSet(x => x % 2, (x, y) => (x % 4) === (y % 4)); for (let i = 0; i < 100; i++) { set.add(i); } @@ -126,7 +126,7 @@ describe("unittests:: compilerCore", () => { assert.deepEqual(keys, expected); }); it("iteration", () => { - const set = ts.createSet(x => x % 2, (x, y) => (x % 4) === (y % 4)); + const set = createSet(x => x % 2, (x, y) => (x % 4) === (y % 4)); for (let i = 0; i < 4; i++) { set.add(i); } @@ -134,15 +134,15 @@ describe("unittests:: compilerCore", () => { const expected = [0, 1, 2, 3]; let actual: number[]; - actual = ts.arrayFrom(set.keys()); + actual = arrayFrom(set.keys()); actual.sort(); assert.deepEqual(actual, expected); - actual = ts.arrayFrom(set.values()); + actual = arrayFrom(set.values()); actual.sort(); assert.deepEqual(actual, expected); - const actualTuple = ts.arrayFrom(set.entries()); + const actualTuple = arrayFrom(set.entries()); assert.isFalse(actualTuple.some(([v, k]) => v !== k)); actual = actualTuple.map(([v, _]) => v); actual.sort(); @@ -154,7 +154,7 @@ describe("unittests:: compilerCore", () => { y: string; } - const set = ts.createSet(t => t.y, (t, u) => t.x === u.x && t.y === u.y); + const set = createSet(t => t.y, (t, u) => t.x === u.x && t.y === u.y); const thing1: Thing = { x: 1, diff --git a/src/testRunner/unittests/config/commandLineParsing.ts b/src/testRunner/unittests/config/commandLineParsing.ts index 5da4fb5116a88..147a4dbe20a49 100644 --- a/src/testRunner/unittests/config/commandLineParsing.ts +++ b/src/testRunner/unittests/config/commandLineParsing.ts @@ -1,9 +1,21 @@ -import * as ts from "../../_namespaces/ts"; +import { + compilerOptionsDidYouMeanDiagnostics, createOptionNameMap, parseBuildCommand, parseCommandLineWorker, + ParseCommandLineWorkerDiagnostics, ParsedBuildCommand, +} from "../../../compiler/commandLineParser"; +import { getEntries } from "../../../compiler/core"; +import { ESMap, Map } from "../../../compiler/corePublic"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { BuildOptions } from "../../../compiler/tsbuildPublic"; +import { + CommandLineOption, DiagnosticMessage, ModuleKind, ModuleResolutionKind, ParsedCommandLine, PollingWatchKind, + ScriptTarget, WatchDirectoryKind, WatchFileKind, +} from "../../../compiler/types"; +import { formatStringFromArgs } from "../../../compiler/utilities"; describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { - function assertParseResult(commandLine: string[], expectedParsedCommandLine: ts.ParsedCommandLine, workerDiagnostic?: () => ts.ParseCommandLineWorkerDiagnostics) { - const parsed = ts.parseCommandLineWorker(workerDiagnostic?.() || ts.compilerOptionsDidYouMeanDiagnostics, commandLine); + function assertParseResult(commandLine: string[], expectedParsedCommandLine: ParsedCommandLine, workerDiagnostic?: () => ParseCommandLineWorkerDiagnostics) { + const parsed = parseCommandLineWorker(workerDiagnostic?.() || compilerOptionsDidYouMeanDiagnostics, commandLine); assert.deepEqual(parsed.options, expectedParsedCommandLine.options); assert.deepEqual(parsed.watchOptions, expectedParsedCommandLine.watchOptions); @@ -53,8 +65,8 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { assertParseResult(buildFlags, { errors: buildFlags.map(buildFlag => ({ messageText: `Compiler option '${buildFlag}' may only be used with '--build'.`, - category: ts.Diagnostics.Compiler_option_0_may_only_be_used_with_build.category, - code: ts.Diagnostics.Compiler_option_0_may_only_be_used_with_build.code, + category: Diagnostics.Compiler_option_0_may_only_be_used_with_build.category, + code: Diagnostics.Compiler_option_0_may_only_be_used_with_build.code, file: undefined, start: undefined, length: undefined @@ -70,16 +82,16 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { errors: [ { messageText: "Unknown compiler option '--declarations'. Did you mean 'declaration'?", - category: ts.Diagnostics.Unknown_compiler_option_0_Did_you_mean_1.category, - code: ts.Diagnostics.Unknown_compiler_option_0_Did_you_mean_1.code, + category: Diagnostics.Unknown_compiler_option_0_Did_you_mean_1.category, + code: Diagnostics.Unknown_compiler_option_0_Did_you_mean_1.code, file: undefined, start: undefined, length: undefined }, { messageText: "Unknown compiler option '--allowTS'. Did you mean 'allowJs'?", - category: ts.Diagnostics.Unknown_compiler_option_0_Did_you_mean_1.category, - code: ts.Diagnostics.Unknown_compiler_option_0_Did_you_mean_1.code, + category: Diagnostics.Unknown_compiler_option_0_Did_you_mean_1.category, + code: Diagnostics.Unknown_compiler_option_0_Did_you_mean_1.code, file: undefined, start: undefined, length: undefined @@ -109,8 +121,8 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { { errors: [{ messageText: "Argument for '--lib' option must be: 'es5', 'es6' [...]", - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, file: undefined, start: undefined, length: undefined, @@ -127,16 +139,16 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { { errors: [{ messageText: "Compiler option 'jsx' expects an argument.", - category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category, - code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code, + category: Diagnostics.Compiler_option_0_expects_an_argument.category, + code: Diagnostics.Compiler_option_0_expects_an_argument.code, file: undefined, start: undefined, length: undefined, }, { messageText: "Argument for '--jsx' option must be: 'preserve', 'react-native', 'react', 'react-jsx', 'react-jsxdev'.", - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, file: undefined, start: undefined, @@ -153,16 +165,16 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { { errors: [{ messageText: "Compiler option 'module' expects an argument.", - category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category, - code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code, + category: Diagnostics.Compiler_option_0_expects_an_argument.category, + code: Diagnostics.Compiler_option_0_expects_an_argument.code, file: undefined, start: undefined, length: undefined, }, { messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015', 'es2020', 'es2022', 'esnext', 'node16', 'nodenext'.", - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, file: undefined, start: undefined, @@ -179,16 +191,16 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { { errors: [{ messageText: "Compiler option 'newLine' expects an argument.", - category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category, - code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code, + category: Diagnostics.Compiler_option_0_expects_an_argument.category, + code: Diagnostics.Compiler_option_0_expects_an_argument.code, file: undefined, start: undefined, length: undefined, }, { messageText: "Argument for '--newLine' option must be: 'crlf', 'lf'.", - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, file: undefined, start: undefined, @@ -205,16 +217,16 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { { errors: [{ messageText: "Compiler option 'target' expects an argument.", - category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category, - code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code, + category: Diagnostics.Compiler_option_0_expects_an_argument.category, + code: Diagnostics.Compiler_option_0_expects_an_argument.code, file: undefined, start: undefined, length: undefined, }, { messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'es2021', 'es2022', 'esnext'.", - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, file: undefined, start: undefined, @@ -231,16 +243,16 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { { errors: [{ messageText: "Compiler option 'moduleResolution' expects an argument.", - category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category, - code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code, + category: Diagnostics.Compiler_option_0_expects_an_argument.category, + code: Diagnostics.Compiler_option_0_expects_an_argument.code, file: undefined, start: undefined, length: undefined, }, { messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic', 'node16', 'nodenext'.", - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, file: undefined, start: undefined, @@ -257,8 +269,8 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { { errors: [{ messageText: "Compiler option 'lib' expects an argument.", - category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category, - code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code, + category: Diagnostics.Compiler_option_0_expects_an_argument.category, + code: Diagnostics.Compiler_option_0_expects_an_argument.code, file: undefined, start: undefined, @@ -278,8 +290,8 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { { errors: [{ messageText: "Compiler option 'lib' expects an argument.", - category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category, - code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code, + category: Diagnostics.Compiler_option_0_expects_an_argument.category, + code: Diagnostics.Compiler_option_0_expects_an_argument.code, file: undefined, start: undefined, @@ -311,8 +323,8 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { { errors: [{ messageText: "Argument for '--lib' option must be: 'es5', 'es6' [...].", - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, file: undefined, start: undefined, length: undefined, @@ -330,8 +342,8 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { { errors: [{ messageText: "Argument for '--lib' option must be: 'es5', 'es6', [...]", - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, file: undefined, start: undefined, length: undefined, @@ -351,7 +363,7 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { fileNames: ["0.ts"], options: { lib: ["lib.es5.d.ts", "lib.es2015.symbol.wellknown.d.ts"], - target: ts.ScriptTarget.ES5, + target: ScriptTarget.ES5, } }); }); @@ -363,8 +375,8 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { errors: [], fileNames: ["0.ts"], options: { - module: ts.ModuleKind.CommonJS, - target: ts.ScriptTarget.ES5, + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, lib: ["lib.es5.d.ts", "lib.es2015.symbol.wellknown.d.ts"], } }); @@ -377,8 +389,8 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { errors: [], fileNames: ["0.ts"], options: { - module: ts.ModuleKind.CommonJS, - target: ts.ScriptTarget.ES5, + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, lib: ["lib.es2015.core.d.ts", "lib.es2015.symbol.wellknown.d.ts"], } }); @@ -441,8 +453,8 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { interface VerifyNull { optionName: string; nonNullValue?: string; - workerDiagnostic?: () => ts.ParseCommandLineWorkerDiagnostics; - diagnosticMessage: ts.DiagnosticMessage; + workerDiagnostic?: () => ParseCommandLineWorkerDiagnostics; + diagnosticMessage: DiagnosticMessage; } function verifyNull({ optionName, nonNullValue, workerDiagnostic, diagnosticMessage }: VerifyNull) { it("allows setting it to null", () => { @@ -463,7 +475,7 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { [`--${optionName}`, nonNullValue, "0.ts"], { errors: [{ - messageText: ts.formatStringFromArgs(diagnosticMessage.message, [optionName]), + messageText: formatStringFromArgs(diagnosticMessage.message, [optionName]), category: diagnosticMessage.category, code: diagnosticMessage.code, file: undefined, @@ -483,7 +495,7 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { ["0.ts", "--strictNullChecks", `--${optionName}`], { errors: [{ - messageText: ts.formatStringFromArgs(diagnosticMessage.message, [optionName]), + messageText: formatStringFromArgs(diagnosticMessage.message, [optionName]), category: diagnosticMessage.category, code: diagnosticMessage.code, file: undefined, @@ -502,7 +514,7 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { ["0.ts", `--${optionName}`], { errors: [{ - messageText: ts.formatStringFromArgs(diagnosticMessage.message, [optionName]), + messageText: formatStringFromArgs(diagnosticMessage.message, [optionName]), category: diagnosticMessage.category, code: diagnosticMessage.code, file: undefined, @@ -518,30 +530,30 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { } interface VerifyNullNonIncludedOption { - type: () => "string" | "number" | ts.ESMap; + type: () => "string" | "number" | ESMap; nonNullValue?: string; } function verifyNullNonIncludedOption({ type, nonNullValue }: VerifyNullNonIncludedOption) { verifyNull({ optionName: "optionName", nonNullValue, - diagnosticMessage: ts.Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_null_on_command_line, + diagnosticMessage: Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_null_on_command_line, workerDiagnostic: () => { - const optionDeclarations: ts.CommandLineOption[] = [ - ...ts.compilerOptionsDidYouMeanDiagnostics.optionDeclarations, + const optionDeclarations: CommandLineOption[] = [ + ...compilerOptionsDidYouMeanDiagnostics.optionDeclarations, { name: "optionName", type: type(), isTSConfigOnly: true, - category: ts.Diagnostics.Backwards_Compatibility, - description: ts.Diagnostics.Enable_project_compilation, + category: Diagnostics.Backwards_Compatibility, + description: Diagnostics.Enable_project_compilation, defaultValueDescription: undefined, } ]; return { - ...ts.compilerOptionsDidYouMeanDiagnostics, + ...compilerOptionsDidYouMeanDiagnostics, optionDeclarations, - getOptionsNameMap: () => ts.createOptionNameMap(optionDeclarations) + getOptionsNameMap: () => createOptionNameMap(optionDeclarations) }; } }); @@ -562,14 +574,14 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { verifyNull({ optionName: "composite", nonNullValue: "true", - diagnosticMessage: ts.Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_false_or_null_on_command_line + diagnosticMessage: Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_false_or_null_on_command_line }); }); describe("option of type object", () => { verifyNull({ optionName: "paths", - diagnosticMessage: ts.Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_null_on_command_line + diagnosticMessage: Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_null_on_command_line }); }); @@ -577,7 +589,7 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { verifyNull({ optionName: "rootDirs", nonNullValue: "abc,xyz", - diagnosticMessage: ts.Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_null_on_command_line + diagnosticMessage: Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_null_on_command_line }); }); @@ -597,9 +609,9 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { describe("option of type Map", () => { verifyNullNonIncludedOption({ - type: () => new ts.Map(ts.getEntries({ - node: ts.ModuleResolutionKind.NodeJs, - classic: ts.ModuleResolutionKind.Classic, + type: () => new Map(getEntries({ + node: ModuleResolutionKind.NodeJs, + classic: ModuleResolutionKind.Classic, })), nonNullValue: "node" }); @@ -622,7 +634,7 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { errors: [], fileNames: ["0.ts"], options: {}, - watchOptions: { watchFile: ts.WatchFileKind.UseFsEvents } + watchOptions: { watchFile: WatchFileKind.UseFsEvents } }); }); @@ -632,7 +644,7 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { errors: [], fileNames: ["0.ts"], options: {}, - watchOptions: { watchDirectory: ts.WatchDirectoryKind.FixedPollingInterval } + watchOptions: { watchDirectory: WatchDirectoryKind.FixedPollingInterval } }); }); @@ -642,7 +654,7 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { errors: [], fileNames: ["0.ts"], options: {}, - watchOptions: { fallbackPolling: ts.PollingWatchKind.PriorityInterval } + watchOptions: { fallbackPolling: PollingWatchKind.PriorityInterval } }); }); @@ -662,16 +674,16 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { errors: [ { messageText: "Watch option 'fallbackPolling' requires a value of type string.", - category: ts.Diagnostics.Watch_option_0_requires_a_value_of_type_1.category, - code: ts.Diagnostics.Watch_option_0_requires_a_value_of_type_1.code, + category: Diagnostics.Watch_option_0_requires_a_value_of_type_1.category, + code: Diagnostics.Watch_option_0_requires_a_value_of_type_1.code, file: undefined, start: undefined, length: undefined }, { messageText: "Argument for '--fallbackPolling' option must be: 'fixedinterval', 'priorityinterval', 'dynamicpriority', 'fixedchunksize'.", - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, file: undefined, start: undefined, length: undefined @@ -699,8 +711,8 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { errors: [ { messageText: `File specification cannot contain a parent directory ('..') that appears after a recursive directory wildcard ('**'): '**/../*'.`, - category: ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.category, - code: ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.code, + category: Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.category, + code: Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.code, file: undefined, start: undefined, length: undefined @@ -728,8 +740,8 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { errors: [ { messageText: `File specification cannot contain a parent directory ('..') that appears after a recursive directory wildcard ('**'): '**/../*'.`, - category: ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.category, - code: ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.code, + category: Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.category, + code: Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.code, file: undefined, start: undefined, length: undefined @@ -744,8 +756,8 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { }); describe("unittests:: config:: commandLineParsing:: parseBuildOptions", () => { - function assertParseResult(commandLine: string[], expectedParsedBuildCommand: ts.ParsedBuildCommand) { - const parsed = ts.parseBuildCommand(commandLine); + function assertParseResult(commandLine: string[], expectedParsedBuildCommand: ParsedBuildCommand) { + const parsed = parseBuildCommand(commandLine); assert.deepEqual(parsed.buildOptions, expectedParsedBuildCommand.buildOptions); assert.deepEqual(parsed.watchOptions, expectedParsedBuildCommand.watchOptions); @@ -792,8 +804,8 @@ describe("unittests:: config:: commandLineParsing:: parseBuildOptions", () => { { errors: [{ messageText: "Unknown build option '--invalidOption'.", - category: ts.Diagnostics.Unknown_build_option_0.category, - code: ts.Diagnostics.Unknown_build_option_0.code, + category: Diagnostics.Unknown_build_option_0.category, + code: Diagnostics.Unknown_build_option_0.code, file: undefined, start: undefined, length: undefined, @@ -810,8 +822,8 @@ describe("unittests:: config:: commandLineParsing:: parseBuildOptions", () => { { errors: [{ messageText: "Compiler option '--listFilesOnly' may not be used with '--build'.", - category: ts.Diagnostics.Compiler_option_0_may_not_be_used_with_build.category, - code: ts.Diagnostics.Compiler_option_0_may_not_be_used_with_build.code, + category: Diagnostics.Compiler_option_0_may_not_be_used_with_build.category, + code: Diagnostics.Compiler_option_0_may_not_be_used_with_build.code, file: undefined, start: undefined, length: undefined, @@ -883,8 +895,8 @@ describe("unittests:: config:: commandLineParsing:: parseBuildOptions", () => { { errors: [{ messageText: "Compiler option '--tsBuildInfoFile' may not be used with '--build'.", - category: ts.Diagnostics.Compiler_option_0_may_not_be_used_with_build.category, - code: ts.Diagnostics.Compiler_option_0_may_not_be_used_with_build.code, + category: Diagnostics.Compiler_option_0_may_not_be_used_with_build.category, + code: Diagnostics.Compiler_option_0_may_not_be_used_with_build.code, file: undefined, start: undefined, length: undefined @@ -901,8 +913,8 @@ describe("unittests:: config:: commandLineParsing:: parseBuildOptions", () => { assertParseResult(buildFlags, { errors: buildFlags.map(buildFlag => ({ messageText: `Compiler option '${buildFlag}' may not be used with '--build'.`, - category: ts.Diagnostics.Compiler_option_0_may_not_be_used_with_build.category, - code: ts.Diagnostics.Compiler_option_0_may_not_be_used_with_build.code, + category: Diagnostics.Compiler_option_0_may_not_be_used_with_build.category, + code: Diagnostics.Compiler_option_0_may_not_be_used_with_build.code, file: undefined, start: undefined, length: undefined @@ -914,15 +926,15 @@ describe("unittests:: config:: commandLineParsing:: parseBuildOptions", () => { }); describe("Combining options that make no sense together", () => { - function verifyInvalidCombination(flag1: keyof ts.BuildOptions, flag2: keyof ts.BuildOptions) { + function verifyInvalidCombination(flag1: keyof BuildOptions, flag2: keyof BuildOptions) { it(`--${flag1} and --${flag2} together is invalid`, () => { // --module commonjs --target es5 0.ts --lib es5,es2015.symbol.wellknown assertParseResult([`--${flag1}`, `--${flag2}`], { errors: [{ messageText: `Options '${flag1}' and '${flag2}' cannot be combined.`, - category: ts.Diagnostics.Options_0_and_1_cannot_be_combined.category, - code: ts.Diagnostics.Options_0_and_1_cannot_be_combined.code, + category: Diagnostics.Options_0_and_1_cannot_be_combined.category, + code: Diagnostics.Options_0_and_1_cannot_be_combined.code, file: undefined, start: undefined, length: undefined, @@ -947,7 +959,7 @@ describe("unittests:: config:: commandLineParsing:: parseBuildOptions", () => { errors: [], projects: ["."], buildOptions: { verbose: true }, - watchOptions: { watchFile: ts.WatchFileKind.UseFsEvents } + watchOptions: { watchFile: WatchFileKind.UseFsEvents } }); }); @@ -957,7 +969,7 @@ describe("unittests:: config:: commandLineParsing:: parseBuildOptions", () => { errors: [], projects: ["."], buildOptions: { verbose: true }, - watchOptions: { watchDirectory: ts.WatchDirectoryKind.FixedPollingInterval } + watchOptions: { watchDirectory: WatchDirectoryKind.FixedPollingInterval } }); }); @@ -967,7 +979,7 @@ describe("unittests:: config:: commandLineParsing:: parseBuildOptions", () => { errors: [], projects: ["."], buildOptions: { verbose: true }, - watchOptions: { fallbackPolling: ts.PollingWatchKind.PriorityInterval } + watchOptions: { fallbackPolling: PollingWatchKind.PriorityInterval } }); }); @@ -987,16 +999,16 @@ describe("unittests:: config:: commandLineParsing:: parseBuildOptions", () => { errors: [ { messageText: "Watch option 'fallbackPolling' requires a value of type string.", - category: ts.Diagnostics.Watch_option_0_requires_a_value_of_type_1.category, - code: ts.Diagnostics.Watch_option_0_requires_a_value_of_type_1.code, + category: Diagnostics.Watch_option_0_requires_a_value_of_type_1.category, + code: Diagnostics.Watch_option_0_requires_a_value_of_type_1.code, file: undefined, start: undefined, length: undefined }, { messageText: "Argument for '--fallbackPolling' option must be: 'fixedinterval', 'priorityinterval', 'dynamicpriority', 'fixedchunksize'.", - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, file: undefined, start: undefined, length: undefined @@ -1014,8 +1026,8 @@ describe("unittests:: config:: commandLineParsing:: parseBuildOptions", () => { errors: [ { messageText: `File specification cannot contain a parent directory ('..') that appears after a recursive directory wildcard ('**'): '**/../*'.`, - category: ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.category, - code: ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.code, + category: Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.category, + code: Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.code, file: undefined, start: undefined, length: undefined @@ -1043,8 +1055,8 @@ describe("unittests:: config:: commandLineParsing:: parseBuildOptions", () => { errors: [ { messageText: `File specification cannot contain a parent directory ('..') that appears after a recursive directory wildcard ('**'): '**/../*'.`, - category: ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.category, - code: ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.code, + category: Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.category, + code: Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.code, file: undefined, start: undefined, length: undefined diff --git a/src/testRunner/unittests/config/configurationExtension.ts b/src/testRunner/unittests/config/configurationExtension.ts index 01b438bde9602..b09f07987732c 100644 --- a/src/testRunner/unittests/config/configurationExtension.ts +++ b/src/testRunner/unittests/config/configurationExtension.ts @@ -1,9 +1,15 @@ -import * as fakes from "../../_namespaces/fakes"; -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; +import { + parseJsonConfigFileContent, parseJsonSourceFileConfigFileContent, readConfigFile, readJsonConfigFile, +} from "../../../compiler/commandLineParser"; +import { forEach } from "../../../compiler/core"; +import { combinePaths } from "../../../compiler/path"; +import { flattenDiagnosticMessageText } from "../../../compiler/program"; +import { CompilerOptions, Diagnostic, DiagnosticCategory, ModuleKind } from "../../../compiler/types"; +import { ParseConfigHost } from "../../../harness/fakesHosts"; +import { FileSystem } from "../../../harness/vfsUtil"; function createFileSystem(ignoreCase: boolean, cwd: string, root: string) { - return new vfs.FileSystem(ignoreCase, { + return new FileSystem(ignoreCase, { cwd, files: { [root]: { @@ -193,54 +199,54 @@ function createFileSystem(ignoreCase: boolean, cwd: string, root: string) { } const caseInsensitiveBasePath = "c:/dev/"; -const caseInsensitiveHost = new fakes.ParseConfigHost(createFileSystem(/*ignoreCase*/ true, caseInsensitiveBasePath, "c:/")); +const caseInsensitiveHost = new ParseConfigHost(createFileSystem(/*ignoreCase*/ true, caseInsensitiveBasePath, "c:/")); const caseSensitiveBasePath = "/dev/"; -const caseSensitiveHost = new fakes.ParseConfigHost(createFileSystem(/*ignoreCase*/ false, caseSensitiveBasePath, "/")); +const caseSensitiveHost = new ParseConfigHost(createFileSystem(/*ignoreCase*/ false, caseSensitiveBasePath, "/")); -function verifyDiagnostics(actual: ts.Diagnostic[], expected: { code: number; messageText: string; }[]) { +function verifyDiagnostics(actual: Diagnostic[], expected: { code: number; messageText: string; }[]) { assert.isTrue(expected.length === actual.length, `Expected error: ${JSON.stringify(expected)}. Actual error: ${JSON.stringify(actual)}.`); for (let i = 0; i < actual.length; i++) { const actualError = actual[i]; const expectedError = expected[i]; assert.equal(actualError.code, expectedError.code, "Error code mismatch"); - assert.equal(actualError.category, ts.DiagnosticCategory.Error, "Category mismatch"); // Should always be error - assert.equal(ts.flattenDiagnosticMessageText(actualError.messageText, "\n"), expectedError.messageText); + assert.equal(actualError.category, DiagnosticCategory.Error, "Category mismatch"); // Should always be error + assert.equal(flattenDiagnosticMessageText(actualError.messageText, "\n"), expectedError.messageText); } } describe("unittests:: config:: configurationExtension", () => { - ts.forEach<[string, string, fakes.ParseConfigHost], void>([ + forEach<[string, string, ParseConfigHost], void>([ ["under a case insensitive host", caseInsensitiveBasePath, caseInsensitiveHost], ["under a case sensitive host", caseSensitiveBasePath, caseSensitiveHost] ], ([testName, basePath, host]) => { function getParseCommandLine(entry: string) { - const {config, error} = ts.readConfigFile(entry, name => host.readFile(name)); - assert(config && !error, ts.flattenDiagnosticMessageText(error && error.messageText, "\n")); - return ts.parseJsonConfigFileContent(config, host, basePath, {}, entry); + const {config, error} = readConfigFile(entry, name => host.readFile(name)); + assert(config && !error, flattenDiagnosticMessageText(error && error.messageText, "\n")); + return parseJsonConfigFileContent(config, host, basePath, {}, entry); } function getParseCommandLineJsonSourceFile(entry: string) { - const jsonSourceFile = ts.readJsonConfigFile(entry, name => host.readFile(name)); - assert(jsonSourceFile.endOfFileToken && !jsonSourceFile.parseDiagnostics.length, ts.flattenDiagnosticMessageText(jsonSourceFile.parseDiagnostics[0] && jsonSourceFile.parseDiagnostics[0].messageText, "\n")); + const jsonSourceFile = readJsonConfigFile(entry, name => host.readFile(name)); + assert(jsonSourceFile.endOfFileToken && !jsonSourceFile.parseDiagnostics.length, flattenDiagnosticMessageText(jsonSourceFile.parseDiagnostics[0] && jsonSourceFile.parseDiagnostics[0].messageText, "\n")); return { jsonSourceFile, - parsed: ts.parseJsonSourceFileConfigFileContent(jsonSourceFile, host, basePath, {}, entry) + parsed: parseJsonSourceFileConfigFileContent(jsonSourceFile, host, basePath, {}, entry) }; } - function testSuccess(name: string, entry: string, expected: ts.CompilerOptions, expectedFiles: string[]) { + function testSuccess(name: string, entry: string, expected: CompilerOptions, expectedFiles: string[]) { expected.configFilePath = entry; it(name, () => { const parsed = getParseCommandLine(entry); - assert(!parsed.errors.length, ts.flattenDiagnosticMessageText(parsed.errors[0] && parsed.errors[0].messageText, "\n")); + assert(!parsed.errors.length, flattenDiagnosticMessageText(parsed.errors[0] && parsed.errors[0].messageText, "\n")); assert.deepEqual(parsed.options, expected); assert.deepEqual(parsed.fileNames, expectedFiles); }); it(name + " with jsonSourceFile", () => { const { parsed, jsonSourceFile } = getParseCommandLineJsonSourceFile(entry); - assert(!parsed.errors.length, ts.flattenDiagnosticMessageText(parsed.errors[0] && parsed.errors[0].messageText, "\n")); + assert(!parsed.errors.length, flattenDiagnosticMessageText(parsed.errors[0] && parsed.errors[0].messageText, "\n")); assert.deepEqual(parsed.options, expected); assert.equal(parsed.options.configFile, jsonSourceFile); assert.deepEqual(parsed.fileNames, expectedFiles); @@ -265,8 +271,8 @@ describe("unittests:: config:: configurationExtension", () => { noImplicitAny: true, strictNullChecks: true, }, [ - ts.combinePaths(basePath, "main.ts"), - ts.combinePaths(basePath, "supplemental.ts"), + combinePaths(basePath, "main.ts"), + combinePaths(basePath, "supplemental.ts"), ]); testSuccess("can resolve an extension with a base extension that overrides options", "tsconfig.nostrictnull.json", { @@ -274,14 +280,14 @@ describe("unittests:: config:: configurationExtension", () => { noImplicitAny: true, strictNullChecks: false, }, [ - ts.combinePaths(basePath, "main.ts"), - ts.combinePaths(basePath, "supplemental.ts"), + combinePaths(basePath, "main.ts"), + combinePaths(basePath, "supplemental.ts"), ]); testFailure("can report errors on circular imports", "circular.json", [ { code: 18000, - messageText: `Circularity detected while resolving configuration: ${[ts.combinePaths(basePath, "circular.json"), ts.combinePaths(basePath, "circular2.json"), ts.combinePaths(basePath, "circular.json")].join(" -> ")}` + messageText: `Circularity detected while resolving configuration: ${[combinePaths(basePath, "circular.json"), combinePaths(basePath, "circular2.json"), combinePaths(basePath, "circular.json")].join(" -> ")}` } ]); @@ -306,49 +312,49 @@ describe("unittests:: config:: configurationExtension", () => { strictNullChecks: true, module: undefined // Technically, this is distinct from the key never being set; but within the compiler we don't make the distinction }, [ - ts.combinePaths(basePath, "supplemental.ts") + combinePaths(basePath, "supplemental.ts") ]); testSuccess("can overwrite top-level options using extended 'null'", "configs/fourth.json", { allowJs: true, noImplicitAny: true, strictNullChecks: true, - module: ts.ModuleKind.System + module: ModuleKind.System }, [ - ts.combinePaths(basePath, "main.ts") + combinePaths(basePath, "main.ts") ]); testSuccess("can overwrite top-level files using extended []", "configs/fifth.json", { allowJs: true, noImplicitAny: true, strictNullChecks: true, - module: ts.ModuleKind.System + module: ModuleKind.System }, [ - ts.combinePaths(basePath, "tests/utils.ts") + combinePaths(basePath, "tests/utils.ts") ]); describe("finding extended configs from node_modules", () => { - testSuccess("can lookup via tsconfig field", "tsconfig.extendsBox.json", { strict: true }, [ts.combinePaths(basePath, "main.ts")]); - testSuccess("can lookup via package-relative path", "tsconfig.extendsStrict.json", { strict: true }, [ts.combinePaths(basePath, "main.ts")]); - testSuccess("can lookup via non-redirected-to package-relative path", "tsconfig.extendsUnStrict.json", { strict: false }, [ts.combinePaths(basePath, "main.ts")]); - testSuccess("can lookup via package-relative path with extension", "tsconfig.extendsStrictExtension.json", { strict: true }, [ts.combinePaths(basePath, "main.ts")]); - testSuccess("can lookup via an implicit tsconfig", "tsconfig.extendsBoxImplied.json", { strict: true }, [ts.combinePaths(basePath, "main.ts")]); - testSuccess("can lookup via an implicit tsconfig in a package-relative directory", "tsconfig.extendsBoxImpliedUnstrict.json", { strict: false }, [ts.combinePaths(basePath, "main.ts")]); - testSuccess("can lookup via an implicit tsconfig in a package-relative directory with name", "tsconfig.extendsBoxImpliedUnstrictExtension.json", { strict: false }, [ts.combinePaths(basePath, "main.ts")]); - testSuccess("can lookup via an implicit tsconfig in a package-relative directory with extension", "tsconfig.extendsBoxImpliedPath.json", { strict: true }, [ts.combinePaths(basePath, "main.ts")]); + testSuccess("can lookup via tsconfig field", "tsconfig.extendsBox.json", { strict: true }, [combinePaths(basePath, "main.ts")]); + testSuccess("can lookup via package-relative path", "tsconfig.extendsStrict.json", { strict: true }, [combinePaths(basePath, "main.ts")]); + testSuccess("can lookup via non-redirected-to package-relative path", "tsconfig.extendsUnStrict.json", { strict: false }, [combinePaths(basePath, "main.ts")]); + testSuccess("can lookup via package-relative path with extension", "tsconfig.extendsStrictExtension.json", { strict: true }, [combinePaths(basePath, "main.ts")]); + testSuccess("can lookup via an implicit tsconfig", "tsconfig.extendsBoxImplied.json", { strict: true }, [combinePaths(basePath, "main.ts")]); + testSuccess("can lookup via an implicit tsconfig in a package-relative directory", "tsconfig.extendsBoxImpliedUnstrict.json", { strict: false }, [combinePaths(basePath, "main.ts")]); + testSuccess("can lookup via an implicit tsconfig in a package-relative directory with name", "tsconfig.extendsBoxImpliedUnstrictExtension.json", { strict: false }, [combinePaths(basePath, "main.ts")]); + testSuccess("can lookup via an implicit tsconfig in a package-relative directory with extension", "tsconfig.extendsBoxImpliedPath.json", { strict: true }, [combinePaths(basePath, "main.ts")]); }); it("adds extendedSourceFiles only once", () => { - const sourceFile = ts.readJsonConfigFile("configs/fourth.json", (path) => host.readFile(path)); - const dir = ts.combinePaths(basePath, "configs"); + const sourceFile = readJsonConfigFile("configs/fourth.json", (path) => host.readFile(path)); + const dir = combinePaths(basePath, "configs"); const expected = [ - ts.combinePaths(dir, "third.json"), - ts.combinePaths(dir, "second.json"), - ts.combinePaths(dir, "base.json"), + combinePaths(dir, "third.json"), + combinePaths(dir, "second.json"), + combinePaths(dir, "base.json"), ]; - ts.parseJsonSourceFileConfigFileContent(sourceFile, host, dir, {}, "fourth.json"); + parseJsonSourceFileConfigFileContent(sourceFile, host, dir, {}, "fourth.json"); assert.deepEqual(sourceFile.extendedSourceFiles, expected); - ts.parseJsonSourceFileConfigFileContent(sourceFile, host, dir, {}, "fourth.json"); + parseJsonSourceFileConfigFileContent(sourceFile, host, dir, {}, "fourth.json"); assert.deepEqual(sourceFile.extendedSourceFiles, expected); }); }); diff --git a/src/testRunner/unittests/config/convertCompilerOptionsFromJson.ts b/src/testRunner/unittests/config/convertCompilerOptionsFromJson.ts index ed11faab92cf9..ca557215200aa 100644 --- a/src/testRunner/unittests/config/convertCompilerOptionsFromJson.ts +++ b/src/testRunner/unittests/config/convertCompilerOptionsFromJson.ts @@ -1,21 +1,28 @@ +import { + convertCompilerOptionsFromJson, parseJsonSourceFileConfigFileContent, +} from "../../../compiler/commandLineParser"; +import { createGetCanonicalFileName } from "../../../compiler/core"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { parseJsonText } from "../../../compiler/parser"; +import { formatDiagnostic, FormatDiagnosticsHost } from "../../../compiler/program"; +import { CompilerOptions, Diagnostic, ModuleKind, ParseConfigHost, ScriptTarget } from "../../../compiler/types"; +import { FileSystem } from "../../../harness/vfsUtil"; import * as fakes from "../../_namespaces/fakes"; -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; describe("unittests:: config:: convertCompilerOptionsFromJson", () => { - const formatDiagnosticHost: ts.FormatDiagnosticsHost = { + const formatDiagnosticHost: FormatDiagnosticsHost = { getCurrentDirectory: () => "/apath/", - getCanonicalFileName: ts.createGetCanonicalFileName(/*useCaseSensitiveFileNames*/ true), + getCanonicalFileName: createGetCanonicalFileName(/*useCaseSensitiveFileNames*/ true), getNewLine: () => "\n" }; interface ExpectedResultWithParsingSuccess { - compilerOptions: ts.CompilerOptions; - errors: readonly ts.Diagnostic[]; + compilerOptions: CompilerOptions; + errors: readonly Diagnostic[]; } interface ExpectedResultWithParsingFailure { - compilerOptions: ts.CompilerOptions; + compilerOptions: CompilerOptions; hasParseErrors: true; } @@ -31,7 +38,7 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { } function assertCompilerOptionsWithJson(json: any, configFileName: string, expectedResult: ExpectedResultWithParsingSuccess) { - const { options: actualCompilerOptions, errors: actualErrors } = ts.convertCompilerOptionsFromJson(json.compilerOptions, "/apath/", configFileName); + const { options: actualCompilerOptions, errors: actualErrors } = convertCompilerOptionsFromJson(json.compilerOptions, "/apath/", configFileName); const parsedCompilerOptions = JSON.stringify(actualCompilerOptions); const expectedCompilerOptions = JSON.stringify({ ...expectedResult.compilerOptions, configFilePath: configFileName }); @@ -45,11 +52,11 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { } function assertCompilerOptionsWithJsonText(fileText: string, configFileName: string, expectedResult: ExpectedResult) { - const result = ts.parseJsonText(configFileName, fileText); + const result = parseJsonText(configFileName, fileText); assert(!!result.endOfFileToken); assert.equal(!!result.parseDiagnostics.length, isExpectedResultWithParsingFailure(expectedResult)); - const host: ts.ParseConfigHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ false, { cwd: "/apath/" })); - const { options: actualCompilerOptions, errors: actualParseErrors } = ts.parseJsonSourceFileConfigFileContent(result, host, "/apath/", /*existingOptions*/ undefined, configFileName); + const host: ParseConfigHost = new fakes.ParseConfigHost(new FileSystem(/*ignoreCase*/ false, { cwd: "/apath/" })); + const { options: actualCompilerOptions, errors: actualParseErrors } = parseJsonSourceFileConfigFileContent(result, host, "/apath/", /*existingOptions*/ undefined, configFileName); expectedResult.compilerOptions.configFilePath = configFileName; const parsedCompilerOptions = JSON.stringify(actualCompilerOptions); @@ -58,11 +65,11 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { assert.equal(actualCompilerOptions.configFile, result); if (!isExpectedResultWithParsingFailure(expectedResult)) { - verifyErrors(actualParseErrors.filter(error => error.code !== ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code), expectedResult.errors); + verifyErrors(actualParseErrors.filter(error => error.code !== Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code), expectedResult.errors); } } - function verifyErrors(actualErrors: ts.Diagnostic[], expectedErrors: readonly ts.Diagnostic[], ignoreLocation?: boolean) { + function verifyErrors(actualErrors: Diagnostic[], expectedErrors: readonly Diagnostic[], ignoreLocation?: boolean) { assert.isTrue(expectedErrors.length === actualErrors.length, `Expected error: ${JSON.stringify(expectedErrors.map(getDiagnosticString), undefined, " ")}. Actual error: ${JSON.stringify(actualErrors.map(getDiagnosticString), undefined, " ")}.`); for (let i = 0; i < actualErrors.length; i++) { const actualError = actualErrors[i]; @@ -77,12 +84,12 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { } } - function getDiagnosticString(diagnostic: ts.Diagnostic) { + function getDiagnosticString(diagnostic: Diagnostic) { if (ignoreLocation) { const { file, ...rest } = diagnostic; diagnostic = { file: undefined, ...rest }; } - return ts.formatDiagnostic(diagnostic, formatDiagnosticHost); + return formatDiagnostic(diagnostic, formatDiagnosticHost); } } @@ -100,8 +107,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { }, "tsconfig.json", { compilerOptions: { - module: ts.ModuleKind.CommonJS, - target: ts.ScriptTarget.ES5, + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, noImplicitAny: false, sourceMap: false, lib: ["lib.es5.d.ts", "lib.es2015.core.d.ts", "lib.es2015.symbol.d.ts"] @@ -125,8 +132,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { }, "tsconfig.json", { compilerOptions: { - module: ts.ModuleKind.CommonJS, - target: ts.ScriptTarget.ES5, + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, noImplicitAny: false, sourceMap: false, allowJs: false, @@ -150,8 +157,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { }, "tsconfig.json", { compilerOptions: { - module: ts.ModuleKind.CommonJS, - target: ts.ScriptTarget.ES5, + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, noImplicitAny: false, sourceMap: false, }, @@ -160,8 +167,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { start: 0, length: 0, messageText: "Argument for '--jsx' option must be: 'preserve', 'react-native', 'react'.", - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] } ); @@ -179,7 +186,7 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { }, "tsconfig.json", { compilerOptions: { - target: ts.ScriptTarget.ES5, + target: ScriptTarget.ES5, noImplicitAny: false, sourceMap: false, }, @@ -188,8 +195,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { start: 0, length: 0, messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015', 'es2020', 'es2022', 'esnext'.", - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] } ); @@ -207,7 +214,7 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { }, "tsconfig.json", { compilerOptions: { - target: ts.ScriptTarget.ES5, + target: ScriptTarget.ES5, noImplicitAny: false, sourceMap: false, }, @@ -216,8 +223,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { start: 0, length: 0, messageText: "Argument for '--newLine' option must be: 'crlf', 'lf'.", - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] } ); @@ -242,8 +249,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { start: 0, length: 0, messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'es2018', 'es2019', 'esnext'.", - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] } ); @@ -268,8 +275,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { start: 0, length: 0, messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic'.", - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] } ); @@ -288,8 +295,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { }, "tsconfig.json", { compilerOptions: { - module: ts.ModuleKind.CommonJS, - target: ts.ScriptTarget.ES5, + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, noImplicitAny: false, sourceMap: false, lib: ["lib.es5.d.ts", "lib.es2015.core.d.ts"] @@ -299,8 +306,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { start: 0, length: 0, messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'webworker.importscripts', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'esnext.array', 'esnext.symbol', 'esnext.intl', 'esnext.bigint', 'esnext.bigint', 'esnext.string', 'esnext.promise'.", - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] } ); @@ -319,8 +326,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { }, "tsconfig.json", { compilerOptions: { - module: ts.ModuleKind.CommonJS, - target: ts.ScriptTarget.ES5, + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, noImplicitAny: false, sourceMap: false, lib: ["lib.es5.d.ts"] @@ -330,8 +337,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { start: 0, length: 0, messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'webworker.importscripts', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'esnext.array', 'esnext.symbol', 'esnext.intl', 'esnext.bigint', 'esnext.string', 'esnext.promise'.", - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] } ); @@ -350,8 +357,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { }, "tsconfig.json", { compilerOptions: { - module: ts.ModuleKind.CommonJS, - target: ts.ScriptTarget.ES5, + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, noImplicitAny: false, sourceMap: false, lib: [] @@ -361,8 +368,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { start: 0, length: 0, messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'webworker.importscripts', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'esnext.array', 'esnext.symbol', 'esnext.intl', 'esnext.bigint', 'esnext.string', 'esnext.promise'.", - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] } ); @@ -381,8 +388,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { }, "tsconfig.json", { compilerOptions: { - module: ts.ModuleKind.CommonJS, - target: ts.ScriptTarget.ES5, + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, noImplicitAny: false, sourceMap: false, lib: [] @@ -392,8 +399,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { start: 0, length: 0, messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'es2018', 'esnext', 'dom', 'dom.iterable', 'webworker', 'webworker.importscripts', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'es2018.asynciterable', 'es2018.intl', 'es2018.promise', 'es2018.regexp', 'esnext.array', 'esnext.symbol', 'esnext.intl', 'esnext.bigint', 'esnext.string', 'esnext.promise'.", - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] } ); @@ -412,8 +419,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { }, "tsconfig.json", { compilerOptions: { - module: ts.ModuleKind.CommonJS, - target: ts.ScriptTarget.ES5, + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, noImplicitAny: false, sourceMap: false, lib: [] @@ -501,8 +508,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { start: 0, length: 0, messageText: "Unknown compiler option 'modu'.", - code: ts.Diagnostics.Unknown_compiler_option_0.code, - category: ts.Diagnostics.Unknown_compiler_option_0.category + code: Diagnostics.Unknown_compiler_option_0.code, + category: Diagnostics.Unknown_compiler_option_0.category }] } ); @@ -554,8 +561,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { allowSyntheticDefaultImports: true, skipLibCheck: true, noEmit: true, - module: ts.ModuleKind.CommonJS, - target: ts.ScriptTarget.ES5, + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, noImplicitAny: false, sourceMap: false, lib: ["lib.es5.d.ts", "lib.es2015.core.d.ts", "lib.es2015.symbol.d.ts"] @@ -584,8 +591,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { allowSyntheticDefaultImports: true, skipLibCheck: true, noEmit: true, - module: ts.ModuleKind.CommonJS, - target: ts.ScriptTarget.ES5, + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, noImplicitAny: false, sourceMap: false, lib: ["lib.es5.d.ts", "lib.es2015.core.d.ts", "lib.es2015.symbol.d.ts"] @@ -616,8 +623,8 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { start: 0, length: 0, messageText: "Unknown compiler option 'modu'.", - code: ts.Diagnostics.Unknown_compiler_option_0.code, - category: ts.Diagnostics.Unknown_compiler_option_0.category + code: Diagnostics.Unknown_compiler_option_0.code, + category: Diagnostics.Unknown_compiler_option_0.category }] } ); @@ -664,7 +671,7 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { { compilerOptions: { target: undefined, - module: ts.ModuleKind.ESNext, + module: ModuleKind.ESNext, experimentalDecorators: true, }, hasParseErrors: true @@ -678,11 +685,11 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { } } blah`, "tsconfig.json", { compilerOptions: { - target: ts.ScriptTarget.ESNext + target: ScriptTarget.ESNext }, hasParseErrors: true, errors: [{ - ...ts.Diagnostics.The_root_value_of_a_0_file_must_be_an_object, + ...Diagnostics.The_root_value_of_a_0_file_must_be_an_object, messageText: "The root value of a 'tsconfig.json' file must be an object.", file: undefined, start: 0, @@ -698,11 +705,11 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { } }`, "tsconfig.json", { compilerOptions: { - target: ts.ScriptTarget.ESNext + target: ScriptTarget.ESNext }, hasParseErrors: true, errors: [{ - ...ts.Diagnostics.The_root_value_of_a_0_file_must_be_an_object, + ...Diagnostics.The_root_value_of_a_0_file_must_be_an_object, messageText: "The root value of a 'tsconfig.json' file must be an object.", file: undefined, start: 0, @@ -718,10 +725,10 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { } }]`, "tsconfig.json", { compilerOptions: { - target: ts.ScriptTarget.ESNext + target: ScriptTarget.ESNext }, errors: [{ - ...ts.Diagnostics.The_root_value_of_a_0_file_must_be_an_object, + ...Diagnostics.The_root_value_of_a_0_file_must_be_an_object, messageText: "The root value of a 'tsconfig.json' file must be an object.", file: undefined, start: 0, @@ -736,7 +743,7 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { }`, "tsconfig.json", { compilerOptions: {}, errors: [{ - ...ts.Diagnostics._0_should_be_set_inside_the_compilerOptions_object_of_the_config_json_file, + ...Diagnostics._0_should_be_set_inside_the_compilerOptions_object_of_the_config_json_file, messageText: "'module' should be set inside the 'compilerOptions' object of the config json file.", file: undefined, start: 0, @@ -753,7 +760,7 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { } }`, "tsconfig.json", { compilerOptions: { - module: ts.ModuleKind.ESNext + module: ModuleKind.ESNext }, errors: [] }); @@ -763,7 +770,7 @@ describe("unittests:: config:: convertCompilerOptionsFromJson", () => { assertCompilerOptionsWithJsonText(`42`, "tsconfig.json", { compilerOptions: {}, errors: [{ - ...ts.Diagnostics.The_root_value_of_a_0_file_must_be_an_object, + ...Diagnostics.The_root_value_of_a_0_file_must_be_an_object, messageText: "The root value of a 'tsconfig.json' file must be an object.", file: undefined, start: 0, diff --git a/src/testRunner/unittests/config/convertTypeAcquisitionFromJson.ts b/src/testRunner/unittests/config/convertTypeAcquisitionFromJson.ts index ada55e2538ce3..f4594c064faa9 100644 --- a/src/testRunner/unittests/config/convertTypeAcquisitionFromJson.ts +++ b/src/testRunner/unittests/config/convertTypeAcquisitionFromJson.ts @@ -1,21 +1,27 @@ +import { + convertTypeAcquisitionFromJson, parseJsonSourceFileConfigFileContent, +} from "../../../compiler/commandLineParser"; +import { filter } from "../../../compiler/core"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { parseJsonText } from "../../../compiler/parser"; +import { Diagnostic, ParseConfigHost, TypeAcquisition } from "../../../compiler/types"; +import { FileSystem } from "../../../harness/vfsUtil"; import * as fakes from "../../_namespaces/fakes"; -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; -interface ExpectedResult { typeAcquisition: ts.TypeAcquisition; errors: ts.Diagnostic[]; } +interface ExpectedResult { typeAcquisition: TypeAcquisition; errors: Diagnostic[]; } describe("unittests:: config:: convertTypeAcquisitionFromJson", () => { function assertTypeAcquisition(json: any, configFileName: string, expectedResult: ExpectedResult) { assertTypeAcquisitionWithJson(json, configFileName, expectedResult); assertTypeAcquisitionWithJsonNode(json, configFileName, expectedResult); } - function verifyAcquisition(actualTypeAcquisition: ts.TypeAcquisition | undefined, expectedResult: ExpectedResult) { + function verifyAcquisition(actualTypeAcquisition: TypeAcquisition | undefined, expectedResult: ExpectedResult) { const parsedTypeAcquisition = JSON.stringify(actualTypeAcquisition); const expectedTypeAcquisition = JSON.stringify(expectedResult.typeAcquisition); assert.equal(parsedTypeAcquisition, expectedTypeAcquisition); } - function verifyErrors(actualErrors: ts.Diagnostic[], expectedResult: ExpectedResult, hasLocation?: boolean) { + function verifyErrors(actualErrors: Diagnostic[], expectedResult: ExpectedResult, hasLocation?: boolean) { const expectedErrors = expectedResult.errors; assert.isTrue(expectedResult.errors.length === actualErrors.length, `Expected error: ${JSON.stringify(expectedResult.errors)}. Actual error: ${JSON.stringify(actualErrors)}.`); for (let i = 0; i < actualErrors.length; i++) { @@ -33,21 +39,21 @@ describe("unittests:: config:: convertTypeAcquisitionFromJson", () => { function assertTypeAcquisitionWithJson(json: any, configFileName: string, expectedResult: ExpectedResult) { const jsonOptions = json.typeAcquisition || json.typingOptions; - const { options: actualTypeAcquisition, errors: actualErrors } = ts.convertTypeAcquisitionFromJson(jsonOptions, "/apath/", configFileName); + const { options: actualTypeAcquisition, errors: actualErrors } = convertTypeAcquisitionFromJson(jsonOptions, "/apath/", configFileName); verifyAcquisition(actualTypeAcquisition, expectedResult); verifyErrors(actualErrors, expectedResult); } function assertTypeAcquisitionWithJsonNode(json: any, configFileName: string, expectedResult: ExpectedResult) { const fileText = JSON.stringify(json); - const result = ts.parseJsonText(configFileName, fileText); + const result = parseJsonText(configFileName, fileText); assert(!result.parseDiagnostics.length); assert(!!result.endOfFileToken); - const host: ts.ParseConfigHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ false, { cwd: "/apath/" })); - const { typeAcquisition: actualTypeAcquisition, errors: actualParseErrors } = ts.parseJsonSourceFileConfigFileContent(result, host, "/apath/", /*existingOptions*/ undefined, configFileName); + const host: ParseConfigHost = new fakes.ParseConfigHost(new FileSystem(/*ignoreCase*/ false, { cwd: "/apath/" })); + const { typeAcquisition: actualTypeAcquisition, errors: actualParseErrors } = parseJsonSourceFileConfigFileContent(result, host, "/apath/", /*existingOptions*/ undefined, configFileName); verifyAcquisition(actualTypeAcquisition, expectedResult); - const actualErrors = ts.filter(actualParseErrors, error => error.code !== ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code); + const actualErrors = filter(actualParseErrors, error => error.code !== Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code); verifyErrors(actualErrors, expectedResult, /*hasLocation*/ true); } @@ -70,7 +76,7 @@ describe("unittests:: config:: convertTypeAcquisitionFromJson", () => { include: ["0.d.ts", "1.d.ts"], exclude: ["0.js", "1.js"] }, - errors: [] as ts.Diagnostic[] + errors: [] as Diagnostic[] } ); }); @@ -93,7 +99,7 @@ describe("unittests:: config:: convertTypeAcquisitionFromJson", () => { include: ["0.d.ts", "1.d.ts"], exclude: ["0.js", "1.js"] }, - errors: [] as ts.Diagnostic[] + errors: [] as Diagnostic[] }); }); @@ -114,8 +120,8 @@ describe("unittests:: config:: convertTypeAcquisitionFromJson", () => { }, errors: [ { - category: ts.Diagnostics.Unknown_type_acquisition_option_0_Did_you_mean_1.category, - code: ts.Diagnostics.Unknown_type_acquisition_option_0_Did_you_mean_1.code, + category: Diagnostics.Unknown_type_acquisition_option_0_Did_you_mean_1.category, + code: Diagnostics.Unknown_type_acquisition_option_0_Did_you_mean_1.code, file: undefined, start: 0, length: 0, @@ -134,7 +140,7 @@ describe("unittests:: config:: convertTypeAcquisitionFromJson", () => { include: [], exclude: [] }, - errors: [] as ts.Diagnostic[] + errors: [] as Diagnostic[] }); }); @@ -153,7 +159,7 @@ describe("unittests:: config:: convertTypeAcquisitionFromJson", () => { include: [], exclude: [] }, - errors: [] as ts.Diagnostic[] + errors: [] as Diagnostic[] }); }); @@ -175,7 +181,7 @@ describe("unittests:: config:: convertTypeAcquisitionFromJson", () => { include: ["0.d.ts"], exclude: ["0.js"] }, - errors: [] as ts.Diagnostic[] + errors: [] as Diagnostic[] }); }); @@ -188,7 +194,7 @@ describe("unittests:: config:: convertTypeAcquisitionFromJson", () => { include: [], exclude: [] }, - errors: [] as ts.Diagnostic[] + errors: [] as Diagnostic[] }); }); @@ -209,8 +215,8 @@ describe("unittests:: config:: convertTypeAcquisitionFromJson", () => { }, errors: [ { - category: ts.Diagnostics.Unknown_type_acquisition_option_0_Did_you_mean_1.category, - code: ts.Diagnostics.Unknown_type_acquisition_option_0_Did_you_mean_1.code, + category: Diagnostics.Unknown_type_acquisition_option_0_Did_you_mean_1.category, + code: Diagnostics.Unknown_type_acquisition_option_0_Did_you_mean_1.code, file: undefined, start: 0, length: 0, @@ -235,7 +241,7 @@ describe("unittests:: config:: convertTypeAcquisitionFromJson", () => { include: [], exclude: [] }, - errors: [] as ts.Diagnostic[] + errors: [] as Diagnostic[] }); }); }); diff --git a/src/testRunner/unittests/config/initializeTSConfig.ts b/src/testRunner/unittests/config/initializeTSConfig.ts index 67c0d1424368c..7d619bbeee957 100644 --- a/src/testRunner/unittests/config/initializeTSConfig.ts +++ b/src/testRunner/unittests/config/initializeTSConfig.ts @@ -1,15 +1,15 @@ -import * as Harness from "../../_namespaces/Harness"; -import * as ts from "../../_namespaces/ts"; +import { generateTSConfig, parseCommandLine } from "../../../compiler/commandLineParser"; +import { Baseline } from "../../../harness/harnessIO"; describe("unittests:: config:: initTSConfig", () => { function initTSConfigCorrectly(name: string, commandLinesArgs: string[]) { describe(name, () => { - const commandLine = ts.parseCommandLine(commandLinesArgs); - const initResult = ts.generateTSConfig(commandLine.options, commandLine.fileNames, "\n"); + const commandLine = parseCommandLine(commandLinesArgs); + const initResult = generateTSConfig(commandLine.options, commandLine.fileNames, "\n"); const outputFileName = `tsConfig/${name.replace(/[^a-z0-9\-. ]/ig, "")}/tsconfig.json`; it(`Correct output for ${outputFileName}`, () => { - Harness.Baseline.runBaseline(outputFileName, initResult); + Baseline.runBaseline(outputFileName, initResult); }); }); } diff --git a/src/testRunner/unittests/config/matchFiles.ts b/src/testRunner/unittests/config/matchFiles.ts index 5dd0bec681804..36bfddae70a7a 100644 --- a/src/testRunner/unittests/config/matchFiles.ts +++ b/src/testRunner/unittests/config/matchFiles.ts @@ -1,10 +1,18 @@ -import * as fakes from "../../_namespaces/fakes"; +import { parseJsonConfigFileContent, parseJsonSourceFileConfigFileContent } from "../../../compiler/commandLineParser"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { parseJsonText } from "../../../compiler/parser"; +import { + CompilerOptions, Diagnostic, DiagnosticMessage, JsxEmit, ParsedCommandLine, Path, SourceFile, SyntaxKind, + WatchDirectoryFlags, +} from "../../../compiler/types"; +import { createCompilerDiagnostic, createFileDiagnostic } from "../../../compiler/utilities"; +import { ParseConfigHost } from "../../../harness/fakesHosts"; +import { FileSystem } from "../../../harness/vfsUtil"; import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; const caseInsensitiveBasePath = "c:/dev/"; const caseInsensitiveTsconfigPath = "c:/dev/tsconfig.json"; -const caseInsensitiveHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ true, { cwd: caseInsensitiveBasePath, files: { +const caseInsensitiveHost = new ParseConfigHost(new FileSystem(/*ignoreCase*/ true, { cwd: caseInsensitiveBasePath, files: { "c:/dev/a.ts": "", "c:/dev/a.d.ts": "", "c:/dev/a.js": "", @@ -31,7 +39,7 @@ const caseInsensitiveHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignor }})); const caseSensitiveBasePath = "/dev/"; -const caseSensitiveHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ false, { cwd: caseSensitiveBasePath, files: { +const caseSensitiveHost = new ParseConfigHost(new FileSystem(/*ignoreCase*/ false, { cwd: caseSensitiveBasePath, files: { "/dev/a.ts": "", "/dev/a.d.ts": "", "/dev/a.js": "", @@ -55,7 +63,7 @@ const caseSensitiveHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreC "/dev/js/b.js": "", }})); -const caseInsensitiveMixedExtensionHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ true, { cwd: caseInsensitiveBasePath, files: { +const caseInsensitiveMixedExtensionHost = new ParseConfigHost(new FileSystem(/*ignoreCase*/ true, { cwd: caseInsensitiveBasePath, files: { "c:/dev/a.ts": "", "c:/dev/a.d.ts": "", "c:/dev/a.js": "", @@ -69,7 +77,7 @@ const caseInsensitiveMixedExtensionHost = new fakes.ParseConfigHost(new vfs.File "c:/dev/f.other": "", }})); -const caseInsensitiveCommonFoldersHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ true, { cwd: caseInsensitiveBasePath, files: { +const caseInsensitiveCommonFoldersHost = new ParseConfigHost(new FileSystem(/*ignoreCase*/ true, { cwd: caseInsensitiveBasePath, files: { "c:/dev/a.ts": "", "c:/dev/a.d.ts": "", "c:/dev/a.js": "", @@ -80,7 +88,7 @@ const caseInsensitiveCommonFoldersHost = new fakes.ParseConfigHost(new vfs.FileS "c:/dev/jspm_packages/a.ts": "", }})); -const caseInsensitiveDottedFoldersHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ true, { cwd: caseInsensitiveBasePath, files: { +const caseInsensitiveDottedFoldersHost = new ParseConfigHost(new FileSystem(/*ignoreCase*/ true, { cwd: caseInsensitiveBasePath, files: { "c:/dev/x/d.ts": "", "c:/dev/x/y/d.ts": "", "c:/dev/x/y/.e.ts": "", @@ -91,29 +99,29 @@ const caseInsensitiveDottedFoldersHost = new fakes.ParseConfigHost(new vfs.FileS "c:/dev/g.min.js/.g/g.ts": "", }})); -const caseInsensitiveOrderingDiffersWithCaseHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ true, { cwd: caseInsensitiveBasePath, files: { +const caseInsensitiveOrderingDiffersWithCaseHost = new ParseConfigHost(new FileSystem(/*ignoreCase*/ true, { cwd: caseInsensitiveBasePath, files: { "c:/dev/xylophone.ts": "", "c:/dev/Yosemite.ts": "", "c:/dev/zebra.ts": "", }})); -const caseSensitiveOrderingDiffersWithCaseHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ false, { cwd: caseSensitiveBasePath, files: { +const caseSensitiveOrderingDiffersWithCaseHost = new ParseConfigHost(new FileSystem(/*ignoreCase*/ false, { cwd: caseSensitiveBasePath, files: { "/dev/xylophone.ts": "", "/dev/Yosemite.ts": "", "/dev/zebra.ts": "", }})); -function assertParsed(actual: ts.ParsedCommandLine, expected: ts.ParsedCommandLine): void { +function assertParsed(actual: ParsedCommandLine, expected: ParsedCommandLine): void { assert.deepEqual(actual.fileNames, expected.fileNames); assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories); assert.deepEqual(actual.errors, expected.errors); } -function validateMatches(expected: ts.ParsedCommandLine, json: any, host: ts.ParseConfigHost, basePath: string, existingOptions?: ts.CompilerOptions, configFileName?: string, resolutionStack?: ts.Path[]) { +function validateMatches(expected: ParsedCommandLine, json: any, host: ts.ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[]) { { const jsonText = JSON.stringify(json); - const result = ts.parseJsonText(caseInsensitiveTsconfigPath, jsonText); - const actual = ts.parseJsonSourceFileConfigFileContent(result, host, basePath, existingOptions, configFileName, resolutionStack); + const result = parseJsonText(caseInsensitiveTsconfigPath, jsonText); + const actual = parseJsonSourceFileConfigFileContent(result, host, basePath, existingOptions, configFileName, resolutionStack); for (const error of expected.errors) { if (error.file) { error.file = result; @@ -122,8 +130,8 @@ function validateMatches(expected: ts.ParsedCommandLine, json: any, host: ts.Par assertParsed(actual, expected); } { - const actual = ts.parseJsonConfigFileContent(json, host, basePath, existingOptions, configFileName, resolutionStack); - expected.errors = expected.errors.map((error): ts.Diagnostic => ({ + const actual = parseJsonConfigFileContent(json, host, basePath, existingOptions, configFileName, resolutionStack); + expected.errors = expected.errors.map((error): Diagnostic => ({ category: error.category, code: error.code, file: undefined, @@ -137,20 +145,20 @@ function validateMatches(expected: ts.ParsedCommandLine, json: any, host: ts.Par } } -function createDiagnosticForConfigFile(json: any, start: number, length: number, diagnosticMessage: ts.DiagnosticMessage, arg0: string) { +function createDiagnosticForConfigFile(json: any, start: number, length: number, diagnosticMessage: DiagnosticMessage, arg0: string) { const text = JSON.stringify(json); const file = { fileName: caseInsensitiveTsconfigPath, - kind: ts.SyntaxKind.SourceFile, + kind: SyntaxKind.SourceFile, text - } as ts.SourceFile; - return ts.createFileDiagnostic(file, start, length, diagnosticMessage, arg0); + } as SourceFile; + return createFileDiagnostic(file, start, length, diagnosticMessage, arg0); } describe("unittests:: config:: matchFiles", () => { it("with defaults", () => { const json = {}; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -159,7 +167,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/x/a.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive }, }; validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath); @@ -173,7 +181,7 @@ describe("unittests:: config:: matchFiles", () => { "b.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -191,7 +199,7 @@ describe("unittests:: config:: matchFiles", () => { "x.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -212,7 +220,7 @@ describe("unittests:: config:: matchFiles", () => { "b.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -233,7 +241,7 @@ describe("unittests:: config:: matchFiles", () => { "b.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -251,10 +259,10 @@ describe("unittests:: config:: matchFiles", () => { "b.js" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [ - ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, + createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]") ], fileNames: [], @@ -269,10 +277,10 @@ describe("unittests:: config:: matchFiles", () => { "x.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [ - ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, + createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]") ], fileNames: [], @@ -290,7 +298,7 @@ describe("unittests:: config:: matchFiles", () => { "b.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -316,7 +324,7 @@ describe("unittests:: config:: matchFiles", () => { "*/b.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -341,7 +349,7 @@ describe("unittests:: config:: matchFiles", () => { "**/b.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -362,7 +370,7 @@ describe("unittests:: config:: matchFiles", () => { "**/b.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -382,7 +390,7 @@ describe("unittests:: config:: matchFiles", () => { "jspm_packages/a.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -410,7 +418,7 @@ describe("unittests:: config:: matchFiles", () => { "b.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -432,7 +440,7 @@ describe("unittests:: config:: matchFiles", () => { "jspm_packages/a.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -456,7 +464,7 @@ describe("unittests:: config:: matchFiles", () => { "x/*.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -471,8 +479,8 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/x/b.ts" ], wildcardDirectories: { - "c:/dev/z": ts.WatchDirectoryFlags.None, - "c:/dev/x": ts.WatchDirectoryFlags.None + "c:/dev/z": WatchDirectoryFlags.None, + "c:/dev/x": WatchDirectoryFlags.None }, }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -483,7 +491,7 @@ describe("unittests:: config:: matchFiles", () => { "*.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -492,7 +500,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/c.d.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.None + "c:/dev": WatchDirectoryFlags.None }, }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -503,7 +511,7 @@ describe("unittests:: config:: matchFiles", () => { "*" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -512,7 +520,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/c.d.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.None + "c:/dev": WatchDirectoryFlags.None }, }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -523,7 +531,7 @@ describe("unittests:: config:: matchFiles", () => { "x/?.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -531,7 +539,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/x/b.ts" ], wildcardDirectories: { - "c:/dev/x": ts.WatchDirectoryFlags.None + "c:/dev/x": WatchDirectoryFlags.None }, }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -542,7 +550,7 @@ describe("unittests:: config:: matchFiles", () => { "**/a.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -552,7 +560,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/z/a.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive }, }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -565,7 +573,7 @@ describe("unittests:: config:: matchFiles", () => { "z/**/a.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -574,8 +582,8 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/z/a.ts" ], wildcardDirectories: { - "c:/dev/x": ts.WatchDirectoryFlags.Recursive, - "c:/dev/z": ts.WatchDirectoryFlags.Recursive + "c:/dev/x": WatchDirectoryFlags.Recursive, + "c:/dev/z": WatchDirectoryFlags.Recursive }, }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -586,14 +594,14 @@ describe("unittests:: config:: matchFiles", () => { "**/A.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ "/dev/A.ts" ], wildcardDirectories: { - "/dev": ts.WatchDirectoryFlags.Recursive + "/dev": WatchDirectoryFlags.Recursive }, }; validateMatches(expected, json, caseSensitiveHost, caseSensitiveBasePath); @@ -604,15 +612,15 @@ describe("unittests:: config:: matchFiles", () => { "*/z.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [ - ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, + createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]") ], fileNames: [], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive }, }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath); @@ -629,14 +637,14 @@ describe("unittests:: config:: matchFiles", () => { "**/a.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ "c:/dev/a.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive }, }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -651,7 +659,7 @@ describe("unittests:: config:: matchFiles", () => { "x" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -660,7 +668,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/c.d.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -672,7 +680,7 @@ describe("unittests:: config:: matchFiles", () => { "**/a.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -680,7 +688,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/x/a.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive }, }; validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath); @@ -694,7 +702,7 @@ describe("unittests:: config:: matchFiles", () => { "a.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -702,7 +710,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/x/a.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive }, }; validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath); @@ -714,7 +722,7 @@ describe("unittests:: config:: matchFiles", () => { ], exclude: [] as string[] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -722,7 +730,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/x/a.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive }, }; validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath); @@ -734,7 +742,7 @@ describe("unittests:: config:: matchFiles", () => { "**/node_modules/a.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -743,7 +751,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/node_modules/a.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive }, }; validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath); @@ -754,14 +762,14 @@ describe("unittests:: config:: matchFiles", () => { "*/a.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ "c:/dev/x/a.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive }, }; validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath); @@ -773,7 +781,7 @@ describe("unittests:: config:: matchFiles", () => { "node_modules/a.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -781,7 +789,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/node_modules/a.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive }, }; validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath); @@ -796,17 +804,17 @@ describe("unittests:: config:: matchFiles", () => { "js/*" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: { allowJs: false }, errors: [ - ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, + createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]") ], fileNames: [], wildcardDirectories: { - "c:/dev/js": ts.WatchDirectoryFlags.None + "c:/dev/js": WatchDirectoryFlags.None } }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath); @@ -820,7 +828,7 @@ describe("unittests:: config:: matchFiles", () => { "js/*" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: { allowJs: true }, @@ -830,7 +838,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/js/b.js" ], wildcardDirectories: { - "c:/dev/js": ts.WatchDirectoryFlags.None + "c:/dev/js": WatchDirectoryFlags.None } }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -844,7 +852,7 @@ describe("unittests:: config:: matchFiles", () => { "js/*.min.js" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: { allowJs: true }, @@ -854,7 +862,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/js/d.min.js" ], wildcardDirectories: { - "c:/dev/js": ts.WatchDirectoryFlags.None + "c:/dev/js": WatchDirectoryFlags.None } }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -866,7 +874,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/ext/*" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -876,8 +884,8 @@ describe("unittests:: config:: matchFiles", () => { "c:/ext/ext.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.None, - "c:/ext": ts.WatchDirectoryFlags.None + "c:/dev": WatchDirectoryFlags.None, + "c:/ext": WatchDirectoryFlags.None } }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -892,14 +900,14 @@ describe("unittests:: config:: matchFiles", () => { "**" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ "c:/ext/ext.ts" ], wildcardDirectories: { - "c:/ext": ts.WatchDirectoryFlags.None + "c:/ext": WatchDirectoryFlags.None } }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -913,10 +921,10 @@ describe("unittests:: config:: matchFiles", () => { "../**" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [ - ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, + createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(json.exclude))] , fileNames: [], @@ -933,7 +941,7 @@ describe("unittests:: config:: matchFiles", () => { "**" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -952,14 +960,14 @@ describe("unittests:: config:: matchFiles", () => { "c:/ext/b/a..b.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ "c:/ext/ext.ts", ], wildcardDirectories: { - "c:/ext": ts.WatchDirectoryFlags.Recursive + "c:/ext": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -970,7 +978,7 @@ describe("unittests:: config:: matchFiles", () => { allowJs: false } }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: { allowJs: false }, @@ -981,7 +989,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/c.tsx", ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath); @@ -993,9 +1001,9 @@ describe("unittests:: config:: matchFiles", () => { allowJs: false } }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: { - jsx: ts.JsxEmit.Preserve, + jsx: JsxEmit.Preserve, allowJs: false }, errors: [], @@ -1005,7 +1013,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/c.tsx", ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath); @@ -1017,9 +1025,9 @@ describe("unittests:: config:: matchFiles", () => { allowJs: false } }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: { - jsx: ts.JsxEmit.ReactNative, + jsx: JsxEmit.ReactNative, allowJs: false }, errors: [], @@ -1029,7 +1037,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/c.tsx", ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath); @@ -1040,7 +1048,7 @@ describe("unittests:: config:: matchFiles", () => { allowJs: true } }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: { allowJs: true }, @@ -1053,7 +1061,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/e.jsx", ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath); @@ -1065,9 +1073,9 @@ describe("unittests:: config:: matchFiles", () => { allowJs: true } }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: { - jsx: ts.JsxEmit.Preserve, + jsx: JsxEmit.Preserve, allowJs: true }, errors: [], @@ -1079,7 +1087,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/e.jsx", ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath); @@ -1091,9 +1099,9 @@ describe("unittests:: config:: matchFiles", () => { allowJs: true } }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: { - jsx: ts.JsxEmit.ReactNative, + jsx: JsxEmit.ReactNative, allowJs: true }, errors: [], @@ -1105,7 +1113,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/e.jsx", ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath); @@ -1122,7 +1130,7 @@ describe("unittests:: config:: matchFiles", () => { "js/a*" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: { allowJs: true }, @@ -1131,7 +1139,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/js/d.min.js" ], wildcardDirectories: { - "c:/dev/js": ts.WatchDirectoryFlags.None + "c:/dev/js": WatchDirectoryFlags.None } }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -1144,11 +1152,11 @@ describe("unittests:: config:: matchFiles", () => { "**" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [ - createDiagnosticForConfigFile(json, 12, 4, ts.Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**"), - ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, + createDiagnosticForConfigFile(json, 12, 4, Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**"), + createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]") ], fileNames: [], @@ -1165,10 +1173,10 @@ describe("unittests:: config:: matchFiles", () => { "**" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [ - ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, + createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(json.exclude)) ], fileNames: [], @@ -1184,7 +1192,7 @@ describe("unittests:: config:: matchFiles", () => { "**/x/**/*" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -1195,7 +1203,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/x/y/b.ts", ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath); @@ -1209,7 +1217,7 @@ describe("unittests:: config:: matchFiles", () => { "**/x/**" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -1217,7 +1225,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/z/a.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -1231,11 +1239,11 @@ describe("unittests:: config:: matchFiles", () => { "**/../*" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [ - createDiagnosticForConfigFile(json, 12, 9, ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/../*"), - ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, + createDiagnosticForConfigFile(json, 12, 9, Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/../*"), + createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]") ], fileNames: [], @@ -1250,11 +1258,11 @@ describe("unittests:: config:: matchFiles", () => { "**/y/../*" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [ - createDiagnosticForConfigFile(json, 12, 11, ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/../*"), - ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, + createDiagnosticForConfigFile(json, 12, 11, Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/../*"), + createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]") ], fileNames: [], @@ -1272,10 +1280,10 @@ describe("unittests:: config:: matchFiles", () => { "**/.." ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [ - createDiagnosticForConfigFile(json, 34, 7, ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/..") + createDiagnosticForConfigFile(json, 34, 7, Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/..") ], fileNames: [ "c:/dev/a.ts", @@ -1284,7 +1292,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/z/a.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -1299,10 +1307,10 @@ describe("unittests:: config:: matchFiles", () => { "**/y/.." ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [ - createDiagnosticForConfigFile(json, 34, 9, ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/..") + createDiagnosticForConfigFile(json, 34, 9, Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/..") ], fileNames: [ "c:/dev/a.ts", @@ -1311,7 +1319,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/z/a.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -1323,12 +1331,12 @@ describe("unittests:: config:: matchFiles", () => { const json = { include: ["z"] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ "a.ts", "aba.ts", "abz.ts", "b.ts", "bba.ts", "bbz.ts" ].map(x => `c:/dev/z/${x}`), wildcardDirectories: { - "c:/dev/z": ts.WatchDirectoryFlags.Recursive + "c:/dev/z": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath); @@ -1344,7 +1352,7 @@ describe("unittests:: config:: matchFiles", () => { "w/*/*" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -1352,8 +1360,8 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/x/y/d.ts", ], wildcardDirectories: { - "c:/dev/x": ts.WatchDirectoryFlags.Recursive, - "c:/dev/w": ts.WatchDirectoryFlags.Recursive + "c:/dev/x": WatchDirectoryFlags.Recursive, + "c:/dev/w": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath); @@ -1366,7 +1374,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/.z/.b.ts" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -1383,7 +1391,7 @@ describe("unittests:: config:: matchFiles", () => { "**/.*/*" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -1393,7 +1401,7 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/x/.y/a.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath); @@ -1405,7 +1413,7 @@ describe("unittests:: config:: matchFiles", () => { ".z/**/.*" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -1413,8 +1421,8 @@ describe("unittests:: config:: matchFiles", () => { "c:/dev/.z/.b.ts" ], wildcardDirectories: { - "c:/dev/.z": ts.WatchDirectoryFlags.Recursive, - "c:/dev/x": ts.WatchDirectoryFlags.Recursive + "c:/dev/.z": WatchDirectoryFlags.Recursive, + "c:/dev/x": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath); @@ -1428,10 +1436,10 @@ describe("unittests:: config:: matchFiles", () => { "**/*" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [ - ts.createCompilerDiagnostic(ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, + createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(json.exclude)) ], fileNames: [], @@ -1449,7 +1457,7 @@ describe("unittests:: config:: matchFiles", () => { "**/x" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -1467,7 +1475,7 @@ describe("unittests:: config:: matchFiles", () => { "/dev/z/bbz.ts", ], wildcardDirectories: { - "/dev": ts.WatchDirectoryFlags.Recursive + "/dev": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseSensitiveHost, caseSensitiveBasePath); @@ -1479,7 +1487,7 @@ describe("unittests:: config:: matchFiles", () => { "**/a/**/b" ] }; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ @@ -1490,7 +1498,7 @@ describe("unittests:: config:: matchFiles", () => { "/dev/q/a/c/b/d.ts", ], wildcardDirectories: { - "/dev": ts.WatchDirectoryFlags.Recursive + "/dev": WatchDirectoryFlags.Recursive } }; validateMatches(expected, json, caseSensitiveHost, caseSensitiveBasePath); @@ -1498,7 +1506,7 @@ describe("unittests:: config:: matchFiles", () => { }); it("can include files in the same order on multiple platforms", () => { - function getExpected(basePath: string): ts.ParsedCommandLine { + function getExpected(basePath: string): ParsedCommandLine { return { options: {}, errors: [], @@ -1508,7 +1516,7 @@ describe("unittests:: config:: matchFiles", () => { `${basePath}zebra.ts` ], wildcardDirectories: { - [basePath.slice(0, basePath.length - 1)]: ts.WatchDirectoryFlags.Recursive + [basePath.slice(0, basePath.length - 1)]: WatchDirectoryFlags.Recursive }, }; } @@ -1518,7 +1526,7 @@ describe("unittests:: config:: matchFiles", () => { }); it("when recursive symlinked directories are present", () => { - const fs = new vfs.FileSystem(/*ignoreCase*/ true, { + const fs = new FileSystem(/*ignoreCase*/ true, { cwd: caseInsensitiveBasePath, files: { "c:/dev/index.ts": "" } @@ -1527,16 +1535,16 @@ describe("unittests:: config:: matchFiles", () => { fs.symlinkSync("c:/dev/A", "c:/dev/a/self"); fs.symlinkSync("c:/dev/a", "c:/dev/a/b/parent"); fs.symlinkSync("c:/dev/a", "c:/dev/a/b/c/grandparent"); - const host = new fakes.ParseConfigHost(fs); + const host = new ParseConfigHost(fs); const json = {}; - const expected: ts.ParsedCommandLine = { + const expected: ParsedCommandLine = { options: {}, errors: [], fileNames: [ "c:/dev/index.ts" ], wildcardDirectories: { - "c:/dev": ts.WatchDirectoryFlags.Recursive + "c:/dev": WatchDirectoryFlags.Recursive }, }; validateMatches(expected, json, host, caseInsensitiveBasePath); diff --git a/src/testRunner/unittests/config/projectReferences.ts b/src/testRunner/unittests/config/projectReferences.ts index 6c579f0844ca7..d3f05bd5ee2f9 100644 --- a/src/testRunner/unittests/config/projectReferences.ts +++ b/src/testRunner/unittests/config/projectReferences.ts @@ -1,27 +1,35 @@ -import * as fakes from "../../_namespaces/fakes"; -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; +import { parseJsonConfigFileContent, readConfigFile } from "../../../compiler/commandLineParser"; +import { Map } from "../../../compiler/corePublic"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { combinePaths, getDirectoryPath } from "../../../compiler/path"; +import { + createProgram, flattenDiagnosticMessageText, parseConfigHostFromCompilerHostLike, +} from "../../../compiler/program"; +import { CompilerOptions, Diagnostic, DiagnosticMessage, Program, ProjectReference } from "../../../compiler/types"; +import { CompilerHost, System } from "../../../harness/fakesHosts"; +import { FileSystem } from "../../../harness/vfsUtil"; +import { libFile } from "../../../harness/virtualFileSystemWithWatch"; interface TestProjectSpecification { configFileName?: string; - references?: readonly (string | ts.ProjectReference)[]; + references?: readonly (string | ProjectReference)[]; files: { [fileName: string]: string }; outputFiles?: { [fileName: string]: string }; config?: object; - options?: Partial; + options?: Partial; } interface TestSpecification { [path: string]: TestProjectSpecification; } -function assertHasError(message: string, errors: readonly ts.Diagnostic[], diag: ts.DiagnosticMessage) { +function assertHasError(message: string, errors: readonly Diagnostic[], diag: DiagnosticMessage) { if (!errors.some(e => e.code === diag.code)) { const errorString = errors.map(e => ` ${e.file ? e.file.fileName : "[global]"}: ${e.messageText}`).join("\r\n"); assert(false, `${message}: Did not find any diagnostic for ${diag.message} in:\r\n${errorString}`); } } -function assertNoErrors(message: string, errors: readonly ts.Diagnostic[]) { +function assertNoErrors(message: string, errors: readonly Diagnostic[]) { if (errors && errors.length > 0) { assert(false, `${message}: Expected no errors, but found:\r\n${errors.map(e => ` ${e.messageText}`).join("\r\n")}`); } @@ -30,7 +38,7 @@ function assertNoErrors(message: string, errors: readonly ts.Diagnostic[]) { function combineAllPaths(...paths: string[]) { let result = paths[0]; for (let i = 1; i < paths.length; i++) { - result = ts.combinePaths(result, paths[i]); + result = combinePaths(result, paths[i]); } return result; } @@ -45,8 +53,8 @@ function moduleImporting(...names: string[]) { return names.map((n, i) => `import * as mod_${i} from ${n}`).join("\r\n"); } -function testProjectReferences(spec: TestSpecification, entryPointConfigFileName: string, checkResult: (prog: ts.Program, host: fakes.CompilerHost) => void) { - const files = new ts.Map(); +function testProjectReferences(spec: TestSpecification, entryPointConfigFileName: string, checkResult: (prog: Program, host: CompilerHost) => void) { + const files = new Map(); for (const key in spec) { const sp = spec[key]; const configFileName = combineAllPaths("/", key, sp.configFileName || "tsconfig.json"); @@ -77,20 +85,20 @@ function testProjectReferences(spec: TestSpecification, entryPointConfigFileName } } - const vfsys = new vfs.FileSystem(false, { files: { "/lib.d.ts": ts.TestFSWithWatch.libFile.content } }); + const vfsys = new FileSystem(false, { files: { "/lib.d.ts": libFile.content } }); files.forEach((v, k) => { - vfsys.mkdirpSync(ts.getDirectoryPath(k)); + vfsys.mkdirpSync(getDirectoryPath(k)); vfsys.writeFileSync(k, v); }); - const host = new fakes.CompilerHost(new fakes.System(vfsys)); + const host = new CompilerHost(new System(vfsys)); - const { config, error } = ts.readConfigFile(entryPointConfigFileName, name => host.readFile(name)); + const { config, error } = readConfigFile(entryPointConfigFileName, name => host.readFile(name)); // We shouldn't have any errors about invalid tsconfig files in these tests - assert(config && !error, ts.flattenDiagnosticMessageText(error && error.messageText, "\n")); - const file = ts.parseJsonConfigFileContent(config, ts.parseConfigHostFromCompilerHostLike(host), ts.getDirectoryPath(entryPointConfigFileName), {}, entryPointConfigFileName); + assert(config && !error, flattenDiagnosticMessageText(error && error.messageText, "\n")); + const file = parseJsonConfigFileContent(config, parseConfigHostFromCompilerHostLike(host), getDirectoryPath(entryPointConfigFileName), {}, entryPointConfigFileName); file.options.configFilePath = entryPointConfigFileName; - const prog = ts.createProgram({ + const prog = createProgram({ rootNames: file.fileNames, options: file.options, host, @@ -135,7 +143,7 @@ describe("unittests:: config:: project-references constraint checking for settin testProjectReferences(spec, "/primary/tsconfig.json", program => { const errs = program.getOptionsDiagnostics(); - assertHasError("Reports an error about the wrong decl setting", errs, ts.Diagnostics.Composite_projects_may_not_disable_declaration_emit); + assertHasError("Reports an error about the wrong decl setting", errs, Diagnostics.Composite_projects_may_not_disable_declaration_emit); }); }); @@ -158,7 +166,7 @@ describe("unittests:: config:: project-references constraint checking for settin }; testProjectReferences(spec, "/reference/tsconfig.json", program => { const errs = program.getOptionsDiagnostics(); - assertHasError("Reports an error about 'composite' not being set", errs, ts.Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true); + assertHasError("Reports an error about 'composite' not being set", errs, Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true); }); }); @@ -197,7 +205,7 @@ describe("unittests:: config:: project-references constraint checking for settin testProjectReferences(spec, "/primary/tsconfig.json", program => { const errs = program.getSemanticDiagnostics(program.getSourceFile("/primary/a.ts")); - assertHasError("Reports an error about b.ts not being in the list", errs, ts.Diagnostics.File_0_is_not_listed_within_the_file_list_of_project_1_Projects_must_list_all_files_or_use_an_include_pattern); + assertHasError("Reports an error about b.ts not being in the list", errs, Diagnostics.File_0_is_not_listed_within_the_file_list_of_project_1_Projects_must_list_all_files_or_use_an_include_pattern); }); }); @@ -210,7 +218,7 @@ describe("unittests:: config:: project-references constraint checking for settin }; testProjectReferences(spec, "/primary/tsconfig.json", program => { const errs = program.getOptionsDiagnostics(); - assertHasError("Reports an error about a missing file", errs, ts.Diagnostics.File_0_not_found); + assertHasError("Reports an error about a missing file", errs, Diagnostics.File_0_not_found); }); }); @@ -226,7 +234,7 @@ describe("unittests:: config:: project-references constraint checking for settin }; testProjectReferences(spec, "/primary/tsconfig.json", program => { const errs = program.getOptionsDiagnostics(); - assertHasError("Reports an error about outFile not being set", errs, ts.Diagnostics.Cannot_prepend_project_0_because_it_does_not_have_outFile_set); + assertHasError("Reports an error about outFile not being set", errs, Diagnostics.Cannot_prepend_project_0_because_it_does_not_have_outFile_set); }); }); @@ -243,7 +251,7 @@ describe("unittests:: config:: project-references constraint checking for settin }; testProjectReferences(spec, "/primary/tsconfig.json", program => { const errs = program.getOptionsDiagnostics(); - assertHasError("Reports an error about outFile being missing", errs, ts.Diagnostics.Output_file_0_from_project_1_does_not_exist); + assertHasError("Reports an error about outFile being missing", errs, Diagnostics.Output_file_0_from_project_1_does_not_exist); }); }); }); @@ -266,7 +274,7 @@ describe("unittests:: config:: project-references path mapping", () => { }; testProjectReferences(spec, "/beta/tsconfig.json", program => { assertNoErrors("File setup should be correct", program.getOptionsDiagnostics()); - assertHasError("Found a type error", program.getSemanticDiagnostics(), ts.Diagnostics.Module_0_has_no_exported_member_1); + assertHasError("Found a type error", program.getSemanticDiagnostics(), Diagnostics.Module_0_has_no_exported_member_1); }); }); }); @@ -284,7 +292,7 @@ describe("unittests:: config:: project-references nice-behavior", () => { } }; testProjectReferences(spec, "/beta/tsconfig.json", program => { - assertHasError("Issues a useful error", program.getSemanticDiagnostics(), ts.Diagnostics.Output_file_0_has_not_been_built_from_source_file_1); + assertHasError("Issues a useful error", program.getSemanticDiagnostics(), Diagnostics.Output_file_0_has_not_been_built_from_source_file_1); }); }); @@ -306,7 +314,7 @@ describe("unittests:: config:: project-references nice-behavior", () => { } }; testProjectReferences(spec, "/beta/tsconfig.json", program => { - assertHasError("Issues a useful error", program.getSemanticDiagnostics(), ts.Diagnostics.Output_file_0_has_not_been_built_from_source_file_1); + assertHasError("Issues a useful error", program.getSemanticDiagnostics(), Diagnostics.Output_file_0_has_not_been_built_from_source_file_1); }); }); }); @@ -347,8 +355,8 @@ describe("unittests:: config:: project-references errors when a file in a compos }; testProjectReferences(spec, "/alpha/tsconfig.json", (program) => { const semanticDiagnostics = program.getSemanticDiagnostics(program.getSourceFile("/alpha/src/a.ts")); - assertHasError("Issues an error about the rootDir", semanticDiagnostics, ts.Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files); - assertHasError("Issues an error about the fileList", semanticDiagnostics, ts.Diagnostics.File_0_is_not_listed_within_the_file_list_of_project_1_Projects_must_list_all_files_or_use_an_include_pattern); + assertHasError("Issues an error about the rootDir", semanticDiagnostics, Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files); + assertHasError("Issues an error about the fileList", semanticDiagnostics, Diagnostics.File_0_is_not_listed_within_the_file_list_of_project_1_Projects_must_list_all_files_or_use_an_include_pattern); }); }); }); diff --git a/src/testRunner/unittests/config/showConfig.ts b/src/testRunner/unittests/config/showConfig.ts index 2025fc3e36deb..0b10de78aa5aa 100644 --- a/src/testRunner/unittests/config/showConfig.ts +++ b/src/testRunner/unittests/config/showConfig.ts @@ -1,5 +1,13 @@ -import * as Harness from "../../_namespaces/Harness"; -import * as ts from "../../_namespaces/ts"; +import { + convertToTSConfig, getParsedCommandLineOfConfigFile, optionDeclarations, optionsForWatch, parseCommandLine, + ParseConfigFileHost, +} from "../../../compiler/commandLineParser"; +import { Comparison } from "../../../compiler/corePublic"; +import { Debug } from "../../../compiler/debug"; +import { combinePaths, comparePaths, getNormalizedAbsolutePath } from "../../../compiler/path"; +import { flattenDiagnosticMessageText } from "../../../compiler/program"; +import { CommandLineOption } from "../../../compiler/types"; +import { Baseline } from "../../../harness/harnessIO"; describe("unittests:: config:: showConfig", () => { function showTSConfigCorrectly(name: string, commandLinesArgs: string[], configJson?: object) { @@ -8,31 +16,31 @@ describe("unittests:: config:: showConfig", () => { it(`Correct output for ${outputFileName}`, () => { const cwd = `/${name}`; - const configPath = ts.combinePaths(cwd, "tsconfig.json"); + const configPath = combinePaths(cwd, "tsconfig.json"); const configContents = configJson ? JSON.stringify(configJson) : undefined; - const configParseHost: ts.ParseConfigFileHost = { + const configParseHost: ParseConfigFileHost = { fileExists: path => - ts.comparePaths(ts.getNormalizedAbsolutePath(path, cwd), configPath) === ts.Comparison.EqualTo ? true : false, + comparePaths(getNormalizedAbsolutePath(path, cwd), configPath) === Comparison.EqualTo ? true : false, getCurrentDirectory() { return cwd; }, useCaseSensitiveFileNames: true, onUnRecoverableConfigFileDiagnostic: d => { - throw new Error(ts.flattenDiagnosticMessageText(d.messageText, "\n")); + throw new Error(flattenDiagnosticMessageText(d.messageText, "\n")); }, readDirectory() { return []; }, readFile: path => - ts.comparePaths(ts.getNormalizedAbsolutePath(path, cwd), configPath) === ts.Comparison.EqualTo ? configContents : undefined, + comparePaths(getNormalizedAbsolutePath(path, cwd), configPath) === Comparison.EqualTo ? configContents : undefined, }; - let commandLine = ts.parseCommandLine(commandLinesArgs); + let commandLine = parseCommandLine(commandLinesArgs); if (commandLine.options.project) { - const result = ts.getParsedCommandLineOfConfigFile(commandLine.options.project, commandLine.options, configParseHost); + const result = getParsedCommandLineOfConfigFile(commandLine.options.project, commandLine.options, configParseHost); if (result) { commandLine = result; } } - const initResult = ts.convertToTSConfig(commandLine, configPath, configParseHost); + const initResult = convertToTSConfig(commandLine, configPath, configParseHost); // eslint-disable-next-line no-null/no-null - Harness.Baseline.runBaseline(outputFileName, JSON.stringify(initResult, null, 4) + "\n"); + Baseline.runBaseline(outputFileName, JSON.stringify(initResult, null, 4) + "\n"); }); }); } @@ -114,15 +122,15 @@ describe("unittests:: config:: showConfig", () => { }); // Bulk validation of all option declarations - for (const option of ts.optionDeclarations) { + for (const option of optionDeclarations) { baselineOption(option, /*isCompilerOptions*/ true); } - for (const option of ts.optionsForWatch) { + for (const option of optionsForWatch) { baselineOption(option, /*isCompilerOptions*/ false); } - function baselineOption(option: ts.CommandLineOption, isCompilerOptions: boolean) { + function baselineOption(option: CommandLineOption, isCompilerOptions: boolean) { if (option.name === "project") return; let args: string[]; let optionValue: object | undefined; @@ -174,7 +182,7 @@ describe("unittests:: config:: showConfig", () => { } default: { const iterResult = option.type.keys().next(); - if (iterResult.done) return ts.Debug.fail("Expected 'option.type' to have entries"); + if (iterResult.done) return Debug.fail("Expected 'option.type' to have entries"); const val = iterResult.value; if (option.isTSConfigOnly) { args = ["-p", "tsconfig.json"]; diff --git a/src/testRunner/unittests/config/tsconfigParsing.ts b/src/testRunner/unittests/config/tsconfigParsing.ts index a3ef83e46568f..60d6f6b5096ba 100644 --- a/src/testRunner/unittests/config/tsconfigParsing.ts +++ b/src/testRunner/unittests/config/tsconfigParsing.ts @@ -1,50 +1,58 @@ +import { + convertToObject, parseConfigFileTextToJson, parseJsonConfigFileContent, parseJsonSourceFileConfigFileContent, +} from "../../../compiler/commandLineParser"; +import { arrayIsEqualTo } from "../../../compiler/core"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { parseJsonText } from "../../../compiler/parser"; +import { sys } from "../../../compiler/sys"; +import { Diagnostic, ParseConfigHost, WatchDirectoryFlags } from "../../../compiler/types"; +import { createCompilerDiagnostic } from "../../../compiler/utilities"; +import { FileSet, FileSystem } from "../../../harness/vfsUtil"; import * as fakes from "../../_namespaces/fakes"; -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; describe("unittests:: config:: tsconfigParsing:: parseConfigFileTextToJson", () => { - function assertParseResult(jsonText: string, expectedConfigObject: { config?: any; error?: ts.Diagnostic[] }) { - const parsed = ts.parseConfigFileTextToJson("/apath/tsconfig.json", jsonText); + function assertParseResult(jsonText: string, expectedConfigObject: { config?: any; error?: Diagnostic[] }) { + const parsed = parseConfigFileTextToJson("/apath/tsconfig.json", jsonText); assert.equal(JSON.stringify(parsed), JSON.stringify(expectedConfigObject)); } function assertParseErrorWithExcludesKeyword(jsonText: string) { { - const parsed = ts.parseConfigFileTextToJson("/apath/tsconfig.json", jsonText); - const parsedCommand = ts.parseJsonConfigFileContent(parsed.config, ts.sys, "tests/cases/unittests"); + const parsed = parseConfigFileTextToJson("/apath/tsconfig.json", jsonText); + const parsedCommand = parseJsonConfigFileContent(parsed.config, sys, "tests/cases/unittests"); assert.isTrue(parsedCommand.errors && parsedCommand.errors.length === 1 && - parsedCommand.errors[0].code === ts.Diagnostics.Unknown_option_excludes_Did_you_mean_exclude.code); + parsedCommand.errors[0].code === Diagnostics.Unknown_option_excludes_Did_you_mean_exclude.code); } { - const parsed = ts.parseJsonText("/apath/tsconfig.json", jsonText); - const parsedCommand = ts.parseJsonSourceFileConfigFileContent(parsed, ts.sys, "tests/cases/unittests"); + const parsed = parseJsonText("/apath/tsconfig.json", jsonText); + const parsedCommand = parseJsonSourceFileConfigFileContent(parsed, sys, "tests/cases/unittests"); assert.isTrue(parsedCommand.errors && parsedCommand.errors.length === 1 && - parsedCommand.errors[0].code === ts.Diagnostics.Unknown_option_excludes_Did_you_mean_exclude.code); + parsedCommand.errors[0].code === Diagnostics.Unknown_option_excludes_Did_you_mean_exclude.code); } } function getParsedCommandJson(jsonText: string, configFileName: string, basePath: string, allFileList: string[]) { - const parsed = ts.parseConfigFileTextToJson(configFileName, jsonText); - const files = allFileList.reduce((files, value) => (files[value] = "", files), {} as vfs.FileSet); - const host: ts.ParseConfigHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ false, { cwd: basePath, files: { "/": {}, ...files } })); - return ts.parseJsonConfigFileContent(parsed.config, host, basePath, /*existingOptions*/ undefined, configFileName); + const parsed = parseConfigFileTextToJson(configFileName, jsonText); + const files = allFileList.reduce((files, value) => (files[value] = "", files), {} as FileSet); + const host: ParseConfigHost = new fakes.ParseConfigHost(new FileSystem(/*ignoreCase*/ false, { cwd: basePath, files: { "/": {}, ...files } })); + return parseJsonConfigFileContent(parsed.config, host, basePath, /*existingOptions*/ undefined, configFileName); } function getParsedCommandJsonNode(jsonText: string, configFileName: string, basePath: string, allFileList: string[]) { - const parsed = ts.parseJsonText(configFileName, jsonText); - const files = allFileList.reduce((files, value) => (files[value] = "", files), {} as vfs.FileSet); - const host: ts.ParseConfigHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ false, { cwd: basePath, files: { "/": {}, ...files } })); - return ts.parseJsonSourceFileConfigFileContent(parsed, host, basePath, /*existingOptions*/ undefined, configFileName); + const parsed = parseJsonText(configFileName, jsonText); + const files = allFileList.reduce((files, value) => (files[value] = "", files), {} as FileSet); + const host: ParseConfigHost = new fakes.ParseConfigHost(new FileSystem(/*ignoreCase*/ false, { cwd: basePath, files: { "/": {}, ...files } })); + return parseJsonSourceFileConfigFileContent(parsed, host, basePath, /*existingOptions*/ undefined, configFileName); } function assertParseFileList(jsonText: string, configFileName: string, basePath: string, allFileList: string[], expectedFileList: string[]) { { const parsed = getParsedCommandJson(jsonText, configFileName, basePath, allFileList); - assert.isTrue(ts.arrayIsEqualTo(parsed.fileNames.sort(), expectedFileList.sort())); + assert.isTrue(arrayIsEqualTo(parsed.fileNames.sort(), expectedFileList.sort())); } { const parsed = getParsedCommandJsonNode(jsonText, configFileName, basePath, allFileList); - assert.isTrue(ts.arrayIsEqualTo(parsed.fileNames.sort(), expectedFileList.sort())); + assert.isTrue(arrayIsEqualTo(parsed.fileNames.sort(), expectedFileList.sort())); } } @@ -143,9 +151,9 @@ describe("unittests:: config:: tsconfigParsing:: parseConfigFileTextToJson", () }); it("returns object with error when json is invalid", () => { - const parsed = ts.parseConfigFileTextToJson("/apath/tsconfig.json", "invalid"); + const parsed = parseConfigFileTextToJson("/apath/tsconfig.json", "invalid"); assert.deepEqual(parsed.config, {}); - const expected = ts.createCompilerDiagnostic(ts.Diagnostics._0_expected, "{"); + const expected = createCompilerDiagnostic(Diagnostics._0_expected, "{"); const error = parsed.error!; assert.equal(error.messageText, expected.messageText); assert.equal(error.category, expected.category); @@ -271,9 +279,9 @@ describe("unittests:: config:: tsconfigParsing:: parseConfigFileTextToJson", () } "files": ["file1.ts"] }`; - const result = ts.parseJsonText("config.json", content); + const result = parseJsonText("config.json", content); const diagnostics = result.parseDiagnostics; - const configJsonObject = ts.convertToObject(result, diagnostics); + const configJsonObject = convertToObject(result, diagnostics); const expectedResult = { compilerOptions: { allowJs: true, @@ -293,7 +301,7 @@ describe("unittests:: config:: tsconfigParsing:: parseConfigFileTextToJson", () "/apath/tsconfig.json", "tests/cases/unittests", ["/apath/a.ts"], - ts.Diagnostics.The_files_list_in_config_file_0_is_empty.code); + Diagnostics.The_files_list_in_config_file_0_is_empty.code); }); it("generates errors for empty files list when no references are provided", () => { @@ -305,7 +313,7 @@ describe("unittests:: config:: tsconfigParsing:: parseConfigFileTextToJson", () "/apath/tsconfig.json", "tests/cases/unittests", ["/apath/a.ts"], - ts.Diagnostics.The_files_list_in_config_file_0_is_empty.code); + Diagnostics.The_files_list_in_config_file_0_is_empty.code); }); it("does not generate errors for empty files list when one or more references are provided", () => { @@ -317,7 +325,7 @@ describe("unittests:: config:: tsconfigParsing:: parseConfigFileTextToJson", () "/apath/tsconfig.json", "tests/cases/unittests", ["/apath/a.ts"], - ts.Diagnostics.The_files_list_in_config_file_0_is_empty.code); + Diagnostics.The_files_list_in_config_file_0_is_empty.code); }); it("generates errors for directory with no .ts files", () => { @@ -327,7 +335,7 @@ describe("unittests:: config:: tsconfigParsing:: parseConfigFileTextToJson", () "/apath/tsconfig.json", "tests/cases/unittests", ["/apath/a.js"], - ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code, + Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code, /*noLocation*/ true); }); @@ -341,7 +349,7 @@ describe("unittests:: config:: tsconfigParsing:: parseConfigFileTextToJson", () "/apath/tsconfig.json", "tests/cases/unittests", [], - ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code, + Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code, /*noLocation*/ true); }); @@ -353,7 +361,7 @@ describe("unittests:: config:: tsconfigParsing:: parseConfigFileTextToJson", () "/apath/tsconfig.json", "tests/cases/unittests", ["/apath/a.ts"], - ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code, + Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code, /*noLocation*/ true); }); @@ -368,7 +376,7 @@ describe("unittests:: config:: tsconfigParsing:: parseConfigFileTextToJson", () "/apath/tsconfig.json", "tests/cases/unittests", ["/apath/a.ts"], - ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code, + Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code, /*noLocation*/ true); }); @@ -398,7 +406,7 @@ describe("unittests:: config:: tsconfigParsing:: parseConfigFileTextToJson", () "/apath/tsconfig.json", "tests/cases/unittests", ["/apath/a.ts"], - ts.Diagnostics.Compiler_option_0_requires_a_value_of_type_1.code, + Diagnostics.Compiler_option_0_requires_a_value_of_type_1.code, /*noLocation*/ true); }); @@ -412,17 +420,17 @@ describe("unittests:: config:: tsconfigParsing:: parseConfigFileTextToJson", () "/apath/tsconfig.json", "tests/cases/unittests", ["/apath/a.ts"], - ts.Diagnostics.Compiler_option_0_requires_a_value_of_type_1.code, + Diagnostics.Compiler_option_0_requires_a_value_of_type_1.code, /*noLocation*/ true); }); it("parses wildcard directories even when parent directories have dots", () => { - const parsed = ts.parseConfigFileTextToJson("/foo.bar/tsconfig.json", JSON.stringify({ + const parsed = parseConfigFileTextToJson("/foo.bar/tsconfig.json", JSON.stringify({ include: ["src"] })); - const parsedCommand = ts.parseJsonConfigFileContent(parsed.config, ts.sys, "/foo.bar"); - assert.deepEqual(parsedCommand.wildcardDirectories, { "/foo.bar/src": ts.WatchDirectoryFlags.Recursive }); + const parsedCommand = parseJsonConfigFileContent(parsed.config, sys, "/foo.bar"); + assert.deepEqual(parsedCommand.wildcardDirectories, { "/foo.bar/src": WatchDirectoryFlags.Recursive }); }); }); diff --git a/src/testRunner/unittests/config/tsconfigParsingWatchOptions.ts b/src/testRunner/unittests/config/tsconfigParsingWatchOptions.ts index 7aa5fb4cfdee3..0e8b96b4cd0af 100644 --- a/src/testRunner/unittests/config/tsconfigParsingWatchOptions.ts +++ b/src/testRunner/unittests/config/tsconfigParsingWatchOptions.ts @@ -1,11 +1,17 @@ -import * as fakes from "../../_namespaces/fakes"; -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; +import { parseJsonConfigFileContent, parseJsonSourceFileConfigFileContent } from "../../../compiler/commandLineParser"; +import { length } from "../../../compiler/core"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { parseJsonText } from "../../../compiler/parser"; +import { + Diagnostic, PollingWatchKind, SourceFile, WatchDirectoryKind, WatchFileKind, WatchOptions, +} from "../../../compiler/types"; +import { ParseConfigHost } from "../../../harness/fakesHosts"; +import { FileSet, FileSystem } from "../../../harness/vfsUtil"; describe("unittests:: config:: tsconfigParsingWatchOptions:: parseConfigFileTextToJson", () => { - function createParseConfigHost(additionalFiles?: vfs.FileSet) { - return new fakes.ParseConfigHost( - new vfs.FileSystem( + function createParseConfigHost(additionalFiles?: FileSet) { + return new ParseConfigHost( + new FileSystem( /*ignoreCase*/ false, { cwd: "/", @@ -14,8 +20,8 @@ describe("unittests:: config:: tsconfigParsingWatchOptions:: parseConfigFileText ) ); } - function getParsedCommandJson(json: object, additionalFiles?: vfs.FileSet, existingWatchOptions?: ts.WatchOptions) { - return ts.parseJsonConfigFileContent( + function getParsedCommandJson(json: object, additionalFiles?: FileSet, existingWatchOptions?: WatchOptions) { + return parseJsonConfigFileContent( json, createParseConfigHost(additionalFiles), "/", @@ -28,9 +34,9 @@ describe("unittests:: config:: tsconfigParsingWatchOptions:: parseConfigFileText ); } - function getParsedCommandJsonNode(json: object, additionalFiles?: vfs.FileSet, existingWatchOptions?: ts.WatchOptions) { - const parsed = ts.parseJsonText("tsconfig.json", JSON.stringify(json)); - return ts.parseJsonSourceFileConfigFileContent( + function getParsedCommandJsonNode(json: object, additionalFiles?: FileSet, existingWatchOptions?: WatchOptions) { + const parsed = parseJsonText("tsconfig.json", JSON.stringify(json)); + return parseJsonSourceFileConfigFileContent( parsed, createParseConfigHost(additionalFiles), "/", @@ -45,10 +51,10 @@ describe("unittests:: config:: tsconfigParsingWatchOptions:: parseConfigFileText interface VerifyWatchOptions { json: object; - expectedOptions: ts.WatchOptions | undefined; - additionalFiles?: vfs.FileSet; - existingWatchOptions?: ts.WatchOptions | undefined; - expectedErrors?: (sourceFile?: ts.SourceFile) => ts.Diagnostic[]; + expectedOptions: WatchOptions | undefined; + additionalFiles?: FileSet; + existingWatchOptions?: WatchOptions | undefined; + expectedErrors?: (sourceFile?: SourceFile) => Diagnostic[]; } function verifyWatchOptions(scenario: () => VerifyWatchOptions[]) { @@ -56,11 +62,11 @@ describe("unittests:: config:: tsconfigParsingWatchOptions:: parseConfigFileText for (const { json, expectedOptions, additionalFiles, existingWatchOptions, expectedErrors } of scenario()) { const parsed = getParsedCommandJson(json, additionalFiles, existingWatchOptions); assert.deepEqual(parsed.watchOptions, expectedOptions, `With ${JSON.stringify(json)}`); - if (ts.length(parsed.errors)) { + if (length(parsed.errors)) { assert.deepEqual(parsed.errors, expectedErrors?.()); } else { - assert.equal(0, ts.length(expectedErrors?.()), `Expected no errors`); + assert.equal(0, length(expectedErrors?.()), `Expected no errors`); } } }); @@ -69,11 +75,11 @@ describe("unittests:: config:: tsconfigParsingWatchOptions:: parseConfigFileText for (const { json, expectedOptions, additionalFiles, existingWatchOptions, expectedErrors } of scenario()) { const parsed = getParsedCommandJsonNode(json, additionalFiles, existingWatchOptions); assert.deepEqual(parsed.watchOptions, expectedOptions); - if (ts.length(parsed.errors)) { + if (length(parsed.errors)) { assert.deepEqual(parsed.errors, expectedErrors?.(parsed.options.configFile)); } else { - assert.equal(0, ts.length(expectedErrors?.(parsed.options.configFile)), `Expected no errors`); + assert.equal(0, length(expectedErrors?.(parsed.options.configFile)), `Expected no errors`); } } }); @@ -101,7 +107,7 @@ describe("unittests:: config:: tsconfigParsingWatchOptions:: parseConfigFileText extends: "./base.json", watchOptions: { watchFile: "UseFsEvents" } }, - expectedOptions: { watchFile: ts.WatchFileKind.UseFsEvents }, + expectedOptions: { watchFile: WatchFileKind.UseFsEvents }, additionalFiles: { "/base.json": "{}" } }, { @@ -122,8 +128,8 @@ describe("unittests:: config:: tsconfigParsingWatchOptions:: parseConfigFileText } }, expectedOptions: { - watchFile: ts.WatchFileKind.UseFsEvents, - watchDirectory: ts.WatchDirectoryKind.FixedPollingInterval + watchFile: WatchFileKind.UseFsEvents, + watchDirectory: WatchDirectoryKind.FixedPollingInterval }, additionalFiles: { "/base.json": JSON.stringify({ @@ -139,8 +145,8 @@ describe("unittests:: config:: tsconfigParsingWatchOptions:: parseConfigFileText extends: "./base.json", }, expectedOptions: { - watchFile: ts.WatchFileKind.UseFsEventsOnParentDirectory, - watchDirectory: ts.WatchDirectoryKind.FixedPollingInterval + watchFile: WatchFileKind.UseFsEventsOnParentDirectory, + watchDirectory: WatchDirectoryKind.FixedPollingInterval }, additionalFiles: { "/base.json": JSON.stringify({ @@ -159,15 +165,15 @@ describe("unittests:: config:: tsconfigParsingWatchOptions:: parseConfigFileText verifyWatchOptions(() => [ { json: { watchOptions: { watchFile: "UseFsEvents" } }, - expectedOptions: { watchFile: ts.WatchFileKind.UseFsEvents } + expectedOptions: { watchFile: WatchFileKind.UseFsEvents } }, { json: { watchOptions: { watchDirectory: "UseFsEvents" } }, - expectedOptions: { watchDirectory: ts.WatchDirectoryKind.UseFsEvents } + expectedOptions: { watchDirectory: WatchDirectoryKind.UseFsEvents } }, { json: { watchOptions: { fallbackPolling: "DynamicPriority" } }, - expectedOptions: { fallbackPolling: ts.PollingWatchKind.DynamicPriority } + expectedOptions: { fallbackPolling: PollingWatchKind.DynamicPriority } }, { json: { watchOptions: { synchronousWatchDirectory: true } }, @@ -187,8 +193,8 @@ describe("unittests:: config:: tsconfigParsingWatchOptions:: parseConfigFileText expectedErrors: sourceFile => [ { messageText: `File specification cannot contain a parent directory ('..') that appears after a recursive directory wildcard ('**'): '**/../*'.`, - category: ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.category, - code: ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.code, + category: Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.category, + code: Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.code, file: sourceFile, start: sourceFile && sourceFile.text.indexOf(`"**/../*"`), length: sourceFile && `"**/../*"`.length, @@ -203,8 +209,8 @@ describe("unittests:: config:: tsconfigParsingWatchOptions:: parseConfigFileText expectedErrors: sourceFile => [ { messageText: `File specification cannot contain a parent directory ('..') that appears after a recursive directory wildcard ('**'): '**/../*'.`, - category: ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.category, - code: ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.code, + category: Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.category, + code: Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.code, file: sourceFile, start: sourceFile && sourceFile.text.indexOf(`"**/../*"`), length: sourceFile && `"**/../*"`.length, @@ -220,13 +226,13 @@ describe("unittests:: config:: tsconfigParsingWatchOptions:: parseConfigFileText verifyWatchOptions(() => [ { json: { watchOptions: { watchFile: "UseFsEvents" } }, - expectedOptions: { watchFile: ts.WatchFileKind.UseFsEvents, watchDirectory: ts.WatchDirectoryKind.FixedPollingInterval }, - existingWatchOptions: { watchDirectory: ts.WatchDirectoryKind.FixedPollingInterval } + expectedOptions: { watchFile: WatchFileKind.UseFsEvents, watchDirectory: WatchDirectoryKind.FixedPollingInterval }, + existingWatchOptions: { watchDirectory: WatchDirectoryKind.FixedPollingInterval } }, { json: {}, - expectedOptions: { watchDirectory: ts.WatchDirectoryKind.FixedPollingInterval }, - existingWatchOptions: { watchDirectory: ts.WatchDirectoryKind.FixedPollingInterval } + expectedOptions: { watchDirectory: WatchDirectoryKind.FixedPollingInterval }, + existingWatchOptions: { watchDirectory: WatchDirectoryKind.FixedPollingInterval } }, ]); }); diff --git a/src/testRunner/unittests/convertToBase64.ts b/src/testRunner/unittests/convertToBase64.ts index e55a0e1322a62..80160df35f770 100644 --- a/src/testRunner/unittests/convertToBase64.ts +++ b/src/testRunner/unittests/convertToBase64.ts @@ -1,9 +1,10 @@ -import * as ts from "../_namespaces/ts"; +import { sys } from "../../compiler/sys"; +import { convertToBase64 } from "../../compiler/utilities"; describe("unittests:: convertToBase64", () => { function runTest(input: string): void { - const actual = ts.convertToBase64(input); - const expected = ts.sys.base64encode!(input); + const actual = convertToBase64(input); + const expected = sys.base64encode!(input); assert.equal(actual, expected, "Encoded string using convertToBase64 does not match buffer.toString('base64')"); } diff --git a/src/testRunner/unittests/createMapShim.ts b/src/testRunner/unittests/createMapShim.ts index d1e7b1985a839..dae8985c7cf2b 100644 --- a/src/testRunner/unittests/createMapShim.ts +++ b/src/testRunner/unittests/createMapShim.ts @@ -1,3 +1,6 @@ +import { arrayFrom } from "../../compiler/core"; +import { ESMap, Iterator, Map, MapConstructor, ReadonlyESMap, ReadonlySet } from "../../compiler/corePublic"; +import { ShimCollections } from "../../shims/collectionShims"; import * as ts from "../_namespaces/ts"; describe("unittests:: createMapShim", () => { @@ -36,7 +39,7 @@ describe("unittests:: createMapShim", () => { "Y" ]; - function testMapIterationAddedValues(keys: K[], map: ts.ESMap, useForEach: boolean): string { + function testMapIterationAddedValues(keys: K[], map: ESMap, useForEach: boolean): string { let resultString = ""; map.set(keys[0], "1"); @@ -116,21 +119,21 @@ describe("unittests:: createMapShim", () => { return resultString; } - let MapShim!: ts.MapConstructor; + let MapShim!: MapConstructor; beforeEach(() => { - function getIterator | ts.ReadonlyESMap | undefined>(iterable: I): ts.Iterator< - I extends ts.ReadonlyESMap ? [K, V] : - I extends ts.ReadonlySet ? T : + 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>; - function getIterator(iterable: readonly any[] | ts.ReadonlySet | ts.ReadonlyESMap | undefined): ts.Iterator | undefined { + function getIterator(iterable: readonly any[] | ReadonlySet | ReadonlyESMap | undefined): Iterator | undefined { // override `ts.getIterator` with a version that allows us to iterate over a `MapShim` in an environment with a native `Map`. if (iterable instanceof MapShim) return iterable.entries(); return ts.getIterator(iterable); } - MapShim = ts.ShimCollections.createMapShim(getIterator); + MapShim = ShimCollections.createMapShim(getIterator); }); afterEach(() => { MapShim = undefined!; @@ -140,11 +143,11 @@ describe("unittests:: createMapShim", () => { const expectedResult = "1:1;3:3;2:Y2;4:X4;0:X0;3:Y3;999:999;A:A;Z:Z;X:X;Y:Y;"; // First, ensure the test actually has the same behavior as a native Map. - let nativeMap = new ts.Map(); + let nativeMap = new Map(); const nativeMapForEachResult = testMapIterationAddedValues(stringKeys, nativeMap, /* useForEach */ true); assert.equal(nativeMapForEachResult, expectedResult, "nativeMap-forEach"); - nativeMap = new ts.Map(); + nativeMap = new Map(); const nativeMapIteratorResult = testMapIterationAddedValues(stringKeys, nativeMap, /* useForEach */ false); assert.equal(nativeMapIteratorResult, expectedResult, "nativeMap-iterator"); @@ -162,11 +165,11 @@ describe("unittests:: createMapShim", () => { const expectedResult = "true:1;3:3;2:Y2;4:X4;false:X0;3:Y3;null:999;undefined:A;Z:Z;X:X;Y:Y;"; // First, ensure the test actually has the same behavior as a native Map. - let nativeMap = new ts.Map(); + let nativeMap = new Map(); const nativeMapForEachResult = testMapIterationAddedValues(mixedKeys, nativeMap, /* useForEach */ true); assert.equal(nativeMapForEachResult, expectedResult, "nativeMap-forEach"); - nativeMap = new ts.Map(); + nativeMap = new Map(); const nativeMapIteratorResult = testMapIterationAddedValues(mixedKeys, nativeMap, /* useForEach */ false); assert.equal(nativeMapIteratorResult, expectedResult, "nativeMap-iterator"); @@ -259,7 +262,7 @@ describe("unittests:: createMapShim", () => { const map = new MapShim(); map.set("a", "b"); map.delete("a"); - const actual = ts.arrayFrom(map.keys()); + const actual = arrayFrom(map.keys()); assert.deepEqual(actual, []); }); @@ -268,9 +271,9 @@ describe("unittests:: createMapShim", () => { map.set("a", "b"); map.set("c", "d"); map.delete("a"); - assert.deepEqual(ts.arrayFrom(map.keys()), ["c"]); - assert.deepEqual(ts.arrayFrom(map.values()), ["d"]); - assert.deepEqual(ts.arrayFrom(map.entries()), [["c", "d"]]); + assert.deepEqual(arrayFrom(map.keys()), ["c"]); + assert.deepEqual(arrayFrom(map.values()), ["d"]); + assert.deepEqual(arrayFrom(map.entries()), [["c", "d"]]); }); it("remove last item and iterate", () => { @@ -278,9 +281,9 @@ describe("unittests:: createMapShim", () => { map.set("a", "b"); map.set("c", "d"); map.delete("c"); - assert.deepEqual(ts.arrayFrom(map.keys()), ["a"]); - assert.deepEqual(ts.arrayFrom(map.values()), ["b"]); - assert.deepEqual(ts.arrayFrom(map.entries()), [["a", "b"]]); + assert.deepEqual(arrayFrom(map.keys()), ["a"]); + assert.deepEqual(arrayFrom(map.values()), ["b"]); + assert.deepEqual(arrayFrom(map.entries()), [["a", "b"]]); }); it("remove middle item and iterate", () => { @@ -289,30 +292,30 @@ describe("unittests:: createMapShim", () => { map.set("c", "d"); map.set("e", "f"); map.delete("c"); - assert.deepEqual(ts.arrayFrom(map.keys()), ["a", "e"]); - assert.deepEqual(ts.arrayFrom(map.values()), ["b", "f"]); - assert.deepEqual(ts.arrayFrom(map.entries()), [["a", "b"], ["e", "f"]]); + assert.deepEqual(arrayFrom(map.keys()), ["a", "e"]); + assert.deepEqual(arrayFrom(map.values()), ["b", "f"]); + assert.deepEqual(arrayFrom(map.entries()), [["a", "b"], ["e", "f"]]); }); it("keys", () => { const map = new MapShim(); map.set("c", "d"); map.set("a", "b"); - assert.deepEqual(ts.arrayFrom(map.keys()), ["c", "a"]); + assert.deepEqual(arrayFrom(map.keys()), ["c", "a"]); }); it("values", () => { const map = new MapShim(); map.set("c", "d"); map.set("a", "b"); - assert.deepEqual(ts.arrayFrom(map.values()), ["d", "b"]); + assert.deepEqual(arrayFrom(map.values()), ["d", "b"]); }); it("entries", () => { const map = new MapShim(); map.set("c", "d"); map.set("a", "b"); - assert.deepEqual(ts.arrayFrom(map.entries()), [["c", "d"], ["a", "b"]]); + assert.deepEqual(arrayFrom(map.entries()), [["c", "d"], ["a", "b"]]); }); it("forEach", () => { diff --git a/src/testRunner/unittests/createSetShim.ts b/src/testRunner/unittests/createSetShim.ts index 1a1ca47a9df31..6eb5ef8655138 100644 --- a/src/testRunner/unittests/createSetShim.ts +++ b/src/testRunner/unittests/createSetShim.ts @@ -1,3 +1,6 @@ +import { arrayFrom } from "../../compiler/core"; +import { Iterator, ReadonlyESMap, ReadonlySet, Set, SetConstructor } from "../../compiler/corePublic"; +import { ShimCollections } from "../../shims/collectionShims"; import * as ts from "../_namespaces/ts"; describe("unittests:: createSetShim", () => { @@ -35,7 +38,7 @@ describe("unittests:: createSetShim", () => { "Y" ]; - function testSetIterationAddedValues(keys: K[], set: ts.Set, useForEach: boolean): string { + function testSetIterationAddedValues(keys: K[], set: Set, useForEach: boolean): string { let resultString = ""; set.add(keys[0]); @@ -114,21 +117,21 @@ describe("unittests:: createSetShim", () => { return resultString; } - let SetShim!: ts.SetConstructor; + let SetShim!: SetConstructor; beforeEach(() => { - function getIterator | ts.ReadonlyESMap | undefined>(iterable: I): ts.Iterator< - I extends ts.ReadonlyESMap ? [K, V] : - I extends ts.ReadonlySet ? T : + 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>; - function getIterator(iterable: readonly any[] | ts.ReadonlySet | ts.ReadonlyESMap | undefined): ts.Iterator | undefined { + function getIterator(iterable: readonly any[] | ReadonlySet | ReadonlyESMap | undefined): Iterator | undefined { // override `ts.getIterator` with a version that allows us to iterate over a `SetShim` in an environment with a native `Set`. if (iterable instanceof SetShim) return iterable.values(); return ts.getIterator(iterable); } - SetShim = ts.ShimCollections.createSetShim(getIterator); + SetShim = ShimCollections.createSetShim(getIterator); }); afterEach(() => { SetShim = undefined!; @@ -138,11 +141,11 @@ describe("unittests:: createSetShim", () => { const expectedResult = "1;3;2;4;0;3;999;A;Z;X;Y;"; // First, ensure the test actually has the same behavior as a native Set. - let nativeSet = new ts.Set(); + let nativeSet = new Set(); const nativeSetForEachResult = testSetIterationAddedValues(stringKeys, nativeSet, /* useForEach */ true); assert.equal(nativeSetForEachResult, expectedResult, "nativeSet-forEach"); - nativeSet = new ts.Set(); + nativeSet = new Set(); const nativeSetIteratorResult = testSetIterationAddedValues(stringKeys, nativeSet, /* useForEach */ false); assert.equal(nativeSetIteratorResult, expectedResult, "nativeSet-iterator"); @@ -160,11 +163,11 @@ describe("unittests:: createSetShim", () => { const expectedResult = "true;3;2;4;false;3;null;undefined;Z;X;Y;"; // First, ensure the test actually has the same behavior as a native Set. - let nativeSet = new ts.Set(); + let nativeSet = new Set(); const nativeSetForEachResult = testSetIterationAddedValues(mixedKeys, nativeSet, /* useForEach */ true); assert.equal(nativeSetForEachResult, expectedResult, "nativeSet-forEach"); - nativeSet = new ts.Set(); + nativeSet = new Set(); const nativeSetIteratorResult = testSetIterationAddedValues(mixedKeys, nativeSet, /* useForEach */ false); assert.equal(nativeSetIteratorResult, expectedResult, "nativeSet-iterator"); @@ -242,7 +245,7 @@ describe("unittests:: createSetShim", () => { const set = new SetShim(); set.add("a"); set.delete("a"); - const actual = ts.arrayFrom(set.keys()); + const actual = arrayFrom(set.keys()); assert.deepEqual(actual, []); }); @@ -251,9 +254,9 @@ describe("unittests:: createSetShim", () => { set.add("a"); set.add("c"); set.delete("a"); - assert.deepEqual(ts.arrayFrom(set.keys()), ["c"]); - assert.deepEqual(ts.arrayFrom(set.values()), ["c"]); - assert.deepEqual(ts.arrayFrom(set.entries()), [["c", "c"]]); + assert.deepEqual(arrayFrom(set.keys()), ["c"]); + assert.deepEqual(arrayFrom(set.values()), ["c"]); + assert.deepEqual(arrayFrom(set.entries()), [["c", "c"]]); }); it("remove last item and iterate", () => { @@ -261,9 +264,9 @@ describe("unittests:: createSetShim", () => { set.add("a"); set.add("c"); set.delete("c"); - assert.deepEqual(ts.arrayFrom(set.keys()), ["a"]); - assert.deepEqual(ts.arrayFrom(set.values()), ["a"]); - assert.deepEqual(ts.arrayFrom(set.entries()), [["a", "a"]]); + assert.deepEqual(arrayFrom(set.keys()), ["a"]); + assert.deepEqual(arrayFrom(set.values()), ["a"]); + assert.deepEqual(arrayFrom(set.entries()), [["a", "a"]]); }); it("remove middle item and iterate", () => { @@ -272,30 +275,30 @@ describe("unittests:: createSetShim", () => { set.add("c"); set.add("e"); set.delete("c"); - assert.deepEqual(ts.arrayFrom(set.keys()), ["a", "e"]); - assert.deepEqual(ts.arrayFrom(set.values()), ["a", "e"]); - assert.deepEqual(ts.arrayFrom(set.entries()), [["a", "a"], ["e", "e"]]); + assert.deepEqual(arrayFrom(set.keys()), ["a", "e"]); + assert.deepEqual(arrayFrom(set.values()), ["a", "e"]); + assert.deepEqual(arrayFrom(set.entries()), [["a", "a"], ["e", "e"]]); }); it("keys", () => { const set = new SetShim(); set.add("c"); set.add("a"); - assert.deepEqual(ts.arrayFrom(set.keys()), ["c", "a"]); + assert.deepEqual(arrayFrom(set.keys()), ["c", "a"]); }); it("values", () => { const set = new SetShim(); set.add("c"); set.add("a"); - assert.deepEqual(ts.arrayFrom(set.values()), ["c", "a"]); + assert.deepEqual(arrayFrom(set.values()), ["c", "a"]); }); it("entries", () => { const set = new SetShim(); set.add("c"); set.add("a"); - assert.deepEqual(ts.arrayFrom(set.entries()), [["c", "c"], ["a", "a"]]); + assert.deepEqual(arrayFrom(set.entries()), [["c", "c"], ["a", "a"]]); }); it("forEach", () => { diff --git a/src/testRunner/unittests/customTransforms.ts b/src/testRunner/unittests/customTransforms.ts index 76da1b143f6f8..7f02d7197c041 100644 --- a/src/testRunner/unittests/customTransforms.ts +++ b/src/testRunner/unittests/customTransforms.ts @@ -1,13 +1,25 @@ -import * as Harness from "../_namespaces/Harness"; -import * as ts from "../_namespaces/ts"; +import { arrayFrom, arrayToMap, map } from "../../compiler/core"; +import { Map } from "../../compiler/corePublic"; +import { addSyntheticLeadingComment, setSourceMapRange } from "../../compiler/factory/emitNode"; +import { createSourceMapSource, factory } from "../../compiler/factory/nodeFactory"; +import { isIdentifier, isStringLiteral } from "../../compiler/factory/nodeTests"; +import { createSourceFile } from "../../compiler/parser"; +import { createProgram } from "../../compiler/program"; +import { computeLineAndCharacterOfPosition, computeLineStarts } from "../../compiler/scanner"; +import { + CompilerHost, CompilerOptions, CustomTransformers, FunctionDeclaration, ModuleKind, NewLineKind, Node, ScriptTarget, + SourceFile, SyntaxKind, Transformer, TransformerFactory, VariableStatement, VisitResult, +} from "../../compiler/types"; +import { visitEachChild, visitNode } from "../../compiler/visitorPublic"; +import { Baseline } from "../../harness/harnessIO"; describe("unittests:: customTransforms", () => { - function emitsCorrectly(name: string, sources: { file: string, text: string }[], customTransformers: ts.CustomTransformers, options: ts.CompilerOptions = {}) { + function emitsCorrectly(name: string, sources: { file: string, text: string }[], customTransformers: CustomTransformers, options: CompilerOptions = {}) { it(name, () => { - const roots = sources.map(source => ts.createSourceFile(source.file, source.text, ts.ScriptTarget.ES2015)); - const fileMap = ts.arrayToMap(roots, file => file.fileName); - const outputs = new ts.Map(); - const host: ts.CompilerHost = { + const roots = sources.map(source => createSourceFile(source.file, source.text, ScriptTarget.ES2015)); + const fileMap = arrayToMap(roots, file => file.fileName); + const outputs = new Map(); + const host: CompilerHost = { getSourceFile: (fileName) => fileMap.get(fileName), getDefaultLibFileName: () => "lib.d.ts", getCurrentDirectory: () => "", @@ -20,15 +32,15 @@ describe("unittests:: customTransforms", () => { writeFile: (fileName, text) => outputs.set(fileName, text), }; - const program = ts.createProgram(ts.arrayFrom(fileMap.keys()), { newLine: ts.NewLineKind.LineFeed, ...options }, host); + const program = createProgram(arrayFrom(fileMap.keys()), { newLine: NewLineKind.LineFeed, ...options }, host); program.emit(/*targetSourceFile*/ undefined, host.writeFile, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ false, customTransformers); let content = ""; - for (const [file, text] of ts.arrayFrom(outputs.entries())) { + for (const [file, text] of arrayFrom(outputs.entries())) { if (content) content += "\n\n"; content += `// [${file}]\n`; content += text; } - Harness.Baseline.runBaseline(`customTransforms/${name}.js`, content); + Baseline.runBaseline(`customTransforms/${name}.js`, content); }); } @@ -43,34 +55,34 @@ describe("unittests:: customTransforms", () => { ` }]; - const before: ts.TransformerFactory = context => { - return file => ts.visitEachChild(file, visit, context); - function visit(node: ts.Node): ts.VisitResult { + const before: TransformerFactory = context => { + return file => visitEachChild(file, visit, context); + function visit(node: Node): VisitResult { switch (node.kind) { - case ts.SyntaxKind.FunctionDeclaration: - return visitFunction(node as ts.FunctionDeclaration); + case SyntaxKind.FunctionDeclaration: + return visitFunction(node as FunctionDeclaration); default: - return ts.visitEachChild(node, visit, context); + return visitEachChild(node, visit, context); } } - function visitFunction(node: ts.FunctionDeclaration) { - ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, "@before", /*hasTrailingNewLine*/ true); + function visitFunction(node: FunctionDeclaration) { + addSyntheticLeadingComment(node, SyntaxKind.MultiLineCommentTrivia, "@before", /*hasTrailingNewLine*/ true); return node; } }; - const after: ts.TransformerFactory = context => { - return file => ts.visitEachChild(file, visit, context); - function visit(node: ts.Node): ts.VisitResult { + const after: TransformerFactory = context => { + return file => visitEachChild(file, visit, context); + function visit(node: Node): VisitResult { switch (node.kind) { - case ts.SyntaxKind.VariableStatement: - return visitVariableStatement(node as ts.VariableStatement); + case SyntaxKind.VariableStatement: + return visitVariableStatement(node as VariableStatement); default: - return ts.visitEachChild(node, visit, context); + return visitEachChild(node, visit, context); } } - function visitVariableStatement(node: ts.VariableStatement) { - ts.addSyntheticLeadingComment(node, ts.SyntaxKind.SingleLineCommentTrivia, "@after"); + function visitVariableStatement(node: VariableStatement) { + addSyntheticLeadingComment(node, SyntaxKind.SingleLineCommentTrivia, "@after"); return node; } }; @@ -88,13 +100,13 @@ describe("unittests:: customTransforms", () => { 'change' ` }], {before: [ - context => node => ts.visitNode(node, function visitor(node: ts.Node): ts.Node { - if (ts.isStringLiteral(node) && node.text === "change") return ts.factory.createStringLiteral("changed"); - return ts.visitEachChild(node, visitor, context); + context => node => visitNode(node, function visitor(node: Node): Node { + if (isStringLiteral(node) && node.text === "change") return factory.createStringLiteral("changed"); + return visitEachChild(node, visitor, context); }) ]}, { - target: ts.ScriptTarget.ES5, - module: ts.ModuleKind.ES2015, + target: ScriptTarget.ES5, + module: ModuleKind.ES2015, emitDecoratorMetadata: true, experimentalDecorators: true }); @@ -111,21 +123,21 @@ describe("unittests:: customTransforms", () => { ], { before: [ - context => node => ts.visitNode(node, function visitor(node: ts.Node): ts.Node { - if (ts.isStringLiteral(node) && node.text === "change") { + context => node => visitNode(node, function visitor(node: Node): Node { + if (isStringLiteral(node) && node.text === "change") { const text = "'changed'"; - const lineMap = ts.computeLineStarts(text); - ts.setSourceMapRange(node, { + const lineMap = computeLineStarts(text); + setSourceMapRange(node, { pos: 0, end: text.length, source: { text, fileName: "another.html", lineMap, - getLineAndCharacterOfPosition: pos => ts.computeLineAndCharacterOfPosition(lineMap, pos) + getLineAndCharacterOfPosition: pos => computeLineAndCharacterOfPosition(lineMap, pos) } }); return node; } - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); }) ] }, @@ -143,22 +155,22 @@ describe("unittests:: customTransforms", () => { { before: [ context => { - const transformSourceFile: ts.Transformer = node => ts.visitNode(node, function visitor(node: ts.Node): ts.Node { - if (ts.isIdentifier(node) && node.text === "original") { - const newNode = ts.factory.createIdentifier("changed"); - ts.setSourceMapRange(newNode, { + const transformSourceFile: Transformer = node => visitNode(node, function visitor(node: Node): Node { + if (isIdentifier(node) && node.text === "original") { + const newNode = factory.createIdentifier("changed"); + setSourceMapRange(newNode, { pos: 0, end: 7, // Do not provide a custom skipTrivia function for `source`. - source: ts.createSourceMapSource("another.html", "changed;") + source: createSourceMapSource("another.html", "changed;") }); return newNode; } - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); }); return { transformSourceFile, - transformBundle: node => ts.factory.createBundle(ts.map(node.sourceFiles, transformSourceFile), node.prepends), + transformBundle: node => factory.createBundle(map(node.sourceFiles, transformSourceFile), node.prepends), }; } ] diff --git a/src/testRunner/unittests/debugDeprecation.ts b/src/testRunner/unittests/debugDeprecation.ts index 953d9472e7bfc..53390c2b9c5b9 100644 --- a/src/testRunner/unittests/debugDeprecation.ts +++ b/src/testRunner/unittests/debugDeprecation.ts @@ -1,22 +1,23 @@ -import * as ts from "../_namespaces/ts"; +import { noop } from "../../compiler/core"; +import { Debug, LoggingHost } from "../../compiler/debug"; describe("unittests:: debugDeprecation", () => { - let loggingHost: ts.LoggingHost | undefined; + let loggingHost: LoggingHost | undefined; beforeEach(() => { - loggingHost = ts.Debug.loggingHost; + loggingHost = Debug.loggingHost; }); afterEach(() => { - ts.Debug.loggingHost = loggingHost; + Debug.loggingHost = loggingHost; loggingHost = undefined; }); describe("deprecateFunction", () => { it("silent deprecation", () => { - const deprecation = ts.Debug.deprecate(ts.noop, { + const deprecation = Debug.deprecate(noop, { warnAfter: "3.9", typeScriptVersion: "3.8" }); let logWritten = false; - ts.Debug.loggingHost = { + Debug.loggingHost = { log() { logWritten = true; } @@ -25,12 +26,12 @@ describe("unittests:: debugDeprecation", () => { assert.isFalse(logWritten); }); it("warning deprecation with warnAfter", () => { - const deprecation = ts.Debug.deprecate(ts.noop, { + const deprecation = Debug.deprecate(noop, { warnAfter: "3.9", typeScriptVersion: "3.9" }); let logWritten = false; - ts.Debug.loggingHost = { + Debug.loggingHost = { log() { logWritten = true; } @@ -39,11 +40,11 @@ describe("unittests:: debugDeprecation", () => { assert.isTrue(logWritten); }); it("warning deprecation without warnAfter", () => { - const deprecation = ts.Debug.deprecate(ts.noop, { + const deprecation = Debug.deprecate(noop, { typeScriptVersion: "3.9" }); let logWritten = false; - ts.Debug.loggingHost = { + Debug.loggingHost = { log() { logWritten = true; } @@ -52,11 +53,11 @@ describe("unittests:: debugDeprecation", () => { assert.isTrue(logWritten); }); it("warning deprecation writes once", () => { - const deprecation = ts.Debug.deprecate(ts.noop, { + const deprecation = Debug.deprecate(noop, { typeScriptVersion: "3.9" }); let logWrites = 0; - ts.Debug.loggingHost = { + Debug.loggingHost = { log() { logWrites++; } @@ -66,13 +67,13 @@ describe("unittests:: debugDeprecation", () => { assert.equal(logWrites, 1); }); it("error deprecation with errorAfter", () => { - const deprecation = ts.Debug.deprecate(ts.noop, { + const deprecation = Debug.deprecate(noop, { warnAfter: "3.8", errorAfter: "3.9", typeScriptVersion: "3.9" }); let logWritten = false; - ts.Debug.loggingHost = { + Debug.loggingHost = { log() { logWritten = true; } @@ -81,11 +82,11 @@ describe("unittests:: debugDeprecation", () => { assert.isFalse(logWritten); }); it("error deprecation with error", () => { - const deprecation = ts.Debug.deprecate(ts.noop, { + const deprecation = Debug.deprecate(noop, { error: true, }); let logWritten = false; - ts.Debug.loggingHost = { + Debug.loggingHost = { log() { logWritten = true; } diff --git a/src/testRunner/unittests/evaluation/arraySpread.ts b/src/testRunner/unittests/evaluation/arraySpread.ts index 8076cf1feaaef..71c162e47c3f5 100644 --- a/src/testRunner/unittests/evaluation/arraySpread.ts +++ b/src/testRunner/unittests/evaluation/arraySpread.ts @@ -1,8 +1,8 @@ -import * as evaluator from "../../_namespaces/evaluator"; +import { evaluateTypeScript } from "../../../harness/evaluatorImpl"; describe("unittests:: evaluation:: arraySpread", () => { it("array spread preserves side-effects", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` const k = [1, 2]; const o = [3, ...k, k[0]++]; export const output = o; @@ -10,7 +10,7 @@ describe("unittests:: evaluation:: arraySpread", () => { assert.deepEqual(result.output, [3, 1, 2, 1]); }); it("array spread packs spread elements", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` const k = [1, , 2]; const o = [3, ...k, 4]; export const output = o; @@ -19,7 +19,7 @@ describe("unittests:: evaluation:: arraySpread", () => { assert.hasAllKeys(result.output, ["0", "1", "2", "3", "4"]); }); it("array spread does not pack non-spread elements", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` const k = [1, 2]; const o = [3, , ...k, , 4]; export const output = o; @@ -29,7 +29,7 @@ describe("unittests:: evaluation:: arraySpread", () => { assert.doesNotHaveAllKeys(result.output, ["1", "4"]); }); it("argument spread pack does not matter", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` const f = (...args) => args; const k = [1, , 2]; const o = f(3, ...k, 4); diff --git a/src/testRunner/unittests/evaluation/asyncArrow.ts b/src/testRunner/unittests/evaluation/asyncArrow.ts index 6859eb2e89dd2..eb004f6c2ccc6 100644 --- a/src/testRunner/unittests/evaluation/asyncArrow.ts +++ b/src/testRunner/unittests/evaluation/asyncArrow.ts @@ -1,9 +1,9 @@ -import * as evaluator from "../../_namespaces/evaluator"; +import { evaluateTypeScript } from "../../../harness/evaluatorImpl"; describe("unittests:: evaluation:: asyncArrowEvaluation", () => { // https://github.com/Microsoft/TypeScript/issues/24722 it("this capture (es5)", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export class A { b = async (...args: any[]) => { await Promise.resolve(); diff --git a/src/testRunner/unittests/evaluation/asyncGenerator.ts b/src/testRunner/unittests/evaluation/asyncGenerator.ts index 65978895767f1..1aa45ff9ef089 100644 --- a/src/testRunner/unittests/evaluation/asyncGenerator.ts +++ b/src/testRunner/unittests/evaluation/asyncGenerator.ts @@ -1,9 +1,9 @@ -import * as evaluator from "../../_namespaces/evaluator"; -import * as ts from "../../_namespaces/ts"; +import { ScriptTarget } from "../../../compiler/types"; +import { evaluateTypeScript } from "../../../harness/evaluatorImpl"; describe("unittests:: evaluation:: asyncGeneratorEvaluation", () => { it("return (es5)", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` async function * g() { return Promise.resolve(0); } @@ -17,14 +17,14 @@ describe("unittests:: evaluation:: asyncGeneratorEvaluation", () => { ]); }); it("return (es2015)", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` async function * g() { return Promise.resolve(0); } export const output: any[] = []; export async function main() { output.push(await g().next()); - }`, { target: ts.ScriptTarget.ES2015 }); + }`, { target: ScriptTarget.ES2015 }); await result.main(); assert.deepEqual(result.output, [ { value: 0, done: true } diff --git a/src/testRunner/unittests/evaluation/awaiter.ts b/src/testRunner/unittests/evaluation/awaiter.ts index d18ea35263efd..36ad5ea0dbcfa 100644 --- a/src/testRunner/unittests/evaluation/awaiter.ts +++ b/src/testRunner/unittests/evaluation/awaiter.ts @@ -1,9 +1,9 @@ -import * as evaluator from "../../_namespaces/evaluator"; +import { evaluateTypeScript } from "../../../harness/evaluatorImpl"; describe("unittests:: evaluation:: awaiter", () => { // NOTE: This could break if the ECMAScript spec ever changes the timing behavior for Promises (again) it("await (es5)", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` async function a(msg: string) { await Promise.resolve(); output.push(msg); diff --git a/src/testRunner/unittests/evaluation/destructuring.ts b/src/testRunner/unittests/evaluation/destructuring.ts index 489fb0ae7db4c..a14fa54b5ab89 100644 --- a/src/testRunner/unittests/evaluation/destructuring.ts +++ b/src/testRunner/unittests/evaluation/destructuring.ts @@ -1,67 +1,67 @@ -import * as evaluator from "../../_namespaces/evaluator"; -import * as ts from "../../_namespaces/ts"; +import { ScriptTarget } from "../../../compiler/types"; +import { evaluateTypeScript } from "../../../harness/evaluatorImpl"; describe("unittests:: evaluation:: destructuring", () => { // https://github.com/microsoft/TypeScript/issues/39205 describe("correct order for array destructuring evaluation and initializers", () => { it("when element is undefined", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export const output: any[] = []; const order = (n: any): any => output.push(n); let [{ [order(1)]: x } = order(0)] = []; - `, { target: ts.ScriptTarget.ES5 }); + `, { target: ScriptTarget.ES5 }); assert.deepEqual(result.output, [0, 1]); }); it("when element is defined", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export const output: any[] = []; const order = (n: any): any => output.push(n); let [{ [order(1)]: x } = order(0)] = [{}]; - `, { target: ts.ScriptTarget.ES5 }); + `, { target: ScriptTarget.ES5 }); assert.deepEqual(result.output, [1]); }); }); describe("correct order for array destructuring evaluation and initializers with spread", () => { it("ES5", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export const output: any[] = []; const order = (n: any): any => output.push(n); let { [order(0)]: { [order(2)]: z } = order(1), ...w } = {} as any; - `, { target: ts.ScriptTarget.ES5 }); + `, { target: ScriptTarget.ES5 }); assert.deepEqual(result.output, [0, 1, 2]); }); it("ES2015", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export const output: any[] = []; const order = (n: any): any => output.push(n); let { [order(0)]: { [order(2)]: z } = order(1), ...w } = {} as any; - `, { target: ts.ScriptTarget.ES2015 }); + `, { target: ScriptTarget.ES2015 }); assert.deepEqual(result.output, [0, 1, 2]); }); }); describe("correct evaluation for nested rest assignment in destructured object", () => { it("ES5", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` let a: any, b: any, c: any = { x: { a: 1, y: 2 } }, d: any; ({ x: { a, ...b } = d } = c); export const output = { a, b }; - `, { target: ts.ScriptTarget.ES5 }); + `, { target: ScriptTarget.ES5 }); assert.deepEqual(result.output, { a: 1, b: { y: 2 } }); }); it("ES2015", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` let a: any, b: any, c: any = { x: { a: 1, y: 2 } }, d: any; ({ x: { a, ...b } = d } = c); export const output = { a, b }; - `, { target: ts.ScriptTarget.ES2015 }); + `, { target: ScriptTarget.ES2015 }); assert.deepEqual(result.output, { a: 1, b: { y: 2 } }); }); it("ES2018", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` let a: any, b: any, c: any = { x: { a: 1, y: 2 } }, d: any; ({ x: { a, ...b } = d } = c); export const output = { a, b }; - `, { target: ts.ScriptTarget.ES2018 }); + `, { target: ScriptTarget.ES2018 }); assert.deepEqual(result.output, { a: 1, b: { y: 2 } }); }); }); diff --git a/src/testRunner/unittests/evaluation/externalModules.ts b/src/testRunner/unittests/evaluation/externalModules.ts index 96a2c372d23e7..7baa81a4467c7 100644 --- a/src/testRunner/unittests/evaluation/externalModules.ts +++ b/src/testRunner/unittests/evaluation/externalModules.ts @@ -1,9 +1,9 @@ -import * as evaluator from "../../_namespaces/evaluator"; +import { evaluateTypeScript } from "../../../harness/evaluatorImpl"; describe("unittests:: evaluation:: externalModules", () => { // https://github.com/microsoft/TypeScript/issues/35420 it("Correct 'this' in function exported from external module", async () => { - const result = evaluator.evaluateTypeScript({ + const result = evaluateTypeScript({ files: { "/.src/output.ts": ` export const output: any[] = []; @@ -44,7 +44,7 @@ describe("unittests:: evaluation:: externalModules", () => { }); it("Correct 'this' in function expression exported from external module", async () => { - const result = evaluator.evaluateTypeScript({ + const result = evaluateTypeScript({ files: { "/.src/output.ts": ` export const output: any[] = []; diff --git a/src/testRunner/unittests/evaluation/forAwaitOf.ts b/src/testRunner/unittests/evaluation/forAwaitOf.ts index 34aff1ebc11c7..c63ae3c8f1bd4 100644 --- a/src/testRunner/unittests/evaluation/forAwaitOf.ts +++ b/src/testRunner/unittests/evaluation/forAwaitOf.ts @@ -1,9 +1,9 @@ -import * as evaluator from "../../_namespaces/evaluator"; -import * as ts from "../../_namespaces/ts"; +import { ScriptTarget } from "../../../compiler/types"; +import { evaluateTypeScript } from "../../../harness/evaluatorImpl"; describe("unittests:: evaluation:: forAwaitOfEvaluation", () => { it("sync (es5)", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` let i = 0; const iterator: IterableIterator = { [Symbol.iterator]() { return this; }, @@ -29,7 +29,7 @@ describe("unittests:: evaluation:: forAwaitOfEvaluation", () => { }); it("sync (es2015)", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` let i = 0; const iterator: IterableIterator = { [Symbol.iterator]() { return this; }, @@ -47,7 +47,7 @@ describe("unittests:: evaluation:: forAwaitOfEvaluation", () => { for await (const item of iterator) { output.push(item); } - }`, { target: ts.ScriptTarget.ES2015 }); + }`, { target: ScriptTarget.ES2015 }); await result.main(); assert.strictEqual(result.output[0], 1); assert.strictEqual(result.output[1], 2); @@ -55,7 +55,7 @@ describe("unittests:: evaluation:: forAwaitOfEvaluation", () => { }); it("async (es5)", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` let i = 0; const iterator = { [Symbol.asyncIterator](): AsyncIterableIterator { return this; }, @@ -81,7 +81,7 @@ describe("unittests:: evaluation:: forAwaitOfEvaluation", () => { }); it("async (es2015)", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` let i = 0; const iterator = { [Symbol.asyncIterator](): AsyncIterableIterator { return this; }, @@ -99,7 +99,7 @@ describe("unittests:: evaluation:: forAwaitOfEvaluation", () => { for await (const item of iterator) { output.push(item); } - }`, { target: ts.ScriptTarget.ES2015 }); + }`, { target: ScriptTarget.ES2015 }); await result.main(); assert.strictEqual(result.output[0], 1); assert.instanceOf(result.output[1], Promise); diff --git a/src/testRunner/unittests/evaluation/forOf.ts b/src/testRunner/unittests/evaluation/forOf.ts index 6e78a58bf953b..95fa329c9b147 100644 --- a/src/testRunner/unittests/evaluation/forOf.ts +++ b/src/testRunner/unittests/evaluation/forOf.ts @@ -1,9 +1,9 @@ -import * as evaluator from "../../_namespaces/evaluator"; -import * as ts from "../../_namespaces/ts"; +import { ScriptTarget } from "../../../compiler/types"; +import { evaluateTypeScript } from "../../../harness/evaluatorImpl"; describe("unittests:: evaluation:: forOfEvaluation", () => { it("es5 over a array with no Symbol", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` Symbol = undefined; export var output = []; export function main() { @@ -13,7 +13,7 @@ describe("unittests:: evaluation:: forOfEvaluation", () => { output.push(value); } } - `, { downlevelIteration: true, target: ts.ScriptTarget.ES5 }); + `, { downlevelIteration: true, target: ScriptTarget.ES5 }); result.main(); @@ -24,7 +24,7 @@ describe("unittests:: evaluation:: forOfEvaluation", () => { }); it("es5 over a string with no Symbol", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` Symbol = undefined; export var output = []; export function main() { @@ -34,7 +34,7 @@ describe("unittests:: evaluation:: forOfEvaluation", () => { output.push(value); } } - `, { downlevelIteration: true, target: ts.ScriptTarget.ES5 }); + `, { downlevelIteration: true, target: ScriptTarget.ES5 }); result.main(); @@ -46,7 +46,7 @@ describe("unittests:: evaluation:: forOfEvaluation", () => { }); it("es5 over undefined with no Symbol", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` Symbol = undefined; export function main() { let x = undefined; @@ -54,26 +54,26 @@ describe("unittests:: evaluation:: forOfEvaluation", () => { for (let value of x) { } } - `, { downlevelIteration: true, target: ts.ScriptTarget.ES5 }); + `, { downlevelIteration: true, target: ScriptTarget.ES5 }); assert.throws(() => result.main(), "Symbol.iterator is not defined"); }); it("es5 over undefined with Symbol", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export function main() { let x = undefined; for (let value of x) { } } - `, { downlevelIteration: true, target: ts.ScriptTarget.ES5 }); + `, { downlevelIteration: true, target: ScriptTarget.ES5 }); assert.throws(() => result.main(), /cannot read property.*Symbol\(Symbol\.iterator\).*/i); }); it("es5 over object with no Symbol.iterator with no Symbol", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` Symbol = undefined; export function main() { let x = {} as any; @@ -81,26 +81,26 @@ describe("unittests:: evaluation:: forOfEvaluation", () => { for (let value of x) { } } - `, { downlevelIteration: true, target: ts.ScriptTarget.ES5 }); + `, { downlevelIteration: true, target: ScriptTarget.ES5 }); assert.throws(() => result.main(), "Symbol.iterator is not defined"); }); it("es5 over object with no Symbol.iterator with Symbol", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export function main() { let x = {} as any; for (let value of x) { } } - `, { downlevelIteration: true, target: ts.ScriptTarget.ES5 }); + `, { downlevelIteration: true, target: ScriptTarget.ES5 }); assert.throws(() => result.main(), "Object is not iterable"); }); it("es5 over object with Symbol.iterator", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export var output = []; export function main() { let thing : any = {}; @@ -114,7 +114,7 @@ describe("unittests:: evaluation:: forOfEvaluation", () => { output.push(value) } - }`, { downlevelIteration: true, target: ts.ScriptTarget.ES5 }); + }`, { downlevelIteration: true, target: ScriptTarget.ES5 }); result.main(); }); diff --git a/src/testRunner/unittests/evaluation/objectRest.ts b/src/testRunner/unittests/evaluation/objectRest.ts index 7f00f19c19822..6827fc650d4a6 100644 --- a/src/testRunner/unittests/evaluation/objectRest.ts +++ b/src/testRunner/unittests/evaluation/objectRest.ts @@ -1,9 +1,9 @@ -import * as evaluator from "../../_namespaces/evaluator"; +import { evaluateTypeScript } from "../../../harness/evaluatorImpl"; describe("unittests:: evaluation:: objectRest", () => { // https://github.com/microsoft/TypeScript/issues/31469 it("side effects in property assignment", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` const k = { a: 1, b: 2 }; const o = { a: 3, ...k, b: k.a++ }; export const output = o; @@ -11,7 +11,7 @@ describe("unittests:: evaluation:: objectRest", () => { assert.deepEqual(result.output, { a: 1, b: 1 }); }); it("side effects in during spread", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` const k = { a: 1, get b() { l = { c: 9 }; return 2; } }; let l = { c: 3 }; const o = { ...k, ...l }; @@ -20,7 +20,7 @@ describe("unittests:: evaluation:: objectRest", () => { assert.deepEqual(result.output, { a: 1, b: 2, c: 9 }); }); it("trailing literal-valued object-literal", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` const k = { a: 1 } const o = { ...k, ...{ b: 2 } }; export const output = o; diff --git a/src/testRunner/unittests/evaluation/optionalCall.ts b/src/testRunner/unittests/evaluation/optionalCall.ts index fb9236755ed13..b8b5380361fc5 100644 --- a/src/testRunner/unittests/evaluation/optionalCall.ts +++ b/src/testRunner/unittests/evaluation/optionalCall.ts @@ -1,8 +1,8 @@ -import * as evaluator from "../../_namespaces/evaluator"; +import { evaluateTypeScript } from "../../../harness/evaluatorImpl"; describe("unittests:: evaluation:: optionalCall", () => { it("f?.()", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` function f(a) { output.push(a); output.push(this); @@ -14,7 +14,7 @@ describe("unittests:: evaluation:: optionalCall", () => { assert.isUndefined(result.output[1]); }); it("o.f?.()", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export const o = { f(a) { output.push(a); @@ -28,7 +28,7 @@ describe("unittests:: evaluation:: optionalCall", () => { assert.strictEqual(result.output[1], result.o); }); it("o.x.f?.()", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export const o = { x: { f(a) { @@ -44,7 +44,7 @@ describe("unittests:: evaluation:: optionalCall", () => { assert.strictEqual(result.output[1], result.o.x); }); it("o?.f()", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export const o = { f(a) { output.push(a); @@ -58,7 +58,7 @@ describe("unittests:: evaluation:: optionalCall", () => { assert.strictEqual(result.output[1], result.o); }); it("o?.f?.()", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export const o = { f(a) { output.push(a); @@ -72,7 +72,7 @@ describe("unittests:: evaluation:: optionalCall", () => { assert.strictEqual(result.output[1], result.o); }); it("o.x?.f()", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export const o = { x: { f(a) { @@ -88,7 +88,7 @@ describe("unittests:: evaluation:: optionalCall", () => { assert.strictEqual(result.output[1], result.o.x); }); it("o?.x.f()", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export const o = { x: { f(a) { @@ -104,7 +104,7 @@ describe("unittests:: evaluation:: optionalCall", () => { assert.strictEqual(result.output[1], result.o.x); }); it("o?.x?.f()", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export const o = { x: { f(a) { @@ -120,7 +120,7 @@ describe("unittests:: evaluation:: optionalCall", () => { assert.strictEqual(result.output[1], result.o.x); }); it("o?.x?.f?.()", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export const o = { x: { f(a) { @@ -136,7 +136,7 @@ describe("unittests:: evaluation:: optionalCall", () => { assert.strictEqual(result.output[1], result.o.x); }); it("f?.()?.()", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` function g(a) { output.push(a); output.push(this); @@ -153,7 +153,7 @@ describe("unittests:: evaluation:: optionalCall", () => { assert.isUndefined(result.output[2]); }); it("f?.().f?.()", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export const o = { f(a) { output.push(a); @@ -172,7 +172,7 @@ describe("unittests:: evaluation:: optionalCall", () => { assert.strictEqual(result.output[2], result.o); }); it("f?.()?.f?.()", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export const o = { f(a) { output.push(a); @@ -191,7 +191,7 @@ describe("unittests:: evaluation:: optionalCall", () => { assert.strictEqual(result.output[2], result.o); }); it("(o?.f)()", async () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export const foo = { bar() { return this } }; export const output = (foo?.bar)(); `); diff --git a/src/testRunner/unittests/evaluation/superInStaticInitializer.ts b/src/testRunner/unittests/evaluation/superInStaticInitializer.ts index f7c1e48e63ff3..d7c2e555f1303 100644 --- a/src/testRunner/unittests/evaluation/superInStaticInitializer.ts +++ b/src/testRunner/unittests/evaluation/superInStaticInitializer.ts @@ -1,9 +1,9 @@ -import * as evaluator from "../../_namespaces/evaluator"; -import * as ts from "../../_namespaces/ts"; +import { ScriptTarget } from "../../../compiler/types"; +import { evaluateTypeScript } from "../../../harness/evaluatorImpl"; describe("unittests:: evaluation:: superInStaticInitializer", () => { it("super-property-get in es2015", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export function main() { class Base { static x = 1; @@ -16,13 +16,13 @@ describe("unittests:: evaluation:: superInStaticInitializer", () => { Derived ]; } - `, { target: ts.ScriptTarget.ES2015 }); + `, { target: ScriptTarget.ES2015 }); const [Base, Derived] = result.main(); assert.strictEqual(Base.x, 1); assert.strictEqual(Derived.y, 1); }); it("super-property-set in es2015", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export function main() { class Base { static x = 1; @@ -35,14 +35,14 @@ describe("unittests:: evaluation:: superInStaticInitializer", () => { Derived ]; } - `, { target: ts.ScriptTarget.ES2015 }); + `, { target: ScriptTarget.ES2015 }); const [Base, Derived] = result.main(); assert.strictEqual(Base.x, 1); assert.strictEqual(Derived.x, 2); assert.strictEqual(Derived.y, 1); }); it("super-accessor-get in es2015", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export function main() { let thisInBase; class Base { @@ -61,14 +61,14 @@ describe("unittests:: evaluation:: superInStaticInitializer", () => { thisInBase ]; } - `, { target: ts.ScriptTarget.ES2015 }); + `, { target: ScriptTarget.ES2015 }); const [Base, Derived, thisInBase] = result.main(); assert.strictEqual(Base._x, 1); assert.strictEqual(Derived.y, 1); assert.strictEqual(thisInBase, Derived); }); it("super-accessor-set in es2015", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export function main() { let thisInBaseGet; let thisInBaseSet; @@ -93,7 +93,7 @@ describe("unittests:: evaluation:: superInStaticInitializer", () => { thisInBaseSet ]; } - `, { target: ts.ScriptTarget.ES2015 }); + `, { target: ScriptTarget.ES2015 }); const [Base, Derived, thisInBaseGet, thisInBaseSet] = result.main(); assert.strictEqual(Base._x, 1); assert.strictEqual(Derived._x, 2); @@ -102,7 +102,7 @@ describe("unittests:: evaluation:: superInStaticInitializer", () => { assert.strictEqual(thisInBaseSet, Derived); }); it("super-call in es2015", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export function main() { let thisInBase; class Base { @@ -119,13 +119,13 @@ describe("unittests:: evaluation:: superInStaticInitializer", () => { thisInBase, ]; } - `, { target: ts.ScriptTarget.ES2015 }); + `, { target: ScriptTarget.ES2015 }); const [Derived, thisInBase] = result.main(); assert.strictEqual(Derived.y, 1); assert.strictEqual(thisInBase, Derived); }); it("super-call in es5", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export function main() { let thisInBase; class Base { @@ -142,13 +142,13 @@ describe("unittests:: evaluation:: superInStaticInitializer", () => { thisInBase, ]; } - `, { target: ts.ScriptTarget.ES5 }); + `, { target: ScriptTarget.ES5 }); const [Derived, thisInBase] = result.main(); assert.strictEqual(Derived.y, 1); assert.strictEqual(thisInBase, Derived); }); it("super- and this-call in es2015", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export function main() { class Base { static x() { @@ -165,12 +165,12 @@ describe("unittests:: evaluation:: superInStaticInitializer", () => { Derived, ]; } - `, { target: ts.ScriptTarget.ES2015 }); + `, { target: ScriptTarget.ES2015 }); const [Derived] = result.main(); assert.strictEqual(Derived.y, 2); }); it("super- and this-call in es5", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` export function main() { class Base { static x() { @@ -187,7 +187,7 @@ describe("unittests:: evaluation:: superInStaticInitializer", () => { Derived, ]; } - `, { target: ts.ScriptTarget.ES2015 }); + `, { target: ScriptTarget.ES2015 }); const [Derived] = result.main(); assert.strictEqual(Derived.y, 2); }); diff --git a/src/testRunner/unittests/evaluation/templateLiteral.ts b/src/testRunner/unittests/evaluation/templateLiteral.ts index c00f624c1e3e1..7d20f5e0aee0d 100644 --- a/src/testRunner/unittests/evaluation/templateLiteral.ts +++ b/src/testRunner/unittests/evaluation/templateLiteral.ts @@ -1,8 +1,8 @@ -import * as evaluator from "../../_namespaces/evaluator"; +import { evaluateTypeScript } from "../../../harness/evaluatorImpl"; describe("unittests:: evaluation:: templateLiteral", () => { it("toString() over valueOf()", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` class C { toString() { return "toString"; @@ -18,7 +18,7 @@ describe("unittests:: evaluation:: templateLiteral", () => { }); it("correct evaluation order", () => { - const result = evaluator.evaluateTypeScript(` + const result = evaluateTypeScript(` class C { counter: number; diff --git a/src/testRunner/unittests/evaluation/updateExpressionInModule.ts b/src/testRunner/unittests/evaluation/updateExpressionInModule.ts index 662b14e50e1a7..86905abd16d5a 100644 --- a/src/testRunner/unittests/evaluation/updateExpressionInModule.ts +++ b/src/testRunner/unittests/evaluation/updateExpressionInModule.ts @@ -1,12 +1,12 @@ -import * as evaluator from "../../_namespaces/evaluator"; -import * as ts from "../../_namespaces/ts"; +import { ModuleKind } from "../../../compiler/types"; +import { evaluateTypeScript } from "../../../harness/evaluatorImpl"; describe("unittests:: evaluation:: updateExpressionInModule", () => { // only run BigInt tests if BigInt is supported in the host environment const itIfBigInt = typeof BigInt === "function" ? it : it.skip; it("pre-increment in commonjs using Number", () => { - const result = evaluator.evaluateTypeScript({ + const result = evaluateTypeScript({ files: { "/.src/main.ts": ` let a = 1; @@ -16,12 +16,12 @@ describe("unittests:: evaluation:: updateExpressionInModule", () => { }, rootFiles: ["/.src/main.ts"], main: "/.src/main.ts" - }, { module: ts.ModuleKind.CommonJS }); + }, { module: ModuleKind.CommonJS }); assert.equal(result.a, 2); assert.equal(result.b, 2); }); it("pre-increment in System using Number", () => { - const result = evaluator.evaluateTypeScript({ + const result = evaluateTypeScript({ files: { "/.src/main.ts": ` let a = 1; @@ -31,12 +31,12 @@ describe("unittests:: evaluation:: updateExpressionInModule", () => { }, rootFiles: ["/.src/main.ts"], main: "/.src/main.ts" - }, { module: ts.ModuleKind.System }); + }, { module: ModuleKind.System }); assert.equal(result.a, 2); assert.equal(result.b, 2); }); itIfBigInt("pre-increment in commonjs using BigInt", () => { - const result = evaluator.evaluateTypeScript({ + const result = evaluateTypeScript({ files: { "/.src/main.ts": ` let a = BigInt(1); @@ -46,12 +46,12 @@ describe("unittests:: evaluation:: updateExpressionInModule", () => { }, rootFiles: ["/.src/main.ts"], main: "/.src/main.ts" - }, { module: ts.ModuleKind.CommonJS }, { BigInt }); + }, { module: ModuleKind.CommonJS }, { BigInt }); assert.equal(result.a, BigInt(2)); assert.equal(result.b, BigInt(2)); }); itIfBigInt("pre-increment in System using BigInt", () => { - const result = evaluator.evaluateTypeScript({ + const result = evaluateTypeScript({ files: { "/.src/main.ts": ` let a = BigInt(1); @@ -61,12 +61,12 @@ describe("unittests:: evaluation:: updateExpressionInModule", () => { }, rootFiles: ["/.src/main.ts"], main: "/.src/main.ts" - }, { module: ts.ModuleKind.System }, { BigInt }); + }, { module: ModuleKind.System }, { BigInt }); assert.equal(result.a, BigInt(2)); assert.equal(result.b, BigInt(2)); }); it("post-increment in commonjs using Number", () => { - const result = evaluator.evaluateTypeScript({ + const result = evaluateTypeScript({ files: { "/.src/main.ts": ` let a = 1; @@ -76,12 +76,12 @@ describe("unittests:: evaluation:: updateExpressionInModule", () => { }, rootFiles: ["/.src/main.ts"], main: "/.src/main.ts" - }, { module: ts.ModuleKind.CommonJS }); + }, { module: ModuleKind.CommonJS }); assert.equal(result.a, 2); assert.equal(result.b, 1); }); it("post-increment in System using Number", () => { - const result = evaluator.evaluateTypeScript({ + const result = evaluateTypeScript({ files: { "/.src/main.ts": ` let a = 1; @@ -91,12 +91,12 @@ describe("unittests:: evaluation:: updateExpressionInModule", () => { }, rootFiles: ["/.src/main.ts"], main: "/.src/main.ts" - }, { module: ts.ModuleKind.System }); + }, { module: ModuleKind.System }); assert.equal(result.a, 2); assert.equal(result.b, 1); }); itIfBigInt("post-increment in commonjs using BigInt", () => { - const result = evaluator.evaluateTypeScript({ + const result = evaluateTypeScript({ files: { "/.src/main.ts": ` let a = BigInt(1); @@ -106,12 +106,12 @@ describe("unittests:: evaluation:: updateExpressionInModule", () => { }, rootFiles: ["/.src/main.ts"], main: "/.src/main.ts" - }, { module: ts.ModuleKind.CommonJS }, { BigInt }); + }, { module: ModuleKind.CommonJS }, { BigInt }); assert.equal(result.a, BigInt(2)); assert.equal(result.b, BigInt(1)); }); itIfBigInt("post-increment in System using BigInt", () => { - const result = evaluator.evaluateTypeScript({ + const result = evaluateTypeScript({ files: { "/.src/main.ts": ` let a = BigInt(1); @@ -121,7 +121,7 @@ describe("unittests:: evaluation:: updateExpressionInModule", () => { }, rootFiles: ["/.src/main.ts"], main: "/.src/main.ts" - }, { module: ts.ModuleKind.System }, { BigInt }); + }, { module: ModuleKind.System }, { BigInt }); assert.equal(result.a, BigInt(2)); assert.equal(result.b, BigInt(1)); }); diff --git a/src/testRunner/unittests/factory.ts b/src/testRunner/unittests/factory.ts index 10638536960d0..6ca2ec2572cf3 100644 --- a/src/testRunner/unittests/factory.ts +++ b/src/testRunner/unittests/factory.ts @@ -1,41 +1,43 @@ -import * as ts from "../_namespaces/ts"; +import { Debug } from "../../compiler/debug"; +import { factory } from "../../compiler/factory/nodeFactory"; +import { BinaryOperator, ConciseBody, Expression, Node, SyntaxKind } from "../../compiler/types"; describe("unittests:: FactoryAPI", () => { - function assertSyntaxKind(node: ts.Node, expected: ts.SyntaxKind) { - assert.strictEqual(node.kind, expected, `Actual: ${ts.Debug.formatSyntaxKind(node.kind)} Expected: ${ts.Debug.formatSyntaxKind(expected)}`); + function assertSyntaxKind(node: Node, expected: SyntaxKind) { + assert.strictEqual(node.kind, expected, `Actual: ${Debug.formatSyntaxKind(node.kind)} Expected: ${Debug.formatSyntaxKind(expected)}`); } describe("factory.createExportAssignment", () => { it("parenthesizes default export if necessary", () => { - function checkExpression(expression: ts.Expression) { - const node = ts.factory.createExportAssignment( + function checkExpression(expression: Expression) { + const node = factory.createExportAssignment( /*decorators*/ undefined, /*modifiers*/ undefined, /*isExportEquals*/ false, expression, ); - assertSyntaxKind(node.expression, ts.SyntaxKind.ParenthesizedExpression); + assertSyntaxKind(node.expression, SyntaxKind.ParenthesizedExpression); } - const clazz = ts.factory.createClassExpression(/*decorators*/ undefined, /*modifiers*/ undefined, "C", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [ - ts.factory.createPropertyDeclaration(/*decorators*/ undefined, [ts.factory.createToken(ts.SyntaxKind.StaticKeyword)], "prop", /*questionOrExclamationToken*/ undefined, /*type*/ undefined, ts.factory.createStringLiteral("1")), + const clazz = factory.createClassExpression(/*decorators*/ undefined, /*modifiers*/ undefined, "C", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [ + factory.createPropertyDeclaration(/*decorators*/ undefined, [factory.createToken(SyntaxKind.StaticKeyword)], "prop", /*questionOrExclamationToken*/ undefined, /*type*/ undefined, factory.createStringLiteral("1")), ]); checkExpression(clazz); - checkExpression(ts.factory.createPropertyAccessExpression(clazz, "prop")); + checkExpression(factory.createPropertyAccessExpression(clazz, "prop")); - const func = ts.factory.createFunctionExpression(/*modifiers*/ undefined, /*asteriskToken*/ undefined, "fn", /*typeParameters*/ undefined, /*parameters*/ undefined, /*type*/ undefined, ts.factory.createBlock([])); + const func = factory.createFunctionExpression(/*modifiers*/ undefined, /*asteriskToken*/ undefined, "fn", /*typeParameters*/ undefined, /*parameters*/ undefined, /*type*/ undefined, factory.createBlock([])); checkExpression(func); - checkExpression(ts.factory.createCallExpression(func, /*typeArguments*/ undefined, /*argumentsArray*/ undefined)); - checkExpression(ts.factory.createTaggedTemplateExpression(func, /*typeArguments*/ undefined, ts.factory.createNoSubstitutionTemplateLiteral(""))); + checkExpression(factory.createCallExpression(func, /*typeArguments*/ undefined, /*argumentsArray*/ undefined)); + checkExpression(factory.createTaggedTemplateExpression(func, /*typeArguments*/ undefined, factory.createNoSubstitutionTemplateLiteral(""))); - checkExpression(ts.factory.createBinaryExpression(ts.factory.createStringLiteral("a"), ts.SyntaxKind.CommaToken, ts.factory.createStringLiteral("b"))); - checkExpression(ts.factory.createCommaListExpression([ts.factory.createStringLiteral("a"), ts.factory.createStringLiteral("b")])); + checkExpression(factory.createBinaryExpression(factory.createStringLiteral("a"), SyntaxKind.CommaToken, factory.createStringLiteral("b"))); + checkExpression(factory.createCommaListExpression([factory.createStringLiteral("a"), factory.createStringLiteral("b")])); }); }); describe("factory.createArrowFunction", () => { it("parenthesizes concise body if necessary", () => { - function checkBody(body: ts.ConciseBody) { - const node = ts.factory.createArrowFunction( + function checkBody(body: ConciseBody) { + const node = factory.createArrowFunction( /*modifiers*/ undefined, /*typeParameters*/ undefined, [], @@ -43,44 +45,44 @@ describe("unittests:: FactoryAPI", () => { /*equalsGreaterThanToken*/ undefined, body, ); - assertSyntaxKind(node.body, ts.SyntaxKind.ParenthesizedExpression); + assertSyntaxKind(node.body, SyntaxKind.ParenthesizedExpression); } - checkBody(ts.factory.createObjectLiteralExpression()); - checkBody(ts.factory.createPropertyAccessExpression(ts.factory.createObjectLiteralExpression(), "prop")); - checkBody(ts.factory.createAsExpression(ts.factory.createPropertyAccessExpression(ts.factory.createObjectLiteralExpression(), "prop"), ts.factory.createTypeReferenceNode("T", /*typeArguments*/ undefined))); - checkBody(ts.factory.createNonNullExpression(ts.factory.createPropertyAccessExpression(ts.factory.createObjectLiteralExpression(), "prop"))); - checkBody(ts.factory.createCommaListExpression([ts.factory.createStringLiteral("a"), ts.factory.createStringLiteral("b")])); - checkBody(ts.factory.createBinaryExpression(ts.factory.createStringLiteral("a"), ts.SyntaxKind.CommaToken, ts.factory.createStringLiteral("b"))); + checkBody(factory.createObjectLiteralExpression()); + checkBody(factory.createPropertyAccessExpression(factory.createObjectLiteralExpression(), "prop")); + checkBody(factory.createAsExpression(factory.createPropertyAccessExpression(factory.createObjectLiteralExpression(), "prop"), factory.createTypeReferenceNode("T", /*typeArguments*/ undefined))); + checkBody(factory.createNonNullExpression(factory.createPropertyAccessExpression(factory.createObjectLiteralExpression(), "prop"))); + checkBody(factory.createCommaListExpression([factory.createStringLiteral("a"), factory.createStringLiteral("b")])); + checkBody(factory.createBinaryExpression(factory.createStringLiteral("a"), SyntaxKind.CommaToken, factory.createStringLiteral("b"))); }); }); describe("createBinaryExpression", () => { it("parenthesizes arrow function in RHS if necessary", () => { - const lhs = ts.factory.createIdentifier("foo"); - const rhs = ts.factory.createArrowFunction( + const lhs = factory.createIdentifier("foo"); + const rhs = factory.createArrowFunction( /*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, /*equalsGreaterThanToken*/ undefined, - ts.factory.createBlock([]), + factory.createBlock([]), ); - function checkRhs(operator: ts.BinaryOperator, expectParens: boolean) { - const node = ts.factory.createBinaryExpression(lhs, operator, rhs); - assertSyntaxKind(node.right, expectParens ? ts.SyntaxKind.ParenthesizedExpression : ts.SyntaxKind.ArrowFunction); + function checkRhs(operator: BinaryOperator, expectParens: boolean) { + const node = factory.createBinaryExpression(lhs, operator, rhs); + assertSyntaxKind(node.right, expectParens ? SyntaxKind.ParenthesizedExpression : SyntaxKind.ArrowFunction); } - checkRhs(ts.SyntaxKind.CommaToken, /*expectParens*/ false); - checkRhs(ts.SyntaxKind.EqualsToken, /*expectParens*/ false); - checkRhs(ts.SyntaxKind.PlusEqualsToken, /*expectParens*/ false); - checkRhs(ts.SyntaxKind.BarBarToken, /*expectParens*/ true); - checkRhs(ts.SyntaxKind.AmpersandAmpersandToken, /*expectParens*/ true); - checkRhs(ts.SyntaxKind.QuestionQuestionToken, /*expectParens*/ true); - checkRhs(ts.SyntaxKind.EqualsEqualsToken, /*expectParens*/ true); - checkRhs(ts.SyntaxKind.BarBarEqualsToken, /*expectParens*/ false); - checkRhs(ts.SyntaxKind.AmpersandAmpersandEqualsToken, /*expectParens*/ false); - checkRhs(ts.SyntaxKind.QuestionQuestionEqualsToken, /*expectParens*/ false); + checkRhs(SyntaxKind.CommaToken, /*expectParens*/ false); + checkRhs(SyntaxKind.EqualsToken, /*expectParens*/ false); + checkRhs(SyntaxKind.PlusEqualsToken, /*expectParens*/ false); + checkRhs(SyntaxKind.BarBarToken, /*expectParens*/ true); + checkRhs(SyntaxKind.AmpersandAmpersandToken, /*expectParens*/ true); + checkRhs(SyntaxKind.QuestionQuestionToken, /*expectParens*/ true); + checkRhs(SyntaxKind.EqualsEqualsToken, /*expectParens*/ true); + checkRhs(SyntaxKind.BarBarEqualsToken, /*expectParens*/ false); + checkRhs(SyntaxKind.AmpersandAmpersandEqualsToken, /*expectParens*/ false); + checkRhs(SyntaxKind.QuestionQuestionEqualsToken, /*expectParens*/ false); }); }); }); diff --git a/src/testRunner/unittests/incrementalParser.ts b/src/testRunner/unittests/incrementalParser.ts index 331a765df6410..4ea9aa5f76465 100644 --- a/src/testRunner/unittests/incrementalParser.ts +++ b/src/testRunner/unittests/incrementalParser.ts @@ -1,26 +1,33 @@ -import * as ts from "../_namespaces/ts"; -import * as Utils from "../_namespaces/Utils"; - -function withChange(text: ts.IScriptSnapshot, start: number, length: number, newText: string): { text: ts.IScriptSnapshot; textChangeRange: ts.TextChangeRange; } { - const contents = ts.getSnapshotText(text); +import { bindSourceFile } from "../../compiler/binder"; +import { contains, filter } from "../../compiler/core"; +import { forEachChild } from "../../compiler/parser"; +import { Node, ScriptTarget, SourceFile, TextChangeRange } from "../../compiler/types"; +import { createTextChangeRange, createTextSpan } from "../../compiler/utilitiesPublic"; +import { assertInvariants, assertStructuralEquals } from "../../harness/harnessUtils"; +import { createLanguageServiceSourceFile, updateLanguageServiceSourceFile } from "../../services/services"; +import { IScriptSnapshot, ScriptSnapshot } from "../../services/types"; +import { getSnapshotText } from "../../services/utilities"; + +function withChange(text: IScriptSnapshot, start: number, length: number, newText: string): { text: IScriptSnapshot; textChangeRange: TextChangeRange; } { + const contents = getSnapshotText(text); const newContents = contents.substr(0, start) + newText + contents.substring(start + length); - return { text: ts.ScriptSnapshot.fromString(newContents), textChangeRange: ts.createTextChangeRange(ts.createTextSpan(start, length), newText.length) }; + return { text: ScriptSnapshot.fromString(newContents), textChangeRange: createTextChangeRange(createTextSpan(start, length), newText.length) }; } -function withInsert(text: ts.IScriptSnapshot, start: number, newText: string): { text: ts.IScriptSnapshot; textChangeRange: ts.TextChangeRange; } { +function withInsert(text: IScriptSnapshot, start: number, newText: string): { text: IScriptSnapshot; textChangeRange: TextChangeRange; } { return withChange(text, start, 0, newText); } -function withDelete(text: ts.IScriptSnapshot, start: number, length: number): { text: ts.IScriptSnapshot; textChangeRange: ts.TextChangeRange; } { +function withDelete(text: IScriptSnapshot, start: number, length: number): { text: IScriptSnapshot; textChangeRange: TextChangeRange; } { return withChange(text, start, length, ""); } -function createTree(text: ts.IScriptSnapshot, version: string) { - return ts.createLanguageServiceSourceFile(/*fileName:*/ "", text, ts.ScriptTarget.Latest, version, /*setNodeParents:*/ true); +function createTree(text: IScriptSnapshot, version: string) { + return createLanguageServiceSourceFile(/*fileName:*/ "", text, ScriptTarget.Latest, version, /*setNodeParents:*/ true); } -function assertSameDiagnostics(file1: ts.SourceFile, file2: ts.SourceFile) { +function assertSameDiagnostics(file1: SourceFile, file2: SourceFile) { const diagnostics1 = file1.parseDiagnostics; const diagnostics2 = file2.parseDiagnostics; @@ -44,20 +51,20 @@ function assertSameDiagnostics(file1: ts.SourceFile, file2: ts.SourceFile) { // be a good thing. If it decreases, that's not great (less reusability), but that may be // unavoidable. If it does decrease an investigation should be done to make sure that things // are still ok and we're still appropriately reusing most of the tree. -function compareTrees(oldText: ts.IScriptSnapshot, newText: ts.IScriptSnapshot, textChangeRange: ts.TextChangeRange, expectedReusedElements: number, oldTree?: ts.SourceFile) { +function compareTrees(oldText: IScriptSnapshot, newText: IScriptSnapshot, textChangeRange: TextChangeRange, expectedReusedElements: number, oldTree?: SourceFile) { oldTree = oldTree || createTree(oldText, /*version:*/ "."); - Utils.assertInvariants(oldTree, /*parent:*/ undefined); + assertInvariants(oldTree, /*parent:*/ undefined); // Create a tree for the new text, in a non-incremental fashion. const newTree = createTree(newText, oldTree.version + "."); - Utils.assertInvariants(newTree, /*parent:*/ undefined); + assertInvariants(newTree, /*parent:*/ undefined); // Create a tree for the new text, in an incremental fashion. - const incrementalNewTree = ts.updateLanguageServiceSourceFile(oldTree, newText, oldTree.version + ".", textChangeRange); - Utils.assertInvariants(incrementalNewTree, /*parent:*/ undefined); + const incrementalNewTree = updateLanguageServiceSourceFile(oldTree, newText, oldTree.version + ".", textChangeRange); + assertInvariants(incrementalNewTree, /*parent:*/ undefined); // We should get the same tree when doign a full or incremental parse. - Utils.assertStructuralEquals(newTree, incrementalNewTree); + assertStructuralEquals(newTree, incrementalNewTree); // We should also get the exact same set of diagnostics. assertSameDiagnostics(newTree, incrementalNewTree); @@ -76,46 +83,46 @@ function compareTrees(oldText: ts.IScriptSnapshot, newText: ts.IScriptSnapshot, return { oldTree, newTree, incrementalNewTree }; } -function reusedElements(oldNode: ts.SourceFile, newNode: ts.SourceFile): number { +function reusedElements(oldNode: SourceFile, newNode: SourceFile): number { const allOldElements = collectElements(oldNode); const allNewElements = collectElements(newNode); - return ts.filter(allOldElements, v => ts.contains(allNewElements, v)).length; + return filter(allOldElements, v => contains(allNewElements, v)).length; } -function collectElements(node: ts.Node) { - const result: ts.Node[] = []; +function collectElements(node: Node) { + const result: Node[] = []; visit(node); return result; - function visit(node: ts.Node) { + function visit(node: Node) { result.push(node); - ts.forEachChild(node, visit); + forEachChild(node, visit); } } function deleteCode(source: string, index: number, toDelete: string) { const repeat = toDelete.length; - let oldTree = createTree(ts.ScriptSnapshot.fromString(source), /*version:*/ "."); + let oldTree = createTree(ScriptSnapshot.fromString(source), /*version:*/ "."); for (let i = 0; i < repeat; i++) { - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, index, 1); const newTree = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1, oldTree).incrementalNewTree; - source = ts.getSnapshotText(newTextAndChange.text); + source = getSnapshotText(newTextAndChange.text); oldTree = newTree; } } function insertCode(source: string, index: number, toInsert: string) { const repeat = toInsert.length; - let oldTree = createTree(ts.ScriptSnapshot.fromString(source), /*version:*/ "."); + let oldTree = createTree(ScriptSnapshot.fromString(source), /*version:*/ "."); for (let i = 0; i < repeat; i++) { - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, index + i, toInsert.charAt(i)); const newTree = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1, oldTree).incrementalNewTree; - source = ts.getSnapshotText(newTextAndChange.text); + source = getSnapshotText(newTextAndChange.text); oldTree = newTree; } } @@ -130,7 +137,7 @@ describe("unittests:: Incremental Parser", () => { " public foo3() { }\r\n" + "}"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const semicolonIndex = source.indexOf(";"); const newTextAndChange = withInsert(oldText, semicolonIndex, " + 1"); @@ -147,7 +154,7 @@ describe("unittests:: Incremental Parser", () => { "}"; const index = source.indexOf("+ 1"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, index, "+ 1".length); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 8); @@ -157,7 +164,7 @@ describe("unittests:: Incremental Parser", () => { const source = "class C { public foo1() { /; } public foo2() { return 1;} public foo3() { } }"; const semicolonIndex = source.indexOf(";}"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, semicolonIndex, "/"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -167,7 +174,7 @@ describe("unittests:: Incremental Parser", () => { const source = "class C { public foo1() { ; } public foo2() { return 1/;} public foo3() { } }"; const semicolonIndex = source.indexOf(";"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, semicolonIndex, "/"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4); @@ -177,7 +184,7 @@ describe("unittests:: Incremental Parser", () => { const source = "class C { public foo1() { /; } public foo2() { return 1; } public foo3() { } }"; const semicolonIndex = source.indexOf(";"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, semicolonIndex, "/"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -186,7 +193,7 @@ describe("unittests:: Incremental Parser", () => { it("Comment 2", () => { const source = "class C { public foo1() { /; } public foo2() { return 1; } public foo3() { } }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, 0, "//"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -195,7 +202,7 @@ describe("unittests:: Incremental Parser", () => { it("Comment 3", () => { const source = "//class C { public foo1() { /; } public foo2() { return 1; } public foo3() { } }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, 0, 2); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -205,7 +212,7 @@ describe("unittests:: Incremental Parser", () => { const source = "class C { public foo1() { /; } public foo2() { */ return 1; } public foo3() { } }"; const index = source.indexOf(";"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, index, "*"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4); @@ -220,7 +227,7 @@ describe("unittests:: Incremental Parser", () => { "}"; const semicolonIndex = source.indexOf(";"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, semicolonIndex, " + 1"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 8); @@ -231,7 +238,7 @@ describe("unittests:: Incremental Parser", () => { const source = "interface I { a: number; b: string; (c): d; new (e): f; g(): h }"; const index = source.indexOf(": string"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, index, "?"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 14); @@ -242,7 +249,7 @@ describe("unittests:: Incremental Parser", () => { const source = "enum E { a = 1, b = 1 << 1, c = 3, e = 4, f = 5, g = 7, h = 8, i = 9, j = 10 }"; const index = source.indexOf("<<"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, index, 2, "+"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 24); @@ -251,7 +258,7 @@ describe("unittests:: Incremental Parser", () => { it("Strict mode 1", () => { const source = "foo1();\r\nfoo1();\r\nfoo1();\r\package();"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, 0, "'strict';\r\n"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 9); @@ -260,7 +267,7 @@ describe("unittests:: Incremental Parser", () => { it("Strict mode 2", () => { const source = "foo1();\r\nfoo1();\r\nfoo1();\r\package();"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, 0, "'use strict';\r\n"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 9); @@ -270,7 +277,7 @@ describe("unittests:: Incremental Parser", () => { const source = "'strict';\r\nfoo1();\r\nfoo1();\r\nfoo1();\r\npackage();"; const index = source.indexOf("f"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, 0, index); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 9); @@ -280,7 +287,7 @@ describe("unittests:: Incremental Parser", () => { const source = "'use strict';\r\nfoo1();\r\nfoo1();\r\nfoo1();\r\npackage();"; const index = source.indexOf("f"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, 0, index); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 9); @@ -290,7 +297,7 @@ describe("unittests:: Incremental Parser", () => { const source = "'use blahhh';\r\nfoo1();\r\nfoo2();\r\nfoo3();\r\nfoo4();\r\nfoo4();\r\nfoo6();\r\nfoo7();\r\nfoo8();\r\nfoo9();\r\n"; const index = source.indexOf("b"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, index, 6, "strict"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 27); @@ -300,7 +307,7 @@ describe("unittests:: Incremental Parser", () => { const source = "'use strict';\r\nfoo1();\r\nfoo2();\r\nfoo3();\r\nfoo4();\r\nfoo4();\r\nfoo6();\r\nfoo7();\r\nfoo8();\r\nfoo9();\r\n"; const index = source.indexOf("s"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, index, 6, "blahhh"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 27); @@ -310,7 +317,7 @@ describe("unittests:: Incremental Parser", () => { const source = "'use blahhh';\r\nfoo1();\r\nfoo2();\r\nfoo3();\r\nfoo4();\r\nfoo4();\r\nfoo6();\r\nfoo7();\r\nfoo8();\r\nfoo9();\r\n"; const index = source.indexOf("f"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, 0, index); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 24); @@ -320,7 +327,7 @@ describe("unittests:: Incremental Parser", () => { const source = "var v = (a, b, c, d, e)"; const index = source.indexOf("a"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, index + 1, ":"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -330,7 +337,7 @@ describe("unittests:: Incremental Parser", () => { const source = "var v = (a, b) = c"; const index = source.indexOf("= c") + 1; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, index, ">"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -340,7 +347,7 @@ describe("unittests:: Incremental Parser", () => { const source = "var v = (a:, b, c, d, e)"; const index = source.indexOf(":"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, index, 1); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -350,7 +357,7 @@ describe("unittests:: Incremental Parser", () => { const source = "var v = (a, b) => c"; const index = source.indexOf(">"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, index, 1); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -360,7 +367,7 @@ describe("unittests:: Incremental Parser", () => { const source = "var v = Fe"; const index = source.indexOf("b"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, index + 1, ",x"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1); @@ -370,7 +377,7 @@ describe("unittests:: Incremental Parser", () => { const source = "var v = Fe"; const index = source.indexOf("b"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, index + 1, ",x"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1); @@ -380,7 +387,7 @@ describe("unittests:: Incremental Parser", () => { const source = "var v = Fe"; const index = source.indexOf("b"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, index + 1, ",x"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1); @@ -390,7 +397,7 @@ describe("unittests:: Incremental Parser", () => { const source = "var v = Fe"; const index = source.indexOf("b"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, index + 1, ",x"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1); @@ -400,7 +407,7 @@ describe("unittests:: Incremental Parser", () => { const source = "var v = (a);"; const index = source.indexOf(";"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, index, " => 1"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -410,7 +417,7 @@ describe("unittests:: Incremental Parser", () => { const source = "var v = (a) => 1;"; const index = source.indexOf(" =>"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, index, " => 1".length); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -420,7 +427,7 @@ describe("unittests:: Incremental Parser", () => { const source = "var v = 1 >> = 2"; const index = source.indexOf(">> ="); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, index + 2, 1); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -430,7 +437,7 @@ describe("unittests:: Incremental Parser", () => { const source = "var v = 1 >>= 2"; const index = source.indexOf(">>="); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, index + 2, " "); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -440,7 +447,7 @@ describe("unittests:: Incremental Parser", () => { const source = "var v = T>>(2)"; const index = source.indexOf("T"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, index, "Foo { const source = "var v = Foo>(2)"; const index = source.indexOf("Foo { const source = "var v = T>>=2;"; const index = source.indexOf("="); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, index, "= ".length, ": Foo { const source = "var v : Foo>=2;"; const index = source.indexOf(":"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, index, ": Foo { const source = "var v = new Dictionary0"; const index = source.indexOf("0"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, index, 1, "()"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -490,7 +497,7 @@ describe("unittests:: Incremental Parser", () => { const source = "var v = new Dictionary()"; const index = source.indexOf("()"); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, index, 2); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -500,7 +507,7 @@ describe("unittests:: Incremental Parser", () => { // We're changing from a non-generator to a genarator. We can't reuse statement nodes. const source = "function foo() {\r\nyield(foo1);\r\n}"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const index = source.indexOf("foo"); const newTextAndChange = withInsert(oldText, index, "*"); @@ -511,7 +518,7 @@ describe("unittests:: Incremental Parser", () => { // We're changing from a generator to a non-genarator. We can't reuse statement nodes. const source = "function *foo() {\r\nyield(foo1);\r\n}"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const index = source.indexOf("*"); const newTextAndChange = withDelete(oldText, index, "*".length); @@ -521,7 +528,7 @@ describe("unittests:: Incremental Parser", () => { it("Delete semicolon", () => { const source = "export class Foo {\r\n}\r\n\r\nexport var foo = new Foo();\r\n\r\n export function test(foo: Foo) {\r\n return true;\r\n }\r\n"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const index = source.lastIndexOf(";"); const newTextAndChange = withDelete(oldText, index, 1); @@ -531,7 +538,7 @@ describe("unittests:: Incremental Parser", () => { it("Edit after empty type parameter list", () => { const source = "class Dictionary<> { }\r\nvar y;\r\n"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const index = source.length; const newTextAndChange = withInsert(oldText, index, "var x;"); @@ -541,7 +548,7 @@ describe("unittests:: Incremental Parser", () => { it("Delete parameter after comment", () => { const source = "function fn(/* comment! */ a: number, c) { }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const index = source.indexOf("a:"); const newTextAndChange = withDelete(oldText, index, "a: number,".length); @@ -555,7 +562,7 @@ describe("unittests:: Incremental Parser", () => { }\ var o2 = { set Foo(val:number) { } };"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const index = source.indexOf("set"); const newTextAndChange = withInsert(oldText, index, "public "); @@ -571,7 +578,7 @@ constructor();\ constructor(name) { }\ }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const index = source.indexOf("100"); const newTextAndChange = withInsert(oldText, index, "'1', "); @@ -584,7 +591,7 @@ constructor(name) { }\ module m3 { }\ }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const index = 0; const newTextAndChange = withInsert(oldText, index, "declare "); @@ -598,7 +605,7 @@ module m3 { }\ // do something\ 0;"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const index = 0; const newTextAndChange = withInsert(oldText, index, "function Foo() { }"); @@ -608,7 +615,7 @@ module m3 { }\ it("Finish incomplete regular expression", () => { const source = "while (true) /3; return;"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const index = source.length - 1; const newTextAndChange = withInsert(oldText, index, "/"); @@ -618,7 +625,7 @@ module m3 { }\ it("Regular expression to divide operation", () => { const source = "return;\r\nwhile (true) /3/g;"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const index = source.indexOf("while"); const newTextAndChange = withDelete(oldText, index, "while ".length); @@ -628,7 +635,7 @@ module m3 { }\ it("Divide operation to regular expression", () => { const source = "return;\r\n(true) /3/g;"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const index = source.indexOf("("); const newTextAndChange = withInsert(oldText, index, "while "); @@ -641,7 +648,7 @@ module m3 { }\ // change anything, and we should still get the same errors. const source = "return; a.public /*"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, 0, ""); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 7); @@ -650,7 +657,7 @@ module m3 { }\ it("Class to interface", () => { const source = "class A { public M1() { } public M2() { } public M3() { } p1 = 0; p2 = 0; p3 = 0 }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 0, "class".length, "interface"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -659,7 +666,7 @@ module m3 { }\ it("Interface to class", () => { const source = "interface A { M1?(); M2?(); M3?(); p1?; p2?; p3? }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 0, "interface".length, "class"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -668,7 +675,7 @@ module m3 { }\ it("Surrounding function declarations with block", () => { const source = "declare function F1() { } export function F2() { } declare export function F3() { }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, 0, "{"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 9); @@ -677,7 +684,7 @@ module m3 { }\ it("Removing block around function declarations", () => { const source = "{ declare function F1() { } export function F2() { } declare export function F3() { }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, 0, "{".length); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 9); @@ -686,7 +693,7 @@ module m3 { }\ it("Moving methods from class to object literal", () => { const source = "class C { public A() { } public B() { } public C() { } }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 0, "class C".length, "var v ="); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -695,7 +702,7 @@ module m3 { }\ it("Moving methods from object literal to class", () => { const source = "var v = { public A() { } public B() { } public C() { } }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 0, "var v =".length, "class C"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4); @@ -704,7 +711,7 @@ module m3 { }\ it("Moving methods from object literal to class in strict mode", () => { const source = "\"use strict\"; var v = { public A() { } public B() { } public C() { } }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 14, "var v =".length, "class C"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4); @@ -713,7 +720,7 @@ module m3 { }\ it("Do not move constructors from class to object-literal.", () => { const source = "class C { public constructor() { } public constructor() { } public constructor() { } }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 0, "class C".length, "var v ="); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -722,7 +729,7 @@ module m3 { }\ it("Do not move methods called \"constructor\" from object literal to class", () => { const source = "var v = { public constructor() { } public constructor() { } public constructor() { } }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 0, "var v =".length, "class C"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -731,7 +738,7 @@ module m3 { }\ it("Moving index signatures from class to interface", () => { const source = "class C { public [a: number]: string; public [a: number]: string; public [a: number]: string }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 0, "class".length, "interface"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 18); @@ -740,7 +747,7 @@ module m3 { }\ it("Moving index signatures from class to interface in strict mode", () => { const source = "\"use strict\"; class C { public [a: number]: string; public [a: number]: string; public [a: number]: string }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 14, "class".length, "interface"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 18); @@ -749,7 +756,7 @@ module m3 { }\ it("Moving index signatures from interface to class", () => { const source = "interface C { public [a: number]: string; public [a: number]: string; public [a: number]: string }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 0, "interface".length, "class"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 18); @@ -759,7 +766,7 @@ module m3 { }\ it("Moving index signatures from interface to class in strict mode", () => { const source = "\"use strict\"; interface C { public [a: number]: string; public [a: number]: string; public [a: number]: string }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 14, "interface".length, "class"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 18); @@ -768,7 +775,7 @@ module m3 { }\ it("Moving accessors from class to object literal", () => { const source = "class C { public get A() { } public get B() { } public get C() { } }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 0, "class C".length, "var v ="); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); @@ -777,7 +784,7 @@ module m3 { }\ it("Moving accessors from object literal to class", () => { const source = "var v = { public get A() { } public get B() { } public get C() { } }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 0, "var v =".length, "class C"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4); @@ -787,7 +794,7 @@ module m3 { }\ it("Moving accessors from object literal to class in strict mode", () => { const source = "\"use strict\"; var v = { public get A() { } public get B() { } public get C() { } }"; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 14, "var v =".length, "class C"); compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4); @@ -795,11 +802,11 @@ module m3 { }\ it("Reuse transformFlags of subtree during bind", () => { const source = `class Greeter { constructor(element: HTMLElement) { } }`; - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, 15, 0, "\n"); const { oldTree, incrementalNewTree } = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1); - ts.bindSourceFile(oldTree, {}); - ts.bindSourceFile(incrementalNewTree, {}); + bindSourceFile(oldTree, {}); + bindSourceFile(incrementalNewTree, {}); assert.equal(oldTree.transformFlags, incrementalNewTree.transformFlags); }); @@ -867,7 +874,7 @@ module m3 { }\ verifyScenario("when changing text that adds another comment", verifyChangeDirectiveType); verifyScenario("when changing text that keeps the comment but adds more nodes", verifyReuseChange); - function verifyCommentDirectives(oldText: ts.IScriptSnapshot, newTextAndChange: { text: ts.IScriptSnapshot; textChangeRange: ts.TextChangeRange; }) { + function verifyCommentDirectives(oldText: IScriptSnapshot, newTextAndChange: { text: IScriptSnapshot; textChangeRange: TextChangeRange; }) { const { incrementalNewTree, newTree } = compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, -1); assert.deepEqual(incrementalNewTree.commentDirectives, newTree.commentDirectives); } @@ -910,7 +917,7 @@ module m3 { }\ function verifyDelete(atIndex: number, singleIgnore?: true) { const index = getIndexOfTsIgnoreComment(atIndex); - const oldText = ts.ScriptSnapshot.fromString(textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore)); + const oldText = ScriptSnapshot.fromString(textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore)); const newTextAndChange = withDelete(oldText, index, tsIgnoreComment.length); verifyCommentDirectives(oldText, newTextAndChange); } @@ -918,14 +925,14 @@ module m3 { }\ function verifyInsert(atIndex: number, singleIgnore?: true) { const index = getIndexOfTsIgnoreComment(atIndex); const source = textWithIgnoreCommentFrom(textWithIgnoreComment.slice(0, index) + textWithIgnoreComment.slice(index + tsIgnoreComment.length), singleIgnore); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withInsert(oldText, index, tsIgnoreComment); verifyCommentDirectives(oldText, newTextAndChange); } function verifyChangeToBlah(atIndex: number, singleIgnore?: true) { const index = getIndexOfTsIgnoreComment(atIndex) + tsIgnoreComment.indexOf("@"); - const oldText = ts.ScriptSnapshot.fromString(textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore)); + const oldText = ScriptSnapshot.fromString(textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore)); const newTextAndChange = withChange(oldText, index, 1, "blah "); verifyCommentDirectives(oldText, newTextAndChange); } @@ -933,7 +940,7 @@ module m3 { }\ function verifyChangeBackToDirective(atIndex: number, singleIgnore?: true) { const index = getIndexOfTsIgnoreComment(atIndex) + tsIgnoreComment.indexOf("@"); const source = textWithIgnoreCommentFrom(textWithIgnoreComment.slice(0, index) + "blah " + textWithIgnoreComment.slice(index + 1), singleIgnore); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withChange(oldText, index, "blah ".length, "@"); verifyCommentDirectives(oldText, newTextAndChange); } @@ -942,14 +949,14 @@ module m3 { }\ const tsIgnoreIndex = getIndexOfTsIgnoreComment(atIndex); const index = tsIgnoreIndex + tsIgnoreComment.indexOf("@"); const source = textWithIgnoreCommentFrom(textWithIgnoreComment.slice(0, index) + "blah " + textWithIgnoreComment.slice(index + 1), singleIgnore); - const oldText = ts.ScriptSnapshot.fromString(source); + const oldText = ScriptSnapshot.fromString(source); const newTextAndChange = withDelete(oldText, tsIgnoreIndex, tsIgnoreComment.length + "blah".length); verifyCommentDirectives(oldText, newTextAndChange); } function verifyChangeDirectiveType(atIndex: number, singleIgnore?: true) { const index = getIndexOfTsIgnoreComment(atIndex) + tsIgnoreComment.indexOf("ignore"); - const oldText = ts.ScriptSnapshot.fromString(textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore)); + const oldText = ScriptSnapshot.fromString(textWithIgnoreCommentFrom(textWithIgnoreComment, singleIgnore)); const newTextAndChange = withChange(oldText, index, "ignore".length, "expect-error"); verifyCommentDirectives(oldText, newTextAndChange); } @@ -980,7 +987,7 @@ module m3 { }\ foo1(); foo2(); foo3();`; - const oldText = ts.ScriptSnapshot.fromString(textWithIgnoreCommentFrom(source, singleIgnore)); + const oldText = ScriptSnapshot.fromString(textWithIgnoreCommentFrom(source, singleIgnore)); const start = source.indexOf(`const x${atIndex + 1}`); const letStr = `let y${atIndex + 1}: string = x;`; const end = source.indexOf(letStr) + letStr.length; diff --git a/src/testRunner/unittests/jsDocParsing.ts b/src/testRunner/unittests/jsDocParsing.ts index a5a66a7cbcf23..f68b2d26d756e 100644 --- a/src/testRunner/unittests/jsDocParsing.ts +++ b/src/testRunner/unittests/jsDocParsing.ts @@ -1,22 +1,24 @@ -import * as Harness from "../_namespaces/Harness"; -import * as ts from "../_namespaces/ts"; -import * as Utils from "../_namespaces/Utils"; +import { Debug } from "../../compiler/debug"; +import { createSourceFile, parseIsolatedJSDocComment, parseJSDocTypeExpressionForTests } from "../../compiler/parser"; +import { JSDocTemplateTag, ScriptTarget, SyntaxKind } from "../../compiler/types"; +import { Baseline } from "../../harness/harnessIO"; +import { sourceFileToJSON } from "../../harness/harnessUtils"; describe("unittests:: JSDocParsing", () => { describe("TypeExpressions", () => { function parsesCorrectly(name: string, content: string) { it(name, () => { - const typeAndDiagnostics = ts.parseJSDocTypeExpressionForTests(content); + const typeAndDiagnostics = parseJSDocTypeExpressionForTests(content); assert.isTrue(typeAndDiagnostics && typeAndDiagnostics.diagnostics.length === 0, "no errors issued"); - Harness.Baseline.runBaseline("JSDocParsing/TypeExpressions.parsesCorrectly." + name + ".json", - Utils.sourceFileToJSON(typeAndDiagnostics!.jsDocTypeExpression.type)); + Baseline.runBaseline("JSDocParsing/TypeExpressions.parsesCorrectly." + name + ".json", + sourceFileToJSON(typeAndDiagnostics!.jsDocTypeExpression.type)); }); } function parsesIncorrectly(name: string, content: string) { it(name, () => { - const type = ts.parseJSDocTypeExpressionForTests(content); + const type = parseJSDocTypeExpressionForTests(content); assert.isTrue(!type || type.diagnostics.length > 0); }); } @@ -91,23 +93,23 @@ describe("unittests:: JSDocParsing", () => { describe("DocComments", () => { function parsesCorrectly(name: string, content: string) { it(name, () => { - const comment = ts.parseIsolatedJSDocComment(content)!; + const comment = parseIsolatedJSDocComment(content)!; if (!comment) { - ts.Debug.fail("Comment failed to parse entirely"); + Debug.fail("Comment failed to parse entirely"); } if (comment.diagnostics.length > 0) { - ts.Debug.fail("Comment has at least one diagnostic: " + comment.diagnostics[0].messageText); + Debug.fail("Comment has at least one diagnostic: " + comment.diagnostics[0].messageText); } - Harness.Baseline.runBaseline("JSDocParsing/DocComments.parsesCorrectly." + name + ".json", + Baseline.runBaseline("JSDocParsing/DocComments.parsesCorrectly." + name + ".json", JSON.stringify(comment.jsDoc, - (_, v) => v && v.pos !== undefined ? JSON.parse(Utils.sourceFileToJSON(v)) : v, 4)); + (_, v) => v && v.pos !== undefined ? JSON.parse(sourceFileToJSON(v)) : v, 4)); }); } function parsesIncorrectly(name: string, content: string) { it(name, () => { - const type = ts.parseIsolatedJSDocComment(content); + const type = parseIsolatedJSDocComment(content); assert.isTrue(!type || type.diagnostics.length > 0); }); } @@ -379,33 +381,33 @@ oh.no }); describe("getFirstToken", () => { it("gets jsdoc", () => { - const root = ts.createSourceFile("foo.ts", "/** comment */var a = true;", ts.ScriptTarget.ES5, /*setParentNodes*/ true); + const root = createSourceFile("foo.ts", "/** comment */var a = true;", ScriptTarget.ES5, /*setParentNodes*/ true); assert.isDefined(root); - assert.equal(root.kind, ts.SyntaxKind.SourceFile); + assert.equal(root.kind, SyntaxKind.SourceFile); const first = root.getFirstToken(); assert.isDefined(first); - assert.equal(first!.kind, ts.SyntaxKind.VarKeyword); + assert.equal(first!.kind, SyntaxKind.VarKeyword); }); }); describe("getLastToken", () => { it("gets jsdoc", () => { - const root = ts.createSourceFile("foo.ts", "var a = true;/** comment */", ts.ScriptTarget.ES5, /*setParentNodes*/ true); + const root = createSourceFile("foo.ts", "var a = true;/** comment */", ScriptTarget.ES5, /*setParentNodes*/ true); assert.isDefined(root); const last = root.getLastToken(); assert.isDefined(last); - assert.equal(last!.kind, ts.SyntaxKind.EndOfFileToken); + assert.equal(last!.kind, SyntaxKind.EndOfFileToken); }); }); describe("getStart", () => { it("runs when node with JSDoc but no parent pointers", () => { - const root = ts.createSourceFile("foo.ts", "/** */var a = true;", ts.ScriptTarget.ES5, /*setParentNodes*/ false); + const root = createSourceFile("foo.ts", "/** */var a = true;", ScriptTarget.ES5, /*setParentNodes*/ false); root.statements[0].getStart(root, /*includeJsdocComment*/ true); }); }); describe("parseIsolatedJSDocComment", () => { it("doesn't create a 1-element array with missing type parameter in jsDoc", () => { - const doc = ts.parseIsolatedJSDocComment("/**\n @template\n*/"); - assert.equal((doc?.jsDoc.tags?.[0] as ts.JSDocTemplateTag).typeParameters.length, 0); + const doc = parseIsolatedJSDocComment("/**\n @template\n*/"); + assert.equal((doc?.jsDoc.tags?.[0] as JSDocTemplateTag).typeParameters.length, 0); }); }); }); diff --git a/src/testRunner/unittests/jsonParserRecovery.ts b/src/testRunner/unittests/jsonParserRecovery.ts index 660091b39147f..ba9234fc8ddfe 100644 --- a/src/testRunner/unittests/jsonParserRecovery.ts +++ b/src/testRunner/unittests/jsonParserRecovery.ts @@ -1,14 +1,14 @@ -import * as Harness from "../_namespaces/Harness"; -import * as ts from "../_namespaces/ts"; +import { parseJsonText } from "../../compiler/parser"; +import { Baseline, Compiler } from "../../harness/harnessIO"; describe("unittests:: jsonParserRecovery", () => { function parsesToValidSourceFileWithErrors(name: string, text: string) { it(name, () => { - const file = ts.parseJsonText(name, text); + const file = parseJsonText(name, text); assert(file.parseDiagnostics.length, "Should have parse errors"); - Harness.Baseline.runBaseline( + Baseline.runBaseline( `jsonParserRecovery/${name.replace(/[^a-z0-9_-]/ig, "_")}.errors.txt`, - Harness.Compiler.getErrorBaseline([{ + Compiler.getErrorBaseline([{ content: text, unitName: name }], file.parseDiagnostics)); diff --git a/src/testRunner/unittests/moduleResolution.ts b/src/testRunner/unittests/moduleResolution.ts index 802d2bfb366a2..3e8ffc629d6b0 100644 --- a/src/testRunner/unittests/moduleResolution.ts +++ b/src/testRunner/unittests/moduleResolution.ts @@ -1,7 +1,25 @@ -import * as Harness from "../_namespaces/Harness"; -import * as ts from "../_namespaces/ts"; - -export function checkResolvedModule(actual: ts.ResolvedModuleFull | undefined, expected: ts.ResolvedModuleFull | undefined): boolean { +import { + arrayToMap, createGetCanonicalFileName, emptyArray, filter, getEntries, map, notImplemented, +} from "../../compiler/core"; +import { ESMap, Map } from "../../compiler/corePublic"; +import { Diagnostics } from "../../compiler/diagnosticInformationMap.generated"; +import { + createModuleResolutionCache, nodeModuleNameResolver, resolveModuleName, resolveTypeReferenceDirective, +} from "../../compiler/moduleNameResolver"; +import { createSourceFile } from "../../compiler/parser"; +import { combinePaths, getDirectoryPath, getRootLength, normalizePath } from "../../compiler/path"; +import { createProgram } from "../../compiler/program"; +import { + CompilerHost, CompilerOptions, Diagnostic, Extension, JsxEmit, ModuleKind, ModuleResolutionHost, + ModuleResolutionKind, Program, ResolvedModuleFull, ResolvedModuleWithFailedLookupLocations, ScriptTarget, + SourceFile, StructureIsReused, +} from "../../compiler/types"; +import { extensionFromPath, supportedTSExtensions, supportedTSExtensionsFlat } from "../../compiler/utilities"; +import { sortAndDeduplicateDiagnostics } from "../../compiler/utilitiesPublic"; +import { Compiler } from "../../harness/harnessIO"; +import { getDiagnosticMessageChain, getDiagnosticOfFileFrom, getDiagnosticOfFileFromProgram } from "./tscWatch/helpers"; + +export function checkResolvedModule(actual: ResolvedModuleFull | undefined, expected: ResolvedModuleFull | undefined): boolean { if (!expected) { if (actual) { assert.fail(actual, expected, "expected resolved module to be undefined"); @@ -20,14 +38,14 @@ export function checkResolvedModule(actual: ts.ResolvedModuleFull | undefined, e return true; } -export function checkResolvedModuleWithFailedLookupLocations(actual: ts.ResolvedModuleWithFailedLookupLocations, expectedResolvedModule: ts.ResolvedModuleFull, expectedFailedLookupLocations: string[]): void { +export function checkResolvedModuleWithFailedLookupLocations(actual: ResolvedModuleWithFailedLookupLocations, expectedResolvedModule: ResolvedModuleFull, expectedFailedLookupLocations: string[]): void { assert.isTrue(actual.resolvedModule !== undefined, "module should be resolved"); checkResolvedModule(actual.resolvedModule, expectedResolvedModule); assert.deepEqual(actual.failedLookupLocations, expectedFailedLookupLocations, `Failed lookup locations should match - expected has ${expectedFailedLookupLocations.length}, actual has ${actual.failedLookupLocations.length}`); } -export function createResolvedModule(resolvedFileName: string, isExternalLibraryImport = false): ts.ResolvedModuleFull { - return { resolvedFileName, extension: ts.extensionFromPath(resolvedFileName), isExternalLibraryImport }; +export function createResolvedModule(resolvedFileName: string, isExternalLibraryImport = false): ResolvedModuleFull { + return { resolvedFileName, extension: extensionFromPath(resolvedFileName), isExternalLibraryImport }; } interface File { @@ -36,8 +54,8 @@ interface File { symlinks?: string[]; } -function createModuleResolutionHost(hasDirectoryExists: boolean, ...files: File[]): ts.ModuleResolutionHost { - const map = new ts.Map(); +function createModuleResolutionHost(hasDirectoryExists: boolean, ...files: File[]): ModuleResolutionHost { + const map = new Map(); for (const file of files) { map.set(file.name, file); if (file.symlinks) { @@ -48,12 +66,12 @@ function createModuleResolutionHost(hasDirectoryExists: boolean, ...files: File[ } if (hasDirectoryExists) { - const directories = new ts.Map(); + const directories = new Map(); for (const f of files) { - let name = ts.getDirectoryPath(f.name); + let name = getDirectoryPath(f.name); while (true) { directories.set(name, name); - const baseName = ts.getDirectoryPath(name); + const baseName = getDirectoryPath(name); if (baseName === name) { break; } @@ -65,7 +83,7 @@ function createModuleResolutionHost(hasDirectoryExists: boolean, ...files: File[ realpath, directoryExists: path => directories.has(path), fileExists: path => { - assert.isTrue(directories.has(ts.getDirectoryPath(path)), `'fileExists' '${path}' request in non-existing directory`); + assert.isTrue(directories.has(getDirectoryPath(path)), `'fileExists' '${path}' request in non-existing directory`); return map.has(path); }, useCaseSensitiveFileNames: true @@ -85,8 +103,8 @@ function createModuleResolutionHost(hasDirectoryExists: boolean, ...files: File[ describe("unittests:: moduleResolution:: Node module resolution - relative paths", () => { // node module resolution does _not_ implicitly append these extensions to an extensionless path (though will still attempt to load them if explicitly) - const nonImplicitExtensions = [ts.Extension.Mts, ts.Extension.Dmts, ts.Extension.Mjs, ts.Extension.Cts, ts.Extension.Dcts, ts.Extension.Cjs]; - const autoExtensions = ts.filter(ts.supportedTSExtensionsFlat, e => nonImplicitExtensions.indexOf(e) === -1); + const nonImplicitExtensions = [Extension.Mts, Extension.Dmts, Extension.Mjs, Extension.Cts, Extension.Dcts, Extension.Cjs]; + const autoExtensions = filter(supportedTSExtensionsFlat, e => nonImplicitExtensions.indexOf(e) === -1); function testLoadAsFile(containingFileName: string, moduleFileNameNoExt: string, moduleName: string): void { for (const ext of autoExtensions) { test(ext, /*hasDirectoryExists*/ false); @@ -96,17 +114,17 @@ describe("unittests:: moduleResolution:: Node module resolution - relative paths function test(ext: string, hasDirectoryExists: boolean) { const containingFile = { name: containingFileName }; const moduleFile = { name: moduleFileNameNoExt + ext }; - const resolution = ts.nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile)); + const resolution = nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile)); checkResolvedModule(resolution.resolvedModule, createResolvedModule(moduleFile.name)); const failedLookupLocations: string[] = []; - const dir = ts.getDirectoryPath(containingFileName); + const dir = getDirectoryPath(containingFileName); for (const e of autoExtensions) { if (e === ext) { break; } else { - failedLookupLocations.push(ts.normalizePath(ts.getRootLength(moduleName) === 0 ? ts.combinePaths(dir, moduleName) : moduleName) + e); + failedLookupLocations.push(normalizePath(getRootLength(moduleName) === 0 ? combinePaths(dir, moduleName) : moduleName) + e); } } @@ -139,10 +157,10 @@ describe("unittests:: moduleResolution:: Node module resolution - relative paths const containingFile = { name: containingFileName }; const packageJson = { name: packageJsonFileName, content: JSON.stringify({ typings: fieldRef }) }; const moduleFile = { name: moduleFileName }; - const resolution = ts.nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, moduleFile)); + const resolution = nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, moduleFile)); checkResolvedModule(resolution.resolvedModule, createResolvedModule(moduleFile.name)); // expect three failed lookup location - attempt to load module as file with all supported extensions - assert.equal(resolution.failedLookupLocations.length, ts.supportedTSExtensions[0].length); + assert.equal(resolution.failedLookupLocations.length, supportedTSExtensions[0].length); } } @@ -165,7 +183,7 @@ describe("unittests:: moduleResolution:: Node module resolution - relative paths const indexPath = "/node_modules/b/index.d.ts"; const indexFile = { name: indexPath }; - const resolution = ts.nodeModuleNameResolver("b", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, moduleFile, indexFile)); + const resolution = nodeModuleNameResolver("b", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, moduleFile, indexFile)); checkResolvedModule(resolution.resolvedModule, createResolvedModule(indexPath, /*isExternalLibraryImport*/ true)); } @@ -186,7 +204,7 @@ describe("unittests:: moduleResolution:: Node module resolution - relative paths const containingFile = { name: "/a/b/c.ts" }; const packageJson = { name: "/a/b/foo/package.json", content: JSON.stringify({ main: "/c/d" }) }; const indexFile = { name: "/a/b/foo/index.d.ts" }; - const resolution = ts.nodeModuleNameResolver("./foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, indexFile)); + const resolution = nodeModuleNameResolver("./foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, indexFile)); checkResolvedModuleWithFailedLookupLocations(resolution, createResolvedModule(indexFile.name), [ "/a/b/foo.ts", "/a/b/foo.tsx", @@ -207,14 +225,14 @@ describe("unittests:: moduleResolution:: Node module resolution - relative paths describe("unittests:: moduleResolution:: Node module resolution - non-relative paths", () => { it("computes correct commonPrefix for moduleName cache", () => { - const resolutionCache = ts.createModuleResolutionCache("/", (f) => f); + const resolutionCache = createModuleResolutionCache("/", (f) => f); let cache = resolutionCache.getOrCreateCacheForModuleName("a", /*mode*/ undefined); cache.set("/sub", { resolvedModule: { originalPath: undefined, resolvedFileName: "/sub/node_modules/a/index.ts", isExternalLibraryImport: true, - extension: ts.Extension.Ts, + extension: Extension.Ts, }, failedLookupLocations: [], resolutionDiagnostics: [], @@ -228,7 +246,7 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p originalPath: undefined, resolvedFileName: "/sub/directory/node_modules/b/index.ts", isExternalLibraryImport: true, - extension: ts.Extension.Ts, + extension: Extension.Ts, }, failedLookupLocations: [], resolutionDiagnostics: [], @@ -244,7 +262,7 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p originalPath: undefined, resolvedFileName: "/bar/node_modules/c/index.ts", isExternalLibraryImport: true, - extension: ts.Extension.Ts, + extension: Extension.Ts, }, failedLookupLocations: [], resolutionDiagnostics: [], @@ -259,7 +277,7 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p originalPath: undefined, resolvedFileName: "/foo/index.ts", isExternalLibraryImport: true, - extension: ts.Extension.Ts, + extension: Extension.Ts, }, failedLookupLocations: [], resolutionDiagnostics: [], @@ -273,7 +291,7 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p originalPath: undefined, resolvedFileName: "d:/bar/node_modules/e/index.ts", isExternalLibraryImport: true, - extension: ts.Extension.Ts, + extension: Extension.Ts, }, failedLookupLocations: [], resolutionDiagnostics: [], @@ -301,7 +319,7 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p function test(hasDirectoryExists: boolean) { const containingFile = { name: "/a/b/c/d/e.ts" }; const moduleFile = { name: "/a/b/node_modules/foo.ts" }; - const resolution = ts.nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile)); + const resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile)); checkResolvedModuleWithFailedLookupLocations(resolution, createResolvedModule(moduleFile.name, /*isExternalLibraryImport*/ true), [ "/a/b/c/d/node_modules/foo/package.json", "/a/b/c/d/node_modules/foo.ts", @@ -342,7 +360,7 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p function test(hasDirectoryExists: boolean) { const containingFile = { name: "/a/b/c/d/e.ts" }; const moduleFile = { name: "/a/b/node_modules/foo.d.ts" }; - const resolution = ts.nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile)); + const resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile)); checkResolvedModule(resolution.resolvedModule, createResolvedModule(moduleFile.name, /*isExternalLibraryImport*/ true)); } }); @@ -354,7 +372,7 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p function test(hasDirectoryExists: boolean) { const containingFile: File = { name: "/a/node_modules/b/c/node_modules/d/e.ts" }; const moduleFile: File = { name: "/a/node_modules/foo/index.d.ts" }; - const resolution = ts.nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile)); + const resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile)); checkResolvedModuleWithFailedLookupLocations(resolution, createResolvedModule(moduleFile.name, /*isExternalLibraryImport*/ true), [ "/a/node_modules/b/c/node_modules/d/node_modules/foo/package.json", "/a/node_modules/b/c/node_modules/d/node_modules/foo.ts", @@ -420,7 +438,7 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p { name: realFileName, symlinks: [symlinkFileName] }, { name: "/app/node_modules/linked/package.json", content: '{"version": "0.0.0", "main": "./index"}' }, ); - const resolution = ts.nodeModuleNameResolver("linked", "/app/app.ts", { preserveSymlinks }, host); + const resolution = nodeModuleNameResolver("linked", "/app/app.ts", { preserveSymlinks }, host); const resolvedFileName = preserveSymlinks ? symlinkFileName : realFileName; checkResolvedModule(resolution.resolvedModule, createResolvedModule(resolvedFileName, /*isExternalLibraryImport*/ true)); }); @@ -438,15 +456,15 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p content: '{"version": "0.0.0", "main": "./index"}' } ); - const compilerOptions: ts.CompilerOptions = { moduleResolution: ts.ModuleResolutionKind.NodeJs }; - const cache = ts.createModuleResolutionCache("/", (f) => f); - let resolution = ts.resolveModuleName("a", "/sub/dir/foo.ts", compilerOptions, host, cache); + const compilerOptions: CompilerOptions = { moduleResolution: ModuleResolutionKind.NodeJs }; + const cache = createModuleResolutionCache("/", (f) => f); + let resolution = resolveModuleName("a", "/sub/dir/foo.ts", compilerOptions, host, cache); checkResolvedModule(resolution.resolvedModule, createResolvedModule("/modules/a.ts", /*isExternalLibraryImport*/ true)); - resolution = ts.resolveModuleName("a", "/sub/foo.ts", compilerOptions, host, cache); + resolution = resolveModuleName("a", "/sub/foo.ts", compilerOptions, host, cache); checkResolvedModule(resolution.resolvedModule, createResolvedModule("/modules/a.ts", /*isExternalLibraryImport*/ true)); - resolution = ts.resolveModuleName("a", "/foo.ts", compilerOptions, host, cache); + resolution = resolveModuleName("a", "/foo.ts", compilerOptions, host, cache); assert.isUndefined(resolution.resolvedModule, "lookup in parent directory doesn't hit the cache"); }); @@ -456,12 +474,12 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p { name: "/linked/index.d.ts", symlinks: ["/app/node_modules/linked/index.d.ts"] }, { name: "/app/node_modules/linked/package.json", content: '{"version": "0.0.0", "main": "./index"}' }, ); - const cache = ts.createModuleResolutionCache("/", (f) => f); - const compilerOptions: ts.CompilerOptions = { moduleResolution: ts.ModuleResolutionKind.NodeJs }; - checkResolution(ts.resolveModuleName("linked", "/app/src/app.ts", compilerOptions, host, cache)); - checkResolution(ts.resolveModuleName("linked", "/app/lib/main.ts", compilerOptions, host, cache)); + const cache = createModuleResolutionCache("/", (f) => f); + const compilerOptions: CompilerOptions = { moduleResolution: ModuleResolutionKind.NodeJs }; + checkResolution(resolveModuleName("linked", "/app/src/app.ts", compilerOptions, host, cache)); + checkResolution(resolveModuleName("linked", "/app/lib/main.ts", compilerOptions, host, cache)); - function checkResolution(resolution: ts.ResolvedModuleWithFailedLookupLocations) { + function checkResolution(resolution: ResolvedModuleWithFailedLookupLocations) { checkResolvedModule(resolution.resolvedModule, createResolvedModule("/linked/index.d.ts", /*isExternalLibraryImport*/ true)); assert.strictEqual(resolution.resolvedModule!.originalPath, "/app/node_modules/linked/index.d.ts"); } @@ -469,35 +487,35 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p }); describe("unittests:: moduleResolution:: Relative imports", () => { - function test(files: ts.ESMap, currentDirectory: string, rootFiles: string[], expectedFilesCount: number, relativeNamesToCheck: string[]) { - const options: ts.CompilerOptions = { module: ts.ModuleKind.CommonJS }; - const host: ts.CompilerHost = { - getSourceFile: (fileName: string, languageVersion: ts.ScriptTarget) => { - const path = ts.normalizePath(ts.combinePaths(currentDirectory, fileName)); + function test(files: ESMap, currentDirectory: string, rootFiles: string[], expectedFilesCount: number, relativeNamesToCheck: string[]) { + const options: CompilerOptions = { module: ModuleKind.CommonJS }; + const host: CompilerHost = { + getSourceFile: (fileName: string, languageVersion: ScriptTarget) => { + const path = normalizePath(combinePaths(currentDirectory, fileName)); const file = files.get(path); - return file ? ts.createSourceFile(fileName, file, languageVersion) : undefined; + return file ? createSourceFile(fileName, file, languageVersion) : undefined; }, getDefaultLibFileName: () => "lib.d.ts", - writeFile: ts.notImplemented, + writeFile: notImplemented, getCurrentDirectory: () => currentDirectory, getDirectories: () => [], getCanonicalFileName: fileName => fileName.toLowerCase(), getNewLine: () => "\r\n", useCaseSensitiveFileNames: () => false, fileExists: fileName => { - const path = ts.normalizePath(ts.combinePaths(currentDirectory, fileName)); + const path = normalizePath(combinePaths(currentDirectory, fileName)); return files.has(path); }, - readFile: ts.notImplemented, + readFile: notImplemented, }; - const program = ts.createProgram(rootFiles, options, host); + const program = createProgram(rootFiles, options, host); assert.equal(program.getSourceFiles().length, expectedFilesCount); const syntacticDiagnostics = program.getSyntacticDiagnostics(); - assert.equal(syntacticDiagnostics.length, 0, `expect no syntactic diagnostics, got: ${JSON.stringify(Harness.Compiler.minimalDiagnosticsToString(syntacticDiagnostics))}`); + assert.equal(syntacticDiagnostics.length, 0, `expect no syntactic diagnostics, got: ${JSON.stringify(Compiler.minimalDiagnosticsToString(syntacticDiagnostics))}`); const semanticDiagnostics = program.getSemanticDiagnostics(); - assert.equal(semanticDiagnostics.length, 0, `expect no semantic diagnostics, got: ${JSON.stringify(Harness.Compiler.minimalDiagnosticsToString(semanticDiagnostics))}`); + assert.equal(semanticDiagnostics.length, 0, `expect no semantic diagnostics, got: ${JSON.stringify(Compiler.minimalDiagnosticsToString(semanticDiagnostics))}`); // try to get file using a relative name for (const relativeFileName of relativeNamesToCheck) { @@ -506,7 +524,7 @@ describe("unittests:: moduleResolution:: Relative imports", () => { } it("should find all modules", () => { - const files = new ts.Map(ts.getEntries({ + const files = new Map(getEntries({ "/a/b/c/first/shared.ts": ` class A {} export = A`, @@ -525,7 +543,7 @@ export = C; }); it("should find modules in node_modules", () => { - const files = new ts.Map(ts.getEntries({ + const files = new Map(getEntries({ "/parent/node_modules/mod/index.d.ts": "export var x", "/parent/app/myapp.ts": `import {x} from "mod"` })); @@ -533,7 +551,7 @@ export = C; }); it("should find file referenced via absolute and relative names", () => { - const files = new ts.Map(ts.getEntries({ + const files = new Map(getEntries({ "/a/b/c.ts": `/// `, "/a/b/b.ts": "var x" })); @@ -542,96 +560,96 @@ export = C; }); describe("unittests:: moduleResolution:: Files with different casing with forceConsistentCasingInFileNames", () => { - let library: ts.SourceFile; + let library: SourceFile; function test( - files: ts.ESMap, - options: ts.CompilerOptions, + files: ESMap, + options: CompilerOptions, currentDirectory: string, useCaseSensitiveFileNames: boolean, rootFiles: string[], - expectedDiagnostics: (program: ts.Program) => readonly ts.Diagnostic[] + expectedDiagnostics: (program: Program) => readonly Diagnostic[] ): void { - const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); + const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames); if (!useCaseSensitiveFileNames) { const oldFiles = files; - files = new ts.Map(); + files = new Map(); oldFiles.forEach((file, fileName) => { files.set(getCanonicalFileName(fileName), file); }); } - const host: ts.CompilerHost = { - getSourceFile: (fileName: string, languageVersion: ts.ScriptTarget) => { + const host: CompilerHost = { + getSourceFile: (fileName: string, languageVersion: ScriptTarget) => { if (fileName === "lib.d.ts") { if (!library) { - library = ts.createSourceFile("lib.d.ts", "", ts.ScriptTarget.ES5); + library = createSourceFile("lib.d.ts", "", ScriptTarget.ES5); } return library; } - const path = getCanonicalFileName(ts.normalizePath(ts.combinePaths(currentDirectory, fileName))); + const path = getCanonicalFileName(normalizePath(combinePaths(currentDirectory, fileName))); const file = files.get(path); - return file ? ts.createSourceFile(fileName, file, languageVersion) : undefined; + return file ? createSourceFile(fileName, file, languageVersion) : undefined; }, getDefaultLibFileName: () => "lib.d.ts", - writeFile: ts.notImplemented, + writeFile: notImplemented, getCurrentDirectory: () => currentDirectory, getDirectories: () => [], getCanonicalFileName, getNewLine: () => "\r\n", useCaseSensitiveFileNames: () => useCaseSensitiveFileNames, fileExists: fileName => { - const path = getCanonicalFileName(ts.normalizePath(ts.combinePaths(currentDirectory, fileName))); + const path = getCanonicalFileName(normalizePath(combinePaths(currentDirectory, fileName))); return files.has(path); }, - readFile: ts.notImplemented, + readFile: notImplemented, }; - const program = ts.createProgram(rootFiles, options, host); - const diagnostics = ts.sortAndDeduplicateDiagnostics([...program.getSemanticDiagnostics(), ...program.getOptionsDiagnostics()]); - assert.deepEqual(diagnostics, ts.sortAndDeduplicateDiagnostics(expectedDiagnostics(program))); + const program = createProgram(rootFiles, options, host); + const diagnostics = sortAndDeduplicateDiagnostics([...program.getSemanticDiagnostics(), ...program.getOptionsDiagnostics()]); + assert.deepEqual(diagnostics, sortAndDeduplicateDiagnostics(expectedDiagnostics(program))); } it("should succeed when the same file is referenced using absolute and relative names", () => { - const files = new ts.Map(ts.getEntries({ + const files = new Map(getEntries({ "/a/b/c.ts": `/// `, "/a/b/d.ts": "var x" })); test( files, - { module: ts.ModuleKind.AMD }, + { module: ModuleKind.AMD }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "/a/b/d.ts"], - () => ts.emptyArray + () => emptyArray ); }); it("should fail when two files used in program differ only in casing (tripleslash references)", () => { - const files = new ts.Map(ts.getEntries({ + const files = new Map(getEntries({ "/a/b/c.ts": `/// `, "/a/b/d.ts": "var x" })); test( files, - { module: ts.ModuleKind.AMD, forceConsistentCasingInFileNames: true }, + { module: ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "d.ts"], program => [{ - ...ts.tscWatch.getDiagnosticOfFileFromProgram( + ...getDiagnosticOfFileFromProgram( program, "c.ts", `/// `.indexOf(`D.ts`), "D.ts".length, - ts.tscWatch.getDiagnosticMessageChain( - ts.Diagnostics.Already_included_file_name_0_differs_from_file_name_1_only_in_casing, + getDiagnosticMessageChain( + Diagnostics.Already_included_file_name_0_differs_from_file_name_1_only_in_casing, ["D.ts", "d.ts"], [ - ts.tscWatch.getDiagnosticMessageChain( - ts.Diagnostics.The_file_is_in_the_program_because_Colon, - ts.emptyArray, + getDiagnosticMessageChain( + Diagnostics.The_file_is_in_the_program_because_Colon, + emptyArray, [ - ts.tscWatch.getDiagnosticMessageChain(ts.Diagnostics.Referenced_via_0_from_file_1, ["D.ts", "c.ts"]), - ts.tscWatch.getDiagnosticMessageChain(ts.Diagnostics.Root_file_specified_for_compilation) + getDiagnosticMessageChain(Diagnostics.Referenced_via_0_from_file_1, ["D.ts", "c.ts"]), + getDiagnosticMessageChain(Diagnostics.Root_file_specified_for_compilation) ] ) ], @@ -643,32 +661,32 @@ describe("unittests:: moduleResolution:: Files with different casing with forceC }); it("should fail when two files used in program differ only in casing (imports)", () => { - const files = new ts.Map(ts.getEntries({ + const files = new Map(getEntries({ "/a/b/c.ts": `import {x} from "D"`, "/a/b/d.ts": "export var x" })); test( files, - { module: ts.ModuleKind.AMD, forceConsistentCasingInFileNames: true }, + { module: ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /*useCaseSensitiveFileNames*/ false, ["c.ts", "d.ts"], program => [{ - ...ts.tscWatch.getDiagnosticOfFileFromProgram( + ...getDiagnosticOfFileFromProgram( program, "c.ts", `import {x} from "D"`.indexOf(`"D"`), `"D"`.length, - ts.tscWatch.getDiagnosticMessageChain( - ts.Diagnostics.Already_included_file_name_0_differs_from_file_name_1_only_in_casing, + getDiagnosticMessageChain( + Diagnostics.Already_included_file_name_0_differs_from_file_name_1_only_in_casing, ["/a/b/D.ts", "d.ts"], [ - ts.tscWatch.getDiagnosticMessageChain( - ts.Diagnostics.The_file_is_in_the_program_because_Colon, - ts.emptyArray, + getDiagnosticMessageChain( + Diagnostics.The_file_is_in_the_program_because_Colon, + emptyArray, [ - ts.tscWatch.getDiagnosticMessageChain(ts.Diagnostics.Imported_via_0_from_file_1, [`"D"`, "c.ts"]), - ts.tscWatch.getDiagnosticMessageChain(ts.Diagnostics.Root_file_specified_for_compilation) + getDiagnosticMessageChain(Diagnostics.Imported_via_0_from_file_1, [`"D"`, "c.ts"]), + getDiagnosticMessageChain(Diagnostics.Root_file_specified_for_compilation) ] ) ], @@ -680,32 +698,32 @@ describe("unittests:: moduleResolution:: Files with different casing with forceC }); it("should fail when two files used in program differ only in casing (imports, relative module names)", () => { - const files = new ts.Map(ts.getEntries({ + const files = new Map(getEntries({ "moduleA.ts": `import {x} from "./ModuleB"`, "moduleB.ts": "export var x" })); test( files, - { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, + { module: ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /*useCaseSensitiveFileNames*/ false, ["moduleA.ts", "moduleB.ts"], program => [{ - ...ts.tscWatch.getDiagnosticOfFileFromProgram( + ...getDiagnosticOfFileFromProgram( program, "moduleA.ts", `import {x} from "./ModuleB"`.indexOf(`"./ModuleB"`), `"./ModuleB"`.length, - ts.tscWatch.getDiagnosticMessageChain( - ts.Diagnostics.Already_included_file_name_0_differs_from_file_name_1_only_in_casing, + getDiagnosticMessageChain( + Diagnostics.Already_included_file_name_0_differs_from_file_name_1_only_in_casing, ["ModuleB.ts", "moduleB.ts"], [ - ts.tscWatch.getDiagnosticMessageChain( - ts.Diagnostics.The_file_is_in_the_program_because_Colon, - ts.emptyArray, + getDiagnosticMessageChain( + Diagnostics.The_file_is_in_the_program_because_Colon, + emptyArray, [ - ts.tscWatch.getDiagnosticMessageChain(ts.Diagnostics.Imported_via_0_from_file_1, [`"./ModuleB"`, "moduleA.ts"]), - ts.tscWatch.getDiagnosticMessageChain(ts.Diagnostics.Root_file_specified_for_compilation) + getDiagnosticMessageChain(Diagnostics.Imported_via_0_from_file_1, [`"./ModuleB"`, "moduleA.ts"]), + getDiagnosticMessageChain(Diagnostics.Root_file_specified_for_compilation) ] ) ], @@ -717,33 +735,33 @@ describe("unittests:: moduleResolution:: Files with different casing with forceC }); it("should fail when two files exist on disk that differs only in casing", () => { - const files = new ts.Map(ts.getEntries({ + const files = new Map(getEntries({ "/a/b/c.ts": `import {x} from "D"`, "/a/b/D.ts": "export var x", "/a/b/d.ts": "export var y" })); test( files, - { module: ts.ModuleKind.AMD }, + { module: ModuleKind.AMD }, "/a/b", /*useCaseSensitiveFileNames*/ true, ["c.ts", "d.ts"], program => [{ - ...ts.tscWatch.getDiagnosticOfFileFromProgram( + ...getDiagnosticOfFileFromProgram( program, "c.ts", `import {x} from "D"`.indexOf(`"D"`), `"D"`.length, - ts.tscWatch.getDiagnosticMessageChain( - ts.Diagnostics.Already_included_file_name_0_differs_from_file_name_1_only_in_casing, + getDiagnosticMessageChain( + Diagnostics.Already_included_file_name_0_differs_from_file_name_1_only_in_casing, ["/a/b/D.ts", "d.ts"], [ - ts.tscWatch.getDiagnosticMessageChain( - ts.Diagnostics.The_file_is_in_the_program_because_Colon, - ts.emptyArray, + getDiagnosticMessageChain( + Diagnostics.The_file_is_in_the_program_because_Colon, + emptyArray, [ - ts.tscWatch.getDiagnosticMessageChain(ts.Diagnostics.Imported_via_0_from_file_1, [`"D"`, "c.ts"]), - ts.tscWatch.getDiagnosticMessageChain(ts.Diagnostics.Root_file_specified_for_compilation) + getDiagnosticMessageChain(Diagnostics.Imported_via_0_from_file_1, [`"D"`, "c.ts"]), + getDiagnosticMessageChain(Diagnostics.Root_file_specified_for_compilation) ] ) ], @@ -755,55 +773,55 @@ describe("unittests:: moduleResolution:: Files with different casing with forceC }); it("should fail when module name in 'require' calls has inconsistent casing", () => { - const files = new ts.Map(ts.getEntries({ + const files = new Map(getEntries({ "moduleA.ts": `import a = require("./ModuleC")`, "moduleB.ts": `import a = require("./moduleC")`, "moduleC.ts": "export var x" })); test( files, - { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, + { module: ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /*useCaseSensitiveFileNames*/ false, ["moduleA.ts", "moduleB.ts", "moduleC.ts"], program => { const importInA = { - ...ts.tscWatch.getDiagnosticOfFileFromProgram( + ...getDiagnosticOfFileFromProgram( program, "moduleA.ts", `import a = require("./ModuleC")`.indexOf(`"./ModuleC"`), `"./ModuleC"`.length, - ts.Diagnostics.File_is_included_via_import_here, + Diagnostics.File_is_included_via_import_here, ), reportsUnnecessary: undefined, reportsDeprecated: undefined }; const importInB = { - ...ts.tscWatch.getDiagnosticOfFileFromProgram( + ...getDiagnosticOfFileFromProgram( program, "moduleB.ts", `import a = require("./moduleC")`.indexOf(`"./moduleC"`), `"./moduleC"`.length, - ts.Diagnostics.File_is_included_via_import_here, + Diagnostics.File_is_included_via_import_here, ), reportsUnnecessary: undefined, reportsDeprecated: undefined }; - const importHereInA = ts.tscWatch.getDiagnosticMessageChain(ts.Diagnostics.Imported_via_0_from_file_1, [`"./ModuleC"`, "moduleA.ts"]); - const importHereInB = ts.tscWatch.getDiagnosticMessageChain(ts.Diagnostics.Imported_via_0_from_file_1, [`"./moduleC"`, "moduleB.ts"]); - const details = [ts.tscWatch.getDiagnosticMessageChain( - ts.Diagnostics.The_file_is_in_the_program_because_Colon, - ts.emptyArray, - [importHereInA, importHereInB, ts.tscWatch.getDiagnosticMessageChain(ts.Diagnostics.Root_file_specified_for_compilation)] + const importHereInA = getDiagnosticMessageChain(Diagnostics.Imported_via_0_from_file_1, [`"./ModuleC"`, "moduleA.ts"]); + const importHereInB = getDiagnosticMessageChain(Diagnostics.Imported_via_0_from_file_1, [`"./moduleC"`, "moduleB.ts"]); + const details = [getDiagnosticMessageChain( + Diagnostics.The_file_is_in_the_program_because_Colon, + emptyArray, + [importHereInA, importHereInB, getDiagnosticMessageChain(Diagnostics.Root_file_specified_for_compilation)] )]; return [ { - ...ts.tscWatch.getDiagnosticOfFileFrom( + ...getDiagnosticOfFileFrom( importInA.file, importInA.start, importInA.length, - ts.tscWatch.getDiagnosticMessageChain( - ts.Diagnostics.Already_included_file_name_0_differs_from_file_name_1_only_in_casing, + getDiagnosticMessageChain( + Diagnostics.Already_included_file_name_0_differs_from_file_name_1_only_in_casing, ["ModuleC.ts", "moduleC.ts" ], details, ) @@ -811,12 +829,12 @@ describe("unittests:: moduleResolution:: Files with different casing with forceC relatedInformation: [importInB] }, { - ...ts.tscWatch.getDiagnosticOfFileFrom( + ...getDiagnosticOfFileFrom( importInB.file, importInB.start, importInB.length, - ts.tscWatch.getDiagnosticMessageChain( - ts.Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, + getDiagnosticMessageChain( + Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, ["moduleC.ts", "ModuleC.ts"], details, ) @@ -829,7 +847,7 @@ describe("unittests:: moduleResolution:: Files with different casing with forceC }); it("should fail when module names in 'require' calls has inconsistent casing and current directory has uppercase chars", () => { - const files = new ts.Map(ts.getEntries({ + const files = new Map(getEntries({ "/a/B/c/moduleA.ts": `import a = require("./ModuleC")`, "/a/B/c/moduleB.ts": `import a = require("./moduleC")`, "/a/B/c/moduleC.ts": "export var x", @@ -840,26 +858,26 @@ import b = require("./moduleB"); })); test( files, - { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, + { module: ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], program => [{ - ...ts.tscWatch.getDiagnosticOfFileFromProgram( + ...getDiagnosticOfFileFromProgram( program, "moduleB.ts", `import a = require("./moduleC")`.indexOf(`"./moduleC"`), `"./moduleC"`.length, - ts.tscWatch.getDiagnosticMessageChain( - ts.Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, + getDiagnosticMessageChain( + Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, ["/a/B/c/moduleC.ts", "/a/B/c/ModuleC.ts"], [ - ts.tscWatch.getDiagnosticMessageChain( - ts.Diagnostics.The_file_is_in_the_program_because_Colon, - ts.emptyArray, + getDiagnosticMessageChain( + Diagnostics.The_file_is_in_the_program_because_Colon, + emptyArray, [ - ts.tscWatch.getDiagnosticMessageChain(ts.Diagnostics.Imported_via_0_from_file_1, [`"./ModuleC"`, "/a/B/c/moduleA.ts"]), - ts.tscWatch.getDiagnosticMessageChain(ts.Diagnostics.Imported_via_0_from_file_1, [`"./moduleC"`, "/a/B/c/moduleB.ts"]) + getDiagnosticMessageChain(Diagnostics.Imported_via_0_from_file_1, [`"./ModuleC"`, "/a/B/c/moduleA.ts"]), + getDiagnosticMessageChain(Diagnostics.Imported_via_0_from_file_1, [`"./moduleC"`, "/a/B/c/moduleB.ts"]) ] ) ], @@ -867,12 +885,12 @@ import b = require("./moduleB"); ), relatedInformation: [ { - ...ts.tscWatch.getDiagnosticOfFileFromProgram( + ...getDiagnosticOfFileFromProgram( program, "moduleA.ts", `import a = require("./ModuleC")`.indexOf(`"./ModuleC"`), `"./ModuleC"`.length, - ts.Diagnostics.File_is_included_via_import_here, + Diagnostics.File_is_included_via_import_here, ), reportsUnnecessary: undefined, reportsDeprecated: undefined @@ -882,7 +900,7 @@ import b = require("./moduleB"); ); }); it("should not fail when module names in 'require' calls has consistent casing and current directory has uppercase chars", () => { - const files = new ts.Map(ts.getEntries({ + const files = new Map(getEntries({ "/a/B/c/moduleA.ts": `import a = require("./moduleC")`, "/a/B/c/moduleB.ts": `import a = require("./moduleC")`, "/a/B/c/moduleC.ts": "export var x", @@ -893,27 +911,27 @@ import b = require("./moduleB"); })); test( files, - { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, + { module: ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], - () => ts.emptyArray + () => emptyArray ); }); it("should succeed when the two files in program differ only in drive letter in their names", () => { - const files = new ts.Map(ts.getEntries({ + const files = new Map(getEntries({ "d:/someFolder/moduleA.ts": `import a = require("D:/someFolder/moduleC")`, "d:/someFolder/moduleB.ts": `import a = require("./moduleC")`, "D:/someFolder/moduleC.ts": "export const x = 10", })); test( files, - { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, + { module: ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "d:/someFolder", /*useCaseSensitiveFileNames*/ false, ["d:/someFolder/moduleA.ts", "d:/someFolder/moduleB.ts"], - () => ts.emptyArray + () => emptyArray ); }); }); @@ -929,18 +947,18 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( const file2: File = { name: "/root/folder2/file2.ts" }; const file3: File = { name: "/root/folder2/file3.ts" }; const host = createModuleResolutionHost(hasDirectoryExists, file1, file2, file3); - for (const moduleResolution of [ ts.ModuleResolutionKind.NodeJs, ts.ModuleResolutionKind.Classic ]) { - const options: ts.CompilerOptions = { moduleResolution, baseUrl: "/root" }; + for (const moduleResolution of [ ModuleResolutionKind.NodeJs, ModuleResolutionKind.Classic ]) { + const options: CompilerOptions = { moduleResolution, baseUrl: "/root" }; { - const result = ts.resolveModuleName("folder2/file2", file1.name, options, host); + const result = resolveModuleName("folder2/file2", file1.name, options, host); checkResolvedModuleWithFailedLookupLocations(result, createResolvedModule(file2.name), []); } { - const result = ts.resolveModuleName("./file3", file2.name, options, host); + const result = resolveModuleName("./file3", file2.name, options, host); checkResolvedModuleWithFailedLookupLocations(result, createResolvedModule(file3.name), []); } { - const result = ts.resolveModuleName("/root/folder1/file1", file2.name, options, host); + const result = resolveModuleName("/root/folder1/file1", file2.name, options, host); checkResolvedModuleWithFailedLookupLocations(result, createResolvedModule(file1.name), []); } } @@ -960,7 +978,7 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( const m3Typings: File = { name: "/root/m3/dist/typings.d.ts" }; const m4: File = { name: "/root/node_modules/m4.ts" }; // fallback to node - const options: ts.CompilerOptions = { moduleResolution: ts.ModuleResolutionKind.NodeJs, baseUrl: "/root" }; + const options: CompilerOptions = { moduleResolution: ModuleResolutionKind.NodeJs, baseUrl: "/root" }; const host = createModuleResolutionHost(hasDirectoryExists, main, m1, m2, m3, m3Typings, m4); check("m1", main, m1); @@ -969,7 +987,7 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( check("m4", main, m4, /*isExternalLibraryImport*/ true); function check(name: string, caller: File, expected: File, isExternalLibraryImport = false) { - const result = ts.resolveModuleName(name, caller.name, options, host); + const result = resolveModuleName(name, caller.name, options, host); checkResolvedModule(result.resolvedModule, createResolvedModule(expected.name, isExternalLibraryImport)); } } @@ -984,14 +1002,14 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( const m1: File = { name: "/root/x/m1.ts" }; // load from base url const m2: File = { name: "/m2.ts" }; // fallback to classic - const options: ts.CompilerOptions = { moduleResolution: ts.ModuleResolutionKind.Classic, baseUrl: "/root/x", jsx: ts.JsxEmit.React }; + const options: CompilerOptions = { moduleResolution: ModuleResolutionKind.Classic, baseUrl: "/root/x", jsx: JsxEmit.React }; const host = createModuleResolutionHost(hasDirectoryExists, main, m1, m2); check("m1", main, m1); check("m2", main, m2); function check(name: string, caller: File, expected: File) { - const result = ts.resolveModuleName(name, caller.name, options, host); + const result = resolveModuleName(name, caller.name, options, host); checkResolvedModule(result.resolvedModule, createResolvedModule(expected.name)); } } @@ -1013,10 +1031,10 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( const file6: File = { name: "/root/node_modules/file6.ts" }; // fallback to node const host = createModuleResolutionHost(hasDirectoryExists, file1, file2, file3, file4, file4Typings, file5, file6); - const options: ts.CompilerOptions = { - moduleResolution: ts.ModuleResolutionKind.NodeJs, + const options: CompilerOptions = { + moduleResolution: ModuleResolutionKind.NodeJs, baseUrl: "/root", - jsx: ts.JsxEmit.React, + jsx: JsxEmit.React, paths: { "*": [ "*", @@ -1142,7 +1160,7 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( ], /*isExternalLibraryImport*/ true); function check(name: string, expected: File, expectedFailedLookups: string[], isExternalLibraryImport = false) { - const result = ts.resolveModuleName(name, main.name, options, host); + const result = resolveModuleName(name, main.name, options, host); checkResolvedModuleWithFailedLookupLocations(result, createResolvedModule(expected.name, isExternalLibraryImport), expectedFailedLookups); } } @@ -1160,10 +1178,10 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( const file3: File = { name: "/folder1/file3.ts" }; // fallback to classic const host = createModuleResolutionHost(hasDirectoryExists, file1, file2, file3); - const options: ts.CompilerOptions = { - moduleResolution: ts.ModuleResolutionKind.Classic, + const options: CompilerOptions = { + moduleResolution: ModuleResolutionKind.Classic, baseUrl: "/root", - jsx: ts.JsxEmit.React, + jsx: JsxEmit.React, paths: { "*": [ "*", @@ -1205,7 +1223,7 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( ]); function check(name: string, expected: File, expectedFailedLookups: string[]) { - const result = ts.resolveModuleName(name, main.name, options, host); + const result = resolveModuleName(name, main.name, options, host); checkResolvedModuleWithFailedLookupLocations(result, createResolvedModule(expected.name), expectedFailedLookups); } } @@ -1221,8 +1239,8 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( const file2: File = { name: "/root/generated/folder1/file2.ts" }; const file3: File = { name: "/root/generated/folder2/file3.ts" }; const host = createModuleResolutionHost(hasDirectoryExists, file1, file1_1, file2, file3); - const options: ts.CompilerOptions = { - moduleResolution: ts.ModuleResolutionKind.NodeJs, + const options: CompilerOptions = { + moduleResolution: ModuleResolutionKind.NodeJs, rootDirs: [ "/root", "/root/generated/" @@ -1278,7 +1296,7 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( ]); function check(name: string, container: File, expected: File, expectedFailedLookups: string[]) { - const result = ts.resolveModuleName(name, container.name, options, host); + const result = resolveModuleName(name, container.name, options, host); checkResolvedModuleWithFailedLookupLocations(result, createResolvedModule(expected.name), expectedFailedLookups); } } @@ -1293,9 +1311,9 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( const file3: File = { name: "/root/generated/folder2/file3.ts" }; const file4: File = { name: "/folder1/file1_1.ts" }; const host = createModuleResolutionHost(hasDirectoryExists, file1, file2, file3, file4); - const options: ts.CompilerOptions = { - moduleResolution: ts.ModuleResolutionKind.Classic, - jsx: ts.JsxEmit.React, + const options: CompilerOptions = { + moduleResolution: ModuleResolutionKind.Classic, + jsx: JsxEmit.React, rootDirs: [ "/root", "/root/generated/" @@ -1332,7 +1350,7 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( ]); function check(name: string, container: File, expected: File, expectedFailedLookups: string[]) { - const result = ts.resolveModuleName(name, container.name, options, host); + const result = resolveModuleName(name, container.name, options, host); checkResolvedModuleWithFailedLookupLocations(result, createResolvedModule(expected.name), expectedFailedLookups); } } @@ -1347,14 +1365,14 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( const libsPackage: File = { name: "/root/src/libs/guid/package.json", content: JSON.stringify({ typings: "dist/guid.d.ts" }) }; const libsTypings: File = { name: "/root/src/libs/guid/dist/guid.d.ts" }; const host = createModuleResolutionHost(hasDirectoryExists, app, libsPackage, libsTypings); - const options: ts.CompilerOptions = { - moduleResolution: ts.ModuleResolutionKind.NodeJs, + const options: CompilerOptions = { + moduleResolution: ModuleResolutionKind.NodeJs, baseUrl: "/root", paths: { "libs/guid": [ "src/libs/guid" ] } }; - const result = ts.resolveModuleName("libs/guid", app.name, options, host); + const result = resolveModuleName("libs/guid", app.name, options, host); checkResolvedModuleWithFailedLookupLocations(result, createResolvedModule(libsTypings.name), [ // first try to load module as file "/root/src/libs/guid.ts", @@ -1367,13 +1385,13 @@ describe("unittests:: moduleResolution:: baseUrl augmented module resolution", ( describe("unittests:: moduleResolution:: ModuleResolutionHost.directoryExists", () => { it("No 'fileExists' calls if containing directory is missing", () => { - const host: ts.ModuleResolutionHost = { - readFile: ts.notImplemented, - fileExists: ts.notImplemented, + const host: ModuleResolutionHost = { + readFile: notImplemented, + fileExists: notImplemented, directoryExists: _ => false }; - const result = ts.resolveModuleName("someName", "/a/b/c/d", { moduleResolution: ts.ModuleResolutionKind.NodeJs }, host); + const result = resolveModuleName("someName", "/a/b/c/d", { moduleResolution: ModuleResolutionKind.NodeJs }, host); assert(!result.resolvedModule); }); }); @@ -1381,7 +1399,7 @@ describe("unittests:: moduleResolution:: ModuleResolutionHost.directoryExists", describe("unittests:: moduleResolution:: Type reference directive resolution: ", () => { function testWorker(hasDirectoryExists: boolean, typesRoot: string | undefined, typeDirective: string, primary: boolean, initialFile: File, targetFile: File, ...otherFiles: File[]) { const host = createModuleResolutionHost(hasDirectoryExists, ...[initialFile, targetFile].concat(...otherFiles)); - const result = ts.resolveTypeReferenceDirective(typeDirective, initialFile.name, typesRoot ? { typeRoots: [typesRoot] } : {}, host); + const result = resolveTypeReferenceDirective(typeDirective, initialFile.name, typesRoot ? { typeRoots: [typesRoot] } : {}, host); assert(result.resolvedTypeReferenceDirective!.resolvedFileName !== undefined, "expected type directive to be resolved"); assert.equal(result.resolvedTypeReferenceDirective!.resolvedFileName, targetFile.name, "unexpected result of type reference resolution"); assert.equal(result.resolvedTypeReferenceDirective!.primary, primary, "unexpected 'primary' value"); @@ -1470,13 +1488,13 @@ describe("unittests:: moduleResolution:: Type reference directive resolution: ", const f4 = { name: "/root/src/a/b/c/d/f/node_modules/lib/index.d.ts", content: `declare var x: number;` }; const files = [f1, f2, f3, f4]; - const names = ts.map(files, f => f.name); - const sourceFiles = ts.arrayToMap(ts.map(files, f => ts.createSourceFile(f.name, f.content, ts.ScriptTarget.ES2015)), f => f.fileName); - const compilerHost: ts.CompilerHost = { + const names = map(files, f => f.name); + const sourceFiles = arrayToMap(map(files, f => createSourceFile(f.name, f.content, ScriptTarget.ES2015)), f => f.fileName); + const compilerHost: CompilerHost = { fileExists: fileName => sourceFiles.has(fileName), getSourceFile: fileName => sourceFiles.get(fileName), getDefaultLibFileName: () => "lib.d.ts", - writeFile: ts.notImplemented, + writeFile: notImplemented, getCurrentDirectory: () => "/", getDirectories: () => [], getCanonicalFileName: f => f.toLowerCase(), @@ -1487,12 +1505,12 @@ describe("unittests:: moduleResolution:: Type reference directive resolution: ", return file && file.text; }, }; - const program1 = ts.createProgram(names, {}, compilerHost); + const program1 = createProgram(names, {}, compilerHost); const diagnostics1 = program1.getOptionsDiagnostics(); assert.equal(diagnostics1.length, 1, "expected one diagnostic"); - const program2 = ts.createProgram(names, {}, compilerHost, program1); - assert.isTrue(program2.structureIsReused === ts.StructureIsReused.Completely); + const program2 = createProgram(names, {}, compilerHost, program1); + assert.isTrue(program2.structureIsReused === StructureIsReused.Completely); const diagnostics2 = program2.getOptionsDiagnostics(); assert.equal(diagnostics2.length, 1, "expected one diagnostic"); assert.deepEqual(diagnostics1[0].messageText, diagnostics2[0].messageText, "expected one diagnostic"); @@ -1510,21 +1528,21 @@ describe("unittests:: moduleResolution:: Type reference directive resolution: ", export function foo(): Stat; }` }; - const file = ts.createSourceFile(f.name, f.content, ts.ScriptTarget.ES2015); - const compilerHost: ts.CompilerHost = { + const file = createSourceFile(f.name, f.content, ScriptTarget.ES2015); + const compilerHost: CompilerHost = { fileExists: fileName => fileName === file.fileName, getSourceFile: fileName => fileName === file.fileName ? file : undefined, getDefaultLibFileName: () => "lib.d.ts", - writeFile: ts.notImplemented, + writeFile: notImplemented, getCurrentDirectory: () => "/", getDirectories: () => [], getCanonicalFileName: f => f.toLowerCase(), getNewLine: () => "\r\n", useCaseSensitiveFileNames: () => false, readFile: fileName => fileName === file.fileName ? file.text : undefined, - resolveModuleNames: ts.notImplemented, + resolveModuleNames: notImplemented, }; - ts.createProgram([f.name], {}, compilerHost); + createProgram([f.name], {}, compilerHost); }); it("Modules in .ts file are not checked in the same file", () => { @@ -1539,12 +1557,12 @@ describe("unittests:: moduleResolution:: Type reference directive resolution: ", export function foo(): Stat; }` }; - const file = ts.createSourceFile(f.name, f.content, ts.ScriptTarget.ES2015); - const compilerHost: ts.CompilerHost = { + const file = createSourceFile(f.name, f.content, ScriptTarget.ES2015); + const compilerHost: CompilerHost = { fileExists: fileName => fileName === file.fileName, getSourceFile: fileName => fileName === file.fileName ? file : undefined, getDefaultLibFileName: () => "lib.d.ts", - writeFile: ts.notImplemented, + writeFile: notImplemented, getCurrentDirectory: () => "/", getDirectories: () => [], getCanonicalFileName: f => f.toLowerCase(), @@ -1556,7 +1574,7 @@ describe("unittests:: moduleResolution:: Type reference directive resolution: ", return [undefined!]; // TODO: GH#18217 } }; - ts.createProgram([f.name], {}, compilerHost); + createProgram([f.name], {}, compilerHost); }); describe("can be resolved when typeReferenceDirective is relative and in a sibling folder", () => { const initialFile = { name: "/root/src/background/app.ts" }; diff --git a/src/testRunner/unittests/parsePseudoBigInt.ts b/src/testRunner/unittests/parsePseudoBigInt.ts index abb9b1a5a88f1..e5af491f42bd2 100644 --- a/src/testRunner/unittests/parsePseudoBigInt.ts +++ b/src/testRunner/unittests/parsePseudoBigInt.ts @@ -1,4 +1,4 @@ -import * as ts from "../_namespaces/ts"; +import { parsePseudoBigInt } from "../../compiler/utilities"; describe("unittests:: BigInt literal base conversions", () => { describe("parsePseudoBigInt", () => { @@ -11,7 +11,7 @@ describe("unittests:: BigInt literal base conversions", () => { for (const testNumber of testNumbers) { for (let leadingZeros = 0; leadingZeros < 10; leadingZeros++) { assert.equal( - ts.parsePseudoBigInt("0".repeat(leadingZeros) + testNumber + "n"), + parsePseudoBigInt("0".repeat(leadingZeros) + testNumber + "n"), String(testNumber) ); } @@ -22,7 +22,7 @@ describe("unittests:: BigInt literal base conversions", () => { for (let leadingZeros = 0; leadingZeros < 10; leadingZeros++) { const binary = "0".repeat(leadingZeros) + testNumber.toString(2) + "n"; for (const prefix of ["0b", "0B"]) { - assert.equal(ts.parsePseudoBigInt(prefix + binary), String(testNumber)); + assert.equal(parsePseudoBigInt(prefix + binary), String(testNumber)); } } } @@ -32,7 +32,7 @@ describe("unittests:: BigInt literal base conversions", () => { for (let leadingZeros = 0; leadingZeros < 10; leadingZeros++) { const octal = "0".repeat(leadingZeros) + testNumber.toString(8) + "n"; for (const prefix of ["0o", "0O"]) { - assert.equal(ts.parsePseudoBigInt(prefix + octal), String(testNumber)); + assert.equal(parsePseudoBigInt(prefix + octal), String(testNumber)); } } } @@ -43,7 +43,7 @@ describe("unittests:: BigInt literal base conversions", () => { const hex = "0".repeat(leadingZeros) + testNumber.toString(16) + "n"; for (const prefix of ["0x", "0X"]) { for (const hexCase of [hex.toLowerCase(), hex.toUpperCase()]) { - assert.equal(ts.parsePseudoBigInt(prefix + hexCase), String(testNumber)); + assert.equal(parsePseudoBigInt(prefix + hexCase), String(testNumber)); } } } @@ -51,19 +51,19 @@ describe("unittests:: BigInt literal base conversions", () => { }); it("can parse large literals", () => { assert.equal( - ts.parsePseudoBigInt("123456789012345678901234567890n"), + parsePseudoBigInt("123456789012345678901234567890n"), "123456789012345678901234567890" ); assert.equal( - ts.parsePseudoBigInt("0b1100011101110100100001111111101101100001101110011111000001110111001001110001111110000101011010010n"), + parsePseudoBigInt("0b1100011101110100100001111111101101100001101110011111000001110111001001110001111110000101011010010n"), "123456789012345678901234567890" ); assert.equal( - ts.parsePseudoBigInt("0o143564417755415637016711617605322n"), + parsePseudoBigInt("0o143564417755415637016711617605322n"), "123456789012345678901234567890" ); assert.equal( - ts.parsePseudoBigInt("0x18ee90ff6c373e0ee4e3f0ad2n"), + parsePseudoBigInt("0x18ee90ff6c373e0ee4e3f0ad2n"), "123456789012345678901234567890" ); }); diff --git a/src/testRunner/unittests/paths.ts b/src/testRunner/unittests/paths.ts index 0815e633aff7c..ef800d35c052e 100644 --- a/src/testRunner/unittests/paths.ts +++ b/src/testRunner/unittests/paths.ts @@ -1,311 +1,316 @@ -import * as ts from "../_namespaces/ts"; +import { toFileNameLowerCase } from "../../compiler/core"; +import { + combinePaths, getAnyExtensionFromPath, getBaseFileName, getDirectoryPath, getPathComponents, + getRelativePathFromDirectory, getRootLength, isRootedDiskPath, isUrl, normalizeSlashes, reducePathComponents, + resolvePath, +} from "../../compiler/path"; describe("unittests:: core paths", () => { it("normalizeSlashes", () => { - assert.strictEqual(ts.normalizeSlashes("a"), "a"); - assert.strictEqual(ts.normalizeSlashes("a/b"), "a/b"); - assert.strictEqual(ts.normalizeSlashes("a\\b"), "a/b"); - assert.strictEqual(ts.normalizeSlashes("\\\\server\\path"), "//server/path"); + assert.strictEqual(normalizeSlashes("a"), "a"); + assert.strictEqual(normalizeSlashes("a/b"), "a/b"); + assert.strictEqual(normalizeSlashes("a\\b"), "a/b"); + assert.strictEqual(normalizeSlashes("\\\\server\\path"), "//server/path"); }); it("getRootLength", () => { - assert.strictEqual(ts.getRootLength("a"), 0); - assert.strictEqual(ts.getRootLength("/"), 1); - assert.strictEqual(ts.getRootLength("/path"), 1); - assert.strictEqual(ts.getRootLength("c:"), 2); - assert.strictEqual(ts.getRootLength("c:d"), 0); - assert.strictEqual(ts.getRootLength("c:/"), 3); - assert.strictEqual(ts.getRootLength("c:\\"), 3); - assert.strictEqual(ts.getRootLength("//server"), 8); - assert.strictEqual(ts.getRootLength("//server/share"), 9); - assert.strictEqual(ts.getRootLength("\\\\server"), 8); - assert.strictEqual(ts.getRootLength("\\\\server\\share"), 9); - assert.strictEqual(ts.getRootLength("file:///"), 8); - assert.strictEqual(ts.getRootLength("file:///path"), 8); - assert.strictEqual(ts.getRootLength("file:///c:"), 10); - assert.strictEqual(ts.getRootLength("file:///c:d"), 8); - assert.strictEqual(ts.getRootLength("file:///c:/path"), 11); - assert.strictEqual(ts.getRootLength("file:///c%3a"), 12); - assert.strictEqual(ts.getRootLength("file:///c%3ad"), 8); - assert.strictEqual(ts.getRootLength("file:///c%3a/path"), 13); - assert.strictEqual(ts.getRootLength("file:///c%3A"), 12); - assert.strictEqual(ts.getRootLength("file:///c%3Ad"), 8); - assert.strictEqual(ts.getRootLength("file:///c%3A/path"), 13); - assert.strictEqual(ts.getRootLength("file://localhost"), 16); - assert.strictEqual(ts.getRootLength("file://localhost/"), 17); - assert.strictEqual(ts.getRootLength("file://localhost/path"), 17); - assert.strictEqual(ts.getRootLength("file://localhost/c:"), 19); - assert.strictEqual(ts.getRootLength("file://localhost/c:d"), 17); - assert.strictEqual(ts.getRootLength("file://localhost/c:/path"), 20); - assert.strictEqual(ts.getRootLength("file://localhost/c%3a"), 21); - assert.strictEqual(ts.getRootLength("file://localhost/c%3ad"), 17); - assert.strictEqual(ts.getRootLength("file://localhost/c%3a/path"), 22); - assert.strictEqual(ts.getRootLength("file://localhost/c%3A"), 21); - assert.strictEqual(ts.getRootLength("file://localhost/c%3Ad"), 17); - assert.strictEqual(ts.getRootLength("file://localhost/c%3A/path"), 22); - assert.strictEqual(ts.getRootLength("file://server"), 13); - assert.strictEqual(ts.getRootLength("file://server/"), 14); - assert.strictEqual(ts.getRootLength("file://server/path"), 14); - assert.strictEqual(ts.getRootLength("file://server/c:"), 14); - assert.strictEqual(ts.getRootLength("file://server/c:d"), 14); - assert.strictEqual(ts.getRootLength("file://server/c:/d"), 14); - assert.strictEqual(ts.getRootLength("file://server/c%3a"), 14); - assert.strictEqual(ts.getRootLength("file://server/c%3ad"), 14); - assert.strictEqual(ts.getRootLength("file://server/c%3a/d"), 14); - assert.strictEqual(ts.getRootLength("file://server/c%3A"), 14); - assert.strictEqual(ts.getRootLength("file://server/c%3Ad"), 14); - assert.strictEqual(ts.getRootLength("file://server/c%3A/d"), 14); - assert.strictEqual(ts.getRootLength("http://server"), 13); - assert.strictEqual(ts.getRootLength("http://server/path"), 14); + assert.strictEqual(getRootLength("a"), 0); + assert.strictEqual(getRootLength("/"), 1); + assert.strictEqual(getRootLength("/path"), 1); + assert.strictEqual(getRootLength("c:"), 2); + assert.strictEqual(getRootLength("c:d"), 0); + assert.strictEqual(getRootLength("c:/"), 3); + assert.strictEqual(getRootLength("c:\\"), 3); + assert.strictEqual(getRootLength("//server"), 8); + assert.strictEqual(getRootLength("//server/share"), 9); + assert.strictEqual(getRootLength("\\\\server"), 8); + assert.strictEqual(getRootLength("\\\\server\\share"), 9); + assert.strictEqual(getRootLength("file:///"), 8); + assert.strictEqual(getRootLength("file:///path"), 8); + assert.strictEqual(getRootLength("file:///c:"), 10); + assert.strictEqual(getRootLength("file:///c:d"), 8); + assert.strictEqual(getRootLength("file:///c:/path"), 11); + assert.strictEqual(getRootLength("file:///c%3a"), 12); + assert.strictEqual(getRootLength("file:///c%3ad"), 8); + assert.strictEqual(getRootLength("file:///c%3a/path"), 13); + assert.strictEqual(getRootLength("file:///c%3A"), 12); + assert.strictEqual(getRootLength("file:///c%3Ad"), 8); + assert.strictEqual(getRootLength("file:///c%3A/path"), 13); + assert.strictEqual(getRootLength("file://localhost"), 16); + assert.strictEqual(getRootLength("file://localhost/"), 17); + assert.strictEqual(getRootLength("file://localhost/path"), 17); + assert.strictEqual(getRootLength("file://localhost/c:"), 19); + assert.strictEqual(getRootLength("file://localhost/c:d"), 17); + assert.strictEqual(getRootLength("file://localhost/c:/path"), 20); + assert.strictEqual(getRootLength("file://localhost/c%3a"), 21); + assert.strictEqual(getRootLength("file://localhost/c%3ad"), 17); + assert.strictEqual(getRootLength("file://localhost/c%3a/path"), 22); + assert.strictEqual(getRootLength("file://localhost/c%3A"), 21); + assert.strictEqual(getRootLength("file://localhost/c%3Ad"), 17); + assert.strictEqual(getRootLength("file://localhost/c%3A/path"), 22); + assert.strictEqual(getRootLength("file://server"), 13); + assert.strictEqual(getRootLength("file://server/"), 14); + assert.strictEqual(getRootLength("file://server/path"), 14); + assert.strictEqual(getRootLength("file://server/c:"), 14); + assert.strictEqual(getRootLength("file://server/c:d"), 14); + assert.strictEqual(getRootLength("file://server/c:/d"), 14); + assert.strictEqual(getRootLength("file://server/c%3a"), 14); + assert.strictEqual(getRootLength("file://server/c%3ad"), 14); + assert.strictEqual(getRootLength("file://server/c%3a/d"), 14); + assert.strictEqual(getRootLength("file://server/c%3A"), 14); + assert.strictEqual(getRootLength("file://server/c%3Ad"), 14); + assert.strictEqual(getRootLength("file://server/c%3A/d"), 14); + assert.strictEqual(getRootLength("http://server"), 13); + assert.strictEqual(getRootLength("http://server/path"), 14); }); it("isUrl", () => { - assert.isFalse(ts.isUrl("a")); - assert.isFalse(ts.isUrl("/")); - assert.isFalse(ts.isUrl("c:")); - assert.isFalse(ts.isUrl("c:d")); - assert.isFalse(ts.isUrl("c:/")); - assert.isFalse(ts.isUrl("c:\\")); - assert.isFalse(ts.isUrl("//server")); - assert.isFalse(ts.isUrl("//server/share")); - assert.isFalse(ts.isUrl("\\\\server")); - assert.isFalse(ts.isUrl("\\\\server\\share")); - assert.isTrue(ts.isUrl("file:///path")); - assert.isTrue(ts.isUrl("file:///c:")); - assert.isTrue(ts.isUrl("file:///c:d")); - assert.isTrue(ts.isUrl("file:///c:/path")); - assert.isTrue(ts.isUrl("file://server")); - assert.isTrue(ts.isUrl("file://server/path")); - assert.isTrue(ts.isUrl("http://server")); - assert.isTrue(ts.isUrl("http://server/path")); + assert.isFalse(isUrl("a")); + assert.isFalse(isUrl("/")); + assert.isFalse(isUrl("c:")); + assert.isFalse(isUrl("c:d")); + assert.isFalse(isUrl("c:/")); + assert.isFalse(isUrl("c:\\")); + assert.isFalse(isUrl("//server")); + assert.isFalse(isUrl("//server/share")); + assert.isFalse(isUrl("\\\\server")); + assert.isFalse(isUrl("\\\\server\\share")); + assert.isTrue(isUrl("file:///path")); + assert.isTrue(isUrl("file:///c:")); + assert.isTrue(isUrl("file:///c:d")); + assert.isTrue(isUrl("file:///c:/path")); + assert.isTrue(isUrl("file://server")); + assert.isTrue(isUrl("file://server/path")); + assert.isTrue(isUrl("http://server")); + assert.isTrue(isUrl("http://server/path")); }); it("isRootedDiskPath", () => { - assert.isFalse(ts.isRootedDiskPath("a")); - assert.isTrue(ts.isRootedDiskPath("/")); - assert.isTrue(ts.isRootedDiskPath("c:")); - assert.isFalse(ts.isRootedDiskPath("c:d")); - assert.isTrue(ts.isRootedDiskPath("c:/")); - assert.isTrue(ts.isRootedDiskPath("c:\\")); - assert.isTrue(ts.isRootedDiskPath("//server")); - assert.isTrue(ts.isRootedDiskPath("//server/share")); - assert.isTrue(ts.isRootedDiskPath("\\\\server")); - assert.isTrue(ts.isRootedDiskPath("\\\\server\\share")); - assert.isFalse(ts.isRootedDiskPath("file:///path")); - assert.isFalse(ts.isRootedDiskPath("file:///c:")); - assert.isFalse(ts.isRootedDiskPath("file:///c:d")); - assert.isFalse(ts.isRootedDiskPath("file:///c:/path")); - assert.isFalse(ts.isRootedDiskPath("file://server")); - assert.isFalse(ts.isRootedDiskPath("file://server/path")); - assert.isFalse(ts.isRootedDiskPath("http://server")); - assert.isFalse(ts.isRootedDiskPath("http://server/path")); + assert.isFalse(isRootedDiskPath("a")); + assert.isTrue(isRootedDiskPath("/")); + assert.isTrue(isRootedDiskPath("c:")); + assert.isFalse(isRootedDiskPath("c:d")); + assert.isTrue(isRootedDiskPath("c:/")); + assert.isTrue(isRootedDiskPath("c:\\")); + assert.isTrue(isRootedDiskPath("//server")); + assert.isTrue(isRootedDiskPath("//server/share")); + assert.isTrue(isRootedDiskPath("\\\\server")); + assert.isTrue(isRootedDiskPath("\\\\server\\share")); + assert.isFalse(isRootedDiskPath("file:///path")); + assert.isFalse(isRootedDiskPath("file:///c:")); + assert.isFalse(isRootedDiskPath("file:///c:d")); + assert.isFalse(isRootedDiskPath("file:///c:/path")); + assert.isFalse(isRootedDiskPath("file://server")); + assert.isFalse(isRootedDiskPath("file://server/path")); + assert.isFalse(isRootedDiskPath("http://server")); + assert.isFalse(isRootedDiskPath("http://server/path")); }); it("getDirectoryPath", () => { - assert.strictEqual(ts.getDirectoryPath(""), ""); - assert.strictEqual(ts.getDirectoryPath("a"), ""); - assert.strictEqual(ts.getDirectoryPath("a/b"), "a"); - assert.strictEqual(ts.getDirectoryPath("/"), "/"); - assert.strictEqual(ts.getDirectoryPath("/a"), "/"); - assert.strictEqual(ts.getDirectoryPath("/a/"), "/"); - assert.strictEqual(ts.getDirectoryPath("/a/b"), "/a"); - assert.strictEqual(ts.getDirectoryPath("/a/b/"), "/a"); - assert.strictEqual(ts.getDirectoryPath("c:"), "c:"); - assert.strictEqual(ts.getDirectoryPath("c:d"), ""); - assert.strictEqual(ts.getDirectoryPath("c:/"), "c:/"); - assert.strictEqual(ts.getDirectoryPath("c:/path"), "c:/"); - assert.strictEqual(ts.getDirectoryPath("c:/path/"), "c:/"); - assert.strictEqual(ts.getDirectoryPath("//server"), "//server"); - assert.strictEqual(ts.getDirectoryPath("//server/"), "//server/"); - assert.strictEqual(ts.getDirectoryPath("//server/share"), "//server/"); - assert.strictEqual(ts.getDirectoryPath("//server/share/"), "//server/"); - assert.strictEqual(ts.getDirectoryPath("\\\\server"), "//server"); - assert.strictEqual(ts.getDirectoryPath("\\\\server\\"), "//server/"); - assert.strictEqual(ts.getDirectoryPath("\\\\server\\share"), "//server/"); - assert.strictEqual(ts.getDirectoryPath("\\\\server\\share\\"), "//server/"); - assert.strictEqual(ts.getDirectoryPath("file:///"), "file:///"); - assert.strictEqual(ts.getDirectoryPath("file:///path"), "file:///"); - assert.strictEqual(ts.getDirectoryPath("file:///path/"), "file:///"); - assert.strictEqual(ts.getDirectoryPath("file:///c:"), "file:///c:"); - assert.strictEqual(ts.getDirectoryPath("file:///c:d"), "file:///"); - assert.strictEqual(ts.getDirectoryPath("file:///c:/"), "file:///c:/"); - assert.strictEqual(ts.getDirectoryPath("file:///c:/path"), "file:///c:/"); - assert.strictEqual(ts.getDirectoryPath("file:///c:/path/"), "file:///c:/"); - assert.strictEqual(ts.getDirectoryPath("file://server"), "file://server"); - assert.strictEqual(ts.getDirectoryPath("file://server/"), "file://server/"); - assert.strictEqual(ts.getDirectoryPath("file://server/path"), "file://server/"); - assert.strictEqual(ts.getDirectoryPath("file://server/path/"), "file://server/"); - assert.strictEqual(ts.getDirectoryPath("http://server"), "http://server"); - assert.strictEqual(ts.getDirectoryPath("http://server/"), "http://server/"); - assert.strictEqual(ts.getDirectoryPath("http://server/path"), "http://server/"); - assert.strictEqual(ts.getDirectoryPath("http://server/path/"), "http://server/"); + assert.strictEqual(getDirectoryPath(""), ""); + assert.strictEqual(getDirectoryPath("a"), ""); + assert.strictEqual(getDirectoryPath("a/b"), "a"); + assert.strictEqual(getDirectoryPath("/"), "/"); + assert.strictEqual(getDirectoryPath("/a"), "/"); + assert.strictEqual(getDirectoryPath("/a/"), "/"); + assert.strictEqual(getDirectoryPath("/a/b"), "/a"); + assert.strictEqual(getDirectoryPath("/a/b/"), "/a"); + assert.strictEqual(getDirectoryPath("c:"), "c:"); + assert.strictEqual(getDirectoryPath("c:d"), ""); + assert.strictEqual(getDirectoryPath("c:/"), "c:/"); + assert.strictEqual(getDirectoryPath("c:/path"), "c:/"); + assert.strictEqual(getDirectoryPath("c:/path/"), "c:/"); + assert.strictEqual(getDirectoryPath("//server"), "//server"); + assert.strictEqual(getDirectoryPath("//server/"), "//server/"); + assert.strictEqual(getDirectoryPath("//server/share"), "//server/"); + assert.strictEqual(getDirectoryPath("//server/share/"), "//server/"); + assert.strictEqual(getDirectoryPath("\\\\server"), "//server"); + assert.strictEqual(getDirectoryPath("\\\\server\\"), "//server/"); + assert.strictEqual(getDirectoryPath("\\\\server\\share"), "//server/"); + assert.strictEqual(getDirectoryPath("\\\\server\\share\\"), "//server/"); + assert.strictEqual(getDirectoryPath("file:///"), "file:///"); + assert.strictEqual(getDirectoryPath("file:///path"), "file:///"); + assert.strictEqual(getDirectoryPath("file:///path/"), "file:///"); + assert.strictEqual(getDirectoryPath("file:///c:"), "file:///c:"); + assert.strictEqual(getDirectoryPath("file:///c:d"), "file:///"); + assert.strictEqual(getDirectoryPath("file:///c:/"), "file:///c:/"); + assert.strictEqual(getDirectoryPath("file:///c:/path"), "file:///c:/"); + assert.strictEqual(getDirectoryPath("file:///c:/path/"), "file:///c:/"); + assert.strictEqual(getDirectoryPath("file://server"), "file://server"); + assert.strictEqual(getDirectoryPath("file://server/"), "file://server/"); + assert.strictEqual(getDirectoryPath("file://server/path"), "file://server/"); + assert.strictEqual(getDirectoryPath("file://server/path/"), "file://server/"); + assert.strictEqual(getDirectoryPath("http://server"), "http://server"); + assert.strictEqual(getDirectoryPath("http://server/"), "http://server/"); + assert.strictEqual(getDirectoryPath("http://server/path"), "http://server/"); + assert.strictEqual(getDirectoryPath("http://server/path/"), "http://server/"); }); it("getBaseFileName", () => { - assert.strictEqual(ts.getBaseFileName(""), ""); - assert.strictEqual(ts.getBaseFileName("a"), "a"); - assert.strictEqual(ts.getBaseFileName("a/"), "a"); - assert.strictEqual(ts.getBaseFileName("/"), ""); - assert.strictEqual(ts.getBaseFileName("/a"), "a"); - assert.strictEqual(ts.getBaseFileName("/a/"), "a"); - assert.strictEqual(ts.getBaseFileName("/a/b"), "b"); - assert.strictEqual(ts.getBaseFileName("c:"), ""); - assert.strictEqual(ts.getBaseFileName("c:d"), "c:d"); - assert.strictEqual(ts.getBaseFileName("c:/"), ""); - assert.strictEqual(ts.getBaseFileName("c:\\"), ""); - assert.strictEqual(ts.getBaseFileName("c:/path"), "path"); - assert.strictEqual(ts.getBaseFileName("c:/path/"), "path"); - assert.strictEqual(ts.getBaseFileName("//server"), ""); - assert.strictEqual(ts.getBaseFileName("//server/"), ""); - assert.strictEqual(ts.getBaseFileName("//server/share"), "share"); - assert.strictEqual(ts.getBaseFileName("//server/share/"), "share"); - assert.strictEqual(ts.getBaseFileName("file:///"), ""); - assert.strictEqual(ts.getBaseFileName("file:///path"), "path"); - assert.strictEqual(ts.getBaseFileName("file:///path/"), "path"); - assert.strictEqual(ts.getBaseFileName("file:///c:"), ""); - assert.strictEqual(ts.getBaseFileName("file:///c:/"), ""); - assert.strictEqual(ts.getBaseFileName("file:///c:d"), "c:d"); - assert.strictEqual(ts.getBaseFileName("file:///c:/d"), "d"); - assert.strictEqual(ts.getBaseFileName("file:///c:/d/"), "d"); - assert.strictEqual(ts.getBaseFileName("http://server"), ""); - assert.strictEqual(ts.getBaseFileName("http://server/"), ""); - assert.strictEqual(ts.getBaseFileName("http://server/a"), "a"); - assert.strictEqual(ts.getBaseFileName("http://server/a/"), "a"); - assert.strictEqual(ts.getBaseFileName("/path/a.ext", ".ext", /*ignoreCase*/ false), "a"); - assert.strictEqual(ts.getBaseFileName("/path/a.ext", ".EXT", /*ignoreCase*/ true), "a"); - assert.strictEqual(ts.getBaseFileName("/path/a.ext", "ext", /*ignoreCase*/ false), "a"); - assert.strictEqual(ts.getBaseFileName("/path/a.b", ".ext", /*ignoreCase*/ false), "a.b"); - assert.strictEqual(ts.getBaseFileName("/path/a.b", [".b", ".c"], /*ignoreCase*/ false), "a"); - assert.strictEqual(ts.getBaseFileName("/path/a.c", [".b", ".c"], /*ignoreCase*/ false), "a"); - assert.strictEqual(ts.getBaseFileName("/path/a.d", [".b", ".c"], /*ignoreCase*/ false), "a.d"); + assert.strictEqual(getBaseFileName(""), ""); + assert.strictEqual(getBaseFileName("a"), "a"); + assert.strictEqual(getBaseFileName("a/"), "a"); + assert.strictEqual(getBaseFileName("/"), ""); + assert.strictEqual(getBaseFileName("/a"), "a"); + assert.strictEqual(getBaseFileName("/a/"), "a"); + assert.strictEqual(getBaseFileName("/a/b"), "b"); + assert.strictEqual(getBaseFileName("c:"), ""); + assert.strictEqual(getBaseFileName("c:d"), "c:d"); + assert.strictEqual(getBaseFileName("c:/"), ""); + assert.strictEqual(getBaseFileName("c:\\"), ""); + assert.strictEqual(getBaseFileName("c:/path"), "path"); + assert.strictEqual(getBaseFileName("c:/path/"), "path"); + assert.strictEqual(getBaseFileName("//server"), ""); + assert.strictEqual(getBaseFileName("//server/"), ""); + assert.strictEqual(getBaseFileName("//server/share"), "share"); + assert.strictEqual(getBaseFileName("//server/share/"), "share"); + assert.strictEqual(getBaseFileName("file:///"), ""); + assert.strictEqual(getBaseFileName("file:///path"), "path"); + assert.strictEqual(getBaseFileName("file:///path/"), "path"); + assert.strictEqual(getBaseFileName("file:///c:"), ""); + assert.strictEqual(getBaseFileName("file:///c:/"), ""); + assert.strictEqual(getBaseFileName("file:///c:d"), "c:d"); + assert.strictEqual(getBaseFileName("file:///c:/d"), "d"); + assert.strictEqual(getBaseFileName("file:///c:/d/"), "d"); + assert.strictEqual(getBaseFileName("http://server"), ""); + assert.strictEqual(getBaseFileName("http://server/"), ""); + assert.strictEqual(getBaseFileName("http://server/a"), "a"); + assert.strictEqual(getBaseFileName("http://server/a/"), "a"); + assert.strictEqual(getBaseFileName("/path/a.ext", ".ext", /*ignoreCase*/ false), "a"); + assert.strictEqual(getBaseFileName("/path/a.ext", ".EXT", /*ignoreCase*/ true), "a"); + assert.strictEqual(getBaseFileName("/path/a.ext", "ext", /*ignoreCase*/ false), "a"); + assert.strictEqual(getBaseFileName("/path/a.b", ".ext", /*ignoreCase*/ false), "a.b"); + assert.strictEqual(getBaseFileName("/path/a.b", [".b", ".c"], /*ignoreCase*/ false), "a"); + assert.strictEqual(getBaseFileName("/path/a.c", [".b", ".c"], /*ignoreCase*/ false), "a"); + assert.strictEqual(getBaseFileName("/path/a.d", [".b", ".c"], /*ignoreCase*/ false), "a.d"); }); it("getAnyExtensionFromPath", () => { - assert.strictEqual(ts.getAnyExtensionFromPath(""), ""); - assert.strictEqual(ts.getAnyExtensionFromPath(".ext"), ".ext"); - assert.strictEqual(ts.getAnyExtensionFromPath("a.ext"), ".ext"); - assert.strictEqual(ts.getAnyExtensionFromPath("/a.ext"), ".ext"); - assert.strictEqual(ts.getAnyExtensionFromPath("a.ext/"), ".ext"); - assert.strictEqual(ts.getAnyExtensionFromPath("a.ext", ".ext", /*ignoreCase*/ false), ".ext"); - assert.strictEqual(ts.getAnyExtensionFromPath("a.ext", ".EXT", /*ignoreCase*/ true), ".ext"); - assert.strictEqual(ts.getAnyExtensionFromPath("a.ext", "ext", /*ignoreCase*/ false), ".ext"); - assert.strictEqual(ts.getAnyExtensionFromPath("a.b", ".ext", /*ignoreCase*/ false), ""); - assert.strictEqual(ts.getAnyExtensionFromPath("a.b", [".b", ".c"], /*ignoreCase*/ false), ".b"); - assert.strictEqual(ts.getAnyExtensionFromPath("a.c", [".b", ".c"], /*ignoreCase*/ false), ".c"); - assert.strictEqual(ts.getAnyExtensionFromPath("a.d", [".b", ".c"], /*ignoreCase*/ false), ""); + assert.strictEqual(getAnyExtensionFromPath(""), ""); + assert.strictEqual(getAnyExtensionFromPath(".ext"), ".ext"); + assert.strictEqual(getAnyExtensionFromPath("a.ext"), ".ext"); + assert.strictEqual(getAnyExtensionFromPath("/a.ext"), ".ext"); + assert.strictEqual(getAnyExtensionFromPath("a.ext/"), ".ext"); + assert.strictEqual(getAnyExtensionFromPath("a.ext", ".ext", /*ignoreCase*/ false), ".ext"); + assert.strictEqual(getAnyExtensionFromPath("a.ext", ".EXT", /*ignoreCase*/ true), ".ext"); + assert.strictEqual(getAnyExtensionFromPath("a.ext", "ext", /*ignoreCase*/ false), ".ext"); + assert.strictEqual(getAnyExtensionFromPath("a.b", ".ext", /*ignoreCase*/ false), ""); + assert.strictEqual(getAnyExtensionFromPath("a.b", [".b", ".c"], /*ignoreCase*/ false), ".b"); + assert.strictEqual(getAnyExtensionFromPath("a.c", [".b", ".c"], /*ignoreCase*/ false), ".c"); + assert.strictEqual(getAnyExtensionFromPath("a.d", [".b", ".c"], /*ignoreCase*/ false), ""); }); it("getPathComponents", () => { - assert.deepEqual(ts.getPathComponents(""), [""]); - assert.deepEqual(ts.getPathComponents("a"), ["", "a"]); - assert.deepEqual(ts.getPathComponents("./a"), ["", ".", "a"]); - assert.deepEqual(ts.getPathComponents("/"), ["/"]); - assert.deepEqual(ts.getPathComponents("/a"), ["/", "a"]); - assert.deepEqual(ts.getPathComponents("/a/"), ["/", "a"]); - assert.deepEqual(ts.getPathComponents("c:"), ["c:"]); - assert.deepEqual(ts.getPathComponents("c:d"), ["", "c:d"]); - assert.deepEqual(ts.getPathComponents("c:/"), ["c:/"]); - assert.deepEqual(ts.getPathComponents("c:/path"), ["c:/", "path"]); - assert.deepEqual(ts.getPathComponents("//server"), ["//server"]); - assert.deepEqual(ts.getPathComponents("//server/"), ["//server/"]); - assert.deepEqual(ts.getPathComponents("//server/share"), ["//server/", "share"]); - assert.deepEqual(ts.getPathComponents("file:///"), ["file:///"]); - assert.deepEqual(ts.getPathComponents("file:///path"), ["file:///", "path"]); - assert.deepEqual(ts.getPathComponents("file:///c:"), ["file:///c:"]); - assert.deepEqual(ts.getPathComponents("file:///c:d"), ["file:///", "c:d"]); - assert.deepEqual(ts.getPathComponents("file:///c:/"), ["file:///c:/"]); - assert.deepEqual(ts.getPathComponents("file:///c:/path"), ["file:///c:/", "path"]); - assert.deepEqual(ts.getPathComponents("file://server"), ["file://server"]); - assert.deepEqual(ts.getPathComponents("file://server/"), ["file://server/"]); - assert.deepEqual(ts.getPathComponents("file://server/path"), ["file://server/", "path"]); - assert.deepEqual(ts.getPathComponents("http://server"), ["http://server"]); - assert.deepEqual(ts.getPathComponents("http://server/"), ["http://server/"]); - assert.deepEqual(ts.getPathComponents("http://server/path"), ["http://server/", "path"]); + assert.deepEqual(getPathComponents(""), [""]); + assert.deepEqual(getPathComponents("a"), ["", "a"]); + assert.deepEqual(getPathComponents("./a"), ["", ".", "a"]); + assert.deepEqual(getPathComponents("/"), ["/"]); + assert.deepEqual(getPathComponents("/a"), ["/", "a"]); + assert.deepEqual(getPathComponents("/a/"), ["/", "a"]); + assert.deepEqual(getPathComponents("c:"), ["c:"]); + assert.deepEqual(getPathComponents("c:d"), ["", "c:d"]); + assert.deepEqual(getPathComponents("c:/"), ["c:/"]); + assert.deepEqual(getPathComponents("c:/path"), ["c:/", "path"]); + assert.deepEqual(getPathComponents("//server"), ["//server"]); + assert.deepEqual(getPathComponents("//server/"), ["//server/"]); + assert.deepEqual(getPathComponents("//server/share"), ["//server/", "share"]); + assert.deepEqual(getPathComponents("file:///"), ["file:///"]); + assert.deepEqual(getPathComponents("file:///path"), ["file:///", "path"]); + assert.deepEqual(getPathComponents("file:///c:"), ["file:///c:"]); + assert.deepEqual(getPathComponents("file:///c:d"), ["file:///", "c:d"]); + assert.deepEqual(getPathComponents("file:///c:/"), ["file:///c:/"]); + assert.deepEqual(getPathComponents("file:///c:/path"), ["file:///c:/", "path"]); + assert.deepEqual(getPathComponents("file://server"), ["file://server"]); + assert.deepEqual(getPathComponents("file://server/"), ["file://server/"]); + assert.deepEqual(getPathComponents("file://server/path"), ["file://server/", "path"]); + assert.deepEqual(getPathComponents("http://server"), ["http://server"]); + assert.deepEqual(getPathComponents("http://server/"), ["http://server/"]); + assert.deepEqual(getPathComponents("http://server/path"), ["http://server/", "path"]); }); it("reducePathComponents", () => { - assert.deepEqual(ts.reducePathComponents([]), []); - assert.deepEqual(ts.reducePathComponents([""]), [""]); - assert.deepEqual(ts.reducePathComponents(["", "."]), [""]); - assert.deepEqual(ts.reducePathComponents(["", ".", "a"]), ["", "a"]); - assert.deepEqual(ts.reducePathComponents(["", "a", "."]), ["", "a"]); - assert.deepEqual(ts.reducePathComponents(["", ".."]), ["", ".."]); - assert.deepEqual(ts.reducePathComponents(["", "..", ".."]), ["", "..", ".."]); - assert.deepEqual(ts.reducePathComponents(["", "..", ".", ".."]), ["", "..", ".."]); - assert.deepEqual(ts.reducePathComponents(["", "a", ".."]), [""]); - assert.deepEqual(ts.reducePathComponents(["", "..", "a"]), ["", "..", "a"]); - assert.deepEqual(ts.reducePathComponents(["/"]), ["/"]); - assert.deepEqual(ts.reducePathComponents(["/", "."]), ["/"]); - assert.deepEqual(ts.reducePathComponents(["/", ".."]), ["/"]); - assert.deepEqual(ts.reducePathComponents(["/", "a", ".."]), ["/"]); + assert.deepEqual(reducePathComponents([]), []); + assert.deepEqual(reducePathComponents([""]), [""]); + assert.deepEqual(reducePathComponents(["", "."]), [""]); + assert.deepEqual(reducePathComponents(["", ".", "a"]), ["", "a"]); + assert.deepEqual(reducePathComponents(["", "a", "."]), ["", "a"]); + assert.deepEqual(reducePathComponents(["", ".."]), ["", ".."]); + assert.deepEqual(reducePathComponents(["", "..", ".."]), ["", "..", ".."]); + assert.deepEqual(reducePathComponents(["", "..", ".", ".."]), ["", "..", ".."]); + assert.deepEqual(reducePathComponents(["", "a", ".."]), [""]); + assert.deepEqual(reducePathComponents(["", "..", "a"]), ["", "..", "a"]); + assert.deepEqual(reducePathComponents(["/"]), ["/"]); + assert.deepEqual(reducePathComponents(["/", "."]), ["/"]); + assert.deepEqual(reducePathComponents(["/", ".."]), ["/"]); + assert.deepEqual(reducePathComponents(["/", "a", ".."]), ["/"]); }); it("combinePaths", () => { - assert.strictEqual(ts.combinePaths("/", "/node_modules/@types"), "/node_modules/@types"); - assert.strictEqual(ts.combinePaths("/a/..", ""), "/a/.."); - assert.strictEqual(ts.combinePaths("/a/..", "b"), "/a/../b"); - assert.strictEqual(ts.combinePaths("/a/..", "b/"), "/a/../b/"); - assert.strictEqual(ts.combinePaths("/a/..", "/"), "/"); - assert.strictEqual(ts.combinePaths("/a/..", "/b"), "/b"); + assert.strictEqual(combinePaths("/", "/node_modules/@types"), "/node_modules/@types"); + assert.strictEqual(combinePaths("/a/..", ""), "/a/.."); + assert.strictEqual(combinePaths("/a/..", "b"), "/a/../b"); + assert.strictEqual(combinePaths("/a/..", "b/"), "/a/../b/"); + assert.strictEqual(combinePaths("/a/..", "/"), "/"); + assert.strictEqual(combinePaths("/a/..", "/b"), "/b"); }); it("resolvePath", () => { - assert.strictEqual(ts.resolvePath(""), ""); - assert.strictEqual(ts.resolvePath("."), ""); - assert.strictEqual(ts.resolvePath("./"), ""); - assert.strictEqual(ts.resolvePath(".."), ".."); - assert.strictEqual(ts.resolvePath("../"), "../"); - assert.strictEqual(ts.resolvePath("/"), "/"); - assert.strictEqual(ts.resolvePath("/."), "/"); - assert.strictEqual(ts.resolvePath("/./"), "/"); - assert.strictEqual(ts.resolvePath("/../"), "/"); - assert.strictEqual(ts.resolvePath("/a"), "/a"); - assert.strictEqual(ts.resolvePath("/a/"), "/a/"); - assert.strictEqual(ts.resolvePath("/a/."), "/a"); - assert.strictEqual(ts.resolvePath("/a/./"), "/a/"); - assert.strictEqual(ts.resolvePath("/a/./b"), "/a/b"); - assert.strictEqual(ts.resolvePath("/a/./b/"), "/a/b/"); - assert.strictEqual(ts.resolvePath("/a/.."), "/"); - assert.strictEqual(ts.resolvePath("/a/../"), "/"); - assert.strictEqual(ts.resolvePath("/a/../b"), "/b"); - assert.strictEqual(ts.resolvePath("/a/../b/"), "/b/"); - assert.strictEqual(ts.resolvePath("/a/..", "b"), "/b"); - assert.strictEqual(ts.resolvePath("/a/..", "/"), "/"); - assert.strictEqual(ts.resolvePath("/a/..", "b/"), "/b/"); - assert.strictEqual(ts.resolvePath("/a/..", "/b"), "/b"); - assert.strictEqual(ts.resolvePath("/a/.", "b"), "/a/b"); - assert.strictEqual(ts.resolvePath("/a/.", "."), "/a"); - assert.strictEqual(ts.resolvePath("a", "b", "c"), "a/b/c"); - assert.strictEqual(ts.resolvePath("a", "b", "/c"), "/c"); - assert.strictEqual(ts.resolvePath("a", "b", "../c"), "a/c"); + assert.strictEqual(resolvePath(""), ""); + assert.strictEqual(resolvePath("."), ""); + assert.strictEqual(resolvePath("./"), ""); + assert.strictEqual(resolvePath(".."), ".."); + assert.strictEqual(resolvePath("../"), "../"); + assert.strictEqual(resolvePath("/"), "/"); + assert.strictEqual(resolvePath("/."), "/"); + assert.strictEqual(resolvePath("/./"), "/"); + assert.strictEqual(resolvePath("/../"), "/"); + assert.strictEqual(resolvePath("/a"), "/a"); + assert.strictEqual(resolvePath("/a/"), "/a/"); + assert.strictEqual(resolvePath("/a/."), "/a"); + assert.strictEqual(resolvePath("/a/./"), "/a/"); + assert.strictEqual(resolvePath("/a/./b"), "/a/b"); + assert.strictEqual(resolvePath("/a/./b/"), "/a/b/"); + assert.strictEqual(resolvePath("/a/.."), "/"); + assert.strictEqual(resolvePath("/a/../"), "/"); + assert.strictEqual(resolvePath("/a/../b"), "/b"); + assert.strictEqual(resolvePath("/a/../b/"), "/b/"); + assert.strictEqual(resolvePath("/a/..", "b"), "/b"); + assert.strictEqual(resolvePath("/a/..", "/"), "/"); + assert.strictEqual(resolvePath("/a/..", "b/"), "/b/"); + assert.strictEqual(resolvePath("/a/..", "/b"), "/b"); + assert.strictEqual(resolvePath("/a/.", "b"), "/a/b"); + assert.strictEqual(resolvePath("/a/.", "."), "/a"); + assert.strictEqual(resolvePath("a", "b", "c"), "a/b/c"); + assert.strictEqual(resolvePath("a", "b", "/c"), "/c"); + assert.strictEqual(resolvePath("a", "b", "../c"), "a/c"); }); it("getPathRelativeTo", () => { - assert.strictEqual(ts.getRelativePathFromDirectory("/", "/", /*ignoreCase*/ false), ""); - assert.strictEqual(ts.getRelativePathFromDirectory("/a", "/a", /*ignoreCase*/ false), ""); - assert.strictEqual(ts.getRelativePathFromDirectory("/a/", "/a", /*ignoreCase*/ false), ""); - assert.strictEqual(ts.getRelativePathFromDirectory("/a", "/", /*ignoreCase*/ false), ".."); - assert.strictEqual(ts.getRelativePathFromDirectory("/a", "/b", /*ignoreCase*/ false), "../b"); - assert.strictEqual(ts.getRelativePathFromDirectory("/a/b", "/b", /*ignoreCase*/ false), "../../b"); - assert.strictEqual(ts.getRelativePathFromDirectory("/a/b/c", "/b", /*ignoreCase*/ false), "../../../b"); - assert.strictEqual(ts.getRelativePathFromDirectory("/a/b/c", "/b/c", /*ignoreCase*/ false), "../../../b/c"); - assert.strictEqual(ts.getRelativePathFromDirectory("/a/b/c", "/a/b", /*ignoreCase*/ false), ".."); - assert.strictEqual(ts.getRelativePathFromDirectory("c:", "d:", /*ignoreCase*/ false), "d:/"); - assert.strictEqual(ts.getRelativePathFromDirectory("file:///", "file:///", /*ignoreCase*/ false), ""); - assert.strictEqual(ts.getRelativePathFromDirectory("file:///a", "file:///a", /*ignoreCase*/ false), ""); - assert.strictEqual(ts.getRelativePathFromDirectory("file:///a/", "file:///a", /*ignoreCase*/ false), ""); - assert.strictEqual(ts.getRelativePathFromDirectory("file:///a", "file:///", /*ignoreCase*/ false), ".."); - assert.strictEqual(ts.getRelativePathFromDirectory("file:///a", "file:///b", /*ignoreCase*/ false), "../b"); - assert.strictEqual(ts.getRelativePathFromDirectory("file:///a/b", "file:///b", /*ignoreCase*/ false), "../../b"); - assert.strictEqual(ts.getRelativePathFromDirectory("file:///a/b/c", "file:///b", /*ignoreCase*/ false), "../../../b"); - assert.strictEqual(ts.getRelativePathFromDirectory("file:///a/b/c", "file:///b/c", /*ignoreCase*/ false), "../../../b/c"); - assert.strictEqual(ts.getRelativePathFromDirectory("file:///a/b/c", "file:///a/b", /*ignoreCase*/ false), ".."); - assert.strictEqual(ts.getRelativePathFromDirectory("file:///c:", "file:///d:", /*ignoreCase*/ false), "file:///d:/"); + assert.strictEqual(getRelativePathFromDirectory("/", "/", /*ignoreCase*/ false), ""); + assert.strictEqual(getRelativePathFromDirectory("/a", "/a", /*ignoreCase*/ false), ""); + assert.strictEqual(getRelativePathFromDirectory("/a/", "/a", /*ignoreCase*/ false), ""); + assert.strictEqual(getRelativePathFromDirectory("/a", "/", /*ignoreCase*/ false), ".."); + assert.strictEqual(getRelativePathFromDirectory("/a", "/b", /*ignoreCase*/ false), "../b"); + assert.strictEqual(getRelativePathFromDirectory("/a/b", "/b", /*ignoreCase*/ false), "../../b"); + assert.strictEqual(getRelativePathFromDirectory("/a/b/c", "/b", /*ignoreCase*/ false), "../../../b"); + assert.strictEqual(getRelativePathFromDirectory("/a/b/c", "/b/c", /*ignoreCase*/ false), "../../../b/c"); + assert.strictEqual(getRelativePathFromDirectory("/a/b/c", "/a/b", /*ignoreCase*/ false), ".."); + assert.strictEqual(getRelativePathFromDirectory("c:", "d:", /*ignoreCase*/ false), "d:/"); + assert.strictEqual(getRelativePathFromDirectory("file:///", "file:///", /*ignoreCase*/ false), ""); + assert.strictEqual(getRelativePathFromDirectory("file:///a", "file:///a", /*ignoreCase*/ false), ""); + assert.strictEqual(getRelativePathFromDirectory("file:///a/", "file:///a", /*ignoreCase*/ false), ""); + assert.strictEqual(getRelativePathFromDirectory("file:///a", "file:///", /*ignoreCase*/ false), ".."); + assert.strictEqual(getRelativePathFromDirectory("file:///a", "file:///b", /*ignoreCase*/ false), "../b"); + assert.strictEqual(getRelativePathFromDirectory("file:///a/b", "file:///b", /*ignoreCase*/ false), "../../b"); + assert.strictEqual(getRelativePathFromDirectory("file:///a/b/c", "file:///b", /*ignoreCase*/ false), "../../../b"); + assert.strictEqual(getRelativePathFromDirectory("file:///a/b/c", "file:///b/c", /*ignoreCase*/ false), "../../../b/c"); + assert.strictEqual(getRelativePathFromDirectory("file:///a/b/c", "file:///a/b", /*ignoreCase*/ false), ".."); + assert.strictEqual(getRelativePathFromDirectory("file:///c:", "file:///d:", /*ignoreCase*/ false), "file:///d:/"); }); it("toFileNameLowerCase", () => { assert.strictEqual( - ts.toFileNameLowerCase("/user/UserName/projects/Project/file.ts"), + toFileNameLowerCase("/user/UserName/projects/Project/file.ts"), "/user/username/projects/project/file.ts" ); assert.strictEqual( - ts.toFileNameLowerCase("/user/UserName/projects/projectß/file.ts"), + toFileNameLowerCase("/user/UserName/projects/projectß/file.ts"), "/user/username/projects/projectß/file.ts" ); assert.strictEqual( - ts.toFileNameLowerCase("/user/UserName/projects/İproject/file.ts"), + toFileNameLowerCase("/user/UserName/projects/İproject/file.ts"), "/user/username/projects/İproject/file.ts" ); assert.strictEqual( - ts.toFileNameLowerCase("/user/UserName/projects/ı/file.ts"), + toFileNameLowerCase("/user/UserName/projects/ı/file.ts"), "/user/username/projects/ı/file.ts" ); }); diff --git a/src/testRunner/unittests/printer.ts b/src/testRunner/unittests/printer.ts index b6b38240d0073..11cfd633552b2 100644 --- a/src/testRunner/unittests/printer.ts +++ b/src/testRunner/unittests/printer.ts @@ -1,14 +1,23 @@ -import * as fakes from "../_namespaces/fakes"; -import * as Harness from "../_namespaces/Harness"; -import * as ts from "../_namespaces/ts"; -import * as vfs from "../_namespaces/vfs"; +import { emptyArray } from "../../compiler/core"; +import { createPrinter } from "../../compiler/emitter"; +import { setEmitFlags } from "../../compiler/factory/emitNode"; +import { factory } from "../../compiler/factory/nodeFactory"; +import { createSourceFile } from "../../compiler/parser"; +import { createProgram } from "../../compiler/program"; +import { + Bundle, EmitFlags, EmitHint, NewLineKind, NodeFlags, Printer, PrinterOptions, ScriptKind, ScriptTarget, SourceFile, + SyntaxKind, +} from "../../compiler/types"; +import { CompilerHost } from "../../harness/fakesHosts"; +import { Baseline } from "../../harness/harnessIO"; +import { FileSystem } from "../../harness/vfsUtil"; describe("unittests:: PrinterAPI", () => { function makePrintsCorrectly(prefix: string) { - return function printsCorrectly(name: string, options: ts.PrinterOptions, printCallback: (printer: ts.Printer) => string) { + return function printsCorrectly(name: string, options: PrinterOptions, printCallback: (printer: Printer) => string) { it(name, () => { - Harness.Baseline.runBaseline(`printerApi/${prefix}.${name}.js`, - printCallback(ts.createPrinter({ newLine: ts.NewLineKind.CarriageReturnLineFeed, ...options }))); + Baseline.runBaseline(`printerApi/${prefix}.${name}.js`, + printCallback(createPrinter({ newLine: NewLineKind.CarriageReturnLineFeed, ...options }))); }); }; } @@ -17,9 +26,9 @@ describe("unittests:: PrinterAPI", () => { const printsCorrectly = makePrintsCorrectly("printsFileCorrectly"); describe("comment handling", () => { // Avoid eagerly creating the sourceFile so that `createSourceFile` doesn't run unless one of these tests is run. - let sourceFile: ts.SourceFile; + let sourceFile: SourceFile; before(() => { - sourceFile = ts.createSourceFile("source.ts", ` + sourceFile = createSourceFile("source.ts", ` interface A { // comment1 readonly prop?: T; @@ -53,7 +62,7 @@ describe("unittests:: PrinterAPI", () => { // comment10 function functionWithDefaultArgValue(argument: string = "defaultValue"): void { } - `, ts.ScriptTarget.ES2015); + `, ScriptTarget.ES2015); }); printsCorrectly("default", {}, printer => printer.printFile(sourceFile)); printsCorrectly("removeComments", { removeComments: true }, printer => printer.printFile(sourceFile)); @@ -61,64 +70,64 @@ describe("unittests:: PrinterAPI", () => { // https://github.com/microsoft/TypeScript/issues/14948 // eslint-disable-next-line no-template-curly-in-string - printsCorrectly("templateLiteral", {}, printer => printer.printFile(ts.createSourceFile("source.ts", "let greeting = `Hi ${name}, how are you?`;", ts.ScriptTarget.ES2017))); + printsCorrectly("templateLiteral", {}, printer => printer.printFile(createSourceFile("source.ts", "let greeting = `Hi ${name}, how are you?`;", ScriptTarget.ES2017))); // https://github.com/microsoft/TypeScript/issues/18071 - printsCorrectly("regularExpressionLiteral", {}, printer => printer.printFile(ts.createSourceFile("source.ts", "let regex = /abc/;", ts.ScriptTarget.ES2017))); + printsCorrectly("regularExpressionLiteral", {}, printer => printer.printFile(createSourceFile("source.ts", "let regex = /abc/;", ScriptTarget.ES2017))); // https://github.com/microsoft/TypeScript/issues/22239 - printsCorrectly("importStatementRemoveComments", { removeComments: true }, printer => printer.printFile(ts.createSourceFile("source.ts", "import {foo} from 'foo';", ts.ScriptTarget.ESNext))); - printsCorrectly("classHeritageClauses", {}, printer => printer.printFile(ts.createSourceFile( + printsCorrectly("importStatementRemoveComments", { removeComments: true }, printer => printer.printFile(createSourceFile("source.ts", "import {foo} from 'foo';", ScriptTarget.ESNext))); + printsCorrectly("classHeritageClauses", {}, printer => printer.printFile(createSourceFile( "source.ts", `class A extends B implements C implements D {}`, - ts.ScriptTarget.ES2017 + ScriptTarget.ES2017 ))); // https://github.com/microsoft/TypeScript/issues/35093 - printsCorrectly("definiteAssignmentAssertions", {}, printer => printer.printFile(ts.createSourceFile( + printsCorrectly("definiteAssignmentAssertions", {}, printer => printer.printFile(createSourceFile( "source.ts", `class A { prop!: string; } let x!: string;`, - ts.ScriptTarget.ES2017 + ScriptTarget.ES2017 ))); // https://github.com/microsoft/TypeScript/issues/35054 printsCorrectly("jsx attribute escaping", {}, printer => { - return printer.printFile(ts.createSourceFile( + return printer.printFile(createSourceFile( "source.ts", String.raw`
`, - ts.ScriptTarget.ESNext, + ScriptTarget.ESNext, /*setParentNodes*/ undefined, - ts.ScriptKind.TSX + ScriptKind.TSX )); }); }); describe("No duplicate ref directives when emiting .d.ts->.d.ts", () => { it("without statements", () => { - const host = new fakes.CompilerHost(new vfs.FileSystem(true, { + const host = new CompilerHost(new FileSystem(true, { files: { "/test.d.ts": `/// \n/// { - const host = new fakes.CompilerHost(new vfs.FileSystem(true, { + const host = new CompilerHost(new FileSystem(true, { files: { "/test.d.ts": `/// \n/// { describe("printBundle", () => { const printsCorrectly = makePrintsCorrectly("printsBundleCorrectly"); - let bundle: ts.Bundle; + let bundle: Bundle; before(() => { - bundle = ts.factory.createBundle([ - ts.createSourceFile("a.ts", ` + bundle = factory.createBundle([ + createSourceFile("a.ts", ` /*! [a.ts] */ // comment0 const a = 1; - `, ts.ScriptTarget.ES2015), - ts.createSourceFile("b.ts", ` + `, ScriptTarget.ES2015), + createSourceFile("b.ts", ` /*! [b.ts] */ // comment1 const b = 2; - `, ts.ScriptTarget.ES2015) + `, ScriptTarget.ES2015) ]); }); printsCorrectly("default", {}, printer => printer.printBundle(bundle)); @@ -150,181 +159,181 @@ describe("unittests:: PrinterAPI", () => { describe("printNode", () => { const printsCorrectly = makePrintsCorrectly("printsNodeCorrectly"); printsCorrectly("class", {}, printer => printer.printNode( - ts.EmitHint.Unspecified, - ts.factory.createClassDeclaration( + EmitHint.Unspecified, + factory.createClassDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - /*name*/ ts.factory.createIdentifier("C"), + /*name*/ factory.createIdentifier("C"), /*typeParameters*/ undefined, /*heritageClauses*/ undefined, - [ts.factory.createPropertyDeclaration( + [factory.createPropertyDeclaration( /*decorators*/ undefined, - ts.factory.createNodeArray([ts.factory.createToken(ts.SyntaxKind.PublicKeyword)]), - ts.factory.createIdentifier("prop"), + factory.createNodeArray([factory.createToken(SyntaxKind.PublicKeyword)]), + factory.createIdentifier("prop"), /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined )] ), - ts.createSourceFile("source.ts", "", ts.ScriptTarget.ES2015) + createSourceFile("source.ts", "", ScriptTarget.ES2015) )); printsCorrectly("namespaceExportDeclaration", {}, printer => printer.printNode( - ts.EmitHint.Unspecified, - ts.factory.createNamespaceExportDeclaration("B"), - ts.createSourceFile("source.ts", "", ts.ScriptTarget.ES2015) + EmitHint.Unspecified, + factory.createNamespaceExportDeclaration("B"), + createSourceFile("source.ts", "", ScriptTarget.ES2015) )); printsCorrectly("newExpressionWithPropertyAccessOnCallExpression", {}, printer => printer.printNode( - ts.EmitHint.Unspecified, - ts.factory.createNewExpression( - ts.factory.createPropertyAccessExpression( - ts.factory.createCallExpression(ts.factory.createIdentifier("f"), /*typeArguments*/ undefined, /*argumentsArray*/ undefined), + EmitHint.Unspecified, + factory.createNewExpression( + factory.createPropertyAccessExpression( + factory.createCallExpression(factory.createIdentifier("f"), /*typeArguments*/ undefined, /*argumentsArray*/ undefined), "x"), /*typeArguments*/ undefined, /*argumentsArray*/ undefined ), - ts.createSourceFile("source.ts", "", ts.ScriptTarget.ESNext)) + createSourceFile("source.ts", "", ScriptTarget.ESNext)) ); printsCorrectly("newExpressionOnConditionalExpression", {}, printer => printer.printNode( - ts.EmitHint.Unspecified, - ts.factory.createNewExpression( - ts.factory.createConditionalExpression( - ts.factory.createIdentifier("x"), ts.factory.createToken(ts.SyntaxKind.QuestionToken), - ts.factory.createIdentifier("y"), ts.factory.createToken(ts.SyntaxKind.ColonToken), - ts.factory.createIdentifier("z")), + EmitHint.Unspecified, + factory.createNewExpression( + factory.createConditionalExpression( + factory.createIdentifier("x"), factory.createToken(SyntaxKind.QuestionToken), + factory.createIdentifier("y"), factory.createToken(SyntaxKind.ColonToken), + factory.createIdentifier("z")), /*typeArguments*/ undefined, /*argumentsArray*/ undefined ), - ts.createSourceFile("source.ts", "", ts.ScriptTarget.ESNext)) + createSourceFile("source.ts", "", ScriptTarget.ESNext)) ); printsCorrectly("emptyGlobalAugmentation", {}, printer => printer.printNode( - ts.EmitHint.Unspecified, - ts.factory.createModuleDeclaration( + EmitHint.Unspecified, + factory.createModuleDeclaration( /*decorators*/ undefined, - /*modifiers*/ [ts.factory.createToken(ts.SyntaxKind.DeclareKeyword)], - ts.factory.createIdentifier("global"), - ts.factory.createModuleBlock(ts.emptyArray), - ts.NodeFlags.GlobalAugmentation), - ts.createSourceFile("source.ts", "", ts.ScriptTarget.ES2015) + /*modifiers*/ [factory.createToken(SyntaxKind.DeclareKeyword)], + factory.createIdentifier("global"), + factory.createModuleBlock(emptyArray), + NodeFlags.GlobalAugmentation), + createSourceFile("source.ts", "", ScriptTarget.ES2015) )); printsCorrectly("emptyGlobalAugmentationWithNoDeclareKeyword", {}, printer => printer.printNode( - ts.EmitHint.Unspecified, - ts.factory.createModuleDeclaration( + EmitHint.Unspecified, + factory.createModuleDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - ts.factory.createIdentifier("global"), - ts.factory.createModuleBlock(ts.emptyArray), - ts.NodeFlags.GlobalAugmentation), - ts.createSourceFile("source.ts", "", ts.ScriptTarget.ES2015) + factory.createIdentifier("global"), + factory.createModuleBlock(emptyArray), + NodeFlags.GlobalAugmentation), + createSourceFile("source.ts", "", ScriptTarget.ES2015) )); // https://github.com/Microsoft/TypeScript/issues/15971 printsCorrectly("classWithOptionalMethodAndProperty", {}, printer => printer.printNode( - ts.EmitHint.Unspecified, - ts.factory.createClassDeclaration( + EmitHint.Unspecified, + factory.createClassDeclaration( /*decorators*/ undefined, - /*modifiers*/ [ts.factory.createToken(ts.SyntaxKind.DeclareKeyword)], - /*name*/ ts.factory.createIdentifier("X"), + /*modifiers*/ [factory.createToken(SyntaxKind.DeclareKeyword)], + /*name*/ factory.createIdentifier("X"), /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [ - ts.factory.createMethodDeclaration( + factory.createMethodDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*asteriskToken*/ undefined, - /*name*/ ts.factory.createIdentifier("method"), - /*questionToken*/ ts.factory.createToken(ts.SyntaxKind.QuestionToken), + /*name*/ factory.createIdentifier("method"), + /*questionToken*/ factory.createToken(SyntaxKind.QuestionToken), /*typeParameters*/ undefined, [], - /*type*/ ts.factory.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword), + /*type*/ factory.createKeywordTypeNode(SyntaxKind.VoidKeyword), /*body*/ undefined ), - ts.factory.createPropertyDeclaration( + factory.createPropertyDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - /*name*/ ts.factory.createIdentifier("property"), - /*questionToken*/ ts.factory.createToken(ts.SyntaxKind.QuestionToken), - /*type*/ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), + /*name*/ factory.createIdentifier("property"), + /*questionToken*/ factory.createToken(SyntaxKind.QuestionToken), + /*type*/ factory.createKeywordTypeNode(SyntaxKind.StringKeyword), /*initializer*/ undefined ), ] ), - ts.createSourceFile("source.ts", "", ts.ScriptTarget.ES2015) + createSourceFile("source.ts", "", ScriptTarget.ES2015) )); // https://github.com/Microsoft/TypeScript/issues/15651 printsCorrectly("functionTypes", {}, printer => printer.printNode( - ts.EmitHint.Unspecified, - ts.setEmitFlags(ts.factory.createTupleTypeNode([ - ts.factory.createFunctionTypeNode( + EmitHint.Unspecified, + setEmitFlags(factory.createTupleTypeNode([ + factory.createFunctionTypeNode( /*typeArguments*/ undefined, - [ts.factory.createParameterDeclaration( + [factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, - ts.factory.createIdentifier("args") + factory.createIdentifier("args") )], - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword) + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ), - ts.factory.createFunctionTypeNode( - [ts.factory.createTypeParameterDeclaration(/*modifiers*/ undefined, "T")], - [ts.factory.createParameterDeclaration( + factory.createFunctionTypeNode( + [factory.createTypeParameterDeclaration(/*modifiers*/ undefined, "T")], + [factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, - ts.factory.createIdentifier("args") + factory.createIdentifier("args") )], - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword) + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ), - ts.factory.createFunctionTypeNode( + factory.createFunctionTypeNode( /*typeArguments*/ undefined, - [ts.factory.createParameterDeclaration( + [factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - ts.factory.createToken(ts.SyntaxKind.DotDotDotToken), - ts.factory.createIdentifier("args") + factory.createToken(SyntaxKind.DotDotDotToken), + factory.createIdentifier("args") )], - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword) + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ), - ts.factory.createFunctionTypeNode( + factory.createFunctionTypeNode( /*typeArguments*/ undefined, - [ts.factory.createParameterDeclaration( + [factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, - ts.factory.createIdentifier("args"), - ts.factory.createToken(ts.SyntaxKind.QuestionToken) + factory.createIdentifier("args"), + factory.createToken(SyntaxKind.QuestionToken) )], - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword) + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ), - ts.factory.createFunctionTypeNode( + factory.createFunctionTypeNode( /*typeArguments*/ undefined, - [ts.factory.createParameterDeclaration( + [factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, - ts.factory.createIdentifier("args"), + factory.createIdentifier("args"), /*questionToken*/ undefined, - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword) + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) )], - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword) + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ), - ts.factory.createFunctionTypeNode( + factory.createFunctionTypeNode( /*typeArguments*/ undefined, - [ts.factory.createParameterDeclaration( + [factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, - ts.factory.createObjectBindingPattern([]) + factory.createObjectBindingPattern([]) )], - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword) + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ), - ]), ts.EmitFlags.SingleLine), - ts.createSourceFile("source.ts", "", ts.ScriptTarget.ES2015) + ]), EmitFlags.SingleLine), + createSourceFile("source.ts", "", ScriptTarget.ES2015) )); }); }); diff --git a/src/testRunner/unittests/programApi.ts b/src/testRunner/unittests/programApi.ts index cd260a44575c1..a453496e41014 100644 --- a/src/testRunner/unittests/programApi.ts +++ b/src/testRunner/unittests/programApi.ts @@ -1,82 +1,92 @@ -import * as documents from "../_namespaces/documents"; -import * as fakes from "../_namespaces/fakes"; -import * as Harness from "../_namespaces/Harness"; +import { arrayFrom, mapDefinedIterator } from "../../compiler/core"; +import { Set } from "../../compiler/corePublic"; +import { createSourceFile } from "../../compiler/parser"; +import { createProgram } from "../../compiler/program"; +import { sys } from "../../compiler/sys"; +import { + AsExpression, CompilerOptions, ExpressionStatement, ImportDeclaration, ModuleKind, NewLineKind, Path, Program, + ScriptKind, ScriptTarget, +} from "../../compiler/types"; +import { TextDocument } from "../../harness/documentsUtil"; +import { CompilerHost } from "../../harness/fakesHosts"; +import { IO } from "../../harness/harnessIO"; +import { createFromFileSystem } from "../../harness/vfsUtil"; +import { emptyOptions } from "../../services/types"; import * as ts from "../_namespaces/ts"; -import * as vfs from "../_namespaces/vfs"; -function verifyMissingFilePaths(missingPaths: readonly ts.Path[], expected: readonly string[]) { +function verifyMissingFilePaths(missingPaths: readonly Path[], expected: readonly string[]) { assert.isDefined(missingPaths); - const map = new ts.Set(expected); + const map = new Set(expected); for (const missing of missingPaths) { const value = map.has(missing); assert.isTrue(value, `${missing} to be ${value === undefined ? "not present" : "present only once"}, in actual: ${missingPaths} expected: ${expected}`); map.delete(missing); } - const notFound = ts.arrayFrom(ts.mapDefinedIterator(map.keys(), k => map.has(k) ? k : undefined)); + const notFound = arrayFrom(mapDefinedIterator(map.keys(), k => map.has(k) ? k : undefined)); assert.equal(notFound.length, 0, `Not found ${notFound} in actual: ${missingPaths} expected: ${expected}`); } describe("unittests:: programApi:: Program.getMissingFilePaths", () => { - const options: ts.CompilerOptions = { + const options: CompilerOptions = { noLib: true, }; const emptyFileName = "empty.ts"; const emptyFileRelativePath = "./" + emptyFileName; - const emptyFile = new documents.TextDocument(emptyFileName, ""); + const emptyFile = new TextDocument(emptyFileName, ""); const referenceFileName = "reference.ts"; const referenceFileRelativePath = "./" + referenceFileName; - const referenceFile = new documents.TextDocument(referenceFileName, + const referenceFile = new TextDocument(referenceFileName, "/// \n" + // Absolute "/// \n" + // Relative "/// \n" + // Unqualified "/// \n" // No extension ); - const testCompilerHost = new fakes.CompilerHost( - vfs.createFromFileSystem( - Harness.IO, + const testCompilerHost = new CompilerHost( + createFromFileSystem( + IO, /*ignoreCase*/ true, { documents: [emptyFile, referenceFile], cwd: "d:\\pretend\\" }), - { newLine: ts.NewLineKind.LineFeed }); + { newLine: NewLineKind.LineFeed }); it("handles no missing root files", () => { - const program = ts.createProgram([emptyFileRelativePath], options, testCompilerHost); + const program = createProgram([emptyFileRelativePath], options, testCompilerHost); const missing = program.getMissingFilePaths(); verifyMissingFilePaths(missing, []); }); it("handles missing root file", () => { - const program = ts.createProgram(["./nonexistent.ts"], options, testCompilerHost); + const program = createProgram(["./nonexistent.ts"], options, testCompilerHost); const missing = program.getMissingFilePaths(); verifyMissingFilePaths(missing, ["d:/pretend/nonexistent.ts"]); // Absolute path }); it("handles multiple missing root files", () => { - const program = ts.createProgram(["./nonexistent0.ts", "./nonexistent1.ts"], options, testCompilerHost); + const program = createProgram(["./nonexistent0.ts", "./nonexistent1.ts"], options, testCompilerHost); const missing = program.getMissingFilePaths(); verifyMissingFilePaths(missing, ["d:/pretend/nonexistent0.ts", "d:/pretend/nonexistent1.ts"]); }); it("handles a mix of present and missing root files", () => { - const program = ts.createProgram(["./nonexistent0.ts", emptyFileRelativePath, "./nonexistent1.ts"], options, testCompilerHost); + const program = createProgram(["./nonexistent0.ts", emptyFileRelativePath, "./nonexistent1.ts"], options, testCompilerHost); const missing = program.getMissingFilePaths(); verifyMissingFilePaths(missing, ["d:/pretend/nonexistent0.ts", "d:/pretend/nonexistent1.ts"]); }); it("handles repeatedly specified root files", () => { - const program = ts.createProgram(["./nonexistent.ts", "./nonexistent.ts"], options, testCompilerHost); + const program = createProgram(["./nonexistent.ts", "./nonexistent.ts"], options, testCompilerHost); const missing = program.getMissingFilePaths(); verifyMissingFilePaths(missing, ["d:/pretend/nonexistent.ts"]); }); it("normalizes file paths", () => { - const program0 = ts.createProgram(["./nonexistent.ts", "./NONEXISTENT.ts"], options, testCompilerHost); - const program1 = ts.createProgram(["./NONEXISTENT.ts", "./nonexistent.ts"], options, testCompilerHost); + const program0 = createProgram(["./nonexistent.ts", "./NONEXISTENT.ts"], options, testCompilerHost); + const program1 = createProgram(["./NONEXISTENT.ts", "./nonexistent.ts"], options, testCompilerHost); const missing0 = program0.getMissingFilePaths(); const missing1 = program1.getMissingFilePaths(); assert.equal(missing0.length, 1); @@ -84,7 +94,7 @@ describe("unittests:: programApi:: Program.getMissingFilePaths", () => { }); it("handles missing triple slash references", () => { - const program = ts.createProgram([referenceFileRelativePath], options, testCompilerHost); + const program = createProgram([referenceFileRelativePath], options, testCompilerHost); const missing = program.getMissingFilePaths(); verifyMissingFilePaths(missing, [ // From absolute reference @@ -110,22 +120,22 @@ describe("unittests:: programApi:: Program.getMissingFilePaths", () => { }`; const host: ts.CompilerHost = { - getSourceFile: (fileName: string, languageVersion: ts.ScriptTarget, _onError?: (message: string) => void) => { - return fileName === "test.ts" ? ts.createSourceFile(fileName, testSource, languageVersion) : undefined; + getSourceFile: (fileName: string, languageVersion: ScriptTarget, _onError?: (message: string) => void) => { + return fileName === "test.ts" ? createSourceFile(fileName, testSource, languageVersion) : undefined; }, getDefaultLibFileName: () => "", writeFile: (_fileName, _content) => { throw new Error("unsupported"); }, - getCurrentDirectory: () => ts.sys.getCurrentDirectory(), - getCanonicalFileName: fileName => ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(), - getNewLine: () => ts.sys.newLine, - useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames, + getCurrentDirectory: () => sys.getCurrentDirectory(), + getCanonicalFileName: fileName => sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(), + getNewLine: () => sys.newLine, + useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames, fileExists: fileName => fileName === "test.ts", readFile: fileName => fileName === "test.ts" ? testSource : undefined, resolveModuleNames: (_moduleNames: string[], _containingFile: string) => { throw new Error("unsupported"); }, getDirectories: _path => { throw new Error("unsupported"); }, }; - const program = ts.createProgram(["test.ts"], { module: ts.ModuleKind.ES2015 }, host); + const program = createProgram(["test.ts"], { module: ModuleKind.ES2015 }, host); assert(program.getSourceFiles().length === 1, "expected 'getSourceFiles' length to be 1"); assert(program.getMissingFilePaths().length === 0, "expected 'getMissingFilePaths' length to be 0"); assert((program.getFileProcessingDiagnostics()?.length || 0) === 0, "expected 'getFileProcessingDiagnostics' length to be 0"); @@ -135,29 +145,29 @@ describe("unittests:: programApi:: Program.getMissingFilePaths", () => { describe("unittests:: Program.isSourceFileFromExternalLibrary", () => { it("works on redirect files", () => { // In this example '/node_modules/foo/index.d.ts' will redirect to '/node_modules/bar/node_modules/foo/index.d.ts'. - const a = new documents.TextDocument("/a.ts", 'import * as bar from "bar"; import * as foo from "foo";'); - const bar = new documents.TextDocument("/node_modules/bar/index.d.ts", 'import * as foo from "foo";'); + const a = new TextDocument("/a.ts", 'import * as bar from "bar"; import * as foo from "foo";'); + const bar = new TextDocument("/node_modules/bar/index.d.ts", 'import * as foo from "foo";'); const fooPackageJsonText = '{ "name": "foo", "version": "1.2.3" }'; const fooIndexText = "export const x: number;"; - const barFooPackage = new documents.TextDocument("/node_modules/bar/node_modules/foo/package.json", fooPackageJsonText); - const barFooIndex = new documents.TextDocument("/node_modules/bar/node_modules/foo/index.d.ts", fooIndexText); - const fooPackage = new documents.TextDocument("/node_modules/foo/package.json", fooPackageJsonText); - const fooIndex = new documents.TextDocument("/node_modules/foo/index.d.ts", fooIndexText); + const barFooPackage = new TextDocument("/node_modules/bar/node_modules/foo/package.json", fooPackageJsonText); + const barFooIndex = new TextDocument("/node_modules/bar/node_modules/foo/index.d.ts", fooIndexText); + const fooPackage = new TextDocument("/node_modules/foo/package.json", fooPackageJsonText); + const fooIndex = new TextDocument("/node_modules/foo/index.d.ts", fooIndexText); - const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, { documents: [a, bar, barFooPackage, barFooIndex, fooPackage, fooIndex], cwd: "/" }); - const program = ts.createProgram(["/a.ts"], ts.emptyOptions, new fakes.CompilerHost(fs, { newLine: ts.NewLineKind.LineFeed })); + const fs = createFromFileSystem(IO, /*ignoreCase*/ false, { documents: [a, bar, barFooPackage, barFooIndex, fooPackage, fooIndex], cwd: "/" }); + const program = createProgram(["/a.ts"], emptyOptions, new CompilerHost(fs, { newLine: NewLineKind.LineFeed })); assertIsExternal(program, [a, bar, barFooIndex, fooIndex], f => f !== a); }); it('works on `/// `', () => { - const a = new documents.TextDocument("/a.ts", '/// '); - const fooIndex = new documents.TextDocument("/node_modules/foo/index.d.ts", "declare const foo: number;"); - const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, { documents: [a, fooIndex], cwd: "/" }); - const program = ts.createProgram(["/a.ts"], ts.emptyOptions, new fakes.CompilerHost(fs, { newLine: ts.NewLineKind.LineFeed })); + const a = new TextDocument("/a.ts", '/// '); + const fooIndex = new TextDocument("/node_modules/foo/index.d.ts", "declare const foo: number;"); + const fs = createFromFileSystem(IO, /*ignoreCase*/ false, { documents: [a, fooIndex], cwd: "/" }); + const program = createProgram(["/a.ts"], emptyOptions, new CompilerHost(fs, { newLine: NewLineKind.LineFeed })); assertIsExternal(program, [a, fooIndex], f => f !== a); }); - function assertIsExternal(program: ts.Program, files: readonly documents.TextDocument[], isExternalExpected: (file: documents.TextDocument) => boolean): void { + function assertIsExternal(program: Program, files: readonly TextDocument[], isExternalExpected: (file: TextDocument) => boolean): void { for (const file of files) { const actual = program.isSourceFileFromExternalLibrary(program.getSourceFile(file.file)!); const expected = isExternalExpected(file); @@ -168,14 +178,14 @@ describe("unittests:: Program.isSourceFileFromExternalLibrary", () => { describe("unittests:: Program.getNodeCount / Program.getIdentifierCount", () => { it("works on projects that have .json files", () => { - const main = new documents.TextDocument("/main.ts", 'export { version } from "./package.json";'); - const pkg = new documents.TextDocument("/package.json", '{"version": "1.0.0"}'); + const main = new TextDocument("/main.ts", 'export { version } from "./package.json";'); + const pkg = new TextDocument("/package.json", '{"version": "1.0.0"}'); - const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, { documents: [main, pkg], cwd: "/" }); - const program = ts.createProgram(["/main.ts"], { resolveJsonModule: true }, new fakes.CompilerHost(fs, { newLine: ts.NewLineKind.LineFeed })); + const fs = createFromFileSystem(IO, /*ignoreCase*/ false, { documents: [main, pkg], cwd: "/" }); + const program = createProgram(["/main.ts"], { resolveJsonModule: true }, new CompilerHost(fs, { newLine: NewLineKind.LineFeed })); const json = program.getSourceFile("/package.json")!; - assert.equal(json.scriptKind, ts.ScriptKind.JSON); + assert.equal(json.scriptKind, ScriptKind.JSON); assert.isNumber(json.nodeCount); assert.isNumber(json.identifierCount); @@ -186,39 +196,39 @@ describe("unittests:: Program.getNodeCount / Program.getIdentifierCount", () => describe("unittests:: programApi:: Program.getTypeChecker / Program.getSemanticDiagnostics", () => { it("does not produce errors on `as const` it would not normally produce on the command line", () => { - const main = new documents.TextDocument("/main.ts", "0 as const"); + const main = new TextDocument("/main.ts", "0 as const"); - const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, { documents: [main], cwd: "/" }); - const program = ts.createProgram(["/main.ts"], {}, new fakes.CompilerHost(fs, { newLine: ts.NewLineKind.LineFeed })); + const fs = createFromFileSystem(IO, /*ignoreCase*/ false, { documents: [main], cwd: "/" }); + const program = createProgram(["/main.ts"], {}, new CompilerHost(fs, { newLine: NewLineKind.LineFeed })); const typeChecker = program.getTypeChecker(); const sourceFile = program.getSourceFile("main.ts")!; - typeChecker.getTypeAtLocation(((sourceFile.statements[0] as ts.ExpressionStatement).expression as ts.AsExpression).type); + typeChecker.getTypeAtLocation(((sourceFile.statements[0] as ExpressionStatement).expression as AsExpression).type); const diag = program.getSemanticDiagnostics(); assert.isEmpty(diag); }); it("getSymbolAtLocation does not cause additional error to be added on module resolution failure", () => { - const main = new documents.TextDocument("/main.ts", "import \"./module\";"); - const mod = new documents.TextDocument("/module.d.ts", "declare const foo: any;"); + const main = new TextDocument("/main.ts", "import \"./module\";"); + const mod = new TextDocument("/module.d.ts", "declare const foo: any;"); - const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, { documents: [main, mod], cwd: "/" }); - const program = ts.createProgram(["/main.ts"], {}, new fakes.CompilerHost(fs, { newLine: ts.NewLineKind.LineFeed })); + const fs = createFromFileSystem(IO, /*ignoreCase*/ false, { documents: [main, mod], cwd: "/" }); + const program = createProgram(["/main.ts"], {}, new CompilerHost(fs, { newLine: NewLineKind.LineFeed })); const sourceFile = program.getSourceFile("main.ts")!; const typeChecker = program.getTypeChecker(); - typeChecker.getSymbolAtLocation((sourceFile.statements[0] as ts.ImportDeclaration).moduleSpecifier); + typeChecker.getSymbolAtLocation((sourceFile.statements[0] as ImportDeclaration).moduleSpecifier); assert.isEmpty(program.getSemanticDiagnostics()); }); }); describe("unittests:: programApi:: CompilerOptions relative paths", () => { it("resolves relative paths by getCurrentDirectory", () => { - const main = new documents.TextDocument("/main.ts", "import \"module\";"); - const mod = new documents.TextDocument("/lib/module.ts", "declare const foo: any;"); + const main = new TextDocument("/main.ts", "import \"module\";"); + const mod = new TextDocument("/lib/module.ts", "declare const foo: any;"); - const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, { documents: [main, mod], cwd: "/" }); - const program = ts.createProgram(["./main.ts"], { + const fs = createFromFileSystem(IO, /*ignoreCase*/ false, { documents: [main, mod], cwd: "/" }); + const program = createProgram(["./main.ts"], { paths: { "*": ["./lib/*"] } - }, new fakes.CompilerHost(fs, { newLine: ts.NewLineKind.LineFeed })); + }, new CompilerHost(fs, { newLine: NewLineKind.LineFeed })); assert.isEmpty(program.getConfigFileParsingDiagnostics()); assert.isEmpty(program.getGlobalDiagnostics()); diff --git a/src/testRunner/unittests/publicApi.ts b/src/testRunner/unittests/publicApi.ts index 4712494bea61b..cc70bdafdd6bb 100644 --- a/src/testRunner/unittests/publicApi.ts +++ b/src/testRunner/unittests/publicApi.ts @@ -1,9 +1,22 @@ -import * as compiler from "../_namespaces/compiler"; -import * as documents from "../_namespaces/documents"; -import * as fakes from "../_namespaces/fakes"; -import * as Harness from "../_namespaces/Harness"; -import * as ts from "../_namespaces/ts"; -import * as vfs from "../_namespaces/vfs"; +import { findLast, getUILocale, identity, setUILocale } from "../../compiler/core"; +import { Debug } from "../../compiler/debug"; +import { factory } from "../../compiler/factory/nodeFactory"; +import { isClassDeclaration, isFunctionDeclaration, isVariableStatement } from "../../compiler/factory/nodeTests"; +import { createSourceFile, forEachChild } from "../../compiler/parser"; +import { createProgram } from "../../compiler/program"; +import { tokenToString } from "../../compiler/scanner"; +import { + CompilerOptions, Diagnostic, Node, PropertyAccessExpression, ScriptTarget, SyntaxKind, TypeFlags, VariableStatement, +} from "../../compiler/types"; +import { + getJSDocTags, isPropertyName, supportedLocaleDirectories, validateLocaleAndSetLanguage, +} from "../../compiler/utilitiesPublic"; +import { compileFiles } from "../../harness/compilerImpl"; +import { TextDocument } from "../../harness/documentsUtil"; +import { CompilerHost, System } from "../../harness/fakesHosts"; +import { Baseline, Compiler, IO } from "../../harness/harnessIO"; +import { builtFolder, createFromFileSystem, srcFolder } from "../../harness/vfsUtil"; +import { getDefaultCompilerOptions } from "../../services/services"; describe("unittests:: Public APIs", () => { function verifyApi(fileName: string) { @@ -11,27 +24,27 @@ describe("unittests:: Public APIs", () => { const api = `api/${fileName}`; let fileContent: string; before(() => { - fileContent = Harness.IO.readFile(builtFile)!; + fileContent = IO.readFile(builtFile)!; if (!fileContent) throw new Error(`File ${fileName} was not present in built/local`); fileContent = fileContent.replace(/\r\n/g, "\n"); }); it("should be acknowledged when they change", () => { - Harness.Baseline.runBaseline(api, fileContent, { PrintDiff: true }); + Baseline.runBaseline(api, fileContent, { PrintDiff: true }); }); it("should compile", () => { - const fs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false); - fs.linkSync(`${vfs.builtFolder}/${fileName}`, `${vfs.srcFolder}/${fileName}`); - const sys = new fakes.System(fs); - const options: ts.CompilerOptions = { - ...ts.getDefaultCompilerOptions(), + const fs = createFromFileSystem(IO, /*ignoreCase*/ false); + fs.linkSync(`${builtFolder}/${fileName}`, `${srcFolder}/${fileName}`); + const sys = new System(fs); + const options: CompilerOptions = { + ...getDefaultCompilerOptions(), strict: true, exactOptionalPropertyTypes: true, }; - const host = new fakes.CompilerHost(sys, options); - const result = compiler.compileFiles(host, [`${vfs.srcFolder}/${fileName}`], options); - assert(!result.diagnostics || !result.diagnostics.length, Harness.Compiler.minimalDiagnosticsToString(result.diagnostics, /*pretty*/ true)); + const host = new CompilerHost(sys, options); + const result = compileFiles(host, [`${srcFolder}/${fileName}`], options); + assert(!result.diagnostics || !result.diagnostics.length, Compiler.minimalDiagnosticsToString(result.diagnostics, /*pretty*/ true)); }); } @@ -45,23 +58,23 @@ describe("unittests:: Public APIs", () => { }); describe("unittests:: Public APIs:: token to string", () => { - function assertDefinedTokenToString(initial: ts.SyntaxKind, last: ts.SyntaxKind) { + function assertDefinedTokenToString(initial: SyntaxKind, last: SyntaxKind) { for (let t = initial; t <= last; t++) { - assert.isDefined(ts.tokenToString(t), `Expected tokenToString defined for ${ts.Debug.formatSyntaxKind(t)}`); + assert.isDefined(tokenToString(t), `Expected tokenToString defined for ${Debug.formatSyntaxKind(t)}`); } } it("for punctuations", () => { - assertDefinedTokenToString(ts.SyntaxKind.FirstPunctuation, ts.SyntaxKind.LastPunctuation); + assertDefinedTokenToString(SyntaxKind.FirstPunctuation, SyntaxKind.LastPunctuation); }); it("for keywords", () => { - assertDefinedTokenToString(ts.SyntaxKind.FirstKeyword, ts.SyntaxKind.LastKeyword); + assertDefinedTokenToString(SyntaxKind.FirstKeyword, SyntaxKind.LastKeyword); }); }); describe("unittests:: Public APIs:: createPrivateIdentifier", () => { it("throws when name doesn't start with #", () => { - assert.throw(() => ts.factory.createPrivateIdentifier("not"), "Debug Failure. First character of private identifier must be #: not"); + assert.throw(() => factory.createPrivateIdentifier("not"), "Debug Failure. First character of private identifier must be #: not"); }); }); @@ -75,9 +88,9 @@ describe("unittests:: Public APIs:: JSDoc newlines", () => { */ function test() {}`; - const testSourceFile = ts.createSourceFile(testFilePath, testFileText, ts.ScriptTarget.Latest, /*setParentNodes*/ true); - const funcDec = testSourceFile.statements.find(ts.isFunctionDeclaration)!; - const tags = ts.getJSDocTags(funcDec); + const testSourceFile = createSourceFile(testFilePath, testFileText, ScriptTarget.Latest, /*setParentNodes*/ true); + const funcDec = testSourceFile.statements.find(isFunctionDeclaration)!; + const tags = getJSDocTags(funcDec); assert.isDefined(tags[0].comment); assert.isDefined(tags[0].comment![0]); assert.isString(tags[0].comment); @@ -87,8 +100,8 @@ function test() {}`; describe("unittests:: Public APIs:: isPropertyName", () => { it("checks if a PrivateIdentifier is a valid property name", () => { - const prop = ts.factory.createPrivateIdentifier("#foo"); - assert.isTrue(ts.isPropertyName(prop), "PrivateIdentifier must be a valid property name."); + const prop = factory.createPrivateIdentifier("#foo"); + assert.isTrue(isPropertyName(prop), "PrivateIdentifier must be a valid property name."); }); }); @@ -99,12 +112,12 @@ describe("unittests:: Public APIs:: getTypeAtLocation", () => { } class Foo implements Test.Test {}`; - const host = new fakes.CompilerHost(vfs.createFromFileSystem( - Harness.IO, + const host = new CompilerHost(createFromFileSystem( + IO, /*ignoreCase*/ true, - { documents: [new documents.TextDocument("/file.ts", content)], cwd: "/" })); + { documents: [new TextDocument("/file.ts", content)], cwd: "/" })); - const program = ts.createProgram({ + const program = createProgram({ host, rootNames: ["/file.ts"], options: { noLib: true } @@ -112,21 +125,21 @@ describe("unittests:: Public APIs:: getTypeAtLocation", () => { const checker = program.getTypeChecker(); const file = program.getSourceFile("/file.ts")!; - const classDeclaration = file.statements.find(ts.isClassDeclaration)!; - const propertyAccess = classDeclaration.heritageClauses![0].types[0].expression as ts.PropertyAccessExpression; + const classDeclaration = file.statements.find(isClassDeclaration)!; + const propertyAccess = classDeclaration.heritageClauses![0].types[0].expression as PropertyAccessExpression; const type = checker.getTypeAtLocation(propertyAccess); - assert.ok(!(type.flags & ts.TypeFlags.Any)); + assert.ok(!(type.flags & TypeFlags.Any)); assert.equal(type, checker.getTypeAtLocation(propertyAccess.name)); }); it("works on SourceFile", () => { const content = `const foo = 1;`; - const host = new fakes.CompilerHost(vfs.createFromFileSystem( - Harness.IO, + const host = new CompilerHost(createFromFileSystem( + IO, /*ignoreCase*/ true, - { documents: [new documents.TextDocument("/file.ts", content)], cwd: "/" })); + { documents: [new TextDocument("/file.ts", content)], cwd: "/" })); - const program = ts.createProgram({ + const program = createProgram({ host, rootNames: ["/file.ts"], options: { noLib: true } @@ -135,18 +148,18 @@ describe("unittests:: Public APIs:: getTypeAtLocation", () => { const checker = program.getTypeChecker(); const file = program.getSourceFile("/file.ts")!; const type = checker.getTypeAtLocation(file); - assert.equal(type.flags, ts.TypeFlags.Any); + assert.equal(type.flags, TypeFlags.Any); }); it("returns an errorType for VariableDeclaration with BindingPattern name", () => { const content = "const foo = [1];\n" + "const [a] = foo;"; - const host = new fakes.CompilerHost(vfs.createFromFileSystem( - Harness.IO, + const host = new CompilerHost(createFromFileSystem( + IO, /*ignoreCase*/ true, - { documents: [new documents.TextDocument("/file.ts", content)], cwd: "/" })); + { documents: [new TextDocument("/file.ts", content)], cwd: "/" })); - const program = ts.createProgram({ + const program = createProgram({ host, rootNames: ["/file.ts"], options: { noLib: true } @@ -154,22 +167,22 @@ describe("unittests:: Public APIs:: getTypeAtLocation", () => { const checker = program.getTypeChecker(); const file = program.getSourceFile("/file.ts")!; - const [declaration] = (ts.findLast(file.statements, ts.isVariableStatement) as ts.VariableStatement).declarationList.declarations; - assert.equal(checker.getTypeAtLocation(declaration).flags, ts.TypeFlags.Any); + const [declaration] = (findLast(file.statements, isVariableStatement) as VariableStatement).declarationList.declarations; + assert.equal(checker.getTypeAtLocation(declaration).flags, TypeFlags.Any); }); }); describe("unittests:: Public APIs:: validateLocaleAndSetLanguage", () => { let savedUILocale: string | undefined; - beforeEach(() => savedUILocale = ts.getUILocale()); - afterEach(() => ts.setUILocale(savedUILocale)); + beforeEach(() => savedUILocale = getUILocale()); + afterEach(() => setUILocale(savedUILocale)); function verifyValidateLocale(locale: string, expectedToReadFile: boolean) { it(`Verifying ${locale} ${expectedToReadFile ? "reads" : "does not read"} file`, () => { - const errors: ts.Diagnostic[] = []; - ts.validateLocaleAndSetLanguage(locale, { + const errors: Diagnostic[] = []; + validateLocaleAndSetLanguage(locale, { getExecutingFilePath: () => "/tsc.js", - resolvePath: ts.identity, + resolvePath: identity, fileExists: fileName => { assert.isTrue(expectedToReadFile, `Locale : ${locale} ${expectedToReadFile ? "should" : "should not"} check if ${fileName} exists.`); return expectedToReadFile; @@ -182,7 +195,7 @@ describe("unittests:: Public APIs:: validateLocaleAndSetLanguage", () => { }, errors); }); } - ts.supportedLocaleDirectories.forEach(locale => verifyValidateLocale(locale, /*expectedToReadFile*/ true)); + supportedLocaleDirectories.forEach(locale => verifyValidateLocale(locale, /*expectedToReadFile*/ true)); ["en", "en-us"].forEach(locale => verifyValidateLocale(locale, /*expectedToReadFile*/ false)); }); @@ -194,11 +207,11 @@ describe("unittests:: Public APIs :: forEachChild of @param comments in JSDoc", */ var x `; - const sourceFile = ts.createSourceFile("/file.ts", content, ts.ScriptTarget.ESNext, /*setParentNodes*/ true); + const sourceFile = createSourceFile("/file.ts", content, ScriptTarget.ESNext, /*setParentNodes*/ true); const paramTag = sourceFile.getChildren()[0].getChildren()[0].getChildren()[0].getChildren()[0]; const kids = paramTag.getChildren(); - const seen: Set = new Set(); - ts.forEachChild(paramTag, n => { + const seen: Set = new Set(); + forEachChild(paramTag, n => { assert.strictEqual(/*actual*/ false, seen.has(n), "Found a duplicate-added child"); seen.add(n); }); @@ -211,7 +224,7 @@ describe("unittests:: Public APIs:: getChild* methods on EndOfFileToken with JSD const content = ` /** jsdoc comment attached to EndOfFileToken */ `; - const sourceFile = ts.createSourceFile("/file.ts", content, ts.ScriptTarget.ESNext, /*setParentNodes*/ true); + const sourceFile = createSourceFile("/file.ts", content, ScriptTarget.ESNext, /*setParentNodes*/ true); const endOfFileToken = sourceFile.getChildren()[1]; assert.equal(endOfFileToken.getChildren().length, 1); assert.equal(endOfFileToken.getChildCount(), 1); diff --git a/src/testRunner/unittests/reuseProgramStructure.ts b/src/testRunner/unittests/reuseProgramStructure.ts index 7891de1f116ba..61a1a513e88ef 100644 --- a/src/testRunner/unittests/reuseProgramStructure.ts +++ b/src/testRunner/unittests/reuseProgramStructure.ts @@ -1,4 +1,28 @@ -import * as ts from "../_namespaces/ts"; +import { + arrayToMap, createGetCanonicalFileName, emptyArray, find, getEntries, mapEntries, noop, notImplemented, returnFalse, + returnUndefined, +} from "../../compiler/core"; +import { ESMap, Map } from "../../compiler/corePublic"; +import { Debug } from "../../compiler/debug"; +import { ModeAwareCache } from "../../compiler/moduleNameResolver"; +import { createSourceFile, updateSourceFile } from "../../compiler/parser"; +import { toPath } from "../../compiler/path"; +import { createProgram, isProgramUptoDate } from "../../compiler/program"; +import { sys, System } from "../../compiler/sys"; +import { + CompilerHost, CompilerOptions, ModuleKind, ModuleResolutionKind, Program, ResolvedModule, + ResolvedTypeReferenceDirective, ScriptTarget, SourceFile, StructureIsReused, TextChangeRange, TextSpan, +} from "../../compiler/types"; +import { forEachEntry } from "../../compiler/utilities"; +import { createTextChangeRange, createTextSpan } from "../../compiler/utilitiesPublic"; +import { + createWatchCompilerHostOfConfigFile, createWatchCompilerHostOfFilesAndCompilerOptions, parseConfigFileWithSystem, +} from "../../compiler/watch"; +import { createWatchProgram } from "../../compiler/watchPublic"; +import { TestFSWithWatch } from "../../harness/_namespaces/ts"; +import { createWatchedSystem as createTestSystem, libFile } from "../../harness/virtualFileSystemWithWatch"; +import { IScriptSnapshot } from "../../services/types"; +import { checkResolvedModule, createResolvedModule } from "./moduleResolution"; const enum ChangedPart { references = 1 << 0, @@ -8,7 +32,7 @@ const enum ChangedPart { const newLine = "\r\n"; -interface SourceFileWithText extends ts.SourceFile { +interface SourceFileWithText extends SourceFile { sourceText?: SourceText; } @@ -17,16 +41,16 @@ export interface NamedSourceText { text: SourceText; } -export interface ProgramWithSourceTexts extends ts.Program { +export interface ProgramWithSourceTexts extends Program { sourceTexts?: readonly NamedSourceText[]; host: TestCompilerHost; } -interface TestCompilerHost extends ts.CompilerHost { +interface TestCompilerHost extends CompilerHost { getTrace(): string[]; } -export class SourceText implements ts.IScriptSnapshot { +export class SourceText implements IScriptSnapshot { private fullText: string | undefined; constructor(private references: string, @@ -37,9 +61,9 @@ export class SourceText implements ts.IScriptSnapshot { } static New(references: string, importsAndExports: string, program: string): SourceText { - ts.Debug.assert(references !== undefined); - ts.Debug.assert(importsAndExports !== undefined); - ts.Debug.assert(program !== undefined); + Debug.assert(references !== undefined); + Debug.assert(importsAndExports !== undefined); + Debug.assert(program !== undefined); return new SourceText(references + newLine, importsAndExports + newLine, program || ""); } @@ -48,15 +72,15 @@ export class SourceText implements ts.IScriptSnapshot { } public updateReferences(newReferences: string): SourceText { - ts.Debug.assert(newReferences !== undefined); + Debug.assert(newReferences !== undefined); return new SourceText(newReferences + newLine, this.importsAndExports, this.program, this.changedPart | ChangedPart.references, this.version + 1); } public updateImportsAndExports(newImportsAndExports: string): SourceText { - ts.Debug.assert(newImportsAndExports !== undefined); + Debug.assert(newImportsAndExports !== undefined); return new SourceText(this.references, newImportsAndExports + newLine, this.program, this.changedPart | ChangedPart.importsAndExports, this.version + 1); } public updateProgram(newProgram: string): SourceText { - ts.Debug.assert(newProgram !== undefined); + Debug.assert(newProgram !== undefined); return new SourceText(this.references, this.importsAndExports, newProgram, this.changedPart | ChangedPart.program, this.version + 1); } @@ -72,40 +96,40 @@ export class SourceText implements ts.IScriptSnapshot { return this.getFullText().length; } - getChangeRange(oldSnapshot: ts.IScriptSnapshot): ts.TextChangeRange { + getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange { const oldText = oldSnapshot as SourceText; - let oldSpan: ts.TextSpan; + let oldSpan: TextSpan; let newLength: number; switch (oldText.changedPart ^ this.changedPart) { case ChangedPart.references: - oldSpan = ts.createTextSpan(0, oldText.references.length); + oldSpan = createTextSpan(0, oldText.references.length); newLength = this.references.length; break; case ChangedPart.importsAndExports: - oldSpan = ts.createTextSpan(oldText.references.length, oldText.importsAndExports.length); + oldSpan = createTextSpan(oldText.references.length, oldText.importsAndExports.length); newLength = this.importsAndExports.length; break; case ChangedPart.program: - oldSpan = ts.createTextSpan(oldText.references.length + oldText.importsAndExports.length, oldText.program.length); + oldSpan = createTextSpan(oldText.references.length + oldText.importsAndExports.length, oldText.program.length); newLength = this.program.length; break; default: - return ts.Debug.fail("Unexpected change"); + return Debug.fail("Unexpected change"); } - return ts.createTextChangeRange(oldSpan, newLength); + return createTextChangeRange(oldSpan, newLength); } } -function createSourceFileWithText(fileName: string, sourceText: SourceText, target: ts.ScriptTarget) { - const file = ts.createSourceFile(fileName, sourceText.getFullText(), target) as SourceFileWithText; +function createSourceFileWithText(fileName: string, sourceText: SourceText, target: ScriptTarget) { + const file = createSourceFile(fileName, sourceText.getFullText(), target) as SourceFileWithText; file.sourceText = sourceText; file.version = "" + sourceText.getVersion(); return file; } -export function createTestCompilerHost(texts: readonly NamedSourceText[], target: ts.ScriptTarget, oldProgram?: ProgramWithSourceTexts, useGetSourceFileByPath?: boolean) { - const files = ts.arrayToMap(texts, t => t.name, t => { +export function createTestCompilerHost(texts: readonly NamedSourceText[], target: ScriptTarget, oldProgram?: ProgramWithSourceTexts, useGetSourceFileByPath?: boolean) { + const files = arrayToMap(texts, t => t.name, t => { if (oldProgram) { let oldFile = oldProgram.getSourceFile(t.name) as SourceFileWithText; if (oldFile && oldFile.redirectInfo) { @@ -117,20 +141,20 @@ export function createTestCompilerHost(texts: readonly NamedSourceText[], target } return createSourceFileWithText(t.name, t.text, target); }); - const useCaseSensitiveFileNames = ts.sys && ts.sys.useCaseSensitiveFileNames; - const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); + const useCaseSensitiveFileNames = sys && sys.useCaseSensitiveFileNames; + const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames); const trace: string[] = []; const result: TestCompilerHost = { trace: s => trace.push(s), getTrace: () => trace, getSourceFile: fileName => files.get(fileName), getDefaultLibFileName: () => "lib.d.ts", - writeFile: ts.notImplemented, + writeFile: notImplemented, getCurrentDirectory: () => "", getDirectories: () => [], getCanonicalFileName, useCaseSensitiveFileNames: () => useCaseSensitiveFileNames, - getNewLine: () => ts.sys ? ts.sys.newLine : newLine, + getNewLine: () => sys ? sys.newLine : newLine, fileExists: fileName => files.has(fileName), readFile: fileName => { const file = files.get(fileName); @@ -138,44 +162,44 @@ export function createTestCompilerHost(texts: readonly NamedSourceText[], target }, }; if (useGetSourceFileByPath) { - const filesByPath = ts.mapEntries(files, (fileName, file) => [ts.toPath(fileName, "", getCanonicalFileName), file]); + const filesByPath = mapEntries(files, (fileName, file) => [toPath(fileName, "", getCanonicalFileName), file]); result.getSourceFileByPath = (_fileName, path) => filesByPath.get(path); } return result; } -export function newProgram(texts: NamedSourceText[], rootNames: string[], options: ts.CompilerOptions, useGetSourceFileByPath?: boolean): ProgramWithSourceTexts { +export function newProgram(texts: NamedSourceText[], rootNames: string[], options: CompilerOptions, useGetSourceFileByPath?: boolean): ProgramWithSourceTexts { const host = createTestCompilerHost(texts, options.target!, /*oldProgram*/ undefined, useGetSourceFileByPath); - const program = ts.createProgram(rootNames, options, host) as ProgramWithSourceTexts; + const program = createProgram(rootNames, options, host) as ProgramWithSourceTexts; program.sourceTexts = texts; program.host = host; return program; } -export function updateProgram(oldProgram: ProgramWithSourceTexts, rootNames: readonly string[], options: ts.CompilerOptions, updater: (files: NamedSourceText[]) => void, newTexts?: NamedSourceText[], useGetSourceFileByPath?: boolean) { +export function updateProgram(oldProgram: ProgramWithSourceTexts, rootNames: readonly string[], options: CompilerOptions, updater: (files: NamedSourceText[]) => void, newTexts?: NamedSourceText[], useGetSourceFileByPath?: boolean) { if (!newTexts) { newTexts = oldProgram.sourceTexts!.slice(0); } updater(newTexts); const host = createTestCompilerHost(newTexts, options.target!, oldProgram, useGetSourceFileByPath); - const program = ts.createProgram(rootNames, options, host, oldProgram) as ProgramWithSourceTexts; + const program = createProgram(rootNames, options, host, oldProgram) as ProgramWithSourceTexts; program.sourceTexts = newTexts; program.host = host; return program; } export function updateProgramText(files: readonly NamedSourceText[], fileName: string, newProgramText: string) { - const file = ts.find(files, f => f.name === fileName)!; + const file = find(files, f => f.name === fileName)!; file.text = file.text.updateProgram(newProgramText); } -function checkResolvedTypeDirective(actual: ts.ResolvedTypeReferenceDirective, expected: ts.ResolvedTypeReferenceDirective) { +function checkResolvedTypeDirective(actual: ResolvedTypeReferenceDirective, expected: ResolvedTypeReferenceDirective) { assert.equal(actual.resolvedFileName, expected.resolvedFileName, `'resolvedFileName': expected '${actual.resolvedFileName}' to be equal to '${expected.resolvedFileName}'`); assert.equal(actual.primary, expected.primary, `'primary': expected '${actual.primary}' to be equal to '${expected.primary}'`); return true; } -function checkCache(caption: string, program: ts.Program, fileName: string, expectedContent: ts.ESMap | undefined, getCache: (f: ts.SourceFile) => ts.ModeAwareCache | undefined, entryChecker: (expected: T, original: T) => boolean): void { +function checkCache(caption: string, program: Program, fileName: string, expectedContent: ESMap | undefined, getCache: (f: SourceFile) => ModeAwareCache | undefined, entryChecker: (expected: T, original: T) => boolean): void { const file = program.getSourceFile(fileName); assert.isTrue(file !== undefined, `cannot find file ${fileName}`); const cache = getCache(file!); @@ -189,10 +213,10 @@ function checkCache(caption: string, program: ts.Program, fileName: string, e } /** True if the maps have the same keys and values. */ -function mapEqualToCache(left: ts.ESMap, right: ts.ModeAwareCache, valuesAreEqual?: (left: T, right: T) => boolean): boolean { +function mapEqualToCache(left: ESMap, right: ModeAwareCache, valuesAreEqual?: (left: T, right: T) => boolean): boolean { if (left as any === right) return true; // given the type mismatch (the tests never pass a cache), this'll never be true if (!left || !right) return false; - const someInLeftHasNoMatch = ts.forEachEntry(left, (leftValue, leftKey) => { + const someInLeftHasNoMatch = forEachEntry(left, (leftValue, leftKey) => { if (!right.has(leftKey, /*mode*/ undefined)) return true; const rightValue = right.get(leftKey, /*mode*/ undefined)!; return !(valuesAreEqual ? valuesAreEqual(leftValue, rightValue) : leftValue === rightValue); @@ -203,16 +227,16 @@ function mapEqualToCache(left: ts.ESMap, right: ts.ModeAwareCache< return !someInRightHasNoMatch; } -function checkResolvedModulesCache(program: ts.Program, fileName: string, expectedContent: ts.ESMap | undefined): void { - checkCache("resolved modules", program, fileName, expectedContent, f => f.resolvedModules, ts.checkResolvedModule); +function checkResolvedModulesCache(program: Program, fileName: string, expectedContent: ESMap | undefined): void { + checkCache("resolved modules", program, fileName, expectedContent, f => f.resolvedModules, checkResolvedModule); } -function checkResolvedTypeDirectivesCache(program: ts.Program, fileName: string, expectedContent: ts.ESMap | undefined): void { +function checkResolvedTypeDirectivesCache(program: Program, fileName: string, expectedContent: ESMap | undefined): void { checkCache("resolved type directives", program, fileName, expectedContent, f => f.resolvedTypeReferenceDirectiveNames, checkResolvedTypeDirective); } describe("unittests:: Reuse program structure:: General", () => { - const target = ts.ScriptTarget.Latest; + const target = ScriptTarget.Latest; const files: NamedSourceText[] = [ { name: "a.ts", text: SourceText.New( @@ -232,7 +256,7 @@ describe("unittests:: Reuse program structure:: General", () => { const program2 = updateProgram(program1, ["a.ts"], { target }, files => { files[0].text = files[0].text.updateProgram("var x = 100"); }); - assert.equal(program2.structureIsReused, ts.StructureIsReused.Completely); + assert.equal(program2.structureIsReused, StructureIsReused.Completely); const program1Diagnostics = program1.getSemanticDiagnostics(program1.getSourceFile("a.ts")); const program2Diagnostics = program2.getSemanticDiagnostics(program2.getSourceFile("a.ts")); assert.equal(program1Diagnostics.length, program2Diagnostics.length); @@ -243,7 +267,7 @@ describe("unittests:: Reuse program structure:: General", () => { const program2 = updateProgram(program1, ["a.ts"], { target }, files => { files[0].text = files[0].text.updateProgram("var x = 100"); }); - assert.equal(program2.structureIsReused, ts.StructureIsReused.Completely); + assert.equal(program2.structureIsReused, StructureIsReused.Completely); const program1Diagnostics = program1.getSemanticDiagnostics(program1.getSourceFile("a.ts")); const program2Diagnostics = program2.getSemanticDiagnostics(program2.getSourceFile("a.ts")); assert.equal(program1Diagnostics.length, program2Diagnostics.length); @@ -257,12 +281,12 @@ describe("unittests:: Reuse program structure:: General", () => { { name: "/node_modules/b/package.json", text: SourceText.New("", "", JSON.stringify({ name: "b", version: "1.2.3" })) }, ]; - const options: ts.CompilerOptions = { target, moduleResolution: ts.ModuleResolutionKind.NodeJs }; + const options: CompilerOptions = { target, moduleResolution: ModuleResolutionKind.NodeJs }; const program1 = newProgram(files, ["/a.ts"], options); const program2 = updateProgram(program1, ["/a.ts"], options, files => { files[2].text = files[2].text.updateProgram("export const b = 2;"); }); - assert.equal(program2.structureIsReused, ts.StructureIsReused.Completely); + assert.equal(program2.structureIsReused, StructureIsReused.Completely); const program1Diagnostics = program1.getSemanticDiagnostics(program1.getSourceFile("a.ts")); const program2Diagnostics = program2.getSemanticDiagnostics(program2.getSourceFile("a.ts")); assert.equal(program1Diagnostics.length, program2Diagnostics.length); @@ -276,19 +300,19 @@ describe("unittests:: Reuse program structure:: General", () => { `; files[0].text = files[0].text.updateReferences(newReferences); }); - assert.equal(program2.structureIsReused, ts.StructureIsReused.SafeModules); + assert.equal(program2.structureIsReused, StructureIsReused.SafeModules); }); it("fails if change affects type references", () => { const program1 = newProgram(files, ["a.ts"], { types: ["a"] }); - const program2 = updateProgram(program1, ["a.ts"], { types: ["b"] }, ts.noop); - assert.equal(program2.structureIsReused, ts.StructureIsReused.SafeModules); + const program2 = updateProgram(program1, ["a.ts"], { types: ["b"] }, noop); + assert.equal(program2.structureIsReused, StructureIsReused.SafeModules); }); it("succeeds if change doesn't affect type references", () => { const program1 = newProgram(files, ["a.ts"], { types: ["a"] }); - const program2 = updateProgram(program1, ["a.ts"], { types: ["a"] }, ts.noop); - assert.equal(program2.structureIsReused, ts.StructureIsReused.Completely); + const program2 = updateProgram(program1, ["a.ts"], { types: ["a"] }, noop); + assert.equal(program2.structureIsReused, StructureIsReused.Completely); }); it("fails if change affects imports", () => { @@ -296,7 +320,7 @@ describe("unittests:: Reuse program structure:: General", () => { const program2 = updateProgram(program1, ["a.ts"], { target }, files => { files[2].text = files[2].text.updateImportsAndExports("import x from 'b'"); }); - assert.equal(program2.structureIsReused, ts.StructureIsReused.SafeModules); + assert.equal(program2.structureIsReused, StructureIsReused.SafeModules); }); it("fails if change affects type directives", () => { @@ -308,50 +332,50 @@ describe("unittests:: Reuse program structure:: General", () => { /// `; files[0].text = files[0].text.updateReferences(newReferences); }); - assert.equal(program2.structureIsReused, ts.StructureIsReused.SafeModules); + assert.equal(program2.structureIsReused, StructureIsReused.SafeModules); }); it("fails if module kind changes", () => { - const program1 = newProgram(files, ["a.ts"], { target, module: ts.ModuleKind.CommonJS }); - const program2 = updateProgram(program1, ["a.ts"], { target, module: ts.ModuleKind.AMD }, ts.noop); - assert.equal(program2.structureIsReused, ts.StructureIsReused.Not); + const program1 = newProgram(files, ["a.ts"], { target, module: ModuleKind.CommonJS }); + const program2 = updateProgram(program1, ["a.ts"], { target, module: ModuleKind.AMD }, noop); + assert.equal(program2.structureIsReused, StructureIsReused.Not); }); it("succeeds if rootdir changes", () => { - const program1 = newProgram(files, ["a.ts"], { target, module: ts.ModuleKind.CommonJS, rootDir: "/a/b" }); - const program2 = updateProgram(program1, ["a.ts"], { target, module: ts.ModuleKind.CommonJS, rootDir: "/a/c" }, ts.noop); - assert.equal(program2.structureIsReused, ts.StructureIsReused.Completely); + const program1 = newProgram(files, ["a.ts"], { target, module: ModuleKind.CommonJS, rootDir: "/a/b" }); + const program2 = updateProgram(program1, ["a.ts"], { target, module: ModuleKind.CommonJS, rootDir: "/a/c" }, noop); + assert.equal(program2.structureIsReused, StructureIsReused.Completely); }); it("fails if config path changes", () => { - const program1 = newProgram(files, ["a.ts"], { target, module: ts.ModuleKind.CommonJS, configFilePath: "/a/b/tsconfig.json" }); - const program2 = updateProgram(program1, ["a.ts"], { target, module: ts.ModuleKind.CommonJS, configFilePath: "/a/c/tsconfig.json" }, ts.noop); - assert.equal(program2.structureIsReused, ts.StructureIsReused.Not); + const program1 = newProgram(files, ["a.ts"], { target, module: ModuleKind.CommonJS, configFilePath: "/a/b/tsconfig.json" }); + const program2 = updateProgram(program1, ["a.ts"], { target, module: ModuleKind.CommonJS, configFilePath: "/a/c/tsconfig.json" }, noop); + assert.equal(program2.structureIsReused, StructureIsReused.Not); }); it("succeeds if missing files remain missing", () => { - const options: ts.CompilerOptions = { target, noLib: true }; + const options: CompilerOptions = { target, noLib: true }; const program1 = newProgram(files, ["a.ts"], options); - assert.notDeepEqual(ts.emptyArray, program1.getMissingFilePaths()); + assert.notDeepEqual(emptyArray, program1.getMissingFilePaths()); - const program2 = updateProgram(program1, ["a.ts"], options, ts.noop); + const program2 = updateProgram(program1, ["a.ts"], options, noop); assert.deepEqual(program1.getMissingFilePaths(), program2.getMissingFilePaths()); - assert.equal(program2.structureIsReused, ts.StructureIsReused.Completely,); + assert.equal(program2.structureIsReused, StructureIsReused.Completely,); }); it("fails if missing file is created", () => { - const options: ts.CompilerOptions = { target, noLib: true }; + const options: CompilerOptions = { target, noLib: true }; const program1 = newProgram(files, ["a.ts"], options); - assert.notDeepEqual(ts.emptyArray, program1.getMissingFilePaths()); + assert.notDeepEqual(emptyArray, program1.getMissingFilePaths()); const newTexts: NamedSourceText[] = files.concat([{ name: "non-existing-file.ts", text: SourceText.New("", "", `var x = 1`) }]); - const program2 = updateProgram(program1, ["a.ts"], options, ts.noop, newTexts); + const program2 = updateProgram(program1, ["a.ts"], options, noop, newTexts); assert.lengthOf(program2.getMissingFilePaths(), 0); - assert.equal(program2.structureIsReused, ts.StructureIsReused.Not); + assert.equal(program2.structureIsReused, StructureIsReused.Not); }); it("resolution cache follows imports", () => { @@ -361,26 +385,26 @@ describe("unittests:: Reuse program structure:: General", () => { { name: "a.ts", text: SourceText.New("", "import {_} from 'b'", "var x = 1") }, { name: "b.ts", text: SourceText.New("", "", "var y = 2") }, ]; - const options: ts.CompilerOptions = { target }; + const options: CompilerOptions = { target }; const program1 = newProgram(files, ["a.ts"], options); - checkResolvedModulesCache(program1, "a.ts", new ts.Map(ts.getEntries({ b: ts.createResolvedModule("b.ts") }))); + checkResolvedModulesCache(program1, "a.ts", new Map(getEntries({ b: createResolvedModule("b.ts") }))); checkResolvedModulesCache(program1, "b.ts", /*expectedContent*/ undefined); const program2 = updateProgram(program1, ["a.ts"], options, files => { files[0].text = files[0].text.updateProgram("var x = 2"); }); - assert.equal(program2.structureIsReused, ts.StructureIsReused.Completely); + assert.equal(program2.structureIsReused, StructureIsReused.Completely); // content of resolution cache should not change - checkResolvedModulesCache(program1, "a.ts", new ts.Map(ts.getEntries({ b: ts.createResolvedModule("b.ts") }))); + checkResolvedModulesCache(program1, "a.ts", new Map(getEntries({ b: createResolvedModule("b.ts") }))); checkResolvedModulesCache(program1, "b.ts", /*expectedContent*/ undefined); // imports has changed - program is not reused const program3 = updateProgram(program2, ["a.ts"], options, files => { files[0].text = files[0].text.updateImportsAndExports(""); }); - assert.equal(program3.structureIsReused, ts.StructureIsReused.SafeModules); + assert.equal(program3.structureIsReused, StructureIsReused.SafeModules); checkResolvedModulesCache(program3, "a.ts", /*expectedContent*/ undefined); const program4 = updateProgram(program3, ["a.ts"], options, files => { @@ -389,8 +413,8 @@ describe("unittests:: Reuse program structure:: General", () => { `; files[0].text = files[0].text.updateImportsAndExports(newImports); }); - assert.equal(program4.structureIsReused, ts.StructureIsReused.SafeModules); - checkResolvedModulesCache(program4, "a.ts", new ts.Map(ts.getEntries({ b: ts.createResolvedModule("b.ts"), c: undefined }))); + assert.equal(program4.structureIsReused, StructureIsReused.SafeModules); + checkResolvedModulesCache(program4, "a.ts", new Map(getEntries({ b: createResolvedModule("b.ts"), c: undefined }))); }); it("set the resolvedImports after re-using an ambient external module declaration", () => { @@ -398,7 +422,7 @@ describe("unittests:: Reuse program structure:: General", () => { { name: "/a.ts", text: SourceText.New("", "", 'import * as a from "a";') }, { name: "/types/zzz/index.d.ts", text: SourceText.New("", "", 'declare module "a" { }') }, ]; - const options: ts.CompilerOptions = { target, typeRoots: ["/types"] }; + const options: CompilerOptions = { target, typeRoots: ["/types"] }; const program1 = newProgram(files, ["/a.ts"], options); const program2 = updateProgram(program1, ["/a.ts"], options, files => { files[0].text = files[0].text.updateProgram('import * as aa from "a";'); @@ -413,11 +437,11 @@ describe("unittests:: Reuse program structure:: General", () => { { name: "/types/zzz/index.d.ts", text: SourceText.New("", "", 'declare module "a" { }') }, ]; const host = createTestCompilerHost(files, target); - const options: ts.CompilerOptions = { target, typeRoots: ["/types"] }; - const program1 = ts.createProgram(["/a.ts"], options, host); + const options: CompilerOptions = { target, typeRoots: ["/types"] }; + const program1 = createProgram(["/a.ts"], options, host); let sourceFile = program1.getSourceFile("/a.ts")!; assert.isDefined(sourceFile, "'/a.ts' is included in the program"); - sourceFile = ts.updateSourceFile(sourceFile, "'use strict';" + sourceFile.text, { newLength: "'use strict';".length, span: { start: 0, length: 0 } }); + sourceFile = updateSourceFile(sourceFile, "'use strict';" + sourceFile.text, { newLength: "'use strict';".length, span: { start: 0, length: 0 } }); assert.strictEqual(sourceFile.statements[2].getSourceFile(), sourceFile, "parent pointers are updated"); const updateHost: TestCompilerHost = { ...host, @@ -425,7 +449,7 @@ describe("unittests:: Reuse program structure:: General", () => { return fileName === sourceFile.fileName ? sourceFile : program1.getSourceFile(fileName); } }; - const program2 = ts.createProgram(["/a.ts"], options, updateHost, program1); + const program2 = createProgram(["/a.ts"], options, updateHost, program1); assert.isDefined(program2.getSourceFile("/a.ts")!.resolvedModules!.get("a", /*mode*/ undefined), "'a' is not an unresolved module after re-use"); assert.strictEqual(sourceFile.statements[2].getSourceFile(), sourceFile, "parent pointers are not altered"); }); @@ -435,19 +459,19 @@ describe("unittests:: Reuse program structure:: General", () => { { name: "/a.ts", text: SourceText.New("/// ", "", "var x = $") }, { name: "/types/typedefs/index.d.ts", text: SourceText.New("", "", "declare var $: number") }, ]; - const options: ts.CompilerOptions = { target, typeRoots: ["/types"] }; + const options: CompilerOptions = { target, typeRoots: ["/types"] }; const program1 = newProgram(files, ["/a.ts"], options); - checkResolvedTypeDirectivesCache(program1, "/a.ts", new ts.Map(ts.getEntries({ typedefs: { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } }))); + checkResolvedTypeDirectivesCache(program1, "/a.ts", new Map(getEntries({ typedefs: { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } }))); checkResolvedTypeDirectivesCache(program1, "/types/typedefs/index.d.ts", /*expectedContent*/ undefined); const program2 = updateProgram(program1, ["/a.ts"], options, files => { files[0].text = files[0].text.updateProgram("var x = 2"); }); - assert.equal(program2.structureIsReused, ts.StructureIsReused.Completely); + assert.equal(program2.structureIsReused, StructureIsReused.Completely); // content of resolution cache should not change - checkResolvedTypeDirectivesCache(program1, "/a.ts", new ts.Map(ts.getEntries({ typedefs: { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } }))); + checkResolvedTypeDirectivesCache(program1, "/a.ts", new Map(getEntries({ typedefs: { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } }))); checkResolvedTypeDirectivesCache(program1, "/types/typedefs/index.d.ts", /*expectedContent*/ undefined); // type reference directives has changed - program is not reused @@ -455,7 +479,7 @@ describe("unittests:: Reuse program structure:: General", () => { files[0].text = files[0].text.updateReferences(""); }); - assert.equal(program3.structureIsReused, ts.StructureIsReused.SafeModules); + assert.equal(program3.structureIsReused, StructureIsReused.SafeModules); checkResolvedTypeDirectivesCache(program3, "/a.ts", /*expectedContent*/ undefined); const program4 = updateProgram(program3, ["/a.ts"], options, files => { @@ -464,15 +488,15 @@ describe("unittests:: Reuse program structure:: General", () => { `; files[0].text = files[0].text.updateReferences(newReferences); }); - assert.equal(program4.structureIsReused, ts.StructureIsReused.SafeModules); - checkResolvedTypeDirectivesCache(program1, "/a.ts", new ts.Map(ts.getEntries({ typedefs: { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } }))); + assert.equal(program4.structureIsReused, StructureIsReused.SafeModules); + checkResolvedTypeDirectivesCache(program1, "/a.ts", new Map(getEntries({ typedefs: { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } }))); }); it("fetches imports after npm install", () => { const file1Ts = { name: "file1.ts", text: SourceText.New("", `import * as a from "a";`, "const myX: number = a.x;") }; const file2Ts = { name: "file2.ts", text: SourceText.New("", "", "") }; const indexDTS = { name: "node_modules/a/index.d.ts", text: SourceText.New("", "export declare let x: number;", "") }; - const options: ts.CompilerOptions = { target: ts.ScriptTarget.ES2015, traceResolution: true, moduleResolution: ts.ModuleResolutionKind.NodeJs }; + const options: CompilerOptions = { target: ScriptTarget.ES2015, traceResolution: true, moduleResolution: ModuleResolutionKind.NodeJs }; const rootFiles = [file1Ts, file2Ts]; const filesAfterNpmInstall = [file1Ts, file2Ts, indexDTS]; @@ -537,7 +561,7 @@ describe("unittests:: Reuse program structure:: General", () => { { name: "/a/b/app.ts", text: SourceText.New("", "import * as fs from 'fs'", "") }, { name: "/a/b/node.d.ts", text: SourceText.New("", "", "declare module 'fs' {}") } ]; - const options = { target: ts.ScriptTarget.ES2015, traceResolution: true }; + const options = { target: ScriptTarget.ES2015, traceResolution: true }; const program = newProgram(files, files.map(f => f.name), options); assert.deepEqual(program.host.getTrace(), [ @@ -638,7 +662,7 @@ describe("unittests:: Reuse program structure:: General", () => { }, ]; - const options: ts.CompilerOptions = { target: ts.ScriptTarget.ES2015, traceResolution: true, moduleResolution: ts.ModuleResolutionKind.Classic }; + const options: CompilerOptions = { target: ScriptTarget.ES2015, traceResolution: true, moduleResolution: ModuleResolutionKind.Classic }; const program1 = newProgram(files, files.map(f => f.name), options); let expectedErrors = 0; { @@ -819,7 +843,7 @@ describe("unittests:: Reuse program structure:: General", () => { const bxIndex = "/node_modules/b/node_modules/x/index.d.ts"; const bxPackage = "/node_modules/b/node_modules/x/package.json"; const root = "/a.ts"; - const compilerOptions = { target, moduleResolution: ts.ModuleResolutionKind.NodeJs }; + const compilerOptions = { target, moduleResolution: ModuleResolutionKind.NodeJs }; function createRedirectProgram(useGetSourceFileByPath: boolean, options?: { bText: string, bVersion: string }): ProgramWithSourceTexts { const files: NamedSourceText[] = [ @@ -867,7 +891,7 @@ describe("unittests:: Reuse program structure:: General", () => { const program2 = updateRedirectProgram(program1, files => { updateProgramText(files, root, "const x = 1;"); }, useGetSourceFileByPath); - assert.equal(program2.structureIsReused, ts.StructureIsReused.Completely); + assert.equal(program2.structureIsReused, StructureIsReused.Completely); assert.lengthOf(program2.getSemanticDiagnostics(), 0); }); @@ -879,7 +903,7 @@ describe("unittests:: Reuse program structure:: General", () => { updateProgramText(files, axIndex, "export default class X { private x: number; private y: number; }"); updateProgramText(files, axPackage, JSON.stringify('{ name: "x", version: "1.2.4" }')); }, useGetSourceFileByPath); - assert.equal(program2.structureIsReused, ts.StructureIsReused.Not); + assert.equal(program2.structureIsReused, StructureIsReused.Not); assert.lengthOf(program2.getSemanticDiagnostics(), 1); }); @@ -890,7 +914,7 @@ describe("unittests:: Reuse program structure:: General", () => { updateProgramText(files, bxIndex, "export default class X { private x: number; private y: number; }"); updateProgramText(files, bxPackage, JSON.stringify({ name: "x", version: "1.2.4" })); }, useGetSourceFileByPath); - assert.equal(program2.structureIsReused, ts.StructureIsReused.Not); + assert.equal(program2.structureIsReused, StructureIsReused.Not); assert.lengthOf(program2.getSemanticDiagnostics(), 1); }); @@ -901,7 +925,7 @@ describe("unittests:: Reuse program structure:: General", () => { updateProgramText(files, bxIndex, "export default class X { private x: number; }"); updateProgramText(files, bxPackage, JSON.stringify({ name: "x", version: "1.2.3" })); }, useGetSourceFileByPath); - assert.equal(program2.structureIsReused, ts.StructureIsReused.Not); + assert.equal(program2.structureIsReused, StructureIsReused.Not); assert.deepEqual(program2.getSemanticDiagnostics(), []); }); } @@ -917,48 +941,45 @@ describe("unittests:: Reuse program structure:: General", () => { describe("unittests:: Reuse program structure:: host is optional", () => { it("should work if host is not provided", () => { - ts.createProgram([], {}); + createProgram([], {}); }); }); -type File = ts.TestFSWithWatch.File; -import createTestSystem = ts.TestFSWithWatch.createWatchedSystem; -import libFile = ts.TestFSWithWatch.libFile; - +type File = TestFSWithWatch.File; describe("unittests:: Reuse program structure:: isProgramUptoDate", () => { function getWhetherProgramIsUptoDate( - program: ts.Program, + program: Program, newRootFileNames: string[], - newOptions: ts.CompilerOptions + newOptions: CompilerOptions ) { - return ts.isProgramUptoDate( + return isProgramUptoDate( program, newRootFileNames, newOptions, - path => program.getSourceFileByPath(path)!.version, /*fileExists*/ ts.returnFalse, - /*hasInvalidatedResolution*/ ts.returnFalse, + path => program.getSourceFileByPath(path)!.version, /*fileExists*/ returnFalse, + /*hasInvalidatedResolution*/ returnFalse, /*hasChangedAutomaticTypeDirectiveNames*/ undefined, - /*getParsedCommandLine*/ ts.returnUndefined, + /*getParsedCommandLine*/ returnUndefined, /*projectReferences*/ undefined ); } - function duplicate(options: ts.CompilerOptions): ts.CompilerOptions; + function duplicate(options: CompilerOptions): CompilerOptions; function duplicate(fileNames: string[]): string[]; - function duplicate(filesOrOptions: ts.CompilerOptions | string[]) { + function duplicate(filesOrOptions: CompilerOptions | string[]) { return JSON.parse(JSON.stringify(filesOrOptions)); } describe("should return true when there is no change in compiler options and", () => { function verifyProgramIsUptoDate( - program: ts.Program, + program: Program, newRootFileNames: string[], - newOptions: ts.CompilerOptions + newOptions: CompilerOptions ) { const actual = getWhetherProgramIsUptoDate(program, newRootFileNames, newOptions); assert.isTrue(actual); } - function verifyProgramWithoutConfigFile(system: ts.System, rootFiles: string[], options: ts.CompilerOptions) { - const program = ts.createWatchProgram(ts.createWatchCompilerHostOfFilesAndCompilerOptions({ + function verifyProgramWithoutConfigFile(system: System, rootFiles: string[], options: CompilerOptions) { + const program = createWatchProgram(createWatchCompilerHostOfFilesAndCompilerOptions({ rootFiles, options, watchOptions: undefined, @@ -967,16 +988,16 @@ describe("unittests:: Reuse program structure:: isProgramUptoDate", () => { verifyProgramIsUptoDate(program, duplicate(rootFiles), duplicate(options)); } - function verifyProgramWithConfigFile(system: ts.System, configFileName: string) { - const program = ts.createWatchProgram(ts.createWatchCompilerHostOfConfigFile({ + function verifyProgramWithConfigFile(system: System, configFileName: string) { + const program = createWatchProgram(createWatchCompilerHostOfConfigFile({ configFileName, system })).getCurrentProgram().getProgram(); - const { fileNames, options } = ts.parseConfigFileWithSystem(configFileName, {}, /*extendedConfigCache*/ undefined, /*watchOptionsToExtend*/ undefined, system, ts.notImplemented)!; // TODO: GH#18217 + const { fileNames, options } = parseConfigFileWithSystem(configFileName, {}, /*extendedConfigCache*/ undefined, /*watchOptionsToExtend*/ undefined, system, notImplemented)!; // TODO: GH#18217 verifyProgramIsUptoDate(program, fileNames, options); } - function verifyProgram(files: File[], rootFiles: string[], options: ts.CompilerOptions, configFile: string) { + function verifyProgram(files: File[], rootFiles: string[], options: CompilerOptions, configFile: string) { const system = createTestSystem(files); verifyProgramWithoutConfigFile(system, rootFiles, options); verifyProgramWithConfigFile(system, configFile); @@ -999,7 +1020,7 @@ describe("unittests:: Reuse program structure:: isProgramUptoDate", () => { }); it("has lib specified in the options", () => { - const compilerOptions: ts.CompilerOptions = { lib: ["es5", "es2015.promise"] }; + const compilerOptions: CompilerOptions = { lib: ["es5", "es2015.promise"] }; const app: File = { path: "/src/app.ts", content: "var x: Promise;" @@ -1021,7 +1042,7 @@ describe("unittests:: Reuse program structure:: isProgramUptoDate", () => { }); it("has paths specified in the options", () => { - const compilerOptions: ts.CompilerOptions = { + const compilerOptions: CompilerOptions = { baseUrl: ".", paths: { "*": [ @@ -1059,7 +1080,7 @@ describe("unittests:: Reuse program structure:: isProgramUptoDate", () => { }); it("has include paths specified in tsconfig file", () => { - const compilerOptions: ts.CompilerOptions = { + const compilerOptions: CompilerOptions = { baseUrl: ".", paths: { "*": [ @@ -1110,7 +1131,7 @@ describe("unittests:: Reuse program structure:: isProgramUptoDate", () => { const rootFiles = [module1.path, module2.path, module3.path]; const system = createTestSystem([module1, module2, module3]); const options = {}; - const program = ts.createWatchProgram(ts.createWatchCompilerHostOfFilesAndCompilerOptions({ + const program = createWatchProgram(createWatchCompilerHostOfFilesAndCompilerOptions({ rootFiles, options, watchOptions: undefined, @@ -1122,9 +1143,9 @@ describe("unittests:: Reuse program structure:: isProgramUptoDate", () => { }); describe("should return false when there is no change in compiler options but", () => { function verifyProgramIsNotUptoDate( - program: ts.Program, + program: Program, newRootFileNames: string[], - newOptions: ts.CompilerOptions + newOptions: CompilerOptions ) { const actual = getWhetherProgramIsUptoDate(program, newRootFileNames, newOptions); assert.isFalse(actual); @@ -1146,7 +1167,7 @@ describe("unittests:: Reuse program structure:: isProgramUptoDate", () => { const newRootFiles = [module1.path, module2.path, module3.path]; const system = createTestSystem([module1, module2, module3]); const options = {}; - const program = ts.createWatchProgram(ts.createWatchCompilerHostOfFilesAndCompilerOptions({ + const program = createWatchProgram(createWatchCompilerHostOfFilesAndCompilerOptions({ rootFiles, options, watchOptions: undefined, @@ -1171,7 +1192,7 @@ describe("unittests:: Reuse program structure:: isProgramUptoDate", () => { const newRootFiles = [module2.path, module3.path]; const system = createTestSystem([module1, module2, module3]); const options = {}; - const program = ts.createWatchProgram(ts.createWatchCompilerHostOfFilesAndCompilerOptions({ + const program = createWatchProgram(createWatchCompilerHostOfFilesAndCompilerOptions({ rootFiles, options, watchOptions: undefined, diff --git a/src/testRunner/unittests/semver.ts b/src/testRunner/unittests/semver.ts index eb81cfd4433f5..23fab5072396e 100644 --- a/src/testRunner/unittests/semver.ts +++ b/src/testRunner/unittests/semver.ts @@ -1,12 +1,13 @@ -import * as ts from "../_namespaces/ts"; -import * as Utils from "../_namespaces/Utils"; +import { emptyArray } from "../../compiler/core"; +import { Comparison } from "../../compiler/corePublic"; +import { Version, VersionRange } from "../../compiler/semver"; +import { theory } from "../../harness/util"; -import theory = Utils.theory; describe("unittests:: semver", () => { describe("VersionRange", () => { function assertVersionRange(version: string, good: string[], bad: string[]): () => void { return () => { - const range = ts.VersionRange.tryParse(version)!; + const range = VersionRange.tryParse(version)!; assert(range); for (const g of good) { assert.isTrue(range.test(g), g); @@ -27,104 +28,104 @@ describe("unittests:: semver", () => { it(">= works with prerelease", assertVersionRange(">=3.8.0-0", ["3.8", "3.9", "4.0"], ["3.6", "3.7"])); }); describe("Version", () => { - function assertVersion(version: ts.Version, [major, minor, patch, prerelease, build]: [number, number, number, string[]?, string[]?]) { + function assertVersion(version: Version, [major, minor, patch, prerelease, build]: [number, number, number, string[]?, string[]?]) { assert.strictEqual(version.major, major); assert.strictEqual(version.minor, minor); assert.strictEqual(version.patch, patch); - assert.deepEqual(version.prerelease, prerelease || ts.emptyArray); - assert.deepEqual(version.build, build || ts.emptyArray); + assert.deepEqual(version.prerelease, prerelease || emptyArray); + assert.deepEqual(version.build, build || emptyArray); } describe("new", () => { it("text", () => { - assertVersion(new ts.Version("1.2.3-pre.4+build.5"), [1, 2, 3, ["pre", "4"], ["build", "5"]]); + assertVersion(new Version("1.2.3-pre.4+build.5"), [1, 2, 3, ["pre", "4"], ["build", "5"]]); }); it("parts", () => { - assertVersion(new ts.Version(1, 2, 3, "pre.4", "build.5"), [1, 2, 3, ["pre", "4"], ["build", "5"]]); - assertVersion(new ts.Version(1, 2, 3), [1, 2, 3]); - assertVersion(new ts.Version(1, 2), [1, 2, 0]); - assertVersion(new ts.Version(1), [1, 0, 0]); + assertVersion(new Version(1, 2, 3, "pre.4", "build.5"), [1, 2, 3, ["pre", "4"], ["build", "5"]]); + assertVersion(new Version(1, 2, 3), [1, 2, 3]); + assertVersion(new Version(1, 2), [1, 2, 0]); + assertVersion(new Version(1), [1, 0, 0]); }); }); it("toString", () => { - assert.strictEqual(new ts.Version(1, 2, 3, "pre.4", "build.5").toString(), "1.2.3-pre.4+build.5"); - assert.strictEqual(new ts.Version(1, 2, 3, "pre.4").toString(), "1.2.3-pre.4"); - assert.strictEqual(new ts.Version(1, 2, 3, /*prerelease*/ undefined, "build.5").toString(), "1.2.3+build.5"); - assert.strictEqual(new ts.Version(1, 2, 3).toString(), "1.2.3"); - assert.strictEqual(new ts.Version(1, 2).toString(), "1.2.0"); - assert.strictEqual(new ts.Version(1).toString(), "1.0.0"); + assert.strictEqual(new Version(1, 2, 3, "pre.4", "build.5").toString(), "1.2.3-pre.4+build.5"); + assert.strictEqual(new Version(1, 2, 3, "pre.4").toString(), "1.2.3-pre.4"); + assert.strictEqual(new Version(1, 2, 3, /*prerelease*/ undefined, "build.5").toString(), "1.2.3+build.5"); + assert.strictEqual(new Version(1, 2, 3).toString(), "1.2.3"); + assert.strictEqual(new Version(1, 2).toString(), "1.2.0"); + assert.strictEqual(new Version(1).toString(), "1.0.0"); }); it("compareTo", () => { // https://semver.org/#spec-item-11 // > Precedence is determined by the first difference when comparing each of these // > identifiers from left to right as follows: Major, minor, and patch versions are // > always compared numerically. - assert.strictEqual(new ts.Version("1.0.0").compareTo(new ts.Version("2.0.0")), ts.Comparison.LessThan); - assert.strictEqual(new ts.Version("1.0.0").compareTo(new ts.Version("1.1.0")), ts.Comparison.LessThan); - assert.strictEqual(new ts.Version("1.0.0").compareTo(new ts.Version("1.0.1")), ts.Comparison.LessThan); - assert.strictEqual(new ts.Version("2.0.0").compareTo(new ts.Version("1.0.0")), ts.Comparison.GreaterThan); - assert.strictEqual(new ts.Version("1.1.0").compareTo(new ts.Version("1.0.0")), ts.Comparison.GreaterThan); - assert.strictEqual(new ts.Version("1.0.1").compareTo(new ts.Version("1.0.0")), ts.Comparison.GreaterThan); - assert.strictEqual(new ts.Version("1.0.0").compareTo(new ts.Version("1.0.0")), ts.Comparison.EqualTo); + assert.strictEqual(new Version("1.0.0").compareTo(new Version("2.0.0")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0").compareTo(new Version("1.1.0")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0").compareTo(new Version("1.0.1")), Comparison.LessThan); + assert.strictEqual(new Version("2.0.0").compareTo(new Version("1.0.0")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.1.0").compareTo(new Version("1.0.0")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.1").compareTo(new Version("1.0.0")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0").compareTo(new Version("1.0.0")), Comparison.EqualTo); // https://semver.org/#spec-item-11 // > When major, minor, and patch are equal, a pre-release version has lower // > precedence than a normal version. - assert.strictEqual(new ts.Version("1.0.0").compareTo(new ts.Version("1.0.0-pre")), ts.Comparison.GreaterThan); - assert.strictEqual(new ts.Version("1.0.1-pre").compareTo(new ts.Version("1.0.0")), ts.Comparison.GreaterThan); - assert.strictEqual(new ts.Version("1.0.0-pre").compareTo(new ts.Version("1.0.0")), ts.Comparison.LessThan); + assert.strictEqual(new Version("1.0.0").compareTo(new Version("1.0.0-pre")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.1-pre").compareTo(new Version("1.0.0")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0-pre").compareTo(new Version("1.0.0")), Comparison.LessThan); // https://semver.org/#spec-item-11 // > identifiers consisting of only digits are compared numerically - assert.strictEqual(new ts.Version("1.0.0-0").compareTo(new ts.Version("1.0.0-1")), ts.Comparison.LessThan); - assert.strictEqual(new ts.Version("1.0.0-1").compareTo(new ts.Version("1.0.0-0")), ts.Comparison.GreaterThan); - assert.strictEqual(new ts.Version("1.0.0-2").compareTo(new ts.Version("1.0.0-10")), ts.Comparison.LessThan); - assert.strictEqual(new ts.Version("1.0.0-10").compareTo(new ts.Version("1.0.0-2")), ts.Comparison.GreaterThan); - assert.strictEqual(new ts.Version("1.0.0-0").compareTo(new ts.Version("1.0.0-0")), ts.Comparison.EqualTo); + assert.strictEqual(new Version("1.0.0-0").compareTo(new Version("1.0.0-1")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0-1").compareTo(new Version("1.0.0-0")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0-2").compareTo(new Version("1.0.0-10")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0-10").compareTo(new Version("1.0.0-2")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0-0").compareTo(new Version("1.0.0-0")), Comparison.EqualTo); // https://semver.org/#spec-item-11 // > identifiers with letters or hyphens are compared lexically in ASCII sort order. - assert.strictEqual(new ts.Version("1.0.0-a").compareTo(new ts.Version("1.0.0-b")), ts.Comparison.LessThan); - assert.strictEqual(new ts.Version("1.0.0-a-2").compareTo(new ts.Version("1.0.0-a-10")), ts.Comparison.GreaterThan); - assert.strictEqual(new ts.Version("1.0.0-b").compareTo(new ts.Version("1.0.0-a")), ts.Comparison.GreaterThan); - assert.strictEqual(new ts.Version("1.0.0-a").compareTo(new ts.Version("1.0.0-a")), ts.Comparison.EqualTo); - assert.strictEqual(new ts.Version("1.0.0-A").compareTo(new ts.Version("1.0.0-a")), ts.Comparison.LessThan); + assert.strictEqual(new Version("1.0.0-a").compareTo(new Version("1.0.0-b")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0-a-2").compareTo(new Version("1.0.0-a-10")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0-b").compareTo(new Version("1.0.0-a")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0-a").compareTo(new Version("1.0.0-a")), Comparison.EqualTo); + assert.strictEqual(new Version("1.0.0-A").compareTo(new Version("1.0.0-a")), Comparison.LessThan); // https://semver.org/#spec-item-11 // > Numeric identifiers always have lower precedence than non-numeric identifiers. - assert.strictEqual(new ts.Version("1.0.0-0").compareTo(new ts.Version("1.0.0-alpha")), ts.Comparison.LessThan); - assert.strictEqual(new ts.Version("1.0.0-alpha").compareTo(new ts.Version("1.0.0-0")), ts.Comparison.GreaterThan); - assert.strictEqual(new ts.Version("1.0.0-0").compareTo(new ts.Version("1.0.0-0")), ts.Comparison.EqualTo); - assert.strictEqual(new ts.Version("1.0.0-alpha").compareTo(new ts.Version("1.0.0-alpha")), ts.Comparison.EqualTo); + assert.strictEqual(new Version("1.0.0-0").compareTo(new Version("1.0.0-alpha")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0-alpha").compareTo(new Version("1.0.0-0")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0-0").compareTo(new Version("1.0.0-0")), Comparison.EqualTo); + assert.strictEqual(new Version("1.0.0-alpha").compareTo(new Version("1.0.0-alpha")), Comparison.EqualTo); // 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. - assert.strictEqual(new ts.Version("1.0.0-alpha").compareTo(new ts.Version("1.0.0-alpha.0")), ts.Comparison.LessThan); - assert.strictEqual(new ts.Version("1.0.0-alpha.0").compareTo(new ts.Version("1.0.0-alpha")), ts.Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0-alpha").compareTo(new Version("1.0.0-alpha.0")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0-alpha.0").compareTo(new Version("1.0.0-alpha")), Comparison.GreaterThan); // https://semver.org/#spec-item-11 // > Precedence for two pre-release versions with the same major, minor, and patch version // > MUST be determined by comparing each dot separated identifier from left to right until // > a difference is found [...] - assert.strictEqual(new ts.Version("1.0.0-a.0.b.1").compareTo(new ts.Version("1.0.0-a.0.b.2")), ts.Comparison.LessThan); - assert.strictEqual(new ts.Version("1.0.0-a.0.b.1").compareTo(new ts.Version("1.0.0-b.0.a.1")), ts.Comparison.LessThan); - assert.strictEqual(new ts.Version("1.0.0-a.0.b.2").compareTo(new ts.Version("1.0.0-a.0.b.1")), ts.Comparison.GreaterThan); - assert.strictEqual(new ts.Version("1.0.0-b.0.a.1").compareTo(new ts.Version("1.0.0-a.0.b.1")), ts.Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0-a.0.b.1").compareTo(new Version("1.0.0-a.0.b.2")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0-a.0.b.1").compareTo(new Version("1.0.0-b.0.a.1")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0-a.0.b.2").compareTo(new Version("1.0.0-a.0.b.1")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0-b.0.a.1").compareTo(new Version("1.0.0-a.0.b.1")), Comparison.GreaterThan); // https://semver.org/#spec-item-11 // > Build metadata does not figure into precedence - assert.strictEqual(new ts.Version("1.0.0+build").compareTo(new ts.Version("1.0.0")), ts.Comparison.EqualTo); + assert.strictEqual(new Version("1.0.0+build").compareTo(new Version("1.0.0")), Comparison.EqualTo); }); it("increment", () => { - assertVersion(new ts.Version(1, 2, 3, "pre.4", "build.5").increment("major"), [2, 0, 0]); - assertVersion(new ts.Version(1, 2, 3, "pre.4", "build.5").increment("minor"), [1, 3, 0]); - assertVersion(new ts.Version(1, 2, 3, "pre.4", "build.5").increment("patch"), [1, 2, 4]); + assertVersion(new Version(1, 2, 3, "pre.4", "build.5").increment("major"), [2, 0, 0]); + assertVersion(new Version(1, 2, 3, "pre.4", "build.5").increment("minor"), [1, 3, 0]); + assertVersion(new Version(1, 2, 3, "pre.4", "build.5").increment("patch"), [1, 2, 4]); }); }); describe("VersionRange", () => { function assertRange(rangeText: string, versionText: string, inRange = true) { - const range = new ts.VersionRange(rangeText); - const version = new ts.Version(versionText); + const range = new VersionRange(rangeText); + const version = new Version(versionText); assert.strictEqual(range.test(version), inRange, `Expected version '${version}' ${inRange ? `to be` : `to not be`} in range '${rangeText}' (${range})`); } theory("comparators", assertRange, [ diff --git a/src/testRunner/unittests/services/cancellableLanguageServiceOperations.ts b/src/testRunner/unittests/services/cancellableLanguageServiceOperations.ts index 7f075c49786fb..aa90bcaa18d7d 100644 --- a/src/testRunner/unittests/services/cancellableLanguageServiceOperations.ts +++ b/src/testRunner/unittests/services/cancellableLanguageServiceOperations.ts @@ -1,5 +1,8 @@ -import * as Harness from "../../_namespaces/Harness"; -import * as ts from "../../_namespaces/ts"; +import { CompilerOptions, OperationCanceledException } from "../../../compiler/types"; +import { NativeLanguageServiceAdapter } from "../../../harness/harnessLanguageService"; +import { + emptyOptions, FormatCodeSettings, HostCancellationToken, IndentStyle, LanguageService, +} from "../../../services/types"; describe("unittests:: services:: cancellableLanguageServiceOperations", () => { const file = ` @@ -10,7 +13,7 @@ describe("unittests:: services:: cancellableLanguageServiceOperations", () => { `; it("can cancel signature help mid-request", () => { verifyOperationCancelledAfter(file, 4, service => // Two calls are top-level in services, one is the root type, and the second should be for the parameter type - service.getSignatureHelpItems("file.ts", file.lastIndexOf("f"), ts.emptyOptions)!, r => assert.exists(r.items[0]) + service.getSignatureHelpItems("file.ts", file.lastIndexOf("f"), emptyOptions)!, r => assert.exists(r.items[0]) ); }); @@ -27,12 +30,12 @@ describe("unittests:: services:: cancellableLanguageServiceOperations", () => { }); it("can cancel completion entry details mid-request", () => { - const options: ts.FormatCodeSettings = { + const options: FormatCodeSettings = { indentSize: 4, tabSize: 4, newLineCharacter: "\n", convertTabsToSpaces: true, - indentStyle: ts.IndentStyle.Smart, + indentStyle: IndentStyle.Smart, insertSpaceAfterConstructor: false, insertSpaceAfterCommaDelimiter: true, insertSpaceAfterSemicolonInForStatements: true, @@ -60,9 +63,9 @@ describe("unittests:: services:: cancellableLanguageServiceOperations", () => { }); }); -function verifyOperationCancelledAfter(content: string, cancelAfter: number, operation: (service: ts.LanguageService) => T, validator: (arg: T) => void, fileName?: string, fileContent?: string, options?: ts.CompilerOptions) { +function verifyOperationCancelledAfter(content: string, cancelAfter: number, operation: (service: LanguageService) => T, validator: (arg: T) => void, fileName?: string, fileContent?: string, options?: CompilerOptions) { let checks = 0; - const token: ts.HostCancellationToken = { + const token: HostCancellationToken = { isCancellationRequested() { checks++; const result = checks >= cancelAfter; @@ -72,7 +75,7 @@ function verifyOperationCancelledAfter(content: string, cancelAfter: number, return result; } }; - const adapter = new Harness.LanguageService.NativeLanguageServiceAdapter(token, options); + const adapter = new NativeLanguageServiceAdapter(token, options); const host = adapter.getHost(); host.addScript(fileName || "file.ts", fileContent || content, /*isRootFile*/ true); const service = adapter.getLanguageService(); @@ -92,7 +95,7 @@ function assertCancelled(cb: () => void) { caught = e; } assert.exists(caught, "Expected operation to be cancelled, but was not"); - assert.instanceOf(caught, ts.OperationCanceledException); + assert.instanceOf(caught, OperationCanceledException); } export { }; diff --git a/src/testRunner/unittests/services/colorization.ts b/src/testRunner/unittests/services/colorization.ts index a0ee864f16336..151ea5845ca80 100644 --- a/src/testRunner/unittests/services/colorization.ts +++ b/src/testRunner/unittests/services/colorization.ts @@ -1,21 +1,22 @@ -import * as Harness from "../../_namespaces/Harness"; -import * as ts from "../../_namespaces/ts"; +import { last } from "../../../compiler/core"; +import { ShimLanguageServiceAdapter } from "../../../harness/harnessLanguageService"; +import { ClassificationResult, EndOfLineState, TokenClass } from "../../../services/types"; // lots of tests use quoted code /* eslint-disable no-template-curly-in-string */ interface ClassificationEntry { value: any; - classification: ts.TokenClass; + classification: TokenClass; position?: number; } describe("unittests:: services:: Colorization", () => { // Use the shim adapter to ensure test coverage of the shim layer for the classifier - const languageServiceAdapter = new Harness.LanguageService.ShimLanguageServiceAdapter(/*preprocessToResolve*/ false); + const languageServiceAdapter = new ShimLanguageServiceAdapter(/*preprocessToResolve*/ false); const classifier = languageServiceAdapter.getClassifier(); - function getEntryAtPosition(result: ts.ClassificationResult, position: number) { + function getEntryAtPosition(result: ClassificationResult, position: number) { let entryPosition = 0; for (const entry of result.entries) { if (entryPosition === position) { @@ -27,38 +28,38 @@ describe("unittests:: services:: Colorization", () => { } function punctuation(text: string, position?: number) { - return createClassification(text, ts.TokenClass.Punctuation, position); + return createClassification(text, TokenClass.Punctuation, position); } function keyword(text: string, position?: number) { - return createClassification(text, ts.TokenClass.Keyword, position); + return createClassification(text, TokenClass.Keyword, position); } function operator(text: string, position?: number) { - return createClassification(text, ts.TokenClass.Operator, position); + return createClassification(text, TokenClass.Operator, position); } function comment(text: string, position?: number) { - return createClassification(text, ts.TokenClass.Comment, position); + return createClassification(text, TokenClass.Comment, position); } function whitespace(text: string, position?: number) { - return createClassification(text, ts.TokenClass.Whitespace, position); + return createClassification(text, TokenClass.Whitespace, position); } function identifier(text: string, position?: number) { - return createClassification(text, ts.TokenClass.Identifier, position); + return createClassification(text, TokenClass.Identifier, position); } function numberLiteral(text: string, position?: number) { - return createClassification(text, ts.TokenClass.NumberLiteral, position); + return createClassification(text, TokenClass.NumberLiteral, position); } function stringLiteral(text: string, position?: number) { - return createClassification(text, ts.TokenClass.StringLiteral, position); + return createClassification(text, TokenClass.StringLiteral, position); } function finalEndOfLineState(value: number): ClassificationEntry { // TODO: GH#18217 return { value, classification: undefined!, position: 0 }; } - function createClassification(value: string, classification: ts.TokenClass, position?: number): ClassificationEntry { + function createClassification(value: string, classification: TokenClass, position?: number): ClassificationEntry { return { value, classification, position }; } - function testLexicalClassification(text: string, initialEndOfLineState: ts.EndOfLineState, ...expectedEntries: ClassificationEntry[]): void { + function testLexicalClassification(text: string, initialEndOfLineState: EndOfLineState, ...expectedEntries: ClassificationEntry[]): void { const result = classifier.getClassificationsForLine(text, initialEndOfLineState, /*syntacticClassifierAbsent*/ false); for (const expectedEntry of expectedEntries) { @@ -72,8 +73,8 @@ describe("unittests:: services:: Colorization", () => { const actualEntry = getEntryAtPosition(result, actualEntryPosition)!; assert(actualEntry, "Could not find classification entry for '" + expectedEntry.value + "' at position: " + actualEntryPosition); - assert.equal(actualEntry.classification, expectedEntry.classification, "Classification class does not match expected. Expected: " + ts.TokenClass[expectedEntry.classification] + ", Actual: " + ts.TokenClass[actualEntry.classification]); - assert.equal(actualEntry.length, expectedEntry.value.length, "Classification length does not match expected. Expected: " + ts.TokenClass[expectedEntry.value.length] + ", Actual: " + ts.TokenClass[actualEntry.length]); + assert.equal(actualEntry.classification, expectedEntry.classification, "Classification class does not match expected. Expected: " + TokenClass[expectedEntry.classification] + ", Actual: " + TokenClass[actualEntry.classification]); + assert.equal(actualEntry.length, expectedEntry.value.length, "Classification length does not match expected. Expected: " + TokenClass[expectedEntry.value.length] + ", Actual: " + TokenClass[actualEntry.length]); } } } @@ -81,7 +82,7 @@ describe("unittests:: services:: Colorization", () => { describe("test getClassifications", () => { it("returns correct token classes", () => { testLexicalClassification("var x: string = \"foo\" ?? \"bar\"; //Hello", - ts.EndOfLineState.None, + EndOfLineState.None, keyword("var"), whitespace(" "), identifier("x"), @@ -98,7 +99,7 @@ describe("unittests:: services:: Colorization", () => { it("correctly classifies a comment after a divide operator", () => { testLexicalClassification("1 / 2 // comment", - ts.EndOfLineState.None, + EndOfLineState.None, numberLiteral("1"), whitespace(" "), operator("/"), @@ -108,7 +109,7 @@ describe("unittests:: services:: Colorization", () => { it("correctly classifies a literal after a divide operator", () => { testLexicalClassification("1 / 2, 3 / 4", - ts.EndOfLineState.None, + EndOfLineState.None, numberLiteral("1"), whitespace(" "), operator("/"), @@ -120,131 +121,131 @@ describe("unittests:: services:: Colorization", () => { it("correctly classifies a multiline string with one backslash", () => { testLexicalClassification("'line1\\", - ts.EndOfLineState.None, + EndOfLineState.None, stringLiteral("'line1\\"), - finalEndOfLineState(ts.EndOfLineState.InSingleQuoteStringLiteral)); + finalEndOfLineState(EndOfLineState.InSingleQuoteStringLiteral)); }); it("correctly classifies a multiline string with three backslashes", () => { testLexicalClassification("'line1\\\\\\", - ts.EndOfLineState.None, + EndOfLineState.None, stringLiteral("'line1\\\\\\"), - finalEndOfLineState(ts.EndOfLineState.InSingleQuoteStringLiteral)); + finalEndOfLineState(EndOfLineState.InSingleQuoteStringLiteral)); }); it("correctly classifies an unterminated single-line string with no backslashes", () => { testLexicalClassification("'line1", - ts.EndOfLineState.None, + EndOfLineState.None, stringLiteral("'line1"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); it("correctly classifies an unterminated single-line string with two backslashes", () => { testLexicalClassification("'line1\\\\", - ts.EndOfLineState.None, + EndOfLineState.None, stringLiteral("'line1\\\\"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); it("correctly classifies an unterminated single-line string with four backslashes", () => { testLexicalClassification("'line1\\\\\\\\", - ts.EndOfLineState.None, + EndOfLineState.None, stringLiteral("'line1\\\\\\\\"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); it("correctly classifies the continuing line of a multiline string ending in one backslash", () => { testLexicalClassification("\\", - ts.EndOfLineState.InDoubleQuoteStringLiteral, + EndOfLineState.InDoubleQuoteStringLiteral, stringLiteral("\\"), - finalEndOfLineState(ts.EndOfLineState.InDoubleQuoteStringLiteral)); + finalEndOfLineState(EndOfLineState.InDoubleQuoteStringLiteral)); }); it("correctly classifies the continuing line of a multiline string ending in three backslashes", () => { testLexicalClassification("\\", - ts.EndOfLineState.InDoubleQuoteStringLiteral, + EndOfLineState.InDoubleQuoteStringLiteral, stringLiteral("\\"), - finalEndOfLineState(ts.EndOfLineState.InDoubleQuoteStringLiteral)); + finalEndOfLineState(EndOfLineState.InDoubleQuoteStringLiteral)); }); it("correctly classifies the last line of an unterminated multiline string ending in no backslashes", () => { testLexicalClassification(" ", - ts.EndOfLineState.InDoubleQuoteStringLiteral, + EndOfLineState.InDoubleQuoteStringLiteral, stringLiteral(" "), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); it("correctly classifies the last line of an unterminated multiline string ending in two backslashes", () => { testLexicalClassification("\\\\", - ts.EndOfLineState.InDoubleQuoteStringLiteral, + EndOfLineState.InDoubleQuoteStringLiteral, stringLiteral("\\\\"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); it("correctly classifies the last line of an unterminated multiline string ending in four backslashes", () => { testLexicalClassification("\\\\\\\\", - ts.EndOfLineState.InDoubleQuoteStringLiteral, + EndOfLineState.InDoubleQuoteStringLiteral, stringLiteral("\\\\\\\\"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); it("correctly classifies the last line of a multiline string", () => { testLexicalClassification("'", - ts.EndOfLineState.InSingleQuoteStringLiteral, + EndOfLineState.InSingleQuoteStringLiteral, stringLiteral("'"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); it("correctly classifies an unterminated multiline comment", () => { testLexicalClassification("/*", - ts.EndOfLineState.None, + EndOfLineState.None, comment("/*"), - finalEndOfLineState(ts.EndOfLineState.InMultiLineCommentTrivia)); + finalEndOfLineState(EndOfLineState.InMultiLineCommentTrivia)); }); it("correctly classifies the termination of a multiline comment", () => { testLexicalClassification(" */ ", - ts.EndOfLineState.InMultiLineCommentTrivia, + EndOfLineState.InMultiLineCommentTrivia, comment(" */"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); it("correctly classifies the continuation of a multiline comment", () => { testLexicalClassification("LOREM IPSUM DOLOR ", - ts.EndOfLineState.InMultiLineCommentTrivia, + EndOfLineState.InMultiLineCommentTrivia, comment("LOREM IPSUM DOLOR "), - finalEndOfLineState(ts.EndOfLineState.InMultiLineCommentTrivia)); + finalEndOfLineState(EndOfLineState.InMultiLineCommentTrivia)); }); it("correctly classifies an unterminated multiline comment on a line ending in '/*/'", () => { testLexicalClassification(" /*/", - ts.EndOfLineState.None, + EndOfLineState.None, comment("/*/"), - finalEndOfLineState(ts.EndOfLineState.InMultiLineCommentTrivia)); + finalEndOfLineState(EndOfLineState.InMultiLineCommentTrivia)); }); it("correctly classifies an unterminated multiline comment with trailing space", () => { testLexicalClassification("/* ", - ts.EndOfLineState.None, + EndOfLineState.None, comment("/* "), - finalEndOfLineState(ts.EndOfLineState.InMultiLineCommentTrivia)); + finalEndOfLineState(EndOfLineState.InMultiLineCommentTrivia)); }); it("correctly classifies a keyword after a dot", () => { testLexicalClassification("a.var", - ts.EndOfLineState.None, + EndOfLineState.None, identifier("var")); }); it("correctly classifies a string literal after a dot", () => { testLexicalClassification("a.\"var\"", - ts.EndOfLineState.None, + EndOfLineState.None, stringLiteral("\"var\"")); }); it("correctly classifies a keyword after a dot separated by comment trivia", () => { testLexicalClassification("a./*hello world*/ var", - ts.EndOfLineState.None, + EndOfLineState.None, identifier("a"), punctuation("."), comment("/*hello world*/"), @@ -253,41 +254,41 @@ describe("unittests:: services:: Colorization", () => { it("classifies a property access with whitespace around the dot", () => { testLexicalClassification(" x .\tfoo ()", - ts.EndOfLineState.None, + EndOfLineState.None, identifier("x"), identifier("foo")); }); it("classifies a keyword after a dot on previous line", () => { testLexicalClassification("var", - ts.EndOfLineState.None, + EndOfLineState.None, keyword("var"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); it("classifies multiple keywords properly", () => { testLexicalClassification("public static", - ts.EndOfLineState.None, + EndOfLineState.None, keyword("public"), keyword("static"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); testLexicalClassification("public var", - ts.EndOfLineState.None, + EndOfLineState.None, keyword("public"), identifier("var"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); it("classifies a single line no substitution template string correctly", () => { testLexicalClassification("`number number public string`", - ts.EndOfLineState.None, + EndOfLineState.None, stringLiteral("`number number public string`"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); it("classifies substitution parts of a template string correctly", () => { testLexicalClassification("`number '${ 1 + 1 }' string '${ 'hello' }'`", - ts.EndOfLineState.None, + EndOfLineState.None, stringLiteral("`number '${"), numberLiteral("1"), operator("+"), @@ -295,64 +296,64 @@ describe("unittests:: services:: Colorization", () => { stringLiteral("}' string '${"), stringLiteral("'hello'"), stringLiteral("}'`"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); it("classifies an unterminated no substitution template string correctly", () => { testLexicalClassification("`hello world", - ts.EndOfLineState.None, + EndOfLineState.None, stringLiteral("`hello world"), - finalEndOfLineState(ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate)); + finalEndOfLineState(EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate)); }); it("classifies the entire line of an unterminated multiline no-substitution/head template", () => { testLexicalClassification("...", - ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, + EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, stringLiteral("..."), - finalEndOfLineState(ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate)); + finalEndOfLineState(EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate)); }); it("classifies the entire line of an unterminated multiline template middle/end", () => { testLexicalClassification("...", - ts.EndOfLineState.InTemplateMiddleOrTail, + EndOfLineState.InTemplateMiddleOrTail, stringLiteral("..."), - finalEndOfLineState(ts.EndOfLineState.InTemplateMiddleOrTail)); + finalEndOfLineState(EndOfLineState.InTemplateMiddleOrTail)); }); it("classifies a termination of a multiline template head", () => { testLexicalClassification("...${", - ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, + EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, stringLiteral("...${"), - finalEndOfLineState(ts.EndOfLineState.InTemplateSubstitutionPosition)); + finalEndOfLineState(EndOfLineState.InTemplateSubstitutionPosition)); }); it("classifies the termination of a multiline no substitution template", () => { testLexicalClassification("...`", - ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, + EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, stringLiteral("...`"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); it("classifies the substitution parts and middle/tail of a multiline template string", () => { testLexicalClassification("${ 1 + 1 }...`", - ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, + EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, stringLiteral("${"), numberLiteral("1"), operator("+"), numberLiteral("1"), stringLiteral("}...`"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); it("classifies a template middle and propagates the end of line state", () => { testLexicalClassification("${ 1 + 1 }...`", - ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, + EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, stringLiteral("${"), numberLiteral("1"), operator("+"), numberLiteral("1"), stringLiteral("}...`"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); it("classifies substitution expressions with curly braces appropriately", () => { let pos = 0; let lastLength = 0; testLexicalClassification("...${ () => { } } ${ { x: `1` } }...`", - ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, + EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate, stringLiteral(track("...${"), pos), punctuation(track(" ", "("), pos), punctuation(track(")"), pos), @@ -366,7 +367,7 @@ describe("unittests:: services:: Colorization", () => { stringLiteral(track(" ", "`1`"), pos), punctuation(track(" ", "}"), pos), stringLiteral(track(" ", "}...`"), pos), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); // Adjusts 'pos' by accounting for the length of each portion of the string, // but only return the last given string @@ -375,28 +376,28 @@ describe("unittests:: services:: Colorization", () => { pos += lastLength; lastLength = val.length; } - return ts.last(vals); + return last(vals); } }); it("classifies partially written generics correctly.", () => { testLexicalClassification("Foo { identifier("Foo"), operator("<"), identifier("number"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); it("LexicallyClassifiesConflictTokens", () => { @@ -417,7 +418,7 @@ describe("unittests:: services:: Colorization", () => { v = 2;\r\n\ >>>>>>> Branch - a\r\n\ }", - ts.EndOfLineState.None, + EndOfLineState.None, keyword("class"), identifier("C"), punctuation("{"), @@ -429,7 +430,7 @@ describe("unittests:: services:: Colorization", () => { comment("=======\r\n v = 2;\r\n"), comment(">>>>>>> Branch - a"), punctuation("}"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); testLexicalClassification( "<<<<<<< HEAD\r\n\ @@ -437,7 +438,7 @@ class C { }\r\n\ =======\r\n\ class D { }\r\n\ >>>>>>> Branch - a\r\n", - ts.EndOfLineState.None, + EndOfLineState.None, comment("<<<<<<< HEAD"), keyword("class"), identifier("C"), @@ -445,7 +446,7 @@ class D { }\r\n\ punctuation("}"), comment("=======\r\nclass D { }\r\n"), comment(">>>>>>> Branch - a"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); testLexicalClassification( "class C {\r\n\ @@ -457,7 +458,7 @@ class D { }\r\n\ v = 2;\r\n\ >>>>>>> Branch - a\r\n\ }", - ts.EndOfLineState.None, + EndOfLineState.None, keyword("class"), identifier("C"), punctuation("{"), @@ -470,7 +471,7 @@ class D { }\r\n\ comment("=======\r\n v = 2;\r\n"), comment(">>>>>>> Branch - a"), punctuation("}"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); testLexicalClassification( "<<<<<<< HEAD\r\n\ @@ -480,7 +481,7 @@ class E { }\r\n\ =======\r\n\ class D { }\r\n\ >>>>>>> Branch - a\r\n", - ts.EndOfLineState.None, + EndOfLineState.None, comment("<<<<<<< HEAD"), keyword("class"), identifier("C"), @@ -489,12 +490,12 @@ class D { }\r\n\ comment("||||||| merged common ancestors\r\nclass E { }\r\n"), comment("=======\r\nclass D { }\r\n"), comment(">>>>>>> Branch - a"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); it("'of' keyword", () => { testLexicalClassification("for (var of of of) { }", - ts.EndOfLineState.None, + EndOfLineState.None, keyword("for"), punctuation("("), keyword("var"), @@ -504,7 +505,7 @@ class D { }\r\n\ punctuation(")"), punctuation("{"), punctuation("}"), - finalEndOfLineState(ts.EndOfLineState.None)); + finalEndOfLineState(EndOfLineState.None)); }); }); }); diff --git a/src/testRunner/unittests/services/convertToAsyncFunction.ts b/src/testRunner/unittests/services/convertToAsyncFunction.ts index 83dab9a8d65c0..a4ed9b0cf2b70 100644 --- a/src/testRunner/unittests/services/convertToAsyncFunction.ts +++ b/src/testRunner/unittests/services/convertToAsyncFunction.ts @@ -1,7 +1,17 @@ -import * as Harness from "../../_namespaces/Harness"; -import * as ts from "../../_namespaces/ts"; - -const libFile: ts.TestFSWithWatch.File = { +import { find, first, length, noop, returnFalse } from "../../../compiler/core"; +import { Debug } from "../../../compiler/debug"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { Extension, Program } from "../../../compiler/types"; +import { Baseline } from "../../../harness/harnessIO"; +import { File } from "../../../harness/virtualFileSystemWithWatch"; +import { getFixes } from "../../../services/codeFixProvider"; +import { getFormatContext } from "../../../services/formatting/rulesMap"; +import { applyChanges } from "../../../services/textChanges"; +import { CodeFixContext, emptyOptions, testFormatSettings } from "../../../services/types"; +import { createProjectService, createServerHost } from "../tsserver/helpers"; +import { extractTest, newLineCharacter, notImplementedHost } from "./extract/helpers"; + +const libFile: File = { path: "/a/lib/lib.d.ts", content: `/// interface Boolean {} @@ -264,7 +274,7 @@ interface String { charAt: any; } interface Array {}` }; -const moduleFile: ts.TestFSWithWatch.File = { +const moduleFile: File = { path: "/module.ts", content: `export function fn(res: any): any { @@ -307,28 +317,28 @@ function testConvertToAsyncFunction(it: Mocha.PendingTestFunction, caption: stri const expectAction = !!(flags & ConvertToAsyncTestFlags.ExpectAction); const expectNoAction = !!(flags & ConvertToAsyncTestFlags.ExpectNoAction); const expectFailure = expectNoSuggestionDiagnostic || expectNoAction; - ts.Debug.assert(!(expectSuggestionDiagnostic && expectNoSuggestionDiagnostic), "Cannot combine both 'ExpectSuggestionDiagnostic' and 'ExpectNoSuggestionDiagnostic'"); - ts.Debug.assert(!(expectAction && expectNoAction), "Cannot combine both 'ExpectAction' and 'ExpectNoAction'"); + Debug.assert(!(expectSuggestionDiagnostic && expectNoSuggestionDiagnostic), "Cannot combine both 'ExpectSuggestionDiagnostic' and 'ExpectNoSuggestionDiagnostic'"); + Debug.assert(!(expectAction && expectNoAction), "Cannot combine both 'ExpectAction' and 'ExpectNoAction'"); - const t = ts.extractTest(text); + const t = extractTest(text); const selectionRange = t.ranges.get("selection")!; if (!selectionRange) { throw new Error(`Test ${caption} does not specify selection range`); } - const extensions = expectFailure ? [ts.Extension.Ts] : [ts.Extension.Ts, ts.Extension.Js]; + const extensions = expectFailure ? [Extension.Ts] : [Extension.Ts, Extension.Js]; extensions.forEach(extension => it(`${caption} [${extension}]`, () => runBaseline(extension))); - function runBaseline(extension: ts.Extension) { + function runBaseline(extension: Extension) { const path = "/a" + extension; const languageService = makeLanguageService({ path, content: t.source }, includeLib, includeModule); const program = languageService.getProgram()!; if (hasSyntacticDiagnostics(program)) { // Don't bother generating JS baselines for inputs that aren't valid JS. - assert.equal(ts.Extension.Js, extension, "Syntactic diagnostics found in non-JS file"); + assert.equal(Extension.Js, extension, "Syntactic diagnostics found in non-JS file"); return; } @@ -338,22 +348,22 @@ function testConvertToAsyncFunction(it: Mocha.PendingTestFunction, caption: stri }; const sourceFile = program.getSourceFile(path)!; - const context: ts.CodeFixContext = { + const context: CodeFixContext = { errorCode: 80006, span: { start: selectionRange.pos, length: selectionRange.end - selectionRange.pos }, sourceFile, program, - cancellationToken: { throwIfCancellationRequested: ts.noop, isCancellationRequested: ts.returnFalse }, - preferences: ts.emptyOptions, - host: ts.notImplementedHost, - formatContext: ts.formatting.getFormatContext(ts.testFormatSettings, ts.notImplementedHost) + cancellationToken: { throwIfCancellationRequested: noop, isCancellationRequested: returnFalse }, + preferences: emptyOptions, + host: notImplementedHost, + formatContext: getFormatContext(testFormatSettings, notImplementedHost) }; const diagnostics = languageService.getSuggestionDiagnostics(f.path); - const diagnostic = ts.find(diagnostics, diagnostic => diagnostic.messageText === ts.Diagnostics.This_may_be_converted_to_an_async_function.message && + const diagnostic = find(diagnostics, diagnostic => diagnostic.messageText === Diagnostics.This_may_be_converted_to_an_async_function.message && diagnostic.start === context.span.start && diagnostic.length === context.span.length); - const actions = ts.codefix.getFixes(context); - const action = ts.find(actions, action => action.description === ts.Diagnostics.Convert_to_async_function.message); + const actions = getFixes(context); + const action = find(actions, action => action.description === Diagnostics.Convert_to_async_function.message); let outputText: string | null; if (action?.changes.length) { @@ -364,19 +374,19 @@ function testConvertToAsyncFunction(it: Mocha.PendingTestFunction, caption: stri assert.lengthOf(changes, 1); data.push(`// ==ASYNC FUNCTION::${action.description}==`); - const newText = ts.textChanges.applyChanges(sourceFile.text, changes[0].textChanges); + const newText = applyChanges(sourceFile.text, changes[0].textChanges); data.push(newText); const diagProgram = makeLanguageService({ path, content: newText }, includeLib, includeModule).getProgram()!; assert.isFalse(hasSyntacticDiagnostics(diagProgram)); - outputText = data.join(ts.newLineCharacter); + outputText = data.join(newLineCharacter); } else { // eslint-disable-next-line no-null/no-null outputText = null; } - Harness.Baseline.runBaseline(`${baselineFolder}/${caption}${extension}`, outputText); + Baseline.runBaseline(`${baselineFolder}/${caption}${extension}`, outputText); if (expectNoSuggestionDiagnostic) { assert.isUndefined(diagnostic, "Expected code fix to not provide a suggestion diagnostic"); @@ -395,7 +405,7 @@ function testConvertToAsyncFunction(it: Mocha.PendingTestFunction, caption: stri } } - function makeLanguageService(file: ts.TestFSWithWatch.File, includeLib?: boolean, includeModule?: boolean) { + function makeLanguageService(file: File, includeLib?: boolean, includeModule?: boolean) { const files = [file]; if (includeLib) { files.push(libFile); // libFile is expensive to parse repeatedly - only test when required @@ -403,15 +413,15 @@ function testConvertToAsyncFunction(it: Mocha.PendingTestFunction, caption: stri if (includeModule) { files.push(moduleFile); } - const host = ts.projectSystem.createServerHost(files); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost(files); + const projectService = createProjectService(host); projectService.openClientFile(file.path); - return ts.first(projectService.inferredProjects).getLanguageService(); + return first(projectService.inferredProjects).getLanguageService(); } - function hasSyntacticDiagnostics(program: ts.Program) { + function hasSyntacticDiagnostics(program: Program) { const diags = program.getSyntacticDiagnostics(); - return ts.length(diags) > 0; + return length(diags) > 0; } } diff --git a/src/testRunner/unittests/services/documentRegistry.ts b/src/testRunner/unittests/services/documentRegistry.ts index 0238720b39357..9ed68d2b13e65 100644 --- a/src/testRunner/unittests/services/documentRegistry.ts +++ b/src/testRunner/unittests/services/documentRegistry.ts @@ -1,68 +1,72 @@ -import * as ts from "../../_namespaces/ts"; +import { CompilerOptions, ModuleKind, ScriptTarget } from "../../../compiler/types"; +import { createTextChangeRange, createTextSpan } from "../../../compiler/utilitiesPublic"; +import { createDocumentRegistry } from "../../../services/documentRegistry"; +import { getDefaultCompilerOptions } from "../../../services/services"; +import { ScriptSnapshot } from "../../../services/types"; describe("unittests:: services:: DocumentRegistry", () => { it("documents are shared between projects", () => { - const documentRegistry = ts.createDocumentRegistry(); - const defaultCompilerOptions = ts.getDefaultCompilerOptions(); + const documentRegistry = createDocumentRegistry(); + const defaultCompilerOptions = getDefaultCompilerOptions(); - const f1 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); - const f2 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); + const f1 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); + const f2 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); assert(f1 === f2, "DocumentRegistry should return the same document for the same name"); }); it("documents are refreshed when settings in compilation settings affect syntax", () => { - const documentRegistry = ts.createDocumentRegistry(); - const compilerOptions: ts.CompilerOptions = { target: ts.ScriptTarget.ES5, module: ts.ModuleKind.AMD }; + const documentRegistry = createDocumentRegistry(); + const compilerOptions: CompilerOptions = { target: ScriptTarget.ES5, module: ModuleKind.AMD }; // change compilation setting that doesn't affect parsing - should have the same document compilerOptions.declaration = true; - const f1 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); + const f1 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); compilerOptions.declaration = false; - const f2 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); + const f2 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); assert(f1 === f2, "Expected to have the same document instance"); // change value of compilation setting that is used during production of AST - new document is required - compilerOptions.target = ts.ScriptTarget.ES3; - const f3 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); + compilerOptions.target = ScriptTarget.ES3; + const f3 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); assert(f1 !== f3, "Changed target: Expected to have different instances of document"); compilerOptions.preserveConstEnums = true; - const f4 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); + const f4 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); assert(f3 === f4, "Changed preserveConstEnums: Expected to have the same instance of the document"); - compilerOptions.module = ts.ModuleKind.System; - const f5 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); + compilerOptions.module = ModuleKind.System; + const f5 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); assert(f4 !== f5, "Changed module: Expected to have different instances of the document"); }); it("Acquiring document gets correct version 1", () => { - const documentRegistry = ts.createDocumentRegistry(); - const defaultCompilerOptions = ts.getDefaultCompilerOptions(); + const documentRegistry = createDocumentRegistry(); + const defaultCompilerOptions = getDefaultCompilerOptions(); // Simulate one LS getting the document. - documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); + documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ScriptSnapshot.fromString("var x = 1;"), /* version */ "1"); // Simulate another LS getting the document at another version. - const f2 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "2"); + const f2 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ScriptSnapshot.fromString("var x = 1;"), /* version */ "2"); assert(f2.version === "2"); }); it("Acquiring document gets correct version 2", () => { - const documentRegistry = ts.createDocumentRegistry(); - const defaultCompilerOptions = ts.getDefaultCompilerOptions(); + const documentRegistry = createDocumentRegistry(); + const defaultCompilerOptions = getDefaultCompilerOptions(); const contents = "var x = 1;"; - const snapshot = ts.ScriptSnapshot.fromString(contents); + const snapshot = ScriptSnapshot.fromString(contents); // Always treat any change as a full change. - snapshot.getChangeRange = () => ts.createTextChangeRange(ts.createTextSpan(0, contents.length), contents.length); + snapshot.getChangeRange = () => createTextChangeRange(createTextSpan(0, contents.length), contents.length); // Simulate one LS getting the document. documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, snapshot, /* version */ "1"); diff --git a/src/testRunner/unittests/services/extract/constants.ts b/src/testRunner/unittests/services/extract/constants.ts index 1e642180fa2ab..13a837cd5a3bd 100644 --- a/src/testRunner/unittests/services/extract/constants.ts +++ b/src/testRunner/unittests/services/extract/constants.ts @@ -1,4 +1,5 @@ -import * as ts from "../../../_namespaces/ts"; +import { Diagnostics } from "../../../../compiler/diagnosticInformationMap.generated"; +import { testExtractSymbol, testExtractSymbolFailed } from "./helpers"; describe("unittests:: services:: extract:: extractConstants", () => { testExtractConstant("extractConstant_TopLevel", @@ -296,11 +297,11 @@ switch (1) { }); function testExtractConstant(caption: string, text: string) { - ts.testExtractSymbol(caption, text, "extractConstant", ts.Diagnostics.Extract_constant); + testExtractSymbol(caption, text, "extractConstant", Diagnostics.Extract_constant); } function testExtractConstantFailed(caption: string, text: string) { - ts.testExtractSymbolFailed(caption, text, ts.Diagnostics.Extract_constant); + testExtractSymbolFailed(caption, text, Diagnostics.Extract_constant); } export { }; diff --git a/src/testRunner/unittests/services/extract/functions.ts b/src/testRunner/unittests/services/extract/functions.ts index e77825dd64dd0..9fcc4a2d75a62 100644 --- a/src/testRunner/unittests/services/extract/functions.ts +++ b/src/testRunner/unittests/services/extract/functions.ts @@ -1,4 +1,5 @@ -import * as ts from "../../../_namespaces/ts"; +import { Diagnostics } from "../../../../compiler/diagnosticInformationMap.generated"; +import { testExtractSymbol } from "./helpers"; describe("unittests:: services:: extract:: extractFunctions", () => { testExtractFunction("extractFunction1", @@ -565,7 +566,7 @@ function F() { }); function testExtractFunction(caption: string, text: string, includeLib?: boolean) { - ts.testExtractSymbol(caption, text, "extractFunction", ts.Diagnostics.Extract_function, includeLib); + testExtractSymbol(caption, text, "extractFunction", Diagnostics.Extract_function, includeLib); } export { }; diff --git a/src/testRunner/unittests/services/extract/helpers.ts b/src/testRunner/unittests/services/extract/helpers.ts index 78d51816bc0c1..64cda43778655 100644 --- a/src/testRunner/unittests/services/extract/helpers.ts +++ b/src/testRunner/unittests/services/extract/helpers.ts @@ -1,5 +1,16 @@ -import * as Harness from "../../../_namespaces/Harness"; -import * as ts from "../../../_namespaces/ts"; +import { find, hasProperty, length, noop, notImplemented, returnFalse } from "../../../../compiler/core"; +import { ESMap, Map } from "../../../../compiler/corePublic"; +import { isIdentifierPart } from "../../../../compiler/scanner"; +import { CharacterCodes, DiagnosticMessage, Extension, Program, ScriptTarget } from "../../../../compiler/types"; +import { Baseline } from "../../../../harness/harnessIO"; +import { getFormatContext } from "../../../../services/formatting/rulesMap"; +import { + getRangeToExtract, getRefactorActionsToExtractSymbol, getRefactorEditsToExtractSymbol, +} from "../../../../services/refactors/extractSymbol"; +import { applyChanges } from "../../../../services/textChanges"; +import { emptyOptions, LanguageServiceHost, RefactorContext, testFormatSettings } from "../../../../services/types"; +import { createTextSpanFromRange } from "../../../../services/utilities"; +import { createProjectService, createServerHost, libFile } from "../../tsserver/helpers"; interface Range { pos: number; @@ -9,7 +20,7 @@ interface Range { interface Test { source: string; - ranges: ts.ESMap; + ranges: ESMap; } export function extractTest(source: string): Test { @@ -17,21 +28,21 @@ export function extractTest(source: string): Test { let text = ""; let lastPos = 0; let pos = 0; - const ranges = new ts.Map(); + const ranges = new Map(); while (pos < source.length) { - if (source.charCodeAt(pos) === ts.CharacterCodes.openBracket && - (source.charCodeAt(pos + 1) === ts.CharacterCodes.hash || source.charCodeAt(pos + 1) === ts.CharacterCodes.$)) { + if (source.charCodeAt(pos) === CharacterCodes.openBracket && + (source.charCodeAt(pos + 1) === CharacterCodes.hash || source.charCodeAt(pos + 1) === CharacterCodes.$)) { const saved = pos; pos += 2; const s = pos; consumeIdentifier(); const e = pos; - if (source.charCodeAt(pos) === ts.CharacterCodes.bar) { + if (source.charCodeAt(pos) === CharacterCodes.bar) { pos++; text += source.substring(lastPos, saved); const name = s === e - ? source.charCodeAt(saved + 1) === ts.CharacterCodes.hash ? "selection" : "extracted" + ? source.charCodeAt(saved + 1) === CharacterCodes.hash ? "selection" : "extracted" : source.substring(s, e); activeRanges.push({ name, pos: text.length, end: undefined! }); // TODO: GH#18217 lastPos = pos; @@ -41,11 +52,11 @@ export function extractTest(source: string): Test { pos = saved; } } - else if (source.charCodeAt(pos) === ts.CharacterCodes.bar && source.charCodeAt(pos + 1) === ts.CharacterCodes.closeBracket) { + else if (source.charCodeAt(pos) === CharacterCodes.bar && source.charCodeAt(pos + 1) === CharacterCodes.closeBracket) { text += source.substring(lastPos, pos); activeRanges[activeRanges.length - 1].end = text.length; const range = activeRanges.pop()!; - if (ts.hasProperty(ranges, range.name)) { + if (hasProperty(ranges, range.name)) { throw new Error(`Duplicate name of range ${range.name}`); } ranges.set(range.name, range); @@ -58,7 +69,7 @@ export function extractTest(source: string): Test { text += source.substring(lastPos, pos); function consumeIdentifier() { - while (ts.isIdentifierPart(source.charCodeAt(pos), ts.ScriptTarget.Latest)) { + while (isIdentifierPart(source.charCodeAt(pos), ScriptTarget.Latest)) { pos++; } } @@ -67,86 +78,86 @@ export function extractTest(source: string): Test { export const newLineCharacter = "\n"; -export const notImplementedHost: ts.LanguageServiceHost = { - getCompilationSettings: ts.notImplemented, - getScriptFileNames: ts.notImplemented, - getScriptVersion: ts.notImplemented, - getScriptSnapshot: ts.notImplemented, - getDefaultLibFileName: ts.notImplemented, - getCurrentDirectory: ts.notImplemented, - readFile: ts.notImplemented, - fileExists: ts.notImplemented +export const notImplementedHost: LanguageServiceHost = { + getCompilationSettings: notImplemented, + getScriptFileNames: notImplemented, + getScriptVersion: notImplemented, + getScriptSnapshot: notImplemented, + getDefaultLibFileName: notImplemented, + getCurrentDirectory: notImplemented, + readFile: notImplemented, + fileExists: notImplemented }; -export function testExtractSymbol(caption: string, text: string, baselineFolder: string, description: ts.DiagnosticMessage, includeLib?: boolean) { +export function testExtractSymbol(caption: string, text: string, baselineFolder: string, description: DiagnosticMessage, includeLib?: boolean) { const t = extractTest(text); const selectionRange = t.ranges.get("selection")!; if (!selectionRange) { throw new Error(`Test ${caption} does not specify selection range`); } - [ts.Extension.Ts, ts.Extension.Js].forEach(extension => + [Extension.Ts, Extension.Js].forEach(extension => it(`${caption} [${extension}]`, () => runBaseline(extension))); - function runBaseline(extension: ts.Extension) { + function runBaseline(extension: Extension) { const path = "/a" + extension; const { program } = makeProgram({ path, content: t.source }, includeLib); if (hasSyntacticDiagnostics(program)) { // Don't bother generating JS baselines for inputs that aren't valid JS. - assert.equal(ts.Extension.Js, extension, "Syntactic diagnostics found in non-JS file"); + assert.equal(Extension.Js, extension, "Syntactic diagnostics found in non-JS file"); return; } const sourceFile = program.getSourceFile(path)!; - const context: ts.RefactorContext = { - cancellationToken: { throwIfCancellationRequested: ts.noop, isCancellationRequested: ts.returnFalse }, + const context: RefactorContext = { + cancellationToken: { throwIfCancellationRequested: noop, isCancellationRequested: returnFalse }, program, file: sourceFile, startPosition: selectionRange.pos, endPosition: selectionRange.end, host: notImplementedHost, - formatContext: ts.formatting.getFormatContext(ts.testFormatSettings, notImplementedHost), - preferences: ts.emptyOptions, + formatContext: getFormatContext(testFormatSettings, notImplementedHost), + preferences: emptyOptions, }; - const rangeToExtract = ts.refactor.extractSymbol.getRangeToExtract(sourceFile, ts.createTextSpanFromRange(selectionRange)); + const rangeToExtract = getRangeToExtract(sourceFile, createTextSpanFromRange(selectionRange)); assert.equal(rangeToExtract.errors, undefined, rangeToExtract.errors && "Range error: " + rangeToExtract.errors[0].messageText); - const infos = ts.refactor.extractSymbol.getRefactorActionsToExtractSymbol(context); - const actions = ts.find(infos, info => info.description === description.message)!.actions; + const infos = getRefactorActionsToExtractSymbol(context); + const actions = find(infos, info => info.description === description.message)!.actions; const data: string[] = []; data.push(`// ==ORIGINAL==`); data.push(text.replace("[#|", "/*[#|*/").replace("|]", "/*|]*/")); for (const action of actions) { - const { renameLocation, edits } = ts.refactor.extractSymbol.getRefactorEditsToExtractSymbol(context, action.name)!; + const { renameLocation, edits } = getRefactorEditsToExtractSymbol(context, action.name)!; assert.lengthOf(edits, 1); data.push(`// ==SCOPE::${action.description}==`); - const newText = ts.textChanges.applyChanges(sourceFile.text, edits[0].textChanges); + const newText = applyChanges(sourceFile.text, edits[0].textChanges); const newTextWithRename = newText.slice(0, renameLocation) + "/*RENAME*/" + newText.slice(renameLocation); data.push(newTextWithRename); const { program: diagProgram } = makeProgram({ path, content: newText }, includeLib); assert.isFalse(hasSyntacticDiagnostics(diagProgram)); } - Harness.Baseline.runBaseline(`${baselineFolder}/${caption}${extension}`, data.join(newLineCharacter)); + Baseline.runBaseline(`${baselineFolder}/${caption}${extension}`, data.join(newLineCharacter)); } function makeProgram(f: {path: string, content: string }, includeLib?: boolean) { - const host = ts.projectSystem.createServerHost(includeLib ? [f, ts.projectSystem.libFile] : [f]); // libFile is expensive to parse repeatedly - only test when required - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost(includeLib ? [f, libFile] : [f]); // libFile is expensive to parse repeatedly - only test when required + const projectService = createProjectService(host); projectService.openClientFile(f.path); const program = projectService.inferredProjects[0].getLanguageService().getProgram()!; const autoImportProvider = projectService.inferredProjects[0].getLanguageService().getAutoImportProvider(); return { program, autoImportProvider }; } - function hasSyntacticDiagnostics(program: ts.Program) { + function hasSyntacticDiagnostics(program: Program) { const diags = program.getSyntacticDiagnostics(); - return ts.length(diags) > 0; + return length(diags) > 0; } } -export function testExtractSymbolFailed(caption: string, text: string, description: ts.DiagnosticMessage) { +export function testExtractSymbolFailed(caption: string, text: string, description: DiagnosticMessage) { it(caption, () => { const t = extractTest(text); const selectionRange = t.ranges.get("selection"); @@ -157,24 +168,24 @@ export function testExtractSymbolFailed(caption: string, text: string, descripti path: "/a.ts", content: t.source }; - const host = ts.projectSystem.createServerHost([f, ts.projectSystem.libFile]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([f, libFile]); + const projectService = createProjectService(host); projectService.openClientFile(f.path); const program = projectService.inferredProjects[0].getLanguageService().getProgram()!; const sourceFile = program.getSourceFile(f.path)!; - const context: ts.RefactorContext = { - cancellationToken: { throwIfCancellationRequested: ts.noop, isCancellationRequested: ts.returnFalse }, + const context: RefactorContext = { + cancellationToken: { throwIfCancellationRequested: noop, isCancellationRequested: returnFalse }, program, file: sourceFile, startPosition: selectionRange.pos, endPosition: selectionRange.end, host: notImplementedHost, - formatContext: ts.formatting.getFormatContext(ts.testFormatSettings, notImplementedHost), - preferences: ts.emptyOptions, + formatContext: getFormatContext(testFormatSettings, notImplementedHost), + preferences: emptyOptions, }; - const rangeToExtract = ts.refactor.extractSymbol.getRangeToExtract(sourceFile, ts.createTextSpanFromRange(selectionRange)); + const rangeToExtract = getRangeToExtract(sourceFile, createTextSpanFromRange(selectionRange)); assert.isUndefined(rangeToExtract.errors, rangeToExtract.errors && "Range error: " + rangeToExtract.errors[0].messageText); - const infos = ts.refactor.extractSymbol.getRefactorActionsToExtractSymbol(context); - assert.isUndefined(ts.find(infos, info => info.description === description.message)); + const infos = getRefactorActionsToExtractSymbol(context); + assert.isUndefined(find(infos, info => info.description === description.message)); }); } diff --git a/src/testRunner/unittests/services/extract/ranges.ts b/src/testRunner/unittests/services/extract/ranges.ts index 94d5f0f507105..7d0b833380a46 100644 --- a/src/testRunner/unittests/services/extract/ranges.ts +++ b/src/testRunner/unittests/services/extract/ranges.ts @@ -1,14 +1,19 @@ -import * as ts from "../../../_namespaces/ts"; +import { isArray, last } from "../../../../compiler/core"; +import { createSourceFile } from "../../../../compiler/parser"; +import { ScriptTarget } from "../../../../compiler/types"; +import { getRangeToExtract, Messages } from "../../../../services/refactors/extractSymbol"; +import { createTextSpanFromRange } from "../../../../services/utilities"; +import { extractTest } from "./helpers"; function testExtractRangeFailed(caption: string, s: string, expectedErrors: string[]) { return it(caption, () => { - const t = ts.extractTest(s); - const file = ts.createSourceFile("a.ts", t.source, ts.ScriptTarget.Latest, /*setParentNodes*/ true); + const t = extractTest(s); + const file = createSourceFile("a.ts", t.source, ScriptTarget.Latest, /*setParentNodes*/ true); const selectionRange = t.ranges.get("selection"); if (!selectionRange) { throw new Error(`Test ${s} does not specify selection range`); } - const result = ts.refactor.extractSymbol.getRangeToExtract(file, ts.createTextSpanFromRange(selectionRange), /*userRequested*/ false); + const result = getRangeToExtract(file, createTextSpanFromRange(selectionRange), /*userRequested*/ false); assert(result.targetRange === undefined, "failure expected"); const sortedErrors = result.errors.map(e => e.messageText as string).sort(); assert.deepEqual(sortedErrors, expectedErrors.sort(), "unexpected errors"); @@ -17,20 +22,20 @@ function testExtractRangeFailed(caption: string, s: string, expectedErrors: stri function testExtractRange(caption: string, s: string) { return it(caption, () => { - const t = ts.extractTest(s); - const f = ts.createSourceFile("a.ts", t.source, ts.ScriptTarget.Latest, /*setParentNodes*/ true); + const t = extractTest(s); + const f = createSourceFile("a.ts", t.source, ScriptTarget.Latest, /*setParentNodes*/ true); const selectionRange = t.ranges.get("selection"); if (!selectionRange) { throw new Error(`Test ${s} does not specify selection range`); } - const result = ts.refactor.extractSymbol.getRangeToExtract(f, ts.createTextSpanFromRange(selectionRange)); + const result = getRangeToExtract(f, createTextSpanFromRange(selectionRange)); const expectedRange = t.ranges.get("extracted"); if (expectedRange) { let pos: number, end: number; const targetRange = result.targetRange!; - if (ts.isArray(targetRange.range)) { + if (isArray(targetRange.range)) { pos = targetRange.range[0].getStart(f); - end = ts.last(targetRange.range).getEnd(); + end = last(targetRange.range).getEnd(); } else { pos = targetRange.range.getStart(f); @@ -209,7 +214,7 @@ function f() { } } `, - [ts.refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalReturnStatement.message]); + [Messages.cannotExtractRangeContainingConditionalReturnStatement.message]); testExtractRangeFailed("extractRangeFailed2", ` @@ -226,7 +231,7 @@ function f() { } } `, - [ts.refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); + [Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); testExtractRangeFailed("extractRangeFailed3", ` @@ -243,7 +248,7 @@ function f() { } } `, - [ts.refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); + [Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); testExtractRangeFailed("extractRangeFailed4", ` @@ -260,7 +265,7 @@ function f() { } } `, - [ts.refactor.extractSymbol.Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange.message]); + [Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange.message]); testExtractRangeFailed("extractRangeFailed5", ` @@ -279,7 +284,7 @@ function f2() { } } `, - [ts.refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalReturnStatement.message]); + [Messages.cannotExtractRangeContainingConditionalReturnStatement.message]); testExtractRangeFailed("extractRangeFailed6", ` @@ -298,7 +303,7 @@ function f2() { } } `, - [ts.refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalReturnStatement.message]); + [Messages.cannotExtractRangeContainingConditionalReturnStatement.message]); testExtractRangeFailed("extractRangeFailed7", ` @@ -309,7 +314,7 @@ while (x) { } } `, - [ts.refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); + [Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); testExtractRangeFailed("extractRangeFailed8", ` @@ -320,11 +325,11 @@ switch (x) { } } `, - [ts.refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); + [Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); testExtractRangeFailed("extractRangeFailed9", `var x = ([#||]1 + 2);`, - [ts.refactor.extractSymbol.Messages.cannotExtractEmpty.message]); + [Messages.cannotExtractEmpty.message]); testExtractRangeFailed("extractRangeFailed10", ` @@ -333,7 +338,7 @@ switch (x) { } } `, - [ts.refactor.extractSymbol.Messages.cannotExtractRange.message]); + [Messages.cannotExtractRange.message]); testExtractRangeFailed("extractRangeFailed11", ` @@ -348,15 +353,15 @@ switch (x) { } } `, - [ts.refactor.extractSymbol.Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); + [Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements.message]); testExtractRangeFailed("extractRangeFailed12", `let [#|x|];`, - [ts.refactor.extractSymbol.Messages.statementOrExpressionExpected.message]); + [Messages.statementOrExpressionExpected.message]); testExtractRangeFailed("extractRangeFailed13", `[#|return;|]`, - [ts.refactor.extractSymbol.Messages.cannotExtractRange.message]); + [Messages.cannotExtractRange.message]); testExtractRangeFailed("extractRangeFailed14", ` @@ -365,7 +370,7 @@ switch (x) { break;|] } `, - [ts.refactor.extractSymbol.Messages.cannotExtractRange.message]); + [Messages.cannotExtractRange.message]); testExtractRangeFailed("extractRangeFailed15", ` @@ -374,7 +379,7 @@ switch (x) { break|]; } `, - [ts.refactor.extractSymbol.Messages.cannotExtractRange.message]); + [Messages.cannotExtractRange.message]); // Documentation only - it would be nice if the result were [$|1|] testExtractRangeFailed("extractRangeFailed16", @@ -384,7 +389,7 @@ switch (x) { break; } `, - [ts.refactor.extractSymbol.Messages.cannotExtractRange.message]); + [Messages.cannotExtractRange.message]); // Documentation only - it would be nice if the result were [$|1|] testExtractRangeFailed("extractRangeFailed17", @@ -394,17 +399,17 @@ switch (x) { break; } `, - [ts.refactor.extractSymbol.Messages.cannotExtractRange.message]); + [Messages.cannotExtractRange.message]); testExtractRangeFailed("extractRangeFailed18", `[#|{ 1;|] }`, - [ts.refactor.extractSymbol.Messages.cannotExtractRange.message]); + [Messages.cannotExtractRange.message]); testExtractRangeFailed("extractRangeFailed19", `[#|/** @type {number} */|] const foo = 1;`, - [ts.refactor.extractSymbol.Messages.cannotExtractJSDoc.message]); + [Messages.cannotExtractJSDoc.message]); - testExtractRangeFailed("extract-method-not-for-token-expression-statement", `[#|a|]`, [ts.refactor.extractSymbol.Messages.cannotExtractIdentifier.message]); + testExtractRangeFailed("extract-method-not-for-token-expression-statement", `[#|a|]`, [Messages.cannotExtractIdentifier.message]); }); export { }; diff --git a/src/testRunner/unittests/services/extract/symbolWalker.ts b/src/testRunner/unittests/services/extract/symbolWalker.ts index 0a5e42a4c2c66..3520fddc57a83 100644 --- a/src/testRunner/unittests/services/extract/symbolWalker.ts +++ b/src/testRunner/unittests/services/extract/symbolWalker.ts @@ -1,10 +1,12 @@ -import * as Harness from "../../../_namespaces/Harness"; -import * as ts from "../../../_namespaces/ts"; +import { forEach } from "../../../../compiler/core"; +import { SourceFile, TypeChecker } from "../../../../compiler/types"; +import { getSourceFileOfNode } from "../../../../compiler/utilities"; +import { Compiler } from "../../../../harness/harnessIO"; describe("unittests:: services:: extract:: Symbol Walker", () => { - function test(description: string, source: string, verifier: (file: ts.SourceFile, checker: ts.TypeChecker) => void) { + function test(description: string, source: string, verifier: (file: SourceFile, checker: TypeChecker) => void) { it(description, () => { - const result = Harness.Compiler.compileFiles([{ + const result = Compiler.compileFiles([{ unitName: "main.ts", content: source }], [], {}, {}, "/"); @@ -25,8 +27,8 @@ export default function foo(a: number, b: Bar): void {}`, (file, checker) => { let stdLibRefSymbols = 0; const expectedSymbols = ["default", "a", "b", "Bar", "x", "y", "history"]; const walker = checker.getSymbolWalker(symbol => { - const isStdLibSymbol = ts.forEach(symbol.declarations, d => { - return ts.getSourceFileOfNode(d).hasNoDefaultLib; + const isStdLibSymbol = forEach(symbol.declarations, d => { + return getSourceFileOfNode(d).hasNoDefaultLib; }); if (isStdLibSymbol) { stdLibRefSymbols++; diff --git a/src/testRunner/unittests/services/hostNewLineSupport.ts b/src/testRunner/unittests/services/hostNewLineSupport.ts index d2a6078a43490..4ec1c101861bf 100644 --- a/src/testRunner/unittests/services/hostNewLineSupport.ts +++ b/src/testRunner/unittests/services/hostNewLineSupport.ts @@ -1,18 +1,21 @@ -import * as Harness from "../../_namespaces/Harness"; -import * as ts from "../../_namespaces/ts"; +import { find, map } from "../../../compiler/core"; +import { CompilerOptions, NewLineKind } from "../../../compiler/types"; +import { Compiler } from "../../../harness/harnessIO"; +import { createLanguageService } from "../../../services/services"; +import { IScriptSnapshot, LanguageServiceHost, ScriptSnapshot } from "../../../services/types"; describe("unittests:: services:: hostNewLineSupport", () => { - function testLSWithFiles(settings: ts.CompilerOptions, files: Harness.Compiler.TestFile[]) { - function snapFor(path: string): ts.IScriptSnapshot | undefined { + function testLSWithFiles(settings: CompilerOptions, files: Compiler.TestFile[]) { + function snapFor(path: string): IScriptSnapshot | undefined { if (path === "lib.d.ts") { - return ts.ScriptSnapshot.fromString(""); + return ScriptSnapshot.fromString(""); } - const result = ts.find(files, f => f.unitName === path); - return result && ts.ScriptSnapshot.fromString(result.content); + const result = find(files, f => f.unitName === path); + return result && ScriptSnapshot.fromString(result.content); } - const lshost: ts.LanguageServiceHost = { + const lshost: LanguageServiceHost = { getCompilationSettings: () => settings, - getScriptFileNames: () => ts.map(files, f => f.unitName), + getScriptFileNames: () => map(files, f => f.unitName), getScriptVersion: () => "1", getScriptSnapshot: name => snapFor(name), getDefaultLibFileName: () => "lib.d.ts", @@ -24,10 +27,10 @@ describe("unittests:: services:: hostNewLineSupport", () => { }, fileExists: name => !!snapFor(name), }; - return ts.createLanguageService(lshost); + return createLanguageService(lshost); } - function verifyNewLines(content: string, options: ts.CompilerOptions) { + function verifyNewLines(content: string, options: CompilerOptions) { const ls = testLSWithFiles(options, [{ content, fileOptions: {}, @@ -37,16 +40,16 @@ describe("unittests:: services:: hostNewLineSupport", () => { assert(!result.emitSkipped, "emit was skipped"); assert(result.outputFiles.length === 1, "a number of files other than 1 was output"); assert(result.outputFiles[0].name === "input.js", `Expected output file name input.js, but got ${result.outputFiles[0].name}`); - assert(result.outputFiles[0].text.match(options.newLine === ts.NewLineKind.CarriageReturnLineFeed ? /\r\n/ : /[^\r]\n/), "expected to find appropriate newlines"); - assert(!result.outputFiles[0].text.match(options.newLine === ts.NewLineKind.CarriageReturnLineFeed ? /[^\r]\n/ : /\r\n/), "expected not to find inappropriate newlines"); + assert(result.outputFiles[0].text.match(options.newLine === NewLineKind.CarriageReturnLineFeed ? /\r\n/ : /[^\r]\n/), "expected to find appropriate newlines"); + assert(!result.outputFiles[0].text.match(options.newLine === NewLineKind.CarriageReturnLineFeed ? /[^\r]\n/ : /\r\n/), "expected not to find inappropriate newlines"); } function verifyBothNewLines(content: string) { - verifyNewLines(content, { newLine: ts.NewLineKind.CarriageReturnLineFeed }); - verifyNewLines(content, { newLine: ts.NewLineKind.LineFeed }); + verifyNewLines(content, { newLine: NewLineKind.CarriageReturnLineFeed }); + verifyNewLines(content, { newLine: NewLineKind.LineFeed }); } - function verifyOutliningSpanNewLines(content: string, options: ts.CompilerOptions) { + function verifyOutliningSpanNewLines(content: string, options: CompilerOptions) { const ls = testLSWithFiles(options, [{ content, fileOptions: {}, @@ -54,8 +57,8 @@ describe("unittests:: services:: hostNewLineSupport", () => { }]); const span = ls.getOutliningSpans("input.ts")[0]; const textAfterSpanCollapse = content.substring(span.textSpan.start + span.textSpan.length); - assert(textAfterSpanCollapse.match(options.newLine === ts.NewLineKind.CarriageReturnLineFeed ? /\r\n/ : /[^\r]\n/), "expected to find appropriate newlines"); - assert(!textAfterSpanCollapse.match(options.newLine === ts.NewLineKind.CarriageReturnLineFeed ? /[^\r]\n/ : /\r\n/), "expected not to find inappropriate newlines"); + assert(textAfterSpanCollapse.match(options.newLine === NewLineKind.CarriageReturnLineFeed ? /\r\n/ : /[^\r]\n/), "expected to find appropriate newlines"); + assert(!textAfterSpanCollapse.match(options.newLine === NewLineKind.CarriageReturnLineFeed ? /[^\r]\n/ : /\r\n/), "expected not to find inappropriate newlines"); } it("should exist and respect provided compiler options", () => { @@ -68,12 +71,12 @@ describe("unittests:: services:: hostNewLineSupport", () => { it("should respect CRLF line endings around outlining spans", () => { verifyOutliningSpanNewLines("// comment not included\r\n// #region name\r\nlet x: string = \"x\";\r\n// #endregion name\r\n", - { newLine: ts.NewLineKind.CarriageReturnLineFeed }); + { newLine: NewLineKind.CarriageReturnLineFeed }); }); it("should respect LF line endings around outlining spans", () => { verifyOutliningSpanNewLines("// comment not included\n// #region name\nlet x: string = \"x\";\n// #endregion name\n\n", - { newLine: ts.NewLineKind.LineFeed }); + { newLine: NewLineKind.LineFeed }); }); }); diff --git a/src/testRunner/unittests/services/languageService.ts b/src/testRunner/unittests/services/languageService.ts index 14f2356bb15a6..a2f957f776bf7 100644 --- a/src/testRunner/unittests/services/languageService.ts +++ b/src/testRunner/unittests/services/languageService.ts @@ -1,4 +1,13 @@ +import { getParsedCommandLineOfConfigFile } from "../../../compiler/commandLineParser"; +import { emptyArray, noop, returnTrue } from "../../../compiler/core"; +import { Map } from "../../../compiler/corePublic"; +import { Program } from "../../../compiler/types"; +import { File } from "../../../harness/virtualFileSystemWithWatch"; +import { getDefaultCompilerOptions, getDefaultLibFilePath } from "../../../services/services"; +import { LanguageServiceHost, ScriptSnapshot } from "../../../services/types"; import * as ts from "../../_namespaces/ts"; +import { projectRoot } from "../tscWatch/helpers"; +import { createServerHost, libFile } from "../tsserver/helpers"; const _chai: typeof import("chai") = require("chai"); const expect: typeof _chai.expect = _chai.expect; @@ -32,13 +41,13 @@ export function Component(x: Config): any;` }, getScriptSnapshot(fileName) { if (fileName === ".ts") { - return ts.ScriptSnapshot.fromString(""); + return ScriptSnapshot.fromString(""); } - return ts.ScriptSnapshot.fromString(files[fileName] || ""); + return ScriptSnapshot.fromString(files[fileName] || ""); }, getCurrentDirectory: () => ".", getDefaultLibFileName(options) { - return ts.getDefaultLibFilePath(options); + return getDefaultLibFilePath(options); }, fileExists: name => !!files[name], readFile: name => files[name] @@ -61,8 +70,8 @@ export function Component(x: Config): any;` ), { emitSkipped: true, - diagnostics: ts.emptyArray, - outputFiles: ts.emptyArray, + diagnostics: emptyArray, + outputFiles: emptyArray, exportedModulesFromDeclarationEmit: undefined } ); @@ -75,7 +84,7 @@ export function Component(x: Config): any;` ), { emitSkipped: false, - diagnostics: ts.emptyArray, + diagnostics: emptyArray, outputFiles: [{ name: "foo.d.ts", text: "export {};\r\n", @@ -89,13 +98,13 @@ export function Component(x: Config): any;` describe("detects program upto date correctly", () => { function verifyProgramUptoDate(useProjectVersion: boolean) { let projectVersion = "1"; - const files = new ts.Map(); + const files = new Map(); files.set("/project/root.ts", { version: "1", text: `import { foo } from "./other"` }); files.set("/project/other.ts", { version: "1", text: `export function foo() { }` }); - files.set("/lib/lib.d.ts", { version: "1", text: ts.projectSystem.libFile.content }); - const host: ts.LanguageServiceHost = { - useCaseSensitiveFileNames: ts.returnTrue, - getCompilationSettings: ts.getDefaultCompilerOptions, + files.set("/lib/lib.d.ts", { version: "1", text: libFile.content }); + const host: LanguageServiceHost = { + useCaseSensitiveFileNames: returnTrue, + getCompilationSettings: getDefaultCompilerOptions, fileExists: path => files.has(path), readFile: path => files.get(path)?.text, getProjectVersion: !useProjectVersion ? undefined : () => projectVersion, @@ -103,7 +112,7 @@ export function Component(x: Config): any;` getScriptVersion: path => files.get(path)?.version || "", getScriptSnapshot: path => { const text = files.get(path)?.text; - return text ? ts.ScriptSnapshot.fromString(text) : undefined; + return text ? ScriptSnapshot.fromString(text) : undefined; }, getCurrentDirectory: () => "/project", getDefaultLibFileName: () => "/lib/lib.d.ts" @@ -128,7 +137,7 @@ export function Component(x: Config): any;` assert.notStrictEqual(program3, program4); verifyProgramFiles(program4); - function verifyProgramFiles(program: ts.Program) { + function verifyProgramFiles(program: Program) { assert.deepEqual( program.getSourceFiles().map(f => f.fileName), ["/lib/lib.d.ts", "/project/other.ts", "/project/root.ts"] @@ -145,8 +154,8 @@ export function Component(x: Config): any;` describe("detects program upto date when new file is added to the referenced project", () => { function setup(useSourceOfProjectReferenceRedirect: (() => boolean) | undefined) { - const config1: ts.TestFSWithWatch.File = { - path: `${ts.tscWatch.projectRoot}/projects/project1/tsconfig.json`, + const config1: File = { + path: `${projectRoot}/projects/project1/tsconfig.json`, content: JSON.stringify({ compilerOptions: { module: "none", @@ -155,16 +164,16 @@ export function Component(x: Config): any;` exclude: ["temp"] }) }; - const class1: ts.TestFSWithWatch.File = { - path: `${ts.tscWatch.projectRoot}/projects/project1/class1.ts`, + const class1: File = { + path: `${projectRoot}/projects/project1/class1.ts`, content: `class class1 {}` }; - const class1Dts: ts.TestFSWithWatch.File = { - path: `${ts.tscWatch.projectRoot}/projects/project1/class1.d.ts`, + const class1Dts: File = { + path: `${projectRoot}/projects/project1/class1.d.ts`, content: `declare class class1 {}` }; - const config2: ts.TestFSWithWatch.File = { - path: `${ts.tscWatch.projectRoot}/projects/project2/tsconfig.json`, + const config2: File = { + path: `${projectRoot}/projects/project2/tsconfig.json`, content: JSON.stringify({ compilerOptions: { module: "none", @@ -175,21 +184,21 @@ export function Component(x: Config): any;` ] }) }; - const class2: ts.TestFSWithWatch.File = { - path: `${ts.tscWatch.projectRoot}/projects/project2/class2.ts`, + const class2: File = { + path: `${projectRoot}/projects/project2/class2.ts`, content: `class class2 {}` }; - const system = ts.projectSystem.createServerHost([config1, class1, class1Dts, config2, class2, ts.projectSystem.libFile]); - const result = ts.getParsedCommandLineOfConfigFile(`${ts.tscWatch.projectRoot}/projects/project2/tsconfig.json`, /*optionsToExtend*/ undefined, { + const system = createServerHost([config1, class1, class1Dts, config2, class2, libFile]); + const result = getParsedCommandLineOfConfigFile(`${projectRoot}/projects/project2/tsconfig.json`, /*optionsToExtend*/ undefined, { useCaseSensitiveFileNames: true, fileExists: path => system.fileExists(path), readFile: path => system.readFile(path), getCurrentDirectory: () => system.getCurrentDirectory(), readDirectory: (path, extensions, excludes, includes, depth) => system.readDirectory(path, extensions, excludes, includes, depth), - onUnRecoverableConfigFileDiagnostic: ts.noop, + onUnRecoverableConfigFileDiagnostic: noop, })!; - const host: ts.LanguageServiceHost = { - useCaseSensitiveFileNames: ts.returnTrue, + const host: LanguageServiceHost = { + useCaseSensitiveFileNames: returnTrue, useSourceOfProjectReferenceRedirect, getCompilationSettings: () => result.options, fileExists: path => system.fileExists(path), @@ -201,35 +210,35 @@ export function Component(x: Config): any;` }, getScriptSnapshot: path => { const text = system.readFile(path); - return text ? ts.ScriptSnapshot.fromString(text) : undefined; + return text ? ScriptSnapshot.fromString(text) : undefined; }, readDirectory: (path, extensions, excludes, includes, depth) => system.readDirectory(path, extensions, excludes, includes, depth), getCurrentDirectory: () => system.getCurrentDirectory(), - getDefaultLibFileName: () => ts.projectSystem.libFile.path, + getDefaultLibFileName: () => libFile.path, getProjectReferences: () => result.projectReferences, }; const ls = ts.createLanguageService(host); return { system, ls, class1, class1Dts, class2 }; } it("detects program upto date when new file is added to the referenced project", () => { - const { ls, system, class1, class2 } = setup(ts.returnTrue); + const { ls, system, class1, class2 } = setup(returnTrue); assert.deepEqual( ls.getProgram()!.getSourceFiles().map(f => f.fileName), - [ts.projectSystem.libFile.path, class1.path, class2.path] + [libFile.path, class1.path, class2.path] ); // Add new file to referenced project - const class3 = `${ts.tscWatch.projectRoot}/projects/project1/class3.ts`; + const class3 = `${projectRoot}/projects/project1/class3.ts`; system.writeFile(class3, `class class3 {}`); const program = ls.getProgram()!; assert.deepEqual( program.getSourceFiles().map(f => f.fileName), - [ts.projectSystem.libFile.path, class1.path, class3, class2.path] + [libFile.path, class1.path, class3, class2.path] ); // Add excluded file to referenced project - system.ensureFileOrFolder({ path: `${ts.tscWatch.projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + system.ensureFileOrFolder({ path: `${projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); assert.strictEqual(ls.getProgram(), program); // Add output from new class to referenced project - system.writeFile(`${ts.tscWatch.projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`); + system.writeFile(`${projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`); assert.strictEqual(ls.getProgram(), program); }); @@ -238,38 +247,38 @@ export function Component(x: Config): any;` const program1 = ls.getProgram()!; assert.deepEqual( program1.getSourceFiles().map(f => f.fileName), - [ts.projectSystem.libFile.path, class1Dts.path, class2.path] + [libFile.path, class1Dts.path, class2.path] ); // Add new file to referenced project - const class3 = `${ts.tscWatch.projectRoot}/projects/project1/class3.ts`; + const class3 = `${projectRoot}/projects/project1/class3.ts`; system.writeFile(class3, `class class3 {}`); assert.notStrictEqual(ls.getProgram(), program1); assert.deepEqual( ls.getProgram()!.getSourceFiles().map(f => f.fileName), - [ts.projectSystem.libFile.path, class1Dts.path, class2.path] + [libFile.path, class1Dts.path, class2.path] ); // Add class3 output - const class3Dts = `${ts.tscWatch.projectRoot}/projects/project1/class3.d.ts`; + const class3Dts = `${projectRoot}/projects/project1/class3.d.ts`; system.writeFile(class3Dts, `declare class class3 {}`); const program2 = ls.getProgram()!; assert.deepEqual( program2.getSourceFiles().map(f => f.fileName), - [ts.projectSystem.libFile.path, class1Dts.path, class3Dts, class2.path] + [libFile.path, class1Dts.path, class3Dts, class2.path] ); // Add excluded file to referenced project - system.ensureFileOrFolder({ path: `${ts.tscWatch.projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + system.ensureFileOrFolder({ path: `${projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); assert.strictEqual(ls.getProgram(), program2); // Delete output from new class to referenced project system.deleteFile(class3Dts); assert.deepEqual( ls.getProgram()!.getSourceFiles().map(f => f.fileName), - [ts.projectSystem.libFile.path, class1Dts.path, class2.path] + [libFile.path, class1Dts.path, class2.path] ); // Write output again system.writeFile(class3Dts, `declare class class3 {}`); assert.deepEqual( ls.getProgram()!.getSourceFiles().map(f => f.fileName), - [ts.projectSystem.libFile.path, class1Dts.path, class3Dts, class2.path] + [libFile.path, class1Dts.path, class3Dts, class2.path] ); }); }); diff --git a/src/testRunner/unittests/services/organizeImports.ts b/src/testRunner/unittests/services/organizeImports.ts index 39173ad22a211..65506b87d4ce7 100644 --- a/src/testRunner/unittests/services/organizeImports.ts +++ b/src/testRunner/unittests/services/organizeImports.ts @@ -1,5 +1,18 @@ -import * as Harness from "../../_namespaces/Harness"; -import * as ts from "../../_namespaces/ts"; +import { filter } from "../../../compiler/core"; +import { Comparison } from "../../../compiler/corePublic"; +import { isExportDeclaration, isImportDeclaration } from "../../../compiler/factory/nodeTests"; +import { createSourceFile } from "../../../compiler/parser"; +import { + ExportDeclaration, ExportSpecifier, Identifier, ImportClause, ImportDeclaration, ImportSpecifier, JsxEmit, + LiteralLikeNode, NamedExports, NamedImports, NamespaceImport, Node, ScriptKind, ScriptTarget, SyntaxKind, +} from "../../../compiler/types"; +import { Baseline } from "../../../harness/harnessIO"; +import { File } from "../../../harness/virtualFileSystemWithWatch"; +import { coalesceExports, coalesceImports, compareModuleSpecifiers } from "../../../services/organizeImports"; +import { applyChanges } from "../../../services/textChanges"; +import { emptyOptions, testFormatSettings } from "../../../services/types"; +import { createProjectService, createServerHost } from "../tsserver/helpers"; +import { newLineCharacter } from "./extract/helpers"; describe("unittests:: services:: organizeImports", () => { describe("Sort imports", () => { @@ -32,19 +45,19 @@ describe("unittests:: services:: organizeImports", () => { function assertSortsBefore(importString1: string, importString2: string) { const [{moduleSpecifier: moduleSpecifier1}, {moduleSpecifier: moduleSpecifier2}] = parseImports(importString1, importString2); - assert.equal(ts.OrganizeImports.compareModuleSpecifiers(moduleSpecifier1, moduleSpecifier2), ts.Comparison.LessThan); - assert.equal(ts.OrganizeImports.compareModuleSpecifiers(moduleSpecifier2, moduleSpecifier1), ts.Comparison.GreaterThan); + assert.equal(compareModuleSpecifiers(moduleSpecifier1, moduleSpecifier2), Comparison.LessThan); + assert.equal(compareModuleSpecifiers(moduleSpecifier2, moduleSpecifier1), Comparison.GreaterThan); } }); describe("Coalesce imports", () => { it("No imports", () => { - assert.isEmpty(ts.OrganizeImports.coalesceImports([])); + assert.isEmpty(coalesceImports([])); }); it("Sort specifiers - case-insensitive", () => { const sortedImports = parseImports(`import { default as M, a as n, B, y, Z as O } from "lib";`); - const actualCoalescedImports = ts.OrganizeImports.coalesceImports(sortedImports); + const actualCoalescedImports = coalesceImports(sortedImports); const expectedCoalescedImports = parseImports(`import { a as n, B, default as M, y, Z as O } from "lib";`); assertListEqual(actualCoalescedImports, expectedCoalescedImports); }); @@ -53,7 +66,7 @@ describe("unittests:: services:: organizeImports", () => { const sortedImports = parseImports( `import "lib";`, `import "lib";`); - const actualCoalescedImports = ts.OrganizeImports.coalesceImports(sortedImports); + const actualCoalescedImports = coalesceImports(sortedImports); const expectedCoalescedImports = parseImports(`import "lib";`); assertListEqual(actualCoalescedImports, expectedCoalescedImports); }); @@ -62,7 +75,7 @@ describe("unittests:: services:: organizeImports", () => { const sortedImports = parseImports( `import * as x from "lib";`, `import * as y from "lib";`); - const actualCoalescedImports = ts.OrganizeImports.coalesceImports(sortedImports); + const actualCoalescedImports = coalesceImports(sortedImports); const expectedCoalescedImports = sortedImports; assertListEqual(actualCoalescedImports, expectedCoalescedImports); }); @@ -71,7 +84,7 @@ describe("unittests:: services:: organizeImports", () => { const sortedImports = parseImports( `import x from "lib";`, `import y from "lib";`); - const actualCoalescedImports = ts.OrganizeImports.coalesceImports(sortedImports); + const actualCoalescedImports = coalesceImports(sortedImports); const expectedCoalescedImports = parseImports(`import { default as x, default as y } from "lib";`); assertListEqual(actualCoalescedImports, expectedCoalescedImports); }); @@ -80,7 +93,7 @@ describe("unittests:: services:: organizeImports", () => { const sortedImports = parseImports( `import { x } from "lib";`, `import { y as z } from "lib";`); - const actualCoalescedImports = ts.OrganizeImports.coalesceImports(sortedImports); + const actualCoalescedImports = coalesceImports(sortedImports); const expectedCoalescedImports = parseImports(`import { x, y as z } from "lib";`); assertListEqual(actualCoalescedImports, expectedCoalescedImports); }); @@ -89,7 +102,7 @@ describe("unittests:: services:: organizeImports", () => { const sortedImports = parseImports( `import "lib";`, `import * as x from "lib";`); - const actualCoalescedImports = ts.OrganizeImports.coalesceImports(sortedImports); + const actualCoalescedImports = coalesceImports(sortedImports); const expectedCoalescedImports = sortedImports; assertListEqual(actualCoalescedImports, expectedCoalescedImports); }); @@ -98,7 +111,7 @@ describe("unittests:: services:: organizeImports", () => { const sortedImports = parseImports( `import "lib";`, `import x from "lib";`); - const actualCoalescedImports = ts.OrganizeImports.coalesceImports(sortedImports); + const actualCoalescedImports = coalesceImports(sortedImports); const expectedCoalescedImports = sortedImports; assertListEqual(actualCoalescedImports, expectedCoalescedImports); }); @@ -107,7 +120,7 @@ describe("unittests:: services:: organizeImports", () => { const sortedImports = parseImports( `import "lib";`, `import { x } from "lib";`); - const actualCoalescedImports = ts.OrganizeImports.coalesceImports(sortedImports); + const actualCoalescedImports = coalesceImports(sortedImports); const expectedCoalescedImports = sortedImports; assertListEqual(actualCoalescedImports, expectedCoalescedImports); }); @@ -116,7 +129,7 @@ describe("unittests:: services:: organizeImports", () => { const sortedImports = parseImports( `import * as x from "lib";`, `import y from "lib";`); - const actualCoalescedImports = ts.OrganizeImports.coalesceImports(sortedImports); + const actualCoalescedImports = coalesceImports(sortedImports); const expectedCoalescedImports = parseImports( `import y, * as x from "lib";`); assertListEqual(actualCoalescedImports, expectedCoalescedImports); @@ -126,7 +139,7 @@ describe("unittests:: services:: organizeImports", () => { const sortedImports = parseImports( `import * as x from "lib";`, `import { y } from "lib";`); - const actualCoalescedImports = ts.OrganizeImports.coalesceImports(sortedImports); + const actualCoalescedImports = coalesceImports(sortedImports); const expectedCoalescedImports = sortedImports; assertListEqual(actualCoalescedImports, expectedCoalescedImports); }); @@ -135,7 +148,7 @@ describe("unittests:: services:: organizeImports", () => { const sortedImports = parseImports( `import x from "lib";`, `import { y } from "lib";`); - const actualCoalescedImports = ts.OrganizeImports.coalesceImports(sortedImports); + const actualCoalescedImports = coalesceImports(sortedImports); const expectedCoalescedImports = parseImports( `import x, { y } from "lib";`); assertListEqual(actualCoalescedImports, expectedCoalescedImports); @@ -151,7 +164,7 @@ describe("unittests:: services:: organizeImports", () => { `import * as x from "lib";`, `import z from "lib";`, `import { a } from "lib";`); - const actualCoalescedImports = ts.OrganizeImports.coalesceImports(sortedImports); + const actualCoalescedImports = coalesceImports(sortedImports); const expectedCoalescedImports = parseImports( `import "lib";`, `import * as x from "lib";`, @@ -166,7 +179,7 @@ describe("unittests:: services:: organizeImports", () => { `import * as x from "lib";`, `import * as y from "lib";`, `import z from "lib";`); - const actualCoalescedImports = ts.OrganizeImports.coalesceImports(sortedImports); + const actualCoalescedImports = coalesceImports(sortedImports); const expectedCoalescedImports = sortedImports; assertListEqual(actualCoalescedImports, expectedCoalescedImports); }); @@ -176,7 +189,7 @@ describe("unittests:: services:: organizeImports", () => { `import type { x } from "lib";`, `import type { y } from "lib";`, `import { z } from "lib";`); - const actualCoalescedImports = ts.OrganizeImports.coalesceImports(sortedImports); + const actualCoalescedImports = coalesceImports(sortedImports); const expectedCoalescedImports = parseImports( `import { z } from "lib";`, `import type { x, y } from "lib";`); @@ -190,7 +203,7 @@ describe("unittests:: services:: organizeImports", () => { `import type z from "lib";`); // Default import could be rewritten as a named import to combine with `x`, // but seems of debatable merit. - const actualCoalescedImports = ts.OrganizeImports.coalesceImports(sortedImports); + const actualCoalescedImports = coalesceImports(sortedImports); const expectedCoalescedImports = actualCoalescedImports; assertListEqual(actualCoalescedImports, expectedCoalescedImports); }); @@ -198,19 +211,19 @@ describe("unittests:: services:: organizeImports", () => { describe("Coalesce exports", () => { it("No exports", () => { - assert.isEmpty(ts.OrganizeImports.coalesceExports([])); + assert.isEmpty(coalesceExports([])); }); it("Sort specifiers - case-insensitive", () => { const sortedExports = parseExports(`export { default as M, a as n, B, y, Z as O } from "lib";`); - const actualCoalescedExports = ts.OrganizeImports.coalesceExports(sortedExports); + const actualCoalescedExports = coalesceExports(sortedExports); const expectedCoalescedExports = parseExports(`export { a as n, B, default as M, y, Z as O } from "lib";`); assertListEqual(actualCoalescedExports, expectedCoalescedExports); }); it("Sort specifiers - type-only", () => { const sortedImports = parseImports(`import { type z, y, type x, c, type b, a } from "lib";`); - const actualCoalescedImports = ts.OrganizeImports.coalesceImports(sortedImports); + const actualCoalescedImports = coalesceImports(sortedImports); const expectedCoalescedImports = parseImports(`import { a, c, y, type b, type x, type z } from "lib";`); assertListEqual(actualCoalescedImports, expectedCoalescedImports); }); @@ -219,7 +232,7 @@ describe("unittests:: services:: organizeImports", () => { const sortedExports = parseExports( `export * from "lib";`, `export * from "lib";`); - const actualCoalescedExports = ts.OrganizeImports.coalesceExports(sortedExports); + const actualCoalescedExports = coalesceExports(sortedExports); const expectedCoalescedExports = parseExports(`export * from "lib";`); assertListEqual(actualCoalescedExports, expectedCoalescedExports); }); @@ -228,7 +241,7 @@ describe("unittests:: services:: organizeImports", () => { const sortedExports = parseExports( `export { x };`, `export { y as z };`); - const actualCoalescedExports = ts.OrganizeImports.coalesceExports(sortedExports); + const actualCoalescedExports = coalesceExports(sortedExports); const expectedCoalescedExports = parseExports(`export { x, y as z };`); assertListEqual(actualCoalescedExports, expectedCoalescedExports); }); @@ -237,7 +250,7 @@ describe("unittests:: services:: organizeImports", () => { const sortedExports = parseExports( `export { x } from "lib";`, `export { y as z } from "lib";`); - const actualCoalescedExports = ts.OrganizeImports.coalesceExports(sortedExports); + const actualCoalescedExports = coalesceExports(sortedExports); const expectedCoalescedExports = parseExports(`export { x, y as z } from "lib";`); assertListEqual(actualCoalescedExports, expectedCoalescedExports); }); @@ -246,7 +259,7 @@ describe("unittests:: services:: organizeImports", () => { const sortedExports = parseExports( `export * from "lib";`, `export { y } from "lib";`); - const actualCoalescedExports = ts.OrganizeImports.coalesceExports(sortedExports); + const actualCoalescedExports = coalesceExports(sortedExports); const expectedCoalescedExports = sortedExports; assertListEqual(actualCoalescedExports, expectedCoalescedExports); }); @@ -256,7 +269,7 @@ describe("unittests:: services:: organizeImports", () => { `export { x };`, `export { y as w, z as default };`, `export { w as q };`); - const actualCoalescedExports = ts.OrganizeImports.coalesceExports(sortedExports); + const actualCoalescedExports = coalesceExports(sortedExports); const expectedCoalescedExports = parseExports( `export { w as q, x, y as w, z as default };`); assertListEqual(actualCoalescedExports, expectedCoalescedExports); @@ -267,7 +280,7 @@ describe("unittests:: services:: organizeImports", () => { `export { x as a, y } from "lib";`, `export * from "lib";`, `export { z as b } from "lib";`); - const actualCoalescedExports = ts.OrganizeImports.coalesceExports(sortedExports); + const actualCoalescedExports = coalesceExports(sortedExports); const expectedCoalescedExports = parseExports( `export * from "lib";`, `export { x as a, y, z as b } from "lib";`); @@ -278,7 +291,7 @@ describe("unittests:: services:: organizeImports", () => { const sortedExports = parseExports( `export { x };`, `export type { y };`); - const actualCoalescedExports = ts.OrganizeImports.coalesceExports(sortedExports); + const actualCoalescedExports = coalesceExports(sortedExports); const expectedCoalescedExports = sortedExports; assertListEqual(actualCoalescedExports, expectedCoalescedExports); }); @@ -287,7 +300,7 @@ describe("unittests:: services:: organizeImports", () => { const sortedExports = parseExports( `export type { x };`, `export type { y };`); - const actualCoalescedExports = ts.OrganizeImports.coalesceExports(sortedExports); + const actualCoalescedExports = coalesceExports(sortedExports); const expectedCoalescedExports = parseExports( `export type { x, y };`); assertListEqual(actualCoalescedExports, expectedCoalescedExports); @@ -323,7 +336,7 @@ export const Other = 1; content: "function F() { }", }; const languageService = makeLanguageService(testFile); - const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, ts.testFormatSettings, ts.emptyOptions); + const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatSettings, emptyOptions); assert.isEmpty(changes); }); @@ -333,7 +346,7 @@ export const Other = 1; content: "declare module '*';", }; const languageService = makeLanguageService(testFile); - const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, ts.testFormatSettings, ts.emptyOptions); + const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatSettings, emptyOptions); assert.isEmpty(changes); }); @@ -343,7 +356,7 @@ export const Other = 1; content: `import { f } from 'foo';\nf();` }; const languageService = makeLanguageService(testFile); - const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, ts.testFormatSettings, ts.emptyOptions); + const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatSettings, emptyOptions); assert.isEmpty(changes); }); @@ -459,7 +472,7 @@ D; content: `import { f } from 'foo';\nf();` }; const languageService = makeLanguageService(testFile); - const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, ts.testFormatSettings, ts.emptyOptions); + const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatSettings, emptyOptions); assert.isEmpty(changes); }); @@ -483,7 +496,7 @@ import { } from "lib"; `, }; const languageService = makeLanguageService(testFile); - const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, ts.testFormatSettings, ts.emptyOptions); + const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatSettings, emptyOptions); assert.isEmpty(changes); }); @@ -528,7 +541,7 @@ const o = { x }; ` }; const languageService = makeLanguageService(testFile); - const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, ts.testFormatSettings, ts.emptyOptions); + const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatSettings, emptyOptions); assert.isEmpty(changes); }); @@ -541,7 +554,7 @@ export { x }; ` }; const languageService = makeLanguageService(testFile); - const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, ts.testFormatSettings, ts.emptyOptions); + const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatSettings, emptyOptions); assert.isEmpty(changes); }); @@ -1004,54 +1017,54 @@ export * from "lib"; libFile); }); - function testOrganizeExports(testName: string, testFile: ts.TestFSWithWatch.File, ...otherFiles: ts.TestFSWithWatch.File[]) { + function testOrganizeExports(testName: string, testFile: File, ...otherFiles: File[]) { testOrganizeImports(`${testName}.exports`, /*skipDestructiveCodeActions*/ true, testFile, ...otherFiles); } - function testOrganizeImports(testName: string, skipDestructiveCodeActions: boolean, testFile: ts.TestFSWithWatch.File, ...otherFiles: ts.TestFSWithWatch.File[]) { + function testOrganizeImports(testName: string, skipDestructiveCodeActions: boolean, testFile: File, ...otherFiles: File[]) { it(testName, () => runBaseline(`organizeImports/${testName}.ts`, skipDestructiveCodeActions, testFile, ...otherFiles)); } - function runBaseline(baselinePath: string, skipDestructiveCodeActions: boolean, testFile: ts.TestFSWithWatch.File, ...otherFiles: ts.TestFSWithWatch.File[]) { + function runBaseline(baselinePath: string, skipDestructiveCodeActions: boolean, testFile: File, ...otherFiles: File[]) { const { path: testPath, content: testContent } = testFile; const languageService = makeLanguageService(testFile, ...otherFiles); - const changes = languageService.organizeImports({ skipDestructiveCodeActions, type: "file", fileName: testPath }, ts.testFormatSettings, ts.emptyOptions); + const changes = languageService.organizeImports({ skipDestructiveCodeActions, type: "file", fileName: testPath }, testFormatSettings, emptyOptions); assert.equal(changes.length, 1); assert.equal(changes[0].fileName, testPath); - const newText = ts.textChanges.applyChanges(testContent, changes[0].textChanges); - Harness.Baseline.runBaseline(baselinePath, [ + const newText = applyChanges(testContent, changes[0].textChanges); + Baseline.runBaseline(baselinePath, [ "// ==ORIGINAL==", testContent, "// ==ORGANIZED==", newText, - ].join(ts.newLineCharacter)); + ].join(newLineCharacter)); } - function makeLanguageService(...files: ts.TestFSWithWatch.File[]) { - const host = ts.projectSystem.createServerHost(files); - const projectService = ts.projectSystem.createProjectService(host, { useSingleInferredProject: true }); - projectService.setCompilerOptionsForInferredProjects({ jsx: files.some(f => f.path.endsWith("x")) ? ts.JsxEmit.React : ts.JsxEmit.None }); + function makeLanguageService(...files: File[]) { + const host = createServerHost(files); + const projectService = createProjectService(host, { useSingleInferredProject: true }); + projectService.setCompilerOptionsForInferredProjects({ jsx: files.some(f => f.path.endsWith("x")) ? JsxEmit.React : JsxEmit.None }); files.forEach(f => projectService.openClientFile(f.path)); return projectService.inferredProjects[0].getLanguageService(); } }); - function parseImports(...importStrings: string[]): readonly ts.ImportDeclaration[] { - const sourceFile = ts.createSourceFile("a.ts", importStrings.join("\n"), ts.ScriptTarget.ES2015, /*setParentNodes*/ true, ts.ScriptKind.TS); - const imports = ts.filter(sourceFile.statements, ts.isImportDeclaration); + function parseImports(...importStrings: string[]): readonly ImportDeclaration[] { + const sourceFile = createSourceFile("a.ts", importStrings.join("\n"), ScriptTarget.ES2015, /*setParentNodes*/ true, ScriptKind.TS); + const imports = filter(sourceFile.statements, isImportDeclaration); assert.equal(imports.length, importStrings.length); return imports; } - function parseExports(...exportStrings: string[]): readonly ts.ExportDeclaration[] { - const sourceFile = ts.createSourceFile("a.ts", exportStrings.join("\n"), ts.ScriptTarget.ES2015, /*setParentNodes*/ true, ts.ScriptKind.TS); - const exports = ts.filter(sourceFile.statements, ts.isExportDeclaration); + function parseExports(...exportStrings: string[]): readonly ExportDeclaration[] { + const sourceFile = createSourceFile("a.ts", exportStrings.join("\n"), ScriptTarget.ES2015, /*setParentNodes*/ true, ScriptKind.TS); + const exports = filter(sourceFile.statements, isExportDeclaration); assert.equal(exports.length, exportStrings.length); return exports; } - function assertEqual(node1?: ts.Node, node2?: ts.Node) { + function assertEqual(node1?: Node, node2?: Node) { if (node1 === undefined) { assert.isUndefined(node2); return; @@ -1064,60 +1077,60 @@ export * from "lib"; assert.equal(node1.kind, node2.kind); switch (node1.kind) { - case ts.SyntaxKind.ImportDeclaration: - const decl1 = node1 as ts.ImportDeclaration; - const decl2 = node2 as ts.ImportDeclaration; + case SyntaxKind.ImportDeclaration: + const decl1 = node1 as ImportDeclaration; + const decl2 = node2 as ImportDeclaration; assertEqual(decl1.importClause, decl2.importClause); assertEqual(decl1.moduleSpecifier, decl2.moduleSpecifier); break; - case ts.SyntaxKind.ImportClause: - const clause1 = node1 as ts.ImportClause; - const clause2 = node2 as ts.ImportClause; + case SyntaxKind.ImportClause: + const clause1 = node1 as ImportClause; + const clause2 = node2 as ImportClause; assertEqual(clause1.name, clause2.name); assertEqual(clause1.namedBindings, clause2.namedBindings); break; - case ts.SyntaxKind.NamespaceImport: - const nsi1 = node1 as ts.NamespaceImport; - const nsi2 = node2 as ts.NamespaceImport; + case SyntaxKind.NamespaceImport: + const nsi1 = node1 as NamespaceImport; + const nsi2 = node2 as NamespaceImport; assertEqual(nsi1.name, nsi2.name); break; - case ts.SyntaxKind.NamedImports: - const ni1 = node1 as ts.NamedImports; - const ni2 = node2 as ts.NamedImports; + case SyntaxKind.NamedImports: + const ni1 = node1 as NamedImports; + const ni2 = node2 as NamedImports; assertListEqual(ni1.elements, ni2.elements); break; - case ts.SyntaxKind.ImportSpecifier: - const is1 = node1 as ts.ImportSpecifier; - const is2 = node2 as ts.ImportSpecifier; + case SyntaxKind.ImportSpecifier: + const is1 = node1 as ImportSpecifier; + const is2 = node2 as ImportSpecifier; assertEqual(is1.name, is2.name); assertEqual(is1.propertyName, is2.propertyName); break; - case ts.SyntaxKind.ExportDeclaration: - const ed1 = node1 as ts.ExportDeclaration; - const ed2 = node2 as ts.ExportDeclaration; + case SyntaxKind.ExportDeclaration: + const ed1 = node1 as ExportDeclaration; + const ed2 = node2 as ExportDeclaration; assertEqual(ed1.exportClause, ed2.exportClause); assertEqual(ed1.moduleSpecifier, ed2.moduleSpecifier); break; - case ts.SyntaxKind.NamedExports: - const ne1 = node1 as ts.NamedExports; - const ne2 = node2 as ts.NamedExports; + case SyntaxKind.NamedExports: + const ne1 = node1 as NamedExports; + const ne2 = node2 as NamedExports; assertListEqual(ne1.elements, ne2.elements); break; - case ts.SyntaxKind.ExportSpecifier: - const es1 = node1 as ts.ExportSpecifier; - const es2 = node2 as ts.ExportSpecifier; + case SyntaxKind.ExportSpecifier: + const es1 = node1 as ExportSpecifier; + const es2 = node2 as ExportSpecifier; assertEqual(es1.name, es2.name); assertEqual(es1.propertyName, es2.propertyName); break; - case ts.SyntaxKind.Identifier: - const id1 = node1 as ts.Identifier; - const id2 = node2 as ts.Identifier; + case SyntaxKind.Identifier: + const id1 = node1 as Identifier; + const id2 = node2 as Identifier; assert.equal(id1.text, id2.text); break; - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - const sl1 = node1 as ts.LiteralLikeNode; - const sl2 = node2 as ts.LiteralLikeNode; + case SyntaxKind.StringLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + const sl1 = node1 as LiteralLikeNode; + const sl2 = node2 as LiteralLikeNode; assert.equal(sl1.text, sl2.text); break; default: @@ -1126,7 +1139,7 @@ export * from "lib"; } } - function assertListEqual(list1: readonly ts.Node[], list2: readonly ts.Node[]) { + function assertListEqual(list1: readonly Node[], list2: readonly Node[]) { if (list1 === undefined || list2 === undefined) { assert.isUndefined(list1); assert.isUndefined(list2); diff --git a/src/testRunner/unittests/services/patternMatcher.ts b/src/testRunner/unittests/services/patternMatcher.ts index ff54d9a527cc4..8c1444ced367f 100644 --- a/src/testRunner/unittests/services/patternMatcher.ts +++ b/src/testRunner/unittests/services/patternMatcher.ts @@ -1,3 +1,5 @@ +import { TextSpan } from "../../../compiler/types"; +import { createPatternMatcher, PatternMatch, PatternMatchKind } from "../../../services/patternMatcher"; import * as ts from "../../_namespaces/ts"; describe("unittests:: services:: PatternMatcher", () => { @@ -95,27 +97,27 @@ describe("unittests:: services:: PatternMatcher", () => { describe("SingleWordPattern", () => { it("PreferCaseSensitiveExact", () => { - assertSegmentMatch("Foo", "Foo", { kind: ts.PatternMatchKind.exact, isCaseSensitive: true }); + assertSegmentMatch("Foo", "Foo", { kind: PatternMatchKind.exact, isCaseSensitive: true }); }); it("PreferCaseSensitiveExactInsensitive", () => { - assertSegmentMatch("foo", "Foo", { kind: ts.PatternMatchKind.exact, isCaseSensitive: false }); + assertSegmentMatch("foo", "Foo", { kind: PatternMatchKind.exact, isCaseSensitive: false }); }); it("PreferCaseSensitivePrefix", () => { - assertSegmentMatch("Foo", "Fo", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true }); + assertSegmentMatch("Foo", "Fo", { kind: PatternMatchKind.prefix, isCaseSensitive: true }); }); it("PreferCaseSensitivePrefixCaseInsensitive", () => { - assertSegmentMatch("Foo", "fo", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: false }); + assertSegmentMatch("Foo", "fo", { kind: PatternMatchKind.prefix, isCaseSensitive: false }); }); it("PreferCaseSensitiveCamelCaseMatchSimple", () => { - assertSegmentMatch("FogBar", "FB", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true }); + assertSegmentMatch("FogBar", "FB", { kind: PatternMatchKind.camelCase, isCaseSensitive: true }); }); it("PreferCaseSensitiveCamelCaseMatchPartialPattern", () => { - assertSegmentMatch("FogBar", "FoB", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true }); + assertSegmentMatch("FogBar", "FoB", { kind: PatternMatchKind.camelCase, isCaseSensitive: true }); }); it("PreferCaseSensitiveCamelCaseMatchToLongPattern1", () => { @@ -135,35 +137,35 @@ describe("unittests:: services:: PatternMatcher", () => { }); it("TwoUppercaseCharacters", () => { - assertSegmentMatch("SimpleUIElement", "SiUI", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true }); + assertSegmentMatch("SimpleUIElement", "SiUI", { kind: PatternMatchKind.camelCase, isCaseSensitive: true }); }); it("PreferCaseSensitiveLowercasePattern", () => { - assertSegmentMatch("FogBar", "b", { kind: ts.PatternMatchKind.substring, isCaseSensitive: false }); + assertSegmentMatch("FogBar", "b", { kind: PatternMatchKind.substring, isCaseSensitive: false }); }); it("PreferCaseSensitiveLowercasePattern2", () => { - assertSegmentMatch("FogBar", "fB", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: false }); + assertSegmentMatch("FogBar", "fB", { kind: PatternMatchKind.camelCase, isCaseSensitive: false }); }); it("PreferCaseSensitiveTryUnderscoredName", () => { - assertSegmentMatch("_fogBar", "_fB", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true }); + assertSegmentMatch("_fogBar", "_fB", { kind: PatternMatchKind.camelCase, isCaseSensitive: true }); }); it("PreferCaseSensitiveTryUnderscoredName2", () => { - assertSegmentMatch("_fogBar", "fB", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true }); + assertSegmentMatch("_fogBar", "fB", { kind: PatternMatchKind.camelCase, isCaseSensitive: true }); }); it("PreferCaseSensitiveTryUnderscoredNameInsensitive", () => { - assertSegmentMatch("_FogBar", "_fB", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: false }); + assertSegmentMatch("_FogBar", "_fB", { kind: PatternMatchKind.camelCase, isCaseSensitive: false }); }); it("PreferCaseSensitiveMiddleUnderscore", () => { - assertSegmentMatch("Fog_Bar", "FB", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true }); + assertSegmentMatch("Fog_Bar", "FB", { kind: PatternMatchKind.camelCase, isCaseSensitive: true }); }); it("PreferCaseSensitiveMiddleUnderscore2", () => { - assertSegmentMatch("Fog_Bar", "F_B", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true }); + assertSegmentMatch("Fog_Bar", "F_B", { kind: PatternMatchKind.camelCase, isCaseSensitive: true }); }); it("PreferCaseSensitiveMiddleUnderscore3", () => { @@ -171,15 +173,15 @@ describe("unittests:: services:: PatternMatcher", () => { }); it("PreferCaseSensitiveMiddleUnderscore4", () => { - assertSegmentMatch("Fog_Bar", "f_B", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: false }); + assertSegmentMatch("Fog_Bar", "f_B", { kind: PatternMatchKind.camelCase, isCaseSensitive: false }); }); it("PreferCaseSensitiveMiddleUnderscore5", () => { - assertSegmentMatch("Fog_Bar", "F_b", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: false }); + assertSegmentMatch("Fog_Bar", "F_b", { kind: PatternMatchKind.camelCase, isCaseSensitive: false }); }); it("AllLowerPattern1", () => { - assertSegmentMatch("FogBarChangedEventArgs", "changedeventargs", { kind: ts.PatternMatchKind.substring, isCaseSensitive: false }); + assertSegmentMatch("FogBarChangedEventArgs", "changedeventargs", { kind: PatternMatchKind.substring, isCaseSensitive: false }); }); it("AllLowerPattern2", () => { @@ -187,7 +189,7 @@ describe("unittests:: services:: PatternMatcher", () => { }); it("AllLowerPattern3", () => { - assertSegmentMatch("ABCDEFGH", "bcd", { kind: ts.PatternMatchKind.substring, isCaseSensitive: false }); + assertSegmentMatch("ABCDEFGH", "bcd", { kind: PatternMatchKind.substring, isCaseSensitive: false }); }); it("AllLowerPattern4", () => { @@ -197,55 +199,55 @@ describe("unittests:: services:: PatternMatcher", () => { describe("MultiWordPattern", () => { it("ExactWithLowercase", () => { - assertSegmentMatch("AddMetadataReference", "addmetadatareference", { kind: ts.PatternMatchKind.exact, isCaseSensitive: false }); + assertSegmentMatch("AddMetadataReference", "addmetadatareference", { kind: PatternMatchKind.exact, isCaseSensitive: false }); }); it("SingleLowercasedSearchWord1", () => { - assertSegmentMatch("AddMetadataReference", "add", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: false }); + assertSegmentMatch("AddMetadataReference", "add", { kind: PatternMatchKind.prefix, isCaseSensitive: false }); }); it("SingleLowercasedSearchWord2", () => { - assertSegmentMatch("AddMetadataReference", "metadata", { kind: ts.PatternMatchKind.substring, isCaseSensitive: false }); + assertSegmentMatch("AddMetadataReference", "metadata", { kind: PatternMatchKind.substring, isCaseSensitive: false }); }); it("SingleUppercaseSearchWord1", () => { - assertSegmentMatch("AddMetadataReference", "Add", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "Add", { kind: PatternMatchKind.prefix, isCaseSensitive: true }); }); it("SingleUppercaseSearchWord2", () => { - assertSegmentMatch("AddMetadataReference", "Metadata", { kind: ts.PatternMatchKind.substring, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "Metadata", { kind: PatternMatchKind.substring, isCaseSensitive: true }); }); it("SingleUppercaseSearchLetter1", () => { - assertSegmentMatch("AddMetadataReference", "A", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "A", { kind: PatternMatchKind.prefix, isCaseSensitive: true }); }); it("SingleUppercaseSearchLetter2", () => { - assertSegmentMatch("AddMetadataReference", "M", { kind: ts.PatternMatchKind.substring, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "M", { kind: PatternMatchKind.substring, isCaseSensitive: true }); }); it("TwoLowercaseWords0", () => { - assertSegmentMatch("AddMetadataReference", "add metadata", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: false }); + assertSegmentMatch("AddMetadataReference", "add metadata", { kind: PatternMatchKind.prefix, isCaseSensitive: false }); }); it("TwoLowercaseWords1", () => { - assertSegmentMatch("AddMetadataReference", "A M", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "A M", { kind: PatternMatchKind.prefix, isCaseSensitive: true }); }); it("TwoLowercaseWords2", () => { - assertSegmentMatch("AddMetadataReference", "AM", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "AM", { kind: PatternMatchKind.camelCase, isCaseSensitive: true }); }); it("TwoLowercaseWords3", () => { - assertSegmentMatch("AddMetadataReference", "ref Metadata", { kind: ts.PatternMatchKind.substring, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "ref Metadata", { kind: PatternMatchKind.substring, isCaseSensitive: true }); }); it("TwoLowercaseWords4", () => { - assertSegmentMatch("AddMetadataReference", "ref M", { kind: ts.PatternMatchKind.substring, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "ref M", { kind: PatternMatchKind.substring, isCaseSensitive: true }); }); it("MixedCamelCase", () => { - assertSegmentMatch("AddMetadataReference", "AMRe", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "AMRe", { kind: PatternMatchKind.camelCase, isCaseSensitive: true }); }); it("BlankPattern", () => { @@ -257,15 +259,15 @@ describe("unittests:: services:: PatternMatcher", () => { }); it("EachWordSeparately1", () => { - assertSegmentMatch("AddMetadataReference", "add Meta", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: false }); + assertSegmentMatch("AddMetadataReference", "add Meta", { kind: PatternMatchKind.prefix, isCaseSensitive: false }); }); it("EachWordSeparately2", () => { - assertSegmentMatch("AddMetadataReference", "Add meta", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "Add meta", { kind: PatternMatchKind.prefix, isCaseSensitive: true }); }); it("EachWordSeparately3", () => { - assertSegmentMatch("AddMetadataReference", "Add Meta", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true }); + assertSegmentMatch("AddMetadataReference", "Add Meta", { kind: PatternMatchKind.prefix, isCaseSensitive: true }); }); it("MixedCasing", () => { @@ -277,7 +279,7 @@ describe("unittests:: services:: PatternMatcher", () => { }); it("AsteriskSplit", () => { - assertSegmentMatch("GetKeyWord", "K*W", { kind: ts.PatternMatchKind.substring, isCaseSensitive: true }); + assertSegmentMatch("GetKeyWord", "K*W", { kind: PatternMatchKind.substring, isCaseSensitive: true }); }); it("LowercaseSubstring1", () => { @@ -285,13 +287,13 @@ describe("unittests:: services:: PatternMatcher", () => { }); it("LowercaseSubstring2", () => { - assertSegmentMatch("FooAttribute", "a", { kind: ts.PatternMatchKind.substring, isCaseSensitive: false }); + assertSegmentMatch("FooAttribute", "a", { kind: PatternMatchKind.substring, isCaseSensitive: false }); }); }); describe("DottedPattern", () => { it("DottedPattern1", () => { - assertFullMatch("Foo.Bar.Baz", "Quux", "B.Q", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true }); + assertFullMatch("Foo.Bar.Baz", "Quux", "B.Q", { kind: PatternMatchKind.prefix, isCaseSensitive: true }); }); it("DottedPattern2", () => { @@ -299,15 +301,15 @@ describe("unittests:: services:: PatternMatcher", () => { }); it("DottedPattern3", () => { - assertFullMatch("Foo.Bar.Baz", "Quux", "B.B.Q", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true }); + assertFullMatch("Foo.Bar.Baz", "Quux", "B.B.Q", { kind: PatternMatchKind.prefix, isCaseSensitive: true }); }); it("DottedPattern4", () => { - assertFullMatch("Foo.Bar.Baz", "Quux", "Baz.Quux", { kind: ts.PatternMatchKind.exact, isCaseSensitive: true }); + assertFullMatch("Foo.Bar.Baz", "Quux", "Baz.Quux", { kind: PatternMatchKind.exact, isCaseSensitive: true }); }); it("DottedPattern5", () => { - assertFullMatch("Foo.Bar.Baz", "Quux", "F.B.B.Quux", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true }); + assertFullMatch("Foo.Bar.Baz", "Quux", "F.B.B.Quux", { kind: PatternMatchKind.prefix, isCaseSensitive: true }); }); it("DottedPattern6", () => { @@ -315,24 +317,24 @@ describe("unittests:: services:: PatternMatcher", () => { }); it("DottedPattern7", () => { - assertSegmentMatch("UIElement", "UIElement", { kind: ts.PatternMatchKind.exact, isCaseSensitive: true }); + assertSegmentMatch("UIElement", "UIElement", { kind: PatternMatchKind.exact, isCaseSensitive: true }); assertSegmentMatch("GetKeyword", "UIElement", undefined); }); }); - function assertSegmentMatch(candidate: string, pattern: string, expected: ts.PatternMatch | undefined): void { - assert.deepEqual(ts.createPatternMatcher(pattern)!.getMatchForLastSegmentOfPattern(candidate), expected); + function assertSegmentMatch(candidate: string, pattern: string, expected: PatternMatch | undefined): void { + assert.deepEqual(createPatternMatcher(pattern)!.getMatchForLastSegmentOfPattern(candidate), expected); } function assertInvalidPattern(pattern: string) { - assert.equal(ts.createPatternMatcher(pattern), undefined); + assert.equal(createPatternMatcher(pattern), undefined); } - function assertFullMatch(dottedContainer: string, candidate: string, pattern: string, expected: ts.PatternMatch | undefined): void { - assert.deepEqual(ts.createPatternMatcher(pattern)!.getFullMatch(dottedContainer.split("."), candidate), expected); + function assertFullMatch(dottedContainer: string, candidate: string, pattern: string, expected: PatternMatch | undefined): void { + assert.deepEqual(createPatternMatcher(pattern)!.getFullMatch(dottedContainer.split("."), candidate), expected); } - function spanListToSubstrings(identifier: string, spans: ts.TextSpan[]) { + function spanListToSubstrings(identifier: string, spans: TextSpan[]) { return spans.map(s => identifier.substr(s.start, s.length)); } diff --git a/src/testRunner/unittests/services/preProcessFile.ts b/src/testRunner/unittests/services/preProcessFile.ts index 43997dc8b8f0d..04c186d69ec4a 100644 --- a/src/testRunner/unittests/services/preProcessFile.ts +++ b/src/testRunner/unittests/services/preProcessFile.ts @@ -1,8 +1,10 @@ -import * as ts from "../../_namespaces/ts"; +import { FileReference } from "../../../compiler/types"; +import { preProcessFile } from "../../../services/preProcess"; +import { PreProcessedFileInfo } from "../../../services/types"; describe("unittests:: services:: PreProcessFile:", () => { - function test(sourceText: string, readImportFile: boolean, detectJavaScriptImports: boolean, expectedPreProcess: ts.PreProcessedFileInfo): void { - const resultPreProcess = ts.preProcessFile(sourceText, readImportFile, detectJavaScriptImports); + function test(sourceText: string, readImportFile: boolean, detectJavaScriptImports: boolean, expectedPreProcess: PreProcessedFileInfo): void { + const resultPreProcess = preProcessFile(sourceText, readImportFile, detectJavaScriptImports); assert.equal(resultPreProcess.isLibFile, expectedPreProcess.isLibFile, "Pre-processed file has different value for isLibFile. Expected: " + expectedPreProcess.isLibFile + ". Actual: " + resultPreProcess.isLibFile); @@ -14,7 +16,7 @@ describe("unittests:: services:: PreProcessFile:", () => { assert.deepEqual(resultPreProcess.ambientExternalModules, expectedPreProcess.ambientExternalModules); } - function checkFileReferenceList(kind: string, expected: ts.FileReference[], actual: ts.FileReference[]) { + function checkFileReferenceList(kind: string, expected: FileReference[], actual: FileReference[]) { if (expected === actual) { return; } @@ -29,7 +31,7 @@ describe("unittests:: services:: PreProcessFile:", () => { { referencedFiles: [{ fileName: "refFile1.ts", pos: 22, end: 33 }, { fileName: "refFile2.ts", pos: 59, end: 70 }, { fileName: "refFile3.ts", pos: 94, end: 105 }, { fileName: "..\\refFile4d.ts", pos: 131, end: 146 }], - importedFiles: [] as ts.FileReference[], + importedFiles: [] as FileReference[], typeReferenceDirectives: [], libReferenceDirectives: [], ambientExternalModules: undefined, @@ -42,8 +44,8 @@ describe("unittests:: services:: PreProcessFile:", () => { /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { - referencedFiles: [] as ts.FileReference[], - importedFiles: [] as ts.FileReference[], + referencedFiles: [] as FileReference[], + importedFiles: [] as FileReference[], typeReferenceDirectives: [], libReferenceDirectives: [], ambientExternalModules: undefined, @@ -56,8 +58,8 @@ describe("unittests:: services:: PreProcessFile:", () => { /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { - referencedFiles: [] as ts.FileReference[], - importedFiles: [] as ts.FileReference[], + referencedFiles: [] as FileReference[], + importedFiles: [] as FileReference[], typeReferenceDirectives: [], libReferenceDirectives: [], ambientExternalModules: undefined, @@ -70,8 +72,8 @@ describe("unittests:: services:: PreProcessFile:", () => { /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { - referencedFiles: [] as ts.FileReference[], - importedFiles: [] as ts.FileReference[], + referencedFiles: [] as FileReference[], + importedFiles: [] as FileReference[], typeReferenceDirectives: [], libReferenceDirectives: [], ambientExternalModules: undefined, @@ -84,7 +86,7 @@ describe("unittests:: services:: PreProcessFile:", () => { /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { - referencedFiles: [] as ts.FileReference[], + referencedFiles: [] as FileReference[], typeReferenceDirectives: [], libReferenceDirectives: [], importedFiles: [{ fileName: "r1.ts", pos: 20, end: 25 }, { fileName: "r2.ts", pos: 49, end: 54 }, { fileName: "r3.ts", pos: 78, end: 83 }, @@ -99,10 +101,10 @@ describe("unittests:: services:: PreProcessFile:", () => { /*readImportFile*/ false, /*detectJavaScriptImports*/ false, { - referencedFiles: [] as ts.FileReference[], + referencedFiles: [] as FileReference[], typeReferenceDirectives: [], libReferenceDirectives: [], - importedFiles: [] as ts.FileReference[], + importedFiles: [] as FileReference[], ambientExternalModules: undefined, isLibFile: false }); @@ -113,7 +115,7 @@ describe("unittests:: services:: PreProcessFile:", () => { /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { - referencedFiles: [] as ts.FileReference[], + referencedFiles: [] as FileReference[], typeReferenceDirectives: [], libReferenceDirectives: [], importedFiles: [{ fileName: "r3.ts", pos: 73, end: 78 }], @@ -387,7 +389,7 @@ describe("unittests:: services:: PreProcessFile:", () => { /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { - referencedFiles: [] as ts.FileReference[], + referencedFiles: [] as FileReference[], typeReferenceDirectives: [], libReferenceDirectives: [], importedFiles: [ @@ -417,7 +419,7 @@ describe("unittests:: services:: PreProcessFile:", () => { /*readImportFile*/ true, /*detectJavaScriptImports*/ false, { - referencedFiles: [] as ts.FileReference[], + referencedFiles: [] as FileReference[], typeReferenceDirectives: [], libReferenceDirectives: [], importedFiles: [ diff --git a/src/testRunner/unittests/services/textChanges.ts b/src/testRunner/unittests/services/textChanges.ts index 0ee4a3364c1ff..4ce51c24752e0 100644 --- a/src/testRunner/unittests/services/textChanges.ts +++ b/src/testRunner/unittests/services/textChanges.ts @@ -1,62 +1,80 @@ -import * as Harness from "../../_namespaces/Harness"; -import * as ts from "../../_namespaces/ts"; +import { cast, emptyArray, find, forEach, isArray, last, zipWith } from "../../../compiler/core"; +import { Debug } from "../../../compiler/debug"; +import { factory } from "../../../compiler/factory/nodeFactory"; +import { + isConstructorDeclaration, isIdentifier, isVariableDeclaration, isVariableStatement, +} from "../../../compiler/factory/nodeTests"; +import { createSourceFile, forEachChild } from "../../../compiler/parser"; +import { + ClassDeclaration, ClassElement, ConstructorDeclaration, FunctionDeclaration, NewLineKind, Node, NodeArray, + ScriptTarget, SourceFile, SyntaxKind, VariableDeclaration, VariableStatement, +} from "../../../compiler/types"; +import { getNewLineCharacter } from "../../../compiler/utilities"; +import { isDeclaration } from "../../../compiler/utilitiesPublic"; +import { Baseline } from "../../../harness/harnessIO"; +import { textChanges } from "../../../services/_namespaces/ts"; +import { FormatContext } from "../../../services/formatting/formatting"; +import { getFormatContext } from "../../../services/formatting/rulesMap"; +import { applyChanges, ChangeTracker, LeadingTriviaOption, TrailingTriviaOption } from "../../../services/textChanges"; +import { testFormatSettings } from "../../../services/types"; +import { notImplementedHost } from "./extract/helpers"; // Some tests have trailing whitespace describe("unittests:: services:: textChanges", () => { - function findChild(name: string, n: ts.Node) { + function findChild(name: string, n: Node) { return find(n)!; - function find(node: ts.Node): ts.Node | undefined { - if (ts.isDeclaration(node) && node.name && ts.isIdentifier(node.name) && node.name.escapedText === name) { + function find(node: Node): Node | undefined { + if (isDeclaration(node) && node.name && isIdentifier(node.name) && node.name.escapedText === name) { return node; } else { - return ts.forEachChild(node, find); + return forEachChild(node, find); } } } - const printerOptions = { newLine: ts.NewLineKind.LineFeed }; - const newLineCharacter = ts.getNewLineCharacter(printerOptions); + const printerOptions = { newLine: NewLineKind.LineFeed }; + const newLineCharacter = getNewLineCharacter(printerOptions); - function getRuleProvider(placeOpenBraceOnNewLineForFunctions: boolean): ts.formatting.FormatContext { - return ts.formatting.getFormatContext(placeOpenBraceOnNewLineForFunctions ? { ...ts.testFormatSettings, placeOpenBraceOnNewLineForFunctions: true } : ts.testFormatSettings, ts.notImplementedHost); + function getRuleProvider(placeOpenBraceOnNewLineForFunctions: boolean): FormatContext { + return getFormatContext(placeOpenBraceOnNewLineForFunctions ? { ...testFormatSettings, placeOpenBraceOnNewLineForFunctions: true } : testFormatSettings, notImplementedHost); } // validate that positions that were recovered from the printed text actually match positions that will be created if the same text is parsed. - function verifyPositions(node: ts.Node, text: string): void { + function verifyPositions(node: Node, text: string): void { const nodeList = flattenNodes(node); - const sourceFile = ts.createSourceFile("f.ts", text, ts.ScriptTarget.ES2015); + const sourceFile = createSourceFile("f.ts", text, ScriptTarget.ES2015); const parsedNodeList = flattenNodes(sourceFile.statements[0]); - ts.zipWith(nodeList, parsedNodeList, (left, right) => { - ts.Debug.assert(left.pos === right.pos); - ts.Debug.assert(left.end === right.end); + zipWith(nodeList, parsedNodeList, (left, right) => { + Debug.assert(left.pos === right.pos); + Debug.assert(left.end === right.end); }); - function flattenNodes(n: ts.Node) { - const data: (ts.Node | ts.NodeArray)[] = []; + function flattenNodes(n: Node) { + const data: (Node | NodeArray)[] = []; walk(n); return data; - function walk(n: ts.Node | ts.NodeArray): void { + function walk(n: Node | NodeArray): void { data.push(n); - return ts.isArray(n) ? ts.forEach(n, walk) : ts.forEachChild(n, walk, walk); + return isArray(n) ? forEach(n, walk) : forEachChild(n, walk, walk); } } } - function runSingleFileTest(caption: string, placeOpenBraceOnNewLineForFunctions: boolean, text: string, validateNodes: boolean, testBlock: (sourceFile: ts.SourceFile, changeTracker: ts.textChanges.ChangeTracker) => void) { + function runSingleFileTest(caption: string, placeOpenBraceOnNewLineForFunctions: boolean, text: string, validateNodes: boolean, testBlock: (sourceFile: SourceFile, changeTracker: ChangeTracker) => void) { it(caption, () => { - const sourceFile = ts.createSourceFile("source.ts", text, ts.ScriptTarget.ES2015, /*setParentNodes*/ true); + const sourceFile = createSourceFile("source.ts", text, ScriptTarget.ES2015, /*setParentNodes*/ true); const rulesProvider = getRuleProvider(placeOpenBraceOnNewLineForFunctions); - const changeTracker = new ts.textChanges.ChangeTracker(newLineCharacter, rulesProvider); + const changeTracker = new ChangeTracker(newLineCharacter, rulesProvider); testBlock(sourceFile, changeTracker); const changes = changeTracker.getChanges(validateNodes ? verifyPositions : undefined); assert.equal(changes.length, 1); assert.equal(changes[0].fileName, sourceFile.fileName); - const modified = ts.textChanges.applyChanges(sourceFile.text, changes[0].textChanges); - Harness.Baseline.runBaseline(`textChanges/${caption}.js`, `===ORIGINAL===${newLineCharacter}${text}${newLineCharacter}===MODIFIED===${newLineCharacter}${modified}`); + const modified = applyChanges(sourceFile.text, changes[0].textChanges); + Baseline.runBaseline(`textChanges/${caption}.js`, `===ORIGINAL===${newLineCharacter}${text}${newLineCharacter}===MODIFIED===${newLineCharacter}${modified}`); }); } @@ -83,28 +101,28 @@ namespace M } }`; runSingleFileTest("extractMethodLike", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - const statements = (findChild("foo", sourceFile) as ts.FunctionDeclaration).body!.statements.slice(1); - const newFunction = ts.factory.createFunctionDeclaration( + const statements = (findChild("foo", sourceFile) as FunctionDeclaration).body!.statements.slice(1); + const newFunction = factory.createFunctionDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*asteriskToken*/ undefined, /*name*/ "bar", /*typeParameters*/ undefined, - /*parameters*/ ts.emptyArray, - /*type*/ ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), - /*body */ ts.factory.createBlock(statements) + /*parameters*/ emptyArray, + /*type*/ factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), + /*body */ factory.createBlock(statements) ); changeTracker.insertNodeBefore(sourceFile, /*before*/findChild("M2", sourceFile), newFunction); // replace statements with return statement - const newStatement = ts.factory.createReturnStatement( - ts.factory.createCallExpression( + const newStatement = factory.createReturnStatement( + factory.createCallExpression( /*expression*/ newFunction.name!, /*typeArguments*/ undefined, - /*argumentsArray*/ ts.emptyArray + /*argumentsArray*/ emptyArray )); - changeTracker.replaceNodeRange(sourceFile, statements[0], ts.last(statements), newStatement, { suffix: newLineCharacter }); + changeTracker.replaceNodeRange(sourceFile, statements[0], last(statements), newStatement, { suffix: newLineCharacter }); }); } { @@ -121,13 +139,13 @@ function bar() { changeTracker.deleteRange(sourceFile, { pos: text.indexOf("function foo"), end: text.indexOf("function bar") }); }); } - function findVariableStatementContaining(name: string, sourceFile: ts.SourceFile): ts.VariableStatement { - return ts.cast(findVariableDeclarationContaining(name, sourceFile).parent.parent, ts.isVariableStatement); + function findVariableStatementContaining(name: string, sourceFile: SourceFile): VariableStatement { + return cast(findVariableDeclarationContaining(name, sourceFile).parent.parent, isVariableStatement); } - function findVariableDeclarationContaining(name: string, sourceFile: ts.SourceFile): ts.VariableDeclaration { - return ts.cast(findChild(name, sourceFile), ts.isVariableDeclaration); + function findVariableDeclarationContaining(name: string, sourceFile: SourceFile): VariableDeclaration { + return cast(findChild(name, sourceFile), isVariableDeclaration); } - const { deleteNode } = ts.textChanges; + const { deleteNode } = textChanges; { const text = ` var x = 1; // some comment - 1 @@ -141,13 +159,13 @@ var z = 3; // comment 4 deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile)); }); runSingleFileTest("deleteNode2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude }); + deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { leadingTriviaOption: LeadingTriviaOption.Exclude }); }); runSingleFileTest("deleteNode3", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude }); + deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { trailingTriviaOption: TrailingTriviaOption.Exclude }); }); runSingleFileTest("deleteNode4", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude }); + deleteNode(changeTracker, sourceFile, findVariableStatementContaining("y", sourceFile), { leadingTriviaOption: LeadingTriviaOption.Exclude, trailingTriviaOption: TrailingTriviaOption.Exclude }); }); runSingleFileTest("deleteNode5", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { deleteNode(changeTracker, sourceFile, findVariableStatementContaining("x", sourceFile)); @@ -168,43 +186,43 @@ var a = 4; // comment 7 }); runSingleFileTest("deleteNodeRange2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), - { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude }); + { leadingTriviaOption: LeadingTriviaOption.Exclude }); }); runSingleFileTest("deleteNodeRange3", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), - { trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude }); + { trailingTriviaOption: TrailingTriviaOption.Exclude }); }); runSingleFileTest("deleteNodeRange4", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { changeTracker.deleteNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), - { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude }); + { leadingTriviaOption: LeadingTriviaOption.Exclude, trailingTriviaOption: TrailingTriviaOption.Exclude }); }); } function createTestVariableDeclaration(name: string) { - return ts.factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createObjectLiteralExpression([ts.factory.createPropertyAssignment("p1", ts.factory.createNumericLiteral(1))], /*multiline*/ true)); + return factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, /*type*/ undefined, factory.createObjectLiteralExpression([factory.createPropertyAssignment("p1", factory.createNumericLiteral(1))], /*multiline*/ true)); } function createTestClass() { - return ts.factory.createClassDeclaration( + return factory.createClassDeclaration( /*decorators*/ undefined, [ - ts.factory.createToken(ts.SyntaxKind.PublicKeyword) + factory.createToken(SyntaxKind.PublicKeyword) ], "class1", /*typeParameters*/ undefined, [ - ts.factory.createHeritageClause( - ts.SyntaxKind.ImplementsKeyword, + factory.createHeritageClause( + SyntaxKind.ImplementsKeyword, [ - ts.factory.createExpressionWithTypeArguments(ts.factory.createIdentifier("interface1"), /*typeArguments*/ undefined) + factory.createExpressionWithTypeArguments(factory.createIdentifier("interface1"), /*typeArguments*/ undefined) ] ) ], [ - ts.factory.createPropertyDeclaration( + factory.createPropertyDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, "property1", /*questionToken*/ undefined, - ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword), + factory.createKeywordTypeNode(SyntaxKind.BooleanKeyword), /*initializer*/ undefined ) ] @@ -255,16 +273,16 @@ var a = 4; // comment 7`; changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { suffix: newLineCharacter }); }); runSingleFileTest("replaceNode2", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, suffix: newLineCharacter, prefix: newLineCharacter }); + changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { leadingTriviaOption: LeadingTriviaOption.Exclude, suffix: newLineCharacter, prefix: newLineCharacter }); }); runSingleFileTest("replaceNode3", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude, suffix: newLineCharacter }); + changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { trailingTriviaOption: TrailingTriviaOption.Exclude, suffix: newLineCharacter }); }); runSingleFileTest("replaceNode4", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude }); + changeTracker.replaceNode(sourceFile, findVariableStatementContaining("y", sourceFile), createTestClass(), { leadingTriviaOption: LeadingTriviaOption.Exclude, trailingTriviaOption: TrailingTriviaOption.Exclude }); }); runSingleFileTest("replaceNode5", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceNode(sourceFile, findVariableStatementContaining("x", sourceFile), createTestClass(), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude }); + changeTracker.replaceNode(sourceFile, findVariableStatementContaining("x", sourceFile), createTestClass(), { leadingTriviaOption: LeadingTriviaOption.Exclude, trailingTriviaOption: TrailingTriviaOption.Exclude }); }); } { @@ -280,13 +298,13 @@ var a = 4; // comment 7`; changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { suffix: newLineCharacter }); }); runSingleFileTest("replaceNodeRange2", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, suffix: newLineCharacter, prefix: newLineCharacter }); + changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { leadingTriviaOption: LeadingTriviaOption.Exclude, suffix: newLineCharacter, prefix: newLineCharacter }); }); runSingleFileTest("replaceNodeRange3", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude, suffix: newLineCharacter }); + changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { trailingTriviaOption: TrailingTriviaOption.Exclude, suffix: newLineCharacter }); }); runSingleFileTest("replaceNodeRange4", /*placeOpenBraceOnNewLineForFunctions*/ true, text, /*validateNodes*/ true, (sourceFile, changeTracker) => { - changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude }); + changeTracker.replaceNodeRange(sourceFile, findVariableStatementContaining("y", sourceFile), findVariableStatementContaining("z", sourceFile), createTestClass(), { leadingTriviaOption: LeadingTriviaOption.Exclude, trailingTriviaOption: TrailingTriviaOption.Exclude }); }); } { @@ -330,17 +348,17 @@ namespace M { }); } - function findConstructor(sourceFile: ts.SourceFile): ts.ConstructorDeclaration { - const classDecl = sourceFile.statements[0] as ts.ClassDeclaration; - return ts.find(classDecl.members, (m): m is ts.ConstructorDeclaration => ts.isConstructorDeclaration(m) && !!m.body)!; + function findConstructor(sourceFile: SourceFile): ConstructorDeclaration { + const classDecl = sourceFile.statements[0] as ClassDeclaration; + return find(classDecl.members, (m): m is ConstructorDeclaration => isConstructorDeclaration(m) && !!m.body)!; } function createTestSuperCall() { - const superCall = ts.factory.createCallExpression( - ts.factory.createSuper(), + const superCall = factory.createCallExpression( + factory.createSuper(), /*typeArguments*/ undefined, - /*argumentsArray*/ ts.emptyArray + /*argumentsArray*/ emptyArray ); - return ts.factory.createExpressionStatement(superCall); + return factory.createExpressionStatement(superCall); } { @@ -486,27 +504,27 @@ function foo( const text = ` const x = 1, y = 2;`; runSingleFileTest("insertNodeInListAfter1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); runSingleFileTest("insertNodeInListAfter2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); } { const text = ` const /*x*/ x = 1, /*y*/ y = 2;`; runSingleFileTest("insertNodeInListAfter3", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); runSingleFileTest("insertNodeInListAfter4", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); } { const text = ` const x = 1;`; runSingleFileTest("insertNodeInListAfter5", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); } { @@ -514,10 +532,10 @@ const x = 1;`; const x = 1, y = 2;`; runSingleFileTest("insertNodeInListAfter6", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); runSingleFileTest("insertNodeInListAfter7", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); } { @@ -525,10 +543,10 @@ const x = 1, const /*x*/ x = 1, /*y*/ y = 2;`; runSingleFileTest("insertNodeInListAfter8", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); runSingleFileTest("insertNodeInListAfter9", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), ts.factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createNumericLiteral(1))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("y", sourceFile), factory.createVariableDeclaration("z", /*exclamationToken*/ undefined, /*type*/ undefined, factory.createNumericLiteral(1))); }); } { @@ -537,7 +555,7 @@ import { x } from "bar"`; runSingleFileTest("insertNodeInListAfter10", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, ts.factory.createIdentifier("b"), ts.factory.createIdentifier("a"))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, factory.createIdentifier("b"), factory.createIdentifier("a"))); }); } { @@ -546,7 +564,7 @@ import { x // this is x } from "bar"`; runSingleFileTest("insertNodeInListAfter11", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, ts.factory.createIdentifier("b"), ts.factory.createIdentifier("a"))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, factory.createIdentifier("b"), factory.createIdentifier("a"))); }); } { @@ -556,7 +574,7 @@ import { } from "bar"`; runSingleFileTest("insertNodeInListAfter12", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { // eslint-disable-next-line boolean-trivia - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, ts.factory.createIdentifier("a"))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, factory.createIdentifier("a"))); }); } { @@ -566,7 +584,7 @@ import { } from "bar"`; runSingleFileTest("insertNodeInListAfter13", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { // eslint-disable-next-line boolean-trivia - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, ts.factory.createIdentifier("a"))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, factory.createIdentifier("a"))); }); } { @@ -576,7 +594,7 @@ import { x } from "bar"`; runSingleFileTest("insertNodeInListAfter14", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, ts.factory.createIdentifier("b"), ts.factory.createIdentifier("a"))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, factory.createIdentifier("b"), factory.createIdentifier("a"))); }); } { @@ -586,7 +604,7 @@ import { x // this is x } from "bar"`; runSingleFileTest("insertNodeInListAfter15", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, ts.factory.createIdentifier("b"), ts.factory.createIdentifier("a"))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, factory.createIdentifier("b"), factory.createIdentifier("a"))); }); } { @@ -597,7 +615,7 @@ import { } from "bar"`; runSingleFileTest("insertNodeInListAfter16", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { // eslint-disable-next-line boolean-trivia - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, ts.factory.createIdentifier("a"))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, factory.createIdentifier("a"))); }); } { @@ -608,7 +626,7 @@ import { } from "bar"`; runSingleFileTest("insertNodeInListAfter17", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { // eslint-disable-next-line boolean-trivia - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, ts.factory.createIdentifier("a"))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, factory.createIdentifier("a"))); }); } { @@ -618,14 +636,14 @@ import { } from "bar"`; runSingleFileTest("insertNodeInListAfter18", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { // eslint-disable-next-line boolean-trivia - changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, ts.factory.createIdentifier("a"))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, factory.createIdentifier("a"))); }); } { const runTest = (name: string, text: string) => runSingleFileTest(name, /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { for (const specifier of ["x3", "x4", "x5"]) { // eslint-disable-next-line boolean-trivia - changeTracker.insertNodeInListAfter(sourceFile, findChild("x2", sourceFile), ts.factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, ts.factory.createIdentifier(specifier))); + changeTracker.insertNodeInListAfter(sourceFile, findChild("x2", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, factory.createIdentifier(specifier))); } }); @@ -645,7 +663,7 @@ class A { for (let i = 0; i < 11 /*error doesn't occur with fewer nodes*/; ++i) { newNodes.push( // eslint-disable-next-line boolean-trivia - ts.factory.createPropertyDeclaration(undefined, undefined, i + "", undefined, undefined, undefined)); + factory.createPropertyDeclaration(undefined, undefined, i + "", undefined, undefined, undefined)); } const insertAfter = findChild("x", sourceFile); for (const newNode of newNodes) { @@ -661,7 +679,7 @@ class A { `; runSingleFileTest("insertNodeAfterInClass1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { // eslint-disable-next-line boolean-trivia - changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), ts.factory.createPropertyDeclaration(undefined, undefined, "a", undefined, ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword), undefined)); + changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), factory.createPropertyDeclaration(undefined, undefined, "a", undefined, factory.createKeywordTypeNode(SyntaxKind.BooleanKeyword), undefined)); }); } { @@ -672,7 +690,7 @@ class A { `; runSingleFileTest("insertNodeAfterInClass2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { // eslint-disable-next-line boolean-trivia - changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), ts.factory.createPropertyDeclaration(undefined, undefined, "a", undefined, ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword), undefined)); + changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), factory.createPropertyDeclaration(undefined, undefined, "a", undefined, factory.createKeywordTypeNode(SyntaxKind.BooleanKeyword), undefined)); }); } { @@ -704,12 +722,12 @@ class A { } `; runSingleFileTest("insertNodeInClassAfterNodeWithoutSeparator1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNode = ts.factory.createPropertyDeclaration( + const newNode = factory.createPropertyDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - ts.factory.createComputedPropertyName(ts.factory.createNumericLiteral(1)), + factory.createComputedPropertyName(factory.createNumericLiteral(1)), /*questionToken*/ undefined, - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), /*initializer*/ undefined); changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); }); @@ -722,12 +740,12 @@ class A { } `; runSingleFileTest("insertNodeInClassAfterNodeWithoutSeparator2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNode = ts.factory.createPropertyDeclaration( + const newNode = factory.createPropertyDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - ts.factory.createComputedPropertyName(ts.factory.createNumericLiteral(1)), + factory.createComputedPropertyName(factory.createNumericLiteral(1)), /*questionToken*/ undefined, - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), /*initializer*/ undefined); changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); }); @@ -739,12 +757,12 @@ interface A { } `; runSingleFileTest("insertNodeInInterfaceAfterNodeWithoutSeparator1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNode = ts.factory.createPropertyDeclaration( + const newNode = factory.createPropertyDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - ts.factory.createComputedPropertyName(ts.factory.createNumericLiteral(1)), + factory.createComputedPropertyName(factory.createNumericLiteral(1)), /*questionToken*/ undefined, - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), /*initializer*/ undefined); changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); }); @@ -756,12 +774,12 @@ interface A { } `; runSingleFileTest("insertNodeInInterfaceAfterNodeWithoutSeparator2", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNode = ts.factory.createPropertyDeclaration( + const newNode = factory.createPropertyDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - ts.factory.createComputedPropertyName(ts.factory.createNumericLiteral(1)), + factory.createComputedPropertyName(factory.createNumericLiteral(1)), /*questionToken*/ undefined, - ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), + factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), /*initializer*/ undefined); changeTracker.insertNodeAfter(sourceFile, findChild("x", sourceFile), newNode); }); @@ -771,7 +789,7 @@ interface A { let x = foo `; runSingleFileTest("insertNodeInStatementListAfterNodeWithoutSeparator1", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => { - const newNode = ts.factory.createExpressionStatement(ts.factory.createParenthesizedExpression(ts.factory.createNumericLiteral(1))); + const newNode = factory.createExpressionStatement(factory.createParenthesizedExpression(factory.createNumericLiteral(1))); changeTracker.insertNodeAfter(sourceFile, findVariableStatementContaining("x", sourceFile), newNode); }); } diff --git a/src/testRunner/unittests/services/transpile.ts b/src/testRunner/unittests/services/transpile.ts index 2f3688fb7de64..eb716c9b2f042 100644 --- a/src/testRunner/unittests/services/transpile.ts +++ b/src/testRunner/unittests/services/transpile.ts @@ -1,30 +1,33 @@ -import * as Harness from "../../_namespaces/Harness"; -import * as ts from "../../_namespaces/ts"; +import { + Diagnostic, Extension, JsxEmit, ModuleKind, ModuleResolutionKind, NewLineKind, ScriptTarget, +} from "../../../compiler/types"; +import { Baseline, Compiler } from "../../../harness/harnessIO"; +import { transpile, transpileModule, TranspileOptions, TranspileOutput } from "../../../services/transpile"; describe("unittests:: services:: Transpile", () => { interface TranspileTestSettings { - options?: ts.TranspileOptions; + options?: TranspileOptions; noSetFileName?: boolean; } function transpilesCorrectly(name: string, input: string, testSettings: TranspileTestSettings) { describe(name, () => { - let transpileResult: ts.TranspileOutput; + let transpileResult: TranspileOutput; let oldTranspileResult: string; - let oldTranspileDiagnostics: ts.Diagnostic[]; + let oldTranspileDiagnostics: Diagnostic[]; - const transpileOptions: ts.TranspileOptions = testSettings.options || {}; + const transpileOptions: TranspileOptions = testSettings.options || {}; if (!transpileOptions.compilerOptions) { transpileOptions.compilerOptions = { }; } if (transpileOptions.compilerOptions.target === undefined) { - transpileOptions.compilerOptions.target = ts.ScriptTarget.ES3; + transpileOptions.compilerOptions.target = ScriptTarget.ES3; } if (transpileOptions.compilerOptions.newLine === undefined) { // use \r\n as default new line - transpileOptions.compilerOptions.newLine = ts.NewLineKind.CarriageReturnLineFeed; + transpileOptions.compilerOptions.newLine = NewLineKind.CarriageReturnLineFeed; } transpileOptions.compilerOptions.sourceMap = true; @@ -39,7 +42,7 @@ describe("unittests:: services:: Transpile", () => { transpileOptions.reportDiagnostics = true; - const justName = "transpile/" + name.replace(/[^a-z0-9\-. ]/ig, "") + (transpileOptions.compilerOptions.jsx ? ts.Extension.Tsx : ts.Extension.Ts); + const justName = "transpile/" + name.replace(/[^a-z0-9\-. ]/ig, "") + (transpileOptions.compilerOptions.jsx ? Extension.Tsx : Extension.Ts); const toBeCompiled = [{ unitName, content: input @@ -47,11 +50,11 @@ describe("unittests:: services:: Transpile", () => { const canUseOldTranspile = !transpileOptions.renamedDependencies; before(() => { - transpileResult = ts.transpileModule(input, transpileOptions); + transpileResult = transpileModule(input, transpileOptions); if (canUseOldTranspile) { oldTranspileDiagnostics = []; - oldTranspileResult = ts.transpile(input, transpileOptions.compilerOptions, transpileOptions.fileName, oldTranspileDiagnostics, transpileOptions.moduleName); + oldTranspileResult = transpile(input, transpileOptions.compilerOptions, transpileOptions.fileName, oldTranspileDiagnostics, transpileOptions.moduleName); } }); @@ -63,86 +66,86 @@ describe("unittests:: services:: Transpile", () => { /* eslint-disable no-null/no-null */ it("Correct errors for " + justName, () => { - Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".errors.txt"), - transpileResult.diagnostics!.length === 0 ? null : Harness.Compiler.getErrorBaseline(toBeCompiled, transpileResult.diagnostics!)); + Baseline.runBaseline(justName.replace(/\.tsx?$/, ".errors.txt"), + transpileResult.diagnostics!.length === 0 ? null : Compiler.getErrorBaseline(toBeCompiled, transpileResult.diagnostics!)); }); if (canUseOldTranspile) { it("Correct errors (old transpile) for " + justName, () => { - Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".oldTranspile.errors.txt"), - oldTranspileDiagnostics.length === 0 ? null : Harness.Compiler.getErrorBaseline(toBeCompiled, oldTranspileDiagnostics)); + Baseline.runBaseline(justName.replace(/\.tsx?$/, ".oldTranspile.errors.txt"), + oldTranspileDiagnostics.length === 0 ? null : Compiler.getErrorBaseline(toBeCompiled, oldTranspileDiagnostics)); }); } /* eslint-enable no-null/no-null */ it("Correct output for " + justName, () => { - Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ts.Extension.Js), transpileResult.outputText); + Baseline.runBaseline(justName.replace(/\.tsx?$/, Extension.Js), transpileResult.outputText); }); if (canUseOldTranspile) { it("Correct output (old transpile) for " + justName, () => { - Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".oldTranspile.js"), oldTranspileResult); + Baseline.runBaseline(justName.replace(/\.tsx?$/, ".oldTranspile.js"), oldTranspileResult); }); } }); } transpilesCorrectly("Generates no diagnostics with valid inputs", `var x = 0;`, { - options: { compilerOptions: { module: ts.ModuleKind.CommonJS } } + options: { compilerOptions: { module: ModuleKind.CommonJS } } }); transpilesCorrectly("Generates no diagnostics for missing file references", `/// var x = 0;`, { - options: { compilerOptions: { module: ts.ModuleKind.CommonJS } } + options: { compilerOptions: { module: ModuleKind.CommonJS } } }); transpilesCorrectly("Generates no diagnostics for missing module imports", `import {a} from "module2";`, { - options: { compilerOptions: { module: ts.ModuleKind.CommonJS } } + options: { compilerOptions: { module: ModuleKind.CommonJS } } }); transpilesCorrectly("Generates expected syntactic diagnostics", `a b`, { - options: { compilerOptions: { module: ts.ModuleKind.CommonJS } } + options: { compilerOptions: { module: ModuleKind.CommonJS } } }); transpilesCorrectly("Does not generate semantic diagnostics", `var x: string = 0;`, { - options: { compilerOptions: { module: ts.ModuleKind.CommonJS } } + options: { compilerOptions: { module: ModuleKind.CommonJS } } }); transpilesCorrectly("Generates module output", `var x = 0;`, { - options: { compilerOptions: { module: ts.ModuleKind.AMD } } + options: { compilerOptions: { module: ModuleKind.AMD } } }); transpilesCorrectly("Uses correct newLine character", `var x = 0;`, { - options: { compilerOptions: { module: ts.ModuleKind.CommonJS, newLine: ts.NewLineKind.LineFeed } } + options: { compilerOptions: { module: ModuleKind.CommonJS, newLine: NewLineKind.LineFeed } } }); transpilesCorrectly("Sets module name", "var x = 1;", { - options: { compilerOptions: { module: ts.ModuleKind.System, newLine: ts.NewLineKind.LineFeed }, moduleName: "NamedModule" } + options: { compilerOptions: { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, moduleName: "NamedModule" } }); transpilesCorrectly("No extra errors for file without extension", `"use strict";\r\nvar x = 0;`, { - options: { compilerOptions: { module: ts.ModuleKind.CommonJS }, fileName: "file" } + options: { compilerOptions: { module: ModuleKind.CommonJS }, fileName: "file" } }); transpilesCorrectly("Rename dependencies - System", `import {foo} from "SomeName";\n` + `declare function use(a: any);\n` + `use(foo);`, { - options: { compilerOptions: { module: ts.ModuleKind.System, newLine: ts.NewLineKind.LineFeed }, renamedDependencies: { SomeName: "SomeOtherName" } } + options: { compilerOptions: { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, renamedDependencies: { SomeName: "SomeOtherName" } } }); transpilesCorrectly("Rename dependencies - AMD", `import {foo} from "SomeName";\n` + `declare function use(a: any);\n` + `use(foo);`, { - options: { compilerOptions: { module: ts.ModuleKind.AMD, newLine: ts.NewLineKind.LineFeed }, renamedDependencies: { SomeName: "SomeOtherName" } } + options: { compilerOptions: { module: ModuleKind.AMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { SomeName: "SomeOtherName" } } }); transpilesCorrectly("Rename dependencies - UMD", `import {foo} from "SomeName";\n` + `declare function use(a: any);\n` + `use(foo);`, { - options: { compilerOptions: { module: ts.ModuleKind.UMD, newLine: ts.NewLineKind.LineFeed }, renamedDependencies: { SomeName: "SomeOtherName" } } + options: { compilerOptions: { module: ModuleKind.UMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { SomeName: "SomeOtherName" } } }); transpilesCorrectly("Transpile with emit decorators and emit metadata", @@ -161,12 +164,12 @@ var x = 0;`, { `export {MyClass}; \n`, { options: { compilerOptions: { - module: ts.ModuleKind.CommonJS, - newLine: ts.NewLineKind.LineFeed, + module: ModuleKind.CommonJS, + newLine: NewLineKind.LineFeed, noEmitHelpers: true, emitDecoratorMetadata: true, experimentalDecorators: true, - target: ts.ScriptTarget.ES5, + target: ScriptTarget.ES5, } } }); @@ -176,11 +179,11 @@ var x = 0;`, { }); transpilesCorrectly("transpile file as 'tsx' if 'jsx' is specified", `var x =
`, { - options: { compilerOptions: { jsx: ts.JsxEmit.React, newLine: ts.NewLineKind.LineFeed } } + options: { compilerOptions: { jsx: JsxEmit.React, newLine: NewLineKind.LineFeed } } }); transpilesCorrectly("transpile .js files", "const a = 10;", { - options: { compilerOptions: { newLine: ts.NewLineKind.LineFeed, module: ts.ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true } + options: { compilerOptions: { newLine: NewLineKind.LineFeed, module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true } }); transpilesCorrectly("Supports urls in file name", "var x", { @@ -190,27 +193,27 @@ var x = 0;`, { transpilesCorrectly("Accepts string as enum values for compile-options", "export const x = 0", { options: { compilerOptions: { - module: "es6" as any as ts.ModuleKind, + module: "es6" as any as ModuleKind, // Capitalization and spaces ignored - target: " Es6 " as any as ts.ScriptTarget + target: " Es6 " as any as ScriptTarget } } }); transpilesCorrectly("Report an error when compiler-options module-kind is out-of-range", "", { - options: { compilerOptions: { module: 123 as any as ts.ModuleKind } } + options: { compilerOptions: { module: 123 as any as ModuleKind } } }); transpilesCorrectly("Report an error when compiler-options target-script is out-of-range", "", { - options: { compilerOptions: { module: 123 as any as ts.ModuleKind } } + options: { compilerOptions: { module: 123 as any as ModuleKind } } }); transpilesCorrectly("Support options with lib values", "const a = 10;", { - options: { compilerOptions: { lib: ["es6", "dom"], module: ts.ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true } + options: { compilerOptions: { lib: ["es6", "dom"], module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true } }); transpilesCorrectly("Support options with types values", "const a = 10;", { - options: { compilerOptions: { types: ["jquery", "typescript"], module: ts.ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true } + options: { compilerOptions: { types: ["jquery", "typescript"], module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true } }); transpilesCorrectly("Supports setting 'allowJs'", "x;", { @@ -282,15 +285,15 @@ var x = 0;`, { }); transpilesCorrectly("Supports setting 'module'", "x;", { - options: { compilerOptions: { module: ts.ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true } + options: { compilerOptions: { module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true } }); transpilesCorrectly("Supports setting 'moduleResolution'", "x;", { - options: { compilerOptions: { moduleResolution: ts.ModuleResolutionKind.NodeJs }, fileName: "input.js", reportDiagnostics: true } + options: { compilerOptions: { moduleResolution: ModuleResolutionKind.NodeJs }, fileName: "input.js", reportDiagnostics: true } }); transpilesCorrectly("Supports setting 'newLine'", "x;", { - options: { compilerOptions: { newLine: ts.NewLineKind.CarriageReturnLineFeed }, fileName: "input.js", reportDiagnostics: true } + options: { compilerOptions: { newLine: NewLineKind.CarriageReturnLineFeed }, fileName: "input.js", reportDiagnostics: true } }); transpilesCorrectly("Supports setting 'noEmit'", "x;", { @@ -438,9 +441,9 @@ var x = 0;`, { `}`, { options: { compilerOptions: { - target: ts.ScriptTarget.ES5, - module: ts.ModuleKind.CommonJS, - moduleResolution: ts.ModuleResolutionKind.NodeJs, + target: ScriptTarget.ES5, + module: ModuleKind.CommonJS, + moduleResolution: ModuleResolutionKind.NodeJs, emitDecoratorMetadata: true, experimentalDecorators: true, isolatedModules: true, @@ -458,9 +461,9 @@ var x = 0;`, { `}`, { options: { compilerOptions: { - target: ts.ScriptTarget.ES5, - module: ts.ModuleKind.System, - moduleResolution: ts.ModuleResolutionKind.NodeJs, + target: ScriptTarget.ES5, + module: ModuleKind.System, + moduleResolution: ModuleResolutionKind.NodeJs, emitDecoratorMetadata: true, experimentalDecorators: true, isolatedModules: true, @@ -470,11 +473,11 @@ var x = 0;`, { ); transpilesCorrectly("Supports readonly keyword for arrays", "let x: readonly string[];", { - options: { compilerOptions: { module: ts.ModuleKind.CommonJS } } + options: { compilerOptions: { module: ModuleKind.CommonJS } } }); transpilesCorrectly("Supports 'as const' arrays", `([] as const).forEach(k => console.log(k));`, { - options: { compilerOptions: { module: ts.ModuleKind.CommonJS } } + options: { compilerOptions: { module: ModuleKind.CommonJS } } }); transpilesCorrectly("Infer correct file extension", `const fn = (a: T) => a`, { diff --git a/src/testRunner/unittests/transform.ts b/src/testRunner/unittests/transform.ts index 3127978b0f5d7..457851f166b32 100644 --- a/src/testRunner/unittests/transform.ts +++ b/src/testRunner/unittests/transform.ts @@ -1,85 +1,106 @@ -import * as documents from "../_namespaces/documents"; -import * as evaluator from "../_namespaces/evaluator"; -import * as fakes from "../_namespaces/fakes"; -import * as Harness from "../_namespaces/Harness"; -import * as ts from "../_namespaces/ts"; -import * as vfs from "../_namespaces/vfs"; +import { createPrinter } from "../../compiler/emitter"; +import { + addSyntheticTrailingComment, setEmitFlags, setSyntheticLeadingComments, +} from "../../compiler/factory/emitNode"; +import { factory } from "../../compiler/factory/nodeFactory"; +import { + isClassDeclaration, isConstructorDeclaration, isExportDeclaration, isExportSpecifier, isIdentifier, + isImportDeclaration, isImportSpecifier, isMethodDeclaration, isModuleDeclaration, isNoSubstitutionTemplateLiteral, + isNumericLiteral, isPropertyDeclaration, isSourceFile, isVariableDeclaration, isVariableStatement, isVoidExpression, +} from "../../compiler/factory/nodeTests"; +import { setTextRange } from "../../compiler/factory/utilitiesPublic"; +import { createSourceFile } from "../../compiler/parser"; +import { createProgram } from "../../compiler/program"; +import { + EmitFlags, EmitHint, ExportDeclaration, Identifier, ModuleBlock, ModuleKind, NewLineKind, Node, ScriptTarget, + SourceFile, SyntaxKind, TransformationContext, Transformer, TransformerFactory, VariableStatement, Visitor, + VisitResult, +} from "../../compiler/types"; +import { isClassLike, isParameterPropertyDeclaration } from "../../compiler/utilitiesPublic"; +import { visitEachChild, visitNode } from "../../compiler/visitorPublic"; +import { TextDocument } from "../../harness/documentsUtil"; +import { evaluateJavaScript } from "../../harness/evaluatorImpl"; +import { CompilerHost } from "../../harness/fakesHosts"; +import { Baseline, IO } from "../../harness/harnessIO"; +import { createFromFileSystem } from "../../harness/vfsUtil"; +import { transform } from "../../services/transform"; +import { transpileModule, TranspileOptions } from "../../services/transpile"; describe("unittests:: TransformAPI", () => { - function replaceUndefinedWithVoid0(context: ts.TransformationContext) { + function replaceUndefinedWithVoid0(context: TransformationContext) { const previousOnSubstituteNode = context.onSubstituteNode; - context.enableSubstitution(ts.SyntaxKind.Identifier); + context.enableSubstitution(SyntaxKind.Identifier); context.onSubstituteNode = (hint, node) => { node = previousOnSubstituteNode(hint, node); - if (hint === ts.EmitHint.Expression && ts.isIdentifier(node) && node.escapedText === "undefined") { - node = ts.factory.createPartiallyEmittedExpression( - ts.addSyntheticTrailingComment( - ts.setTextRange( - ts.factory.createVoidZero(), + if (hint === EmitHint.Expression && isIdentifier(node) && node.escapedText === "undefined") { + node = factory.createPartiallyEmittedExpression( + addSyntheticTrailingComment( + setTextRange( + factory.createVoidZero(), node), - ts.SyntaxKind.MultiLineCommentTrivia, "undefined")); + SyntaxKind.MultiLineCommentTrivia, "undefined")); } return node; }; - return (file: ts.SourceFile) => file; + return (file: SourceFile) => file; } - function replaceNumberWith2(context: ts.TransformationContext) { - function visitor(node: ts.Node): ts.Node { - if (ts.isNumericLiteral(node)) { - return ts.factory.createNumericLiteral("2"); + function replaceNumberWith2(context: TransformationContext) { + function visitor(node: Node): Node { + if (isNumericLiteral(node)) { + return factory.createNumericLiteral("2"); } - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); } - return (file: ts.SourceFile) => ts.visitNode(file, visitor); + return (file: SourceFile) => visitNode(file, visitor); } - function replaceIdentifiersNamedOldNameWithNewName(context: ts.TransformationContext) { + function replaceIdentifiersNamedOldNameWithNewName(context: TransformationContext) { const previousOnSubstituteNode = context.onSubstituteNode; - context.enableSubstitution(ts.SyntaxKind.Identifier); + context.enableSubstitution(SyntaxKind.Identifier); context.onSubstituteNode = (hint, node) => { node = previousOnSubstituteNode(hint, node); - if (ts.isIdentifier(node) && node.escapedText === "oldName") { - node = ts.setTextRange(ts.factory.createIdentifier("newName"), node); + if (isIdentifier(node) && node.escapedText === "oldName") { + node = setTextRange(factory.createIdentifier("newName"), node); } return node; }; - return (file: ts.SourceFile) => file; + return (file: SourceFile) => file; } - function replaceIdentifiersNamedOldNameWithNewName2(context: ts.TransformationContext) { - const visitor: ts.Visitor = (node) => { - if (ts.isIdentifier(node) && node.text === "oldName") { - return ts.factory.createIdentifier("newName"); + function replaceIdentifiersNamedOldNameWithNewName2(context: TransformationContext) { + const visitor: Visitor = (node) => { + if (isIdentifier(node) && node.text === "oldName") { + return factory.createIdentifier("newName"); } - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); }; - return (node: ts.SourceFile) => ts.visitNode(node, visitor); + return (node: SourceFile) => visitNode(node, visitor); } - function createTaggedTemplateLiteral(): ts.Transformer { - return sourceFile => ts.factory.updateSourceFile(sourceFile, [ - ts.factory.createExpressionStatement( - ts.factory.createTaggedTemplateExpression( - ts.factory.createIdentifier("$tpl"), + function createTaggedTemplateLiteral(): Transformer { + return sourceFile => factory.updateSourceFile(sourceFile, [ + factory.createExpressionStatement( + factory.createTaggedTemplateExpression( + factory.createIdentifier("$tpl"), /*typeArguments*/ undefined, - ts.factory.createNoSubstitutionTemplateLiteral("foo", "foo"))) + factory.createNoSubstitutionTemplateLiteral("foo", "foo"))) ]); } - function transformSourceFile(sourceText: string, transformers: ts.TransformerFactory[]) { - const transformed = ts.transform(ts.createSourceFile("source.ts", sourceText, ts.ScriptTarget.ES2015), transformers); - const printer = ts.createPrinter({ newLine: ts.NewLineKind.CarriageReturnLineFeed }, { + function transformSourceFile(sourceText: string, transformers: TransformerFactory[]) { + const transformed = transform(createSourceFile("source.ts", sourceText, ScriptTarget.ES2015), transformers); + const printer = createPrinter({ newLine: NewLineKind.CarriageReturnLineFeed }, { onEmitNode: transformed.emitNodeWithNotification, substituteNode: transformed.substituteNode }); - const result = printer.printBundle(ts.factory.createBundle(transformed.transformed)); + const result = printer.printBundle(factory.createBundle(transformed.transformed)); transformed.dispose(); return result; } function testBaseline(testName: string, test: () => string) { it(testName, () => { - Harness.Baseline.runBaseline(`transformApi/transformsCorrectly.${testName}.js`, test()); + Baseline.runBaseline(`transformApi/transformsCorrectly.${testName}.js`, test()); }); } @@ -93,10 +114,10 @@ describe("unittests:: TransformAPI", () => { sourceText = undefined!; }); it("compare baselines", () => { - Harness.Baseline.runBaseline(`transformApi/transformsCorrectly.${testName}.js`, sourceText); + Baseline.runBaseline(`transformApi/transformsCorrectly.${testName}.js`, sourceText); }); it("evaluate", () => { - onEvaluate(evaluator.evaluateJavaScript(sourceText)); + onEvaluate(evaluateJavaScript(sourceText)); }); }); } @@ -107,55 +128,55 @@ describe("unittests:: TransformAPI", () => { testBaseline("types", () => { return transformSourceFile(`let a: () => void`, [ - context => file => ts.visitNode(file, function visitor(node: ts.Node): ts.VisitResult { - return ts.visitEachChild(node, visitor, context); + context => file => visitNode(file, function visitor(node: Node): VisitResult { + return visitEachChild(node, visitor, context); }) ]); }); testBaseline("transformDefiniteAssignmentAssertions", () => { return transformSourceFile(`let a!: () => void`, [ - context => file => ts.visitNode(file, function visitor(node: ts.Node): ts.VisitResult { - if (node.kind === ts.SyntaxKind.VoidKeyword) { - return ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword); + context => file => visitNode(file, function visitor(node: Node): VisitResult { + if (node.kind === SyntaxKind.VoidKeyword) { + return factory.createKeywordTypeNode(SyntaxKind.UndefinedKeyword); } - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); }) ]); }); testBaseline("fromTranspileModule", () => { - return ts.transpileModule(`var oldName = undefined;`, { + return transpileModule(`var oldName = undefined;`, { transformers: { before: [replaceUndefinedWithVoid0], after: [replaceIdentifiersNamedOldNameWithNewName] }, compilerOptions: { - newLine: ts.NewLineKind.CarriageReturnLineFeed + newLine: NewLineKind.CarriageReturnLineFeed } }).outputText; }); testBaseline("transformTaggedTemplateLiteral", () => { - return ts.transpileModule("", { + return transpileModule("", { transformers: { before: [createTaggedTemplateLiteral], }, compilerOptions: { - target: ts.ScriptTarget.ES5, - newLine: ts.NewLineKind.CarriageReturnLineFeed + target: ScriptTarget.ES5, + newLine: NewLineKind.CarriageReturnLineFeed } }).outputText; }); testBaseline("issue27854", () => { - return ts.transpileModule(`oldName<{ a: string; }>\` ... \`;`, { + return transpileModule(`oldName<{ a: string; }>\` ... \`;`, { transformers: { before: [replaceIdentifiersNamedOldNameWithNewName2] }, compilerOptions: { - newLine: ts.NewLineKind.CarriageReturnLineFeed, - target: ts.ScriptTarget.Latest + newLine: NewLineKind.CarriageReturnLineFeed, + target: ScriptTarget.Latest } }).outputText; }); @@ -166,10 +187,10 @@ describe("unittests:: TransformAPI", () => { const SecondVar = null; `, [ context => file => { - const firstVarName = (file.statements[0] as ts.VariableStatement) - .declarationList.declarations[0].name as ts.Identifier; - const secondVarName = (file.statements[0] as ts.VariableStatement) - .declarationList.declarations[0].name as ts.Identifier; + const firstVarName = (file.statements[0] as VariableStatement) + .declarationList.declarations[0].name as Identifier; + const secondVarName = (file.statements[0] as VariableStatement) + .declarationList.declarations[0].name as Identifier; return context.factory.updateSourceFile(file, file.statements.concat([ context.factory.createExpressionStatement( @@ -181,18 +202,18 @@ describe("unittests:: TransformAPI", () => { }); testBaseline("rewrittenNamespace", () => { - return ts.transpileModule(`namespace Reflect { const x = 1; }`, { + return transpileModule(`namespace Reflect { const x = 1; }`, { transformers: { before: [forceNamespaceRewrite], }, compilerOptions: { - newLine: ts.NewLineKind.CarriageReturnLineFeed, + newLine: NewLineKind.CarriageReturnLineFeed, } }).outputText; }); testBaseline("rewrittenNamespaceFollowingClass", () => { - return ts.transpileModule(` + return transpileModule(` class C { foo = 10; static bar = 20 } namespace C { export let x = 10; } `, { @@ -200,46 +221,46 @@ describe("unittests:: TransformAPI", () => { before: [forceNamespaceRewrite], }, compilerOptions: { - target: ts.ScriptTarget.ESNext, - newLine: ts.NewLineKind.CarriageReturnLineFeed, + target: ScriptTarget.ESNext, + newLine: NewLineKind.CarriageReturnLineFeed, useDefineForClassFields: false, } }).outputText; }); testBaseline("transformTypesInExportDefault", () => { - return ts.transpileModule(` + return transpileModule(` export default (foo: string) => { return 1; } `, { transformers: { before: [replaceNumberWith2], }, compilerOptions: { - target: ts.ScriptTarget.ESNext, - newLine: ts.NewLineKind.CarriageReturnLineFeed, + target: ScriptTarget.ESNext, + newLine: NewLineKind.CarriageReturnLineFeed, } }).outputText; }); testBaseline("synthesizedClassAndNamespaceCombination", () => { - return ts.transpileModule("", { + return transpileModule("", { transformers: { before: [replaceWithClassAndNamespace], }, compilerOptions: { - target: ts.ScriptTarget.ESNext, - newLine: ts.NewLineKind.CarriageReturnLineFeed, + target: ScriptTarget.ESNext, + newLine: NewLineKind.CarriageReturnLineFeed, } }).outputText; function replaceWithClassAndNamespace() { - return (sourceFile: ts.SourceFile) => { + return (sourceFile: SourceFile) => { // TODO(rbuckton): Does this need to be parented? - const result = ts.factory.updateSourceFile( + const result = factory.updateSourceFile( sourceFile, - ts.factory.createNodeArray([ - ts.factory.createClassDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, /*members*/ undefined!), // TODO: GH#18217 - ts.factory.createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, ts.factory.createIdentifier("Foo"), ts.factory.createModuleBlock([ts.factory.createEmptyStatement()])) + factory.createNodeArray([ + factory.createClassDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, /*members*/ undefined!), // TODO: GH#18217 + factory.createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, factory.createIdentifier("Foo"), factory.createModuleBlock([factory.createEmptyStatement()])) ]) ); return result; @@ -247,47 +268,47 @@ describe("unittests:: TransformAPI", () => { } }); - function forceNamespaceRewrite(context: ts.TransformationContext) { - return (sourceFile: ts.SourceFile): ts.SourceFile => { + function forceNamespaceRewrite(context: TransformationContext) { + return (sourceFile: SourceFile): SourceFile => { return visitNode(sourceFile); - function visitNode(node: T): T { - if (node.kind === ts.SyntaxKind.ModuleBlock) { - const block = node as T & ts.ModuleBlock; - const statements = ts.factory.createNodeArray([...block.statements]); - return ts.factory.updateModuleBlock(block, statements) as typeof block; + function visitNode(node: T): T { + if (node.kind === SyntaxKind.ModuleBlock) { + const block = node as T & ModuleBlock; + const statements = factory.createNodeArray([...block.statements]); + return factory.updateModuleBlock(block, statements) as typeof block; } - return ts.visitEachChild(node, visitNode, context); + return visitEachChild(node, visitNode, context); } }; } testBaseline("transformAwayExportStar", () => { - return ts.transpileModule("export * from './helper';", { + return transpileModule("export * from './helper';", { transformers: { before: [expandExportStar], }, compilerOptions: { - target: ts.ScriptTarget.ESNext, - newLine: ts.NewLineKind.CarriageReturnLineFeed, + target: ScriptTarget.ESNext, + newLine: NewLineKind.CarriageReturnLineFeed, } }).outputText; - function expandExportStar(context: ts.TransformationContext) { - return (sourceFile: ts.SourceFile): ts.SourceFile => { + function expandExportStar(context: TransformationContext) { + return (sourceFile: SourceFile): SourceFile => { return visitNode(sourceFile); - function visitNode(node: T): T { - if (node.kind === ts.SyntaxKind.ExportDeclaration) { - const ed = node as ts.Node as ts.ExportDeclaration; + function visitNode(node: T): T { + if (node.kind === SyntaxKind.ExportDeclaration) { + const ed = node as Node as ExportDeclaration; const exports = [{ name: "x" }]; - const exportSpecifiers = exports.map(e => ts.factory.createExportSpecifier(/*isTypeOnly*/ false, e.name, e.name)); - const exportClause = ts.factory.createNamedExports(exportSpecifiers); - const newEd = ts.factory.updateExportDeclaration(ed, ed.decorators, ed.modifiers, ed.isTypeOnly, exportClause, ed.moduleSpecifier, ed.assertClause); + const exportSpecifiers = exports.map(e => factory.createExportSpecifier(/*isTypeOnly*/ false, e.name, e.name)); + const exportClause = factory.createNamedExports(exportSpecifiers); + const newEd = factory.updateExportDeclaration(ed, ed.decorators, ed.modifiers, ed.isTypeOnly, exportClause, ed.moduleSpecifier, ed.assertClause); - return newEd as ts.Node as T; + return newEd as Node as T; } - return ts.visitEachChild(node, visitNode, context); + return visitEachChild(node, visitNode, context); } }; } @@ -295,60 +316,60 @@ describe("unittests:: TransformAPI", () => { // https://github.com/Microsoft/TypeScript/issues/19618 testBaseline("transformAddImportStar", () => { - return ts.transpileModule("", { + return transpileModule("", { transformers: { before: [transformAddImportStar], }, compilerOptions: { - target: ts.ScriptTarget.ES5, - module: ts.ModuleKind.System, - newLine: ts.NewLineKind.CarriageReturnLineFeed, + target: ScriptTarget.ES5, + module: ModuleKind.System, + newLine: NewLineKind.CarriageReturnLineFeed, } }).outputText; - function transformAddImportStar(_context: ts.TransformationContext) { - return (sourceFile: ts.SourceFile): ts.SourceFile => { + function transformAddImportStar(_context: TransformationContext) { + return (sourceFile: SourceFile): SourceFile => { return visitNode(sourceFile); }; - function visitNode(sf: ts.SourceFile) { + function visitNode(sf: SourceFile) { // produce `import * as i0 from './comp'; - const importStar = ts.factory.createImportDeclaration( + const importStar = factory.createImportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, - /*importClause*/ ts.factory.createImportClause( + /*importClause*/ factory.createImportClause( /*isTypeOnly*/ false, /*name*/ undefined, - ts.factory.createNamespaceImport(ts.factory.createIdentifier("i0")) + factory.createNamespaceImport(factory.createIdentifier("i0")) ), - /*moduleSpecifier*/ ts.factory.createStringLiteral("./comp1"), + /*moduleSpecifier*/ factory.createStringLiteral("./comp1"), /*assertClause*/ undefined); - return ts.factory.updateSourceFile(sf, [importStar]); + return factory.updateSourceFile(sf, [importStar]); } } }); // https://github.com/Microsoft/TypeScript/issues/17384 testBaseline("transformAddDecoratedNode", () => { - return ts.transpileModule("", { + return transpileModule("", { transformers: { before: [transformAddDecoratedNode], }, compilerOptions: { - target: ts.ScriptTarget.ES5, - newLine: ts.NewLineKind.CarriageReturnLineFeed, + target: ScriptTarget.ES5, + newLine: NewLineKind.CarriageReturnLineFeed, } }).outputText; - function transformAddDecoratedNode(_context: ts.TransformationContext) { - return (sourceFile: ts.SourceFile): ts.SourceFile => { + function transformAddDecoratedNode(_context: TransformationContext) { + return (sourceFile: SourceFile): SourceFile => { return visitNode(sourceFile); }; - function visitNode(sf: ts.SourceFile) { + function visitNode(sf: SourceFile) { // produce `class Foo { @Bar baz() {} }`; - const classDecl = ts.factory.createClassDeclaration([], [], "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [ - ts.factory.createMethodDeclaration([ts.factory.createDecorator(ts.factory.createIdentifier("Bar"))], [], /**/ undefined, "baz", /**/ undefined, /**/ undefined, [], /**/ undefined, ts.factory.createBlock([])) + const classDecl = factory.createClassDeclaration([], [], "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [ + factory.createMethodDeclaration([factory.createDecorator(factory.createIdentifier("Bar"))], [], /**/ undefined, "baz", /**/ undefined, /**/ undefined, [], /**/ undefined, factory.createBlock([])) ]); - return ts.factory.updateSourceFile(sf, [classDecl]); + return factory.updateSourceFile(sf, [classDecl]); } } }); @@ -359,7 +380,7 @@ describe("unittests:: TransformAPI", () => { afterDeclarations: [replaceIdentifiersNamedOldNameWithNewName] }, compilerOptions: { - newLine: ts.NewLineKind.CarriageReturnLineFeed, + newLine: NewLineKind.CarriageReturnLineFeed, declaration: true } }); @@ -367,89 +388,89 @@ describe("unittests:: TransformAPI", () => { // https://github.com/microsoft/TypeScript/issues/33295 testBaseline("transformParameterProperty", () => { - return ts.transpileModule("", { + return transpileModule("", { transformers: { before: [transformAddParameterProperty], }, compilerOptions: { - target: ts.ScriptTarget.ES5, - newLine: ts.NewLineKind.CarriageReturnLineFeed, + target: ScriptTarget.ES5, + newLine: NewLineKind.CarriageReturnLineFeed, } }).outputText; - function transformAddParameterProperty(_context: ts.TransformationContext) { - return (sourceFile: ts.SourceFile): ts.SourceFile => { + function transformAddParameterProperty(_context: TransformationContext) { + return (sourceFile: SourceFile): SourceFile => { return visitNode(sourceFile); }; - function visitNode(sf: ts.SourceFile) { + function visitNode(sf: SourceFile) { // produce `class Foo { constructor(@Dec private x) {} }`; // The decorator is required to trigger ts.ts transformations. - const classDecl = ts.factory.createClassDeclaration([], [], "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [ - ts.factory.createConstructorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, [ - ts.factory.createParameterDeclaration(/*decorators*/ [ts.factory.createDecorator(ts.factory.createIdentifier("Dec"))], /*modifiers*/ [ts.factory.createModifier(ts.SyntaxKind.PrivateKeyword)], /*dotDotDotToken*/ undefined, "x")], ts.factory.createBlock([])) + const classDecl = factory.createClassDeclaration([], [], "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, [ + factory.createConstructorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, [ + factory.createParameterDeclaration(/*decorators*/ [factory.createDecorator(factory.createIdentifier("Dec"))], /*modifiers*/ [factory.createModifier(SyntaxKind.PrivateKeyword)], /*dotDotDotToken*/ undefined, "x")], factory.createBlock([])) ]); - return ts.factory.updateSourceFile(sf, [classDecl]); + return factory.updateSourceFile(sf, [classDecl]); } } }); - function baselineDeclarationTransform(text: string, opts: ts.TranspileOptions) { - const fs = vfs.createFromFileSystem(Harness.IO, /*caseSensitive*/ true, { documents: [new documents.TextDocument("/.src/index.ts", text)] }); - const host = new fakes.CompilerHost(fs, opts.compilerOptions); - const program = ts.createProgram(["/.src/index.ts"], opts.compilerOptions!, host); + function baselineDeclarationTransform(text: string, opts: TranspileOptions) { + const fs = createFromFileSystem(IO, /*caseSensitive*/ true, { documents: [new TextDocument("/.src/index.ts", text)] }); + const host = new CompilerHost(fs, opts.compilerOptions); + const program = createProgram(["/.src/index.ts"], opts.compilerOptions!, host); program.emit(program.getSourceFile("/.src/index.ts"), (p, s, bom) => host.writeFile(p, s, bom), /*cancellationToken*/ undefined, /*onlyDts*/ true, opts.transformers); return fs.readFileSync("/.src/index.d.ts").toString(); } - function addSyntheticComment(nodeFilter: (node: ts.Node) => boolean) { - return (context: ts.TransformationContext) => { - return (sourceFile: ts.SourceFile): ts.SourceFile => { - return ts.visitNode(sourceFile, rootTransform, ts.isSourceFile); + function addSyntheticComment(nodeFilter: (node: Node) => boolean) { + return (context: TransformationContext) => { + return (sourceFile: SourceFile): SourceFile => { + return visitNode(sourceFile, rootTransform, isSourceFile); }; - function rootTransform(node: T): ts.VisitResult { + function rootTransform(node: T): VisitResult { if (nodeFilter(node)) { - ts.setEmitFlags(node, ts.EmitFlags.NoLeadingComments); - ts.setSyntheticLeadingComments(node, [{ kind: ts.SyntaxKind.MultiLineCommentTrivia, text: "comment", pos: -1, end: -1, hasTrailingNewLine: true }]); + setEmitFlags(node, EmitFlags.NoLeadingComments); + setSyntheticLeadingComments(node, [{ kind: SyntaxKind.MultiLineCommentTrivia, text: "comment", pos: -1, end: -1, hasTrailingNewLine: true }]); } - return ts.visitEachChild(node, rootTransform, context); + return visitEachChild(node, rootTransform, context); } }; } // https://github.com/Microsoft/TypeScript/issues/24096 testBaseline("transformAddCommentToArrowReturnValue", () => { - return ts.transpileModule(`const foo = () => + return transpileModule(`const foo = () => void 0 `, { transformers: { - before: [addSyntheticComment(ts.isVoidExpression)], + before: [addSyntheticComment(isVoidExpression)], }, compilerOptions: { - target: ts.ScriptTarget.ES5, - newLine: ts.NewLineKind.CarriageReturnLineFeed, + target: ScriptTarget.ES5, + newLine: NewLineKind.CarriageReturnLineFeed, } }).outputText; }); // https://github.com/Microsoft/TypeScript/issues/17594 testBaseline("transformAddCommentToExportedVar", () => { - return ts.transpileModule(`export const exportedDirectly = 1; + return transpileModule(`export const exportedDirectly = 1; const exportedSeparately = 2; export {exportedSeparately}; `, { transformers: { - before: [addSyntheticComment(ts.isVariableStatement)], + before: [addSyntheticComment(isVariableStatement)], }, compilerOptions: { - target: ts.ScriptTarget.ES5, - newLine: ts.NewLineKind.CarriageReturnLineFeed, + target: ScriptTarget.ES5, + newLine: NewLineKind.CarriageReturnLineFeed, } }).outputText; }); // https://github.com/Microsoft/TypeScript/issues/17594 testBaseline("transformAddCommentToImport", () => { - return ts.transpileModule(` + return transpileModule(` // Previous comment on import. import {Value} from 'somewhere'; import * as X from 'somewhere'; @@ -459,18 +480,18 @@ export * from 'somewhere'; export {Value}; `, { transformers: { - before: [addSyntheticComment(n => ts.isImportDeclaration(n) || ts.isExportDeclaration(n) || ts.isImportSpecifier(n) || ts.isExportSpecifier(n))], + before: [addSyntheticComment(n => isImportDeclaration(n) || isExportDeclaration(n) || isImportSpecifier(n) || isExportSpecifier(n))], }, compilerOptions: { - target: ts.ScriptTarget.ES5, - newLine: ts.NewLineKind.CarriageReturnLineFeed, + target: ScriptTarget.ES5, + newLine: NewLineKind.CarriageReturnLineFeed, } }).outputText; }); // https://github.com/Microsoft/TypeScript/issues/17594 testBaseline("transformAddCommentToProperties", () => { - return ts.transpileModule(` + return transpileModule(` // class comment. class Clazz { // original comment 1. @@ -482,17 +503,17 @@ class Clazz { } `, { transformers: { - before: [addSyntheticComment(n => ts.isPropertyDeclaration(n) || ts.isParameterPropertyDeclaration(n, n.parent) || ts.isClassDeclaration(n) || ts.isConstructorDeclaration(n))], + before: [addSyntheticComment(n => isPropertyDeclaration(n) || isParameterPropertyDeclaration(n, n.parent) || isClassDeclaration(n) || isConstructorDeclaration(n))], }, compilerOptions: { - target: ts.ScriptTarget.ES2015, - newLine: ts.NewLineKind.CarriageReturnLineFeed, + target: ScriptTarget.ES2015, + newLine: NewLineKind.CarriageReturnLineFeed, } }).outputText; }); testBaseline("transformAddCommentToNamespace", () => { - return ts.transpileModule(` + return transpileModule(` // namespace comment. namespace Foo { export const x = 1; @@ -503,17 +524,17 @@ namespace Foo { } `, { transformers: { - before: [addSyntheticComment(n => ts.isModuleDeclaration(n))], + before: [addSyntheticComment(n => isModuleDeclaration(n))], }, compilerOptions: { - target: ts.ScriptTarget.ES2015, - newLine: ts.NewLineKind.CarriageReturnLineFeed, + target: ScriptTarget.ES2015, + newLine: NewLineKind.CarriageReturnLineFeed, } }).outputText; }); testBaseline("transformUpdateModuleMember", () => { - return ts.transpileModule(` + return transpileModule(` module MyModule { const myVariable = 1; function foo(param: string) {} @@ -523,49 +544,49 @@ module MyModule { before: [renameVariable], }, compilerOptions: { - target: ts.ScriptTarget.ES2015, - newLine: ts.NewLineKind.CarriageReturnLineFeed, + target: ScriptTarget.ES2015, + newLine: NewLineKind.CarriageReturnLineFeed, } }).outputText; - function renameVariable(context: ts.TransformationContext) { - return (sourceFile: ts.SourceFile): ts.SourceFile => { - return ts.visitNode(sourceFile, rootTransform, ts.isSourceFile); + function renameVariable(context: TransformationContext) { + return (sourceFile: SourceFile): SourceFile => { + return visitNode(sourceFile, rootTransform, isSourceFile); }; - function rootTransform(node: T): ts.Node { - if (ts.isVariableDeclaration(node)) { - return ts.factory.updateVariableDeclaration(node, ts.factory.createIdentifier("newName"), /*exclamationToken*/ undefined, /*type*/ undefined, node.initializer); + function rootTransform(node: T): Node { + if (isVariableDeclaration(node)) { + return factory.updateVariableDeclaration(node, factory.createIdentifier("newName"), /*exclamationToken*/ undefined, /*type*/ undefined, node.initializer); } - return ts.visitEachChild(node, rootTransform, context); + return visitEachChild(node, rootTransform, context); } } }); // https://github.com/Microsoft/TypeScript/issues/24709 testBaseline("issue24709", () => { - const fs = vfs.createFromFileSystem(Harness.IO, /*caseSensitive*/ true); - const transformed = ts.transform(ts.createSourceFile("source.ts", "class X { echo(x: string) { return x; } }", ts.ScriptTarget.ES3), [transformSourceFile]); + const fs = createFromFileSystem(IO, /*caseSensitive*/ true); + const transformed = transform(createSourceFile("source.ts", "class X { echo(x: string) { return x; } }", ScriptTarget.ES3), [transformSourceFile]); const transformedSourceFile = transformed.transformed[0]; transformed.dispose(); - const host = new fakes.CompilerHost(fs); + const host = new CompilerHost(fs); host.getSourceFile = () => transformedSourceFile; - const program = ts.createProgram(["source.ts"], { - target: ts.ScriptTarget.ES3, - module: ts.ModuleKind.None, + const program = createProgram(["source.ts"], { + target: ScriptTarget.ES3, + module: ModuleKind.None, noLib: true }, host); program.emit(transformedSourceFile, (_p, s, b) => host.writeFile("source.js", s, b)); return host.readFile("source.js")!.toString(); - function transformSourceFile(context: ts.TransformationContext) { - const visitor: ts.Visitor = (node) => { - if (ts.isMethodDeclaration(node)) { - return ts.factory.updateMethodDeclaration( + function transformSourceFile(context: TransformationContext) { + const visitor: Visitor = (node) => { + if (isMethodDeclaration(node)) { + return factory.updateMethodDeclaration( node, node.decorators, node.modifiers, node.asteriskToken, - ts.factory.createIdentifier("foobar"), + factory.createIdentifier("foobar"), node.questionToken, node.typeParameters, node.parameters, @@ -573,65 +594,65 @@ module MyModule { node.body, ); } - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); }; - return (node: ts.SourceFile) => ts.visitNode(node, visitor); + return (node: SourceFile) => visitNode(node, visitor); } }); testBaselineAndEvaluate("templateSpans", () => { - return ts.transpileModule("const x = String.raw`\n\nhello`; exports.stringLength = x.trim().length;", { + return transpileModule("const x = String.raw`\n\nhello`; exports.stringLength = x.trim().length;", { compilerOptions: { - target: ts.ScriptTarget.ESNext, - newLine: ts.NewLineKind.CarriageReturnLineFeed, + target: ScriptTarget.ESNext, + newLine: NewLineKind.CarriageReturnLineFeed, }, transformers: { before: [transformSourceFile] } }).outputText; - function transformSourceFile(context: ts.TransformationContext): ts.Transformer { - function visitor(node: ts.Node): ts.VisitResult { - if (ts.isNoSubstitutionTemplateLiteral(node)) { - return ts.factory.createNoSubstitutionTemplateLiteral(node.text, node.rawText); + function transformSourceFile(context: TransformationContext): Transformer { + function visitor(node: Node): VisitResult { + if (isNoSubstitutionTemplateLiteral(node)) { + return factory.createNoSubstitutionTemplateLiteral(node.text, node.rawText); } else { - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); } } - return sourceFile => ts.visitNode(sourceFile, visitor, ts.isSourceFile); + return sourceFile => visitNode(sourceFile, visitor, isSourceFile); } }, exports => { assert.equal(exports.stringLength, 5); }); - function addStaticFieldWithComment(context: ts.TransformationContext) { - return (sourceFile: ts.SourceFile): ts.SourceFile => { - return ts.visitNode(sourceFile, rootTransform, ts.isSourceFile); + function addStaticFieldWithComment(context: TransformationContext) { + return (sourceFile: SourceFile): SourceFile => { + return visitNode(sourceFile, rootTransform, isSourceFile); }; - function rootTransform(node: T): ts.Node { - if (ts.isClassLike(node)) { - const newMembers = [ts.factory.createPropertyDeclaration(/* decorators */ undefined, [ts.factory.createModifier(ts.SyntaxKind.StaticKeyword)], "newField", /* questionOrExclamationToken */ undefined, /* type */ undefined, ts.factory.createStringLiteral("x"))]; - ts.setSyntheticLeadingComments(newMembers[0], [{ kind: ts.SyntaxKind.MultiLineCommentTrivia, text: "comment", pos: -1, end: -1, hasTrailingNewLine: true }]); - return ts.isClassDeclaration(node) ? - ts.factory.updateClassDeclaration( + function rootTransform(node: T): Node { + if (isClassLike(node)) { + const newMembers = [factory.createPropertyDeclaration(/* decorators */ undefined, [factory.createModifier(SyntaxKind.StaticKeyword)], "newField", /* questionOrExclamationToken */ undefined, /* type */ undefined, factory.createStringLiteral("x"))]; + setSyntheticLeadingComments(newMembers[0], [{ kind: SyntaxKind.MultiLineCommentTrivia, text: "comment", pos: -1, end: -1, hasTrailingNewLine: true }]); + return isClassDeclaration(node) ? + factory.updateClassDeclaration( node, node.decorators, /* modifierFlags */ undefined, node.name, node.typeParameters, node.heritageClauses, newMembers) : - ts.factory.updateClassExpression( + factory.updateClassExpression( node, node.decorators, /* modifierFlags */ undefined, node.name, node.typeParameters, node.heritageClauses, newMembers); } - return ts.visitEachChild(node, rootTransform, context); + return visitEachChild(node, rootTransform, context); } } testBaseline("transformSyntheticCommentOnStaticFieldInClassDeclaration", () => { - return ts.transpileModule(` + return transpileModule(` declare const Decorator: any; @Decorator class MyClass { @@ -641,14 +662,14 @@ class MyClass { before: [addStaticFieldWithComment], }, compilerOptions: { - target: ts.ScriptTarget.ES2015, - newLine: ts.NewLineKind.CarriageReturnLineFeed, + target: ScriptTarget.ES2015, + newLine: NewLineKind.CarriageReturnLineFeed, } }).outputText; }); testBaseline("transformSyntheticCommentOnStaticFieldInClassExpression", () => { - return ts.transpileModule(` + return transpileModule(` const MyClass = class { }; `, { @@ -656,8 +677,8 @@ const MyClass = class { before: [addStaticFieldWithComment], }, compilerOptions: { - target: ts.ScriptTarget.ES2015, - newLine: ts.NewLineKind.CarriageReturnLineFeed, + target: ScriptTarget.ES2015, + newLine: NewLineKind.CarriageReturnLineFeed, } }).outputText; }); diff --git a/src/testRunner/unittests/tsbuild/amdModulesWithOut.ts b/src/testRunner/unittests/tsbuild/amdModulesWithOut.ts index 885b502ba878f..aee1e45b4774b 100644 --- a/src/testRunner/unittests/tsbuild/amdModulesWithOut.ts +++ b/src/testRunner/unittests/tsbuild/amdModulesWithOut.ts @@ -1,10 +1,15 @@ -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; +import { emptyArray } from "../../../compiler/core"; +import { FileSystem } from "../../../harness/vfsUtil"; +import { verifyTsc } from "../tsc/helpers"; +import { + addRest, addShebang, addSpread, addTestPrologue, addTripleSlashRef, appendText, enableStrict, loadProjectFromDisk, + removeRest, replaceText, verifyTscWithEdits, +} from "./helpers"; describe("unittests:: tsbuild:: outFile:: on amd modules with --out", () => { - let outFileFs: vfs.FileSystem; + let outFileFs: FileSystem; before(() => { - outFileFs = ts.loadProjectFromDisk("tests/projects/amdModulesWithOut"); + outFileFs = loadProjectFromDisk("tests/projects/amdModulesWithOut"); }); after(() => { outFileFs = undefined!; @@ -12,8 +17,8 @@ describe("unittests:: tsbuild:: outFile:: on amd modules with --out", () => { interface VerifyOutFileScenarioInput { subScenario: string; - modifyFs?: (fs: vfs.FileSystem) => void; - modifyAgainFs?: (fs: vfs.FileSystem) => void; + modifyFs?: (fs: FileSystem) => void; + modifyAgainFs?: (fs: FileSystem) => void; } function verifyOutFileScenario({ @@ -21,7 +26,7 @@ describe("unittests:: tsbuild:: outFile:: on amd modules with --out", () => { modifyFs, modifyAgainFs }: VerifyOutFileScenarioInput) { - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "amdModulesWithOut", subScenario, fs: () => outFileFs, @@ -31,12 +36,12 @@ describe("unittests:: tsbuild:: outFile:: on amd modules with --out", () => { edits: [ { subScenario: "incremental-declaration-doesnt-change", - modifyFs: fs => ts.appendText(fs, "/src/lib/file1.ts", "console.log(x);") + modifyFs: fs => appendText(fs, "/src/lib/file1.ts", "console.log(x);") }, ...(modifyAgainFs ? [{ subScenario: "incremental-headers-change-without-dts-changes", modifyFs: modifyAgainFs - }] : ts.emptyArray), + }] : emptyArray), ] }); } @@ -51,15 +56,15 @@ describe("unittests:: tsbuild:: outFile:: on amd modules with --out", () => { verifyOutFileScenario({ subScenario: "multiple prologues in all projects", modifyFs: fs => { - ts.enableStrict(fs, "/src/lib/tsconfig.json"); - ts.addTestPrologue(fs, "/src/lib/file0.ts", `"myPrologue"`); - ts.addTestPrologue(fs, "/src/lib/file2.ts", `"myPrologueFile"`); - ts.addTestPrologue(fs, "/src/lib/global.ts", `"myPrologue3"`); - ts.enableStrict(fs, "/src/app/tsconfig.json"); - ts.addTestPrologue(fs, "/src/app/file3.ts", `"myPrologue"`); - ts.addTestPrologue(fs, "/src/app/file4.ts", `"myPrologue2";`); + enableStrict(fs, "/src/lib/tsconfig.json"); + addTestPrologue(fs, "/src/lib/file0.ts", `"myPrologue"`); + addTestPrologue(fs, "/src/lib/file2.ts", `"myPrologueFile"`); + addTestPrologue(fs, "/src/lib/global.ts", `"myPrologue3"`); + enableStrict(fs, "/src/app/tsconfig.json"); + addTestPrologue(fs, "/src/app/file3.ts", `"myPrologue"`); + addTestPrologue(fs, "/src/app/file4.ts", `"myPrologue2";`); }, - modifyAgainFs: fs => ts.addTestPrologue(fs, "/src/lib/file1.ts", `"myPrologue5"`) + modifyAgainFs: fs => addTestPrologue(fs, "/src/lib/file1.ts", `"myPrologue5"`) }); }); @@ -69,9 +74,9 @@ describe("unittests:: tsbuild:: outFile:: on amd modules with --out", () => { verifyOutFileScenario({ subScenario: "shebang in all projects", modifyFs: fs => { - ts.addShebang(fs, "lib", "file0"); - ts.addShebang(fs, "lib", "file1"); - ts.addShebang(fs, "app", "file3"); + addShebang(fs, "lib", "file0"); + addShebang(fs, "lib", "file1"); + addShebang(fs, "app", "file3"); }, }); }); @@ -81,12 +86,12 @@ describe("unittests:: tsbuild:: outFile:: on amd modules with --out", () => { verifyOutFileScenario({ subScenario: "multiple emitHelpers in all projects", modifyFs: fs => { - ts.addSpread(fs, "lib", "file0"); - ts.addRest(fs, "lib", "file1"); - ts.addRest(fs, "app", "file3"); - ts.addSpread(fs, "app", "file4"); + addSpread(fs, "lib", "file0"); + addRest(fs, "lib", "file1"); + addRest(fs, "app", "file3"); + addSpread(fs, "app", "file4"); }, - modifyAgainFs: fs => ts.removeRest(fs, "lib", "file1") + modifyAgainFs: fs => removeRest(fs, "lib", "file1") }); }); @@ -96,19 +101,19 @@ describe("unittests:: tsbuild:: outFile:: on amd modules with --out", () => { verifyOutFileScenario({ subScenario: "triple slash refs in all projects", modifyFs: fs => { - ts.addTripleSlashRef(fs, "lib", "file0"); - ts.addTripleSlashRef(fs, "app", "file4"); + addTripleSlashRef(fs, "lib", "file0"); + addTripleSlashRef(fs, "app", "file4"); } }); }); describe("stripInternal", () => { - function stripInternalScenario(fs: vfs.FileSystem) { + function stripInternalScenario(fs: FileSystem) { const internal = "/*@internal*/"; - ts.replaceText(fs, "/src/app/tsconfig.json", `"composite": true,`, `"composite": true, + replaceText(fs, "/src/app/tsconfig.json", `"composite": true,`, `"composite": true, "stripInternal": true,`); - ts.replaceText(fs, "/src/lib/file0.ts", "const", `${internal} const`); - ts.appendText(fs, "/src/lib/file1.ts", ` + replaceText(fs, "/src/lib/file0.ts", "const", `${internal} const`); + appendText(fs, "/src/lib/file1.ts", ` export class normalC { ${internal} constructor() { } ${internal} prop: string; @@ -140,19 +145,19 @@ ${internal} export enum internalEnum { a, b, c }`); verifyOutFileScenario({ subScenario: "stripInternal", modifyFs: stripInternalScenario, - modifyAgainFs: fs => ts.replaceText(fs, "/src/lib/file1.ts", `export const`, `/*@internal*/ export const`), + modifyAgainFs: fs => replaceText(fs, "/src/lib/file1.ts", `export const`, `/*@internal*/ export const`), }); }); describe("when the module resolution finds original source file", () => { - function modifyFs(fs: vfs.FileSystem) { + function modifyFs(fs: FileSystem) { // Make lib to output to parent dir - ts.replaceText(fs, "/src/lib/tsconfig.json", `"outFile": "module.js"`, `"outFile": "../module.js", "rootDir": "../"`); + replaceText(fs, "/src/lib/tsconfig.json", `"outFile": "module.js"`, `"outFile": "../module.js", "rootDir": "../"`); // Change reference to file1 module to resolve to lib/file1 - ts.replaceText(fs, "/src/app/file3.ts", "file1", "lib/file1"); + replaceText(fs, "/src/app/file3.ts", "file1", "lib/file1"); } - ts.verifyTsc({ + verifyTsc({ scenario: "amdModulesWithOut", subScenario: "when the module resolution finds original source file", fs: () => outFileFs, diff --git a/src/testRunner/unittests/tsbuild/clean.ts b/src/testRunner/unittests/tsbuild/clean.ts index 63b507b1e12e0..61b04ccc7d770 100644 --- a/src/testRunner/unittests/tsbuild/clean.ts +++ b/src/testRunner/unittests/tsbuild/clean.ts @@ -1,11 +1,12 @@ -import * as ts from "../../_namespaces/ts"; +import { verifyTsc } from "../tsc/helpers"; +import { loadProjectFromFiles } from "./helpers"; describe("unittests:: tsbuild - clean", () => { - ts.verifyTsc({ + verifyTsc({ scenario: "clean", subScenario: `file name and output name clashing`, commandLineArgs: ["--b", "/src/tsconfig.json", "-clean"], - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/index.js": "", "/src/bar.ts": "", "/src/tsconfig.json": JSON.stringify({ diff --git a/src/testRunner/unittests/tsbuild/configFileErrors.ts b/src/testRunner/unittests/tsbuild/configFileErrors.ts index 44e50949d7bbc..487a2bad987a8 100644 --- a/src/testRunner/unittests/tsbuild/configFileErrors.ts +++ b/src/testRunner/unittests/tsbuild/configFileErrors.ts @@ -1,23 +1,24 @@ -import * as ts from "../../_namespaces/ts"; -import * as Utils from "../../_namespaces/Utils"; +import { dedent } from "../../../harness/util"; +import { noChangeRun, verifyTsc } from "../tsc/helpers"; +import { appendText, loadProjectFromDisk, loadProjectFromFiles, replaceText, verifyTscWithEdits } from "./helpers"; describe("unittests:: tsbuild:: configFileErrors:: when tsconfig extends the missing file", () => { - ts.verifyTsc({ + verifyTsc({ scenario: "configFileErrors", subScenario: "when tsconfig extends the missing file", - fs: () => ts.loadProjectFromDisk("tests/projects/missingExtendedConfig"), + fs: () => loadProjectFromDisk("tests/projects/missingExtendedConfig"), commandLineArgs: ["--b", "/src/tsconfig.json"], }); }); describe("unittests:: tsbuild:: configFileErrors:: reports syntax errors in config file", () => { - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "configFileErrors", subScenario: "reports syntax errors in config file", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/a.ts": "export function foo() { }", "/src/b.ts": "export function bar() { }", - "/src/tsconfig.json": Utils.dedent` + "/src/tsconfig.json": dedent` { "compilerOptions": { "composite": true, @@ -31,15 +32,15 @@ describe("unittests:: tsbuild:: configFileErrors:: reports syntax errors in conf commandLineArgs: ["--b", "/src/tsconfig.json"], edits: [ { - modifyFs: fs => ts.replaceText(fs, "/src/tsconfig.json", ",", `, + modifyFs: fs => replaceText(fs, "/src/tsconfig.json", ",", `, "declaration": true,`), subScenario: "reports syntax errors after change to config file" }, { - modifyFs: fs => ts.appendText(fs, "/src/a.ts", "export function fooBar() { }"), + modifyFs: fs => appendText(fs, "/src/a.ts", "export function fooBar() { }"), subScenario: "reports syntax errors after change to ts file" }, - ts.noChangeRun, + noChangeRun, { modifyFs: fs => fs.writeFileSync( "/src/tsconfig.json", diff --git a/src/testRunner/unittests/tsbuild/configFileExtends.ts b/src/testRunner/unittests/tsbuild/configFileExtends.ts index 512c3d9a44b00..18d5025117287 100644 --- a/src/testRunner/unittests/tsbuild/configFileExtends.ts +++ b/src/testRunner/unittests/tsbuild/configFileExtends.ts @@ -1,8 +1,9 @@ -import * as ts from "../../_namespaces/ts"; +import { verifyTsc } from "../tsc/helpers"; +import { loadProjectFromFiles } from "./helpers"; describe("unittests:: tsbuild:: configFileExtends:: when tsconfig extends another config", () => { function getConfigExtendsWithIncludeFs() { - return ts.loadProjectFromFiles({ + return loadProjectFromFiles({ "/src/tsconfig.json": JSON.stringify({ references: [ { path: "./shared/tsconfig.json" }, @@ -37,13 +38,13 @@ describe("unittests:: tsbuild:: configFileExtends:: when tsconfig extends anothe "/src/webpack/index.ts": `export const b: Unrestricted = 1;`, }); } - ts.verifyTsc({ + verifyTsc({ scenario: "configFileExtends", subScenario: "when building solution with projects extends config with include", fs: getConfigExtendsWithIncludeFs, commandLineArgs: ["--b", "/src/tsconfig.json", "--v", "--listFiles"], }); - ts.verifyTsc({ + verifyTsc({ scenario: "configFileExtends", subScenario: "when building project uses reference and both extend config with include", fs: getConfigExtendsWithIncludeFs, diff --git a/src/testRunner/unittests/tsbuild/containerOnlyReferenced.ts b/src/testRunner/unittests/tsbuild/containerOnlyReferenced.ts index 1dee22e1e8717..d75b4caf34f52 100644 --- a/src/testRunner/unittests/tsbuild/containerOnlyReferenced.ts +++ b/src/testRunner/unittests/tsbuild/containerOnlyReferenced.ts @@ -1,12 +1,13 @@ -import * as ts from "../../_namespaces/ts"; +import { noChangeOnlyRuns } from "../tsc/helpers"; +import { loadProjectFromDisk, verifyTscWithEdits } from "./helpers"; describe("unittests:: tsbuild:: when containerOnly project is referenced", () => { - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "containerOnlyReferenced", subScenario: "verify that subsequent builds after initial build doesnt build anything", - fs: () => ts.loadProjectFromDisk("tests/projects/containerOnlyReferenced"), + fs: () => loadProjectFromDisk("tests/projects/containerOnlyReferenced"), commandLineArgs: ["--b", "/src", "--verbose"], - edits: ts.noChangeOnlyRuns + edits: noChangeOnlyRuns }); }); diff --git a/src/testRunner/unittests/tsbuild/declarationEmit.ts b/src/testRunner/unittests/tsbuild/declarationEmit.ts index 79fe2e0f809de..5ef3b4a7910bf 100644 --- a/src/testRunner/unittests/tsbuild/declarationEmit.ts +++ b/src/testRunner/unittests/tsbuild/declarationEmit.ts @@ -1,9 +1,10 @@ -import * as ts from "../../_namespaces/ts"; -import * as Utils from "../../_namespaces/Utils"; -import * as vfs from "../../_namespaces/vfs"; +import { dedent } from "../../../harness/util"; +import { FileSet } from "../../../harness/vfsUtil"; +import { verifyTsc } from "../tsc/helpers"; +import { loadProjectFromFiles } from "./helpers"; describe("unittests:: tsbuild:: declarationEmit", () => { - function getFiles(): vfs.FileSet { + function getFiles(): FileSet { return { "/src/solution/tsconfig.base.json": JSON.stringify({ compilerOptions: { @@ -27,7 +28,7 @@ describe("unittests:: tsbuild:: declarationEmit", () => { references: [{ path: "../common" }], include: ["./index.ts"] }), - "/src/solution/src/subProject/index.ts": Utils.dedent` + "/src/solution/src/subProject/index.ts": dedent` import { Nominal } from '../common/nominal'; export type MyNominal = Nominal;`, "/src/solution/src/subProject2/tsconfig.json": JSON.stringify({ @@ -36,7 +37,7 @@ export type MyNominal = Nominal;`, references: [{ path: "../subProject" }], include: ["./index.ts"] }), - "/src/solution/src/subProject2/index.ts": Utils.dedent` + "/src/solution/src/subProject2/index.ts": dedent` import { MyNominal } from '../subProject/index'; const variable = { key: 'value' as MyNominal, @@ -49,26 +50,26 @@ export function getVar(): keyof typeof variable { compilerOptions: { composite: true }, include: ["./nominal.ts"] }), - "/src/solution/src/common/nominal.ts": Utils.dedent` + "/src/solution/src/common/nominal.ts": dedent` /// export declare type Nominal = MyNominal;`, - "/src/solution/src/common/types.d.ts": Utils.dedent` + "/src/solution/src/common/types.d.ts": dedent` declare type MyNominal = T & { specialKey: Name; };`, }; } - ts.verifyTsc({ + verifyTsc({ scenario: "declarationEmit", subScenario: "when declaration file is referenced through triple slash", - fs: () => ts.loadProjectFromFiles(getFiles()), + fs: () => loadProjectFromFiles(getFiles()), commandLineArgs: ["--b", "/src/solution/tsconfig.json", "--verbose"] }); - ts.verifyTsc({ + verifyTsc({ scenario: "declarationEmit", subScenario: "when declaration file is referenced through triple slash but uses no references", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ ...getFiles(), "/src/solution/tsconfig.json": JSON.stringify({ extends: "./tsconfig.base.json", @@ -79,10 +80,10 @@ declare type MyNominal = T & { commandLineArgs: ["--b", "/src/solution/tsconfig.json", "--verbose"] }); - ts.verifyTsc({ + verifyTsc({ scenario: "declarationEmit", subScenario: "when declaration file used inferred type from referenced project", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/tsconfig.json": JSON.stringify({ compilerOptions: { composite: true, @@ -90,7 +91,7 @@ declare type MyNominal = T & { paths: { "@fluentui/*": ["packages/*/src"] } } }), - "/src/packages/pkg1/src/index.ts": Utils.dedent` + "/src/packages/pkg1/src/index.ts": dedent` export interface IThing { a: string; } @@ -102,7 +103,7 @@ export interface IThings { compilerOptions: { outDir: "lib" }, include: ["src"] }), - "/src/packages/pkg2/src/index.ts": Utils.dedent` + "/src/packages/pkg2/src/index.ts": dedent` import { IThings } from '@fluentui/pkg1'; export function fn4() { const a: IThings = { thing1: { a: 'b' } }; diff --git a/src/testRunner/unittests/tsbuild/demo.ts b/src/testRunner/unittests/tsbuild/demo.ts index 45f0a131bbd81..f24ec6ad4ddfb 100644 --- a/src/testRunner/unittests/tsbuild/demo.ts +++ b/src/testRunner/unittests/tsbuild/demo.ts @@ -1,29 +1,30 @@ -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; +import { FileSystem } from "../../../harness/vfsUtil"; +import { verifyTsc } from "../tsc/helpers"; +import { loadProjectFromDisk, prependText, replaceText } from "./helpers"; describe("unittests:: tsbuild:: on demo project", () => { - let projFs: vfs.FileSystem; + let projFs: FileSystem; before(() => { - projFs = ts.loadProjectFromDisk("tests/projects/demo"); + projFs = loadProjectFromDisk("tests/projects/demo"); }); after(() => { projFs = undefined!; // Release the contents }); - ts.verifyTsc({ + verifyTsc({ scenario: "demo", subScenario: "in master branch with everything setup correctly and reports no error", fs: () => projFs, commandLineArgs: ["--b", "/src/tsconfig.json", "--verbose"] }); - ts.verifyTsc({ + verifyTsc({ scenario: "demo", subScenario: "in circular branch reports the error about it by stopping build", fs: () => projFs, commandLineArgs: ["--b", "/src/tsconfig.json", "--verbose"], - modifyFs: fs => ts.replaceText( + modifyFs: fs => replaceText( fs, "/src/core/tsconfig.json", "}", @@ -35,12 +36,12 @@ describe("unittests:: tsbuild:: on demo project", () => { ]` ) }); - ts.verifyTsc({ + verifyTsc({ scenario: "demo", subScenario: "in bad-ref branch reports the error about files not in rootDir at the import location", fs: () => projFs, commandLineArgs: ["--b", "/src/tsconfig.json", "--verbose"], - modifyFs: fs => ts.prependText( + modifyFs: fs => prependText( fs, "/src/core/utilities.ts", `import * as A from '../animals'; diff --git a/src/testRunner/unittests/tsbuild/emitDeclarationOnly.ts b/src/testRunner/unittests/tsbuild/emitDeclarationOnly.ts index 59bb4f0e9a3bd..8b8162f6b5091 100644 --- a/src/testRunner/unittests/tsbuild/emitDeclarationOnly.ts +++ b/src/testRunner/unittests/tsbuild/emitDeclarationOnly.ts @@ -1,52 +1,52 @@ -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; +import { FileSystem } from "../../../harness/vfsUtil"; +import { loadProjectFromDisk, replaceText, verifyTscWithEdits } from "./helpers"; describe("unittests:: tsbuild:: on project with emitDeclarationOnly set to true", () => { - let projFs: vfs.FileSystem; + let projFs: FileSystem; before(() => { - projFs = ts.loadProjectFromDisk("tests/projects/emitDeclarationOnly"); + projFs = loadProjectFromDisk("tests/projects/emitDeclarationOnly"); }); after(() => { projFs = undefined!; }); function verifyEmitDeclarationOnly(disableMap?: true) { - ts.verifyTscWithEdits({ + verifyTscWithEdits({ subScenario: `only dts output in circular import project with emitDeclarationOnly${disableMap ? "" : " and declarationMap"}`, fs: () => projFs, scenario: "emitDeclarationOnly", commandLineArgs: ["--b", "/src", "--verbose"], modifyFs: disableMap ? - (fs => ts.replaceText(fs, "/src/tsconfig.json", `"declarationMap": true,`, "")) : + (fs => replaceText(fs, "/src/tsconfig.json", `"declarationMap": true,`, "")) : undefined, edits: [{ subScenario: "incremental-declaration-changes", - modifyFs: fs => ts.replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"), + modifyFs: fs => replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"), }], }); } verifyEmitDeclarationOnly(); verifyEmitDeclarationOnly(/*disableMap*/ true); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ subScenario: `only dts output in non circular imports project with emitDeclarationOnly`, fs: () => projFs, scenario: "emitDeclarationOnly", commandLineArgs: ["--b", "/src", "--verbose"], modifyFs: fs => { fs.rimrafSync("/src/src/index.ts"); - ts.replaceText(fs, "/src/src/a.ts", `import { B } from "./b";`, `export class B { prop = "hello"; }`); + replaceText(fs, "/src/src/a.ts", `import { B } from "./b";`, `export class B { prop = "hello"; }`); }, edits: [ { subScenario: "incremental-declaration-doesnt-change", - modifyFs: fs => ts.replaceText(fs, "/src/src/a.ts", "export interface A {", `class C { } + modifyFs: fs => replaceText(fs, "/src/src/a.ts", "export interface A {", `class C { } export interface A {`), }, { subScenario: "incremental-declaration-changes", - modifyFs: fs => ts.replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"), + modifyFs: fs => replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"), }, ], }); diff --git a/src/testRunner/unittests/tsbuild/emptyFiles.ts b/src/testRunner/unittests/tsbuild/emptyFiles.ts index 1326e594cbc42..1a8a5910ffefd 100644 --- a/src/testRunner/unittests/tsbuild/emptyFiles.ts +++ b/src/testRunner/unittests/tsbuild/emptyFiles.ts @@ -1,23 +1,24 @@ -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; +import { FileSystem } from "../../../harness/vfsUtil"; +import { verifyTsc } from "../tsc/helpers"; +import { loadProjectFromDisk } from "./helpers"; describe("unittests:: tsbuild - empty files option in tsconfig", () => { - let projFs: vfs.FileSystem; + let projFs: FileSystem; before(() => { - projFs = ts.loadProjectFromDisk("tests/projects/empty-files"); + projFs = loadProjectFromDisk("tests/projects/empty-files"); }); after(() => { projFs = undefined!; }); - ts.verifyTsc({ + verifyTsc({ scenario: "emptyFiles", subScenario: "has empty files diagnostic when files is empty and no references are provided", fs: () => projFs, commandLineArgs: ["--b", "/src/no-references"], }); - ts.verifyTsc({ + verifyTsc({ scenario: "emptyFiles", subScenario: "does not have empty files diagnostic when files is empty and references are provided", fs: () => projFs, diff --git a/src/testRunner/unittests/tsbuild/exitCodeOnBogusFile.ts b/src/testRunner/unittests/tsbuild/exitCodeOnBogusFile.ts index a582423aea340..1f4b3dd0f3ea3 100644 --- a/src/testRunner/unittests/tsbuild/exitCodeOnBogusFile.ts +++ b/src/testRunner/unittests/tsbuild/exitCodeOnBogusFile.ts @@ -1,11 +1,12 @@ -import * as ts from "../../_namespaces/ts"; +import { verifyTsc } from "../tsc/helpers"; +import { loadProjectFromFiles } from "./helpers"; // https://github.com/microsoft/TypeScript/issues/33849 describe("unittests:: tsbuild:: exitCodeOnBogusFile:: test exit code", () => { - ts.verifyTsc({ + verifyTsc({ scenario: "exitCodeOnBogusFile", subScenario: `test exit code`, - fs: () => ts.loadProjectFromFiles({}), + fs: () => loadProjectFromFiles({}), commandLineArgs: ["-b", "bogus.json"] }); }); diff --git a/src/testRunner/unittests/tsbuild/graphOrdering.ts b/src/testRunner/unittests/tsbuild/graphOrdering.ts index feab9b890c291..0a9addf6cdddc 100644 --- a/src/testRunner/unittests/tsbuild/graphOrdering.ts +++ b/src/testRunner/unittests/tsbuild/graphOrdering.ts @@ -1,9 +1,12 @@ -import * as fakes from "../../_namespaces/fakes"; -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; +import { + createSolutionBuilder, getBuildOrderFromAnyBuildOrder, isCircularBuildOrder, +} from "../../../compiler/tsbuildPublic"; +import { ResolvedConfigFileName } from "../../../compiler/types"; +import { SolutionBuilderHost } from "../../../harness/fakesHosts"; +import { FileSystem } from "../../../harness/vfsUtil"; describe("unittests:: tsbuild - graph-ordering", () => { - let host: fakes.SolutionBuilderHost | undefined; + let host: SolutionBuilderHost | undefined; const deps: [string, string][] = [ ["A", "B"], ["B", "C"], @@ -19,8 +22,8 @@ describe("unittests:: tsbuild - graph-ordering", () => { ]; before(() => { - const fs = new vfs.FileSystem(false); - host = fakes.SolutionBuilderHost.create(fs); + const fs = new FileSystem(false); + host = SolutionBuilderHost.create(fs); writeProjects(fs, ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"], deps); }); @@ -50,10 +53,10 @@ describe("unittests:: tsbuild - graph-ordering", () => { }); function checkGraphOrdering(rootNames: string[], expectedBuildSet: string[], circular?: true) { - const builder = ts.createSolutionBuilder(host!, rootNames.map(getProjectFileName), { dry: true, force: false, verbose: false }); + const builder = createSolutionBuilder(host!, rootNames.map(getProjectFileName), { dry: true, force: false, verbose: false }); const buildOrder = builder.getBuildOrder(); - assert.equal(ts.isCircularBuildOrder(buildOrder), !!circular); - const buildQueue = ts.getBuildOrderFromAnyBuildOrder(buildOrder); + assert.equal(isCircularBuildOrder(buildOrder), !!circular); + const buildQueue = getBuildOrderFromAnyBuildOrder(buildOrder); assert.deepEqual(buildQueue, expectedBuildSet.map(getProjectFileName)); if (!circular) { @@ -67,10 +70,10 @@ describe("unittests:: tsbuild - graph-ordering", () => { } function getProjectFileName(proj: string) { - return `/project/${proj}/tsconfig.json` as ts.ResolvedConfigFileName; + return `/project/${proj}/tsconfig.json` as ResolvedConfigFileName; } - function writeProjects(fileSystem: vfs.FileSystem, projectNames: string[], deps: [string, string][]): string[] { + function writeProjects(fileSystem: FileSystem, projectNames: string[], deps: [string, string][]): string[] { const projFileNames: string[] = []; for (const dep of deps) { if (projectNames.indexOf(dep[0]) < 0) throw new Error(`Invalid dependency - project ${dep[0]} does not exist`); diff --git a/src/testRunner/unittests/tsbuild/helpers.ts b/src/testRunner/unittests/tsbuild/helpers.ts index 9b4ed88b7d294..5b68e6ed282ad 100644 --- a/src/testRunner/unittests/tsbuild/helpers.ts +++ b/src/testRunner/unittests/tsbuild/helpers.ts @@ -1,29 +1,59 @@ +import { + BuilderFileEmit, ProgramBuildInfoFileId, ProgramBuildInfoFileIdListId, ProgramBuildInfoReferencedMap, + ReusableDiagnostic, toBuilderStateFileInfo, +} from "../../../compiler/builder"; +import { BuilderState } from "../../../compiler/builderState"; +import { + arrayFrom, arrayIsEqualTo, createGetCanonicalFileName, emptyArray, findIndex, first, getEntries, hasProperty, + isNumber, isString, last, length, mapDefinedIterator, +} from "../../../compiler/core"; +import { Map, MapLike, ReadonlyCollection } from "../../../compiler/corePublic"; +import { Debug } from "../../../compiler/debug"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { + getBuildInfo, getBuildInfoText, getOutputPathsForBundle, getTsBuildInfoEmitOutputFilePath, isBuildInfoFile, +} from "../../../compiler/emitter"; +import { fileExtensionIs, toPath } from "../../../compiler/path"; +import { System } from "../../../compiler/sys"; +import { + BuildInfo, BundleFileInfo, BundleFileSection, BundleFileSectionKind, CompilerOptions, Path, +} from "../../../compiler/types"; +import { outFile } from "../../../compiler/utilities"; +import { isBuild } from "../../../executeCommandLine/executeCommandLine"; +import { + ExpectedDiagnostic, ExpectedDiagnosticLocation, ExpectedDiagnosticMessage, ExpectedErrorDiagnostic, + SolutionBuilderHost, version, +} from "../../../harness/fakesHosts"; +import { Baseline, Compiler, IO } from "../../../harness/harnessIO"; +import { getSourceMapRecordWithSystem } from "../../../harness/sourceMapRecorder"; +import { createResolver, FileSet, FileSystem, Mount } from "../../../harness/vfsUtil"; +import { libFile } from "../../../harness/virtualFileSystemWithWatch"; +import { resolve } from "../../../harness/vpathUtil"; import * as fakes from "../../_namespaces/fakes"; -import * as Harness from "../../_namespaces/Harness"; import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; -import * as vpath from "../../_namespaces/vpath"; +import { testTscCompile, TestTscCompile, TscCompileSystem, verifyTscBaseline } from "../tsc/helpers"; +import { WatchedSystem } from "../tscWatch/helpers"; -export function errorDiagnostic(message: fakes.ExpectedDiagnosticMessage): fakes.ExpectedErrorDiagnostic { +export function errorDiagnostic(message: ExpectedDiagnosticMessage): ExpectedErrorDiagnostic { return { message }; } -export function getExpectedDiagnosticForProjectsInBuild(...projects: string[]): fakes.ExpectedDiagnostic { - return [ts.Diagnostics.Projects_in_this_build_Colon_0, projects.map(p => "\r\n * " + p).join("")]; +export function getExpectedDiagnosticForProjectsInBuild(...projects: string[]): ExpectedDiagnostic { + return [Diagnostics.Projects_in_this_build_Colon_0, projects.map(p => "\r\n * " + p).join("")]; } -export function changeCompilerVersion(host: fakes.SolutionBuilderHost) { +export function changeCompilerVersion(host: SolutionBuilderHost) { const originalReadFile = host.readFile; host.readFile = path => { const value = originalReadFile.call(host, path); - if (!value || !ts.isBuildInfoFile(path)) return value; - const buildInfo = ts.getBuildInfo(value); - buildInfo.version = fakes.version; - return ts.getBuildInfoText(buildInfo); + if (!value || !isBuildInfoFile(path)) return value; + const buildInfo = getBuildInfo(value); + buildInfo.version = version; + return getBuildInfoText(buildInfo); }; } -export function replaceText(fs: vfs.FileSystem, path: string, oldText: string, newText: string) { +export function replaceText(fs: FileSystem, path: string, oldText: string, newText: string) { if (!fs.statSync(path).isFile()) { throw new Error(`File ${path} does not exist`); } @@ -35,7 +65,7 @@ export function replaceText(fs: vfs.FileSystem, path: string, oldText: string, n fs.writeFileSync(path, newContent, "utf-8"); } -export function prependText(fs: vfs.FileSystem, path: string, additionalContent: string) { +export function prependText(fs: FileSystem, path: string, additionalContent: string) { if (!fs.statSync(path).isFile()) { throw new Error(`File ${path} does not exist`); } @@ -43,7 +73,7 @@ export function prependText(fs: vfs.FileSystem, path: string, additionalContent: fs.writeFileSync(path, `${additionalContent}${old}`, "utf-8"); } -export function appendText(fs: vfs.FileSystem, path: string, additionalContent: string) { +export function appendText(fs: FileSystem, path: string, additionalContent: string) { if (!fs.statSync(path).isFile()) { throw new Error(`File ${path} does not exist`); } @@ -51,7 +81,7 @@ export function appendText(fs: vfs.FileSystem, path: string, additionalContent: fs.writeFileSync(path, `${old}${additionalContent}`); } -export function indexOf(fs: vfs.FileSystem, path: string, searchStr: string) { +export function indexOf(fs: FileSystem, path: string, searchStr: string) { if (!fs.statSync(path).isFile()) { throw new Error(`File ${path} does not exist`); } @@ -59,7 +89,7 @@ export function indexOf(fs: vfs.FileSystem, path: string, searchStr: string) { return content.indexOf(searchStr); } -export function lastIndexOf(fs: vfs.FileSystem, path: string, searchStr: string) { +export function lastIndexOf(fs: FileSystem, path: string, searchStr: string) { if (!fs.statSync(path).isFile()) { throw new Error(`File ${path} does not exist`); } @@ -67,7 +97,7 @@ export function lastIndexOf(fs: vfs.FileSystem, path: string, searchStr: string) return content.lastIndexOf(searchStr); } -export function expectedLocationIndexOf(fs: vfs.FileSystem, file: string, searchStr: string): fakes.ExpectedDiagnosticLocation { +export function expectedLocationIndexOf(fs: FileSystem, file: string, searchStr: string): ExpectedDiagnosticLocation { return { file, start: indexOf(fs, file, searchStr), @@ -75,7 +105,7 @@ export function expectedLocationIndexOf(fs: vfs.FileSystem, file: string, search }; } -export function expectedLocationLastIndexOf(fs: vfs.FileSystem, file: string, searchStr: string): fakes.ExpectedDiagnosticLocation { +export function expectedLocationLastIndexOf(fs: FileSystem, file: string, searchStr: string): ExpectedDiagnosticLocation { return { file, start: lastIndexOf(fs, file, searchStr), @@ -83,7 +113,7 @@ export function expectedLocationLastIndexOf(fs: vfs.FileSystem, file: string, se }; } -export const libContent = `${ts.TestFSWithWatch.libFile.content} +export const libContent = `${libFile.content} interface ReadonlyArray {} declare const console: { log(msg: any): void; };`; @@ -104,11 +134,11 @@ interface Symbol { export function loadProjectFromDisk( root: string, libContentToAppend?: string -): vfs.FileSystem { - const resolver = vfs.createResolver(Harness.IO); - const fs = new vfs.FileSystem(/*ignoreCase*/ true, { +): FileSystem { + const resolver = createResolver(IO); + const fs = new FileSystem(/*ignoreCase*/ true, { files: { - ["/src"]: new vfs.Mount(vpath.resolve(Harness.IO.getWorkspaceRoot(), root), resolver) + ["/src"]: new Mount(resolve(IO.getWorkspaceRoot(), root), resolver) }, cwd: "/", meta: { defaultLibLocation: "/lib" }, @@ -121,10 +151,10 @@ export function loadProjectFromDisk( * All the files must be in /src */ export function loadProjectFromFiles( - files: vfs.FileSet, + files: FileSet, libContentToAppend?: string -): vfs.FileSystem { - const fs = new vfs.FileSystem(/*ignoreCase*/ true, { +): FileSystem { + const fs = new FileSystem(/*ignoreCase*/ true, { files, cwd: "/", meta: { defaultLibLocation: "/lib" }, @@ -133,50 +163,50 @@ export function loadProjectFromFiles( return fs; } -function addLibAndMakeReadonly(fs: vfs.FileSystem, libContentToAppend?: string) { +function addLibAndMakeReadonly(fs: FileSystem, libContentToAppend?: string) { fs.mkdirSync("/lib"); fs.writeFileSync("/lib/lib.d.ts", libContentToAppend ? `${libContent}${libContentToAppend}` : libContent); fs.makeReadonly(); } -export function verifyOutputsPresent(fs: vfs.FileSystem, outputs: readonly string[]) { +export function verifyOutputsPresent(fs: FileSystem, outputs: readonly string[]) { for (const output of outputs) { assert(fs.existsSync(output), `Expect file ${output} to exist`); } } -export function verifyOutputsAbsent(fs: vfs.FileSystem, outputs: readonly string[]) { +export function verifyOutputsAbsent(fs: FileSystem, outputs: readonly string[]) { for (const output of outputs) { assert.isFalse(fs.existsSync(output), `Expect file ${output} to not exist`); } } -export function generateSourceMapBaselineFiles(sys: ts.System & { writtenFiles: ts.ReadonlyCollection; }) { - const mapFileNames = ts.mapDefinedIterator(sys.writtenFiles.keys(), f => f.endsWith(".map") ? f : undefined); +export function generateSourceMapBaselineFiles(sys: System & { writtenFiles: ReadonlyCollection; }) { + const mapFileNames = mapDefinedIterator(sys.writtenFiles.keys(), f => f.endsWith(".map") ? f : undefined); while (true) { const result = mapFileNames.next(); if (result.done) break; const mapFile = result.value; - const text = Harness.SourceMapRecorder.getSourceMapRecordWithSystem(sys, mapFile); + const text = getSourceMapRecordWithSystem(sys, mapFile); sys.writeFile(`${mapFile}.baseline.txt`, text); } } -function generateBundleFileSectionInfo(sys: ts.System, originalReadCall: ts.System["readFile"], baselineRecorder: Harness.Compiler.WriterAggregator, bundleFileInfo: ts.BundleFileInfo | undefined, outFile: string | undefined) { - if (!ts.length(bundleFileInfo && bundleFileInfo.sections) && !outFile) return; // Nothing to baseline +function generateBundleFileSectionInfo(sys: System, originalReadCall: System["readFile"], baselineRecorder: Compiler.WriterAggregator, bundleFileInfo: BundleFileInfo | undefined, outFile: string | undefined) { + if (!length(bundleFileInfo && bundleFileInfo.sections) && !outFile) return; // Nothing to baseline const content = outFile && sys.fileExists(outFile) ? originalReadCall.call(sys, outFile, "utf8")! : ""; baselineRecorder.WriteLine("======================================================================"); baselineRecorder.WriteLine(`File:: ${outFile}`); - for (const section of bundleFileInfo ? bundleFileInfo.sections : ts.emptyArray) { + for (const section of bundleFileInfo ? bundleFileInfo.sections : emptyArray) { baselineRecorder.WriteLine("----------------------------------------------------------------------"); writeSectionHeader(section); - if (section.kind !== ts.BundleFileSectionKind.Prepend) { + if (section.kind !== BundleFileSectionKind.Prepend) { writeTextOfSection(section.pos, section.end); } else if (section.texts.length > 0) { - ts.Debug.assert(section.pos === ts.first(section.texts).pos); - ts.Debug.assert(section.end === ts.last(section.texts).end); + Debug.assert(section.pos === first(section.texts).pos); + Debug.assert(section.end === last(section.texts).end); for (const text of section.texts) { baselineRecorder.WriteLine(">>--------------------------------------------------------------------"); writeSectionHeader(text); @@ -184,7 +214,7 @@ function generateBundleFileSectionInfo(sys: ts.System, originalReadCall: ts.Syst } } else { - ts.Debug.assert(section.pos === section.end); + Debug.assert(section.pos === section.end); } } baselineRecorder.WriteLine("======================================================================"); @@ -196,27 +226,27 @@ function generateBundleFileSectionInfo(sys: ts.System, originalReadCall: ts.Syst } } - function writeSectionHeader(section: ts.BundleFileSection) { - baselineRecorder.WriteLine(`${section.kind}: (${section.pos}-${section.end})${section.data ? ":: " + section.data : ""}${section.kind === ts.BundleFileSectionKind.Prepend ? " texts:: " + section.texts.length : ""}`); + function writeSectionHeader(section: BundleFileSection) { + baselineRecorder.WriteLine(`${section.kind}: (${section.pos}-${section.end})${section.data ? ":: " + section.data : ""}${section.kind === BundleFileSectionKind.Prepend ? " texts:: " + section.texts.length : ""}`); } } -type ReadableProgramBuildInfoDiagnostic = string | [string, readonly ts.ReusableDiagnostic[]]; +type ReadableProgramBuildInfoDiagnostic = string | [string, readonly ReusableDiagnostic[]]; type ReadableProgramBuilderInfoFilePendingEmit = [string, "DtsOnly" | "Full"]; interface ReadableProgramBuildInfo { fileNames: readonly string[]; fileNamesList: readonly (readonly string[])[] | undefined; - fileInfos: ts.MapLike; - options: ts.CompilerOptions | undefined; - referencedMap?: ts.MapLike; - exportedModulesMap?: ts.MapLike; + fileInfos: MapLike; + options: CompilerOptions | undefined; + referencedMap?: MapLike; + exportedModulesMap?: MapLike; semanticDiagnosticsPerFile?: readonly ReadableProgramBuildInfoDiagnostic[]; affectedFilesPendingEmit?: readonly ReadableProgramBuilderInfoFilePendingEmit[]; } -type ReadableBuildInfo = Omit & { program: ReadableProgramBuildInfo | undefined; size: number; }; -function generateBuildInfoProgramBaseline(sys: ts.System, buildInfoPath: string, buildInfo: ts.BuildInfo) { +type ReadableBuildInfo = Omit & { program: ReadableProgramBuildInfo | undefined; size: number; }; +function generateBuildInfoProgramBaseline(sys: System, buildInfoPath: string, buildInfo: BuildInfo) { const fileInfos: ReadableProgramBuildInfo["fileInfos"] = {}; - buildInfo.program?.fileInfos.forEach((fileInfo, index) => fileInfos[toFileName(index + 1 as ts.ProgramBuildInfoFileId)] = ts.toBuilderStateFileInfo(fileInfo)); + buildInfo.program?.fileInfos.forEach((fileInfo, index) => fileInfos[toFileName(index + 1 as ProgramBuildInfoFileId)] = toBuilderStateFileInfo(fileInfo)); const fileNamesList = buildInfo.program?.fileIdsList?.map(fileIdsListId => fileIdsListId.map(toFileName)); const program: ReadableProgramBuildInfo | undefined = buildInfo.program && { fileNames: buildInfo.program.fileNames, @@ -226,15 +256,15 @@ function generateBuildInfoProgramBaseline(sys: ts.System, buildInfoPath: string, referencedMap: toMapOfReferencedSet(buildInfo.program.referencedMap), exportedModulesMap: toMapOfReferencedSet(buildInfo.program.exportedModulesMap), semanticDiagnosticsPerFile: buildInfo.program.semanticDiagnosticsPerFile?.map(d => - ts.isNumber(d) ? + isNumber(d) ? toFileName(d) : [toFileName(d[0]), d[1]] ), affectedFilesPendingEmit: buildInfo.program.affectedFilesPendingEmit?.map(([fileId, emitKind]) => [ toFileName(fileId), - emitKind === ts.BuilderFileEmit.DtsOnly ? "DtsOnly" : - emitKind === ts.BuilderFileEmit.Full ? "Full" : - ts.Debug.assertNever(emitKind) + emitKind === BuilderFileEmit.DtsOnly ? "DtsOnly" : + emitKind === BuilderFileEmit.Full ? "Full" : + Debug.assertNever(emitKind) ]), }; const version = buildInfo.version === ts.version ? fakes.version : buildInfo.version; @@ -242,22 +272,22 @@ function generateBuildInfoProgramBaseline(sys: ts.System, buildInfoPath: string, bundle: buildInfo.bundle, program, version, - size: ts.getBuildInfoText({ ...buildInfo, version }).length, + size: getBuildInfoText({ ...buildInfo, version }).length, }; // For now its just JSON.stringify sys.writeFile(`${buildInfoPath}.readable.baseline.txt`, JSON.stringify(result, /*replacer*/ undefined, 2)); - function toFileName(fileId: ts.ProgramBuildInfoFileId) { + function toFileName(fileId: ProgramBuildInfoFileId) { return buildInfo.program!.fileNames[fileId - 1]; } - function toFileNames(fileIdsListId: ts.ProgramBuildInfoFileIdListId) { + function toFileNames(fileIdsListId: ProgramBuildInfoFileIdListId) { return fileNamesList![fileIdsListId - 1]; } - function toMapOfReferencedSet(referenceMap: ts.ProgramBuildInfoReferencedMap | undefined): ts.MapLike | undefined { + function toMapOfReferencedSet(referenceMap: ProgramBuildInfoReferencedMap | undefined): MapLike | undefined { if (!referenceMap) return undefined; - const result: ts.MapLike = {}; + const result: MapLike = {}; for (const [fileNamesKey, fileNamesListKey] of referenceMap) { result[toFileName(fileNamesKey)] = toFileNames(fileNamesListKey); } @@ -265,29 +295,29 @@ function generateBuildInfoProgramBaseline(sys: ts.System, buildInfoPath: string, } } -export function toPathWithSystem(sys: ts.System, fileName: string): ts.Path { - return ts.toPath(fileName, sys.getCurrentDirectory(), ts.createGetCanonicalFileName(sys.useCaseSensitiveFileNames)); +export function toPathWithSystem(sys: System, fileName: string): Path { + return toPath(fileName, sys.getCurrentDirectory(), createGetCanonicalFileName(sys.useCaseSensitiveFileNames)); } export function baselineBuildInfo( - options: ts.CompilerOptions, - sys: ts.TscCompileSystem | ts.tscWatch.WatchedSystem, - originalReadCall?: ts.System["readFile"], + options: CompilerOptions, + sys: TscCompileSystem | WatchedSystem, + originalReadCall?: System["readFile"], ) { - const buildInfoPath = ts.getTsBuildInfoEmitOutputFilePath(options); + const buildInfoPath = getTsBuildInfoEmitOutputFilePath(options); if (!buildInfoPath || !sys.writtenFiles!.has(toPathWithSystem(sys, buildInfoPath))) return; if (!sys.fileExists(buildInfoPath)) return; - const buildInfo = ts.getBuildInfo((originalReadCall || sys.readFile).call(sys, buildInfoPath, "utf8")!); + const buildInfo = getBuildInfo((originalReadCall || sys.readFile).call(sys, buildInfoPath, "utf8")!); generateBuildInfoProgramBaseline(sys, buildInfoPath, buildInfo); - if (!ts.outFile(options)) return; - const { jsFilePath, declarationFilePath } = ts.getOutputPathsForBundle(options, /*forceDts*/ false); + if (!outFile(options)) return; + const { jsFilePath, declarationFilePath } = getOutputPathsForBundle(options, /*forceDts*/ false); const bundle = buildInfo.bundle; - if (!bundle || (!ts.length(bundle.js && bundle.js.sections) && !ts.length(bundle.dts && bundle.dts.sections))) return; + if (!bundle || (!length(bundle.js && bundle.js.sections) && !length(bundle.dts && bundle.dts.sections))) return; // Write the baselines: - const baselineRecorder = new Harness.Compiler.WriterAggregator(); + const baselineRecorder = new Compiler.WriterAggregator(); generateBundleFileSectionInfo(sys, originalReadCall || sys.readFile, baselineRecorder, bundle.js, jsFilePath); generateBundleFileSectionInfo(sys, originalReadCall || sys.readFile, baselineRecorder, bundle.dts, declarationFilePath); baselineRecorder.Close(); @@ -296,14 +326,14 @@ export function baselineBuildInfo( } interface VerifyTscEditDiscrepanciesInput { index: number; - scenario: ts.TestTscCompile["scenario"]; - subScenario: ts.TestTscCompile["subScenario"]; + scenario: TestTscCompile["scenario"]; + subScenario: TestTscCompile["subScenario"]; baselines: string[] | undefined; - commandLineArgs: ts.TestTscCompile["commandLineArgs"]; - modifyFs: ts.TestTscCompile["modifyFs"]; + commandLineArgs: TestTscCompile["commandLineArgs"]; + modifyFs: TestTscCompile["modifyFs"]; editFs: TestTscEdit["modifyFs"]; - baseFs: vfs.FileSystem; - newSys: ts.TscCompileSystem; + baseFs: FileSystem; + newSys: TscCompileSystem; discrepancyExplanation: TestTscEdit["discrepancyExplanation"]; } function verifyTscEditDiscrepancies({ @@ -311,7 +341,7 @@ function verifyTscEditDiscrepancies({ discrepancyExplanation, baselines, modifyFs, editFs, baseFs, newSys }: VerifyTscEditDiscrepanciesInput): string[] | undefined { - const sys = ts.testTscCompile({ + const sys = testTscCompile({ scenario, subScenario, fs: () => baseFs.makeReadonly(), @@ -323,16 +353,16 @@ function verifyTscEditDiscrepancies({ disableUseFileVersionAsSignature: true, }); let headerAdded = false; - for (const outputFile of ts.arrayFrom(sys.writtenFiles.keys())) { + for (const outputFile of arrayFrom(sys.writtenFiles.keys())) { const cleanBuildText = sys.readFile(outputFile); const incrementalBuildText = newSys.readFile(outputFile); - if (ts.isBuildInfoFile(outputFile)) { + if (isBuildInfoFile(outputFile)) { // Check only presence and absence and not text as we will do that for readable baseline if (!sys.fileExists(`${outputFile}.readable.baseline.txt`)) addBaseline(`Readable baseline not present in clean build:: File:: ${outputFile}`); if (!newSys.fileExists(`${outputFile}.readable.baseline.txt`)) addBaseline(`Readable baseline not present in incremental build:: File:: ${outputFile}`); verifyPresenceAbsence(incrementalBuildText, cleanBuildText, `Incremental and clean tsbuildinfo file presence differs:: File:: ${outputFile}`); } - else if (!ts.fileExtensionIs(outputFile, ".tsbuildinfo.readable.baseline.txt")) { + else if (!fileExtensionIs(outputFile, ".tsbuildinfo.readable.baseline.txt")) { verifyTextEqual(incrementalBuildText, cleanBuildText, `File: ${outputFile}`); } else if (incrementalBuildText !== cleanBuildText) { @@ -360,7 +390,7 @@ function verifyTscEditDiscrepancies({ incrementalReadableBuildInfo?.program?.exportedModulesMap, cleanReadableBuildInfo?.program?.exportedModulesMap, (key, incrementalReferenceSet, cleanReferenceSet) => { - if (!ts.arrayIsEqualTo(incrementalReferenceSet, cleanReferenceSet) && !ts.arrayIsEqualTo(incrementalReferenceSet, incrementalReadableBuildInfo!.program!.referencedMap![key])) { + if (!arrayIsEqualTo(incrementalReferenceSet, cleanReferenceSet) && !arrayIsEqualTo(incrementalReferenceSet, incrementalReadableBuildInfo!.program!.referencedMap![key])) { return [ `Incremental Reference set is neither from dts nor files reference map for File:: ${key}::`, `Incremental:: ${JSON.stringify(incrementalReferenceSet, /*replacer*/ undefined, 2)}`, @@ -383,7 +413,7 @@ function verifyTscEditDiscrepancies({ } let expectedIndex = 0; incrementalReadableBuildInfo.program.affectedFilesPendingEmit.forEach(([actualFile]) => { - expectedIndex = ts.findIndex(cleanReadableBuildInfo!.program!.affectedFilesPendingEmit!, ([expectedFile]) => actualFile === expectedFile, expectedIndex); + expectedIndex = findIndex(cleanReadableBuildInfo!.program!.affectedFilesPendingEmit!, ([expectedFile]) => actualFile === expectedFile, expectedIndex); if (expectedIndex === -1) { addBaseline( `Incremental build contains ${actualFile} file as pending emit, clean build does not have it: ${outputFile}::`, @@ -403,11 +433,11 @@ function verifyTscEditDiscrepancies({ if (incrementalText !== cleanText) writeNotEqual(incrementalText, cleanText, message); } - function verifyMapLike(incremental: ts.MapLike | undefined, clean: ts.MapLike | undefined, verifyValue: (key: string, incrementalValue: T, cleanValue: T) => string[] | undefined, message: string) { + function verifyMapLike(incremental: MapLike | undefined, clean: MapLike | undefined, verifyValue: (key: string, incrementalValue: T, cleanValue: T) => string[] | undefined, message: string) { verifyPresenceAbsence(incremental, clean, `Incremental and clean do not match:: ${message}`); if (!incremental || !clean) return; - const incrementalMap = new ts.Map(ts.getEntries(incremental)); - const cleanMap = new ts.Map(ts.getEntries(clean)); + const incrementalMap = new Map(getEntries(incremental)); + const cleanMap = new Map(getEntries(clean)); if (incrementalMap.size !== cleanMap.size) { addBaseline( `Incremental and clean size of maps do not match:: ${message}`, @@ -446,9 +476,9 @@ function verifyTscEditDiscrepancies({ addBaseline( message, "CleanBuild:", - ts.isString(expected) ? expected : JSON.stringify(expected), + isString(expected) ? expected : JSON.stringify(expected), "IncrementalBuild:", - ts.isString(actual) ? actual : JSON.stringify(actual), + isString(actual) ? actual : JSON.stringify(actual), ); } @@ -467,11 +497,11 @@ function getBuildInfoForIncrementalCorrectnessCheck(text: string | undefined): { } { if (!text) return { buildInfo: text }; const readableBuildInfo = JSON.parse(text) as ReadableBuildInfo; - let sanitizedFileInfos: ts.MapLike | undefined; + let sanitizedFileInfos: MapLike | undefined; if (readableBuildInfo.program?.fileInfos) { sanitizedFileInfos = {}; for (const id in readableBuildInfo.program.fileInfos) { - if (ts.hasProperty(readableBuildInfo.program.fileInfos, id)) { + if (hasProperty(readableBuildInfo.program.fileInfos, id)) { sanitizedFileInfos[id] = { ...readableBuildInfo.program.fileInfos[id], signature: undefined }; } } @@ -501,14 +531,14 @@ export enum CleanBuildDescrepancy { } export interface TestTscEdit { - modifyFs: (fs: vfs.FileSystem) => void; + modifyFs: (fs: FileSystem) => void; subScenario: string; commandLineArgs?: readonly string[]; /** An array of lines to be printed in order when a discrepancy is detected */ discrepancyExplanation?: () => readonly string[]; } -export interface VerifyTscWithEditsInput extends ts.TestTscCompile { +export interface VerifyTscWithEditsInput extends TestTscCompile { edits: TestTscEdit[]; } @@ -521,13 +551,13 @@ export function verifyTscWithEdits({ edits }: VerifyTscWithEditsInput) { describe(`tsc ${commandLineArgs.join(" ")} ${scenario}:: ${subScenario} serializedEdits`, () => { - let sys: ts.TscCompileSystem; - let baseFs: vfs.FileSystem; - let editsSys: ts.TscCompileSystem[]; + let sys: TscCompileSystem; + let baseFs: FileSystem; + let editsSys: TscCompileSystem[]; before(() => { - ts.Debug.assert(!!edits.length, `${scenario}/${subScenario}:: No incremental scenarios, you probably want to use verifyTsc instead.`); + Debug.assert(!!edits.length, `${scenario}/${subScenario}:: No incremental scenarios, you probably want to use verifyTsc instead.`); baseFs = fs().makeReadonly(); - sys = ts.testTscCompile({ + sys = testTscCompile({ scenario, subScenario, fs: () => baseFs, @@ -541,7 +571,7 @@ export function verifyTscWithEdits({ { modifyFs, subScenario: editScenario, commandLineArgs: editCommandLineArgs }, index ) => { - (editsSys || (editsSys = [])).push(ts.testTscCompile({ + (editsSys || (editsSys = [])).push(testTscCompile({ scenario, subScenario: editScenario || subScenario, diffWithInitial: true, @@ -559,7 +589,7 @@ export function verifyTscWithEdits({ sys = undefined!; editsSys = undefined!; }); - ts.verifyTscBaseline(() => ({ + verifyTscBaseline(() => ({ baseLine: () => { const { file, text } = sys.baseLine(); const texts: string[] = [text]; @@ -592,24 +622,24 @@ export function verifyTscWithEdits({ modifyFs }); } - Harness.Baseline.runBaseline( - `${ts.isBuild(commandLineArgs) ? "tsbuild" : "tsc"}/${scenario}/${subScenario.split(" ").join("-")}-discrepancies.js`, + Baseline.runBaseline( + `${isBuild(commandLineArgs) ? "tsbuild" : "tsc"}/${scenario}/${subScenario.split(" ").join("-")}-discrepancies.js`, baselines ? baselines.join("\r\n") : null // eslint-disable-line no-null/no-null ); }); }); } -export function enableStrict(fs: vfs.FileSystem, path: string) { +export function enableStrict(fs: FileSystem, path: string) { replaceText(fs, path, `"strict": false`, `"strict": true`); } -export function addTestPrologue(fs: vfs.FileSystem, path: string, prologue: string) { +export function addTestPrologue(fs: FileSystem, path: string, prologue: string) { prependText(fs, path, `${prologue} `); } -export function addShebang(fs: vfs.FileSystem, project: string, file: string) { +export function addShebang(fs: FileSystem, project: string, file: string) { prependText(fs, `src/${project}/${file}.ts`, `#!someshebang ${project} ${file} `); } @@ -624,23 +654,23 @@ function nonrestContent(project: string, file: string) { return `function for${project}${file}Rest() { }`; } -export function addRest(fs: vfs.FileSystem, project: string, file: string) { +export function addRest(fs: FileSystem, project: string, file: string) { appendText(fs, `src/${project}/${file}.ts`, restContent(project, file)); } -export function removeRest(fs: vfs.FileSystem, project: string, file: string) { +export function removeRest(fs: FileSystem, project: string, file: string) { replaceText(fs, `src/${project}/${file}.ts`, restContent(project, file), nonrestContent(project, file)); } -export function addStubFoo(fs: vfs.FileSystem, project: string, file: string) { +export function addStubFoo(fs: FileSystem, project: string, file: string) { appendText(fs, `src/${project}/${file}.ts`, nonrestContent(project, file)); } -export function changeStubToRest(fs: vfs.FileSystem, project: string, file: string) { +export function changeStubToRest(fs: FileSystem, project: string, file: string) { replaceText(fs, `src/${project}/${file}.ts`, nonrestContent(project, file), restContent(project, file)); } -export function addSpread(fs: vfs.FileSystem, project: string, file: string) { +export function addSpread(fs: FileSystem, project: string, file: string) { const path = `src/${project}/${file}.ts`; const content = fs.readFileSync(path, "utf8"); fs.writeFileSync(path, `${content} @@ -656,7 +686,7 @@ export function getTripleSlashRef(project: string) { return `/src/${project}/tripleRef.d.ts`; } -export function addTripleSlashRef(fs: vfs.FileSystem, project: string, file: string) { +export function addTripleSlashRef(fs: FileSystem, project: string, file: string) { fs.writeFileSync(getTripleSlashRef(project), `declare class ${project}${file} { }`); prependText(fs, `src/${project}/${file}.ts`, `/// const ${file}Const = new ${project}${file}(); diff --git a/src/testRunner/unittests/tsbuild/inferredTypeFromTransitiveModule.ts b/src/testRunner/unittests/tsbuild/inferredTypeFromTransitiveModule.ts index ca06b25faaa26..7ff5f4fc6814f 100644 --- a/src/testRunner/unittests/tsbuild/inferredTypeFromTransitiveModule.ts +++ b/src/testRunner/unittests/tsbuild/inferredTypeFromTransitiveModule.ts @@ -1,16 +1,16 @@ -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; +import { FileSystem } from "../../../harness/vfsUtil"; +import { appendText, loadProjectFromDisk, replaceText, verifyTscWithEdits } from "./helpers"; describe("unittests:: tsbuild:: inferredTypeFromTransitiveModule::", () => { - let projFs: vfs.FileSystem; + let projFs: FileSystem; before(() => { - projFs = ts.loadProjectFromDisk("tests/projects/inferredTypeFromTransitiveModule"); + projFs = loadProjectFromDisk("tests/projects/inferredTypeFromTransitiveModule"); }); after(() => { projFs = undefined!; }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "inferredTypeFromTransitiveModule", subScenario: "inferred type from transitive module", fs: () => projFs, @@ -27,7 +27,7 @@ describe("unittests:: tsbuild:: inferredTypeFromTransitiveModule::", () => { ], }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ subScenario: "inferred type from transitive module with isolatedModules", fs: () => projFs, scenario: "inferredTypeFromTransitiveModule", @@ -45,14 +45,14 @@ describe("unittests:: tsbuild:: inferredTypeFromTransitiveModule::", () => { ] }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "inferredTypeFromTransitiveModule", subScenario: "reports errors in files affected by change in signature with isolatedModules", fs: () => projFs, commandLineArgs: ["--b", "/src", "--verbose"], modifyFs: fs => { changeToIsolatedModules(fs); - ts.appendText(fs, "/src/lazyIndex.ts", ` + appendText(fs, "/src/lazyIndex.ts", ` import { default as bar } from './bar'; bar("hello");`); }, @@ -71,22 +71,22 @@ bar("hello");`); }, { subScenario: "Fix Error", - modifyFs: fs => ts.replaceText(fs, "/src/lazyIndex.ts", `bar("hello")`, "bar()") + modifyFs: fs => replaceText(fs, "/src/lazyIndex.ts", `bar("hello")`, "bar()") }, ] }); }); -function changeToIsolatedModules(fs: vfs.FileSystem) { - ts.replaceText(fs, "/src/tsconfig.json", `"incremental": true`, `"incremental": true, "isolatedModules": true`); +function changeToIsolatedModules(fs: FileSystem) { + replaceText(fs, "/src/tsconfig.json", `"incremental": true`, `"incremental": true, "isolatedModules": true`); } -function changeBarParam(fs: vfs.FileSystem) { - ts.replaceText(fs, "/src/bar.ts", "param: string", ""); +function changeBarParam(fs: FileSystem) { + replaceText(fs, "/src/bar.ts", "param: string", ""); } -function changeBarParamBack(fs: vfs.FileSystem) { - ts.replaceText(fs, "/src/bar.ts", "foobar()", "foobar(param: string)"); +function changeBarParamBack(fs: FileSystem) { + replaceText(fs, "/src/bar.ts", "foobar()", "foobar(param: string)"); } export { }; diff --git a/src/testRunner/unittests/tsbuild/javascriptProjectEmit.ts b/src/testRunner/unittests/tsbuild/javascriptProjectEmit.ts index 568a269afea5a..fe4339059b859 100644 --- a/src/testRunner/unittests/tsbuild/javascriptProjectEmit.ts +++ b/src/testRunner/unittests/tsbuild/javascriptProjectEmit.ts @@ -1,19 +1,20 @@ -import * as ts from "../../_namespaces/ts"; -import * as Utils from "../../_namespaces/Utils"; +import { dedent } from "../../../harness/util"; +import { verifyTsc } from "../tsc/helpers"; +import { loadProjectFromFiles, replaceText, symbolLibContent, verifyTscWithEdits } from "./helpers"; describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { - ts.verifyTsc({ + verifyTsc({ scenario: "javascriptProjectEmit", subScenario: `loads js-based projects and emits them correctly`, - fs: () => ts.loadProjectFromFiles({ - "/src/common/nominal.js": Utils.dedent` + fs: () => loadProjectFromFiles({ + "/src/common/nominal.js": dedent` /** * @template T, Name * @typedef {T & {[Symbol.species]: Name}} Nominal */ module.exports = {}; `, - "/src/common/tsconfig.json": Utils.dedent` + "/src/common/tsconfig.json": dedent` { "extends": "../tsconfig.base.json", "compilerOptions": { @@ -21,14 +22,14 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { }, "include": ["nominal.js"] }`, - "/src/sub-project/index.js": Utils.dedent` + "/src/sub-project/index.js": dedent` import { Nominal } from '../common/nominal'; /** * @typedef {Nominal} MyNominal */ `, - "/src/sub-project/tsconfig.json": Utils.dedent` + "/src/sub-project/tsconfig.json": dedent` { "extends": "../tsconfig.base.json", "compilerOptions": { @@ -39,7 +40,7 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { ], "include": ["./index.js"] }`, - "/src/sub-project-2/index.js": Utils.dedent` + "/src/sub-project-2/index.js": dedent` import { MyNominal } from '../sub-project/index'; const variable = { @@ -53,7 +54,7 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { return 'key'; } `, - "/src/sub-project-2/tsconfig.json": Utils.dedent` + "/src/sub-project-2/tsconfig.json": dedent` { "extends": "../tsconfig.base.json", "compilerOptions": { @@ -64,7 +65,7 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { ], "include": ["./index.js"] }`, - "/src/tsconfig.json": Utils.dedent` + "/src/tsconfig.json": dedent` { "compilerOptions": { "composite": true @@ -75,7 +76,7 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { ], "include": [] }`, - "/src/tsconfig.base.json": Utils.dedent` + "/src/tsconfig.base.json": dedent` { "compilerOptions": { "skipLibCheck": true, @@ -86,21 +87,21 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { "declaration": true } }`, - }, ts.symbolLibContent), + }, symbolLibContent), commandLineArgs: ["-b", "/src"] }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "javascriptProjectEmit", subScenario: `modifies outfile js projects and concatenates them correctly`, - fs: () => ts.loadProjectFromFiles({ - "/src/common/nominal.js": Utils.dedent` + fs: () => loadProjectFromFiles({ + "/src/common/nominal.js": dedent` /** * @template T, Name * @typedef {T & {[Symbol.species]: Name}} Nominal */ `, - "/src/common/tsconfig.json": Utils.dedent` + "/src/common/tsconfig.json": dedent` { "extends": "../tsconfig.base.json", "compilerOptions": { @@ -110,13 +111,13 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { }, "include": ["nominal.js"] }`, - "/src/sub-project/index.js": Utils.dedent` + "/src/sub-project/index.js": dedent` /** * @typedef {Nominal} MyNominal */ const c = /** @type {*} */(null); `, - "/src/sub-project/tsconfig.json": Utils.dedent` + "/src/sub-project/tsconfig.json": dedent` { "extends": "../tsconfig.base.json", "compilerOptions": { @@ -129,7 +130,7 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { ], "include": ["./index.js"] }`, - "/src/sub-project-2/index.js": Utils.dedent` + "/src/sub-project-2/index.js": dedent` const variable = { key: /** @type {MyNominal} */('value'), }; @@ -141,7 +142,7 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { return 'key'; } `, - "/src/sub-project-2/tsconfig.json": Utils.dedent` + "/src/sub-project-2/tsconfig.json": dedent` { "extends": "../tsconfig.base.json", "compilerOptions": { @@ -154,7 +155,7 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { ], "include": ["./index.js"] }`, - "/src/tsconfig.json": Utils.dedent` + "/src/tsconfig.json": dedent` { "compilerOptions": { "composite": true, @@ -166,7 +167,7 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { ], "include": [] }`, - "/src/tsconfig.base.json": Utils.dedent` + "/src/tsconfig.base.json": dedent` { "compilerOptions": { "skipLibCheck": true, @@ -176,27 +177,27 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { "declaration": true } }`, - }, ts.symbolLibContent), + }, symbolLibContent), commandLineArgs: ["-b", "/src"], edits: [{ subScenario: "incremental-declaration-doesnt-change", - modifyFs: fs => ts.replaceText(fs, "/src/sub-project/index.js", "null", "undefined") + modifyFs: fs => replaceText(fs, "/src/sub-project/index.js", "null", "undefined") }] }); - ts.verifyTsc({ + verifyTsc({ scenario: "javascriptProjectEmit", subScenario: `loads js-based projects with non-moved json files and emits them correctly`, - fs: () => ts.loadProjectFromFiles({ - "/src/common/obj.json": Utils.dedent` + fs: () => loadProjectFromFiles({ + "/src/common/obj.json": dedent` { "val": 42 }`, - "/src/common/index.ts": Utils.dedent` + "/src/common/index.ts": dedent` import x = require("./obj.json"); export = x; `, - "/src/common/tsconfig.json": Utils.dedent` + "/src/common/tsconfig.json": dedent` { "extends": "../tsconfig.base.json", "compilerOptions": { @@ -205,12 +206,12 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { }, "include": ["index.ts", "obj.json"] }`, - "/src/sub-project/index.js": Utils.dedent` + "/src/sub-project/index.js": dedent` import mod from '../common'; export const m = mod; `, - "/src/sub-project/tsconfig.json": Utils.dedent` + "/src/sub-project/tsconfig.json": dedent` { "extends": "../tsconfig.base.json", "compilerOptions": { @@ -221,7 +222,7 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { ], "include": ["./index.js"] }`, - "/src/sub-project-2/index.js": Utils.dedent` + "/src/sub-project-2/index.js": dedent` import { m } from '../sub-project/index'; const variable = { @@ -232,7 +233,7 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { return variable; } `, - "/src/sub-project-2/tsconfig.json": Utils.dedent` + "/src/sub-project-2/tsconfig.json": dedent` { "extends": "../tsconfig.base.json", "compilerOptions": { @@ -243,7 +244,7 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { ], "include": ["./index.js"] }`, - "/src/tsconfig.json": Utils.dedent` + "/src/tsconfig.json": dedent` { "compilerOptions": { "composite": true @@ -254,7 +255,7 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { ], "include": [] }`, - "/src/tsconfig.base.json": Utils.dedent` + "/src/tsconfig.base.json": dedent` { "compilerOptions": { "skipLibCheck": true, @@ -267,7 +268,7 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => { "declaration": true } }`, - }, ts.symbolLibContent), + }, symbolLibContent), commandLineArgs: ["-b", "/src"] }); }); diff --git a/src/testRunner/unittests/tsbuild/lateBoundSymbol.ts b/src/testRunner/unittests/tsbuild/lateBoundSymbol.ts index 8ff3d6cea656c..c22dc94460f21 100644 --- a/src/testRunner/unittests/tsbuild/lateBoundSymbol.ts +++ b/src/testRunner/unittests/tsbuild/lateBoundSymbol.ts @@ -1,19 +1,19 @@ -import * as ts from "../../_namespaces/ts"; +import { appendText, loadProjectFromDisk, replaceText, verifyTscWithEdits } from "./helpers"; describe("unittests:: tsbuild:: lateBoundSymbol:: interface is merged and contains late bound member", () => { - ts.verifyTscWithEdits({ + verifyTscWithEdits({ subScenario: "interface is merged and contains late bound member", - fs: () => ts.loadProjectFromDisk("tests/projects/lateBoundSymbol"), + fs: () => loadProjectFromDisk("tests/projects/lateBoundSymbol"), scenario: "lateBoundSymbol", commandLineArgs: ["--b", "/src/tsconfig.json", "--verbose"], edits: [ { subScenario: "incremental-declaration-doesnt-change", - modifyFs: fs => ts.replaceText(fs, "/src/src/main.ts", "const x = 10;", ""), + modifyFs: fs => replaceText(fs, "/src/src/main.ts", "const x = 10;", ""), }, { subScenario: "incremental-declaration-doesnt-change", - modifyFs: fs => ts.appendText(fs, "/src/src/main.ts", "const x = 10;"), + modifyFs: fs => appendText(fs, "/src/src/main.ts", "const x = 10;"), }, ] }); diff --git a/src/testRunner/unittests/tsbuild/moduleResolution.ts b/src/testRunner/unittests/tsbuild/moduleResolution.ts index f83e9a4994f99..492aab602dd1a 100644 --- a/src/testRunner/unittests/tsbuild/moduleResolution.ts +++ b/src/testRunner/unittests/tsbuild/moduleResolution.ts @@ -1,32 +1,38 @@ -import * as ts from "../../_namespaces/ts"; -import * as Utils from "../../_namespaces/Utils"; +import { emptyArray } from "../../../compiler/core"; +import { CompilerOptions } from "../../../compiler/types"; +import { dedent } from "../../../harness/util"; +import { verifyTsc } from "../tsc/helpers"; +import { + createWatchedSystem, libFile, projectRoot, replaceFileText, runQueuedTimeoutCallbacks, verifyTscWatch, +} from "../tscWatch/helpers"; +import { loadProjectFromFiles } from "./helpers"; describe("unittests:: tsbuild:: moduleResolution:: handles the modules and options from referenced project correctly", () => { - function sys(optionsToExtend?: ts.CompilerOptions) { - return ts.tscWatch.createWatchedSystem([ + function sys(optionsToExtend?: CompilerOptions) { + return createWatchedSystem([ { - path: `${ts.tscWatch.projectRoot}/packages/pkg1/index.ts`, - content: Utils.dedent` + path: `${projectRoot}/packages/pkg1/index.ts`, + content: dedent` import type { TheNum } from 'pkg2' export const theNum: TheNum = 42;` }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg1/tsconfig.json`, + path: `${projectRoot}/packages/pkg1/tsconfig.json`, content: JSON.stringify({ compilerOptions: { outDir: "build", ...optionsToExtend }, references: [{ path: "../pkg2" }] }) }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg2/const.ts`, + path: `${projectRoot}/packages/pkg2/const.ts`, content: `export type TheNum = 42;` }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg2/index.ts`, + path: `${projectRoot}/packages/pkg2/index.ts`, content: `export type { TheNum } from 'const';` }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg2/tsconfig.json`, + path: `${projectRoot}/packages/pkg2/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, @@ -37,7 +43,7 @@ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and optio }) }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg2/package.json`, + path: `${projectRoot}/packages/pkg2/package.json`, content: JSON.stringify({ name: "pkg2", version: "1.0.0", @@ -45,35 +51,35 @@ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and optio }) }, { - path: `${ts.tscWatch.projectRoot}/node_modules/pkg2`, - symLink: `${ts.tscWatch.projectRoot}/packages/pkg2`, + path: `${projectRoot}/node_modules/pkg2`, + symLink: `${projectRoot}/packages/pkg2`, }, - ts.tscWatch.libFile - ], { currentDirectory: ts.tscWatch.projectRoot }); + libFile + ], { currentDirectory: projectRoot }); } - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "moduleResolution", subScenario: `resolves specifier in output declaration file from referenced project correctly`, sys, commandLineArgs: ["-b", "packages/pkg1", "--verbose", "--traceResolution"], - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "moduleResolution", subScenario: `resolves specifier in output declaration file from referenced project correctly with preserveSymlinks`, sys: () => sys({ preserveSymlinks: true }), commandLineArgs: ["-b", "packages/pkg1", "--verbose", "--traceResolution"], - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "moduleResolution", subScenario: `resolves specifier in output declaration file from referenced project correctly with cts and mts extensions`, - sys: () => ts.tscWatch.createWatchedSystem([ + sys: () => createWatchedSystem([ { - path: `${ts.tscWatch.projectRoot}/packages/pkg1/package.json`, + path: `${projectRoot}/packages/pkg1/package.json`, content: JSON.stringify({ name: "pkg1", version: "1.0.0", @@ -82,13 +88,13 @@ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and optio }) }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg1/index.ts`, - content: Utils.dedent` + path: `${projectRoot}/packages/pkg1/index.ts`, + content: dedent` import type { TheNum } from 'pkg2' export const theNum: TheNum = 42;` }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg1/tsconfig.json`, + path: `${projectRoot}/packages/pkg1/tsconfig.json`, content: JSON.stringify({ compilerOptions: { outDir: "build", @@ -98,15 +104,15 @@ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and optio }) }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg2/const.cts`, + path: `${projectRoot}/packages/pkg2/const.cts`, content: `export type TheNum = 42;` }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg2/index.ts`, + path: `${projectRoot}/packages/pkg2/index.ts`, content: `export type { TheNum } from './const.cjs';` }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg2/tsconfig.json`, + path: `${projectRoot}/packages/pkg2/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, @@ -116,7 +122,7 @@ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and optio }) }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg2/package.json`, + path: `${projectRoot}/packages/pkg2/package.json`, content: JSON.stringify({ name: "pkg2", version: "1.0.0", @@ -125,65 +131,65 @@ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and optio }) }, { - path: `${ts.tscWatch.projectRoot}/node_modules/pkg2`, - symLink: `${ts.tscWatch.projectRoot}/packages/pkg2`, + path: `${projectRoot}/node_modules/pkg2`, + symLink: `${projectRoot}/packages/pkg2`, }, - { ...ts.tscWatch.libFile, path: `/a/lib/lib.es2022.full.d.ts` } - ], { currentDirectory: ts.tscWatch.projectRoot }), + { ...libFile, path: `/a/lib/lib.es2022.full.d.ts` } + ], { currentDirectory: projectRoot }), commandLineArgs: ["-b", "packages/pkg1", "-w", "--verbose", "--traceResolution"], changes: [ { caption: "reports import errors after change to package file", - change: sys => ts.tscWatch.replaceFileText(sys, `${ts.tscWatch.projectRoot}/packages/pkg1/package.json`, `"module"`, `"commonjs"`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => replaceFileText(sys, `${projectRoot}/packages/pkg1/package.json`, `"module"`, `"commonjs"`), + timeouts: runQueuedTimeoutCallbacks, }, { caption: "removes those errors when a package file is changed back", - change: sys => ts.tscWatch.replaceFileText(sys, `${ts.tscWatch.projectRoot}/packages/pkg1/package.json`, `"commonjs"`, `"module"`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => replaceFileText(sys, `${projectRoot}/packages/pkg1/package.json`, `"commonjs"`, `"module"`), + timeouts: runQueuedTimeoutCallbacks, }, { caption: "reports import errors after change to package file", - change: sys => ts.tscWatch.replaceFileText(sys, `${ts.tscWatch.projectRoot}/packages/pkg1/package.json`, `"module"`, `"commonjs"`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => replaceFileText(sys, `${projectRoot}/packages/pkg1/package.json`, `"module"`, `"commonjs"`), + timeouts: runQueuedTimeoutCallbacks, }, { caption: "removes those errors when a package file is changed to cjs extensions", change: sys => { - ts.tscWatch.replaceFileText(sys, `${ts.tscWatch.projectRoot}/packages/pkg2/package.json`, `"build/index.js"`, `"build/index.cjs"`); - sys.renameFile(`${ts.tscWatch.projectRoot}/packages/pkg2/index.ts`, `${ts.tscWatch.projectRoot}/packages/pkg2/index.cts`); + replaceFileText(sys, `${projectRoot}/packages/pkg2/package.json`, `"build/index.js"`, `"build/index.cjs"`); + sys.renameFile(`${projectRoot}/packages/pkg2/index.ts`, `${projectRoot}/packages/pkg2/index.cts`); }, - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }, ] }); - ts.verifyTsc({ + verifyTsc({ scenario: "moduleResolution", subScenario: `type reference resolution uses correct options for different resolution options referenced project`, - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/packages/pkg1_index.ts": `export const theNum: TheNum = "type1";`, "/src/packages/pkg1.tsconfig.json": JSON.stringify({ compilerOptions: { composite: true, typeRoots: ["./typeroot1"] }, files: ["./pkg1_index.ts"] }), - "/src/packages/typeroot1/sometype/index.d.ts": Utils.dedent`declare type TheNum = "type1";`, + "/src/packages/typeroot1/sometype/index.d.ts": dedent`declare type TheNum = "type1";`, "/src/packages/pkg2_index.ts": `export const theNum: TheNum2 = "type2";`, "/src/packages/pkg2.tsconfig.json": JSON.stringify({ compilerOptions: { composite: true, typeRoots: ["./typeroot2"] }, files: ["./pkg2_index.ts"] }), - "/src/packages/typeroot2/sometype/index.d.ts": Utils.dedent`declare type TheNum2 = "type2";`, + "/src/packages/typeroot2/sometype/index.d.ts": dedent`declare type TheNum2 = "type2";`, }), commandLineArgs: ["-b", "/src/packages/pkg1.tsconfig.json", "/src/packages/pkg2.tsconfig.json", "--verbose", "--traceResolution"], }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "moduleResolution", subScenario: `watches for changes to package-json main fields`, - sys: () => ts.tscWatch.createWatchedSystem([ + sys: () => createWatchedSystem([ { - path: `${ts.tscWatch.projectRoot}/packages/pkg1/package.json`, + path: `${projectRoot}/packages/pkg1/package.json`, content: JSON.stringify({ name: "pkg1", version: "1.0.0", @@ -191,13 +197,13 @@ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and optio }) }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg1/index.ts`, - content: Utils.dedent` + path: `${projectRoot}/packages/pkg1/index.ts`, + content: dedent` import type { TheNum } from 'pkg2' export const theNum: TheNum = 42;` }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg1/tsconfig.json`, + path: `${projectRoot}/packages/pkg1/tsconfig.json`, content: JSON.stringify({ compilerOptions: { outDir: "build", @@ -205,19 +211,19 @@ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and optio }) }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg2/build/const.d.ts`, + path: `${projectRoot}/packages/pkg2/build/const.d.ts`, content: `export type TheNum = 42;` }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg2/build/index.d.ts`, + path: `${projectRoot}/packages/pkg2/build/index.d.ts`, content: `export type { TheNum } from './const.js';` }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg2/build/other.d.ts`, + path: `${projectRoot}/packages/pkg2/build/other.d.ts`, content: `export type TheStr = string;` }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg2/package.json`, + path: `${projectRoot}/packages/pkg2/package.json`, content: JSON.stringify({ name: "pkg2", version: "1.0.0", @@ -225,33 +231,33 @@ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and optio }) }, { - path: `${ts.tscWatch.projectRoot}/node_modules/pkg2`, - symLink: `${ts.tscWatch.projectRoot}/packages/pkg2`, + path: `${projectRoot}/node_modules/pkg2`, + symLink: `${projectRoot}/packages/pkg2`, }, - ts.tscWatch.libFile - ], { currentDirectory: ts.tscWatch.projectRoot }), + libFile + ], { currentDirectory: projectRoot }), commandLineArgs: ["--project", "./packages/pkg1/tsconfig.json", "-w", "--traceResolution"], changes: [ { caption: "reports import errors after change to package file", - change: sys => ts.tscWatch.replaceFileText(sys, `${ts.tscWatch.projectRoot}/packages/pkg2/package.json`, `index.js`, `other.js`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => replaceFileText(sys, `${projectRoot}/packages/pkg2/package.json`, `index.js`, `other.js`), + timeouts: runQueuedTimeoutCallbacks, }, { caption: "removes those errors when a package file is changed back", - change: sys => ts.tscWatch.replaceFileText(sys, `${ts.tscWatch.projectRoot}/packages/pkg2/package.json`, `other.js`, `index.js`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => replaceFileText(sys, `${projectRoot}/packages/pkg2/package.json`, `other.js`, `index.js`), + timeouts: runQueuedTimeoutCallbacks, }, ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "moduleResolution", subScenario: `build mode watches for changes to package-json main fields`, - sys: () => ts.tscWatch.createWatchedSystem([ + sys: () => createWatchedSystem([ { - path: `${ts.tscWatch.projectRoot}/packages/pkg1/package.json`, + path: `${projectRoot}/packages/pkg1/package.json`, content: JSON.stringify({ name: "pkg1", version: "1.0.0", @@ -259,13 +265,13 @@ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and optio }) }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg1/index.ts`, - content: Utils.dedent` + path: `${projectRoot}/packages/pkg1/index.ts`, + content: dedent` import type { TheNum } from 'pkg2' export const theNum: TheNum = 42;` }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg1/tsconfig.json`, + path: `${projectRoot}/packages/pkg1/tsconfig.json`, content: JSON.stringify({ compilerOptions: { outDir: "build", @@ -274,7 +280,7 @@ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and optio }) }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg2/tsconfig.json`, + path: `${projectRoot}/packages/pkg2/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, @@ -284,19 +290,19 @@ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and optio }) }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg2/const.ts`, + path: `${projectRoot}/packages/pkg2/const.ts`, content: `export type TheNum = 42;` }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg2/index.ts`, + path: `${projectRoot}/packages/pkg2/index.ts`, content: `export type { TheNum } from './const.js';` }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg2/other.ts`, + path: `${projectRoot}/packages/pkg2/other.ts`, content: `export type TheStr = string;` }, { - path: `${ts.tscWatch.projectRoot}/packages/pkg2/package.json`, + path: `${projectRoot}/packages/pkg2/package.json`, content: JSON.stringify({ name: "pkg2", version: "1.0.0", @@ -304,22 +310,22 @@ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and optio }) }, { - path: `${ts.tscWatch.projectRoot}/node_modules/pkg2`, - symLink: `${ts.tscWatch.projectRoot}/packages/pkg2`, + path: `${projectRoot}/node_modules/pkg2`, + symLink: `${projectRoot}/packages/pkg2`, }, - ts.tscWatch.libFile - ], { currentDirectory: ts.tscWatch.projectRoot }), + libFile + ], { currentDirectory: projectRoot }), commandLineArgs: ["-b", "packages/pkg1", "--verbose", "-w", "--traceResolution"], changes: [ { caption: "reports import errors after change to package file", - change: sys => ts.tscWatch.replaceFileText(sys, `${ts.tscWatch.projectRoot}/packages/pkg2/package.json`, `index.js`, `other.js`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => replaceFileText(sys, `${projectRoot}/packages/pkg2/package.json`, `index.js`, `other.js`), + timeouts: runQueuedTimeoutCallbacks, }, { caption: "removes those errors when a package file is changed back", - change: sys => ts.tscWatch.replaceFileText(sys, `${ts.tscWatch.projectRoot}/packages/pkg2/package.json`, `other.js`, `index.js`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => replaceFileText(sys, `${projectRoot}/packages/pkg2/package.json`, `other.js`, `index.js`), + timeouts: runQueuedTimeoutCallbacks, }, ] }); diff --git a/src/testRunner/unittests/tsbuild/moduleSpecifiers.ts b/src/testRunner/unittests/tsbuild/moduleSpecifiers.ts index e3dde7d0f8907..a55809426f676 100644 --- a/src/testRunner/unittests/tsbuild/moduleSpecifiers.ts +++ b/src/testRunner/unittests/tsbuild/moduleSpecifiers.ts @@ -1,18 +1,20 @@ -import * as ts from "../../_namespaces/ts"; -import * as Utils from "../../_namespaces/Utils"; +import { dedent } from "../../../harness/util"; +import { verifyTsc } from "../tsc/helpers"; +import { libFile } from "../tscWatch/helpers"; +import { loadProjectFromFiles, symbolLibContent } from "./helpers"; // https://github.com/microsoft/TypeScript/issues/31696 describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers to referenced projects resolve correctly", () => { - ts.verifyTsc({ + verifyTsc({ scenario: "moduleSpecifiers", subScenario: `synthesized module specifiers resolve correctly`, - fs: () => ts.loadProjectFromFiles({ - "/src/solution/common/nominal.ts": Utils.dedent` + fs: () => loadProjectFromFiles({ + "/src/solution/common/nominal.ts": dedent` export declare type Nominal = T & { [Symbol.species]: Name; }; `, - "/src/solution/common/tsconfig.json": Utils.dedent` + "/src/solution/common/tsconfig.json": dedent` { "extends": "../../tsconfig.base.json", "compilerOptions": { @@ -20,12 +22,12 @@ describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers }, "include": ["nominal.ts"] }`, - "/src/solution/sub-project/index.ts": Utils.dedent` + "/src/solution/sub-project/index.ts": dedent` import { Nominal } from '../common/nominal'; export type MyNominal = Nominal; `, - "/src/solution/sub-project/tsconfig.json": Utils.dedent` + "/src/solution/sub-project/tsconfig.json": dedent` { "extends": "../../tsconfig.base.json", "compilerOptions": { @@ -36,7 +38,7 @@ describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers ], "include": ["./index.ts"] }`, - "/src/solution/sub-project-2/index.ts": Utils.dedent` + "/src/solution/sub-project-2/index.ts": dedent` import { MyNominal } from '../sub-project/index'; const variable = { @@ -47,7 +49,7 @@ describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers return 'key'; } `, - "/src/solution/sub-project-2/tsconfig.json": Utils.dedent` + "/src/solution/sub-project-2/tsconfig.json": dedent` { "extends": "../../tsconfig.base.json", "compilerOptions": { @@ -58,7 +60,7 @@ describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers ], "include": ["./index.ts"] }`, - "/src/solution/tsconfig.json": Utils.dedent` + "/src/solution/tsconfig.json": dedent` { "compilerOptions": { "composite": true @@ -69,7 +71,7 @@ describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers ], "include": [] }`, - "/src/tsconfig.base.json": Utils.dedent` + "/src/tsconfig.base.json": dedent` { "compilerOptions": { "skipLibCheck": true, @@ -77,7 +79,7 @@ describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers "outDir": "lib", } }`, - "/src/tsconfig.json": Utils.dedent`{ + "/src/tsconfig.json": dedent`{ "compilerOptions": { "composite": true }, @@ -86,35 +88,35 @@ describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers ], "include": [] }` - }, ts.symbolLibContent), + }, symbolLibContent), commandLineArgs: ["-b", "/src", "--verbose"] }); }); // https://github.com/microsoft/TypeScript/issues/44434 but with `module: node16`, some `exports` maps blocking direct access, and no `baseUrl` describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers across referenced projects resolve correctly", () => { - ts.verifyTsc({ + verifyTsc({ scenario: "moduleSpecifiers", subScenario: `synthesized module specifiers across projects resolve correctly`, - fs: () => ts.loadProjectFromFiles({ - "/src/src-types/index.ts": Utils.dedent` + fs: () => loadProjectFromFiles({ + "/src/src-types/index.ts": dedent` export * from './dogconfig.js';`, - "/src/src-types/dogconfig.ts": Utils.dedent` + "/src/src-types/dogconfig.ts": dedent` export interface DogConfig { name: string; }`, - "/src/src-dogs/index.ts": Utils.dedent` + "/src/src-dogs/index.ts": dedent` export * from 'src-types'; export * from './lassie/lassiedog.js'; `, - "/src/src-dogs/dogconfig.ts": Utils.dedent` + "/src/src-dogs/dogconfig.ts": dedent` import { DogConfig } from 'src-types'; export const DOG_CONFIG: DogConfig = { name: 'Default dog', }; `, - "/src/src-dogs/dog.ts": Utils.dedent` + "/src/src-dogs/dog.ts": dedent` import { DogConfig } from 'src-types'; import { DOG_CONFIG } from './dogconfig.js'; @@ -125,7 +127,7 @@ describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers } } `, - "/src/src-dogs/lassie/lassiedog.ts": Utils.dedent` + "/src/src-dogs/lassie/lassiedog.ts": dedent` import { Dog } from '../dog.js'; import { LASSIE_CONFIG } from './lassieconfig.js'; @@ -133,29 +135,29 @@ describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers protected static getDogConfig = () => LASSIE_CONFIG; } `, - "/src/src-dogs/lassie/lassieconfig.ts": Utils.dedent` + "/src/src-dogs/lassie/lassieconfig.ts": dedent` import { DogConfig } from 'src-types'; export const LASSIE_CONFIG: DogConfig = { name: 'Lassie' }; `, - "/src/tsconfig-base.json": Utils.dedent` + "/src/tsconfig-base.json": dedent` { "compilerOptions": { "declaration": true, "module": "node16" } }`, - "/src/src-types/package.json": Utils.dedent` + "/src/src-types/package.json": dedent` { "type": "module", "exports": "./index.js" }`, - "/src/src-dogs/package.json": Utils.dedent` + "/src/src-dogs/package.json": dedent` { "type": "module", "exports": "./index.js" }`, - "/src/src-types/tsconfig.json": Utils.dedent` + "/src/src-types/tsconfig.json": dedent` { "extends": "../tsconfig-base.json", "compilerOptions": { @@ -165,7 +167,7 @@ describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers "**/*" ] }`, - "/src/src-dogs/tsconfig.json": Utils.dedent` + "/src/src-dogs/tsconfig.json": dedent` { "extends": "../tsconfig-base.json", "compilerOptions": { @@ -180,7 +182,7 @@ describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers }`, }, ""), modifyFs: fs => { - fs.writeFileSync("/lib/lib.es2022.full.d.ts", ts.tscWatch.libFile.content); + fs.writeFileSync("/lib/lib.es2022.full.d.ts", libFile.content); fs.symlinkSync("/src", "/src/src-types/node_modules"); fs.symlinkSync("/src", "/src/src-dogs/node_modules"); }, diff --git a/src/testRunner/unittests/tsbuild/noEmitOnError.ts b/src/testRunner/unittests/tsbuild/noEmitOnError.ts index 9990afe2a0a69..9bdcb9314ac28 100644 --- a/src/testRunner/unittests/tsbuild/noEmitOnError.ts +++ b/src/testRunner/unittests/tsbuild/noEmitOnError.ts @@ -1,22 +1,23 @@ -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; +import { FileSystem } from "../../../harness/vfsUtil"; +import { noChangeRun, noChangeWithExportsDiscrepancyRun } from "../tsc/helpers"; +import { loadProjectFromDisk, verifyTscWithEdits } from "./helpers"; describe("unittests:: tsbuild - with noEmitOnError", () => { - let projFs: vfs.FileSystem; + let projFs: FileSystem; before(() => { - projFs = ts.loadProjectFromDisk("tests/projects/noEmitOnError"); + projFs = loadProjectFromDisk("tests/projects/noEmitOnError"); }); after(() => { projFs = undefined!; }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "noEmitOnError", subScenario: "syntax errors", fs: () => projFs, commandLineArgs: ["--b", "/src/tsconfig.json"], edits: [ - ts.noChangeRun, + noChangeRun, { subScenario: "Fix error", modifyFs: fs => fs.writeFileSync("/src/src/main.ts", `import { A } from "../shared/types/db"; @@ -24,32 +25,32 @@ const a = { lastName: 'sdsd' };`, "utf-8"), }, - ts.noChangeRun, + noChangeRun, ], baselinePrograms: true, }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "noEmitOnError", subScenario: "syntax errors with incremental", fs: () => projFs, commandLineArgs: ["--b", "/src/tsconfig.json", "--incremental"], edits: [ - ts.noChangeRun, + noChangeRun, { subScenario: "Fix error", modifyFs: fs => fs.writeFileSync("/src/src/main.ts", `import { A } from "../shared/types/db"; const a = { lastName: 'sdsd' };`, "utf-8"), - discrepancyExplanation: ts.noChangeWithExportsDiscrepancyRun.discrepancyExplanation, + discrepancyExplanation: noChangeWithExportsDiscrepancyRun.discrepancyExplanation, }, - ts.noChangeWithExportsDiscrepancyRun, + noChangeWithExportsDiscrepancyRun, ], baselinePrograms: true, }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "noEmitOnError", subScenario: "semantic errors", fs: () => projFs, @@ -57,18 +58,18 @@ const a = { const a: string = 10;`, "utf-8"), commandLineArgs: ["--b", "/src/tsconfig.json"], edits: [ - ts.noChangeRun, + noChangeRun, { subScenario: "Fix error", modifyFs: fs => fs.writeFileSync("/src/src/main.ts", `import { A } from "../shared/types/db"; const a: string = "hello";`, "utf-8"), }, - ts.noChangeRun, + noChangeRun, ], baselinePrograms: true, }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "noEmitOnError", subScenario: "semantic errors with incremental", fs: () => projFs, @@ -76,13 +77,13 @@ const a: string = "hello";`, "utf-8"), const a: string = 10;`, "utf-8"), commandLineArgs: ["--b", "/src/tsconfig.json", "--incremental"], edits: [ - ts.noChangeWithExportsDiscrepancyRun, + noChangeWithExportsDiscrepancyRun, { subScenario: "Fix error", modifyFs: fs => fs.writeFileSync("/src/src/main.ts", `import { A } from "../shared/types/db"; const a: string = "hello";`, "utf-8"), }, - ts.noChangeRun, + noChangeRun, ], baselinePrograms: true, }); diff --git a/src/testRunner/unittests/tsbuild/outFile.ts b/src/testRunner/unittests/tsbuild/outFile.ts index 0dd4df5dd4a02..7b5d5f05ae00a 100644 --- a/src/testRunner/unittests/tsbuild/outFile.ts +++ b/src/testRunner/unittests/tsbuild/outFile.ts @@ -1,12 +1,21 @@ -import * as fakes from "../../_namespaces/fakes"; -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; +import { createSolutionBuilder } from "../../../compiler/tsbuildPublic"; +import { System } from "../../../harness/fakesHosts"; +import { FileSystem } from "../../../harness/vfsUtil"; +import { + createSolutionBuilderHostForBaseline, noChangeOnlyRuns, testTscCompileLike, TscCompileSystem, verifyTsc, + verifyTscCompileLike, +} from "../tsc/helpers"; +import { + addRest, addShebang, addSpread, addStubFoo, addTestPrologue, addTripleSlashRef, appendText, changeStubToRest, + enableStrict, loadProjectFromDisk, prependText, removeRest, replaceText, TestTscEdit, verifyTscWithEdits, + VerifyTscWithEditsInput, +} from "./helpers"; describe("unittests:: tsbuild:: outFile::", () => { - let outFileFs: vfs.FileSystem; - let outFileWithBuildFs: vfs.FileSystem; + let outFileFs: FileSystem; + let outFileWithBuildFs: FileSystem; before(() => { - outFileFs = ts.loadProjectFromDisk("tests/projects/outfile-concat"); + outFileFs = loadProjectFromDisk("tests/projects/outfile-concat"); }); after(() => { outFileFs = undefined!; @@ -15,8 +24,8 @@ describe("unittests:: tsbuild:: outFile::", () => { interface VerifyOutFileScenarioInput { subScenario: string; - modifyFs?: (fs: vfs.FileSystem) => void; - modifyAgainFs?: (fs: vfs.FileSystem) => void; + modifyFs?: (fs: FileSystem) => void; + modifyAgainFs?: (fs: FileSystem) => void; ignoreDtsChanged?: true; ignoreDtsUnchanged?: true; baselineOnly?: true; @@ -32,17 +41,17 @@ describe("unittests:: tsbuild:: outFile::", () => { baselineOnly, additionalCommandLineArgs, }: VerifyOutFileScenarioInput) { - const edits: ts.TestTscEdit[] = []; + const edits: TestTscEdit[] = []; if (!ignoreDtsChanged) { edits.push({ subScenario: "incremental-declaration-changes", - modifyFs: fs => ts.replaceText(fs, "/src/first/first_PART1.ts", "Hello", "Hola"), + modifyFs: fs => replaceText(fs, "/src/first/first_PART1.ts", "Hello", "Hola"), }); } if (!ignoreDtsUnchanged) { edits.push({ subScenario: "incremental-declaration-doesnt-change", - modifyFs: fs => ts.appendText(fs, "/src/first/first_PART1.ts", "console.log(s);"), + modifyFs: fs => appendText(fs, "/src/first/first_PART1.ts", "console.log(s);"), }); } if (modifyAgainFs) { @@ -51,7 +60,7 @@ describe("unittests:: tsbuild:: outFile::", () => { modifyFs: modifyAgainFs }); } - const input: ts.VerifyTscWithEditsInput = { + const input: VerifyTscWithEditsInput = { subScenario, fs: () => outFileFs, scenario: "outfile-concat", @@ -62,8 +71,8 @@ describe("unittests:: tsbuild:: outFile::", () => { edits, }; return edits.length ? - ts.verifyTscWithEdits(input) : - ts.verifyTsc(input); + verifyTscWithEdits(input) : + verifyTsc(input); } // Verify initial + incremental edits @@ -80,7 +89,7 @@ describe("unittests:: tsbuild:: outFile::", () => { // Verify baseline with build info + dts unChanged verifyOutFileScenario({ subScenario: "when final project is not composite but uses project references", - modifyFs: fs => ts.replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, ""), + modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, ""), ignoreDtsChanged: true, baselineOnly: true }); @@ -88,7 +97,7 @@ describe("unittests:: tsbuild:: outFile::", () => { // Verify baseline with build info verifyOutFileScenario({ subScenario: "when final project is not composite but incremental", - modifyFs: fs => ts.replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, `"incremental": true,`), + modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, `"incremental": true,`), ignoreDtsChanged: true, ignoreDtsUnchanged: true, baselineOnly: true @@ -97,7 +106,7 @@ describe("unittests:: tsbuild:: outFile::", () => { // Verify baseline with build info verifyOutFileScenario({ subScenario: "when final project specifies tsBuildInfoFile", - modifyFs: fs => ts.replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, `"composite": true, + modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, `"composite": true, "tsBuildInfoFile": "./thirdjs/output/third.tsbuildinfo",`), ignoreDtsChanged: true, ignoreDtsUnchanged: true, @@ -107,23 +116,23 @@ describe("unittests:: tsbuild:: outFile::", () => { function getOutFileFsAfterBuild() { if (outFileWithBuildFs) return outFileWithBuildFs; const fs = outFileFs.shadow(); - const sys = new fakes.System(fs, { executingFilePath: "/lib/tsc" }); - const host = ts.createSolutionBuilderHostForBaseline(sys as ts.TscCompileSystem); - const builder = ts.createSolutionBuilder(host, ["/src/third"], { dry: false, force: false, verbose: true }); + const sys = new System(fs, { executingFilePath: "/lib/tsc" }); + const host = createSolutionBuilderHostForBaseline(sys as TscCompileSystem); + const builder = createSolutionBuilder(host, ["/src/third"], { dry: false, force: false, verbose: true }); builder.build(); fs.makeReadonly(); return outFileWithBuildFs = fs; } - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "outFile", subScenario: "clean projects", fs: getOutFileFsAfterBuild, commandLineArgs: ["--b", "/src/third", "--clean"], - edits: ts.noChangeOnlyRuns + edits: noChangeOnlyRuns }); - ts.verifyTsc({ + verifyTsc({ scenario: "outFile", subScenario: "verify buildInfo absence results in new build", fs: getOutFileFsAfterBuild, @@ -131,69 +140,69 @@ describe("unittests:: tsbuild:: outFile::", () => { modifyFs: fs => fs.unlinkSync("/src/first/bin/first-output.tsbuildinfo"), }); - ts.verifyTsc({ + verifyTsc({ scenario: "outFile", subScenario: "tsbuildinfo is not generated when incremental is set to false", fs: () => outFileFs, commandLineArgs: ["--b", "/src/third", "--verbose"], - modifyFs: fs => ts.replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, ""), + modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, ""), }); - ts.verifyTscCompileLike(ts.testTscCompileLike, { + verifyTscCompileLike(testTscCompileLike, { scenario: "outFile", subScenario: "rebuilds completely when version in tsbuildinfo doesnt match ts version", fs: getOutFileFsAfterBuild, commandLineArgs: ["--b", "/src/third", "--verbose"], compile: sys => { // Buildinfo will have version which does not match with current ts version - const buildHost = ts.createSolutionBuilderHostForBaseline(sys, "FakeTSCurrentVersion"); - const builder = ts.createSolutionBuilder(buildHost, ["/src/third"], { verbose: true }); + const buildHost = createSolutionBuilderHostForBaseline(sys, "FakeTSCurrentVersion"); + const builder = createSolutionBuilder(buildHost, ["/src/third"], { verbose: true }); sys.exit(builder.build()); } }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "outFile", subScenario: "rebuilds completely when command line incremental flag changes between non dts changes", fs: () => outFileFs, // Make non composite third project - modifyFs: fs => ts.replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, ""), + modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, ""), // Build with command line incremental commandLineArgs: ["--b", "/src/third", "--i", "--verbose"], edits: [ { subScenario: "Make non incremental build with change in file that doesnt affect dts", - modifyFs: fs => ts.appendText(fs, "/src/first/first_PART1.ts", "console.log(s);"), + modifyFs: fs => appendText(fs, "/src/first/first_PART1.ts", "console.log(s);"), commandLineArgs: ["--b", "/src/third", "--verbose"], }, { subScenario: "Make incremental build with change in file that doesnt affect dts", - modifyFs: fs => ts.appendText(fs, "/src/first/first_PART1.ts", "console.log(s);"), + modifyFs: fs => appendText(fs, "/src/first/first_PART1.ts", "console.log(s);"), commandLineArgs: ["--b", "/src/third", "--verbose", "--incremental"], } ] }); - ts.verifyTscCompileLike(ts.testTscCompileLike, { + verifyTscCompileLike(testTscCompileLike, { scenario: "outFile", subScenario: "builds till project specified", fs: () => outFileFs, commandLineArgs: ["--build", "/src/second/tsconfig.json"], compile: sys => { - const buildHost = ts.createSolutionBuilderHostForBaseline(sys); - const builder = ts.createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], {}); + const buildHost = createSolutionBuilderHostForBaseline(sys); + const builder = createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], {}); sys.exit(builder.build("/src/second/tsconfig.json")); } }); - ts.verifyTscCompileLike(ts.testTscCompileLike, { + verifyTscCompileLike(testTscCompileLike, { scenario: "outFile", subScenario: "cleans till project specified", fs: getOutFileFsAfterBuild, commandLineArgs: ["--build", "--clean", "/src/second/tsconfig.json"], compile: sys => { - const buildHost = ts.createSolutionBuilderHostForBaseline(sys); - const builder = ts.createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], { verbose: true }); + const buildHost = createSolutionBuilderHostForBaseline(sys); + const builder = createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], { verbose: true }); sys.exit(builder.clean("/src/second/tsconfig.json")); } }); @@ -205,18 +214,18 @@ describe("unittests:: tsbuild:: outFile::", () => { verifyOutFileScenario({ subScenario: "strict in all projects", modifyFs: fs => { - ts.enableStrict(fs, "/src/first/tsconfig.json"); - ts.enableStrict(fs, "/src/second/tsconfig.json"); - ts.enableStrict(fs, "/src/third/tsconfig.json"); + enableStrict(fs, "/src/first/tsconfig.json"); + enableStrict(fs, "/src/second/tsconfig.json"); + enableStrict(fs, "/src/third/tsconfig.json"); }, - modifyAgainFs: fs => ts.addTestPrologue(fs, "/src/first/first_PART1.ts", `"myPrologue"`) + modifyAgainFs: fs => addTestPrologue(fs, "/src/first/first_PART1.ts", `"myPrologue"`) }); // Verify ignore dtsChanged verifyOutFileScenario({ subScenario: "strict in one dependency", - modifyFs: fs => ts.enableStrict(fs, "/src/second/tsconfig.json"), - modifyAgainFs: fs => ts.addTestPrologue(fs, "src/first/first_PART1.ts", `"myPrologue"`), + modifyFs: fs => enableStrict(fs, "/src/second/tsconfig.json"), + modifyAgainFs: fs => addTestPrologue(fs, "src/first/first_PART1.ts", `"myPrologue"`), ignoreDtsChanged: true, baselineOnly: true }); @@ -225,28 +234,28 @@ describe("unittests:: tsbuild:: outFile::", () => { verifyOutFileScenario({ subScenario: "multiple prologues in all projects", modifyFs: fs => { - ts.enableStrict(fs, "/src/first/tsconfig.json"); - ts.addTestPrologue(fs, "/src/first/first_PART1.ts", `"myPrologue"`); - ts.enableStrict(fs, "/src/second/tsconfig.json"); - ts.addTestPrologue(fs, "/src/second/second_part1.ts", `"myPrologue"`); - ts.addTestPrologue(fs, "/src/second/second_part2.ts", `"myPrologue2";`); - ts.enableStrict(fs, "/src/third/tsconfig.json"); - ts.addTestPrologue(fs, "/src/third/third_part1.ts", `"myPrologue";`); - ts.addTestPrologue(fs, "/src/third/third_part1.ts", `"myPrologue3";`); + enableStrict(fs, "/src/first/tsconfig.json"); + addTestPrologue(fs, "/src/first/first_PART1.ts", `"myPrologue"`); + enableStrict(fs, "/src/second/tsconfig.json"); + addTestPrologue(fs, "/src/second/second_part1.ts", `"myPrologue"`); + addTestPrologue(fs, "/src/second/second_part2.ts", `"myPrologue2";`); + enableStrict(fs, "/src/third/tsconfig.json"); + addTestPrologue(fs, "/src/third/third_part1.ts", `"myPrologue";`); + addTestPrologue(fs, "/src/third/third_part1.ts", `"myPrologue3";`); }, - modifyAgainFs: fs => ts.addTestPrologue(fs, "/src/first/first_PART1.ts", `"myPrologue5"`) + modifyAgainFs: fs => addTestPrologue(fs, "/src/first/first_PART1.ts", `"myPrologue5"`) }); // Verify ignore dtsChanged verifyOutFileScenario({ subScenario: "multiple prologues in different projects", modifyFs: fs => { - ts.enableStrict(fs, "/src/first/tsconfig.json"); - ts.addTestPrologue(fs, "/src/second/second_part1.ts", `"myPrologue"`); - ts.addTestPrologue(fs, "/src/second/second_part2.ts", `"myPrologue2";`); - ts.enableStrict(fs, "/src/third/tsconfig.json"); + enableStrict(fs, "/src/first/tsconfig.json"); + addTestPrologue(fs, "/src/second/second_part1.ts", `"myPrologue"`); + addTestPrologue(fs, "/src/second/second_part2.ts", `"myPrologue2";`); + enableStrict(fs, "/src/third/tsconfig.json"); }, - modifyAgainFs: fs => ts.addTestPrologue(fs, "/src/first/first_PART1.ts", `"myPrologue5"`), + modifyAgainFs: fs => addTestPrologue(fs, "/src/first/first_PART1.ts", `"myPrologue5"`), ignoreDtsChanged: true, baselineOnly: true }); @@ -259,17 +268,17 @@ describe("unittests:: tsbuild:: outFile::", () => { verifyOutFileScenario({ subScenario: "shebang in all projects", modifyFs: fs => { - ts.addShebang(fs, "first", "first_PART1"); - ts.addShebang(fs, "first", "first_part2"); - ts.addShebang(fs, "second", "second_part1"); - ts.addShebang(fs, "third", "third_part1"); + addShebang(fs, "first", "first_PART1"); + addShebang(fs, "first", "first_part2"); + addShebang(fs, "second", "second_part1"); + addShebang(fs, "third", "third_part1"); }, }); // Verify ignore dtsChanged verifyOutFileScenario({ subScenario: "shebang in only one dependency project", - modifyFs: fs => ts.addShebang(fs, "second", "second_part1"), + modifyFs: fs => addShebang(fs, "second", "second_part1"), ignoreDtsChanged: true, baselineOnly: true }); @@ -281,21 +290,21 @@ describe("unittests:: tsbuild:: outFile::", () => { verifyOutFileScenario({ subScenario: "emitHelpers in all projects", modifyFs: fs => { - ts.addRest(fs, "first", "first_PART1"); - ts.addRest(fs, "second", "second_part1"); - ts.addRest(fs, "third", "third_part1"); + addRest(fs, "first", "first_PART1"); + addRest(fs, "second", "second_part1"); + addRest(fs, "third", "third_part1"); }, - modifyAgainFs: fs => ts.removeRest(fs, "first", "first_PART1") + modifyAgainFs: fs => removeRest(fs, "first", "first_PART1") }); // Verify ignore dtsChanged verifyOutFileScenario({ subScenario: "emitHelpers in only one dependency project", modifyFs: fs => { - ts.addStubFoo(fs, "first", "first_PART1"); - ts.addRest(fs, "second", "second_part1"); + addStubFoo(fs, "first", "first_PART1"); + addRest(fs, "second", "second_part1"); }, - modifyAgainFs: fs => ts.changeStubToRest(fs, "first", "first_PART1"), + modifyAgainFs: fs => changeStubToRest(fs, "first", "first_PART1"), ignoreDtsChanged: true, baselineOnly: true }); @@ -304,14 +313,14 @@ describe("unittests:: tsbuild:: outFile::", () => { verifyOutFileScenario({ subScenario: "multiple emitHelpers in all projects", modifyFs: fs => { - ts.addRest(fs, "first", "first_PART1"); - ts.addSpread(fs, "first", "first_part3"); - ts.addRest(fs, "second", "second_part1"); - ts.addSpread(fs, "second", "second_part2"); - ts.addRest(fs, "third", "third_part1"); - ts.addSpread(fs, "third", "third_part1"); + addRest(fs, "first", "first_PART1"); + addSpread(fs, "first", "first_part3"); + addRest(fs, "second", "second_part1"); + addSpread(fs, "second", "second_part2"); + addRest(fs, "third", "third_part1"); + addSpread(fs, "third", "third_part1"); }, - modifyAgainFs: fs => ts.removeRest(fs, "first", "first_PART1"), + modifyAgainFs: fs => removeRest(fs, "first", "first_PART1"), ignoreDtsChanged: true, baselineOnly: true }); @@ -320,11 +329,11 @@ describe("unittests:: tsbuild:: outFile::", () => { verifyOutFileScenario({ subScenario: "multiple emitHelpers in different projects", modifyFs: fs => { - ts.addRest(fs, "first", "first_PART1"); - ts.addSpread(fs, "second", "second_part1"); - ts.addRest(fs, "third", "third_part1"); + addRest(fs, "first", "first_PART1"); + addSpread(fs, "second", "second_part1"); + addRest(fs, "third", "third_part1"); }, - modifyAgainFs: fs => ts.removeRest(fs, "first", "first_PART1"), + modifyAgainFs: fs => removeRest(fs, "first", "first_PART1"), ignoreDtsChanged: true, baselineOnly: true }); @@ -337,45 +346,45 @@ describe("unittests:: tsbuild:: outFile::", () => { verifyOutFileScenario({ subScenario: "triple slash refs in all projects", modifyFs: fs => { - ts.addTripleSlashRef(fs, "first", "first_part2"); - ts.addTripleSlashRef(fs, "second", "second_part1"); - ts.addTripleSlashRef(fs, "third", "third_part1"); + addTripleSlashRef(fs, "first", "first_part2"); + addTripleSlashRef(fs, "second", "second_part1"); + addTripleSlashRef(fs, "third", "third_part1"); } }); // Verify ignore dtsChanged verifyOutFileScenario({ subScenario: "triple slash refs in one project", - modifyFs: fs => ts.addTripleSlashRef(fs, "second", "second_part1"), + modifyFs: fs => addTripleSlashRef(fs, "second", "second_part1"), ignoreDtsChanged: true, baselineOnly: true }); }); describe("stripInternal", () => { - function disableRemoveComments(fs: vfs.FileSystem, file: string) { - ts.replaceText(fs, file, `"removeComments": true`, `"removeComments": false`); + function disableRemoveComments(fs: FileSystem, file: string) { + replaceText(fs, file, `"removeComments": true`, `"removeComments": false`); } - function diableRemoveCommentsInAll(fs: vfs.FileSystem) { + function diableRemoveCommentsInAll(fs: FileSystem) { disableRemoveComments(fs, "/src/first/tsconfig.json"); disableRemoveComments(fs, "/src/second/tsconfig.json"); disableRemoveComments(fs, "/src/third/tsconfig.json"); } - function stripInternalOfThird(fs: vfs.FileSystem) { - ts.replaceText(fs, "/src/third/tsconfig.json", `"declaration": true,`, `"declaration": true, + function stripInternalOfThird(fs: FileSystem) { + replaceText(fs, "/src/third/tsconfig.json", `"declaration": true,`, `"declaration": true, "stripInternal": true,`); } - function stripInternalScenario(fs: vfs.FileSystem, removeCommentsDisabled?: boolean, jsDocStyle?: boolean) { + function stripInternalScenario(fs: FileSystem, removeCommentsDisabled?: boolean, jsDocStyle?: boolean) { const internal: string = jsDocStyle ? `/**@internal*/` : `/*@internal*/`; if (removeCommentsDisabled) { diableRemoveCommentsInAll(fs); } stripInternalOfThird(fs); - ts.replaceText(fs, "/src/first/first_PART1.ts", "interface", `${internal} interface`); - ts.appendText(fs, "/src/second/second_part1.ts", ` + replaceText(fs, "/src/first/first_PART1.ts", "interface", `${internal} interface`); + appendText(fs, "/src/second/second_part1.ts", ` class normalC { ${internal} constructor() { } ${internal} prop: string; @@ -407,14 +416,14 @@ ${internal} enum internalEnum { a, b, c }`); verifyOutFileScenario({ subScenario: "stripInternal", modifyFs: stripInternalScenario, - modifyAgainFs: fs => ts.replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"), + modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"), }); // Verify ignore dtsChanged verifyOutFileScenario({ subScenario: "stripInternal with comments emit enabled", modifyFs: fs => stripInternalScenario(fs, /*removeCommentsDisabled*/ true), - modifyAgainFs: fs => ts.replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"), + modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"), ignoreDtsChanged: true, baselineOnly: true }); @@ -423,7 +432,7 @@ ${internal} enum internalEnum { a, b, c }`); verifyOutFileScenario({ subScenario: "stripInternal jsdoc style comment", modifyFs: fs => stripInternalScenario(fs, /*removeCommentsDisabled*/ false, /*jsDocStyle*/ true), - modifyAgainFs: fs => ts.replaceText(fs, "/src/first/first_PART1.ts", `/**@internal*/ interface`, "interface"), + modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/**@internal*/ interface`, "interface"), ignoreDtsChanged: true, baselineOnly: true }); @@ -437,13 +446,13 @@ ${internal} enum internalEnum { a, b, c }`); }); describe("with three levels of project dependency", () => { - function makeOneTwoThreeDependOrder(fs: vfs.FileSystem) { - ts.replaceText(fs, "/src/second/tsconfig.json", "[", `[ + function makeOneTwoThreeDependOrder(fs: FileSystem) { + replaceText(fs, "/src/second/tsconfig.json", "[", `[ { "path": "../first", "prepend": true }`); - ts.replaceText(fs, "/src/third/tsconfig.json", `{ "path": "../first", "prepend": true },`, ""); + replaceText(fs, "/src/third/tsconfig.json", `{ "path": "../first", "prepend": true },`, ""); } - function stripInternalWithDependentOrder(fs: vfs.FileSystem, removeCommentsDisabled?: boolean, jsDocStyle?: boolean) { + function stripInternalWithDependentOrder(fs: FileSystem, removeCommentsDisabled?: boolean, jsDocStyle?: boolean) { stripInternalScenario(fs, removeCommentsDisabled, jsDocStyle); makeOneTwoThreeDependOrder(fs); } @@ -452,14 +461,14 @@ ${internal} enum internalEnum { a, b, c }`); verifyOutFileScenario({ subScenario: "stripInternal when one-two-three are prepended in order", modifyFs: stripInternalWithDependentOrder, - modifyAgainFs: fs => ts.replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"), + modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"), }); // Verify ignore dtsChanged verifyOutFileScenario({ subScenario: "stripInternal with comments emit enabled when one-two-three are prepended in order", modifyFs: fs => stripInternalWithDependentOrder(fs, /*removeCommentsDisabled*/ true), - modifyAgainFs: fs => ts.replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"), + modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/*@internal*/ interface`, "interface"), ignoreDtsChanged: true, baselineOnly: true }); @@ -468,7 +477,7 @@ ${internal} enum internalEnum { a, b, c }`); verifyOutFileScenario({ subScenario: "stripInternal jsdoc style comment when one-two-three are prepended in order", modifyFs: fs => stripInternalWithDependentOrder(fs, /*removeCommentsDisabled*/ false, /*jsDocStyle*/ true), - modifyAgainFs: fs => ts.replaceText(fs, "/src/first/first_PART1.ts", `/**@internal*/ interface`, "interface"), + modifyAgainFs: fs => replaceText(fs, "/src/first/first_PART1.ts", `/**@internal*/ interface`, "interface"), ignoreDtsChanged: true, baselineOnly: true }); @@ -487,7 +496,7 @@ ${internal} enum internalEnum { a, b, c }`); subScenario: "stripInternal baseline when internal is inside another internal", modifyFs: fs => { stripInternalOfThird(fs); - ts.prependText(fs, "/src/first/first_PART1.ts", `namespace ts { + prependText(fs, "/src/first/first_PART1.ts", `namespace ts { /* @internal */ /** * Subset of properties from SourceFile that are used in multiple utility functions @@ -526,7 +535,7 @@ ${internal} enum internalEnum { a, b, c }`); subScenario: "stripInternal when few members of enum are internal", modifyFs: fs => { stripInternalOfThird(fs); - ts.prependText(fs, "/src/first/first_PART1.ts", `enum TokenFlags { + prependText(fs, "/src/first/first_PART1.ts", `enum TokenFlags { None = 0, /* @internal */ PrecedingLineBreak = 1 << 0, @@ -591,7 +600,7 @@ ${internal} enum internalEnum { a, b, c }`); }); describe("empty source files", () => { - function makeThirdEmptySourceFile(fs: vfs.FileSystem) { + function makeThirdEmptySourceFile(fs: FileSystem) { fs.writeFileSync("/src/third/third_part1.ts", "", "utf8"); } @@ -608,9 +617,9 @@ ${internal} enum internalEnum { a, b, c }`); subScenario: "declarationMap and sourceMap disabled", modifyFs: fs => { makeThirdEmptySourceFile(fs); - ts.replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, ""); - ts.replaceText(fs, "/src/third/tsconfig.json", `"sourceMap": true,`, ""); - ts.replaceText(fs, "/src/third/tsconfig.json", `"declarationMap": true,`, ""); + replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, ""); + replaceText(fs, "/src/third/tsconfig.json", `"sourceMap": true,`, ""); + replaceText(fs, "/src/third/tsconfig.json", `"declarationMap": true,`, ""); }, ignoreDtsChanged: true, ignoreDtsUnchanged: true, @@ -619,25 +628,25 @@ ${internal} enum internalEnum { a, b, c }`); }); }); - ts.verifyTsc({ + verifyTsc({ scenario: "outFile", subScenario: "non module projects without prepend", fs: () => outFileFs, commandLineArgs: ["--b", "/src/third", "--verbose"], modifyFs: fs => { // No prepend - ts.replaceText(fs, "/src/third/tsconfig.json", `{ "path": "../first", "prepend": true }`, `{ "path": "../first" }`); - ts.replaceText(fs, "/src/third/tsconfig.json", `{ "path": "../second", "prepend": true }`, `{ "path": "../second" }`); + replaceText(fs, "/src/third/tsconfig.json", `{ "path": "../first", "prepend": true }`, `{ "path": "../first" }`); + replaceText(fs, "/src/third/tsconfig.json", `{ "path": "../second", "prepend": true }`, `{ "path": "../second" }`); // Non Modules - ts.replaceText(fs, "/src/first/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`); - ts.replaceText(fs, "/src/second/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`); - ts.replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`); + replaceText(fs, "/src/first/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`); + replaceText(fs, "/src/second/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`); + replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`); // Own file emit - ts.replaceText(fs, "/src/first/tsconfig.json", `"outFile": "./bin/first-output.js",`, ""); - ts.replaceText(fs, "/src/second/tsconfig.json", `"outFile": "../2/second-output.js",`, ""); - ts.replaceText(fs, "/src/third/tsconfig.json", `"outFile": "./thirdjs/output/third-output.js",`, ""); + replaceText(fs, "/src/first/tsconfig.json", `"outFile": "./bin/first-output.js",`, ""); + replaceText(fs, "/src/second/tsconfig.json", `"outFile": "../2/second-output.js",`, ""); + replaceText(fs, "/src/third/tsconfig.json", `"outFile": "./thirdjs/output/third-output.js",`, ""); }, }); }); diff --git a/src/testRunner/unittests/tsbuild/outputPaths.ts b/src/testRunner/unittests/tsbuild/outputPaths.ts index 71e5b6eb86297..f896ca1d83a20 100644 --- a/src/testRunner/unittests/tsbuild/outputPaths.ts +++ b/src/testRunner/unittests/tsbuild/outputPaths.ts @@ -1,30 +1,34 @@ -import * as fakes from "../../_namespaces/fakes"; -import * as ts from "../../_namespaces/ts"; +import { noop } from "../../../compiler/core"; +import { getOutputFileNames } from "../../../compiler/emitter"; +import { parseConfigFileWithSystem } from "../../../compiler/watch"; +import { System } from "../../../harness/fakesHosts"; +import { noChangeRun, TscCompileSystem } from "../tsc/helpers"; +import { loadProjectFromFiles, TestTscEdit, verifyTscWithEdits, VerifyTscWithEditsInput } from "./helpers"; describe("unittests:: tsbuild - output file paths", () => { - const noChangeProject: ts.TestTscEdit = { - modifyFs: ts.noop, + const noChangeProject: TestTscEdit = { + modifyFs: noop, subScenario: "Normal build without change, that does not block emit on error to show files that get emitted", commandLineArgs: ["-p", "/src/tsconfig.json"], }; - const edits: ts.TestTscEdit[] = [ - ts.noChangeRun, + const edits: TestTscEdit[] = [ + noChangeRun, noChangeProject, ]; - function verify(input: Pick, expectedOuptutNames: readonly string[]) { - ts.verifyTscWithEdits({ + function verify(input: Pick, expectedOuptutNames: readonly string[]) { + verifyTscWithEdits({ scenario: "outputPaths", commandLineArgs: ["--b", "/src/tsconfig.json", "-v"], ...input }); it("verify getOutputFileNames", () => { - const sys = new fakes.System(input.fs().makeReadonly(), { executingFilePath: "/lib/tsc" }) as ts.TscCompileSystem; + const sys = new System(input.fs().makeReadonly(), { executingFilePath: "/lib/tsc" }) as TscCompileSystem; ; assert.deepEqual( - ts.getOutputFileNames( - ts.parseConfigFileWithSystem("/src/tsconfig.json", {}, /*extendedConfigCache*/ undefined, {}, sys, ts.noop)!, + getOutputFileNames( + parseConfigFileWithSystem("/src/tsconfig.json", {}, /*extendedConfigCache*/ undefined, {}, sys, noop)!, "/src/src/index.ts", /*ignoreCase*/ false ), @@ -35,7 +39,7 @@ describe("unittests:: tsbuild - output file paths", () => { verify({ subScenario: "when rootDir is not specified", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/src/index.ts": "export const x = 10;", "/src/tsconfig.json": JSON.stringify({ compilerOptions: { @@ -48,7 +52,7 @@ describe("unittests:: tsbuild - output file paths", () => { verify({ subScenario: "when rootDir is not specified and is composite", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/src/index.ts": "export const x = 10;", "/src/tsconfig.json": JSON.stringify({ compilerOptions: { @@ -62,7 +66,7 @@ describe("unittests:: tsbuild - output file paths", () => { verify({ subScenario: "when rootDir is specified", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/src/index.ts": "export const x = 10;", "/src/tsconfig.json": JSON.stringify({ compilerOptions: { @@ -76,7 +80,7 @@ describe("unittests:: tsbuild - output file paths", () => { verify({ subScenario: "when rootDir is specified but not all files belong to rootDir", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/src/index.ts": "export const x = 10;", "/src/types/type.ts": "export type t = string;", "/src/tsconfig.json": JSON.stringify({ @@ -91,7 +95,7 @@ describe("unittests:: tsbuild - output file paths", () => { verify({ subScenario: "when rootDir is specified but not all files belong to rootDir and is composite", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/src/index.ts": "export const x = 10;", "/src/types/type.ts": "export type t = string;", "/src/tsconfig.json": JSON.stringify({ diff --git a/src/testRunner/unittests/tsbuild/publicApi.ts b/src/testRunner/unittests/tsbuild/publicApi.ts index ff8965bf0b97b..534a5f0e275bc 100644 --- a/src/testRunner/unittests/tsbuild/publicApi.ts +++ b/src/testRunner/unittests/tsbuild/publicApi.ts @@ -1,11 +1,25 @@ -import * as fakes from "../../_namespaces/fakes"; -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; +import { emptyArray } from "../../../compiler/core"; +import { Set } from "../../../compiler/corePublic"; +import { addSyntheticLeadingComment } from "../../../compiler/factory/emitNode"; +import { + createBuilderStatusReporter, createSolutionBuilder, createSolutionBuilderHost, +} from "../../../compiler/tsbuildPublic"; +import { + CustomTransformers, ExitStatus, FunctionDeclaration, Node, SourceFile, SyntaxKind, TransformerFactory, + VariableStatement, VisitResult, +} from "../../../compiler/types"; +import { visitEachChild } from "../../../compiler/visitorPublic"; +import { createDiagnosticReporter, getErrorSummaryText } from "../../../compiler/watch"; +import { patchHostForBuildInfoReadWrite, System } from "../../../harness/fakesHosts"; +import { formatPatch } from "../../../harness/vfsUtil"; +import { commandLineCallbacks, TscCompileSystem, verifyTscBaseline } from "../tsc/helpers"; +import { baselinePrograms } from "../tscWatch/helpers"; +import { loadProjectFromFiles, toPathWithSystem } from "./helpers"; describe("unittests:: tsbuild:: Public API with custom transformers when passed to build", () => { - let sys: ts.TscCompileSystem; + let sys: TscCompileSystem; before(() => { - const inputFs = ts.loadProjectFromFiles({ + const inputFs = loadProjectFromFiles({ "/src/tsconfig.json": JSON.stringify({ references: [ { path: "./shared/tsconfig.json" }, @@ -36,35 +50,35 @@ export function f22() { } // trailing`, const fs = inputFs.shadow(); // Create system - sys = new fakes.System(fs, { executingFilePath: "/lib/tsc" }) as ts.TscCompileSystem; - fakes.patchHostForBuildInfoReadWrite(sys); + sys = new System(fs, { executingFilePath: "/lib/tsc" }) as TscCompileSystem; + patchHostForBuildInfoReadWrite(sys); const commandLineArgs = ["--b", "/src/tsconfig.json"]; sys.write(`${sys.getExecutingFilePath()} ${commandLineArgs.join(" ")}\n`); sys.exit = exitCode => sys.exitCode = exitCode; - const writtenFiles = sys.writtenFiles = new ts.Set(); + const writtenFiles = sys.writtenFiles = new Set(); const originalWriteFile = sys.writeFile; sys.writeFile = (fileName, content, writeByteOrderMark) => { - const path = ts.toPathWithSystem(sys, fileName); + const path = toPathWithSystem(sys, fileName); assert.isFalse(writtenFiles.has(path)); writtenFiles.add(path); return originalWriteFile.call(sys, fileName, content, writeByteOrderMark); }; - const { cb, getPrograms } = ts.commandLineCallbacks(sys, /*originalReadCall*/ undefined); - const buildHost = ts.createSolutionBuilderHost( + const { cb, getPrograms } = commandLineCallbacks(sys, /*originalReadCall*/ undefined); + const buildHost = createSolutionBuilderHost( sys, /*createProgram*/ undefined, - ts.createDiagnosticReporter(sys, /*pretty*/ true), - ts.createBuilderStatusReporter(sys, /*pretty*/ true), - (errorCount, filesInError) => sys.write(ts.getErrorSummaryText(errorCount, filesInError, sys.newLine, sys)) + createDiagnosticReporter(sys, /*pretty*/ true), + createBuilderStatusReporter(sys, /*pretty*/ true), + (errorCount, filesInError) => sys.write(getErrorSummaryText(errorCount, filesInError, sys.newLine, sys)) ); buildHost.afterProgramEmitAndDiagnostics = cb; buildHost.afterEmitBundle = cb; - const builder = ts.createSolutionBuilder(buildHost, [commandLineArgs[1]], { verbose: true }); + const builder = createSolutionBuilder(buildHost, [commandLineArgs[1]], { verbose: true }); const exitStatus = builder.build(/*project*/ undefined, /*cancellationToken*/ undefined, /*writeFile*/ undefined, getCustomTransformers); sys.exit(exitStatus); - sys.write(`exitCode:: ExitStatus.${ts.ExitStatus[sys.exitCode as ts.ExitStatus]}\n`); + sys.write(`exitCode:: ExitStatus.${ExitStatus[sys.exitCode as ExitStatus]}\n`); const baseline: string[] = []; - ts.tscWatch.baselinePrograms(baseline, getPrograms, ts.emptyArray, /*baselineDependencies*/ false); + baselinePrograms(baseline, getPrograms, emptyArray, /*baselineDependencies*/ false); sys.write(baseline.join("\n")); fs.makeReadonly(); sys.baseLine = () => { @@ -73,44 +87,44 @@ export function f22() { } // trailing`, return { file: `tsbuild/publicAPI/build-with-custom-transformers.js`, text: `Input:: -${baseFsPatch ? vfs.formatPatch(baseFsPatch) : ""} +${baseFsPatch ? formatPatch(baseFsPatch) : ""} Output:: ${sys.output.join("")} -${patch ? vfs.formatPatch(patch) : ""}` +${patch ? formatPatch(patch) : ""}` }; }; - function getCustomTransformers(project: string): ts.CustomTransformers { - const before: ts.TransformerFactory = context => { - return file => ts.visitEachChild(file, visit, context); - function visit(node: ts.Node): ts.VisitResult { + function getCustomTransformers(project: string): CustomTransformers { + const before: TransformerFactory = context => { + return file => visitEachChild(file, visit, context); + function visit(node: Node): VisitResult { switch (node.kind) { - case ts.SyntaxKind.FunctionDeclaration: - return visitFunction(node as ts.FunctionDeclaration); + case SyntaxKind.FunctionDeclaration: + return visitFunction(node as FunctionDeclaration); default: - return ts.visitEachChild(node, visit, context); + return visitEachChild(node, visit, context); } } - function visitFunction(node: ts.FunctionDeclaration) { - ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, `@before${project}`, /*hasTrailingNewLine*/ true); + function visitFunction(node: FunctionDeclaration) { + addSyntheticLeadingComment(node, SyntaxKind.MultiLineCommentTrivia, `@before${project}`, /*hasTrailingNewLine*/ true); return node; } }; - const after: ts.TransformerFactory = context => { - return file => ts.visitEachChild(file, visit, context); - function visit(node: ts.Node): ts.VisitResult { + const after: TransformerFactory = context => { + return file => visitEachChild(file, visit, context); + function visit(node: Node): VisitResult { switch (node.kind) { - case ts.SyntaxKind.VariableStatement: - return visitVariableStatement(node as ts.VariableStatement); + case SyntaxKind.VariableStatement: + return visitVariableStatement(node as VariableStatement); default: - return ts.visitEachChild(node, visit, context); + return visitEachChild(node, visit, context); } } - function visitVariableStatement(node: ts.VariableStatement) { - ts.addSyntheticLeadingComment(node, ts.SyntaxKind.SingleLineCommentTrivia, `@after${project}`); + function visitVariableStatement(node: VariableStatement) { + addSyntheticLeadingComment(node, SyntaxKind.SingleLineCommentTrivia, `@after${project}`); return node; } }; @@ -120,7 +134,7 @@ ${patch ? vfs.formatPatch(patch) : ""}` after(() => { sys = undefined!; }); - ts.verifyTscBaseline(() => sys); + verifyTscBaseline(() => sys); }); export { }; diff --git a/src/testRunner/unittests/tsbuild/referencesWithRootDirInParent.ts b/src/testRunner/unittests/tsbuild/referencesWithRootDirInParent.ts index d2c757ceee855..42cb854e68870 100644 --- a/src/testRunner/unittests/tsbuild/referencesWithRootDirInParent.ts +++ b/src/testRunner/unittests/tsbuild/referencesWithRootDirInParent.ts @@ -1,32 +1,33 @@ -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; +import { FileSystem } from "../../../harness/vfsUtil"; +import { verifyTsc } from "../tsc/helpers"; +import { loadProjectFromDisk, replaceText } from "./helpers"; describe("unittests:: tsbuild:: with rootDir of project reference in parentDirectory", () => { - let projFs: vfs.FileSystem; + let projFs: FileSystem; before(() => { - projFs = ts.loadProjectFromDisk("tests/projects/projectReferenceWithRootDirInParent"); + projFs = loadProjectFromDisk("tests/projects/projectReferenceWithRootDirInParent"); }); after(() => { projFs = undefined!; // Release the contents }); - ts.verifyTsc({ + verifyTsc({ scenario: "projectReferenceWithRootDirInParent", subScenario: "builds correctly", fs: () => projFs, commandLineArgs: ["--b", "/src/src/main", "/src/src/other"], }); - ts.verifyTsc({ + verifyTsc({ scenario: "projectReferenceWithRootDirInParent", subScenario: "reports error for same tsbuildinfo file because no rootDir in the base", fs: () => projFs, commandLineArgs: ["--b", "/src/src/main", "--verbose"], - modifyFs: fs => ts.replaceText(fs, "/src/tsconfig.base.json", `"rootDir": "./src/",`, ""), + modifyFs: fs => replaceText(fs, "/src/tsconfig.base.json", `"rootDir": "./src/",`, ""), }); - ts.verifyTsc({ + verifyTsc({ scenario: "projectReferenceWithRootDirInParent", subScenario: "reports error for same tsbuildinfo file", fs: () => projFs, @@ -42,7 +43,7 @@ describe("unittests:: tsbuild:: with rootDir of project reference in parentDirec }, }); - ts.verifyTsc({ + verifyTsc({ scenario: "projectReferenceWithRootDirInParent", subScenario: "reports no error when tsbuildinfo differ", fs: () => projFs, diff --git a/src/testRunner/unittests/tsbuild/resolveJsonModule.ts b/src/testRunner/unittests/tsbuild/resolveJsonModule.ts index d8ba1a20b3810..dd0a75303c9ea 100644 --- a/src/testRunner/unittests/tsbuild/resolveJsonModule.ts +++ b/src/testRunner/unittests/tsbuild/resolveJsonModule.ts @@ -1,31 +1,32 @@ -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; +import { FileSystem } from "../../../harness/vfsUtil"; +import { noChangeOnlyRuns, verifyTsc } from "../tsc/helpers"; +import { loadProjectFromDisk, replaceText, verifyTscWithEdits } from "./helpers"; describe("unittests:: tsbuild:: with resolveJsonModule option on project resolveJsonModuleAndComposite", () => { - let projFs: vfs.FileSystem; + let projFs: FileSystem; before(() => { - projFs = ts.loadProjectFromDisk("tests/projects/resolveJsonModuleAndComposite"); + projFs = loadProjectFromDisk("tests/projects/resolveJsonModuleAndComposite"); }); after(() => { projFs = undefined!; // Release the contents }); - ts.verifyTsc({ + verifyTsc({ scenario: "resolveJsonModule", subScenario: "include only", fs: () => projFs, commandLineArgs: ["--b", "/src/tsconfig_withInclude.json", "--v", "--explainFiles"], }); - ts.verifyTsc({ + verifyTsc({ scenario: "resolveJsonModule", subScenario: "include of json along with other include", fs: () => projFs, commandLineArgs: ["--b", "/src/tsconfig_withIncludeOfJson.json", "--v", "--explainFiles"], }); - ts.verifyTsc({ + verifyTsc({ scenario: "resolveJsonModule", subScenario: "include of json along with other include and file name matches ts file", fs: () => projFs, @@ -39,46 +40,46 @@ export default hello.hello`); }, }); - ts.verifyTsc({ + verifyTsc({ scenario: "resolveJsonModule", subScenario: "files containing json file", fs: () => projFs, commandLineArgs: ["--b", "/src/tsconfig_withFiles.json", "--v", "--explainFiles"], }); - ts.verifyTsc({ + verifyTsc({ scenario: "resolveJsonModule", subScenario: "include and files", fs: () => projFs, commandLineArgs: ["--b", "/src/tsconfig_withIncludeAndFiles.json", "--v", "--explainFiles"], }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "resolveJsonModule", subScenario: "sourcemap", fs: () => projFs, commandLineArgs: ["--b", "src/tsconfig_withFiles.json", "--verbose", "--explainFiles"], - modifyFs: fs => ts.replaceText(fs, "src/tsconfig_withFiles.json", `"composite": true,`, `"composite": true, "sourceMap": true,`), - edits: ts.noChangeOnlyRuns + modifyFs: fs => replaceText(fs, "src/tsconfig_withFiles.json", `"composite": true,`, `"composite": true, "sourceMap": true,`), + edits: noChangeOnlyRuns }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "resolveJsonModule", subScenario: "without outDir", fs: () => projFs, commandLineArgs: ["--b", "src/tsconfig_withFiles.json", "--verbose"], - modifyFs: fs => ts.replaceText(fs, "src/tsconfig_withFiles.json", `"outDir": "dist",`, ""), - edits: ts.noChangeOnlyRuns + modifyFs: fs => replaceText(fs, "src/tsconfig_withFiles.json", `"outDir": "dist",`, ""), + edits: noChangeOnlyRuns }); }); describe("unittests:: tsbuild:: with resolveJsonModule option on project importJsonFromProjectReference", () => { - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "resolveJsonModule", subScenario: "importing json module from project reference", - fs: () => ts.loadProjectFromDisk("tests/projects/importJsonFromProjectReference"), + fs: () => loadProjectFromDisk("tests/projects/importJsonFromProjectReference"), commandLineArgs: ["--b", "src/tsconfig.json", "--verbose", "--explainFiles"], - edits: ts.noChangeOnlyRuns + edits: noChangeOnlyRuns }); }); diff --git a/src/testRunner/unittests/tsbuild/sample.ts b/src/testRunner/unittests/tsbuild/sample.ts index bd1d7d17a524d..82e49d491ea05 100644 --- a/src/testRunner/unittests/tsbuild/sample.ts +++ b/src/testRunner/unittests/tsbuild/sample.ts @@ -1,13 +1,24 @@ -import * as fakes from "../../_namespaces/fakes"; -import * as Harness from "../../_namespaces/Harness"; -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; +import { createAbstractBuilder } from "../../../compiler/builderPublic"; +import { UpToDateStatusType } from "../../../compiler/tsbuild"; +import { createSolutionBuilder, ResolvedConfigFilePath } from "../../../compiler/tsbuildPublic"; +import { patchHostForBuildInfoReadWrite, SolutionBuilderHost, System } from "../../../harness/fakesHosts"; +import { Baseline } from "../../../harness/harnessIO"; +import { FileSystem } from "../../../harness/vfsUtil"; +import { + changeToHostTrackingWrittenFiles, getTsBuildProjectFilePath, TestServerHost, +} from "../../../harness/virtualFileSystemWithWatch"; +import { + createSolutionBuilderHostForBaseline, noChangeOnlyRuns, noChangeRun, testTscCompileLike, TscCompileSystem, + verifyTsc, verifyTscCompileLike, +} from "../tsc/helpers"; +import { createWatchedSystem, File, libFile } from "../tscWatch/helpers"; +import { appendText, libContent, loadProjectFromDisk, replaceText, TestTscEdit, verifyTscWithEdits } from "./helpers"; describe("unittests:: tsbuild:: on 'sample1' project", () => { - let projFs: vfs.FileSystem; - let projFsWithBuild: vfs.FileSystem; + let projFs: FileSystem; + let projFsWithBuild: FileSystem; before(() => { - projFs = ts.loadProjectFromDisk("tests/projects/sample1"); + projFs = loadProjectFromDisk("tests/projects/sample1"); }); after(() => { @@ -15,9 +26,9 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { projFsWithBuild = undefined!; }); - function getTsBuildProjectFile(project: string, file: string): ts.tscWatch.File { + function getTsBuildProjectFile(project: string, file: string): File { return { - path: ts.TestFSWithWatch.getTsBuildProjectFilePath(project, file), + path: getTsBuildProjectFilePath(project, file), content: projFs.readFileSync(`/src/${project}/${file}`, "utf8")! }; } @@ -25,16 +36,16 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { function getSampleFsAfterBuild() { if (projFsWithBuild) return projFsWithBuild; const fs = projFs.shadow(); - const sys = new fakes.System(fs, { executingFilePath: "/lib/tsc" }); - const host = ts.createSolutionBuilderHostForBaseline(sys as ts.TscCompileSystem); - const builder = ts.createSolutionBuilder(host, ["/src/tests"], {}); + const sys = new System(fs, { executingFilePath: "/lib/tsc" }); + const host = createSolutionBuilderHostForBaseline(sys as TscCompileSystem); + const builder = createSolutionBuilder(host, ["/src/tests"], {}); builder.build(); fs.makeReadonly(); return projFsWithBuild = fs; } describe("sanity check of clean build of 'sample1' project", () => { - ts.verifyTsc({ + verifyTsc({ scenario: "sample1", subScenario: "builds correctly when outDir is specified", fs: () => projFs, @@ -45,7 +56,7 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { })), }); - ts.verifyTsc({ + verifyTsc({ scenario: "sample1", subScenario: "builds correctly when declarationDir is specified", fs: () => projFs, @@ -56,17 +67,17 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { })), }); - ts.verifyTsc({ + verifyTsc({ scenario: "sample1", subScenario: "builds correctly when project is not composite or doesnt have any references", fs: () => projFs, commandLineArgs: ["--b", "/src/core", "--verbose"], - modifyFs: fs => ts.replaceText(fs, "/src/core/tsconfig.json", `"composite": true,`, ""), + modifyFs: fs => replaceText(fs, "/src/core/tsconfig.json", `"composite": true,`, ""), }); }); describe("dry builds", () => { - ts.verifyTsc({ + verifyTsc({ scenario: "sample1", subScenario: "does not write any files in a dry build", fs: () => projFs, @@ -75,51 +86,51 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { }); describe("clean builds", () => { - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "sample1", subScenario: "removes all files it built", fs: getSampleFsAfterBuild, commandLineArgs: ["--b", "/src/tests", "--clean"], - edits: ts.noChangeOnlyRuns + edits: noChangeOnlyRuns }); - ts.verifyTscCompileLike(ts.testTscCompileLike, { + verifyTscCompileLike(testTscCompileLike, { scenario: "sample1", subScenario: "cleans till project specified", fs: getSampleFsAfterBuild, commandLineArgs: ["--b", "/src/logic", "--clean"], compile: sys => { - const buildHost = ts.createSolutionBuilderHostForBaseline(sys); - const builder = ts.createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], {}); + const buildHost = createSolutionBuilderHostForBaseline(sys); + const builder = createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], {}); sys.exit(builder.clean("/src/logic")); } }); - ts.verifyTscCompileLike(ts.testTscCompileLike, { + verifyTscCompileLike(testTscCompileLike, { scenario: "sample1", subScenario: "cleaning project in not build order doesnt throw error", fs: getSampleFsAfterBuild, commandLineArgs: ["--b", "/src/logic2", "--clean"], compile: sys => { - const buildHost = ts.createSolutionBuilderHostForBaseline(sys); - const builder = ts.createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], {}); + const buildHost = createSolutionBuilderHostForBaseline(sys); + const builder = createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], {}); sys.exit(builder.clean("/src/logic2")); } }); }); describe("force builds", () => { - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "sample1", subScenario: "always builds under with force option", fs: () => projFs, commandLineArgs: ["--b", "/src/tests", "--force"], - edits: ts.noChangeOnlyRuns + edits: noChangeOnlyRuns }); }); describe("can detect when and what to rebuild", () => { - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "sample1", subScenario: "can detect when and what to rebuild", fs: getSampleFsAfterBuild, @@ -133,49 +144,49 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { // Update a file in the parent (without affecting types), should get fast downstream builds { subScenario: "Detects type-only changes in upstream projects", - modifyFs: fs => ts.replaceText(fs, "/src/core/index.ts", "HELLO WORLD", "WELCOME PLANET"), + modifyFs: fs => replaceText(fs, "/src/core/index.ts", "HELLO WORLD", "WELCOME PLANET"), }, { subScenario: "rebuilds when tsconfig changes", - modifyFs: fs => ts.replaceText(fs, "/src/tests/tsconfig.json", `"composite": true`, `"composite": true, "target": "es3"`), + modifyFs: fs => replaceText(fs, "/src/tests/tsconfig.json", `"composite": true`, `"composite": true, "target": "es3"`), }, ] }); - ts.verifyTsc({ + verifyTsc({ scenario: "sample1", subScenario: "indicates that it would skip builds during a dry build", fs: getSampleFsAfterBuild, commandLineArgs: ["--b", "/src/tests", "--dry"], }); - ts.verifyTsc({ + verifyTsc({ scenario: "sample1", subScenario: "rebuilds from start if force option is set", fs: getSampleFsAfterBuild, commandLineArgs: ["--b", "/src/tests", "--verbose", "--force"], }); - ts.verifyTscCompileLike(ts.testTscCompileLike, { + verifyTscCompileLike(testTscCompileLike, { scenario: "sample1", subScenario: "rebuilds completely when version in tsbuildinfo doesnt match ts version", fs: getSampleFsAfterBuild, commandLineArgs: ["--b", "/src/tests", "--verbose"], compile: sys => { // Buildinfo will have version which does not match with current ts version - const buildHost = ts.createSolutionBuilderHostForBaseline(sys, "FakeTSCurrentVersion"); - const builder = ts.createSolutionBuilder(buildHost, ["/src/tests"], { verbose: true }); + const buildHost = createSolutionBuilderHostForBaseline(sys, "FakeTSCurrentVersion"); + const builder = createSolutionBuilder(buildHost, ["/src/tests"], { verbose: true }); sys.exit(builder.build()); } }); - ts.verifyTscCompileLike(ts.testTscCompileLike, { + verifyTscCompileLike(testTscCompileLike, { scenario: "sample1", subScenario: "does not rebuild if there is no program and bundle in the ts build info event if version doesnt match ts version", fs: () => { const fs = projFs.shadow(); - const host = fakes.SolutionBuilderHost.create(fs, /*options*/ undefined, /*setParentNodes*/ undefined, ts.createAbstractBuilder); - const builder = ts.createSolutionBuilder(host, ["/src/tests"], { verbose: true }); + const host = SolutionBuilderHost.create(fs, /*options*/ undefined, /*setParentNodes*/ undefined, createAbstractBuilder); + const builder = createSolutionBuilder(host, ["/src/tests"], { verbose: true }); builder.build(); fs.makeReadonly(); return fs; @@ -183,20 +194,20 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { commandLineArgs: ["--b", "/src/tests", "--verbose"], compile: sys => { // Buildinfo will have version which does not match with current ts version - const buildHost = ts.createSolutionBuilderHostForBaseline(sys, "FakeTSCurrentVersion"); - const builder = ts.createSolutionBuilder(buildHost, ["/src/tests"], { verbose: true }); + const buildHost = createSolutionBuilderHostForBaseline(sys, "FakeTSCurrentVersion"); + const builder = createSolutionBuilder(buildHost, ["/src/tests"], { verbose: true }); sys.exit(builder.build()); }, }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "sample1", subScenario: "rebuilds when extended config file changes", fs: () => projFs, commandLineArgs: ["--b", "/src/tests", "--verbose"], modifyFs: fs => { fs.writeFileSync("/src/tests/tsconfig.base.json", JSON.stringify({ compilerOptions: { target: "es3" } })); - ts.replaceText(fs, "/src/tests/tsconfig.json", `"references": [`, `"extends": "./tsconfig.base.json", "references": [`); + replaceText(fs, "/src/tests/tsconfig.json", `"references": [`, `"extends": "./tsconfig.base.json", "references": [`); }, edits: [{ subScenario: "incremental-declaration-changes", @@ -204,26 +215,26 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { }] }); - ts.verifyTscCompileLike(ts.testTscCompileLike, { + verifyTscCompileLike(testTscCompileLike, { scenario: "sample1", subScenario: "builds till project specified", fs: () => projFs, commandLineArgs: ["--build", "/src/logic/tsconfig.json"], compile: sys => { - const buildHost = ts.createSolutionBuilderHostForBaseline(sys); - const builder = ts.createSolutionBuilder(buildHost, ["/src/tests"], {}); + const buildHost = createSolutionBuilderHostForBaseline(sys); + const builder = createSolutionBuilder(buildHost, ["/src/tests"], {}); sys.exit(builder.build("/src/logic/tsconfig.json")); } }); - ts.verifyTscCompileLike(ts.testTscCompileLike, { + verifyTscCompileLike(testTscCompileLike, { scenario: "sample1", subScenario: "building project in not build order doesnt throw error", fs: () => projFs, commandLineArgs: ["--build", "/src/logic2/tsconfig.json"], compile: sys => { - const buildHost = ts.createSolutionBuilderHostForBaseline(sys); - const builder = ts.createSolutionBuilder(buildHost, ["/src/tests"], {}); + const buildHost = createSolutionBuilderHostForBaseline(sys); + const builder = createSolutionBuilder(buildHost, ["/src/tests"], {}); sys.exit(builder.build("/src/logic2/tsconfig.json")); } }); @@ -238,27 +249,27 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { const testsConfig = getTsBuildProjectFile("tests", "tsconfig.json"); const testsIndex = getTsBuildProjectFile("tests", "index.ts"); const baseline: string[] = []; - let oldSnap: ReturnType | undefined; - const system = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - fakes.patchHostForBuildInfoReadWrite( - ts.tscWatch.createWatchedSystem([ + let oldSnap: ReturnType | undefined; + const system = changeToHostTrackingWrittenFiles( + patchHostForBuildInfoReadWrite( + createWatchedSystem([ coreConfig, coreIndex, coreDecl, coreAnotherModule, logicConfig, logicIndex, testsConfig, testsIndex, - ts.tscWatch.libFile + libFile ]) ) ); - const host = ts.createSolutionBuilderHostForBaseline(system); - const builder = ts.createSolutionBuilder(host, [testsConfig.path], {}); + const host = createSolutionBuilderHostForBaseline(system); + const builder = createSolutionBuilder(host, [testsConfig.path], {}); baseline.push("Input::"); baselineState(); verifyBuildNextResult(); // core verifyBuildNextResult(); // logic verifyBuildNextResult();// tests verifyBuildNextResult(); // All Done - Harness.Baseline.runBaseline(`tsbuild/sample1/building-using-getNextInvalidatedProject.js`, baseline.join("\r\n")); + Baseline.runBaseline(`tsbuild/sample1/building-using-getNextInvalidatedProject.js`, baseline.join("\r\n")); function verifyBuildNextResult() { const project = builder.getNextInvalidatedProject(); @@ -275,26 +286,26 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { } }); - ts.verifyTscCompileLike(ts.testTscCompileLike, { + verifyTscCompileLike(testTscCompileLike, { scenario: "sample1", subScenario: "building using buildReferencedProject", fs: () => projFs, commandLineArgs: ["--build", "/src/logic2/tsconfig.json"], compile: sys => { - const buildHost = ts.createSolutionBuilderHostForBaseline(sys); - const builder = ts.createSolutionBuilder(buildHost, ["/src/tests"], { verbose: true }); + const buildHost = createSolutionBuilderHostForBaseline(sys); + const builder = createSolutionBuilder(buildHost, ["/src/tests"], { verbose: true }); sys.exit(builder.buildReferences("/src/tests")); } }); }); describe("downstream-blocked compilations", () => { - ts.verifyTsc({ + verifyTsc({ scenario: "sample1", subScenario: "does not build downstream projects if upstream projects have errors", fs: () => projFs, commandLineArgs: ["--b", "/src/tests", "--verbose"], - modifyFs: fs => ts.replaceText(fs, "/src/logic/index.ts", "c.multiply(10, 15)", `c.muitply()`) + modifyFs: fs => replaceText(fs, "/src/logic/index.ts", "c.multiply(10, 15)", `c.muitply()`) }); }); @@ -309,20 +320,20 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { const testsConfig = getTsBuildProjectFile("tests", "tsconfig.json"); const testsIndex = getTsBuildProjectFile("tests", "index.ts"); const baseline: string[] = []; - let oldSnap: ReturnType | undefined; - const system = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - fakes.patchHostForBuildInfoReadWrite( - ts.tscWatch.createWatchedSystem([ + let oldSnap: ReturnType | undefined; + const system = changeToHostTrackingWrittenFiles( + patchHostForBuildInfoReadWrite( + createWatchedSystem([ coreConfig, coreIndex, coreDecl, coreAnotherModule, logicConfig, logicIndex, testsConfig, testsIndex, - ts.tscWatch.libFile + libFile ]) ) ); - const host = ts.createSolutionBuilderHostForBaseline(system); - const builder = ts.createSolutionBuilder(host, [testsConfig.path], { dry: false, force: false, verbose: false }); + const host = createSolutionBuilderHostForBaseline(system); + const builder = createSolutionBuilder(host, [testsConfig.path], { dry: false, force: false, verbose: false }); builder.build(); baselineState("Build of project"); @@ -331,17 +342,17 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { // Because we haven't reset the build context, the builder should assume there's nothing to do right now const status = builder.getUpToDateStatusOfProject(logicConfig.path); - baseline.push(`Project should still be upto date: ${ts.UpToDateStatusType[status.type]}`); + baseline.push(`Project should still be upto date: ${UpToDateStatusType[status.type]}`); verifyInvalidation("non Dts change to logic"); // Rebuild this project system.appendFile(logicIndex.path, `export class cNew {}`); verifyInvalidation("Dts change to Logic"); - Harness.Baseline.runBaseline(`tsbuild/sample1/invalidates-projects-correctly.js`, baseline.join("\r\n")); + Baseline.runBaseline(`tsbuild/sample1/invalidates-projects-correctly.js`, baseline.join("\r\n")); function verifyInvalidation(heading: string) { // Rebuild this project - builder.invalidateProject(logicConfig.path as ts.ResolvedConfigFilePath); + builder.invalidateProject(logicConfig.path as ResolvedConfigFilePath); builder.buildNextInvalidatedProject(); baselineState(`${heading}:: After rebuilding logicConfig`); @@ -360,35 +371,35 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => { }); }); - const coreChanges: ts.TestTscEdit[] = [ + const coreChanges: TestTscEdit[] = [ { subScenario: "incremental-declaration-changes", - modifyFs: fs => ts.appendText(fs, "/src/core/index.ts", ` + modifyFs: fs => appendText(fs, "/src/core/index.ts", ` export class someClass { }`), }, { subScenario: "incremental-declaration-doesnt-change", - modifyFs: fs => ts.appendText(fs, "/src/core/index.ts", ` + modifyFs: fs => appendText(fs, "/src/core/index.ts", ` class someClass2 { }`), } ]; describe("lists files", () => { - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "sample1", subScenario: "listFiles", fs: () => projFs, commandLineArgs: ["--b", "/src/tests", "--listFiles"], edits: coreChanges }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "sample1", subScenario: "listEmittedFiles", fs: () => projFs, commandLineArgs: ["--b", "/src/tests", "--listEmittedFiles"], edits: coreChanges }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "sample1", subScenario: "explainFiles", fs: () => projFs, @@ -398,7 +409,7 @@ class someClass2 { }`), }); describe("emit output", () => { - ts.verifyTscWithEdits({ + verifyTscWithEdits({ subScenario: "sample", fs: () => projFs, scenario: "sample1", @@ -409,25 +420,25 @@ class someClass2 { }`), ...coreChanges, { subScenario: "when logic config changes declaration dir", - modifyFs: fs => ts.replaceText(fs, "/src/logic/tsconfig.json", `"declaration": true,`, `"declaration": true, + modifyFs: fs => replaceText(fs, "/src/logic/tsconfig.json", `"declaration": true,`, `"declaration": true, "declarationDir": "decls",`), }, - ts.noChangeRun, + noChangeRun, ], }); - ts.verifyTsc({ + verifyTsc({ scenario: "sample1", subScenario: "when logic specifies tsBuildInfoFile", fs: () => projFs, - modifyFs: fs => ts.replaceText(fs, "/src/logic/tsconfig.json", `"composite": true,`, `"composite": true, + modifyFs: fs => replaceText(fs, "/src/logic/tsconfig.json", `"composite": true,`, `"composite": true, "tsBuildInfoFile": "ownFile.tsbuildinfo",`), commandLineArgs: ["--b", "/src/tests", "--verbose"], baselineSourceMap: true, baselineReadFileCalls: true }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ subScenario: "when declaration option changes", fs: () => projFs, scenario: "sample1", @@ -440,11 +451,11 @@ class someClass2 { }`), }`), edits: [{ subScenario: "incremental-declaration-changes", - modifyFs: fs => ts.replaceText(fs, "/src/core/tsconfig.json", `"incremental": true,`, `"incremental": true, "declaration": true,`), + modifyFs: fs => replaceText(fs, "/src/core/tsconfig.json", `"incremental": true,`, `"incremental": true, "declaration": true,`), }], }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ subScenario: "when target option changes", fs: () => projFs, scenario: "sample1", @@ -452,7 +463,7 @@ class someClass2 { }`), modifyFs: fs => { fs.writeFileSync("/lib/lib.esnext.full.d.ts", `/// /// `); - fs.writeFileSync("/lib/lib.esnext.d.ts", ts.libContent); + fs.writeFileSync("/lib/lib.esnext.d.ts", libContent); fs.writeFileSync("/lib/lib.d.ts", `/// /// `); fs.writeFileSync("/src/core/tsconfig.json", `{ @@ -466,11 +477,11 @@ class someClass2 { }`), }, edits: [{ subScenario: "incremental-declaration-changes", - modifyFs: fs => ts.replaceText(fs, "/src/core/tsconfig.json", "esnext", "es5"), + modifyFs: fs => replaceText(fs, "/src/core/tsconfig.json", "esnext", "es5"), }], }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ subScenario: "when module option changes", fs: () => projFs, scenario: "sample1", @@ -483,11 +494,11 @@ class someClass2 { }`), }`), edits: [{ subScenario: "incremental-declaration-changes", - modifyFs: fs => ts.replaceText(fs, "/src/core/tsconfig.json", `"module": "commonjs"`, `"module": "amd"`), + modifyFs: fs => replaceText(fs, "/src/core/tsconfig.json", `"module": "commonjs"`, `"module": "amd"`), }], }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ subScenario: "when esModuleInterop option changes", fs: () => projFs, scenario: "sample1", @@ -508,7 +519,7 @@ class someClass2 { }`), }`), edits: [{ subScenario: "incremental-declaration-changes", - modifyFs: fs => ts.replaceText(fs, "/src/tests/tsconfig.json", `"esModuleInterop": false`, `"esModuleInterop": true`), + modifyFs: fs => replaceText(fs, "/src/tests/tsconfig.json", `"esModuleInterop": false`, `"esModuleInterop": true`), }], }); }); diff --git a/src/testRunner/unittests/tsbuild/transitiveReferences.ts b/src/testRunner/unittests/tsbuild/transitiveReferences.ts index c9e54752b9487..4ceaca3f09e24 100644 --- a/src/testRunner/unittests/tsbuild/transitiveReferences.ts +++ b/src/testRunner/unittests/tsbuild/transitiveReferences.ts @@ -1,16 +1,17 @@ -import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; +import { FileSystem } from "../../../harness/vfsUtil"; +import { verifyTsc } from "../tsc/helpers"; +import { loadProjectFromDisk } from "./helpers"; describe("unittests:: tsbuild:: when project reference is referenced transitively", () => { - let projFs: vfs.FileSystem; + let projFs: FileSystem; before(() => { - projFs = ts.loadProjectFromDisk("tests/projects/transitiveReferences"); + projFs = loadProjectFromDisk("tests/projects/transitiveReferences"); }); after(() => { projFs = undefined!; // Release the contents }); - function modifyFsBTsToNonRelativeImport(fs: vfs.FileSystem, moduleResolution: "node" | "classic") { + function modifyFsBTsToNonRelativeImport(fs: FileSystem, moduleResolution: "node" | "classic") { fs.writeFileSync("/src/b.ts", `import {A} from 'a'; export const b = new A();`); fs.writeFileSync("/src/tsconfig.b.json", JSON.stringify({ @@ -23,14 +24,14 @@ export const b = new A();`); })); } - ts.verifyTsc({ + verifyTsc({ scenario: "transitiveReferences", subScenario: "builds correctly", fs: () => projFs, commandLineArgs: ["--b", "/src/tsconfig.c.json", "--listFiles"], }); - ts.verifyTsc({ + verifyTsc({ scenario: "transitiveReferences", subScenario: "builds correctly when the referenced project uses different module resolution", fs: () => projFs, @@ -38,7 +39,7 @@ export const b = new A();`); modifyFs: fs => modifyFsBTsToNonRelativeImport(fs, "classic"), }); - ts.verifyTsc({ + verifyTsc({ scenario: "transitiveReferences", subScenario: "reports error about module not found with node resolution with external module name", fs: () => projFs, diff --git a/src/testRunner/unittests/tsbuildWatch/configFileErrors.ts b/src/testRunner/unittests/tsbuildWatch/configFileErrors.ts index 9c9a3a603e15e..4b31b8e387c6d 100644 --- a/src/testRunner/unittests/tsbuildWatch/configFileErrors.ts +++ b/src/testRunner/unittests/tsbuildWatch/configFileErrors.ts @@ -1,21 +1,23 @@ -import * as ts from "../../_namespaces/ts"; -import * as Utils from "../../_namespaces/Utils"; +import { dedent } from "../../../harness/util"; +import { + createWatchedSystem, libFile, projectRoot, replaceFileText, verifyTscWatch, WatchedSystem, +} from "../tscWatch/helpers"; describe("unittests:: tsbuildWatch:: watchMode:: configFileErrors:: reports syntax errors in config file", () => { - function build(sys: ts.tscWatch.WatchedSystem) { + function build(sys: WatchedSystem) { sys.checkTimeoutQueueLengthAndRun(1); // build the project sys.checkTimeoutQueueLength(0); } - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "configFileErrors", subScenario: "reports syntax errors in config file", - sys: () => ts.tscWatch.createWatchedSystem( + sys: () => createWatchedSystem( [ - { path: `${ts.tscWatch.projectRoot}/a.ts`, content: "export function foo() { }" }, - { path: `${ts.tscWatch.projectRoot}/b.ts`, content: "export function bar() { }" }, + { path: `${projectRoot}/a.ts`, content: "export function foo() { }" }, + { path: `${projectRoot}/b.ts`, content: "export function bar() { }" }, { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, - content: Utils.dedent` + path: `${projectRoot}/tsconfig.json`, + content: dedent` { "compilerOptions": { "composite": true, @@ -26,31 +28,31 @@ describe("unittests:: tsbuildWatch:: watchMode:: configFileErrors:: reports synt ] }` }, - ts.tscWatch.libFile + libFile ], - { currentDirectory: ts.tscWatch.projectRoot } + { currentDirectory: projectRoot } ), commandLineArgs: ["--b", "-w"], changes: [ { caption: "reports syntax errors after change to config file", - change: sys => ts.tscWatch.replaceFileText(sys, `${ts.tscWatch.projectRoot}/tsconfig.json`, ",", `, + change: sys => replaceFileText(sys, `${projectRoot}/tsconfig.json`, ",", `, "declaration": true,`), timeouts: build, }, { caption: "reports syntax errors after change to ts file", - change: sys => ts.tscWatch.replaceFileText(sys, `${ts.tscWatch.projectRoot}/a.ts`, "foo", "fooBar"), + change: sys => replaceFileText(sys, `${projectRoot}/a.ts`, "foo", "fooBar"), timeouts: build, }, { caption: "reports error when there is no change to tsconfig file", - change: sys => ts.tscWatch.replaceFileText(sys, `${ts.tscWatch.projectRoot}/tsconfig.json`, "", ""), + change: sys => replaceFileText(sys, `${projectRoot}/tsconfig.json`, "", ""), timeouts: build, }, { caption: "builds after fixing config file errors", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/tsconfig.json`, JSON.stringify({ + change: sys => sys.writeFile(`${projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: { composite: true, declaration: true }, files: ["a.ts", "b.ts"] })), diff --git a/src/testRunner/unittests/tsbuildWatch/demo.ts b/src/testRunner/unittests/tsbuildWatch/demo.ts index d48aa6fe5495b..0b6d0220437d4 100644 --- a/src/testRunner/unittests/tsbuildWatch/demo.ts +++ b/src/testRunner/unittests/tsbuildWatch/demo.ts @@ -1,20 +1,24 @@ -import * as ts from "../../_namespaces/ts"; +import { getTsBuildProjectFile, tsbuildProjectsLocation } from "../../../harness/virtualFileSystemWithWatch"; +import { libContent } from "../tsbuild/helpers"; +import { + checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, createWatchedSystem, File, libFile, verifyTscWatch, +} from "../tscWatch/helpers"; describe("unittests:: tsbuildWatch:: watchMode:: with demo project", () => { - const projectLocation = `${ts.TestFSWithWatch.tsbuildProjectsLocation}/demo`; - let coreFiles: ts.tscWatch.File[]; - let animalFiles: ts.tscWatch.File[]; - let zooFiles: ts.tscWatch.File[]; - let solutionFile: ts.tscWatch.File; - let baseConfig: ts.tscWatch.File; - let allFiles: ts.tscWatch.File[]; + const projectLocation = `${tsbuildProjectsLocation}/demo`; + let coreFiles: File[]; + let animalFiles: File[]; + let zooFiles: File[]; + let solutionFile: File; + let baseConfig: File; + let allFiles: File[]; before(() => { coreFiles = subProjectFiles("core", ["tsconfig.json", "utilities.ts"]); animalFiles = subProjectFiles("animals", ["tsconfig.json", "animal.ts", "dog.ts", "index.ts"]); zooFiles = subProjectFiles("zoo", ["tsconfig.json", "zoo.ts"]); solutionFile = projectFile("tsconfig.json"); baseConfig = projectFile("tsconfig-base.json"); - allFiles = [...coreFiles, ...animalFiles, ...zooFiles, solutionFile, baseConfig, { path: ts.tscWatch.libFile.path, content: ts.libContent }]; + allFiles = [...coreFiles, ...animalFiles, ...zooFiles, solutionFile, baseConfig, { path: libFile.path, content: libContent }]; }); after(() => { @@ -26,12 +30,12 @@ describe("unittests:: tsbuildWatch:: watchMode:: with demo project", () => { allFiles = undefined!; }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "demo", subScenario: "updates with circular reference", commandLineArgs: ["-b", "-w", "-verbose"], sys: () => { - const sys = ts.tscWatch.createWatchedSystem(allFiles, { currentDirectory: projectLocation }); + const sys = createWatchedSystem(allFiles, { currentDirectory: projectLocation }); sys.writeFile(coreFiles[0].path, coreFiles[0].content.replace( "}", `}, @@ -58,12 +62,12 @@ describe("unittests:: tsbuildWatch:: watchMode:: with demo project", () => { ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "demo", subScenario: "updates with bad reference", commandLineArgs: ["-b", "-w", "-verbose"], sys: () => { - const sys = ts.tscWatch.createWatchedSystem(allFiles, { currentDirectory: projectLocation }); + const sys = createWatchedSystem(allFiles, { currentDirectory: projectLocation }); sys.writeFile(coreFiles[1].path, `import * as A from '../animals'; ${coreFiles[1].content}`); return sys; @@ -75,17 +79,17 @@ ${coreFiles[1].content}`); import * as A from '../animals'; ${coreFiles[1].content}`), // build core - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, + timeouts: checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, } ] }); - function subProjectFiles(subProject: string, fileNames: readonly string[]): ts.tscWatch.File[] { + function subProjectFiles(subProject: string, fileNames: readonly string[]): File[] { return fileNames.map(file => projectFile(`${subProject}/${file}`)); } - function projectFile(fileName: string): ts.tscWatch.File { - return ts.TestFSWithWatch.getTsBuildProjectFile("demo", fileName); + function projectFile(fileName: string): File { + return getTsBuildProjectFile("demo", fileName); } }); diff --git a/src/testRunner/unittests/tsbuildWatch/moduleResolution.ts b/src/testRunner/unittests/tsbuildWatch/moduleResolution.ts index 6ba06f9ff2757..dcef2a88ad313 100644 --- a/src/testRunner/unittests/tsbuildWatch/moduleResolution.ts +++ b/src/testRunner/unittests/tsbuildWatch/moduleResolution.ts @@ -1,33 +1,33 @@ -import * as ts from "../../_namespaces/ts"; +import { createWatchedSystem, libFile, projectRoot, verifyTscWatch } from "../tscWatch/helpers"; describe("unittests:: tsbuildWatch:: watchMode:: module resolution different in referenced project", () => { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "moduleResolutionCache", subScenario: "handles the cache correctly when two projects use different module resolution settings", - sys: () => ts.tscWatch.createWatchedSystem( + sys: () => createWatchedSystem( [ - { path: `${ts.tscWatch.projectRoot}/project1/index.ts`, content: `import { foo } from "file";` }, - { path: `${ts.tscWatch.projectRoot}/project1/node_modules/file/index.d.ts`, content: "export const foo = 10;" }, + { path: `${projectRoot}/project1/index.ts`, content: `import { foo } from "file";` }, + { path: `${projectRoot}/project1/node_modules/file/index.d.ts`, content: "export const foo = 10;" }, { - path: `${ts.tscWatch.projectRoot}/project1/tsconfig.json`, + path: `${projectRoot}/project1/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, types: ["foo", "bar"] }, files: ["index.ts"] }) }, - { path: `${ts.tscWatch.projectRoot}/project2/index.ts`, content: `import { foo } from "file";` }, - { path: `${ts.tscWatch.projectRoot}/project2/file.d.ts`, content: "export const foo = 10;" }, + { path: `${projectRoot}/project2/index.ts`, content: `import { foo } from "file";` }, + { path: `${projectRoot}/project2/file.d.ts`, content: "export const foo = 10;" }, { - path: `${ts.tscWatch.projectRoot}/project2/tsconfig.json`, + path: `${projectRoot}/project2/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, types: ["foo"], moduleResolution: "classic" }, files: ["index.ts"] }) }, - { path: `${ts.tscWatch.projectRoot}/node_modules/@types/foo/index.d.ts`, content: "export const foo = 10;" }, - { path: `${ts.tscWatch.projectRoot}/node_modules/@types/bar/index.d.ts`, content: "export const bar = 10;" }, + { path: `${projectRoot}/node_modules/@types/foo/index.d.ts`, content: "export const foo = 10;" }, + { path: `${projectRoot}/node_modules/@types/bar/index.d.ts`, content: "export const bar = 10;" }, { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ files: [], references: [ @@ -36,15 +36,15 @@ describe("unittests:: tsbuildWatch:: watchMode:: module resolution different in ] }) }, - ts.tscWatch.libFile + libFile ], - { currentDirectory: ts.tscWatch.projectRoot } + { currentDirectory: projectRoot } ), commandLineArgs: ["--b", "-w", "-v"], changes: [ { caption: "Append text", - change: sys => sys.appendFile(`${ts.tscWatch.projectRoot}/project1/index.ts`, "const bar = 10;"), + change: sys => sys.appendFile(`${projectRoot}/project1/index.ts`, "const bar = 10;"), timeouts: sys => { sys.checkTimeoutQueueLengthAndRun(1); // build project1 sys.checkTimeoutQueueLengthAndRun(1); // Solution diff --git a/src/testRunner/unittests/tsbuildWatch/noEmit.ts b/src/testRunner/unittests/tsbuildWatch/noEmit.ts index c26e77d024716..627eed4ee9f13 100644 --- a/src/testRunner/unittests/tsbuildWatch/noEmit.ts +++ b/src/testRunner/unittests/tsbuildWatch/noEmit.ts @@ -1,32 +1,35 @@ -import * as ts from "../../_namespaces/ts"; +import { libContent } from "../tsbuild/helpers"; +import { + checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, createWatchedSystem, libFile, projectRoot, verifyTscWatch, +} from "../tscWatch/helpers"; describe("unittests:: tsbuildWatch:: watchMode:: with noEmit", () => { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "noEmit", subScenario: "does not go in loop when watching when no files are emitted", commandLineArgs: ["-b", "-w", "-verbose"], - sys: () => ts.tscWatch.createWatchedSystem( + sys: () => createWatchedSystem( [ - ts.tscWatch.libFile, - { path: `${ts.tscWatch.projectRoot}/a.js`, content: "" }, - { path: `${ts.tscWatch.projectRoot}/b.ts`, content: "" }, - { path: `${ts.tscWatch.projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { allowJs: true, noEmit: true } }) }, - { path: ts.tscWatch.libFile.path, content: ts.libContent } + libFile, + { path: `${projectRoot}/a.js`, content: "" }, + { path: `${projectRoot}/b.ts`, content: "" }, + { path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { allowJs: true, noEmit: true } }) }, + { path: libFile.path, content: libContent } ], - { currentDirectory: ts.tscWatch.projectRoot } + { currentDirectory: projectRoot } ), changes: [ { caption: "No change", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/a.js`, sys.readFile(`${ts.tscWatch.projectRoot}/a.js`)!), + change: sys => sys.writeFile(`${projectRoot}/a.js`, sys.readFile(`${projectRoot}/a.js`)!), // build project - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, + timeouts: checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, }, { caption: "change", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/a.js`, "const x = 10;"), + change: sys => sys.writeFile(`${projectRoot}/a.js`, "const x = 10;"), // build project - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, + timeouts: checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, }, ], baselineIncremental: true diff --git a/src/testRunner/unittests/tsbuildWatch/noEmitOnError.ts b/src/testRunner/unittests/tsbuildWatch/noEmitOnError.ts index ffa565ff03156..58fc8db372dc2 100644 --- a/src/testRunner/unittests/tsbuildWatch/noEmitOnError.ts +++ b/src/testRunner/unittests/tsbuildWatch/noEmitOnError.ts @@ -1,32 +1,37 @@ -import * as ts from "../../_namespaces/ts"; +import { getTsBuildProjectFile, tsbuildProjectsLocation } from "../../../harness/virtualFileSystemWithWatch"; +import { libContent } from "../tsbuild/helpers"; +import { + checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, createWatchedSystem, libFile, TscWatchCompileChange, + verifyTscWatch, +} from "../tscWatch/helpers"; describe("unittests:: tsbuildWatch:: watchMode:: with noEmitOnError", () => { - function change(caption: string, content: string): ts.tscWatch.TscWatchCompileChange { + function change(caption: string, content: string): TscWatchCompileChange { return { caption, - change: sys => sys.writeFile(`${ts.TestFSWithWatch.tsbuildProjectsLocation}/noEmitOnError/src/main.ts`, content), + change: sys => sys.writeFile(`${tsbuildProjectsLocation}/noEmitOnError/src/main.ts`, content), // build project - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, + timeouts: checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, }; } - const noChange: ts.tscWatch.TscWatchCompileChange = { + const noChange: TscWatchCompileChange = { caption: "No change", - change: sys => sys.writeFile(`${ts.TestFSWithWatch.tsbuildProjectsLocation}/noEmitOnError/src/main.ts`, sys.readFile(`${ts.TestFSWithWatch.tsbuildProjectsLocation}/noEmitOnError/src/main.ts`)!), + change: sys => sys.writeFile(`${tsbuildProjectsLocation}/noEmitOnError/src/main.ts`, sys.readFile(`${tsbuildProjectsLocation}/noEmitOnError/src/main.ts`)!), // build project - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, + timeouts: checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, }; - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "noEmitOnError", subScenario: "does not emit any files on error", commandLineArgs: ["-b", "-w", "-verbose"], - sys: () => ts.tscWatch.createWatchedSystem( + sys: () => createWatchedSystem( [ ...["tsconfig.json", "shared/types/db.ts", "src/main.ts", "src/other.ts"] - .map(f => ts.TestFSWithWatch.getTsBuildProjectFile("noEmitOnError", f)), - { path: ts.tscWatch.libFile.path, content: ts.libContent } + .map(f => getTsBuildProjectFile("noEmitOnError", f)), + { path: libFile.path, content: libContent } ], - { currentDirectory: `${ts.TestFSWithWatch.tsbuildProjectsLocation}/noEmitOnError` } + { currentDirectory: `${tsbuildProjectsLocation}/noEmitOnError` } ), changes: [ noChange, diff --git a/src/testRunner/unittests/tsbuildWatch/programUpdates.ts b/src/testRunner/unittests/tsbuildWatch/programUpdates.ts index 3a9382ce8dc15..6efb50cdf0de7 100644 --- a/src/testRunner/unittests/tsbuildWatch/programUpdates.ts +++ b/src/testRunner/unittests/tsbuildWatch/programUpdates.ts @@ -1,6 +1,15 @@ -import * as ts from "../../_namespaces/ts"; +import { emptyArray, isString, noop } from "../../../compiler/core"; +import { createSolutionBuilderWithWatch } from "../../../compiler/tsbuildPublic"; +import { + getTsBuildProjectFile, getTsBuildProjectFilePath, tsbuildProjectsLocation as projectsLocation, +} from "../../../harness/virtualFileSystemWithWatch"; +import { + checkSingleTimeoutQueueLengthAndRun, checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, commonFile1, + commonFile2, createBaseline, createSolutionBuilderWithWatchHostForBaseline, createWatchedSystem, File, libFile, + noopChange, projectRoot, runQueuedTimeoutCallbacks, runWatchBaseline, TscWatchCompileChange, verifyTscWatch, + WatchedSystem, +} from "../tscWatch/helpers"; -import projectsLocation = ts.TestFSWithWatch.tsbuildProjectsLocation; describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => { const enum SubProject { core = "core", @@ -8,15 +17,15 @@ describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => { tests = "tests", ui = "ui" } - type ReadonlyFile = Readonly; + type ReadonlyFile = Readonly; /** [tsconfig, index] | [tsconfig, index, anotherModule, someDecl] */ type SubProjectFiles = [tsconfig: ReadonlyFile, index: ReadonlyFile] | [tsconfig: ReadonlyFile, index: ReadonlyFile, anotherModule: ReadonlyFile, someDecl: ReadonlyFile]; function projectFilePath(subProject: SubProject, baseFileName: string) { - return `${ts.TestFSWithWatch.getTsBuildProjectFilePath("sample1", subProject)}/${baseFileName.toLowerCase()}`; + return `${getTsBuildProjectFilePath("sample1", subProject)}/${baseFileName.toLowerCase()}`; } - function projectFile(subProject: SubProject, baseFileName: string): ts.tscWatch.File { - return ts.TestFSWithWatch.getTsBuildProjectFile("sample1", `${subProject}/${baseFileName}`); + function projectFile(subProject: SubProject, baseFileName: string): File { + return getTsBuildProjectFile("sample1", `${subProject}/${baseFileName}`); } function subProjectFiles(subProject: SubProject, anotherModuleAndSomeDecl?: true): SubProjectFiles { @@ -30,11 +39,11 @@ describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => { return [tsconfig, index, anotherModule, someDecl]; } - function changeFile(fileName: string | (() => string), content: string | (() => string), caption: string): ts.tscWatch.TscWatchCompileChange { + function changeFile(fileName: string | (() => string), content: string | (() => string), caption: string): TscWatchCompileChange { return { caption, - change: sys => sys.writeFile(ts.isString(fileName) ? fileName : fileName(), ts.isString(content) ? content : content()), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, // Builds core + change: sys => sys.writeFile(isString(fileName) ? fileName : fileName(), isString(content) ? content : content()), + timeouts: checkSingleTimeoutQueueLengthAndRun, // Builds core }; } @@ -46,14 +55,14 @@ describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => { let logic: SubProjectFiles; let tests: SubProjectFiles; let ui: SubProjectFiles; - let allFiles: readonly ts.tscWatch.File[]; + let allFiles: readonly File[]; before(() => { core = subProjectFiles(SubProject.core, /*anotherModuleAndSomeDecl*/ true); logic = subProjectFiles(SubProject.logic); tests = subProjectFiles(SubProject.tests); ui = subProjectFiles(SubProject.ui); - allFiles = [ts.tscWatch.libFile, ...core, ...logic, ...tests, ...ui]; + allFiles = [libFile, ...core, ...logic, ...tests, ...ui]; }); after(() => { @@ -64,20 +73,20 @@ describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => { allFiles = undefined!; }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: "creates solution in watch mode", commandLineArgs: ["-b", "-w", `sample1/${SubProject.tests}`], - sys: () => ts.tscWatch.createWatchedSystem(allFiles, { currentDirectory: projectsLocation }), - changes: ts.emptyArray + sys: () => createWatchedSystem(allFiles, { currentDirectory: projectsLocation }), + changes: emptyArray }); it("verify building references watches only those projects", () => { - const { sys, baseline, oldSnap, cb, getPrograms } = ts.tscWatch.createBaseline(ts.tscWatch.createWatchedSystem(allFiles, { currentDirectory: projectsLocation })); - const host = ts.tscWatch.createSolutionBuilderWithWatchHostForBaseline(sys, cb); - const solutionBuilder = ts.createSolutionBuilderWithWatch(host, [`sample1/${SubProject.tests}`], { watch: true }); + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem(allFiles, { currentDirectory: projectsLocation })); + const host = createSolutionBuilderWithWatchHostForBaseline(sys, cb); + const solutionBuilder = createSolutionBuilderWithWatch(host, [`sample1/${SubProject.tests}`], { watch: true }); solutionBuilder.buildReferences(`sample1/${SubProject.tests}`); - ts.tscWatch.runWatchBaseline({ + runWatchBaseline({ scenario: "programUpdates", subScenario: "verify building references watches only those projects", commandLineArgs: ["--b", "--w"], @@ -85,37 +94,37 @@ describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => { baseline, oldSnap, getPrograms, - changes: ts.emptyArray, + changes: emptyArray, watchOrSolution: solutionBuilder }); }); - const buildTests: ts.tscWatch.TscWatchCompileChange = { + const buildTests: TscWatchCompileChange = { caption: "Build Tests", - change: ts.noop, + change: noop, // Build tests - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, + timeouts: checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, }; describe("validates the changes and watched files", () => { const newFileWithoutExtension = "newFile"; - const newFile: ts.tscWatch.File = { + const newFile: File = { path: projectFilePath(SubProject.core, `${newFileWithoutExtension}.ts`), content: `export const newFileConst = 30;` }; - function verifyProjectChanges(subScenario: string, allFilesGetter: () => readonly ts.tscWatch.File[]) { - const buildLogicOrUpdateTimeStamps: ts.tscWatch.TscWatchCompileChange = { + function verifyProjectChanges(subScenario: string, allFilesGetter: () => readonly File[]) { + const buildLogicOrUpdateTimeStamps: TscWatchCompileChange = { caption: "Build logic or update time stamps", - change: ts.noop, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, // Builds logic or updates timestamps + change: noop, + timeouts: checkSingleTimeoutQueueLengthAndRun, // Builds logic or updates timestamps }; - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: `${subScenario}/change builds changes and reports found errors message`, commandLineArgs: ["-b", "-w", `sample1/${SubProject.tests}`], - sys: () => ts.tscWatch.createWatchedSystem( + sys: () => createWatchedSystem( allFilesGetter(), { currentDirectory: projectsLocation } ), @@ -139,18 +148,18 @@ export class someClass { }`; sys.writeFile(core[1].path, `${change1} export class someClass2 { }`); }, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, // Builds core + timeouts: checkSingleTimeoutQueueLengthAndRun, // Builds core }, buildLogicOrUpdateTimeStamps, buildTests, ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: `${subScenario}/non local change does not start build of referencing projects`, commandLineArgs: ["-b", "-w", `sample1/${SubProject.tests}`], - sys: () => ts.tscWatch.createWatchedSystem( + sys: () => createWatchedSystem( allFilesGetter(), { currentDirectory: projectsLocation } ), @@ -165,11 +174,11 @@ function foo() { }`, "Make local change to core"), function changeNewFile(newFileContent: string) { return changeFile(newFile.path, newFileContent, "Change to new File and build core"); } - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: `${subScenario}/builds when new file is added, and its subsequent updates`, commandLineArgs: ["-b", "-w", `sample1/${SubProject.tests}`], - sys: () => ts.tscWatch.createWatchedSystem( + sys: () => createWatchedSystem( allFilesGetter(), { currentDirectory: projectsLocation } ), @@ -197,39 +206,39 @@ export class someClass2 { }`), "with circular project reference", () => { const [coreTsconfig, ...otherCoreFiles] = core; - const circularCoreConfig: ts.tscWatch.File = { + const circularCoreConfig: File = { path: coreTsconfig.path, content: JSON.stringify({ compilerOptions: { composite: true, declaration: true }, references: [{ path: "../tests", circular: true }] }) }; - return [ts.tscWatch.libFile, circularCoreConfig, ...otherCoreFiles, ...logic, ...tests]; + return [libFile, circularCoreConfig, ...otherCoreFiles, ...logic, ...tests]; } ); }); }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: "watches config files that are not present", commandLineArgs: ["-b", "-w", `sample1/${SubProject.tests}`], - sys: () => ts.tscWatch.createWatchedSystem( - [ts.tscWatch.libFile, ...core, logic[1], ...tests], + sys: () => createWatchedSystem( + [libFile, ...core, logic[1], ...tests], { currentDirectory: projectsLocation } ), changes: [ { caption: "Write logic tsconfig and build logic", change: sys => sys.writeFile(logic[0].path, logic[0].content), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, // Builds logic + timeouts: checkSingleTimeoutQueueLengthAndRun, // Builds logic }, buildTests ] }); describe("when referenced using prepend, builds referencing project even for non local change", () => { - let coreIndex: ts.tscWatch.File; + let coreIndex: File; before(() => { coreIndex = { path: core[1].path, @@ -239,35 +248,35 @@ export class someClass2 { }`), after(() => { coreIndex = undefined!; }); - const buildLogic: ts.tscWatch.TscWatchCompileChange = { + const buildLogic: TscWatchCompileChange = { caption: "Build logic", - change: ts.noop, + change: noop, // Builds logic - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, + timeouts: checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, }; - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: "when referenced using prepend builds referencing project even for non local change", commandLineArgs: ["-b", "-w", `sample1/${SubProject.logic}`], sys: () => { - const coreTsConfig: ts.tscWatch.File = { + const coreTsConfig: File = { path: core[0].path, content: JSON.stringify({ compilerOptions: { composite: true, declaration: true, outFile: "index.js" } }) }; - const logicTsConfig: ts.tscWatch.File = { + const logicTsConfig: File = { path: logic[0].path, content: JSON.stringify({ compilerOptions: { composite: true, declaration: true, outFile: "index.js" }, references: [{ path: "../core", prepend: true }] }) }; - const logicIndex: ts.tscWatch.File = { + const logicIndex: File = { path: logic[1].path, content: `function bar() { return foo() + 1 };` }; - return ts.tscWatch.createWatchedSystem([ts.tscWatch.libFile, coreTsConfig, coreIndex, logicTsConfig, logicIndex], { currentDirectory: projectsLocation }); + return createWatchedSystem([libFile, coreTsConfig, coreIndex, logicTsConfig, logicIndex], { currentDirectory: projectsLocation }); }, changes: [ changeCore(() => `${coreIndex.content} @@ -282,7 +291,7 @@ function myFunc() { return 100; }`, "Make local change and build core"), describe("when referenced project change introduces error in the down stream project and then fixes it", () => { const subProjectLibrary = `${projectsLocation}/sample1/Library`; - const libraryTs: ts.tscWatch.File = { + const libraryTs: File = { path: `${subProjectLibrary}/library.ts`, content: ` interface SomeObject @@ -297,28 +306,28 @@ export function createSomeObject(): SomeObject }; }` }; - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: "when referenced project change introduces error in the down stream project and then fixes it", commandLineArgs: ["-b", "-w", "App"], sys: () => { - const libraryTsconfig: ts.tscWatch.File = { + const libraryTsconfig: File = { path: `${subProjectLibrary}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true } }) }; const subProjectApp = `${projectsLocation}/sample1/App`; - const appTs: ts.tscWatch.File = { + const appTs: File = { path: `${subProjectApp}/app.ts`, content: `import { createSomeObject } from "../Library/library"; createSomeObject().message;` }; - const appTsconfig: ts.tscWatch.File = { + const appTsconfig: File = { path: `${subProjectApp}/tsconfig.json`, content: JSON.stringify({ references: [{ path: "../Library" }] }) }; - const files = [ts.tscWatch.libFile, libraryTs, libraryTsconfig, appTs, appTsconfig]; - return ts.tscWatch.createWatchedSystem(files, { currentDirectory: `${projectsLocation}/sample1` }); + const files = [libFile, libraryTs, libraryTsconfig, appTs, appTsconfig]; + return createWatchedSystem(files, { currentDirectory: `${projectsLocation}/sample1` }); }, changes: [ { @@ -346,80 +355,80 @@ createSomeObject().message;` describe("reports errors in all projects on incremental compile", () => { function verifyIncrementalErrors(subScenario: string, buildOptions: readonly string[]) { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: `reportErrors/${subScenario}`, commandLineArgs: ["-b", "-w", `sample1/${SubProject.tests}`, ...buildOptions], - sys: () => ts.tscWatch.createWatchedSystem(allFiles, { currentDirectory: projectsLocation }), + sys: () => createWatchedSystem(allFiles, { currentDirectory: projectsLocation }), changes: [ { caption: "change logic", change: sys => sys.writeFile(logic[1].path, `${logic[1].content} let y: string = 10;`), // Builds logic - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, + timeouts: checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, }, { caption: "change core", change: sys => sys.writeFile(core[1].path, `${core[1].content} let x: string = 10;`), // Builds core - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, + timeouts: checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, } ] }); } - verifyIncrementalErrors("when preserveWatchOutput is not used", ts.emptyArray); + verifyIncrementalErrors("when preserveWatchOutput is not used", emptyArray); verifyIncrementalErrors("when preserveWatchOutput is passed on command line", ["--preserveWatchOutput"]); describe("when declaration emit errors are present", () => { const solution = "solution"; const subProject = "app"; const subProjectLocation = `${projectsLocation}/${solution}/${subProject}`; - const fileWithError: ts.tscWatch.File = { + const fileWithError: File = { path: `${subProjectLocation}/fileWithError.ts`, content: `export var myClassWithError = class { tags() { } private p = 12 };` }; - const fileWithFixedError: ts.tscWatch.File = { + const fileWithFixedError: File = { path: fileWithError.path, content: fileWithError.content.replace("private p = 12", "") }; - const fileWithoutError: ts.tscWatch.File = { + const fileWithoutError: File = { path: `${subProjectLocation}/fileWithoutError.ts`, content: `export class myClass { }` }; - const tsconfig: ts.tscWatch.File = { + const tsconfig: File = { path: `${subProjectLocation}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true } }) }; - function incrementalBuild(sys: ts.tscWatch.WatchedSystem) { + function incrementalBuild(sys: WatchedSystem) { sys.checkTimeoutQueueLengthAndRun(1); // Build the app sys.checkTimeoutQueueLength(0); } - const fixError: ts.tscWatch.TscWatchCompileChange = { + const fixError: TscWatchCompileChange = { caption: "Fix error in fileWithError", // Fix error change: sys => sys.writeFile(fileWithError.path, fileWithFixedError.content), timeouts: incrementalBuild }; - const changeFileWithoutError: ts.tscWatch.TscWatchCompileChange = { + const changeFileWithoutError: TscWatchCompileChange = { caption: "Change fileWithoutError", change: sys => sys.writeFile(fileWithoutError.path, fileWithoutError.content.replace(/myClass/g, "myClass2")), timeouts: incrementalBuild }; - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: "reportErrors/declarationEmitErrors/when fixing error files all files are emitted", commandLineArgs: ["-b", "-w", subProject], - sys: () => ts.tscWatch.createWatchedSystem( - [ts.tscWatch.libFile, fileWithError, fileWithoutError, tsconfig], + sys: () => createWatchedSystem( + [libFile, fileWithError, fileWithoutError, tsconfig], { currentDirectory: `${projectsLocation}/${solution}` } ), changes: [ @@ -427,12 +436,12 @@ let x: string = 10;`), ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: "reportErrors/declarationEmitErrors/when file with no error changes", commandLineArgs: ["-b", "-w", subProject], - sys: () => ts.tscWatch.createWatchedSystem( - [ts.tscWatch.libFile, fileWithError, fileWithoutError, tsconfig], + sys: () => createWatchedSystem( + [libFile, fileWithError, fileWithoutError, tsconfig], { currentDirectory: `${projectsLocation}/${solution}` } ), changes: [ @@ -441,18 +450,18 @@ let x: string = 10;`), }); describe("when reporting errors on introducing error", () => { - const introduceError: ts.tscWatch.TscWatchCompileChange = { + const introduceError: TscWatchCompileChange = { caption: "Introduce error", change: sys => sys.writeFile(fileWithError.path, fileWithError.content), timeouts: incrementalBuild, }; - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: "reportErrors/declarationEmitErrors/introduceError/when fixing errors only changed file is emitted", commandLineArgs: ["-b", "-w", subProject], - sys: () => ts.tscWatch.createWatchedSystem( - [ts.tscWatch.libFile, fileWithFixedError, fileWithoutError, tsconfig], + sys: () => createWatchedSystem( + [libFile, fileWithFixedError, fileWithoutError, tsconfig], { currentDirectory: `${projectsLocation}/${solution}` } ), changes: [ @@ -461,12 +470,12 @@ let x: string = 10;`), ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: "reportErrors/declarationEmitErrors/introduceError/when file with no error changes", commandLineArgs: ["-b", "-w", subProject], - sys: () => ts.tscWatch.createWatchedSystem( - [ts.tscWatch.libFile, fileWithFixedError, fileWithoutError, tsconfig], + sys: () => createWatchedSystem( + [libFile, fileWithFixedError, fileWithoutError, tsconfig], { currentDirectory: `${projectsLocation}/${solution}` } ), changes: [ @@ -478,11 +487,11 @@ let x: string = 10;`), }); }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: "incremental updates in verbose mode", commandLineArgs: ["-b", "-w", `sample1/${SubProject.tests}`, "-verbose"], - sys: () => ts.tscWatch.createWatchedSystem(allFiles, { currentDirectory: projectsLocation }), + sys: () => createWatchedSystem(allFiles, { currentDirectory: projectsLocation }), changes: [ { caption: "Make non dts change", @@ -505,104 +514,104 @@ export function someFn() { }`), ], }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: "works when noUnusedParameters changes to false", commandLineArgs: ["-b", "-w"], sys: () => { - const index: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/index.ts`, + const index: File = { + path: `${projectRoot}/index.ts`, content: `const fn = (a: string, b: string) => b;` }; - const configFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const configFile: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { noUnusedParameters: true } }) }; - return ts.tscWatch.createWatchedSystem([index, configFile, ts.tscWatch.libFile], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([index, configFile, libFile], { currentDirectory: projectRoot }); }, changes: [ { caption: "Change tsconfig to set noUnusedParameters to false", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/tsconfig.json`, JSON.stringify({ + change: sys => sys.writeFile(`${projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: { noUnusedParameters: false } })), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }, ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: "should not trigger recompilation because of program emit", commandLineArgs: ["-b", "-w", `sample1/${SubProject.core}`, "-verbose"], - sys: () => ts.tscWatch.createWatchedSystem([ts.tscWatch.libFile, ...core], { currentDirectory: projectsLocation }), + sys: () => createWatchedSystem([libFile, ...core], { currentDirectory: projectsLocation }), changes: [ - ts.tscWatch.noopChange, + noopChange, { caption: "Add new file", change: sys => sys.writeFile(`sample1/${SubProject.core}/file3.ts`, `export const y = 10;`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + timeouts: checkSingleTimeoutQueueLengthAndRun }, - ts.tscWatch.noopChange, + noopChange, ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: "should not trigger recompilation because of program emit with outDir specified", commandLineArgs: ["-b", "-w", `sample1/${SubProject.core}`, "-verbose"], sys: () => { const [coreConfig, ...rest] = core; - const newCoreConfig: ts.tscWatch.File = { path: coreConfig.path, content: JSON.stringify({ compilerOptions: { composite: true, outDir: "outDir" } }) }; - return ts.tscWatch.createWatchedSystem([ts.tscWatch.libFile, newCoreConfig, ...rest], { currentDirectory: projectsLocation }); + const newCoreConfig: File = { path: coreConfig.path, content: JSON.stringify({ compilerOptions: { composite: true, outDir: "outDir" } }) }; + return createWatchedSystem([libFile, newCoreConfig, ...rest], { currentDirectory: projectsLocation }); }, changes: [ - ts.tscWatch.noopChange, + noopChange, { caption: "Add new file", change: sys => sys.writeFile(`sample1/${SubProject.core}/file3.ts`, `export const y = 10;`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + timeouts: checkSingleTimeoutQueueLengthAndRun }, - ts.tscWatch.noopChange + noopChange ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: "works with extended source files", commandLineArgs: ["-b", "-w", "-v", "project1.tsconfig.json", "project2.tsconfig.json"], sys: () => { - const alphaExtendedConfigFile: ts.tscWatch.File = { + const alphaExtendedConfigFile: File = { path: "/a/b/alpha.tsconfig.json", content: "{}" }; - const project1Config: ts.tscWatch.File = { + const project1Config: File = { path: "/a/b/project1.tsconfig.json", content: JSON.stringify({ extends: "./alpha.tsconfig.json", compilerOptions: { composite: true, }, - files: [ts.tscWatch.commonFile1.path, ts.tscWatch.commonFile2.path] + files: [commonFile1.path, commonFile2.path] }) }; - const bravoExtendedConfigFile: ts.tscWatch.File = { + const bravoExtendedConfigFile: File = { path: "/a/b/bravo.tsconfig.json", content: JSON.stringify({ extends: "./alpha.tsconfig.json" }) }; - const otherFile: ts.tscWatch.File = { + const otherFile: File = { path: "/a/b/other.ts", content: "let z = 0;", }; - const project2Config: ts.tscWatch.File = { + const project2Config: File = { path: "/a/b/project2.tsconfig.json", content: JSON.stringify({ extends: "./bravo.tsconfig.json", @@ -612,9 +621,9 @@ export function someFn() { }`), files: [otherFile.path] }) }; - return ts.tscWatch.createWatchedSystem([ - ts.tscWatch.libFile, - alphaExtendedConfigFile, project1Config, ts.tscWatch.commonFile1, ts.tscWatch.commonFile2, + return createWatchedSystem([ + libFile, + alphaExtendedConfigFile, project1Config, commonFile1, commonFile2, bravoExtendedConfigFile, project2Config, otherFile ], { currentDirectory: "/a/b" }); }, @@ -624,12 +633,14 @@ export function someFn() { }`), change: sys => sys.writeFile("/a/b/alpha.tsconfig.json", JSON.stringify({ compilerOptions: { strict: true } })), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun // Build project1 + timeouts: checkSingleTimeoutQueueLengthAndRun // Build project1 + // Build project1 }, { caption: "Build project 2", - change: ts.noop, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout // Build project2 + change: noop, + timeouts: checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout // Build project2 + // Build project2 }, { caption: "change bravo config", @@ -637,34 +648,37 @@ export function someFn() { }`), extends: "./alpha.tsconfig.json", compilerOptions: { strict: false } })), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout // Build project2 + timeouts: checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout // Build project2 + // Build project2 }, { caption: "project 2 extends alpha", change: sys => sys.writeFile("/a/b/project2.tsconfig.json", JSON.stringify({ extends: "./alpha.tsconfig.json", })), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout // Build project2 + timeouts: checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout // Build project2 + // Build project2 }, { caption: "update aplha config", change: sys => sys.writeFile("/a/b/alpha.tsconfig.json", "{}"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, // build project1 + timeouts: checkSingleTimeoutQueueLengthAndRun, // build project1 }, { caption: "Build project 2", - change: ts.noop, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout // Build project2 + change: noop, + timeouts: checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout // Build project2 + // Build project2 }, ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "programUpdates", subScenario: "works correctly when project with extended config is removed", commandLineArgs: ["-b", "-w", "-v"], sys: () => { - const alphaExtendedConfigFile: ts.tscWatch.File = { + const alphaExtendedConfigFile: File = { path: "/a/b/alpha.tsconfig.json", content: JSON.stringify({ compilerOptions: { @@ -672,17 +686,17 @@ export function someFn() { }`), } }) }; - const project1Config: ts.tscWatch.File = { + const project1Config: File = { path: "/a/b/project1.tsconfig.json", content: JSON.stringify({ extends: "./alpha.tsconfig.json", compilerOptions: { composite: true, }, - files: [ts.tscWatch.commonFile1.path, ts.tscWatch.commonFile2.path] + files: [commonFile1.path, commonFile2.path] }) }; - const bravoExtendedConfigFile: ts.tscWatch.File = { + const bravoExtendedConfigFile: File = { path: "/a/b/bravo.tsconfig.json", content: JSON.stringify({ compilerOptions: { @@ -690,11 +704,11 @@ export function someFn() { }`), } }) }; - const otherFile: ts.tscWatch.File = { + const otherFile: File = { path: "/a/b/other.ts", content: "let z = 0;", }; - const project2Config: ts.tscWatch.File = { + const project2Config: File = { path: "/a/b/project2.tsconfig.json", content: JSON.stringify({ extends: "./bravo.tsconfig.json", @@ -704,7 +718,7 @@ export function someFn() { }`), files: [otherFile.path] }) }; - const configFile: ts.tscWatch.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: JSON.stringify({ references: [ @@ -718,9 +732,9 @@ export function someFn() { }`), files: [], }) }; - return ts.tscWatch.createWatchedSystem([ - ts.tscWatch.libFile, configFile, - alphaExtendedConfigFile, project1Config, ts.tscWatch.commonFile1, ts.tscWatch.commonFile2, + return createWatchedSystem([ + libFile, configFile, + alphaExtendedConfigFile, project1Config, commonFile1, commonFile2, bravoExtendedConfigFile, project2Config, otherFile ], { currentDirectory: "/a/b" }); }, @@ -735,7 +749,7 @@ export function someFn() { }`), ], files: [], })), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, + timeouts: checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout, } ] }); diff --git a/src/testRunner/unittests/tsbuildWatch/publicApi.ts b/src/testRunner/unittests/tsbuildWatch/publicApi.ts index 7e664950177f8..7dd3be862ee7e 100644 --- a/src/testRunner/unittests/tsbuildWatch/publicApi.ts +++ b/src/testRunner/unittests/tsbuildWatch/publicApi.ts @@ -1,8 +1,18 @@ -import * as ts from "../../_namespaces/ts"; +import { addSyntheticLeadingComment } from "../../../compiler/factory/emitNode"; +import { createSolutionBuilderWithWatch } from "../../../compiler/tsbuildPublic"; +import { + CustomTransformers, FunctionDeclaration, Node, SourceFile, SyntaxKind, TransformerFactory, VariableStatement, + VisitResult, +} from "../../../compiler/types"; +import { visitEachChild } from "../../../compiler/visitorPublic"; +import { + createBaseline, createSolutionBuilderWithWatchHostForBaseline, createWatchedSystem, File, libFile, projectRoot, + runWatchBaseline, +} from "../tscWatch/helpers"; it("unittests:: tsbuildWatch:: watchMode:: Public API with custom transformers", () => { - const solution: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const solution: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ references: [ { path: "./shared/tsconfig.json" }, @@ -11,29 +21,29 @@ it("unittests:: tsbuildWatch:: watchMode:: Public API with custom transformers", files: [] }) }; - const sharedConfig: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/shared/tsconfig.json`, + const sharedConfig: File = { + path: `${projectRoot}/shared/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true }, }) }; - const sharedIndex: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/shared/index.ts`, + const sharedIndex: File = { + path: `${projectRoot}/shared/index.ts`, content: `export function f1() { } export class c { } export enum e { } // leading export function f2() { } // trailing` }; - const webpackConfig: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/webpack/tsconfig.json`, + const webpackConfig: File = { + path: `${projectRoot}/webpack/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, }, references: [{ path: "../shared/tsconfig.json" }] }) }; - const webpackIndex: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/webpack/index.ts`, + const webpackIndex: File = { + path: `${projectRoot}/webpack/index.ts`, content: `export function f2() { } export class c2 { } export enum e2 { } @@ -41,12 +51,12 @@ export enum e2 { } export function f22() { } // trailing` }; const commandLineArgs = ["--b", "--w"]; - const { sys, baseline, oldSnap, cb, getPrograms } = ts.tscWatch.createBaseline(ts.tscWatch.createWatchedSystem([ts.tscWatch.libFile, solution, sharedConfig, sharedIndex, webpackConfig, webpackIndex], { currentDirectory: ts.tscWatch.projectRoot })); - const buildHost = ts.tscWatch.createSolutionBuilderWithWatchHostForBaseline(sys, cb); + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([libFile, solution, sharedConfig, sharedIndex, webpackConfig, webpackIndex], { currentDirectory: projectRoot })); + const buildHost = createSolutionBuilderWithWatchHostForBaseline(sys, cb); buildHost.getCustomTransformers = getCustomTransformers; - const builder = ts.createSolutionBuilderWithWatch(buildHost, [solution.path], { verbose: true }); + const builder = createSolutionBuilderWithWatch(buildHost, [solution.path], { verbose: true }); builder.build(); - ts.tscWatch.runWatchBaseline({ + runWatchBaseline({ scenario: "publicApi", subScenario: "with custom transformers", commandLineArgs, @@ -69,35 +79,35 @@ export function f22() { } // trailing` watchOrSolution: builder }); - function getCustomTransformers(project: string): ts.CustomTransformers { - const before: ts.TransformerFactory = context => { - return file => ts.visitEachChild(file, visit, context); - function visit(node: ts.Node): ts.VisitResult { + function getCustomTransformers(project: string): CustomTransformers { + const before: TransformerFactory = context => { + return file => visitEachChild(file, visit, context); + function visit(node: Node): VisitResult { switch (node.kind) { - case ts.SyntaxKind.FunctionDeclaration: - return visitFunction(node as ts.FunctionDeclaration); + case SyntaxKind.FunctionDeclaration: + return visitFunction(node as FunctionDeclaration); default: - return ts.visitEachChild(node, visit, context); + return visitEachChild(node, visit, context); } } - function visitFunction(node: ts.FunctionDeclaration) { - ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, `@before${project}`, /*hasTrailingNewLine*/ true); + function visitFunction(node: FunctionDeclaration) { + addSyntheticLeadingComment(node, SyntaxKind.MultiLineCommentTrivia, `@before${project}`, /*hasTrailingNewLine*/ true); return node; } }; - const after: ts.TransformerFactory = context => { - return file => ts.visitEachChild(file, visit, context); - function visit(node: ts.Node): ts.VisitResult { + const after: TransformerFactory = context => { + return file => visitEachChild(file, visit, context); + function visit(node: Node): VisitResult { switch (node.kind) { - case ts.SyntaxKind.VariableStatement: - return visitVariableStatement(node as ts.VariableStatement); + case SyntaxKind.VariableStatement: + return visitVariableStatement(node as VariableStatement); default: - return ts.visitEachChild(node, visit, context); + return visitEachChild(node, visit, context); } } - function visitVariableStatement(node: ts.VariableStatement) { - ts.addSyntheticLeadingComment(node, ts.SyntaxKind.SingleLineCommentTrivia, `@after${project}`); + function visitVariableStatement(node: VariableStatement) { + addSyntheticLeadingComment(node, SyntaxKind.SingleLineCommentTrivia, `@after${project}`); return node; } }; diff --git a/src/testRunner/unittests/tsbuildWatch/reexport.ts b/src/testRunner/unittests/tsbuildWatch/reexport.ts index 5e66c8ed1c6ef..80509b00c272f 100644 --- a/src/testRunner/unittests/tsbuildWatch/reexport.ts +++ b/src/testRunner/unittests/tsbuildWatch/reexport.ts @@ -1,37 +1,39 @@ -import * as ts from "../../_namespaces/ts"; +import { getTsBuildProjectFile, tsbuildProjectsLocation } from "../../../harness/virtualFileSystemWithWatch"; +import { libContent } from "../tsbuild/helpers"; +import { createWatchedSystem, libFile, replaceFileText, verifyTscWatch, WatchedSystem } from "../tscWatch/helpers"; describe("unittests:: tsbuildWatch:: watchMode:: with reexport when referenced project reexports definitions from another file", () => { - function build(sys: ts.tscWatch.WatchedSystem) { + function build(sys: WatchedSystem) { sys.checkTimeoutQueueLengthAndRun(1); // build src/pure sys.checkTimeoutQueueLengthAndRun(1); // build src/main sys.checkTimeoutQueueLengthAndRun(1); // build src sys.checkTimeoutQueueLength(0); } - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "reexport", subScenario: "Reports errors correctly", commandLineArgs: ["-b", "-w", "-verbose", "src"], - sys: () => ts.tscWatch.createWatchedSystem( + sys: () => createWatchedSystem( [ ...[ "src/tsconfig.json", "src/main/tsconfig.json", "src/main/index.ts", "src/pure/tsconfig.json", "src/pure/index.ts", "src/pure/session.ts" ] - .map(f => ts.TestFSWithWatch.getTsBuildProjectFile("reexport", f)), - { path: ts.tscWatch.libFile.path, content: ts.libContent } + .map(f => getTsBuildProjectFile("reexport", f)), + { path: libFile.path, content: libContent } ], - { currentDirectory: `${ts.TestFSWithWatch.tsbuildProjectsLocation}/reexport` } + { currentDirectory: `${tsbuildProjectsLocation}/reexport` } ), changes: [ { caption: "Introduce error", - change: sys => ts.tscWatch.replaceFileText(sys, `${ts.TestFSWithWatch.tsbuildProjectsLocation}/reexport/src/pure/session.ts`, "// ", ""), + change: sys => replaceFileText(sys, `${tsbuildProjectsLocation}/reexport/src/pure/session.ts`, "// ", ""), timeouts: build, }, { caption: "Fix error", - change: sys => ts.tscWatch.replaceFileText(sys, `${ts.TestFSWithWatch.tsbuildProjectsLocation}/reexport/src/pure/session.ts`, "bar: ", "// bar: "), + change: sys => replaceFileText(sys, `${tsbuildProjectsLocation}/reexport/src/pure/session.ts`, "bar: ", "// bar: "), timeouts: build } ] diff --git a/src/testRunner/unittests/tsbuildWatch/watchEnvironment.ts b/src/testRunner/unittests/tsbuildWatch/watchEnvironment.ts index 42e3e26f7b3e9..44d70099bb926 100644 --- a/src/testRunner/unittests/tsbuildWatch/watchEnvironment.ts +++ b/src/testRunner/unittests/tsbuildWatch/watchEnvironment.ts @@ -1,4 +1,11 @@ -import * as ts from "../../_namespaces/ts"; +import { arrayToMap, flatMap, identity } from "../../../compiler/core"; +import { ESMap } from "../../../compiler/corePublic"; +import { createSolutionBuilderWithWatch } from "../../../compiler/tsbuildPublic"; +import { TestServerHost, tsbuildProjectsLocation, Tsc_WatchFile } from "../../../harness/virtualFileSystemWithWatch"; +import { + checkSingleTimeoutQueueLengthAndRun, createBaseline, createSolutionBuilderWithWatchHostForBaseline, + createWatchedSystem, File, libFile, runWatchBaseline, +} from "../tscWatch/helpers"; describe("unittests:: tsbuildWatch:: watchEnvironment:: tsbuild:: watchMode:: with different watch environments", () => { describe("when watchFile can create multiple watchers per file", () => { @@ -8,28 +15,28 @@ describe("unittests:: tsbuildWatch:: watchEnvironment:: tsbuild:: watchMode:: wi describe("when watchFile is single watcher per file", () => { verifyWatchFileOnMultipleProjects( /*singleWatchPerFile*/ true, - ts.arrayToMap(["TSC_WATCHFILE"], ts.identity, () => ts.TestFSWithWatch.Tsc_WatchFile.SingleFileWatcherPerName) + arrayToMap(["TSC_WATCHFILE"], identity, () => Tsc_WatchFile.SingleFileWatcherPerName) ); }); - function verifyWatchFileOnMultipleProjects(singleWatchPerFile: boolean, environmentVariables?: ts.ESMap) { + function verifyWatchFileOnMultipleProjects(singleWatchPerFile: boolean, environmentVariables?: ESMap) { it("watchFile on same file multiple times because file is part of multiple projects", () => { - const project = `${ts.TestFSWithWatch.tsbuildProjectsLocation}/myproject`; + const project = `${tsbuildProjectsLocation}/myproject`; let maxPkgs = 4; const configPath = `${project}/tsconfig.json`; - const typing: ts.tscWatch.File = { + const typing: File = { path: `${project}/typings/xterm.d.ts`, content: "export const typing = 10;" }; const allPkgFiles = pkgs(pkgFiles); - const system = ts.tscWatch.createWatchedSystem([ts.tscWatch.libFile, typing, ...flatArray(allPkgFiles)], { currentDirectory: project, environmentVariables }); + const system = createWatchedSystem([libFile, typing, ...flatArray(allPkgFiles)], { currentDirectory: project, environmentVariables }); writePkgReferences(system); - const { sys, baseline, oldSnap, cb, getPrograms } = ts.tscWatch.createBaseline(system); - const host = ts.tscWatch.createSolutionBuilderWithWatchHostForBaseline(sys, cb); - const solutionBuilder = ts.createSolutionBuilderWithWatch(host, ["tsconfig.json"], { watch: true, verbose: true }); + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(system); + const host = createSolutionBuilderWithWatchHostForBaseline(sys, cb); + const solutionBuilder = createSolutionBuilderWithWatch(host, ["tsconfig.json"], { watch: true, verbose: true }); solutionBuilder.build(); - ts.tscWatch.runWatchBaseline({ + runWatchBaseline({ scenario: "watchEnvironment", subScenario: `same file in multiple projects${singleWatchPerFile ? " with single watcher per file" : ""}`, commandLineArgs: ["--b", "--w"], @@ -50,7 +57,7 @@ describe("unittests:: tsbuildWatch:: watchEnvironment:: tsbuild:: watchMode:: wi maxPkgs--; writePkgReferences(sys); }, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "modify typing file", @@ -64,7 +71,7 @@ describe("unittests:: tsbuildWatch:: watchEnvironment:: tsbuild:: watchMode:: wi maxPkgs = 0; writePkgReferences(sys); }, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "modify typing file", @@ -76,7 +83,7 @@ describe("unittests:: tsbuildWatch:: watchEnvironment:: tsbuild:: watchMode:: wi }); function flatArray(arr: T[][]): readonly T[] { - return ts.flatMap(arr, ts.identity); + return flatMap(arr, identity); } function pkgs(cb: (index: number) => T): T[] { const result: T[] = []; @@ -88,7 +95,7 @@ describe("unittests:: tsbuildWatch:: watchEnvironment:: tsbuild:: watchMode:: wi function createPkgReference(index: number) { return { path: `./pkg${index}` }; } - function pkgFiles(index: number): ts.tscWatch.File[] { + function pkgFiles(index: number): File[] { return [ { path: `${project}/pkg${index}/index.ts`, @@ -106,7 +113,7 @@ describe("unittests:: tsbuildWatch:: watchEnvironment:: tsbuild:: watchMode:: wi } ]; } - function writePkgReferences(system: ts.TestFSWithWatch.TestServerHost) { + function writePkgReferences(system: TestServerHost) { system.writeFile(configPath, JSON.stringify({ files: [], include: [], diff --git a/src/testRunner/unittests/tsc/composite.ts b/src/testRunner/unittests/tsc/composite.ts index 6ce9cab2fac44..3463c3c1f0f26 100644 --- a/src/testRunner/unittests/tsc/composite.ts +++ b/src/testRunner/unittests/tsc/composite.ts @@ -1,13 +1,14 @@ -import * as ts from "../../_namespaces/ts"; -import * as Utils from "../../_namespaces/Utils"; +import { dedent } from "../../../harness/util"; +import { loadProjectFromFiles } from "../tsbuild/helpers"; +import { verifyTsc } from "./helpers"; describe("unittests:: tsc:: composite::", () => { - ts.verifyTsc({ + verifyTsc({ scenario: "composite", subScenario: "when setting composite false on command line", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/project/src/main.ts": "export const x = 10;", - "/src/project/tsconfig.json": Utils.dedent` + "/src/project/tsconfig.json": dedent` { "compilerOptions": { "target": "es5", @@ -22,12 +23,12 @@ describe("unittests:: tsc:: composite::", () => { commandLineArgs: ["--composite", "false", "--p", "src/project"], }); - ts.verifyTsc({ + verifyTsc({ scenario: "composite", subScenario: "when setting composite null on command line", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/project/src/main.ts": "export const x = 10;", - "/src/project/tsconfig.json": Utils.dedent` + "/src/project/tsconfig.json": dedent` { "compilerOptions": { "target": "es5", @@ -42,12 +43,12 @@ describe("unittests:: tsc:: composite::", () => { commandLineArgs: ["--composite", "null", "--p", "src/project"], }); - ts.verifyTsc({ + verifyTsc({ scenario: "composite", subScenario: "when setting composite false on command line but has tsbuild info in config", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/project/src/main.ts": "export const x = 10;", - "/src/project/tsconfig.json": Utils.dedent` + "/src/project/tsconfig.json": dedent` { "compilerOptions": { "target": "es5", @@ -63,12 +64,12 @@ describe("unittests:: tsc:: composite::", () => { commandLineArgs: ["--composite", "false", "--p", "src/project"], }); - ts.verifyTsc({ + verifyTsc({ scenario: "composite", subScenario: "when setting composite false and tsbuildinfo as null on command line but has tsbuild info in config", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/project/src/main.ts": "export const x = 10;", - "/src/project/tsconfig.json": Utils.dedent` + "/src/project/tsconfig.json": dedent` { "compilerOptions": { "target": "es5", diff --git a/src/testRunner/unittests/tsc/declarationEmit.ts b/src/testRunner/unittests/tsc/declarationEmit.ts index ad014a998c25a..25b774146442c 100644 --- a/src/testRunner/unittests/tsc/declarationEmit.ts +++ b/src/testRunner/unittests/tsc/declarationEmit.ts @@ -1,42 +1,44 @@ -import * as ts from "../../_namespaces/ts"; -import * as Utils from "../../_namespaces/Utils"; +import { emptyArray, stringContains } from "../../../compiler/core"; +import { dedent } from "../../../harness/util"; +import { FileOrFolderOrSymLink, isSymLink } from "../../../harness/virtualFileSystemWithWatch"; +import { createWatchedSystem, libFile, projectRoot, verifyTscWatch } from "../tscWatch/helpers"; describe("unittests:: tsc:: declarationEmit::", () => { interface VerifyDeclarationEmitInput { subScenario: string; - files: ts.TestFSWithWatch.FileOrFolderOrSymLink[]; + files: FileOrFolderOrSymLink[]; rootProject: string; changeCaseFileTestPath: (path: string) => boolean; } - function changeCaseFile(file: ts.TestFSWithWatch.FileOrFolderOrSymLink, testPath: (path: string) => boolean, replacePath: (path: string) => string): ts.TestFSWithWatch.FileOrFolderOrSymLink { - return !ts.TestFSWithWatch.isSymLink(file) || !testPath(file.symLink) ? + function changeCaseFile(file: FileOrFolderOrSymLink, testPath: (path: string) => boolean, replacePath: (path: string) => string): FileOrFolderOrSymLink { + return !isSymLink(file) || !testPath(file.symLink) ? testPath(file.path) ? { ...file, path: replacePath(file.path) } : file : { path: testPath(file.path) ? replacePath(file.path) : file.path, symLink: replacePath(file.symLink) }; } function verifyDeclarationEmit({ subScenario, files, rootProject, changeCaseFileTestPath }: VerifyDeclarationEmitInput) { describe(subScenario, () => { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "declarationEmit", subScenario, - sys: () => ts.tscWatch.createWatchedSystem(files, { currentDirectory: ts.tscWatch.projectRoot }), + sys: () => createWatchedSystem(files, { currentDirectory: projectRoot }), commandLineArgs: ["-p", rootProject, "--explainFiles"], - changes: ts.emptyArray + changes: emptyArray }); }); const caseChangeScenario = `${subScenario} moduleCaseChange`; describe(caseChangeScenario, () => { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "declarationEmit", subScenario: caseChangeScenario, - sys: () => ts.tscWatch.createWatchedSystem( + sys: () => createWatchedSystem( files.map(f => changeCaseFile(f, changeCaseFileTestPath, str => str.replace("myproject", "myProject"))), - { currentDirectory: ts.tscWatch.projectRoot } + { currentDirectory: projectRoot } ), commandLineArgs: ["-p", rootProject, "--explainFiles"], - changes: ts.emptyArray + changes: emptyArray }); }); } @@ -55,14 +57,14 @@ describe("unittests:: tsc:: declarationEmit::", () => { return `import pluginTwo from "plugin-two"; // include this to add reference to symlink`; } function pluginOneAction() { - return Utils.dedent` + return dedent` import { actionCreatorFactory } from "typescript-fsa"; // Include version of shared lib const action = actionCreatorFactory("somekey"); const featureOne = action<{ route: string }>("feature-one"); export const actions = { featureOne };`; } function pluginTwoDts() { - return Utils.dedent` + return dedent` declare const _default: { features: { featureOne: { @@ -92,7 +94,7 @@ describe("unittests:: tsc:: declarationEmit::", () => { }); } function fsaIndex() { - return Utils.dedent` + return dedent` export interface Action { type: string; payload: Payload; @@ -112,18 +114,18 @@ describe("unittests:: tsc:: declarationEmit::", () => { subScenario: "when same version is referenced through source and another symlinked package", rootProject: "plugin-one", files: [ - { path: `${ts.tscWatch.projectRoot}/plugin-two/index.d.ts`, content: pluginTwoDts() }, - { path: `${ts.tscWatch.projectRoot}/plugin-two/node_modules/typescript-fsa/package.json`, content: fsaPackageJson() }, - { path: `${ts.tscWatch.projectRoot}/plugin-two/node_modules/typescript-fsa/index.d.ts`, content: fsaIndex() }, - { path: `${ts.tscWatch.projectRoot}/plugin-one/tsconfig.json`, content: pluginOneConfig() }, - { path: `${ts.tscWatch.projectRoot}/plugin-one/index.ts`, content: pluginOneIndex() }, - { path: `${ts.tscWatch.projectRoot}/plugin-one/action.ts`, content: pluginOneAction() }, - { path: `${ts.tscWatch.projectRoot}/plugin-one/node_modules/typescript-fsa/package.json`, content: fsaPackageJson() }, - { path: `${ts.tscWatch.projectRoot}/plugin-one/node_modules/typescript-fsa/index.d.ts`, content: fsaIndex() }, - { path: `${ts.tscWatch.projectRoot}/plugin-one/node_modules/plugin-two`, symLink: `${ts.tscWatch.projectRoot}/plugin-two` }, - ts.tscWatch.libFile + { path: `${projectRoot}/plugin-two/index.d.ts`, content: pluginTwoDts() }, + { path: `${projectRoot}/plugin-two/node_modules/typescript-fsa/package.json`, content: fsaPackageJson() }, + { path: `${projectRoot}/plugin-two/node_modules/typescript-fsa/index.d.ts`, content: fsaIndex() }, + { path: `${projectRoot}/plugin-one/tsconfig.json`, content: pluginOneConfig() }, + { path: `${projectRoot}/plugin-one/index.ts`, content: pluginOneIndex() }, + { path: `${projectRoot}/plugin-one/action.ts`, content: pluginOneAction() }, + { path: `${projectRoot}/plugin-one/node_modules/typescript-fsa/package.json`, content: fsaPackageJson() }, + { path: `${projectRoot}/plugin-one/node_modules/typescript-fsa/index.d.ts`, content: fsaIndex() }, + { path: `${projectRoot}/plugin-one/node_modules/plugin-two`, symLink: `${projectRoot}/plugin-two` }, + libFile ], - changeCaseFileTestPath: str => ts.stringContains(str, "/plugin-two"), + changeCaseFileTestPath: str => stringContains(str, "/plugin-two"), }); verifyDeclarationEmit({ @@ -131,29 +133,29 @@ describe("unittests:: tsc:: declarationEmit::", () => { rootProject: "plugin-one", files: [ { - path: `${ts.tscWatch.projectRoot}/plugin-two/package.json`, + path: `${projectRoot}/plugin-two/package.json`, content: JSON.stringify({ name: "plugin-two", version: "0.1.3", main: "dist/commonjs/index.js" }) }, - { path: `${ts.tscWatch.projectRoot}/plugin-two/dist/commonjs/index.d.ts`, content: pluginTwoDts() }, - { path: `${ts.tscWatch.projectRoot}/plugin-two/node_modules/typescript-fsa/package.json`, content: fsaPackageJson() }, - { path: `${ts.tscWatch.projectRoot}/plugin-two/node_modules/typescript-fsa/index.d.ts`, content: fsaIndex() }, - { path: `${ts.tscWatch.projectRoot}/plugin-one/tsconfig.json`, content: pluginOneConfig() }, + { path: `${projectRoot}/plugin-two/dist/commonjs/index.d.ts`, content: pluginTwoDts() }, + { path: `${projectRoot}/plugin-two/node_modules/typescript-fsa/package.json`, content: fsaPackageJson() }, + { path: `${projectRoot}/plugin-two/node_modules/typescript-fsa/index.d.ts`, content: fsaIndex() }, + { path: `${projectRoot}/plugin-one/tsconfig.json`, content: pluginOneConfig() }, { - path: `${ts.tscWatch.projectRoot}/plugin-one/index.ts`, + path: `${projectRoot}/plugin-one/index.ts`, content: `${pluginOneIndex()} ${pluginOneAction()}` }, - { path: `${ts.tscWatch.projectRoot}/plugin-one/node_modules/typescript-fsa/package.json`, content: fsaPackageJson() }, - { path: `${ts.tscWatch.projectRoot}/plugin-one/node_modules/typescript-fsa/index.d.ts`, content: fsaIndex() }, - { path: `/temp/yarn/data/link/plugin-two`, symLink: `${ts.tscWatch.projectRoot}/plugin-two` }, - { path: `${ts.tscWatch.projectRoot}/plugin-one/node_modules/plugin-two`, symLink: `/temp/yarn/data/link/plugin-two` }, - ts.tscWatch.libFile + { path: `${projectRoot}/plugin-one/node_modules/typescript-fsa/package.json`, content: fsaPackageJson() }, + { path: `${projectRoot}/plugin-one/node_modules/typescript-fsa/index.d.ts`, content: fsaIndex() }, + { path: `/temp/yarn/data/link/plugin-two`, symLink: `${projectRoot}/plugin-two` }, + { path: `${projectRoot}/plugin-one/node_modules/plugin-two`, symLink: `/temp/yarn/data/link/plugin-two` }, + libFile ], - changeCaseFileTestPath: str => ts.stringContains(str, "/plugin-two"), + changeCaseFileTestPath: str => stringContains(str, "/plugin-two"), }); }); @@ -162,13 +164,13 @@ ${pluginOneAction()}` rootProject: "pkg3", files: [ { - path: `${ts.tscWatch.projectRoot}/pkg1/dist/index.d.ts`, - content: Utils.dedent` + path: `${projectRoot}/pkg1/dist/index.d.ts`, + content: dedent` export * from './types';` }, { - path: `${ts.tscWatch.projectRoot}/pkg1/dist/types.d.ts`, - content: Utils.dedent` + path: `${projectRoot}/pkg1/dist/types.d.ts`, + content: dedent` export declare type A = { id: string; }; @@ -184,7 +186,7 @@ ${pluginOneAction()}` }` }, { - path: `${ts.tscWatch.projectRoot}/pkg1/package.json`, + path: `${projectRoot}/pkg1/package.json`, content: JSON.stringify({ name: "@raymondfeng/pkg1", version: "1.0.0", @@ -193,17 +195,17 @@ ${pluginOneAction()}` }) }, { - path: `${ts.tscWatch.projectRoot}/pkg2/dist/index.d.ts`, - content: Utils.dedent` + path: `${projectRoot}/pkg2/dist/index.d.ts`, + content: dedent` export * from './types';` }, { - path: `${ts.tscWatch.projectRoot}/pkg2/dist/types.d.ts`, - content: Utils.dedent` + path: `${projectRoot}/pkg2/dist/types.d.ts`, + content: dedent` export {MetadataAccessor} from '@raymondfeng/pkg1';` }, { - path: `${ts.tscWatch.projectRoot}/pkg2/package.json`, + path: `${projectRoot}/pkg2/package.json`, content: JSON.stringify({ name: "@raymondfeng/pkg2", version: "1.0.0", @@ -212,18 +214,18 @@ ${pluginOneAction()}` }) }, { - path: `${ts.tscWatch.projectRoot}/pkg3/src/index.ts`, - content: Utils.dedent` + path: `${projectRoot}/pkg3/src/index.ts`, + content: dedent` export * from './keys';` }, { - path: `${ts.tscWatch.projectRoot}/pkg3/src/keys.ts`, - content: Utils.dedent` + path: `${projectRoot}/pkg3/src/keys.ts`, + content: dedent` import {MetadataAccessor} from "@raymondfeng/pkg2"; export const ADMIN = MetadataAccessor.create('1');` }, { - path: `${ts.tscWatch.projectRoot}/pkg3/tsconfig.json`, + path: `${projectRoot}/pkg3/tsconfig.json`, content: JSON.stringify({ compilerOptions: { outDir: "dist", @@ -237,16 +239,16 @@ ${pluginOneAction()}` }) }, { - path: `${ts.tscWatch.projectRoot}/pkg2/node_modules/@raymondfeng/pkg1`, - symLink: `${ts.tscWatch.projectRoot}/pkg1` + path: `${projectRoot}/pkg2/node_modules/@raymondfeng/pkg1`, + symLink: `${projectRoot}/pkg1` }, { - path: `${ts.tscWatch.projectRoot}/pkg3/node_modules/@raymondfeng/pkg2`, - symLink: `${ts.tscWatch.projectRoot}/pkg2` + path: `${projectRoot}/pkg3/node_modules/@raymondfeng/pkg2`, + symLink: `${projectRoot}/pkg2` }, - ts.tscWatch.libFile + libFile ], - changeCaseFileTestPath: str => ts.stringContains(str, "/pkg1"), + changeCaseFileTestPath: str => stringContains(str, "/pkg1"), }); }); diff --git a/src/testRunner/unittests/tsc/helpers.ts b/src/testRunner/unittests/tsc/helpers.ts index 7d1f9dde81644..54c8dba349cb0 100644 --- a/src/testRunner/unittests/tsc/helpers.ts +++ b/src/testRunner/unittests/tsc/helpers.ts @@ -1,20 +1,33 @@ -import * as fakes from "../../_namespaces/fakes"; -import * as Harness from "../../_namespaces/Harness"; +import { BuilderProgram } from "../../../compiler/builderPublic"; +import { emptyArray, endsWith, getProperty, noop } from "../../../compiler/core"; +import { MapLike, Set } from "../../../compiler/corePublic"; +import { Debug } from "../../../compiler/debug"; +import { createBuilderStatusReporter, createSolutionBuilderHost } from "../../../compiler/tsbuildPublic"; +import { ExitStatus, ParsedCommandLine, Path, Program } from "../../../compiler/types"; +import { createDiagnosticReporter, isBuilderProgram } from "../../../compiler/watch"; +import { + executeCommandLine, ExecuteCommandLineCallbacks, isBuild, +} from "../../../executeCommandLine/executeCommandLine"; +import { patchHostForBuildInfoReadWrite, patchHostForBuildInfoWrite, System } from "../../../harness/fakesHosts"; +import { Baseline } from "../../../harness/harnessIO"; +import { FileSystem, formatPatch } from "../../../harness/vfsUtil"; import * as ts from "../../_namespaces/ts"; -import * as vfs from "../../_namespaces/vfs"; +import { tscWatch } from "../../_namespaces/ts"; +import { baselineBuildInfo, generateSourceMapBaselineFiles, TestTscEdit, toPathWithSystem } from "../tsbuild/helpers"; +import { WatchedSystem } from "../tscWatch/helpers"; -export type TscCompileSystem = fakes.System & { - writtenFiles: ts.Set; +export type TscCompileSystem = System & { + writtenFiles: Set; baseLine(): { file: string; text: string; }; disableUseFileVersionAsSignature?: boolean; storeFilesChangingSignatureDuringEmit?: boolean; }; -export const noChangeRun: ts.TestTscEdit = { +export const noChangeRun: TestTscEdit = { subScenario: "no-change-run", - modifyFs: ts.noop + modifyFs: noop }; -export const noChangeWithExportsDiscrepancyRun: ts.TestTscEdit = { +export const noChangeWithExportsDiscrepancyRun: TestTscEdit = { ...noChangeRun, discrepancyExplanation: () => [ "Incremental build did not emit and has .ts as signature so exports has all imported modules/referenced files", @@ -31,17 +44,17 @@ export interface TestTscCompile extends TestTscCompileLikeBase { baselineDependencies?: boolean; } -export type CommandLineProgram = [ts.Program, ts.BuilderProgram?]; +export type CommandLineProgram = [Program, BuilderProgram?]; export interface CommandLineCallbacks { - cb: ts.ExecuteCommandLineCallbacks; + cb: ExecuteCommandLineCallbacks; getPrograms: () => readonly CommandLineProgram[]; } -function isAnyProgram(program: ts.Program | ts.BuilderProgram | ts.ParsedCommandLine): program is ts.Program | ts.BuilderProgram { - return !!(program as ts.Program | ts.BuilderProgram).getCompilerOptions; +function isAnyProgram(program: Program | BuilderProgram | ParsedCommandLine): program is Program | BuilderProgram { + return !!(program as Program | BuilderProgram).getCompilerOptions; } export function commandLineCallbacks( - sys: TscCompileSystem | ts.tscWatch.WatchedSystem, + sys: TscCompileSystem | WatchedSystem, originalReadCall?: ts.System["readFile"], ): CommandLineCallbacks { let programs: CommandLineProgram[] | undefined; @@ -49,18 +62,18 @@ export function commandLineCallbacks( return { cb: program => { if (isAnyProgram(program)) { - ts.baselineBuildInfo(program.getCompilerOptions(), sys, originalReadCall); - (programs || (programs = [])).push(ts.isBuilderProgram(program) ? + baselineBuildInfo(program.getCompilerOptions(), sys, originalReadCall); + (programs || (programs = [])).push(isBuilderProgram(program) ? [program.getProgram(), program] : [program] ); } else { - ts.baselineBuildInfo(program.options, sys, originalReadCall); + baselineBuildInfo(program.options, sys, originalReadCall); } }, getPrograms: () => { - const result = programs || ts.emptyArray; + const result = programs || emptyArray; programs = undefined; return result; } @@ -68,7 +81,7 @@ export function commandLineCallbacks( } export interface TestTscCompileLikeBase extends VerifyTscCompileLike { diffWithInitial?: boolean; - modifyFs?: (fs: vfs.FileSystem) => void; + modifyFs?: (fs: FileSystem) => void; disableUseFileVersionAsSignature?: boolean; environmentVariables?: Record; } @@ -94,13 +107,13 @@ export function testTscCompileLike(input: TestTscCompileLike) { const fs = inputFs.shadow(); // Create system - const sys = new fakes.System(fs, { executingFilePath: "/lib/tsc", env: environmentVariables }) as TscCompileSystem; + const sys = new System(fs, { executingFilePath: "/lib/tsc", env: environmentVariables }) as TscCompileSystem; if (input.disableUseFileVersionAsSignature) sys.disableUseFileVersionAsSignature = true; sys.storeFilesChangingSignatureDuringEmit = true; sys.write(`${sys.getExecutingFilePath()} ${commandLineArgs.join(" ")}\n`); sys.exit = exitCode => sys.exitCode = exitCode; worker(sys); - sys.write(`exitCode:: ExitStatus.${ts.ExitStatus[sys.exitCode as ts.ExitStatus]}\n`); + sys.write(`exitCode:: ExitStatus.${ExitStatus[sys.exitCode as ExitStatus]}\n`); additionalBaseline?.(sys); fs.makeReadonly(); sys.baseLine = () => { @@ -109,14 +122,14 @@ export function testTscCompileLike(input: TestTscCompileLike) { inputFs.diff(/*base*/ undefined, { baseIsNotShadowRoot: true }); const patch = fs.diff(inputFs, { includeChangedFileWithSameContent: true }); return { - file: `${ts.isBuild(commandLineArgs) ? "tsbuild" : "tsc"}/${scenario}/${subScenario.split(" ").join("-")}.js`, + file: `${isBuild(commandLineArgs) ? "tsbuild" : "tsc"}/${scenario}/${subScenario.split(" ").join("-")}.js`, text: `Input:: -${baseFsPatch ? vfs.formatPatch(baseFsPatch) : ""} +${baseFsPatch ? formatPatch(baseFsPatch) : ""} Output:: ${sys.output.join("")} -${patch ? vfs.formatPatch(patch) : ""}` +${patch ? formatPatch(patch) : ""}` }; }; return sys; @@ -124,35 +137,35 @@ ${patch ? vfs.formatPatch(patch) : ""}` function makeSystemReadyForBaseline(sys: TscCompileSystem, versionToWrite?: string) { if (versionToWrite) { - fakes.patchHostForBuildInfoWrite(sys, versionToWrite); + patchHostForBuildInfoWrite(sys, versionToWrite); } else { - fakes.patchHostForBuildInfoReadWrite(sys); + patchHostForBuildInfoReadWrite(sys); } - const writtenFiles = sys.writtenFiles = new ts.Set(); + const writtenFiles = sys.writtenFiles = new Set(); const originalWriteFile = sys.writeFile; sys.writeFile = (fileName, content, writeByteOrderMark) => { - const path = ts.toPathWithSystem(sys, fileName); + const path = toPathWithSystem(sys, fileName); // When buildinfo is same for two projects, // it gives error and doesnt write buildinfo but because buildInfo is written for one project, // readable baseline will be written two times for those two projects with same contents and is ok - ts.Debug.assert(!writtenFiles.has(path) || ts.endsWith(path, "baseline.txt")); + Debug.assert(!writtenFiles.has(path) || endsWith(path, "baseline.txt")); writtenFiles.add(path); return originalWriteFile.call(sys, fileName, content, writeByteOrderMark); }; } export function createSolutionBuilderHostForBaseline( - sys: TscCompileSystem | ts.tscWatch.WatchedSystem, + sys: TscCompileSystem | WatchedSystem, versionToWrite?: string, - originalRead?: (TscCompileSystem | ts.tscWatch.WatchedSystem)["readFile"] + originalRead?: (TscCompileSystem | WatchedSystem)["readFile"] ) { - if (sys instanceof fakes.System) makeSystemReadyForBaseline(sys, versionToWrite); + if (sys instanceof System) makeSystemReadyForBaseline(sys, versionToWrite); const { cb } = commandLineCallbacks(sys, originalRead); - const host = ts.createSolutionBuilderHost(sys, + const host = createSolutionBuilderHost(sys, /*createProgram*/ undefined, - ts.createDiagnosticReporter(sys, /*pretty*/ true), - ts.createBuilderStatusReporter(sys, /*pretty*/ true), + createDiagnosticReporter(sys, /*pretty*/ true), + createBuilderStatusReporter(sys, /*pretty*/ true), ); host.afterProgramEmitAndDiagnostics = cb; host.afterEmitBundle = cb; @@ -163,7 +176,7 @@ export function createSolutionBuilderHostForBaseline( * Initialize Fs, execute command line and save baseline */ export function testTscCompile(input: TestTscCompile) { - let actualReadFileMap: ts.MapLike | undefined; + let actualReadFileMap: MapLike | undefined; let getPrograms: CommandLineCallbacks["getPrograms"] | undefined; return testTscCompileLike({ ...input, @@ -178,13 +191,13 @@ export function testTscCompile(input: TestTscCompile) { sys.readFile = path => { // Dont record libs if (path.startsWith("/src/")) { - actualReadFileMap![path] = (ts.getProperty(actualReadFileMap!, path) || 0) + 1; + actualReadFileMap![path] = (getProperty(actualReadFileMap!, path) || 0) + 1; } return originalReadFile.call(sys, path); }; const result = commandLineCallbacks(sys, originalReadFile); - ts.executeCommandLine( + executeCommandLine( sys, result.cb, input.commandLineArgs, @@ -197,13 +210,13 @@ export function testTscCompile(input: TestTscCompile) { const { baselineSourceMap, baselineReadFileCalls, baselinePrograms, baselineDependencies } = input; if (baselinePrograms) { const baseline: string[] = []; - ts.tscWatch.baselinePrograms(baseline, getPrograms!, ts.emptyArray, baselineDependencies); + tscWatch.baselinePrograms(baseline, getPrograms!, emptyArray, baselineDependencies); sys.write(baseline.join("\n")); } if (baselineReadFileCalls) { sys.write(`readFiles:: ${JSON.stringify(actualReadFileMap, /*replacer*/ undefined, " ")} `); } - if (baselineSourceMap) ts.generateSourceMapBaselineFiles(sys); + if (baselineSourceMap) generateSourceMapBaselineFiles(sys); actualReadFileMap = undefined; getPrograms = undefined; } @@ -212,14 +225,14 @@ export function testTscCompile(input: TestTscCompile) { export function verifyTscBaseline(sys: () => { baseLine: TscCompileSystem["baseLine"]; }) { it(`Generates files matching the baseline`, () => { const { file, text } = sys().baseLine(); - Harness.Baseline.runBaseline(file, text); + Baseline.runBaseline(file, text); }); } export interface VerifyTscCompileLike { scenario: string; subScenario: string; commandLineArgs: readonly string[]; - fs: () => vfs.FileSystem; + fs: () => FileSystem; } /** diff --git a/src/testRunner/unittests/tsc/incremental.ts b/src/testRunner/unittests/tsc/incremental.ts index 1e11edcb269a3..736f386f52ffa 100644 --- a/src/testRunner/unittests/tsc/incremental.ts +++ b/src/testRunner/unittests/tsc/incremental.ts @@ -1,14 +1,21 @@ -import * as ts from "../../_namespaces/ts"; -import * as Utils from "../../_namespaces/Utils"; -import * as vfs from "../../_namespaces/vfs"; +import { hasProperty } from "../../../compiler/core"; +import { CompilerOptions } from "../../../compiler/types"; +import { getEmitDeclarations } from "../../../compiler/utilities"; +import { dedent } from "../../../harness/util"; +import { FileSystem } from "../../../harness/vfsUtil"; +import { + appendText, libContent, loadProjectFromDisk, loadProjectFromFiles, prependText, replaceText, TestTscEdit, + verifyTscWithEdits, +} from "../tsbuild/helpers"; +import { noChangeOnlyRuns, noChangeRun, noChangeWithExportsDiscrepancyRun, verifyTsc } from "./helpers"; describe("unittests:: tsc:: incremental::", () => { - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "incremental", subScenario: "when passing filename for buildinfo on commandline", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/project/src/main.ts": "export const x = 10;", - "/src/project/tsconfig.json": Utils.dedent` + "/src/project/tsconfig.json": dedent` { "compilerOptions": { "target": "es5", @@ -20,15 +27,15 @@ describe("unittests:: tsc:: incremental::", () => { }`, }), commandLineArgs: ["--incremental", "--p", "src/project", "--tsBuildInfoFile", "src/project/.tsbuildinfo", "--explainFiles"], - edits: ts.noChangeOnlyRuns + edits: noChangeOnlyRuns }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "incremental", subScenario: "when passing rootDir from commandline", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/project/src/main.ts": "export const x = 10;", - "/src/project/tsconfig.json": Utils.dedent` + "/src/project/tsconfig.json": dedent` { "compilerOptions": { "incremental": true, @@ -37,33 +44,33 @@ describe("unittests:: tsc:: incremental::", () => { }`, }), commandLineArgs: ["--p", "src/project", "--rootDir", "src/project/src"], - edits: ts.noChangeOnlyRuns + edits: noChangeOnlyRuns }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "incremental", subScenario: "with only dts files", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/project/src/main.d.ts": "export const x = 10;", "/src/project/src/another.d.ts": "export const y = 10;", "/src/project/tsconfig.json": "{}", }), commandLineArgs: ["--incremental", "--p", "src/project"], edits: [ - ts.noChangeRun, + noChangeRun, { subScenario: "incremental-declaration-doesnt-change", - modifyFs: fs => ts.appendText(fs, "/src/project/src/main.d.ts", "export const xy = 100;") + modifyFs: fs => appendText(fs, "/src/project/src/main.d.ts", "export const xy = 100;") } ] }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "incremental", subScenario: "when passing rootDir is in the tsconfig", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/project/src/main.ts": "export const x = 10;", - "/src/project/tsconfig.json": Utils.dedent` + "/src/project/tsconfig.json": dedent` { "compilerOptions": { "incremental": true, @@ -73,32 +80,32 @@ describe("unittests:: tsc:: incremental::", () => { }`, }), commandLineArgs: ["--p", "src/project"], - edits: ts.noChangeOnlyRuns + edits: noChangeOnlyRuns }); describe("with noEmitOnError", () => { - let projFs: vfs.FileSystem; + let projFs: FileSystem; before(() => { - projFs = ts.loadProjectFromDisk("tests/projects/noEmitOnError"); + projFs = loadProjectFromDisk("tests/projects/noEmitOnError"); }); after(() => { projFs = undefined!; }); - function verifyNoEmitOnError(subScenario: string, fixModifyFs: ts.TestTscEdit["modifyFs"], modifyFs?: ts.TestTscEdit["modifyFs"]) { - ts.verifyTscWithEdits({ + function verifyNoEmitOnError(subScenario: string, fixModifyFs: TestTscEdit["modifyFs"], modifyFs?: TestTscEdit["modifyFs"]) { + verifyTscWithEdits({ scenario: "incremental", subScenario, fs: () => projFs, commandLineArgs: ["--incremental", "-p", "src"], modifyFs, edits: [ - ts.noChangeWithExportsDiscrepancyRun, + noChangeWithExportsDiscrepancyRun, { subScenario: "incremental-declaration-doesnt-change", modifyFs: fixModifyFs }, - ts.noChangeRun, + noChangeRun, ], baselinePrograms: true }); @@ -125,30 +132,30 @@ const a: string = 10;`, "utf-8"), verifyNoEmitChanges({ incremental: true, declaration: true }); verifyNoEmitChanges({ composite: true }); - function verifyNoEmitChanges(compilerOptions: ts.CompilerOptions) { - const discrepancyIfNoDtsEmit = ts.getEmitDeclarations(compilerOptions) ? + function verifyNoEmitChanges(compilerOptions: CompilerOptions) { + const discrepancyIfNoDtsEmit = getEmitDeclarations(compilerOptions) ? undefined : - ts.noChangeWithExportsDiscrepancyRun.discrepancyExplanation; - const noChangeRunWithNoEmit: ts.TestTscEdit = { - ...ts.noChangeRun, + noChangeWithExportsDiscrepancyRun.discrepancyExplanation; + const noChangeRunWithNoEmit: TestTscEdit = { + ...noChangeRun, subScenario: "No Change run with noEmit", commandLineArgs: ["--p", "src/project", "--noEmit"], discrepancyExplanation: discrepancyIfNoDtsEmit, }; - const noChangeRunWithEmit: ts.TestTscEdit = { - ...ts.noChangeRun, + const noChangeRunWithEmit: TestTscEdit = { + ...noChangeRun, subScenario: "No Change run with emit", commandLineArgs: ["--p", "src/project"], discrepancyExplanation: discrepancyIfNoDtsEmit, }; let optionsString = ""; for (const key in compilerOptions) { - if (ts.hasProperty(compilerOptions, key)) { + if (hasProperty(compilerOptions, key)) { optionsString += ` ${key}`; } } - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "incremental", subScenario: `noEmit changes${optionsString}`, commandLineArgs: ["--p", "src/project"], @@ -159,12 +166,12 @@ const a: string = 10;`, "utf-8"), { subScenario: "Introduce error but still noEmit", commandLineArgs: ["--p", "src/project", "--noEmit"], - modifyFs: fs => ts.replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"), - discrepancyExplanation: ts.getEmitDeclarations(compilerOptions) ? ts.noChangeWithExportsDiscrepancyRun.discrepancyExplanation : undefined, + modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"), + discrepancyExplanation: getEmitDeclarations(compilerOptions) ? noChangeWithExportsDiscrepancyRun.discrepancyExplanation : undefined, }, { subScenario: "Fix error and emit", - modifyFs: fs => ts.replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"), + modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"), discrepancyExplanation: discrepancyIfNoDtsEmit }, noChangeRunWithEmit, @@ -173,7 +180,7 @@ const a: string = 10;`, "utf-8"), noChangeRunWithEmit, { subScenario: "Introduce error and emit", - modifyFs: fs => ts.replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"), + modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"), discrepancyExplanation: discrepancyIfNoDtsEmit }, noChangeRunWithEmit, @@ -183,8 +190,8 @@ const a: string = 10;`, "utf-8"), { subScenario: "Fix error and no emit", commandLineArgs: ["--p", "src/project", "--noEmit"], - modifyFs: fs => ts.replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"), - discrepancyExplanation: ts.noChangeWithExportsDiscrepancyRun.discrepancyExplanation, + modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"), + discrepancyExplanation: noChangeWithExportsDiscrepancyRun.discrepancyExplanation, }, noChangeRunWithEmit, noChangeRunWithNoEmit, @@ -193,7 +200,7 @@ const a: string = 10;`, "utf-8"), ], }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "incremental", subScenario: `noEmit changes with initial noEmit${optionsString}`, commandLineArgs: ["--p", "src/project", "--noEmit"], @@ -203,38 +210,38 @@ const a: string = 10;`, "utf-8"), { subScenario: "Introduce error with emit", commandLineArgs: ["--p", "src/project"], - modifyFs: fs => ts.replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"), + modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"), }, { subScenario: "Fix error and no emit", - modifyFs: fs => ts.replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"), - discrepancyExplanation: ts.noChangeWithExportsDiscrepancyRun.discrepancyExplanation + modifyFs: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"), + discrepancyExplanation: noChangeWithExportsDiscrepancyRun.discrepancyExplanation }, noChangeRunWithEmit, ], }); function fs() { - return ts.loadProjectFromFiles({ - "/src/project/src/class.ts": Utils.dedent` + return loadProjectFromFiles({ + "/src/project/src/class.ts": dedent` export class classC { prop = 1; }`, - "/src/project/src/indirectClass.ts": Utils.dedent` + "/src/project/src/indirectClass.ts": dedent` import { classC } from './class'; export class indirectClass { classC = new classC(); }`, - "/src/project/src/directUse.ts": Utils.dedent` + "/src/project/src/directUse.ts": dedent` import { indirectClass } from './indirectClass'; new indirectClass().classC.prop;`, - "/src/project/src/indirectUse.ts": Utils.dedent` + "/src/project/src/indirectUse.ts": dedent` import { indirectClass } from './indirectClass'; new indirectClass().classC.prop;`, - "/src/project/src/noChangeFile.ts": Utils.dedent` + "/src/project/src/noChangeFile.ts": dedent` export function writeLog(s: string) { }`, - "/src/project/src/noChangeFileWithEmitSpecificError.ts": Utils.dedent` + "/src/project/src/noChangeFileWithEmitSpecificError.ts": dedent` function someFunc(arguments: boolean, ...rest: any[]) { }`, "/src/project/tsconfig.json": JSON.stringify({ compilerOptions }), @@ -243,16 +250,16 @@ const a: string = 10;`, "utf-8"), } }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "incremental", subScenario: `when global file is added, the signatures are updated`, - fs: () => ts.loadProjectFromFiles({ - "/src/project/src/main.ts": Utils.dedent` + fs: () => loadProjectFromFiles({ + "/src/project/src/main.ts": dedent` /// /// function main() { } `, - "/src/project/src/anotherFileWithSameReferenes.ts": Utils.dedent` + "/src/project/src/anotherFileWithSameReferenes.ts": dedent` /// /// function anotherFileWithSameReferenes() { } @@ -265,22 +272,22 @@ const a: string = 10;`, "utf-8"), }), commandLineArgs: ["--p", "src/project"], edits: [ - ts.noChangeRun, + noChangeRun, { subScenario: "Modify main file", - modifyFs: fs => ts.appendText(fs, `/src/project/src/main.ts`, `something();`), + modifyFs: fs => appendText(fs, `/src/project/src/main.ts`, `something();`), }, { subScenario: "Modify main file again", - modifyFs: fs => ts.appendText(fs, `/src/project/src/main.ts`, `something();`), + modifyFs: fs => appendText(fs, `/src/project/src/main.ts`, `something();`), }, { subScenario: "Add new file and update main file", modifyFs: fs => { fs.writeFileSync(`/src/project/src/newFile.ts`, "function foo() { return 20; }"); - ts.prependText(fs, `/src/project/src/main.ts`, `/// + prependText(fs, `/src/project/src/main.ts`, `/// `); - ts.appendText(fs, `/src/project/src/main.ts`, `foo();`); + appendText(fs, `/src/project/src/main.ts`, `foo();`); }, }, { @@ -289,7 +296,7 @@ const a: string = 10;`, "utf-8"), }, { subScenario: "Modify main file", - modifyFs: fs => ts.appendText(fs, `/src/project/src/main.ts`, `something();`), + modifyFs: fs => appendText(fs, `/src/project/src/main.ts`, `something();`), }, ], baselinePrograms: true, @@ -311,10 +318,10 @@ declare global { }`; } - ts.verifyTsc({ + verifyTsc({ scenario: "react-jsx-emit-mode", subScenario: "with no backing types found doesn't crash", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result "/src/project/node_modules/@types/react/index.d.ts": getJsxLibraryContent(), // doesn't contain a jsx-runtime definition "/src/project/src/index.tsx": `export const App = () =>
;`, @@ -323,10 +330,10 @@ declare global { commandLineArgs: ["--p", "src/project"] }); - ts.verifyTsc({ + verifyTsc({ scenario: "react-jsx-emit-mode", subScenario: "with no backing types found doesn't crash under --strict", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result "/src/project/node_modules/@types/react/index.d.ts": getJsxLibraryContent(), // doesn't contain a jsx-runtime definition "/src/project/src/index.tsx": `export const App = () =>
;`, @@ -336,11 +343,11 @@ declare global { }); }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "incremental", subScenario: "when new file is added to the referenced project", commandLineArgs: ["-i", "-p", `src/projects/project2`], - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/projects/project1/tsconfig.json": JSON.stringify({ compilerOptions: { module: "none", @@ -397,11 +404,11 @@ declare global { }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "incremental", subScenario: "when project has strict true", commandLineArgs: ["-noEmit", "-p", `src/project`], - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/project/tsconfig.json": JSON.stringify({ compilerOptions: { incremental: true, @@ -410,15 +417,15 @@ declare global { }), "/src/project/class1.ts": `export class class1 {}`, }), - edits: ts.noChangeOnlyRuns, + edits: noChangeOnlyRuns, baselinePrograms: true }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "incremental", subScenario: "serializing error chains", commandLineArgs: ["-p", `src/project`], - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/project/tsconfig.json": JSON.stringify({ compilerOptions: { incremental: true, @@ -427,7 +434,7 @@ declare global { module: "esnext", }, }), - "/src/project/index.tsx": Utils.dedent` + "/src/project/index.tsx": dedent` declare namespace JSX { interface ElementChildrenAttribute { children: {}; } interface IntrinsicElements { div: {} } @@ -442,14 +449,14 @@ declare global {
)` }, `\ninterface ReadonlyArray { readonly length: number }`), - edits: ts.noChangeOnlyRuns, + edits: noChangeOnlyRuns, }); - ts.verifyTsc({ + verifyTsc({ scenario: "incremental", subScenario: "ts file with no-default-lib that augments the global scope", - fs: () => ts.loadProjectFromFiles({ - "/src/project/src/main.ts": Utils.dedent` + fs: () => loadProjectFromFiles({ + "/src/project/src/main.ts": dedent` /// /// @@ -460,7 +467,7 @@ declare global { export {}; `, - "/src/project/tsconfig.json": Utils.dedent` + "/src/project/tsconfig.json": dedent` { "compilerOptions": { "target": "ESNext", @@ -472,15 +479,15 @@ declare global { }), commandLineArgs: ["--p", "src/project", "--rootDir", "src/project/src"], modifyFs: (fs) => { - fs.writeFileSync("/lib/lib.esnext.d.ts", ts.libContent); + fs.writeFileSync("/lib/lib.esnext.d.ts", libContent); } }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "incremental", subScenario: "change to type that gets used as global through export in another file", commandLineArgs: ["-p", `src/project`], - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/project/tsconfig.json": JSON.stringify({ compilerOptions: { composite: true }, }), "/src/project/class1.ts": `const a: MagicNumber = 1; console.log(a);`, @@ -493,11 +500,11 @@ console.log(a);`, }], }); - ts.verifyTscWithEdits({ + verifyTscWithEdits({ scenario: "incremental", subScenario: "change to type that gets used as global through export in another file through indirect import", commandLineArgs: ["-p", `src/project`], - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/project/tsconfig.json": JSON.stringify({ compilerOptions: { composite: true }, }), "/src/project/class1.ts": `const a: MagicNumber = 1; console.log(a);`, diff --git a/src/testRunner/unittests/tsc/listFilesOnly.ts b/src/testRunner/unittests/tsc/listFilesOnly.ts index ca166ab56b17e..909ba3d8742c2 100644 --- a/src/testRunner/unittests/tsc/listFilesOnly.ts +++ b/src/testRunner/unittests/tsc/listFilesOnly.ts @@ -1,22 +1,23 @@ -import * as ts from "../../_namespaces/ts"; -import * as Utils from "../../_namespaces/Utils"; +import { dedent } from "../../../harness/util"; +import { loadProjectFromFiles } from "../tsbuild/helpers"; +import { verifyTsc } from "./helpers"; describe("unittests:: tsc:: listFilesOnly::", () => { - ts.verifyTsc({ + verifyTsc({ scenario: "listFilesOnly", subScenario: "combined with watch", - fs: () => ts.loadProjectFromFiles({ - "/src/test.ts": Utils.dedent` + fs: () => loadProjectFromFiles({ + "/src/test.ts": dedent` export const x = 1;`, }), commandLineArgs: ["/src/test.ts", "--watch", "--listFilesOnly"] }); - ts.verifyTsc({ + verifyTsc({ scenario: "listFilesOnly", subScenario: "loose file", - fs: () => ts.loadProjectFromFiles({ - "/src/test.ts": Utils.dedent` + fs: () => loadProjectFromFiles({ + "/src/test.ts": dedent` export const x = 1;`, }), commandLineArgs: ["/src/test.ts", "--listFilesOnly"] diff --git a/src/testRunner/unittests/tsc/projectReferences.ts b/src/testRunner/unittests/tsc/projectReferences.ts index a75a9f4deef3f..9b11208b527ec 100644 --- a/src/testRunner/unittests/tsc/projectReferences.ts +++ b/src/testRunner/unittests/tsc/projectReferences.ts @@ -1,10 +1,11 @@ -import * as ts from "../../_namespaces/ts"; +import { loadProjectFromFiles } from "../tsbuild/helpers"; +import { verifyTsc } from "./helpers"; describe("unittests:: tsc:: projectReferences::", () => { - ts.verifyTsc({ + verifyTsc({ scenario: "projectReferences", subScenario: "when project contains invalid project reference", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/project/src/main.ts": "export const x = 10;", "/src/project/tsconfig.json": JSON.stringify({ compilerOptions: { @@ -19,10 +20,10 @@ describe("unittests:: tsc:: projectReferences::", () => { commandLineArgs: ["--p", "src/project"], }); - ts.verifyTsc({ + verifyTsc({ scenario: "projectReferences", subScenario: "when project references composite project with noEmit", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/utils/index.ts": "export const x = 10;", "/src/utils/tsconfig.json": JSON.stringify({ compilerOptions: { diff --git a/src/testRunner/unittests/tsc/redirect.ts b/src/testRunner/unittests/tsc/redirect.ts index fb32bd57e194f..a18e18fcb4dfd 100644 --- a/src/testRunner/unittests/tsc/redirect.ts +++ b/src/testRunner/unittests/tsc/redirect.ts @@ -1,10 +1,11 @@ -import * as ts from "../../_namespaces/ts"; +import { loadProjectFromFiles } from "../tsbuild/helpers"; +import { verifyTsc } from "./helpers"; describe("unittests:: tsc:: redirect::", () => { - ts.verifyTsc({ + verifyTsc({ scenario: "redirect", subScenario: "when redirecting ts file", - fs: () => ts.loadProjectFromFiles({ + fs: () => loadProjectFromFiles({ "/src/project/tsconfig.json": JSON.stringify({ compilerOptions: { outDir: "out" diff --git a/src/testRunner/unittests/tsc/runWithoutArgs.ts b/src/testRunner/unittests/tsc/runWithoutArgs.ts index cd69d19964de8..b9653c938293a 100644 --- a/src/testRunner/unittests/tsc/runWithoutArgs.ts +++ b/src/testRunner/unittests/tsc/runWithoutArgs.ts @@ -1,25 +1,26 @@ -import * as ts from "../../_namespaces/ts"; +import { loadProjectFromFiles } from "../tsbuild/helpers"; +import { verifyTsc } from "./helpers"; describe("unittests:: tsc:: runWithoutArgs::", () => { - ts.verifyTsc({ + verifyTsc({ scenario: "runWithoutArgs", subScenario: "show help with ExitStatus.DiagnosticsPresent_OutputsSkipped", - fs: () => ts.loadProjectFromFiles({}), + fs: () => loadProjectFromFiles({}), commandLineArgs: [], environmentVariables: { TS_TEST_TERMINAL_WIDTH: "120" } }); - ts.verifyTsc({ + verifyTsc({ scenario: "runWithoutArgs", subScenario: "show help with ExitStatus.DiagnosticsPresent_OutputsSkipped when host can't provide terminal width", - fs: () => ts.loadProjectFromFiles({}), + fs: () => loadProjectFromFiles({}), commandLineArgs: [], }); - ts.verifyTsc({ + verifyTsc({ scenario: "runWithoutArgs", subScenario: "does not add color when NO_COLOR is set", - fs: () => ts.loadProjectFromFiles({}), + fs: () => loadProjectFromFiles({}), commandLineArgs: [], environmentVariables: { NO_COLOR: "true" } }); diff --git a/src/testRunner/unittests/tscWatch/consoleClearing.ts b/src/testRunner/unittests/tscWatch/consoleClearing.ts index ace84a8b9ecc0..5551fad3b19ee 100644 --- a/src/testRunner/unittests/tscWatch/consoleClearing.ts +++ b/src/testRunner/unittests/tscWatch/consoleClearing.ts @@ -1,24 +1,30 @@ -import * as ts from "../../_namespaces/ts"; +import { emptyArray } from "../../../compiler/core"; +import { CompilerOptions } from "../../../compiler/types"; +import { createWatchProgram } from "../../../compiler/watchPublic"; +import { + createBaseline, createWatchCompilerHostOfConfigFileForBaseline, createWatchedSystem, File, libFile, + runQueuedTimeoutCallbacks, runWatchBaseline, TscWatchCompileChange, verifyTscWatch, +} from "./helpers"; describe("unittests:: tsc-watch:: console clearing", () => { const scenario = "consoleClearing"; - const file: ts.tscWatch.File = { + const file: File = { path: "/f.ts", content: "" }; - const makeChangeToFile: ts.tscWatch.TscWatchCompileChange[] = [{ + const makeChangeToFile: TscWatchCompileChange[] = [{ caption: "Comment added to file f", change: sys => sys.modifyFile(file.path, "//"), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }]; function checkConsoleClearingUsingCommandLineOptions(subScenario: string, commandLineOptions?: string[]) { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario, - commandLineArgs: ["--w", file.path, ...commandLineOptions || ts.emptyArray], - sys: () => ts.tscWatch.createWatchedSystem([file, ts.tscWatch.libFile]), + commandLineArgs: ["--w", file.path, ...commandLineOptions || emptyArray], + sys: () => createWatchedSystem([file, libFile]), changes: makeChangeToFile, }); } @@ -29,23 +35,23 @@ describe("unittests:: tsc-watch:: console clearing", () => { checkConsoleClearingUsingCommandLineOptions("with --preserveWatchOutput", ["--preserveWatchOutput"]); describe("when preserveWatchOutput is true in config file", () => { - const compilerOptions: ts.CompilerOptions = { + const compilerOptions: CompilerOptions = { preserveWatchOutput: true }; - const configFile: ts.tscWatch.File = { + const configFile: File = { path: "/tsconfig.json", content: JSON.stringify({ compilerOptions }) }; - const files = [file, configFile, ts.tscWatch.libFile]; + const files = [file, configFile, libFile]; it("using createWatchOfConfigFile ", () => { - const baseline = ts.tscWatch.createBaseline(ts.tscWatch.createWatchedSystem(files)); - const watch = ts.createWatchProgram(ts.tscWatch.createWatchCompilerHostOfConfigFileForBaseline({ + const baseline = createBaseline(createWatchedSystem(files)); + const watch = createWatchProgram(createWatchCompilerHostOfConfigFileForBaseline({ system: baseline.sys, cb: baseline.cb, configFileName: configFile.path, })); // Initially console is cleared if --preserveOutput is not provided since the config file is yet to be parsed - ts.tscWatch.runWatchBaseline({ + runWatchBaseline({ scenario, subScenario: "when preserveWatchOutput is true in config file/createWatchOfConfigFile", commandLineArgs: ["--w", "-p", configFile.path], @@ -55,11 +61,11 @@ describe("unittests:: tsc-watch:: console clearing", () => { watchOrSolution: watch }); }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "when preserveWatchOutput is true in config file/when createWatchProgram is invoked with configFileParseResult on WatchCompilerHostOfConfigFile", commandLineArgs: ["--w", "-p", configFile.path], - sys: () => ts.tscWatch.createWatchedSystem(files), + sys: () => createWatchedSystem(files), changes: makeChangeToFile, }); }); diff --git a/src/testRunner/unittests/tscWatch/emit.ts b/src/testRunner/unittests/tscWatch/emit.ts index cdc76ed27ebd1..2dccb2e8f0f0b 100644 --- a/src/testRunner/unittests/tscWatch/emit.ts +++ b/src/testRunner/unittests/tscWatch/emit.ts @@ -1,37 +1,41 @@ -import * as ts from "../../_namespaces/ts"; +import { emptyArray, find, map } from "../../../compiler/core"; +import { + checkSingleTimeoutQueueLengthAndRun, createWatchedSystem, File, libFile, runQueuedTimeoutCallbacks, + TscWatchCompileChange, verifyTscWatch, WatchedSystem, +} from "./helpers"; const scenario = "emit"; describe("unittests:: tsc-watch:: emit with outFile or out setting", () => { function verifyOutAndOutFileSetting(subScenario: string, out?: string, outFile?: string) { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: `emit with outFile or out setting/${subScenario}`, commandLineArgs: ["--w", "-p", "/a/tsconfig.json"], sys: () => { - const config: ts.tscWatch.File = { + const config: File = { path: "/a/tsconfig.json", content: JSON.stringify({ compilerOptions: { out, outFile } }) }; - const f1: ts.tscWatch.File = { + const f1: File = { path: "/a/a.ts", content: "let x = 1" }; - const f2: ts.tscWatch.File = { + const f2: File = { path: "/a/b.ts", content: "let y = 1" }; - return ts.tscWatch.createWatchedSystem([f1, f2, config, ts.tscWatch.libFile]); + return createWatchedSystem([f1, f2, config, libFile]); }, changes: [ { caption: "Make change in the file", change: sys => sys.writeFile("/a/a.ts", "let x = 11"), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks + timeouts: runQueuedTimeoutCallbacks }, { caption: "Make change in the file again", change: sys => sys.writeFile("/a/a.ts", "let xy = 11"), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks + timeouts: runQueuedTimeoutCallbacks } ] }); @@ -41,28 +45,28 @@ describe("unittests:: tsc-watch:: emit with outFile or out setting", () => { verifyOutAndOutFileSetting("config has outFile", /*out*/ undefined, "/a/out.js"); function verifyFilesEmittedOnce(subScenario: string, useOutFile: boolean) { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: `emit with outFile or out setting/${subScenario}`, commandLineArgs: ["--w", "-p", "/a/b/project/tsconfig.json"], sys: () => { - const file1: ts.tscWatch.File = { + const file1: File = { path: "/a/b/output/AnotherDependency/file1.d.ts", content: "declare namespace Common.SomeComponent.DynamicMenu { enum Z { Full = 0, Min = 1, Average = 2, } }" }; - const file2: ts.tscWatch.File = { + const file2: File = { path: "/a/b/dependencies/file2.d.ts", content: "declare namespace Dependencies.SomeComponent { export class SomeClass { version: string; } }" }; - const file3: ts.tscWatch.File = { + const file3: File = { path: "/a/b/project/src/main.ts", content: "namespace Main { export function fooBar() {} }" }; - const file4: ts.tscWatch.File = { + const file4: File = { path: "/a/b/project/src/main2.ts", content: "namespace main.file4 { import DynamicMenu = Common.SomeComponent.DynamicMenu; export function foo(a: DynamicMenu.z) { } }" }; - const configFile: ts.tscWatch.File = { + const configFile: File = { path: "/a/b/project/tsconfig.json", content: JSON.stringify({ compilerOptions: useOutFile ? @@ -71,9 +75,9 @@ describe("unittests:: tsc-watch:: emit with outFile or out setting", () => { files: [file1.path, file2.path, file3.path, file4.path] }) }; - return ts.tscWatch.createWatchedSystem([file1, file2, file3, file4, ts.tscWatch.libFile, configFile]); + return createWatchedSystem([file1, file2, file3, file4, libFile, configFile]); }, - changes: ts.emptyArray + changes: emptyArray }); } verifyFilesEmittedOnce("with --outFile and multiple declaration files in the program", /*useOutFile*/ true); @@ -92,10 +96,10 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => { /** custom config file options */ configObj?: any; /** Additional files and folders to add */ - getAdditionalFileOrFolder?: () => ts.tscWatch.File[]; + getAdditionalFileOrFolder?: () => File[]; /** initial list of files to emit if not the default list */ firstReloadFileList?: string[]; - changes: ts.tscWatch.TscWatchCompileChange[] + changes: TscWatchCompileChange[] } function verifyTscWatchEmit({ subScenario, @@ -104,43 +108,43 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => { firstReloadFileList, changes }: VerifyTscWatchEmit) { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: `emit for configured projects/${subScenario}`, commandLineArgs: ["--w", "-p", configFilePath], sys: () => { - const moduleFile1: ts.tscWatch.File = { + const moduleFile1: File = { path: moduleFile1Path, content: "export function Foo() { };", }; - const file1Consumer1: ts.tscWatch.File = { + const file1Consumer1: File = { path: file1Consumer1Path, content: `import {Foo} from "./moduleFile1"; export var y = 10;`, }; - const file1Consumer2: ts.tscWatch.File = { + const file1Consumer2: File = { path: file1Consumer2Path, content: `import {Foo} from "./moduleFile1"; let z = 10;`, }; - const moduleFile2: ts.tscWatch.File = { + const moduleFile2: File = { path: moduleFile2Path, content: `export var Foo4 = 10;`, }; - const globalFile3: ts.tscWatch.File = { + const globalFile3: File = { path: globalFilePath, content: `interface GlobalFoo { age: number }` }; - const configFile: ts.tscWatch.File = { + const configFile: File = { path: configFilePath, content: JSON.stringify(configObj || {}) }; - const additionalFiles = getAdditionalFileOrFolder?.() || ts.emptyArray; - const files = [moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, ts.tscWatch.libFile, ...additionalFiles]; - return ts.tscWatch.createWatchedSystem(firstReloadFileList ? - ts.map(firstReloadFileList, fileName => ts.find(files, file => file.path === fileName)!) : + const additionalFiles = getAdditionalFileOrFolder?.() || emptyArray; + const files = [moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile, ...additionalFiles]; + return createWatchedSystem(firstReloadFileList ? + map(firstReloadFileList, fileName => find(files, file => file.path === fileName)!) : files ); }, @@ -148,13 +152,13 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => { }); } - function modifyModuleFile1Shape(sys: ts.tscWatch.WatchedSystem) { + function modifyModuleFile1Shape(sys: WatchedSystem) { sys.writeFile(moduleFile1Path, `export var T: number;export function Foo() { };`); } - const changeModuleFile1Shape: ts.tscWatch.TscWatchCompileChange = { + const changeModuleFile1Shape: TscWatchCompileChange = { caption: "Change the content of moduleFile1 to `export var T: number;export function Foo() { };`", change: modifyModuleFile1Shape, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }; verifyTscWatchEmit({ @@ -164,7 +168,7 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => { { caption: "Change the content of moduleFile1 to `export var T: number;export function Foo() { console.log('hi'); };`", change: sys => sys.writeFile(moduleFile1Path, `export var T: number;export function Foo() { console.log('hi'); };`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); @@ -175,18 +179,18 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => { { caption: "Change file1Consumer1 content to `export let y = Foo();`", change: sys => sys.writeFile(file1Consumer1Path, `export let y = Foo();`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }, changeModuleFile1Shape, { caption: "Add the import statements back to file1Consumer1", change: sys => sys.writeFile(file1Consumer1Path, `import {Foo} from "./moduleFile1";let y = Foo();`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "Change the content of moduleFile1 to `export var T: number;export var T2: string;export function Foo() { };`", change: sys => sys.writeFile(moduleFile1Path, `export let y = Foo();`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "Multiple file edits in one go", @@ -196,7 +200,7 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => { sys.writeFile(file1Consumer1Path, `import {Foo} from "./moduleFile1";let y = Foo();`); modifyModuleFile1Shape(sys); }, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); @@ -210,7 +214,7 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => { modifyModuleFile1Shape(sys); sys.deleteFile(file1Consumer2Path); }, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); @@ -224,7 +228,7 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => { sys.writeFile("/a/b/file1Consumer3.ts", `import {Foo} from "./moduleFile1"; let y = Foo();`); modifyModuleFile1Shape(sys); }, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); @@ -237,7 +241,7 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => { { caption: "change file1 internal, and verify only file1 is affected", change: sys => sys.appendFile(moduleFile1Path, "var T1: number;"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); @@ -248,7 +252,7 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => { { caption: "change shape of global file", change: sys => sys.appendFile(globalFilePath, "var T2: string;"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); @@ -279,7 +283,7 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => { { caption: "change file1Consumer1", change: sys => sys.appendFile(file1Consumer1Path, "export var T: number;"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }, changeModuleFile1Shape, { @@ -288,7 +292,7 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => { sys.appendFile(file1Consumer1Path, "export var T2: number;"); sys.writeFile(moduleFile1Path, `export var T2: number;export function Foo() { };`); }, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); @@ -307,12 +311,12 @@ export var t1 = 10;` export var t2 = 10;` } ], - firstReloadFileList: [ts.tscWatch.libFile.path, "/a/b/file1.ts", "/a/b/file2.ts", configFilePath], + firstReloadFileList: [libFile.path, "/a/b/file1.ts", "/a/b/file2.ts", configFilePath], changes: [ { caption: "change file1", change: sys => sys.appendFile("/a/b/file1.ts", "export var t3 = 10;"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); @@ -324,12 +328,12 @@ export var t2 = 10;` content: `/// export var x = Foo();` }], - firstReloadFileList: [ts.tscWatch.libFile.path, "/a/b/referenceFile1.ts", moduleFile1Path, configFilePath], + firstReloadFileList: [libFile.path, "/a/b/referenceFile1.ts", moduleFile1Path, configFilePath], changes: [ { caption: "delete moduleFile1", change: sys => sys.deleteFile(moduleFile1Path), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); @@ -341,17 +345,17 @@ export var x = Foo();` content: `/// export var x = Foo();` }], - firstReloadFileList: [ts.tscWatch.libFile.path, "/a/b/referenceFile1.ts", configFilePath], + firstReloadFileList: [libFile.path, "/a/b/referenceFile1.ts", configFilePath], changes: [ { caption: "edit refereceFile1", change: sys => sys.appendFile("/a/b/referenceFile1.ts", "export var yy = Foo();"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "create moduleFile2", change: sys => sys.writeFile(moduleFile2Path, "export var Foo4 = 10;"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); @@ -359,17 +363,17 @@ export var x = Foo();` describe("unittests:: tsc-watch:: emit file content", () => { function verifyNewLine(subScenario: string, newLine: string) { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: `emit file content/${subScenario}`, commandLineArgs: ["--w", "/a/app.ts"], - sys: () => ts.tscWatch.createWatchedSystem( + sys: () => createWatchedSystem( [ { path: "/a/app.ts", content: ["var x = 1;", "var y = 2;"].join(newLine) }, - ts.tscWatch.libFile + libFile ], { newLine } ), @@ -377,7 +381,7 @@ describe("unittests:: tsc-watch:: emit file content", () => { { caption: "Append a line", change: sys => sys.appendFile("/a/app.ts", newLine + "var z = 3;"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ], }); @@ -385,7 +389,7 @@ describe("unittests:: tsc-watch:: emit file content", () => { verifyNewLine("handles new lines lineFeed", "\n"); verifyNewLine("handles new lines carriageReturn lineFeed", "\r\n"); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "emit file content/should emit specified file", commandLineArgs: ["-w", "-p", "/a/b/tsconfig.json"], @@ -409,62 +413,62 @@ describe("unittests:: tsc-watch:: emit file content", () => { path: "/a/b/tsconfig.json", content: "{}" }; - return ts.tscWatch.createWatchedSystem([file1, file2, file3, configFile, ts.tscWatch.libFile]); + return createWatchedSystem([file1, file2, file3, configFile, libFile]); }, changes: [ { caption: "Append content to f1", change: sys => sys.appendFile("/a/b/f1.ts", "export function foo2() { return 2; }"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "Again Append content to f1", change: sys => sys.appendFile("/a/b/f1.ts", "export function fooN() { return 2; }"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ], }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "emit file content/elides const enums correctly in incremental compilation", commandLineArgs: ["-w", "/user/someone/projects/myproject/file3.ts"], sys: () => { const currentDirectory = "/user/someone/projects/myproject"; - const file1: ts.tscWatch.File = { + const file1: File = { path: `${currentDirectory}/file1.ts`, content: "export const enum E1 { V = 1 }" }; - const file2: ts.tscWatch.File = { + const file2: File = { path: `${currentDirectory}/file2.ts`, content: `import { E1 } from "./file1"; export const enum E2 { V = E1.V }` }; - const file3: ts.tscWatch.File = { + const file3: File = { path: `${currentDirectory}/file3.ts`, content: `import { E2 } from "./file2"; const v: E2 = E2.V;` }; - return ts.tscWatch.createWatchedSystem([file1, file2, file3, ts.tscWatch.libFile]); + return createWatchedSystem([file1, file2, file3, libFile]); }, changes: [ { caption: "Append content to file3", change: sys => sys.appendFile("/user/someone/projects/myproject/file3.ts", "function foo2() { return 2; }"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ], }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "emit file content/file is deleted and created as part of change", commandLineArgs: ["-w"], sys: () => { const projectLocation = "/home/username/project"; - const file: ts.tscWatch.File = { + const file: File = { path: `${projectLocation}/app/file.ts`, content: "var a = 10;" }; - const configFile: ts.tscWatch.File = { + const configFile: File = { path: `${projectLocation}/tsconfig.json`, content: JSON.stringify({ include: [ @@ -472,26 +476,26 @@ describe("unittests:: tsc-watch:: emit file content", () => { ] }) }; - const files = [file, configFile, ts.tscWatch.libFile]; - return ts.tscWatch.createWatchedSystem(files, { currentDirectory: projectLocation, useCaseSensitiveFileNames: true }); + const files = [file, configFile, libFile]; + return createWatchedSystem(files, { currentDirectory: projectLocation, useCaseSensitiveFileNames: true }); }, changes: [ { caption: "file is deleted and then created to modify content", change: sys => sys.appendFile("/home/username/project/app/file.ts", "\nvar b = 10;", { invokeFileDeleteCreateAsPartInsteadOfChange: true }), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); }); describe("unittests:: tsc-watch:: emit with when module emit is specified as node", () => { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "when module emit is specified as node/when instead of filechanged recursive directory watcher is invoked", commandLineArgs: ["--w", "--p", "/a/rootFolder/project/tsconfig.json"], sys: () => { - const configFile: ts.tscWatch.File = { + const configFile: File = { path: "/a/rootFolder/project/tsconfig.json", content: JSON.stringify({ compilerOptions: { @@ -504,15 +508,15 @@ describe("unittests:: tsc-watch:: emit with when module emit is specified as nod ], }) }; - const file1: ts.tscWatch.File = { + const file1: File = { path: "/a/rootFolder/project/Scripts/TypeScript.ts", content: "var z = 10;" }; - const file2: ts.tscWatch.File = { + const file2: File = { path: "/a/rootFolder/project/Scripts/Javascript.js", content: "var zz = 10;" }; - return ts.tscWatch.createWatchedSystem([configFile, file1, file2, ts.tscWatch.libFile]); + return createWatchedSystem([configFile, file1, file2, libFile]); }, changes: [ { @@ -522,7 +526,7 @@ describe("unittests:: tsc-watch:: emit with when module emit is specified as nod "var zz30 = 100;", { invokeDirectoryWatcherInsteadOfFileChanged: true }, ), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, } ], }); diff --git a/src/testRunner/unittests/tscWatch/emitAndErrorUpdates.ts b/src/testRunner/unittests/tscWatch/emitAndErrorUpdates.ts index 8ee0afb8eea87..77efcfa5db614 100644 --- a/src/testRunner/unittests/tscWatch/emitAndErrorUpdates.ts +++ b/src/testRunner/unittests/tscWatch/emitAndErrorUpdates.ts @@ -1,12 +1,18 @@ -import * as ts from "../../_namespaces/ts"; +import { CompilerOptions } from "../../../compiler/types"; +import { getTsBuildProjectFile, tsbuildProjectsLocation } from "../../../harness/virtualFileSystemWithWatch"; +import { libContent } from "../tsbuild/helpers"; +import { + checkSingleTimeoutQueueLengthAndRun, createWatchedSystem, File, libFile, projectRoot, runQueuedTimeoutCallbacks, + TscWatchCompileChange, verifyTscWatch, +} from "./helpers"; describe("unittests:: tsc-watch:: Emit times and Error updates in builder after program changes", () => { - const config: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: `{}` }; interface VerifyEmitAndErrorUpdatesWorker extends VerifyEmitAndErrorUpdates { - configFile: () => ts.tscWatch.File; + configFile: () => File; } function verifyEmitAndErrorUpdatesWorker({ subScenario, @@ -17,31 +23,31 @@ describe("unittests:: tsc-watch:: Emit times and Error updates in builder after changes, baselineIncremental }: VerifyEmitAndErrorUpdatesWorker) { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "emitAndErrorUpdates", subScenario, commandLineArgs: ["--w"], - sys: () => ts.tscWatch.createWatchedSystem( - [...files(), configFile(), lib?.() || ts.tscWatch.libFile], - { currentDirectory: currentDirectory || ts.tscWatch.projectRoot } + sys: () => createWatchedSystem( + [...files(), configFile(), lib?.() || libFile], + { currentDirectory: currentDirectory || projectRoot } ), changes, baselineIncremental }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "emitAndErrorUpdates", subScenario: `incremental/${subScenario}`, commandLineArgs: ["--w", "--i"], - sys: () => ts.tscWatch.createWatchedSystem( - [...files(), configFile(), lib?.() || ts.tscWatch.libFile], - { currentDirectory: currentDirectory || ts.tscWatch.projectRoot } + sys: () => createWatchedSystem( + [...files(), configFile(), lib?.() || libFile], + { currentDirectory: currentDirectory || projectRoot } ), changes, baselineIncremental }); } - function changeCompilerOptions(input: VerifyEmitAndErrorUpdates, additionalOptions: ts.CompilerOptions): ts.tscWatch.File { + function changeCompilerOptions(input: VerifyEmitAndErrorUpdates, additionalOptions: CompilerOptions): File { const configFile = input.configFile?.() || config; const content = JSON.parse(configFile.content); content.compilerOptions = { ...content.compilerOptions, ...additionalOptions }; @@ -50,11 +56,11 @@ describe("unittests:: tsc-watch:: Emit times and Error updates in builder after interface VerifyEmitAndErrorUpdates { subScenario: string - files: () => ts.tscWatch.File[]; + files: () => File[]; currentDirectory?: string; - lib?: () => ts.tscWatch.File; - changes: ts.tscWatch.TscWatchCompileChange[]; - configFile?: () => ts.tscWatch.File; + lib?: () => File; + changes: TscWatchCompileChange[]; + configFile?: () => File; baselineIncremental?: boolean } function verifyEmitAndErrorUpdates(input: VerifyEmitAndErrorUpdates) { @@ -96,15 +102,15 @@ describe("unittests:: tsc-watch:: Emit times and Error updates in builder after } describe("deep import changes", () => { - const aFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const aFile: File = { + path: `${projectRoot}/a.ts`, content: `import {B} from './b'; declare var console: any; let b = new B(); console.log(b.c.d);` }; - function verifyDeepImportChange(subScenario: string, bFile: ts.tscWatch.File, cFile: ts.tscWatch.File) { + function verifyDeepImportChange(subScenario: string, bFile: File, cFile: File) { verifyEmitAndErrorUpdates({ subScenario: `deepImportChanges/${subScenario}`, files: () => [aFile, bFile, cFile], @@ -112,32 +118,32 @@ console.log(b.c.d);` { caption: "Rename property d to d2 of class C to initialize signatures", change: sys => sys.writeFile(cFile.path, cFile.content.replace("d", "d2")), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }, { caption: "Rename property d2 to d of class C to revert back to original text", change: sys => sys.writeFile(cFile.path, cFile.content.replace("d2", "d")), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }, { caption: "Rename property d to d2 of class C", change: sys => sys.writeFile(cFile.path, cFile.content.replace("d", "d2")), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, } ], }); } describe("updates errors when deep import file changes", () => { - const bFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/b.ts`, + const bFile: File = { + path: `${projectRoot}/b.ts`, content: `import {C} from './c'; export class B { c = new C(); }` }; - const cFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/c.ts`, + const cFile: File = { + path: `${projectRoot}/c.ts`, content: `export class C { d = 1; @@ -150,16 +156,16 @@ export class B ); }); describe("updates errors when deep import through declaration file changes", () => { - const bFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/b.d.ts`, + const bFile: File = { + path: `${projectRoot}/b.d.ts`, content: `import {C} from './c'; export class B { c: C; }` }; - const cFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/c.d.ts`, + const cFile: File = { + path: `${projectRoot}/c.d.ts`, content: `export class C { d: number; @@ -174,8 +180,8 @@ export class B }); describe("updates errors in file not exporting a deep multilevel import that changes", () => { - const aFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const aFile: File = { + path: `${projectRoot}/a.ts`, content: `export interface Point { name: string; c: Coords; @@ -185,14 +191,14 @@ export interface Coords { y: number; }` }; - const bFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/b.ts`, + const bFile: File = { + path: `${projectRoot}/b.ts`, content: `import { Point } from "./a"; export interface PointWrapper extends Point { }` }; - const cFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/c.ts`, + const cFile: File = { + path: `${projectRoot}/c.ts`, content: `import { PointWrapper } from "./b"; export function getPoint(): PointWrapper { return { @@ -204,13 +210,13 @@ export function getPoint(): PointWrapper { } };` }; - const dFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/d.ts`, + const dFile: File = { + path: `${projectRoot}/d.ts`, content: `import { getPoint } from "./c"; getPoint().c.x;` }; - const eFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/e.ts`, + const eFile: File = { + path: `${projectRoot}/e.ts`, content: `import "./d";` }; verifyEmitAndErrorUpdates({ @@ -220,31 +226,31 @@ getPoint().c.x;` { caption: "Rename property x2 to x of interface Coords to initialize signatures", change: sys => sys.writeFile(aFile.path, aFile.content.replace("x2", "x")), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }, { caption: "Rename property x to x2 of interface Coords to revert back to original text", change: sys => sys.writeFile(aFile.path, aFile.content.replace("x: number", "x2: number")), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }, { caption: "Rename property x2 to x of interface Coords", change: sys => sys.writeFile(aFile.path, aFile.content.replace("x2", "x")), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }, ] }); }); describe("updates errors when file transitively exported file changes", () => { - const config: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ files: ["app.ts"], compilerOptions: { baseUrl: "." } }) }; - const app: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/app.ts`, + const app: File = { + path: `${projectRoot}/app.ts`, content: `import { Data } from "lib2/public"; export class App { public constructor() { @@ -252,12 +258,12 @@ export class App { } }` }; - const lib2Public: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/lib2/public.ts`, + const lib2Public: File = { + path: `${projectRoot}/lib2/public.ts`, content: `export * from "./data";` }; - const lib2Data: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/lib2/data.ts`, + const lib2Data: File = { + path: `${projectRoot}/lib2/data.ts`, content: `import { ITest } from "lib1/public"; export class Data { public test() { @@ -268,22 +274,22 @@ export class Data { } }` }; - const lib1Public: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/lib1/public.ts`, + const lib1Public: File = { + path: `${projectRoot}/lib1/public.ts`, content: `export * from "./tools/public";` }; - const lib1ToolsPublic: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/lib1/tools/public.ts`, + const lib1ToolsPublic: File = { + path: `${projectRoot}/lib1/tools/public.ts`, content: `export * from "./tools.interface";` }; - const lib1ToolsInterface: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/lib1/tools/tools.interface.ts`, + const lib1ToolsInterface: File = { + path: `${projectRoot}/lib1/tools/tools.interface.ts`, content: `export interface ITest { title: string; }` }; - function verifyTransitiveExports(subScenario: string, files: readonly ts.tscWatch.File[]) { + function verifyTransitiveExports(subScenario: string, files: readonly File[]) { verifyEmitAndErrorUpdates({ subScenario: `transitive exports/${subScenario}`, files: () => [lib1ToolsInterface, lib1ToolsPublic, app, lib2Public, lib1Public, ...files], @@ -292,17 +298,17 @@ export class Data { { caption: "Rename property title to title2 of interface ITest to initialize signatures", change: sys => sys.writeFile(lib1ToolsInterface.path, lib1ToolsInterface.content.replace("title", "title2")), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }, { caption: "Rename property title2 to title of interface ITest to revert back to original text", change: sys => sys.writeFile(lib1ToolsInterface.path, lib1ToolsInterface.content.replace("title2", "title")), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }, { caption: "Rename property title to title2 of interface ITest", change: sys => sys.writeFile(lib1ToolsInterface.path, lib1ToolsInterface.content.replace("title", "title2")), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, } ] }); @@ -314,8 +320,8 @@ export class Data { ); }); describe("when there are circular import and exports", () => { - const lib2Data: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/lib2/data.ts`, + const lib2Data: File = { + path: `${projectRoot}/lib2/data.ts`, content: `import { ITest } from "lib1/public"; import { Data2 } from "./data2"; export class Data { public dat?: Data2; public test() { @@ -326,8 +332,8 @@ export class Data { } }` }; - const lib2Data2: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/lib2/data2.ts`, + const lib2Data2: File = { + path: `${projectRoot}/lib2/data2.ts`, content: `import { Data } from "./data"; export class Data2 { public dat?: Data; @@ -341,27 +347,27 @@ export class Data2 { }); describe("with noEmitOnError", () => { - function change(caption: string, content: string): ts.tscWatch.TscWatchCompileChange { + function change(caption: string, content: string): TscWatchCompileChange { return { caption, - change: sys => sys.writeFile(`${ts.TestFSWithWatch.tsbuildProjectsLocation}/noEmitOnError/src/main.ts`, content), + change: sys => sys.writeFile(`${tsbuildProjectsLocation}/noEmitOnError/src/main.ts`, content), // build project - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + timeouts: checkSingleTimeoutQueueLengthAndRun }; } - const noChange: ts.tscWatch.TscWatchCompileChange = { + const noChange: TscWatchCompileChange = { caption: "No change", - change: sys => sys.writeFile(`${ts.TestFSWithWatch.tsbuildProjectsLocation}/noEmitOnError/src/main.ts`, sys.readFile(`${ts.TestFSWithWatch.tsbuildProjectsLocation}/noEmitOnError/src/main.ts`)!), + change: sys => sys.writeFile(`${tsbuildProjectsLocation}/noEmitOnError/src/main.ts`, sys.readFile(`${tsbuildProjectsLocation}/noEmitOnError/src/main.ts`)!), // build project - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }; verifyEmitAndErrorUpdates({ subScenario: "with noEmitOnError", - currentDirectory: `${ts.TestFSWithWatch.tsbuildProjectsLocation}/noEmitOnError`, + currentDirectory: `${tsbuildProjectsLocation}/noEmitOnError`, files: () => ["shared/types/db.ts", "src/main.ts", "src/other.ts"] - .map(f => ts.TestFSWithWatch.getTsBuildProjectFile("noEmitOnError", f)), - lib: () => ({ path: ts.tscWatch.libFile.path, content: ts.libContent }), - configFile: () => ts.TestFSWithWatch.getTsBuildProjectFile("noEmitOnError", "tsconfig.json"), + .map(f => getTsBuildProjectFile("noEmitOnError", f)), + lib: () => ({ path: libFile.path, content: libContent }), + configFile: () => getTsBuildProjectFile("noEmitOnError", "tsconfig.json"), changes: [ noChange, change("Fix Syntax error", `import { A } from "../shared/types/db"; diff --git a/src/testRunner/unittests/tscWatch/forceConsistentCasingInFileNames.ts b/src/testRunner/unittests/tscWatch/forceConsistentCasingInFileNames.ts index 285264ebf6d72..909c595f5c7dc 100644 --- a/src/testRunner/unittests/tscWatch/forceConsistentCasingInFileNames.ts +++ b/src/testRunner/unittests/tscWatch/forceConsistentCasingInFileNames.ts @@ -1,27 +1,31 @@ -import * as ts from "../../_namespaces/ts"; +import { emptyArray } from "../../../compiler/core"; +import { + createWatchedSystem, File, libFile, projectRoot, runQueuedTimeoutCallbacks, SymLink, TscWatchCompileChange, + verifyTscWatch, +} from "./helpers"; describe("unittests:: tsc-watch:: forceConsistentCasingInFileNames", () => { - const loggerFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/logger.ts`, + const loggerFile: File = { + path: `${projectRoot}/logger.ts`, content: `export class logger { }` }; - const anotherFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/another.ts`, + const anotherFile: File = { + path: `${projectRoot}/another.ts`, content: `import { logger } from "./logger"; new logger();` }; - const tsconfig: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { forceConsistentCasingInFileNames: true } }) }; - function verifyConsistentFileNames({ subScenario, changes }: { subScenario: string; changes: ts.tscWatch.TscWatchCompileChange[]; }) { - ts.tscWatch.verifyTscWatch({ + function verifyConsistentFileNames({ subScenario, changes }: { subScenario: string; changes: TscWatchCompileChange[]; }) { + verifyTscWatch({ scenario: "forceConsistentCasingInFileNames", subScenario, commandLineArgs: ["--w", "--p", tsconfig.path], - sys: () => ts.tscWatch.createWatchedSystem([loggerFile, anotherFile, tsconfig, ts.tscWatch.libFile, tsconfig]), + sys: () => createWatchedSystem([loggerFile, anotherFile, tsconfig, libFile, tsconfig]), changes }); } @@ -32,7 +36,7 @@ describe("unittests:: tsc-watch:: forceConsistentCasingInFileNames", () => { { caption: "Change module name from logger to Logger", change: sys => sys.writeFile(anotherFile.path, anotherFile.content.replace("./logger", "./Logger")), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, } ] }); @@ -42,53 +46,53 @@ describe("unittests:: tsc-watch:: forceConsistentCasingInFileNames", () => { changes: [ { caption: "Change name of file from logger to Logger", - change: sys => sys.renameFile(loggerFile.path, `${ts.tscWatch.projectRoot}/Logger.ts`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => sys.renameFile(loggerFile.path, `${projectRoot}/Logger.ts`), + timeouts: runQueuedTimeoutCallbacks, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "forceConsistentCasingInFileNames", subScenario: "when relative information file location changes", commandLineArgs: ["--w", "--p", ".", "--explainFiles"], sys: () => { - const moduleA: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/moduleA.ts`, + const moduleA: File = { + path: `${projectRoot}/moduleA.ts`, content: `import a = require("./ModuleC")` }; - const moduleB: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/moduleB.ts`, + const moduleB: File = { + path: `${projectRoot}/moduleB.ts`, content: `import a = require("./moduleC")` }; - const moduleC: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/moduleC.ts`, + const moduleC: File = { + path: `${projectRoot}/moduleC.ts`, content: `export const x = 10;` }; - const tsconfig: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { forceConsistentCasingInFileNames: true } }) }; - return ts.tscWatch.createWatchedSystem([moduleA, moduleB, moduleC, ts.tscWatch.libFile, tsconfig], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([moduleA, moduleB, moduleC, libFile, tsconfig], { currentDirectory: projectRoot }); }, changes: [ { caption: "Prepend a line to moduleA", - change: sys => sys.prependFile(`${ts.tscWatch.projectRoot}/moduleA.ts`, `// some comment + change: sys => sys.prependFile(`${projectRoot}/moduleA.ts`, `// some comment `), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, } ], }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "forceConsistentCasingInFileNames", subScenario: "jsxImportSource option changed", commandLineArgs: ["--w", "--p", ".", "--explainFiles"], - sys: () => ts.tscWatch.createWatchedSystem([ - ts.tscWatch.libFile, + sys: () => createWatchedSystem([ + libFile, { - path: `${ts.tscWatch.projectRoot}/node_modules/react/Jsx-runtime/index.d.ts`, + path: `${projectRoot}/node_modules/react/Jsx-runtime/index.d.ts`, content: `export namespace JSX { interface Element {} interface IntrinsicElements { @@ -103,38 +107,38 @@ export const Fragment: unique symbol; `, }, { - path: `${ts.tscWatch.projectRoot}/node_modules/react/package.json`, + path: `${projectRoot}/node_modules/react/package.json`, content: JSON.stringify({ name: "react", version: "0.0.1" }) }, { - path: `${ts.tscWatch.projectRoot}/index.tsx`, + path: `${projectRoot}/index.tsx`, content: `export const App = () =>
;` }, { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { jsx: "react-jsx", jsxImportSource: "react", forceConsistentCasingInFileNames: true }, files: ["node_modules/react/jsx-Runtime/index.d.ts", "index.tsx"] // NB: casing does not match disk }) } - ], { currentDirectory: ts.tscWatch.projectRoot }), - changes: ts.emptyArray, + ], { currentDirectory: projectRoot }), + changes: emptyArray, }); function verifyWindowsStyleRoot(subScenario: string, windowsStyleRoot: string, projectRootRelative: string) { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "forceConsistentCasingInFileNames", subScenario, commandLineArgs: ["--w", "--p", `${windowsStyleRoot}/${projectRootRelative}`, "--explainFiles"], sys: () => { - const moduleA: ts.tscWatch.File = { + const moduleA: File = { path: `${windowsStyleRoot}/${projectRootRelative}/a.ts`, content: ` export const a = 1; export const b = 2; ` }; - const moduleB: ts.tscWatch.File = { + const moduleB: File = { path: `${windowsStyleRoot}/${projectRootRelative}/b.ts`, content: ` import { a } from "${windowsStyleRoot.toLocaleUpperCase()}/${projectRootRelative}/a" @@ -143,18 +147,18 @@ import { b } from "${windowsStyleRoot.toLocaleLowerCase()}/${projectRootRelative a;b; ` }; - const tsconfig: ts.tscWatch.File = { + const tsconfig: File = { path: `${windowsStyleRoot}/${projectRootRelative}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { forceConsistentCasingInFileNames: true } }) }; - return ts.tscWatch.createWatchedSystem([moduleA, moduleB, ts.tscWatch.libFile, tsconfig], { windowsStyleRoot, useCaseSensitiveFileNames: false }); + return createWatchedSystem([moduleA, moduleB, libFile, tsconfig], { windowsStyleRoot, useCaseSensitiveFileNames: false }); }, changes: [ { caption: "Prepend a line to moduleA", change: sys => sys.prependFile(`${windowsStyleRoot}/${projectRootRelative}/a.ts`, `// some comment `), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, } ], }); @@ -164,12 +168,12 @@ a;b; verifyWindowsStyleRoot("when Windows-style drive root is uppercase", "C:/", "project"); function verifyFileSymlink(subScenario: string, diskPath: string, targetPath: string, importedPath: string) { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "forceConsistentCasingInFileNames", subScenario, commandLineArgs: ["--w", "--p", ".", "--explainFiles"], sys: () => { - const moduleA: ts.tscWatch.File = { + const moduleA: File = { path: diskPath, content: ` @@ -177,12 +181,12 @@ export const a = 1; export const b = 2; ` }; - const symlinkA: ts.tscWatch.SymLink = { - path: `${ts.tscWatch.projectRoot}/link.ts`, + const symlinkA: SymLink = { + path: `${projectRoot}/link.ts`, symLink: targetPath, }; - const moduleB: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/b.ts`, + const moduleB: File = { + path: `${projectRoot}/b.ts`, content: ` import { a } from "${importedPath}"; import { b } from "./link"; @@ -190,36 +194,36 @@ import { b } from "./link"; a;b; ` }; - const tsconfig: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { forceConsistentCasingInFileNames: true } }) }; - return ts.tscWatch.createWatchedSystem([moduleA, symlinkA, moduleB, ts.tscWatch.libFile, tsconfig], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([moduleA, symlinkA, moduleB, libFile, tsconfig], { currentDirectory: projectRoot }); }, changes: [ { caption: "Prepend a line to moduleA", change: sys => sys.prependFile(diskPath, `// some comment `), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, } ], }); } - verifyFileSymlink("when both file symlink target and import match disk", `${ts.tscWatch.projectRoot}/XY.ts`, `${ts.tscWatch.projectRoot}/XY.ts`, `./XY`); - verifyFileSymlink("when file symlink target matches disk but import does not", `${ts.tscWatch.projectRoot}/XY.ts`, `${ts.tscWatch.projectRoot}/Xy.ts`, `./XY`); - verifyFileSymlink("when import matches disk but file symlink target does not", `${ts.tscWatch.projectRoot}/XY.ts`, `${ts.tscWatch.projectRoot}/XY.ts`, `./Xy`); - verifyFileSymlink("when import and file symlink target agree but do not match disk", `${ts.tscWatch.projectRoot}/XY.ts`, `${ts.tscWatch.projectRoot}/Xy.ts`, `./Xy`); - verifyFileSymlink("when import, file symlink target, and disk are all different", `${ts.tscWatch.projectRoot}/XY.ts`, `${ts.tscWatch.projectRoot}/Xy.ts`, `./yX`); + verifyFileSymlink("when both file symlink target and import match disk", `${projectRoot}/XY.ts`, `${projectRoot}/XY.ts`, `./XY`); + verifyFileSymlink("when file symlink target matches disk but import does not", `${projectRoot}/XY.ts`, `${projectRoot}/Xy.ts`, `./XY`); + verifyFileSymlink("when import matches disk but file symlink target does not", `${projectRoot}/XY.ts`, `${projectRoot}/XY.ts`, `./Xy`); + verifyFileSymlink("when import and file symlink target agree but do not match disk", `${projectRoot}/XY.ts`, `${projectRoot}/Xy.ts`, `./Xy`); + verifyFileSymlink("when import, file symlink target, and disk are all different", `${projectRoot}/XY.ts`, `${projectRoot}/Xy.ts`, `./yX`); function verifyDirSymlink(subScenario: string, diskPath: string, targetPath: string, importedPath: string) { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "forceConsistentCasingInFileNames", subScenario, commandLineArgs: ["--w", "--p", ".", "--explainFiles"], sys: () => { - const moduleA: ts.tscWatch.File = { + const moduleA: File = { path: `${diskPath}/a.ts`, content: ` @@ -227,12 +231,12 @@ export const a = 1; export const b = 2; ` }; - const symlinkA: ts.tscWatch.SymLink = { - path: `${ts.tscWatch.projectRoot}/link`, + const symlinkA: SymLink = { + path: `${projectRoot}/link`, symLink: targetPath, }; - const moduleB: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/b.ts`, + const moduleB: File = { + path: `${projectRoot}/b.ts`, content: ` import { a } from "${importedPath}/a"; import { b } from "./link/a"; @@ -240,29 +244,29 @@ import { b } from "./link/a"; a;b; ` }; - const tsconfig: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, // Use outFile because otherwise the real and linked files will have the same output path content: JSON.stringify({ compilerOptions: { forceConsistentCasingInFileNames: true, outFile: "out.js", module: "system" } }) }; - return ts.tscWatch.createWatchedSystem([moduleA, symlinkA, moduleB, ts.tscWatch.libFile, tsconfig], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([moduleA, symlinkA, moduleB, libFile, tsconfig], { currentDirectory: projectRoot }); }, changes: [ { caption: "Prepend a line to moduleA", change: sys => sys.prependFile(`${diskPath}/a.ts`, `// some comment `), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, } ], }); } - verifyDirSymlink("when both directory symlink target and import match disk", `${ts.tscWatch.projectRoot}/XY`, `${ts.tscWatch.projectRoot}/XY`, `./XY`); - verifyDirSymlink("when directory symlink target matches disk but import does not", `${ts.tscWatch.projectRoot}/XY`, `${ts.tscWatch.projectRoot}/Xy`, `./XY`); - verifyDirSymlink("when import matches disk but directory symlink target does not", `${ts.tscWatch.projectRoot}/XY`, `${ts.tscWatch.projectRoot}/XY`, `./Xy`); - verifyDirSymlink("when import and directory symlink target agree but do not match disk", `${ts.tscWatch.projectRoot}/XY`, `${ts.tscWatch.projectRoot}/Xy`, `./Xy`); - verifyDirSymlink("when import, directory symlink target, and disk are all different", `${ts.tscWatch.projectRoot}/XY`, `${ts.tscWatch.projectRoot}/Xy`, `./yX`); + verifyDirSymlink("when both directory symlink target and import match disk", `${projectRoot}/XY`, `${projectRoot}/XY`, `./XY`); + verifyDirSymlink("when directory symlink target matches disk but import does not", `${projectRoot}/XY`, `${projectRoot}/Xy`, `./XY`); + verifyDirSymlink("when import matches disk but directory symlink target does not", `${projectRoot}/XY`, `${projectRoot}/XY`, `./Xy`); + verifyDirSymlink("when import and directory symlink target agree but do not match disk", `${projectRoot}/XY`, `${projectRoot}/Xy`, `./Xy`); + verifyDirSymlink("when import, directory symlink target, and disk are all different", `${projectRoot}/XY`, `${projectRoot}/Xy`, `./yX`); }); export { }; diff --git a/src/testRunner/unittests/tscWatch/helpers.ts b/src/testRunner/unittests/tscWatch/helpers.ts index 7430651dc1206..bc4d380f0256b 100644 --- a/src/testRunner/unittests/tscWatch/helpers.ts +++ b/src/testRunner/unittests/tscWatch/helpers.ts @@ -1,21 +1,54 @@ -import * as fakes from "../../_namespaces/fakes"; -import * as Harness from "../../_namespaces/Harness"; +import { BuilderProgramState } from "../../../compiler/builder"; +import { BuilderProgram, EmitAndSemanticDiagnosticsBuilderProgram } from "../../../compiler/builderPublic"; +import { emptyArray, forEach, noop } from "../../../compiler/core"; +import { Debug } from "../../../compiler/debug"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { toPath } from "../../../compiler/path"; +import { + createBuilderStatusReporter, createSolutionBuilderWithWatchHost, SolutionBuilder, +} from "../../../compiler/tsbuildPublic"; +import { + CharacterCodes, Diagnostic, DiagnosticMessage, DiagnosticMessageChain, ExitStatus, Path, Program, SourceFile, +} from "../../../compiler/types"; +import { formatStringFromArgs, getLocaleSpecificMessage } from "../../../compiler/utilities"; +import { + createDiagnosticReporter, createWatchCompilerHostOfConfigFile, CreateWatchCompilerHostOfConfigFileInput, + createWatchCompilerHostOfFilesAndCompilerOptions, CreateWatchCompilerHostOfFilesAndCompilerOptionsInput, + createWatchStatusReporter, +} from "../../../compiler/watch"; +import { WatchCompilerHost, WatchOfConfigFile, WatchOfFilesAndCompilerOptions } from "../../../compiler/watchPublic"; +import { + executeCommandLine, ExecuteCommandLineCallbacks, isBuild, +} from "../../../executeCommandLine/executeCommandLine"; +import { TestFSWithWatch } from "../../../harness/_namespaces/ts"; +import { patchHostForBuildInfoReadWrite } from "../../../harness/fakesHosts"; +import { Baseline } from "../../../harness/harnessIO"; +import { + changeToHostTrackingWrittenFiles, checkArray, checkOutputContains, checkOutputDoesNotContain, + checkWatchedDirectories, checkWatchedDirectoriesDetailed, checkWatchedFiles, checkWatchedFilesDetailed, + createWatchedSystem, FileOrFolderOrSymLink, libFile, TestServerHost as WatchedSystem, + TestServerHostCreationParameters, TestServerHostTrackingWrittenFiles, +} from "../../../harness/virtualFileSystemWithWatch"; import * as ts from "../../_namespaces/ts"; +import { generateSourceMapBaselineFiles } from "../tsbuild/helpers"; +import { + commandLineCallbacks, CommandLineCallbacks, CommandLineProgram, createSolutionBuilderHostForBaseline, +} from "../tsc/helpers"; export const projects = `/user/username/projects`; export const projectRoot = `${projects}/myproject`; -export import WatchedSystem = ts.TestFSWithWatch.TestServerHost; -export type File = ts.TestFSWithWatch.File; -export type SymLink = ts.TestFSWithWatch.SymLink; -export import libFile = ts.TestFSWithWatch.libFile; -export import createWatchedSystem = ts.TestFSWithWatch.createWatchedSystem; -export import checkArray = ts.TestFSWithWatch.checkArray; -export import checkWatchedFiles = ts.TestFSWithWatch.checkWatchedFiles; -export import checkWatchedFilesDetailed = ts.TestFSWithWatch.checkWatchedFilesDetailed; -export import checkWatchedDirectories = ts.TestFSWithWatch.checkWatchedDirectories; -export import checkWatchedDirectoriesDetailed = ts.TestFSWithWatch.checkWatchedDirectoriesDetailed; -export import checkOutputContains = ts.TestFSWithWatch.checkOutputContains; -export import checkOutputDoesNotContain = ts.TestFSWithWatch.checkOutputDoesNotContain; +export { WatchedSystem }; +export type File = TestFSWithWatch.File; +export type SymLink = TestFSWithWatch.SymLink; +export { libFile }; +export { createWatchedSystem }; +export { checkArray }; +export { checkWatchedFiles }; +export { checkWatchedFilesDetailed }; +export { checkWatchedDirectories }; +export { checkWatchedDirectoriesDetailed }; +export { checkOutputContains }; +export { checkOutputDoesNotContain }; export const commonFile1: File = { path: "/a/b/commonFile1.ts", @@ -26,14 +59,14 @@ export const commonFile2: File = { content: "let y = 1" }; -export function checkProgramActualFiles(program: ts.Program, expectedFiles: readonly string[]) { +export function checkProgramActualFiles(program: Program, expectedFiles: readonly string[]) { checkArray(`Program actual files`, program.getSourceFiles().map(file => file.fileName), expectedFiles); } -export function getDiagnosticMessageChain(message: ts.DiagnosticMessage, args?: (string | number)[], next?: ts.DiagnosticMessageChain[]): ts.DiagnosticMessageChain { - let text = ts.getLocaleSpecificMessage(message); +export function getDiagnosticMessageChain(message: DiagnosticMessage, args?: (string | number)[], next?: DiagnosticMessageChain[]): DiagnosticMessageChain { + let text = getLocaleSpecificMessage(message); if (args?.length) { - text = ts.formatStringFromArgs(text, args); + text = formatStringFromArgs(text, args); } return { messageText: text, @@ -43,11 +76,11 @@ export function getDiagnosticMessageChain(message: ts.DiagnosticMessage, args?: }; } -function isDiagnosticMessageChain(message: ts.DiagnosticMessage | ts.DiagnosticMessageChain): message is ts.DiagnosticMessageChain { - return !!(message as ts.DiagnosticMessageChain).messageText; +function isDiagnosticMessageChain(message: DiagnosticMessage | DiagnosticMessageChain): message is DiagnosticMessageChain { + return !!(message as DiagnosticMessageChain).messageText; } -export function getDiagnosticOfFileFrom(file: ts.SourceFile | undefined, start: number | undefined, length: number | undefined, message: ts.DiagnosticMessage | ts.DiagnosticMessageChain, ...args: (string | number)[]): ts.Diagnostic { +export function getDiagnosticOfFileFrom(file: SourceFile | undefined, start: number | undefined, length: number | undefined, message: DiagnosticMessage | DiagnosticMessageChain, ...args: (string | number)[]): Diagnostic { return { file, start, @@ -61,32 +94,32 @@ export function getDiagnosticOfFileFrom(file: ts.SourceFile | undefined, start: }; } -export function getDiagnosticWithoutFile(message: ts.DiagnosticMessage | ts.DiagnosticMessageChain, ...args: (string | number)[]): ts.Diagnostic { +export function getDiagnosticWithoutFile(message: DiagnosticMessage | DiagnosticMessageChain, ...args: (string | number)[]): Diagnostic { return getDiagnosticOfFileFrom(/*file*/ undefined, /*start*/ undefined, /*length*/ undefined, message, ...args); } -export function getDiagnosticOfFile(file: ts.SourceFile, start: number, length: number, message: ts.DiagnosticMessage | ts.DiagnosticMessageChain, ...args: (string | number)[]): ts.Diagnostic { +export function getDiagnosticOfFile(file: SourceFile, start: number, length: number, message: DiagnosticMessage | DiagnosticMessageChain, ...args: (string | number)[]): Diagnostic { return getDiagnosticOfFileFrom(file, start, length, message, ...args); } -export function getDiagnosticOfFileFromProgram(program: ts.Program, filePath: string, start: number, length: number, message: ts.DiagnosticMessage | ts.DiagnosticMessageChain, ...args: (string | number)[]): ts.Diagnostic { - return getDiagnosticOfFileFrom(program.getSourceFileByPath(ts.toPath(filePath, program.getCurrentDirectory(), s => s.toLowerCase())), +export function getDiagnosticOfFileFromProgram(program: Program, filePath: string, start: number, length: number, message: DiagnosticMessage | DiagnosticMessageChain, ...args: (string | number)[]): Diagnostic { + return getDiagnosticOfFileFrom(program.getSourceFileByPath(toPath(filePath, program.getCurrentDirectory(), s => s.toLowerCase())), start, length, message, ...args); } -export function getUnknownCompilerOption(program: ts.Program, configFile: File, option: string) { +export function getUnknownCompilerOption(program: Program, configFile: File, option: string) { const quotedOption = `"${option}"`; - return getDiagnosticOfFile(program.getCompilerOptions().configFile!, configFile.content.indexOf(quotedOption), quotedOption.length, ts.Diagnostics.Unknown_compiler_option_0, option); + return getDiagnosticOfFile(program.getCompilerOptions().configFile!, configFile.content.indexOf(quotedOption), quotedOption.length, Diagnostics.Unknown_compiler_option_0, option); } -export function getUnknownDidYouMeanCompilerOption(program: ts.Program, configFile: File, option: string, didYouMean: string) { +export function getUnknownDidYouMeanCompilerOption(program: Program, configFile: File, option: string, didYouMean: string) { const quotedOption = `"${option}"`; - return getDiagnosticOfFile(program.getCompilerOptions().configFile!, configFile.content.indexOf(quotedOption), quotedOption.length, ts.Diagnostics.Unknown_compiler_option_0_Did_you_mean_1, option, didYouMean); + return getDiagnosticOfFile(program.getCompilerOptions().configFile!, configFile.content.indexOf(quotedOption), quotedOption.length, Diagnostics.Unknown_compiler_option_0_Did_you_mean_1, option, didYouMean); } -export function getDiagnosticModuleNotFoundOfFile(program: ts.Program, file: File, moduleName: string) { +export function getDiagnosticModuleNotFoundOfFile(program: Program, file: File, moduleName: string) { const quotedModuleName = `"${moduleName}"`; - return getDiagnosticOfFileFromProgram(program, file.path, file.content.indexOf(quotedModuleName), quotedModuleName.length, ts.Diagnostics.Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_node_or_to_add_aliases_to_the_paths_option, moduleName); + return getDiagnosticOfFileFromProgram(program, file.path, file.content.indexOf(quotedModuleName), quotedModuleName.length, Diagnostics.Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_node_or_to_add_aliases_to_the_paths_option, moduleName); } export function runQueuedTimeoutCallbacks(sys: WatchedSystem) { @@ -102,13 +135,13 @@ export function checkSingleTimeoutQueueLengthAndRunAndVerifyNoTimeout(sys: Watch sys.checkTimeoutQueueLength(0); } -export type WatchOrSolution = void | ts.SolutionBuilder | ts.WatchOfConfigFile | ts.WatchOfFilesAndCompilerOptions; -export interface TscWatchCompileChange { +export type WatchOrSolution = void | SolutionBuilder | WatchOfConfigFile | WatchOfFilesAndCompilerOptions; +export interface TscWatchCompileChange { caption: string; - change: (sys: ts.TestFSWithWatch.TestServerHostTrackingWrittenFiles) => void; + change: (sys: TestServerHostTrackingWrittenFiles) => void; timeouts: ( - sys: ts.TestFSWithWatch.TestServerHostTrackingWrittenFiles, - programs: readonly ts.CommandLineProgram[], + sys: TestServerHostTrackingWrittenFiles, + programs: readonly CommandLineProgram[], watchOrSolution: WatchOrSolution ) => void; } @@ -116,7 +149,7 @@ export interface TscWatchCheckOptions { baselineSourceMap?: boolean; baselineDependencies?: boolean; } -export interface TscWatchCompileBase extends TscWatchCheckOptions { +export interface TscWatchCompileBase extends TscWatchCheckOptions { scenario: string; subScenario: string; commandLineArgs: readonly string[]; @@ -128,7 +161,7 @@ export interface TscWatchCompile extends TscWatchCompileBase { export const noopChange: TscWatchCompileChange = { caption: "No change", - change: ts.noop, + change: noop, timeouts: sys => sys.checkTimeoutQueueLength(0), }; @@ -143,8 +176,8 @@ function tscWatchCompile(input: TscWatchCompile) { } = input; if (!isWatch(commandLineArgs)) sys.exit = exitCode => sys.exitCode = exitCode; - const { cb, getPrograms } = ts.commandLineCallbacks(sys); - const watchOrSolution = ts.executeCommandLine( + const { cb, getPrograms } = commandLineCallbacks(sys); + const watchOrSolution = executeCommandLine( sys, cb, commandLineArgs, @@ -167,71 +200,71 @@ function tscWatchCompile(input: TscWatchCompile) { export interface BaselineBase { baseline: string[]; - sys: ts.TestFSWithWatch.TestServerHostTrackingWrittenFiles; + sys: TestServerHostTrackingWrittenFiles; oldSnap: SystemSnap; } -export interface Baseline extends BaselineBase, ts.CommandLineCallbacks { +export interface Baseline extends BaselineBase, CommandLineCallbacks { } export function createBaseline(system: WatchedSystem, modifySystem?: (sys: WatchedSystem, originalRead: WatchedSystem["readFile"]) => void): Baseline { const originalRead = system.readFile; - const initialSys = fakes.patchHostForBuildInfoReadWrite(system); + const initialSys = patchHostForBuildInfoReadWrite(system); modifySystem?.(initialSys, originalRead); - const sys = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles(initialSys); + const sys = changeToHostTrackingWrittenFiles(initialSys); const baseline: string[] = []; baseline.push("Input::"); sys.diff(baseline); - const { cb, getPrograms } = ts.commandLineCallbacks(sys); + const { cb, getPrograms } = commandLineCallbacks(sys); return { sys, baseline, oldSnap: sys.snap(), cb, getPrograms }; } -export function createSolutionBuilderWithWatchHostForBaseline(sys: WatchedSystem, cb: ts.ExecuteCommandLineCallbacks) { - const host = ts.createSolutionBuilderWithWatchHost(sys, +export function createSolutionBuilderWithWatchHostForBaseline(sys: WatchedSystem, cb: ExecuteCommandLineCallbacks) { + const host = createSolutionBuilderWithWatchHost(sys, /*createProgram*/ undefined, - ts.createDiagnosticReporter(sys, /*pretty*/ true), - ts.createBuilderStatusReporter(sys, /*pretty*/ true), - ts.createWatchStatusReporter(sys, /*pretty*/ true) + createDiagnosticReporter(sys, /*pretty*/ true), + createBuilderStatusReporter(sys, /*pretty*/ true), + createWatchStatusReporter(sys, /*pretty*/ true) ); host.afterProgramEmitAndDiagnostics = cb; host.afterEmitBundle = cb; return host; } -interface CreateWatchCompilerHostOfConfigFileForBaseline extends ts.CreateWatchCompilerHostOfConfigFileInput { +interface CreateWatchCompilerHostOfConfigFileForBaseline extends CreateWatchCompilerHostOfConfigFileInput { system: WatchedSystem, - cb: ts.ExecuteCommandLineCallbacks; + cb: ExecuteCommandLineCallbacks; } -export function createWatchCompilerHostOfConfigFileForBaseline( +export function createWatchCompilerHostOfConfigFileForBaseline( input: CreateWatchCompilerHostOfConfigFileForBaseline ) { - const host = ts.createWatchCompilerHostOfConfigFile({ + const host = createWatchCompilerHostOfConfigFile({ ...input, - reportDiagnostic: ts.createDiagnosticReporter(input.system, /*pretty*/ true), - reportWatchStatus: ts.createWatchStatusReporter(input.system, /*pretty*/ true), + reportDiagnostic: createDiagnosticReporter(input.system, /*pretty*/ true), + reportWatchStatus: createWatchStatusReporter(input.system, /*pretty*/ true), }); updateWatchHostForBaseline(host, input.cb); return host; } -interface CreateWatchCompilerHostOfFilesAndCompilerOptionsForBaseline extends ts.CreateWatchCompilerHostOfFilesAndCompilerOptionsInput { +interface CreateWatchCompilerHostOfFilesAndCompilerOptionsForBaseline extends CreateWatchCompilerHostOfFilesAndCompilerOptionsInput { system: WatchedSystem, - cb: ts.ExecuteCommandLineCallbacks; + cb: ExecuteCommandLineCallbacks; } -export function createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline( +export function createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline( input: CreateWatchCompilerHostOfFilesAndCompilerOptionsForBaseline ) { - const host = ts.createWatchCompilerHostOfFilesAndCompilerOptions({ + const host = createWatchCompilerHostOfFilesAndCompilerOptions({ ...input, - reportDiagnostic: ts.createDiagnosticReporter(input.system, /*pretty*/ true), - reportWatchStatus: ts.createWatchStatusReporter(input.system, /*pretty*/ true), + reportDiagnostic: createDiagnosticReporter(input.system, /*pretty*/ true), + reportWatchStatus: createWatchStatusReporter(input.system, /*pretty*/ true), }); updateWatchHostForBaseline(host, input.cb); return host; } -function updateWatchHostForBaseline(host: ts.WatchCompilerHost, cb: ts.ExecuteCommandLineCallbacks) { +function updateWatchHostForBaseline(host: WatchCompilerHost, cb: ExecuteCommandLineCallbacks) { const emitFilesAndReportErrors = host.afterProgramCreate!; host.afterProgramCreate = builderProgram => { emitFilesAndReportErrors.call(host, builderProgram); @@ -249,12 +282,12 @@ export function applyChange(sys: BaselineBase["sys"], baseline: BaselineBase["ba return sys.snap(); } -export interface RunWatchBaseline extends BaselineBase, TscWatchCompileBase { - sys: ts.TestFSWithWatch.TestServerHostTrackingWrittenFiles; - getPrograms: () => readonly ts.CommandLineProgram[]; +export interface RunWatchBaseline extends BaselineBase, TscWatchCompileBase { + sys: TestServerHostTrackingWrittenFiles; + getPrograms: () => readonly CommandLineProgram[]; watchOrSolution: WatchOrSolution; } -export function runWatchBaseline({ +export function runWatchBaseline({ scenario, subScenario, commandLineArgs, getPrograms, sys, baseline, oldSnap, baselineSourceMap, baselineDependencies, @@ -264,7 +297,7 @@ export function runWatchBaseline { - if (arg.charCodeAt(0) !== ts.CharacterCodes.minus) return false; - const option = arg.slice(arg.charCodeAt(1) === ts.CharacterCodes.minus ? 2 : 1).toLowerCase(); + return forEach(commandLineArgs, arg => { + if (arg.charCodeAt(0) !== CharacterCodes.minus) return false; + const option = arg.slice(arg.charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase(); return option === "watch" || option === "w"; }); } export interface WatchBaseline extends BaselineBase, TscWatchCheckOptions { - oldPrograms: readonly (ts.CommandLineProgram | undefined)[]; - getPrograms: () => readonly ts.CommandLineProgram[]; + oldPrograms: readonly (CommandLineProgram | undefined)[]; + getPrograms: () => readonly CommandLineProgram[]; } export function watchBaseline({ baseline, getPrograms, oldPrograms, sys, oldSnap, baselineSourceMap, baselineDependencies }: WatchBaseline) { - if (baselineSourceMap) ts.generateSourceMapBaselineFiles(sys); + if (baselineSourceMap) generateSourceMapBaselineFiles(sys); sys.serializeOutput(baseline); const programs = baselinePrograms(baseline, getPrograms, oldPrograms, baselineDependencies); sys.serializeWatches(baseline); - baseline.push(`exitCode:: ExitStatus.${ts.ExitStatus[sys.exitCode as ts.ExitStatus]}`, ""); + baseline.push(`exitCode:: ExitStatus.${ExitStatus[sys.exitCode as ExitStatus]}`, ""); sys.diff(baseline, oldSnap); sys.writtenFiles.forEach((value, key) => { assert.equal(value, 1, `Expected to write file ${key} only once`); @@ -313,7 +346,7 @@ export function watchBaseline({ baseline, getPrograms, oldPrograms, sys, oldSnap return programs; } -export function baselinePrograms(baseline: string[], getPrograms: () => readonly ts.CommandLineProgram[], oldPrograms: readonly (ts.CommandLineProgram | undefined)[], baselineDependencies: boolean | undefined) { +export function baselinePrograms(baseline: string[], getPrograms: () => readonly CommandLineProgram[], oldPrograms: readonly (CommandLineProgram | undefined)[], baselineDependencies: boolean | undefined) { const programs = getPrograms(); for (let i = 0; i < programs.length; i++) { baselineProgram(baseline, programs[i], oldPrograms[i], baselineDependencies); @@ -321,7 +354,7 @@ export function baselinePrograms(baseline: string[], getPrograms: () => readonly return programs; } -function baselineProgram(baseline: string[], [program, builderProgram]: ts.CommandLineProgram, oldProgram: ts.CommandLineProgram | undefined, baselineDependencies: boolean | undefined) { +function baselineProgram(baseline: string[], [program, builderProgram]: CommandLineProgram, oldProgram: CommandLineProgram | undefined, baselineDependencies: boolean | undefined) { if (program !== oldProgram?.[0]) { const options = program.getCompilerOptions(); baseline.push(`Program root files: ${JSON.stringify(program.getRootFileNames())}`); @@ -340,7 +373,7 @@ function baselineProgram(baseline: string[], [program, builderProgram]: ts.Comma if (!builderProgram) return; if (builderProgram !== oldProgram?.[1]) { const state = builderProgram.getState(); - const internalState = state as unknown as ts.BuilderProgramState; + const internalState = state as unknown as BuilderProgramState; if (state.semanticDiagnosticsPerFile?.size) { baseline.push("Semantic diagnostics in builder refreshed for::"); for (const file of program.getSourceFiles()) { @@ -356,7 +389,7 @@ function baselineProgram(baseline: string[], [program, builderProgram]: ts.Comma baseline.push(""); if (internalState.hasCalledUpdateShapeSignature?.size) { baseline.push("Shape signatures in builder refreshed for::"); - internalState.hasCalledUpdateShapeSignature.forEach((path: ts.Path) => { + internalState.hasCalledUpdateShapeSignature.forEach((path: Path) => { const info = state.fileInfos.get(path); if (info?.version === info?.signature || !info?.signature) { baseline.push(path + " (used version)"); @@ -410,12 +443,12 @@ export function verifyTscWatch(input: VerifyTscWatch) { } export function replaceFileText(sys: WatchedSystem, file: string, searchValue: string | RegExp, replaceValue: string) { - const content = ts.Debug.checkDefined(sys.readFile(file)); + const content = Debug.checkDefined(sys.readFile(file)); sys.writeFile(file, content.replace(searchValue, replaceValue)); } export function createSolutionBuilder(system: WatchedSystem, rootNames: readonly string[], originalRead?: WatchedSystem["readFile"]) { - const host = ts.createSolutionBuilderHostForBaseline(system, /*versionToWrite*/ undefined, originalRead); + const host = createSolutionBuilderHostForBaseline(system, /*versionToWrite*/ undefined, originalRead); return ts.createSolutionBuilder(host, rootNames, {}); } @@ -429,8 +462,8 @@ export function solutionBuildWithBaseline(sys: WatchedSystem, solutionRoots: rea const originalReadFile = sys.readFile; const originalWrite = sys.write; const originalWriteFile = sys.writeFile; - const solutionBuilder = createSolutionBuilder(ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - fakes.patchHostForBuildInfoReadWrite(sys) + const solutionBuilder = createSolutionBuilder(changeToHostTrackingWrittenFiles( + patchHostForBuildInfoReadWrite(sys) ), solutionRoots, originalRead); solutionBuilder.build(); sys.readFile = originalReadFile; @@ -439,6 +472,6 @@ export function solutionBuildWithBaseline(sys: WatchedSystem, solutionRoots: rea return sys; } -export function createSystemWithSolutionBuild(solutionRoots: readonly string[], files: readonly ts.TestFSWithWatch.FileOrFolderOrSymLink[], params?: ts.TestFSWithWatch.TestServerHostCreationParameters) { +export function createSystemWithSolutionBuild(solutionRoots: readonly string[], files: readonly FileOrFolderOrSymLink[], params?: TestServerHostCreationParameters) { return solutionBuildWithBaseline(createWatchedSystem(files, params), solutionRoots); } diff --git a/src/testRunner/unittests/tscWatch/incremental.ts b/src/testRunner/unittests/tscWatch/incremental.ts index 3e8ac859acf7b..5b3b56f3f1300 100644 --- a/src/testRunner/unittests/tscWatch/incremental.ts +++ b/src/testRunner/unittests/tscWatch/incremental.ts @@ -1,19 +1,32 @@ -import * as Harness from "../../_namespaces/Harness"; -import * as ts from "../../_namespaces/ts"; +import { arrayFrom, emptyArray, noop } from "../../../compiler/core"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { getConfigFileParsingDiagnostics } from "../../../compiler/program"; +import { ModuleKind, Path } from "../../../compiler/types"; +import { + createDiagnosticReporter, parseConfigFileWithSystem, performIncrementalCompilation, +} from "../../../compiler/watch"; +import { createIncrementalCompilerHost, createIncrementalProgram } from "../../../compiler/watchPublic"; +import { executeCommandLine, isBuild } from "../../../executeCommandLine/executeCommandLine"; +import { Baseline } from "../../../harness/harnessIO"; +import { libContent } from "../tsbuild/helpers"; +import { CommandLineProgram } from "../tsc/helpers"; +import { + applyChange, createBaseline, createWatchedSystem, File, libFile, SystemSnap, watchBaseline, WatchedSystem, +} from "./helpers"; describe("unittests:: tsc-watch:: emit file --incremental", () => { const project = "/users/username/projects/project"; - const configFile: ts.tscWatch.File = { + const configFile: File = { path: `${project}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { incremental: true } }) }; interface VerifyIncrementalWatchEmitInput { subScenario: string; - files: () => readonly ts.tscWatch.File[]; + files: () => readonly File[]; optionsToExtend?: readonly string[]; - modifyFs?: (host: ts.tscWatch.WatchedSystem) => void; + modifyFs?: (host: WatchedSystem) => void; } function verifyIncrementalWatchEmit(input: VerifyIncrementalWatchEmitInput) { describe(input.subScenario, () => { @@ -30,27 +43,27 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => { { subScenario, files, optionsToExtend, modifyFs }: VerifyIncrementalWatchEmitInput, incremental: boolean ) { - const { sys, baseline, oldSnap, cb, getPrograms } = ts.tscWatch.createBaseline(ts.tscWatch.createWatchedSystem(files(), { currentDirectory: project })); + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem(files(), { currentDirectory: project })); if (incremental) sys.exit = exitCode => sys.exitCode = exitCode; - const argsToPass = [incremental ? "-i" : "-w", ...(optionsToExtend || ts.emptyArray)]; + const argsToPass = [incremental ? "-i" : "-w", ...(optionsToExtend || emptyArray)]; baseline.push(`${sys.getExecutingFilePath()} ${argsToPass.join(" ")}`); - let oldPrograms: readonly ts.CommandLineProgram[] = ts.emptyArray; + let oldPrograms: readonly CommandLineProgram[] = emptyArray; build(oldSnap); if (modifyFs) { - const oldSnap = ts.tscWatch.applyChange(sys, baseline, modifyFs); + const oldSnap = applyChange(sys, baseline, modifyFs); build(oldSnap); } - Harness.Baseline.runBaseline(`${ts.isBuild(argsToPass) ? "tsbuild/watchMode" : "tscWatch"}/incremental/${subScenario.split(" ").join("-")}-${incremental ? "incremental" : "watch"}.js`, baseline.join("\r\n")); + Baseline.runBaseline(`${isBuild(argsToPass) ? "tsbuild/watchMode" : "tscWatch"}/incremental/${subScenario.split(" ").join("-")}-${incremental ? "incremental" : "watch"}.js`, baseline.join("\r\n")); - function build(oldSnap: ts.tscWatch.SystemSnap) { - const closer = ts.executeCommandLine( + function build(oldSnap: SystemSnap) { + const closer = executeCommandLine( sys, cb, argsToPass, ); - oldPrograms = ts.tscWatch.watchBaseline({ + oldPrograms = watchBaseline({ baseline, getPrograms, oldPrograms, @@ -62,11 +75,11 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => { } describe("non module compilation", () => { - const file1: ts.tscWatch.File = { + const file1: File = { path: `${project}/file1.ts`, content: "const x = 10;" }; - const file2: ts.tscWatch.File = { + const file2: File = { path: `${project}/file2.ts`, content: "const y = 20;" }; @@ -74,7 +87,7 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => { function verify(subScenario: string, optionsToExtend?: readonly string[]) { const modifiedFile2Content = file2.content.replace("y", "z").replace("20", "10"); verifyIncrementalWatchEmit({ - files: () => [ts.tscWatch.libFile, file1, file2, configFile], + files: () => [libFile, file1, file2, configFile], optionsToExtend, subScenario: `own file emit without errors/${subScenario}`, modifyFs: host => host.writeFile(file2.path, modifiedFile2Content), @@ -85,7 +98,7 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => { }); verifyIncrementalWatchEmit({ - files: () => [ts.tscWatch.libFile, file1, configFile, { + files: () => [libFile, file1, configFile, { path: file2.path, content: `const y: string = 20;` }], @@ -94,7 +107,7 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => { }); verifyIncrementalWatchEmit({ - files: () => [ts.tscWatch.libFile, file1, file2, { + files: () => [libFile, file1, file2, { path: configFile.path, content: JSON.stringify({ compilerOptions: { incremental: true, outFile: "out.js" } }) }], @@ -103,76 +116,76 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => { }); describe("module compilation", () => { - const file1: ts.tscWatch.File = { + const file1: File = { path: `${project}/file1.ts`, content: "export const x = 10;" }; - const file2: ts.tscWatch.File = { + const file2: File = { path: `${project}/file2.ts`, content: "export const y = 20;" }; - const config: ts.tscWatch.File = { + const config: File = { path: configFile.path, content: JSON.stringify({ compilerOptions: { incremental: true, module: "amd" } }) }; verifyIncrementalWatchEmit({ - files: () => [ts.tscWatch.libFile, file1, file2, config], + files: () => [libFile, file1, file2, config], subScenario: "module compilation/own file emit without errors", modifyFs: host => host.writeFile(file2.path, file2.content.replace("y", "z").replace("20", "10")), }); describe("own file emit with errors", () => { - const fileModified: ts.tscWatch.File = { + const fileModified: File = { path: file2.path, content: `export const y: string = 20;` }; verifyIncrementalWatchEmit({ - files: () => [ts.tscWatch.libFile, file1, fileModified, config], + files: () => [libFile, file1, fileModified, config], subScenario: "module compilation/own file emit with errors", modifyFs: host => host.writeFile(file1.path, file1.content.replace("x = 10", "z = 10")), }); it("verify that state is read correctly", () => { - const system = ts.tscWatch.createWatchedSystem([ts.tscWatch.libFile, file1, fileModified, config], { currentDirectory: project }); - const reportDiagnostic = ts.createDiagnosticReporter(system); - const parsedConfig = ts.parseConfigFileWithSystem("tsconfig.json", {}, /*extendedConfigCache*/ undefined, /*watchOptionsToExtend*/ undefined, system, reportDiagnostic)!; - ts.performIncrementalCompilation({ + const system = createWatchedSystem([libFile, file1, fileModified, config], { currentDirectory: project }); + const reportDiagnostic = createDiagnosticReporter(system); + const parsedConfig = parseConfigFileWithSystem("tsconfig.json", {}, /*extendedConfigCache*/ undefined, /*watchOptionsToExtend*/ undefined, system, reportDiagnostic)!; + performIncrementalCompilation({ rootNames: parsedConfig.fileNames, options: parsedConfig.options, projectReferences: parsedConfig.projectReferences, - configFileParsingDiagnostics: ts.getConfigFileParsingDiagnostics(parsedConfig), + configFileParsingDiagnostics: getConfigFileParsingDiagnostics(parsedConfig), reportDiagnostic, system }); - const command = ts.parseConfigFileWithSystem("tsconfig.json", {}, /*extendedConfigCache*/ undefined, /*watchOptionsToExtend*/ undefined, system, ts.noop)!; - const builderProgram = ts.createIncrementalProgram({ + const command = parseConfigFileWithSystem("tsconfig.json", {}, /*extendedConfigCache*/ undefined, /*watchOptionsToExtend*/ undefined, system, noop)!; + const builderProgram = createIncrementalProgram({ rootNames: command.fileNames, options: command.options, projectReferences: command.projectReferences, - configFileParsingDiagnostics: ts.getConfigFileParsingDiagnostics(command), - host: ts.createIncrementalCompilerHost(command.options, system) + configFileParsingDiagnostics: getConfigFileParsingDiagnostics(command), + host: createIncrementalCompilerHost(command.options, system) }); const state = builderProgram.getState(); assert.equal(state.changedFilesSet!.size, 0, "changes"); assert.equal(state.fileInfos.size, 3, "FileInfo size"); - assert.deepEqual(state.fileInfos.get(ts.tscWatch.libFile.path as ts.Path), { - version: system.createHash(ts.tscWatch.libFile.content), - signature: system.createHash(ts.tscWatch.libFile.content), + assert.deepEqual(state.fileInfos.get(libFile.path as Path), { + version: system.createHash(libFile.content), + signature: system.createHash(libFile.content), affectsGlobalScope: true, impliedFormat: undefined, }); - assert.deepEqual(state.fileInfos.get(file1.path as ts.Path), { + assert.deepEqual(state.fileInfos.get(file1.path as Path), { version: system.createHash(file1.content), signature: system.createHash(file1.content), affectsGlobalScope: undefined, impliedFormat: undefined, }); - assert.deepEqual(state.fileInfos.get(file2.path as ts.Path), { + assert.deepEqual(state.fileInfos.get(file2.path as Path), { version: system.createHash(fileModified.content), signature: system.createHash(fileModified.content), affectsGlobalScope: undefined, @@ -181,22 +194,22 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => { assert.deepEqual(state.compilerOptions, { incremental: true, - module: ts.ModuleKind.AMD, + module: ModuleKind.AMD, configFilePath: config.path }); - assert.equal(ts.arrayFrom(state.referencedMap!.keys()).length, 0); - assert.equal(ts.arrayFrom(state.exportedModulesMap!.keys()).length, 0); + assert.equal(arrayFrom(state.referencedMap!.keys()).length, 0); + assert.equal(arrayFrom(state.exportedModulesMap!.keys()).length, 0); assert.equal(state.semanticDiagnosticsPerFile!.size, 3); - assert.deepEqual(state.semanticDiagnosticsPerFile!.get(ts.tscWatch.libFile.path as ts.Path), ts.emptyArray); - assert.deepEqual(state.semanticDiagnosticsPerFile!.get(file1.path as ts.Path), ts.emptyArray); - assert.deepEqual(state.semanticDiagnosticsPerFile!.get(file2.path as ts.Path), [{ - file: state.program!.getSourceFileByPath(file2.path as ts.Path)!, + assert.deepEqual(state.semanticDiagnosticsPerFile!.get(libFile.path as Path), emptyArray); + assert.deepEqual(state.semanticDiagnosticsPerFile!.get(file1.path as Path), emptyArray); + assert.deepEqual(state.semanticDiagnosticsPerFile!.get(file2.path as Path), [{ + file: state.program!.getSourceFileByPath(file2.path as Path)!, start: 13, length: 1, - code: ts.Diagnostics.Type_0_is_not_assignable_to_type_1.code, - category: ts.Diagnostics.Type_0_is_not_assignable_to_type_1.category, + code: Diagnostics.Type_0_is_not_assignable_to_type_1.code, + category: Diagnostics.Type_0_is_not_assignable_to_type_1.category, messageText: "Type 'number' is not assignable to type 'string'.", relatedInformation: undefined, reportsUnnecessary: undefined, @@ -208,7 +221,7 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => { }); verifyIncrementalWatchEmit({ - files: () => [ts.tscWatch.libFile, file1, file2, { + files: () => [libFile, file1, file2, { path: configFile.path, content: JSON.stringify({ compilerOptions: { incremental: true, module: "amd", outFile: "out.js" } }) }], @@ -218,7 +231,7 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => { verifyIncrementalWatchEmit({ files: () => { - const config: ts.tscWatch.File = { + const config: File = { path: configFile.path, content: JSON.stringify({ compilerOptions: { @@ -230,7 +243,7 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => { } }) }; - const aTs: ts.tscWatch.File = { + const aTs: File = { path: `${project}/a.ts`, content: `import { B } from "./b"; export interface A { @@ -238,7 +251,7 @@ export interface A { } ` }; - const bTs: ts.tscWatch.File = { + const bTs: File = { path: `${project}/b.ts`, content: `import { C } from "./c"; export interface B { @@ -246,7 +259,7 @@ export interface B { } ` }; - const cTs: ts.tscWatch.File = { + const cTs: File = { path: `${project}/c.ts`, content: `import { A } from "./a"; export interface C { @@ -254,14 +267,14 @@ export interface C { } ` }; - const indexTs: ts.tscWatch.File = { + const indexTs: File = { path: `${project}/index.ts`, content: `export { A } from "./a"; export { B } from "./b"; export { C } from "./c"; ` }; - return [ts.tscWatch.libFile, aTs, bTs, cTs, indexTs, config]; + return [libFile, aTs, bTs, cTs, indexTs, config]; }, subScenario: "incremental with circular references", modifyFs: host => host.writeFile(`${project}/a.ts`, `import { B } from "./b"; @@ -275,7 +288,7 @@ export interface A { verifyIncrementalWatchEmit({ subScenario: "when file with ambient global declaration file is deleted", files: () => [ - { path: ts.tscWatch.libFile.path, content: ts.libContent }, + { path: libFile.path, content: libContent }, { path: `${project}/globals.d.ts`, content: `declare namespace Config { const value: string;} ` }, { path: `${project}/index.ts`, content: `console.log(Config.value);` }, { path: configFile.path, content: JSON.stringify({ compilerOptions: { incremental: true, } }) } @@ -301,7 +314,7 @@ export const Fragment: unique symbol; verifyIncrementalWatchEmit({ subScenario: "jsxImportSource option changed", files: () => [ - { path: ts.tscWatch.libFile.path, content: ts.libContent }, + { path: libFile.path, content: libContent }, { path: `${project}/node_modules/react/jsx-runtime/index.d.ts`, content: jsxLibraryContent }, { path: `${project}/node_modules/react/package.json`, content: JSON.stringify({ name: "react", version: "0.0.1" }) }, { path: `${project}/node_modules/preact/jsx-runtime/index.d.ts`, content: jsxLibraryContent.replace("propA", "propB") }, @@ -316,7 +329,7 @@ export const Fragment: unique symbol; verifyIncrementalWatchEmit({ subScenario: "jsxImportSource backing types added", files: () => [ - { path: ts.tscWatch.libFile.path, content: ts.libContent }, + { path: libFile.path, content: libContent }, { path: `${project}/index.tsx`, content: `export const App = () =>
;` }, { path: configFile.path, content: JSON.stringify({ compilerOptions: jsxImportSourceOptions }) } ], @@ -332,7 +345,7 @@ export const Fragment: unique symbol; verifyIncrementalWatchEmit({ subScenario: "jsxImportSource backing types removed", files: () => [ - { path: ts.tscWatch.libFile.path, content: ts.libContent }, + { path: libFile.path, content: libContent }, { path: `${project}/node_modules/react/jsx-runtime/index.d.ts`, content: jsxLibraryContent }, { path: `${project}/node_modules/react/package.json`, content: JSON.stringify({ name: "react", version: "0.0.1" }) }, { path: `${project}/index.tsx`, content: `export const App = () =>
;` }, @@ -347,7 +360,7 @@ export const Fragment: unique symbol; verifyIncrementalWatchEmit({ subScenario: "importHelpers backing types removed", files: () => [ - { path: ts.tscWatch.libFile.path, content: ts.libContent }, + { path: libFile.path, content: libContent }, { path: `${project}/node_modules/tslib/index.d.ts`, content: "export function __assign(...args: any[]): any;" }, { path: `${project}/node_modules/tslib/package.json`, content: JSON.stringify({ name: "tslib", version: "0.0.1" }) }, { path: `${project}/index.tsx`, content: `export const x = {...{}};` }, @@ -364,7 +377,7 @@ export const Fragment: unique symbol; verifyIncrementalWatchEmit({ subScenario: "editing module augmentation", files: () => [ - { path: ts.tscWatch.libFile.path, content: ts.libContent }, + { path: libFile.path, content: libContent }, { path: `${project}/node_modules/classnames/index.d.ts`, content: `export interface Result {} export default function classNames(): Result;` }, { path: `${project}/src/types/classnames.d.ts`, content: `export {}; declare module "classnames" { interface Result { foo } }` }, { path: `${project}/src/index.ts`, content: `import classNames from "classnames"; classNames().foo;` }, diff --git a/src/testRunner/unittests/tscWatch/nodeNextWatch.ts b/src/testRunner/unittests/tscWatch/nodeNextWatch.ts index 76e1c72cd808a..c452c06aaf713 100644 --- a/src/testRunner/unittests/tscWatch/nodeNextWatch.ts +++ b/src/testRunner/unittests/tscWatch/nodeNextWatch.ts @@ -1,13 +1,13 @@ -import * as ts from "../../_namespaces/ts"; -import * as Utils from "../../_namespaces/Utils"; +import { dedent } from "../../../harness/util"; +import { createWatchedSystem, File, libFile, runQueuedTimeoutCallbacks, verifyTscWatch } from "./helpers"; describe("unittests:: tsc-watch:: nodeNextWatch:: emit when module emit is specified as nodenext", () => { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "nodenext watch emit", subScenario: "esm-mode file is edited", commandLineArgs: ["--w", "--p", "/project/tsconfig.json"], sys: () => { - const configFile: ts.tscWatch.File = { + const configFile: File = { path: "/project/tsconfig.json", content: JSON.stringify({ compilerOptions: { @@ -19,7 +19,7 @@ describe("unittests:: tsc-watch:: nodeNextWatch:: emit when module emit is speci } }) }; - const packageFile: ts.tscWatch.File = { + const packageFile: File = { path: "/project/package.json", content: JSON.stringify({ name: "some-proj", @@ -29,30 +29,30 @@ describe("unittests:: tsc-watch:: nodeNextWatch:: emit when module emit is speci main: "index.js", }) }; - const file1: ts.tscWatch.File = { + const file1: File = { path: "/project/src/index.ts", - content: Utils.dedent` + content: dedent` import * as Thing from "thing"; Thing.fn();` }; - const declFile: ts.tscWatch.File = { + const declFile: File = { path: "/project/src/deps.d.ts", content: `declare module "thing";` }; - return ts.tscWatch.createWatchedSystem([configFile, file1, declFile, packageFile, { ...ts.tscWatch.libFile, path: "/a/lib/lib.es2020.full.d.ts" }]); + return createWatchedSystem([configFile, file1, declFile, packageFile, { ...libFile, path: "/a/lib/lib.es2020.full.d.ts" }]); }, changes: [ { caption: "Modify typescript file", change: sys => sys.modifyFile( "/project/src/index.ts", - Utils.dedent` + dedent` import * as Thing from "thing"; Thing.fn();`, {}, ), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, } ], }); diff --git a/src/testRunner/unittests/tscWatch/programUpdates.ts b/src/testRunner/unittests/tscWatch/programUpdates.ts index 214eb8b670705..8bf5c4220ebc0 100644 --- a/src/testRunner/unittests/tscWatch/programUpdates.ts +++ b/src/testRunner/unittests/tscWatch/programUpdates.ts @@ -1,19 +1,30 @@ -import * as Harness from "../../_namespaces/Harness"; -import * as ts from "../../_namespaces/ts"; +import { generateTSConfig } from "../../../compiler/commandLineParser"; +import { emptyArray } from "../../../compiler/core"; +import { getDirectoryPath } from "../../../compiler/path"; +import { CompilerOptions, ModuleKind } from "../../../compiler/types"; +import { createWatchProgram } from "../../../compiler/watchPublic"; +import { Baseline } from "../../../harness/harnessIO"; +import { commandLineCallbacks } from "../tsc/helpers"; +import { + checkSingleTimeoutQueueLengthAndRun, commonFile1, commonFile2, createBaseline, + createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline, createWatchedSystem, File, libFile, noopChange, + projectRoot, replaceFileText, runQueuedTimeoutCallbacks, runWatchBaseline, SymLink, TscWatchCompileChange, + verifyTscWatch, watchBaseline, WatchedSystem, +} from "./helpers"; describe("unittests:: tsc-watch:: program updates", () => { const scenario = "programUpdates"; const configFilePath = "/a/b/tsconfig.json"; - const configFile: ts.tscWatch.File = { + const configFile: File = { path: configFilePath, content: `{}` }; - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "create watch without config file", commandLineArgs: ["-w", "/a/b/c/app.ts"], sys: () => { - const appFile: ts.tscWatch.File = { + const appFile: File = { path: "/a/b/c/app.ts", content: ` import {f} from "./module" @@ -21,16 +32,16 @@ describe("unittests:: tsc-watch:: program updates", () => { ` }; - const moduleFile: ts.tscWatch.File = { + const moduleFile: File = { path: "/a/b/c/module.d.ts", content: `export let x: number` }; - return ts.tscWatch.createWatchedSystem([appFile, moduleFile, ts.tscWatch.libFile]); + return createWatchedSystem([appFile, moduleFile, libFile]); }, - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "can handle tsconfig file name with difference casing", commandLineArgs: ["-w", "-p", "/A/B/tsconfig.json"], @@ -45,17 +56,17 @@ describe("unittests:: tsc-watch:: program updates", () => { include: ["app.ts"] }) }; - return ts.tscWatch.createWatchedSystem([f1, ts.tscWatch.libFile, config], { useCaseSensitiveFileNames: false }); + return createWatchedSystem([f1, libFile, config], { useCaseSensitiveFileNames: false }); }, - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "create configured project without file list", commandLineArgs: ["-w", "-p", configFilePath], sys: () => { - const configFile: ts.tscWatch.File = { + const configFile: File = { path: configFilePath, content: ` { @@ -65,43 +76,43 @@ describe("unittests:: tsc-watch:: program updates", () => { ] }` }; - const file1: ts.tscWatch.File = { + const file1: File = { path: "/a/b/c/f1.ts", content: "let x = 1" }; - const file2: ts.tscWatch.File = { + const file2: File = { path: "/a/b/d/f2.ts", content: "let y = 1" }; - const file3: ts.tscWatch.File = { + const file3: File = { path: "/a/b/e/f3.ts", content: "let z = 1" }; - return ts.tscWatch.createWatchedSystem([configFile, ts.tscWatch.libFile, file1, file2, file3]); + return createWatchedSystem([configFile, libFile, file1, file2, file3]); }, - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "add new files to a configured program without file list", commandLineArgs: ["-w", "-p", configFilePath], - sys: () => ts.tscWatch.createWatchedSystem([ts.tscWatch.commonFile1, ts.tscWatch.libFile, configFile]), + sys: () => createWatchedSystem([commonFile1, libFile, configFile]), changes: [ { caption: "Create commonFile2", - change: sys => sys.writeFile(ts.tscWatch.commonFile2.path, ts.tscWatch.commonFile2.content), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.writeFile(commonFile2.path, commonFile2.content), + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "should ignore non-existing files specified in the config file", commandLineArgs: ["-w", "-p", configFilePath], sys: () => { - const configFile: ts.tscWatch.File = { + const configFile: File = { path: configFilePath, content: `{ "compilerOptions": {}, @@ -111,131 +122,131 @@ describe("unittests:: tsc-watch:: program updates", () => { ] }` }; - return ts.tscWatch.createWatchedSystem([ts.tscWatch.commonFile1, ts.tscWatch.commonFile2, ts.tscWatch.libFile, configFile]); + return createWatchedSystem([commonFile1, commonFile2, libFile, configFile]); }, - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "handle recreated files correctly", commandLineArgs: ["-w", "-p", configFilePath, "--explainFiles"], sys: () => { - return ts.tscWatch.createWatchedSystem([ts.tscWatch.libFile, ts.tscWatch.commonFile1, ts.tscWatch.commonFile2, configFile]); + return createWatchedSystem([libFile, commonFile1, commonFile2, configFile]); }, changes: [ { caption: "change file to ensure signatures are updated", - change: sys => sys.appendFile(ts.tscWatch.commonFile2.path, ";let xy = 10;"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.appendFile(commonFile2.path, ";let xy = 10;"), + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "delete file2", - change: sys => sys.deleteFile(ts.tscWatch.commonFile2.path), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.deleteFile(commonFile2.path), + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "recreate file2", - change: sys => sys.writeFile(ts.tscWatch.commonFile2.path, ts.tscWatch.commonFile2.content), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.writeFile(commonFile2.path, commonFile2.content), + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "handles the missing files - that were added to program because they were added with tripleSlashRefs", commandLineArgs: ["-w", "/a/b/commonFile1.ts"], sys: () => { - const file1: ts.tscWatch.File = { - path: ts.tscWatch.commonFile1.path, + const file1: File = { + path: commonFile1.path, content: `/// let x = y` }; - return ts.tscWatch.createWatchedSystem([file1, ts.tscWatch.libFile]); + return createWatchedSystem([file1, libFile]); }, changes: [ { caption: "create file2", - change: sys => sys.writeFile(ts.tscWatch.commonFile2.path, ts.tscWatch.commonFile2.content), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.writeFile(commonFile2.path, commonFile2.content), + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "should reflect change in config file", commandLineArgs: ["-w", "-p", configFilePath, "--explainFiles"], sys: () => { - const configFile: ts.tscWatch.File = { + const configFile: File = { path: configFilePath, content: `{ "compilerOptions": {}, - "files": ["${ts.tscWatch.commonFile1.path}", "${ts.tscWatch.commonFile2.path}"] + "files": ["${commonFile1.path}", "${commonFile2.path}"] }` }; - return ts.tscWatch.createWatchedSystem([ts.tscWatch.libFile, ts.tscWatch.commonFile1, ts.tscWatch.commonFile2, configFile]); + return createWatchedSystem([libFile, commonFile1, commonFile2, configFile]); }, changes: [ { caption: "change file to ensure signatures are updated", - change: sys => sys.appendFile(ts.tscWatch.commonFile2.path, ";let xy = 10;"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.appendFile(commonFile2.path, ";let xy = 10;"), + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "Change config", change: sys => sys.writeFile(configFilePath, `{ "compilerOptions": {}, - "files": ["${ts.tscWatch.commonFile1.path}"] + "files": ["${commonFile1.path}"] }`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "works correctly when config file is changed but its content havent", commandLineArgs: ["-w", "-p", configFilePath], sys: () => { - const configFile: ts.tscWatch.File = { + const configFile: File = { path: configFilePath, content: `{ "compilerOptions": {}, - "files": ["${ts.tscWatch.commonFile1.path}", "${ts.tscWatch.commonFile2.path}"] + "files": ["${commonFile1.path}", "${commonFile2.path}"] }` }; - return ts.tscWatch.createWatchedSystem([ts.tscWatch.libFile, ts.tscWatch.commonFile1, ts.tscWatch.commonFile2, configFile]); + return createWatchedSystem([libFile, commonFile1, commonFile2, configFile]); }, changes: [ { caption: "Modify config without changing content", change: sys => sys.modifyFile(configFilePath, `{ "compilerOptions": {}, - "files": ["${ts.tscWatch.commonFile1.path}", "${ts.tscWatch.commonFile2.path}"] + "files": ["${commonFile1.path}", "${commonFile2.path}"] }`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "Updates diagnostics when '--noUnusedLabels' changes", commandLineArgs: ["-w", "-p", "/tsconfig.json"], sys: () => { - const aTs: ts.tscWatch.File = { + const aTs: File = { path: "/a.ts", content: "label: while (1) {}" }; - const tsconfig: ts.tscWatch.File = { + const tsconfig: File = { path: "/tsconfig.json", content: JSON.stringify({ compilerOptions: { allowUnusedLabels: true } }) }; - return ts.tscWatch.createWatchedSystem([ts.tscWatch.libFile, aTs, tsconfig]); + return createWatchedSystem([libFile, aTs, tsconfig]); }, changes: [ { @@ -243,24 +254,24 @@ describe("unittests:: tsc-watch:: program updates", () => { change: sys => sys.modifyFile("/tsconfig.json", JSON.stringify({ compilerOptions: { allowUnusedLabels: false } })), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "Enable allowUnsusedLabels", change: sys => sys.modifyFile("/tsconfig.json", JSON.stringify({ compilerOptions: { allowUnusedLabels: true } })), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "updates diagnostics and emit for decorators", commandLineArgs: ["-w"], sys: () => { - const aTs: ts.tscWatch.File = { + const aTs: File = { path: "/a.ts", content: `import {B} from './b' @((_) => {}) @@ -268,17 +279,17 @@ export class A { constructor(p: B) {} }`, }; - const bTs: ts.tscWatch.File = { + const bTs: File = { path: "/b.ts", content: `export class B {}`, }; - const tsconfig: ts.tscWatch.File = { + const tsconfig: File = { path: "/tsconfig.json", content: JSON.stringify({ compilerOptions: { target: "es6", importsNotUsedAsValues: "error" } }) }; - return ts.tscWatch.createWatchedSystem([ts.tscWatch.libFile, aTs, bTs, tsconfig]); + return createWatchedSystem([libFile, aTs, bTs, tsconfig]); }, changes: [ { @@ -286,7 +297,7 @@ export class A { change: sys => sys.modifyFile("/tsconfig.json", JSON.stringify({ compilerOptions: { target: "es6", importsNotUsedAsValues: "error", experimentalDecorators: true } })), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { @@ -294,50 +305,50 @@ export class A { change: sys => sys.modifyFile("/tsconfig.json", JSON.stringify({ compilerOptions: { target: "es6", importsNotUsedAsValues: "error", experimentalDecorators: true, emitDecoratorMetadata: true } })), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "files explicitly excluded in config file", commandLineArgs: ["-w", "-p", configFilePath], sys: () => { - const configFile: ts.tscWatch.File = { + const configFile: File = { path: configFilePath, content: `{ "compilerOptions": {}, "exclude": ["/a/c"] }` }; - const excludedFile1: ts.tscWatch.File = { + const excludedFile1: File = { path: "/a/c/excluedFile1.ts", content: `let t = 1;` }; - return ts.tscWatch.createWatchedSystem([ts.tscWatch.libFile, ts.tscWatch.commonFile1, ts.tscWatch.commonFile2, excludedFile1, configFile]); + return createWatchedSystem([libFile, commonFile1, commonFile2, excludedFile1, configFile]); }, - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "should properly handle module resolution changes in config file", commandLineArgs: ["-w", "-p", configFilePath], sys: () => { - const file1: ts.tscWatch.File = { + const file1: File = { path: "/a/b/file1.ts", content: `import { T } from "module1";` }; - const nodeModuleFile: ts.tscWatch.File = { + const nodeModuleFile: File = { path: "/a/b/node_modules/module1.ts", content: `export interface T {}` }; - const classicModuleFile: ts.tscWatch.File = { + const classicModuleFile: File = { path: "/a/module1.ts", content: `export interface T {}` }; - const configFile: ts.tscWatch.File = { + const configFile: File = { path: configFilePath, content: `{ "compilerOptions": { @@ -346,7 +357,7 @@ export class A { "files": ["${file1.path}"] }` }; - return ts.tscWatch.createWatchedSystem([ts.tscWatch.libFile, file1, nodeModuleFile, classicModuleFile, configFile]); + return createWatchedSystem([libFile, file1, nodeModuleFile, classicModuleFile, configFile]); }, changes: [ { @@ -357,17 +368,17 @@ export class A { }, "files": ["/a/b/file1.ts"] }`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "should tolerate config file errors and still try to build a project", commandLineArgs: ["-w", "-p", configFilePath], sys: () => { - const configFile: ts.tscWatch.File = { + const configFile: File = { path: configFilePath, content: `{ "compilerOptions": { @@ -377,12 +388,12 @@ export class A { "someOtherProperty": {} }` }; - return ts.tscWatch.createWatchedSystem([ts.tscWatch.commonFile1, ts.tscWatch.commonFile2, ts.tscWatch.libFile, configFile]); + return createWatchedSystem([commonFile1, commonFile2, libFile, configFile]); }, - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "changes in files are reflected in project structure", commandLineArgs: ["-w", "/a/b/f1.ts", "--explainFiles"], @@ -399,19 +410,19 @@ export class A { path: "/a/c/f3.ts", content: `export let y = 1;` }; - return ts.tscWatch.createWatchedSystem([file1, file2, file3, ts.tscWatch.libFile]); + return createWatchedSystem([file1, file2, file3, libFile]); }, changes: [ { caption: "Modify f2 to include f3", // now inferred project should inclule file3 change: sys => sys.modifyFile("/a/b/f2.ts", `export * from "../c/f3"`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "deleted files affect project structure", commandLineArgs: ["-w", "/a/b/f1.ts", "--noImplicitAny"], @@ -428,18 +439,18 @@ export class A { path: "/a/c/f3.ts", content: `export let y = 1;` }; - return ts.tscWatch.createWatchedSystem([file1, file2, file3, ts.tscWatch.libFile]); + return createWatchedSystem([file1, file2, file3, libFile]); }, changes: [ { caption: "Delete f2", change: sys => sys.deleteFile("/a/b/f2.ts"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "deleted files affect project structure-2", commandLineArgs: ["-w", "/a/b/f1.ts", "/a/c/f3.ts", "--noImplicitAny"], @@ -456,18 +467,18 @@ export class A { path: "/a/c/f3.ts", content: `export let y = 1;` }; - return ts.tscWatch.createWatchedSystem([file1, file2, file3, ts.tscWatch.libFile]); + return createWatchedSystem([file1, file2, file3, libFile]); }, changes: [ { caption: "Delete f2", change: sys => sys.deleteFile("/a/b/f2.ts"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "config file includes the file", commandLineArgs: ["-w", "-p", "/a/c/tsconfig.json"], @@ -488,12 +499,12 @@ export class A { path: "/a/c/tsconfig.json", content: JSON.stringify({ compilerOptions: {}, files: ["f2.ts", "f3.ts"] }) }; - return ts.tscWatch.createWatchedSystem([file1, file2, file3, ts.tscWatch.libFile, configFile]); + return createWatchedSystem([file1, file2, file3, libFile, configFile]); }, - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "change module to none", commandLineArgs: ["-w", "-p", configFilePath], @@ -502,11 +513,11 @@ export class A { path: "/a/b/f1.ts", content: "export {}\ndeclare global {}" }; - return ts.tscWatch.createWatchedSystem([file1, ts.tscWatch.libFile, configFile]); + return createWatchedSystem([file1, libFile, configFile]); }, changes: [{ caption: "change `module` to 'none'", - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, change: sys => { sys.writeFile(configFilePath, JSON.stringify({ compilerOptions: { module: "none" } })); } @@ -528,49 +539,49 @@ export class A { path: "/a/d/f3.ts", content: "export let y = 1;" }; - const { sys, baseline, oldSnap, cb, getPrograms } = ts.tscWatch.createBaseline(ts.tscWatch.createWatchedSystem([ts.tscWatch.libFile, file1, file2, file3])); - const host = ts.tscWatch.createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({ + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([libFile, file1, file2, file3])); + const host = createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({ rootFiles: [file2.path, file3.path], system: sys, options: { allowNonTsExtensions: true }, cb, watchOptions: undefined }); - ts.createWatchProgram(host); + createWatchProgram(host); baseline.push(`${sys.getExecutingFilePath()} --w ${file2.path} ${file3.path}`); - ts.tscWatch.watchBaseline({ + watchBaseline({ baseline, getPrograms, - oldPrograms: ts.emptyArray, + oldPrograms: emptyArray, sys, oldSnap, }); - const {cb: cb2, getPrograms: getPrograms2 } = ts.commandLineCallbacks(sys); + const {cb: cb2, getPrograms: getPrograms2 } = commandLineCallbacks(sys); const oldSnap2 = sys.snap(); baseline.push("createing separate watcher"); - ts.createWatchProgram(ts.tscWatch.createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({ + createWatchProgram(createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({ rootFiles:[file1.path], system: sys, options: { allowNonTsExtensions: true }, cb: cb2, watchOptions: undefined })); - ts.tscWatch.watchBaseline({ + watchBaseline({ baseline, getPrograms: getPrograms2, - oldPrograms: ts.emptyArray, + oldPrograms: emptyArray, sys, oldSnap: oldSnap2, }); sys.checkTimeoutQueueLength(0); - baseline.push(`First program is not updated:: ${getPrograms() === ts.emptyArray}`); - baseline.push(`Second program is not updated:: ${getPrograms2() === ts.emptyArray}`); - Harness.Baseline.runBaseline(`tscWatch/${scenario}/two-watch-programs-are-not-affected-by-each-other.js`, baseline.join("\r\n")); + baseline.push(`First program is not updated:: ${getPrograms() === emptyArray}`); + baseline.push(`Second program is not updated:: ${getPrograms2() === emptyArray}`); + Baseline.runBaseline(`tscWatch/${scenario}/two-watch-programs-are-not-affected-by-each-other.js`, baseline.join("\r\n")); }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "can correctly update configured project when set of root files has changed (new file on disk)", commandLineArgs: ["-w", "-p", configFilePath], @@ -579,18 +590,18 @@ export class A { path: "/a/b/f1.ts", content: "let x = 1" }; - return ts.tscWatch.createWatchedSystem([file1, ts.tscWatch.libFile, configFile]); + return createWatchedSystem([file1, libFile, configFile]); }, changes: [ { caption: "Write f2", change: sys => sys.writeFile("/a/b/f2.ts", "let y = 1"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "can correctly update configured project when set of root files has changed (new file in list of files)", commandLineArgs: ["-w", "-p", configFilePath], @@ -607,42 +618,42 @@ export class A { path: configFilePath, content: JSON.stringify({ compilerOptions: {}, files: ["f1.ts"] }) }; - return ts.tscWatch.createWatchedSystem([file1, file2, ts.tscWatch.libFile, configFile]); + return createWatchedSystem([file1, file2, libFile, configFile]); }, changes: [ { caption: "Modify config to make f2 as root too", change: sys => sys.writeFile(configFilePath, JSON.stringify({ compilerOptions: {}, files: ["f1.ts", "f2.ts"] })), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "can correctly update configured project when set of root files has changed through include", commandLineArgs: ["-w", "-p", "."], sys: () => { const file1 = { - path: `${ts.tscWatch.projectRoot}/Project/file1.ts`, + path: `${projectRoot}/Project/file1.ts`, content: "export const x = 10;" }; const configFile = { - path: `${ts.tscWatch.projectRoot}/Project/tsconfig.json`, + path: `${projectRoot}/Project/tsconfig.json`, content: JSON.stringify({ include: [".", "./**/*.json"] }) }; - return ts.tscWatch.createWatchedSystem([file1, ts.tscWatch.libFile, configFile], { currentDirectory: `${ts.tscWatch.projectRoot}/Project` }); + return createWatchedSystem([file1, libFile, configFile], { currentDirectory: `${projectRoot}/Project` }); }, changes: [ { caption: "Write file2", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/Project/file2.ts`, "export const y = 10;"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + change: sys => sys.writeFile(`${projectRoot}/Project/file2.ts`, "export const y = 10;"), + timeouts: checkSingleTimeoutQueueLengthAndRun } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "can update configured project when set of root files was not changed", commandLineArgs: ["-w", "-p", configFilePath], @@ -659,18 +670,18 @@ export class A { path: configFilePath, content: JSON.stringify({ compilerOptions: {}, files: ["f1.ts", "f2.ts"] }) }; - return ts.tscWatch.createWatchedSystem([file1, file2, ts.tscWatch.libFile, configFile]); + return createWatchedSystem([file1, file2, libFile, configFile]); }, changes: [ { caption: "Modify config to set outFile option", change: sys => sys.writeFile(configFilePath, JSON.stringify({ compilerOptions: { outFile: "out.js" }, files: ["f1.ts", "f2.ts"] })), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "file in files is deleted", commandLineArgs: ["-w", "-p", configFilePath], @@ -687,18 +698,18 @@ export class A { path: configFilePath, content: JSON.stringify({ compilerOptions: {}, files: ["f1.ts", "f2.ts"] }) }; - return ts.tscWatch.createWatchedSystem([file1, file2, ts.tscWatch.libFile, configFile]); + return createWatchedSystem([file1, file2, libFile, configFile]); }, changes: [ { caption: "Delete f2", change: sys => sys.deleteFile("/a/b/f2.ts"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "config file is deleted", commandLineArgs: ["-w", "-p", configFilePath], @@ -711,18 +722,18 @@ export class A { path: "/a/b/f2.ts", content: "let y = 2;" }; - return ts.tscWatch.createWatchedSystem([file1, file2, ts.tscWatch.libFile, configFile]); + return createWatchedSystem([file1, file2, libFile, configFile]); }, changes: [ { caption: "Delete config file", change: sys => sys.deleteFile(configFilePath), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "Proper errors document is not contained in project", commandLineArgs: ["-w", "-p", configFilePath], @@ -735,19 +746,19 @@ export class A { path: configFilePath, content: "{" }; - return ts.tscWatch.createWatchedSystem([file1, ts.tscWatch.libFile, corruptedConfig]); + return createWatchedSystem([file1, libFile, corruptedConfig]); }, - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "correctly handles changes in lib section of config file", commandLineArgs: ["-w", "-p", "/src/tsconfig.json"], sys: () => { const libES5 = { path: "/compiler/lib.es5.d.ts", - content: `${ts.tscWatch.libFile.content} + content: `${libFile.content} declare const eval: any` }; const libES2015Promise = { @@ -773,7 +784,7 @@ declare const eval: any` } }) }; - return ts.tscWatch.createWatchedSystem([libES5, libES2015Promise, app, config1], { executingFilePath: "/compiler/tsc.js" }); + return createWatchedSystem([libES5, libES2015Promise, app, config1], { executingFilePath: "/compiler/tsc.js" }); }, changes: [ { @@ -792,12 +803,12 @@ declare const eval: any` } }) ), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "should handle non-existing directories in config file", commandLineArgs: ["-w", "-p", "/a/tsconfig.json"], @@ -816,17 +827,17 @@ declare const eval: any` ] }) }; - return ts.tscWatch.createWatchedSystem([f, config, ts.tscWatch.libFile]); + return createWatchedSystem([f, config, libFile]); }, - changes: ts.emptyArray + changes: emptyArray }); - function runQueuedTimeoutCallbacksTwice(sys: ts.tscWatch.WatchedSystem) { + function runQueuedTimeoutCallbacksTwice(sys: WatchedSystem) { sys.runQueuedTimeoutCallbacks(); // Scheduled invalidation of resolutions sys.runQueuedTimeoutCallbacks(); // Actual update } - const changeModuleFileToModuleFile1: ts.tscWatch.TscWatchCompileChange = { + const changeModuleFileToModuleFile1: TscWatchCompileChange = { caption: "Rename moduleFile to moduleFile1", change: sys => { sys.renameFile("/a/b/moduleFile.ts", "/a/b/moduleFile1.ts"); @@ -834,13 +845,13 @@ declare const eval: any` }, timeouts: runQueuedTimeoutCallbacksTwice }; - const changeModuleFile1ToModuleFile: ts.tscWatch.TscWatchCompileChange = { + const changeModuleFile1ToModuleFile: TscWatchCompileChange = { caption: "Rename moduleFile1 back to moduleFile", change: sys => sys.renameFile("/a/b/moduleFile1.ts", "/a/b/moduleFile.ts"), timeouts: runQueuedTimeoutCallbacksTwice, }; - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "rename a module file and rename back should restore the states for inferred projects", commandLineArgs: ["-w", "/a/b/file1.ts"], @@ -853,7 +864,7 @@ declare const eval: any` path: "/a/b/file1.ts", content: 'import * as T from "./moduleFile"; T.bar();' }; - return ts.tscWatch.createWatchedSystem([moduleFile, file1, ts.tscWatch.libFile]); + return createWatchedSystem([moduleFile, file1, libFile]); }, changes: [ changeModuleFileToModuleFile1, @@ -861,7 +872,7 @@ declare const eval: any` ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "rename a module file and rename back should restore the states for configured projects", commandLineArgs: ["-w", "-p", configFilePath], @@ -874,7 +885,7 @@ declare const eval: any` path: "/a/b/file1.ts", content: 'import * as T from "./moduleFile"; T.bar();' }; - return ts.tscWatch.createWatchedSystem([moduleFile, file1, configFile, ts.tscWatch.libFile]); + return createWatchedSystem([moduleFile, file1, configFile, libFile]); }, changes: [ changeModuleFileToModuleFile1, @@ -882,7 +893,7 @@ declare const eval: any` ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "types should load from config file path if config exists", commandLineArgs: ["-w", "-p", configFilePath], @@ -902,12 +913,12 @@ declare const eval: any` const cwd = { path: "/a/c" }; - return ts.tscWatch.createWatchedSystem([f1, config, node, cwd, ts.tscWatch.libFile], { currentDirectory: cwd.path }); + return createWatchedSystem([f1, config, node, cwd, libFile], { currentDirectory: cwd.path }); }, - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "add the missing module file for inferred project-should remove the module not found error", commandLineArgs: ["-w", "/a/b/file1.ts"], @@ -916,7 +927,7 @@ declare const eval: any` path: "/a/b/file1.ts", content: 'import * as T from "./moduleFile"; T.bar();' }; - return ts.tscWatch.createWatchedSystem([file1, ts.tscWatch.libFile]); + return createWatchedSystem([file1, libFile]); }, changes: [ { @@ -927,7 +938,7 @@ declare const eval: any` ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "Configure file diagnostics events are generated when the config file has errors", commandLineArgs: ["-w", "-p", configFilePath], @@ -945,12 +956,12 @@ declare const eval: any` } }` }; - return ts.tscWatch.createWatchedSystem([file, configFile, ts.tscWatch.libFile]); + return createWatchedSystem([file, configFile, libFile]); }, - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "if config file doesnt have errors, they are not reported", commandLineArgs: ["-w", "-p", configFilePath], @@ -965,12 +976,12 @@ declare const eval: any` "compilerOptions": {} }` }; - return ts.tscWatch.createWatchedSystem([file, configFile, ts.tscWatch.libFile]); + return createWatchedSystem([file, configFile, libFile]); }, - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "Reports errors when the config file changes", commandLineArgs: ["-w", "-p", configFilePath], @@ -979,7 +990,7 @@ declare const eval: any` path: "/a/b/app.ts", content: "let x = 10" }; - return ts.tscWatch.createWatchedSystem([file, configFile, ts.tscWatch.libFile]); + return createWatchedSystem([file, configFile, libFile]); }, changes: [ { @@ -989,7 +1000,7 @@ declare const eval: any` "haha": 123 } }`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }, { caption: "change config file to remove error", @@ -997,12 +1008,12 @@ declare const eval: any` "compilerOptions": { } }`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "non-existing directories listed in config file input array should be tolerated without crashing the server", commandLineArgs: ["-w", "-p", configFilePath], @@ -1018,12 +1029,12 @@ declare const eval: any` path: "/a/b/file1.ts", content: "let t = 10;" }; - return ts.tscWatch.createWatchedSystem([file1, configFile, ts.tscWatch.libFile]); + return createWatchedSystem([file1, configFile, libFile]); }, - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "non-existing directories listed in config file input array should be able to handle @types if input file list is empty", commandLineArgs: ["-w", "-p", "/a/tsconfig.json"], @@ -1047,9 +1058,9 @@ declare const eval: any` path: "/a/node_modules/@types/typings/lib.d.ts", content: `export const x: number` }; - return ts.tscWatch.createWatchedSystem([f, config, t1, t2, ts.tscWatch.libFile], { currentDirectory: ts.getDirectoryPath(f.path) }); + return createWatchedSystem([f, config, t1, t2, libFile], { currentDirectory: getDirectoryPath(f.path) }); }, - changes: ts.emptyArray + changes: emptyArray }); it("should support files without extensions", () => { @@ -1057,15 +1068,15 @@ declare const eval: any` path: "/a/compile", content: "let x = 1" }; - const { sys, baseline, oldSnap, cb, getPrograms } = ts.tscWatch.createBaseline(ts.tscWatch.createWatchedSystem([f, ts.tscWatch.libFile])); - const watch = ts.createWatchProgram(ts.tscWatch.createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({ + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([f, libFile])); + const watch = createWatchProgram(createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({ rootFiles: [f.path], system: sys, options: { allowNonTsExtensions: true }, cb, watchOptions: undefined })); - ts.tscWatch.runWatchBaseline({ + runWatchBaseline({ scenario, subScenario: "should support files without extensions", commandLineArgs: ["--w", f.path], @@ -1073,12 +1084,12 @@ declare const eval: any` baseline, oldSnap, getPrograms, - changes: ts.emptyArray, + changes: emptyArray, watchOrSolution: watch }); }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "Options Diagnostic locations reported correctly with changes in configFile contents when options change", commandLineArgs: ["-w", "-p", configFilePath], @@ -1099,7 +1110,7 @@ declare const eval: any` } }` }; - return ts.tscWatch.createWatchedSystem([file, ts.tscWatch.libFile, configFile]); + return createWatchedSystem([file, libFile, configFile]); }, changes: [ { @@ -1111,81 +1122,81 @@ declare const eval: any` "mapRoot": "./" } }`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, } ] }); describe("should not trigger recompilation because of program emit", () => { - function verifyWithOptions(subScenario: string, options: ts.CompilerOptions) { - ts.tscWatch.verifyTscWatch({ + function verifyWithOptions(subScenario: string, options: CompilerOptions) { + verifyTscWatch({ scenario, subScenario: `should not trigger recompilation because of program emit/${subScenario}`, - commandLineArgs: ["-w", "-p", `${ts.tscWatch.projectRoot}/tsconfig.json`], + commandLineArgs: ["-w", "-p", `${projectRoot}/tsconfig.json`], sys: () => { - const file1: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/file1.ts`, + const file1: File = { + path: `${projectRoot}/file1.ts`, content: "export const c = 30;" }; - const file2: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/src/file2.ts`, + const file2: File = { + path: `${projectRoot}/src/file2.ts`, content: `import {c} from "file1"; export const d = 30;` }; - const tsconfig: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, - content: ts.generateTSConfig(options, ts.emptyArray, "\n") + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, + content: generateTSConfig(options, emptyArray, "\n") }; - return ts.tscWatch.createWatchedSystem([file1, file2, ts.tscWatch.libFile, tsconfig], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([file1, file2, libFile, tsconfig], { currentDirectory: projectRoot }); }, changes: [ - ts.tscWatch.noopChange, + noopChange, { caption: "Add new file", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/src/file3.ts`, `export const y = 10;`), + change: sys => sys.writeFile(`${projectRoot}/src/file3.ts`, `export const y = 10;`), timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2), // To update program and failed lookups }, - ts.tscWatch.noopChange, + noopChange, ] }); } verifyWithOptions( "without outDir or outFile is specified", - { module: ts.ModuleKind.AMD } + { module: ModuleKind.AMD } ); verifyWithOptions( "with outFile", - { module: ts.ModuleKind.AMD, outFile: "build/outFile.js" } + { module: ModuleKind.AMD, outFile: "build/outFile.js" } ); verifyWithOptions( "when outDir is specified", - { module: ts.ModuleKind.AMD, outDir: "build" } + { module: ModuleKind.AMD, outDir: "build" } ); verifyWithOptions( "without outDir or outFile is specified with declaration enabled", - { module: ts.ModuleKind.AMD, declaration: true } + { module: ModuleKind.AMD, declaration: true } ); verifyWithOptions( "when outDir and declarationDir is specified", - { module: ts.ModuleKind.AMD, outDir: "build", declaration: true, declarationDir: "decls" } + { module: ModuleKind.AMD, outDir: "build", declaration: true, declarationDir: "decls" } ); verifyWithOptions( "declarationDir is specified", - { module: ts.ModuleKind.AMD, declaration: true, declarationDir: "decls" } + { module: ModuleKind.AMD, declaration: true, declarationDir: "decls" } ); }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "shouldnt report error about unused function incorrectly when file changes from global to module", commandLineArgs: ["-w", "/a/b/file.ts", "--noUnusedLocals"], sys: () => { - const file: ts.tscWatch.File = { + const file: File = { path: "/a/b/file.ts", content: `function one() {} function two() { @@ -1194,7 +1205,7 @@ function two() { } }` }; - return ts.tscWatch.createWatchedSystem([file, ts.tscWatch.libFile]); + return createWatchedSystem([file, libFile]); }, changes: [ { @@ -1205,64 +1216,64 @@ export function two() { one(); } }`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "watched files when file is deleted and new file is added as part of change", commandLineArgs: ["-w", "-p", "/home/username/project/tsconfig.json"], sys: () => { const projectLocation = "/home/username/project"; - const file: ts.tscWatch.File = { + const file: File = { path: `${projectLocation}/src/file1.ts`, content: "var a = 10;" }; - const configFile: ts.tscWatch.File = { + const configFile: File = { path: `${projectLocation}/tsconfig.json`, content: "{}" }; - return ts.tscWatch.createWatchedSystem([file, ts.tscWatch.libFile, configFile]); + return createWatchedSystem([file, libFile, configFile]); }, changes: [ { caption: "Rename file1 to file2", change: sys => sys.renameFile("/home/username/project/src/file1.ts", "/home/username/project/src/file2.ts"), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, } ] }); - function changeParameterTypeOfBFile(parameterName: string, toType: string): ts.tscWatch.TscWatchCompileChange { + function changeParameterTypeOfBFile(parameterName: string, toType: string): TscWatchCompileChange { return { caption: `Changed ${parameterName} type to ${toType}`, - change: sys => ts.tscWatch.replaceFileText(sys, `${ts.tscWatch.projectRoot}/b.ts`, new RegExp(`${parameterName}\: [a-z]*`), `${parameterName}: ${toType}`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => replaceFileText(sys, `${projectRoot}/b.ts`, new RegExp(`${parameterName}\: [a-z]*`), `${parameterName}: ${toType}`), + timeouts: runQueuedTimeoutCallbacks, }; } - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "updates errors correctly when declaration emit is disabled in compiler options", commandLineArgs: ["-w"], sys: () => { - const aFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const aFile: File = { + path: `${projectRoot}/a.ts`, content: `import test from './b'; test(4, 5);` }; - const bFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/b.ts`, + const bFile: File = { + path: `${projectRoot}/b.ts`, content: `function test(x: number, y: number) { return x + y / 5; } export default test;` }; - const tsconfigFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const tsconfigFile: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { module: "commonjs", @@ -1271,7 +1282,7 @@ export default test;` } }) }; - return ts.tscWatch.createWatchedSystem([aFile, bFile, ts.tscWatch.libFile, tsconfigFile], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([aFile, bFile, libFile, tsconfigFile], { currentDirectory: projectRoot }); }, changes: [ changeParameterTypeOfBFile("x", "string"), @@ -1281,48 +1292,48 @@ export default test;` ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "updates errors when strictNullChecks changes", commandLineArgs: ["-w"], sys: () => { - const aFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const aFile: File = { + path: `${projectRoot}/a.ts`, content: `declare function foo(): null | { hello: any }; foo().hello` }; - const config: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: {} }) }; - return ts.tscWatch.createWatchedSystem([aFile, config, ts.tscWatch.libFile], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([aFile, config, libFile], { currentDirectory: projectRoot }); }, changes: [ { caption: "Enable strict null checks", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: { strictNullChecks: true } })), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => sys.writeFile(`${projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: { strictNullChecks: true } })), + timeouts: runQueuedTimeoutCallbacks, }, { caption: "Set always strict false", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: { strict: true, alwaysStrict: false } })), // Avoid changing 'alwaysStrict' or must re-bind - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => sys.writeFile(`${projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: { strict: true, alwaysStrict: false } })), // Avoid changing 'alwaysStrict' or must re-bind + timeouts: runQueuedTimeoutCallbacks, }, { caption: "Disable strict", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: {} })), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => sys.writeFile(`${projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: {} })), + timeouts: runQueuedTimeoutCallbacks, }, ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "updates errors when noErrorTruncation changes", commandLineArgs: ["-w"], sys: () => { - const aFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const aFile: File = { + path: `${projectRoot}/a.ts`, content: `declare var v: { reallyLongPropertyName1: string | number | boolean | object | symbol | bigint; reallyLongPropertyName2: string | number | boolean | object | symbol | bigint; @@ -1334,172 +1345,172 @@ foo().hello` }; v === 'foo';` }; - const config: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: {} }) }; - return ts.tscWatch.createWatchedSystem([aFile, config, ts.tscWatch.libFile], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([aFile, config, libFile], { currentDirectory: projectRoot }); }, changes: [ { caption: "Enable noErrorTruncation", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: { noErrorTruncation: true } })), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => sys.writeFile(`${projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: { noErrorTruncation: true } })), + timeouts: runQueuedTimeoutCallbacks, }, ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "updates diagnostics and emit when useDefineForClassFields changes", commandLineArgs: ["-w"], sys: () => { - const aFile: ts.tscWatch.File = { + const aFile: File = { path: `/a.ts`, content: `class C { get prop() { return 1; } } class D extends C { prop = 1; }` }; - const config: ts.tscWatch.File = { + const config: File = { path: `/tsconfig.json`, content: JSON.stringify({ compilerOptions: { target: "es6" } }) }; - return ts.tscWatch.createWatchedSystem([aFile, config, ts.tscWatch.libFile]); + return createWatchedSystem([aFile, config, libFile]); }, changes: [ { caption: "Enable useDefineForClassFields", change: sys => sys.writeFile(`/tsconfig.json`, JSON.stringify({ compilerOptions: { target: "es6", useDefineForClassFields: true } })), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }, ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "updates errors and emit when importsNotUsedAsValues changes", commandLineArgs: ["-w"], sys: () => { - const aFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const aFile: File = { + path: `${projectRoot}/a.ts`, content: `export class C {}` }; - const bFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/b.ts`, + const bFile: File = { + path: `${projectRoot}/b.ts`, content: `import {C} from './a'; export function f(p: C) { return p; }` }; - const config: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: {} }) }; - return ts.tscWatch.createWatchedSystem([aFile, bFile, config, ts.tscWatch.libFile], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([aFile, bFile, config, libFile], { currentDirectory: projectRoot }); }, changes: [ { caption: 'Set to "remove"', - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: { importsNotUsedAsValues: "remove" } })), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => sys.writeFile(`${projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: { importsNotUsedAsValues: "remove" } })), + timeouts: runQueuedTimeoutCallbacks, }, { caption: 'Set to "error"', - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: { importsNotUsedAsValues: "error" } })), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => sys.writeFile(`${projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: { importsNotUsedAsValues: "error" } })), + timeouts: runQueuedTimeoutCallbacks, }, { caption: 'Set to "preserve"', - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: { importsNotUsedAsValues: "preserve" } })), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => sys.writeFile(`${projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: { importsNotUsedAsValues: "preserve" } })), + timeouts: runQueuedTimeoutCallbacks, }, ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "updates errors when forceConsistentCasingInFileNames changes", commandLineArgs: ["-w"], sys: () => { - const aFile: ts.tscWatch.File = { + const aFile: File = { path: `/a.ts`, content: `export class C {}` }; - const bFile: ts.tscWatch.File = { + const bFile: File = { path: `/b.ts`, content: `import {C} from './a'; import * as A from './A';` }; - const config: ts.tscWatch.File = { + const config: File = { path: `/tsconfig.json`, content: JSON.stringify({ compilerOptions: {} }) }; - return ts.tscWatch.createWatchedSystem([aFile, bFile, config, ts.tscWatch.libFile], { useCaseSensitiveFileNames: false }); + return createWatchedSystem([aFile, bFile, config, libFile], { useCaseSensitiveFileNames: false }); }, changes: [ { caption: "Enable forceConsistentCasingInFileNames", change: sys => sys.writeFile(`/tsconfig.json`, JSON.stringify({ compilerOptions: { forceConsistentCasingInFileNames: true } })), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }, ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "updates moduleResolution when resolveJsonModule changes", commandLineArgs: ["-w"], sys: () => { - const aFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const aFile: File = { + path: `${projectRoot}/a.ts`, content: `import * as data from './data.json'` }; - const jsonFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/data.json`, + const jsonFile: File = { + path: `${projectRoot}/data.json`, content: `{ "foo": 1 }` }; - const config: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { moduleResolution: "node" } }) }; - return ts.tscWatch.createWatchedSystem([aFile, jsonFile, config, ts.tscWatch.libFile], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([aFile, jsonFile, config, libFile], { currentDirectory: projectRoot }); }, changes: [ { caption: "Enable resolveJsonModule", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: { moduleResolution: "node", resolveJsonModule: true } })), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => sys.writeFile(`${projectRoot}/tsconfig.json`, JSON.stringify({ compilerOptions: { moduleResolution: "node", resolveJsonModule: true } })), + timeouts: runQueuedTimeoutCallbacks, }, ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "updates errors when ambient modules of program changes", commandLineArgs: ["-w"], sys: () => { - const aFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const aFile: File = { + path: `${projectRoot}/a.ts`, content: `declare module 'a' { type foo = number; }` }; - const config: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: "{}" }; - return ts.tscWatch.createWatchedSystem([aFile, config, ts.tscWatch.libFile], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([aFile, config, libFile], { currentDirectory: projectRoot }); }, changes: [ { caption: "Create b.ts with same content", // Create bts with same file contents - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/b.ts`, `declare module 'a' { + change: sys => sys.writeFile(`${projectRoot}/b.ts`, `declare module 'a' { type foo = number; }`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }, { caption: "Delete b.ts", - change: sys => sys.deleteFile(`${ts.tscWatch.projectRoot}/b.ts`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => sys.deleteFile(`${projectRoot}/b.ts`), + timeouts: runQueuedTimeoutCallbacks, }, ] }); @@ -1510,44 +1521,44 @@ export function f(p: C) { return p; }` ${field}: boolean; }`; - const libFileWithDocument: ts.tscWatch.File = { - path: ts.tscWatch.libFile.path, - content: `${ts.tscWatch.libFile.content} + const libFileWithDocument: File = { + path: libFile.path, + content: `${libFile.content} interface Document { readonly ${field}: boolean; }` }; - function verifyLibFileErrorsWith(subScenario: string, aFile: ts.tscWatch.File) { + function verifyLibFileErrorsWith(subScenario: string, aFile: File) { function verifyLibErrors(subScenario: string, commandLineOptions: readonly string[]) { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: `updates errors in lib file/${subScenario}`, commandLineArgs: ["-w", aFile.path, ...commandLineOptions], - sys: () => ts.tscWatch.createWatchedSystem([aFile, libFileWithDocument], { currentDirectory: ts.tscWatch.projectRoot }), + sys: () => createWatchedSystem([aFile, libFileWithDocument], { currentDirectory: projectRoot }), changes: [ { caption: "Remove document declaration from file", change: sys => sys.writeFile(aFile.path, aFile.content.replace(fieldWithoutReadonly, "var x: string;")), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }, { caption: "Rever the file to contain document declaration", change: sys => sys.writeFile(aFile.path, aFile.content), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }, ] }); } - verifyLibErrors(`${subScenario}/with default options`, ts.emptyArray); + verifyLibErrors(`${subScenario}/with default options`, emptyArray); verifyLibErrors(`${subScenario}/with skipLibCheck`, ["--skipLibCheck"]); verifyLibErrors(`${subScenario}/with skipDefaultLibCheck`, ["--skipDefaultLibCheck"]); } describe("when non module file changes", () => { - const aFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const aFile: File = { + path: `${projectRoot}/a.ts`, content: `${fieldWithoutReadonly} var y: number;` }; @@ -1555,8 +1566,8 @@ var y: number;` }); describe("when module file with global definitions changes", () => { - const aFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const aFile: File = { + path: `${projectRoot}/a.ts`, content: `export {} declare global { ${fieldWithoutReadonly} @@ -1567,45 +1578,45 @@ var y: number; }); }); - function changeWhenLibCheckChanges(compilerOptions: ts.CompilerOptions): ts.tscWatch.TscWatchCompileChange { + function changeWhenLibCheckChanges(compilerOptions: CompilerOptions): TscWatchCompileChange { const configFileContent = JSON.stringify({ compilerOptions }); return { caption: `Changing config to ${configFileContent}`, - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/tsconfig.json`, configFileContent), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => sys.writeFile(`${projectRoot}/tsconfig.json`, configFileContent), + timeouts: runQueuedTimeoutCallbacks, }; } - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "when skipLibCheck and skipDefaultLibCheck changes", commandLineArgs: ["-w"], sys: () => { const field = "fullscreen"; - const aFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const aFile: File = { + path: `${projectRoot}/a.ts`, content: `interface Document { ${field}: boolean; }` }; - const bFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/b.d.ts`, + const bFile: File = { + path: `${projectRoot}/b.d.ts`, content: `interface Document { ${field}: boolean; }` }; - const libFileWithDocument: ts.tscWatch.File = { - path: ts.tscWatch.libFile.path, - content: `${ts.tscWatch.libFile.content} + const libFileWithDocument: File = { + path: libFile.path, + content: `${libFile.content} interface Document { readonly ${field}: boolean; }` }; - const configFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const configFile: File = { + path: `${projectRoot}/tsconfig.json`, content: "{}" }; - return ts.tscWatch.createWatchedSystem([aFile, bFile, configFile, libFileWithDocument], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([aFile, bFile, configFile, libFileWithDocument], { currentDirectory: projectRoot }); }, changes: [ changeWhenLibCheckChanges({ skipLibCheck: true }), @@ -1617,54 +1628,54 @@ interface Document { ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "reports errors correctly with isolatedModules", commandLineArgs: ["-w"], sys: () => { - const aFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const aFile: File = { + path: `${projectRoot}/a.ts`, content: `export const a: string = "";` }; - const bFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/b.ts`, + const bFile: File = { + path: `${projectRoot}/b.ts`, content: `import { a } from "./a"; const b: string = a;` }; - const configFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const configFile: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { isolatedModules: true } }) }; - return ts.tscWatch.createWatchedSystem([aFile, bFile, configFile, ts.tscWatch.libFile], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([aFile, bFile, configFile, libFile], { currentDirectory: projectRoot }); }, changes: [ { caption: "Change shape of a", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/a.ts`, `export const a: number = 1`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => sys.writeFile(`${projectRoot}/a.ts`, `export const a: number = 1`), + timeouts: runQueuedTimeoutCallbacks, }, ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "reports errors correctly with file not in rootDir", commandLineArgs: ["-w"], sys: () => { - const aFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const aFile: File = { + path: `${projectRoot}/a.ts`, content: `import { x } from "../b";` }; - const bFile: ts.tscWatch.File = { + const bFile: File = { path: `/user/username/projects/b.ts`, content: `export const x = 10;` }; - const configFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const configFile: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { rootDir: ".", @@ -1672,53 +1683,53 @@ const b: string = a;` } }) }; - return ts.tscWatch.createWatchedSystem([aFile, bFile, configFile, ts.tscWatch.libFile], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([aFile, bFile, configFile, libFile], { currentDirectory: projectRoot }); }, changes: [ { caption: "Make changes to file a", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/a.ts`, ` + change: sys => sys.writeFile(`${projectRoot}/a.ts`, ` import { x } from "../b";`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }, ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "updates emit on jsx option change", commandLineArgs: ["-w"], sys: () => { - const index: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/index.tsx`, + const index: File = { + path: `${projectRoot}/index.tsx`, content: `declare var React: any;\nconst d =
;` }; - const configFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const configFile: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { jsx: "preserve" } }) }; - return ts.tscWatch.createWatchedSystem([index, configFile, ts.tscWatch.libFile], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([index, configFile, libFile], { currentDirectory: projectRoot }); }, changes: [ { caption: "Update 'jsx' to 'react'", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/tsconfig.json`, '{ "compilerOptions": { "jsx": "react" } }'), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => sys.writeFile(`${projectRoot}/tsconfig.json`, '{ "compilerOptions": { "jsx": "react" } }'), + timeouts: runQueuedTimeoutCallbacks, }, ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "extended source files are watched", commandLineArgs: ["-w", "-p", configFilePath], sys: () => { - const firstExtendedConfigFile: ts.tscWatch.File = { + const firstExtendedConfigFile: File = { path: "/a/b/first.tsconfig.json", content: JSON.stringify({ compilerOptions: { @@ -1726,21 +1737,21 @@ import { x } from "../b";`), } }) }; - const secondExtendedConfigFile: ts.tscWatch.File = { + const secondExtendedConfigFile: File = { path: "/a/b/second.tsconfig.json", content: JSON.stringify({ extends: "./first.tsconfig.json" }) }; - const configFile: ts.tscWatch.File = { + const configFile: File = { path: configFilePath, content: JSON.stringify({ compilerOptions: {}, - files: [ts.tscWatch.commonFile1.path, ts.tscWatch.commonFile2.path] + files: [commonFile1.path, commonFile2.path] }) }; - return ts.tscWatch.createWatchedSystem([ - ts.tscWatch.libFile, ts.tscWatch.commonFile1, ts.tscWatch.commonFile2, configFile, firstExtendedConfigFile, secondExtendedConfigFile + return createWatchedSystem([ + libFile, commonFile1, commonFile2, configFile, firstExtendedConfigFile, secondExtendedConfigFile ]); }, changes: [ @@ -1749,9 +1760,9 @@ import { x } from "../b";`), change: sys => sys.modifyFile(configFilePath, JSON.stringify({ extends: "./second.tsconfig.json", compilerOptions: {}, - files: [ts.tscWatch.commonFile1.path, ts.tscWatch.commonFile2.path] + files: [commonFile1.path, commonFile2.path] })), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "Change first extended config", @@ -1760,7 +1771,7 @@ import { x } from "../b";`), strict: false, } })), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "Change second extended config", @@ -1770,38 +1781,38 @@ import { x } from "../b";`), strictNullChecks: true, } })), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "Change config to stop extending another config", change: sys => sys.modifyFile(configFilePath, JSON.stringify({ compilerOptions: {}, - files: [ts.tscWatch.commonFile1.path, ts.tscWatch.commonFile2.path] + files: [commonFile1.path, commonFile2.path] })), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }, ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "when creating new file in symlinked folder", commandLineArgs: ["-w", "-p", ".", "--extendedDiagnostics"], sys: () => { - const module1: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/client/folder1/module1.ts`, + const module1: File = { + path: `${projectRoot}/client/folder1/module1.ts`, content: `export class Module1Class { }` }; - const module2: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/folder2/module2.ts`, + const module2: File = { + path: `${projectRoot}/folder2/module2.ts`, content: `import * as M from "folder1/module1";` }; - const symlink: ts.tscWatch.SymLink = { - path: `${ts.tscWatch.projectRoot}/client/linktofolder2`, - symLink: `${ts.tscWatch.projectRoot}/folder2`, + const symlink: SymLink = { + path: `${projectRoot}/client/linktofolder2`, + symLink: `${projectRoot}/folder2`, }; - const config: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { baseUrl: "client", @@ -1810,24 +1821,24 @@ import { x } from "../b";`), include: ["client/**/*", "folder2"] }) }; - return ts.tscWatch.createWatchedSystem([module1, module2, symlink, config, ts.tscWatch.libFile], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([module1, module2, symlink, config, libFile], { currentDirectory: projectRoot }); }, changes: [ { caption: "Add module3 to folder2", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/client/linktofolder2/module3.ts`, `import * as M from "folder1/module1";`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.writeFile(`${projectRoot}/client/linktofolder2/module3.ts`, `import * as M from "folder1/module1";`), + timeouts: checkSingleTimeoutQueueLengthAndRun, }, ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "when new file is added to the referenced project", - commandLineArgs: ["-w", "-p", `${ts.tscWatch.projectRoot}/projects/project2/tsconfig.json`, "--extendedDiagnostics"], + commandLineArgs: ["-w", "-p", `${projectRoot}/projects/project2/tsconfig.json`, "--extendedDiagnostics"], sys: () => { - const config1: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/projects/project1/tsconfig.json`, + const config1: File = { + path: `${projectRoot}/projects/project1/tsconfig.json`, content: JSON.stringify({ compilerOptions: { module: "none", @@ -1836,17 +1847,17 @@ import { x } from "../b";`), exclude: ["temp"] }) }; - const class1: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/projects/project1/class1.ts`, + const class1: File = { + path: `${projectRoot}/projects/project1/class1.ts`, content: `class class1 {}` }; // Built file - const class1Dt: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/projects/project1/class1.d.ts`, + const class1Dt: File = { + path: `${projectRoot}/projects/project1/class1.d.ts`, content: `declare class class1 {}` }; - const config2: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/projects/project2/tsconfig.json`, + const config2: File = { + path: `${projectRoot}/projects/project2/tsconfig.json`, content: JSON.stringify({ compilerOptions: { module: "none", @@ -1857,61 +1868,61 @@ import { x } from "../b";`), ] }) }; - const class2: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/projects/project2/class2.ts`, + const class2: File = { + path: `${projectRoot}/projects/project2/class2.ts`, content: `class class2 {}` }; - return ts.tscWatch.createWatchedSystem([config1, class1, config2, class2, ts.tscWatch.libFile, class1Dt]); + return createWatchedSystem([config1, class1, config2, class2, libFile, class1Dt]); }, changes: [ { caption: "Add class3 to project1", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/projects/project1/class3.ts`, `class class3 {}`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.writeFile(`${projectRoot}/projects/project1/class3.ts`, `class class3 {}`), + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "Add output of class3", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.writeFile(`${projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`), + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "Add excluded file to project1", - change: sys => sys.ensureFileOrFolder({ path: `${ts.tscWatch.projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }), + change: sys => sys.ensureFileOrFolder({ path: `${projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }), timeouts: sys => sys.checkTimeoutQueueLength(0), }, { caption: "Delete output of class3", - change: sys => sys.deleteFile(`${ts.tscWatch.projectRoot}/projects/project1/class3.d.ts`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.deleteFile(`${projectRoot}/projects/project1/class3.d.ts`), + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "Add output of class3", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.writeFile(`${projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`), + timeouts: checkSingleTimeoutQueueLengthAndRun, }, ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "when creating extensionless file", commandLineArgs: ["-w", "-p", ".", "--extendedDiagnostics"], sys: () => { - const module1: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/index.ts`, + const module1: File = { + path: `${projectRoot}/index.ts`, content: `` }; - const config: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: `{}` }; - return ts.tscWatch.createWatchedSystem([module1, config, ts.tscWatch.libFile], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([module1, config, libFile], { currentDirectory: projectRoot }); }, changes: [ { caption: "Create foo in project root", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/foo`, ``), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.writeFile(`${projectRoot}/foo`, ``), + timeouts: checkSingleTimeoutQueueLengthAndRun, }, ] }); diff --git a/src/testRunner/unittests/tscWatch/projectsWithReferences.ts b/src/testRunner/unittests/tscWatch/projectsWithReferences.ts index b02aec9329448..1a720d0ac4015 100644 --- a/src/testRunner/unittests/tscWatch/projectsWithReferences.ts +++ b/src/testRunner/unittests/tscWatch/projectsWithReferences.ts @@ -1,194 +1,201 @@ -import * as ts from "../../_namespaces/ts"; +import { emptyArray } from "../../../compiler/core"; +import { + getTsBuildProjectFile, getTsBuildProjectFilePath, tsbuildProjectsLocation, +} from "../../../harness/virtualFileSystemWithWatch"; +import { + checkSingleTimeoutQueueLengthAndRun, createSolutionBuilder, createSystemWithSolutionBuild, libFile, verifyTscWatch, + WatchedSystem, +} from "./helpers"; describe("unittests:: tsc-watch:: projects with references: invoking when references are already built", () => { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "projectsWithReferences", subScenario: "on sample project", - sys: () => ts.tscWatch.createSystemWithSolutionBuild( + sys: () => createSystemWithSolutionBuild( ["tests"], [ - ts.tscWatch.libFile, - ts.TestFSWithWatch.getTsBuildProjectFile("sample1", "core/tsconfig.json"), - ts.TestFSWithWatch.getTsBuildProjectFile("sample1", "core/index.ts"), - ts.TestFSWithWatch.getTsBuildProjectFile("sample1", "core/anotherModule.ts"), - ts.TestFSWithWatch.getTsBuildProjectFile("sample1", "core/some_decl.d.ts"), - ts.TestFSWithWatch.getTsBuildProjectFile("sample1", "logic/tsconfig.json"), - ts.TestFSWithWatch.getTsBuildProjectFile("sample1", "logic/index.ts"), - ts.TestFSWithWatch.getTsBuildProjectFile("sample1", "tests/tsconfig.json"), - ts.TestFSWithWatch.getTsBuildProjectFile("sample1", "tests/index.ts"), + libFile, + getTsBuildProjectFile("sample1", "core/tsconfig.json"), + getTsBuildProjectFile("sample1", "core/index.ts"), + getTsBuildProjectFile("sample1", "core/anotherModule.ts"), + getTsBuildProjectFile("sample1", "core/some_decl.d.ts"), + getTsBuildProjectFile("sample1", "logic/tsconfig.json"), + getTsBuildProjectFile("sample1", "logic/index.ts"), + getTsBuildProjectFile("sample1", "tests/tsconfig.json"), + getTsBuildProjectFile("sample1", "tests/index.ts"), ], - { currentDirectory: `${ts.TestFSWithWatch.tsbuildProjectsLocation}/sample1` } + { currentDirectory: `${tsbuildProjectsLocation}/sample1` } ), commandLineArgs: ["-w", "-p", "tests"], changes: [ { caption: "local edit in logic ts, and build logic", change: sys => { - sys.appendFile(ts.TestFSWithWatch.getTsBuildProjectFilePath("sample1", "logic/index.ts"), `function foo() { }`); - const solutionBuilder = ts.tscWatch.createSolutionBuilder(sys, ["logic"]); + sys.appendFile(getTsBuildProjectFilePath("sample1", "logic/index.ts"), `function foo() { }`); + const solutionBuilder = createSolutionBuilder(sys, ["logic"]); solutionBuilder.build(); }, // not ideal, but currently because of d.ts but no new file is written // There will be timeout queued even though file contents are same - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "non local edit in logic ts, and build logic", change: sys => { - sys.appendFile(ts.TestFSWithWatch.getTsBuildProjectFilePath("sample1", "logic/index.ts"), `export function gfoo() { }`); - const solutionBuilder = ts.tscWatch.createSolutionBuilder(sys, ["logic"]); + sys.appendFile(getTsBuildProjectFilePath("sample1", "logic/index.ts"), `export function gfoo() { }`); + const solutionBuilder = createSolutionBuilder(sys, ["logic"]); solutionBuilder.build(); }, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "change in project reference config file builds correctly", change: sys => { - sys.writeFile(ts.TestFSWithWatch.getTsBuildProjectFilePath("sample1", "logic/tsconfig.json"), JSON.stringify({ + sys.writeFile(getTsBuildProjectFilePath("sample1", "logic/tsconfig.json"), JSON.stringify({ compilerOptions: { composite: true, declaration: true, declarationDir: "decls" }, references: [{ path: "../core" }] })); - const solutionBuilder = ts.tscWatch.createSolutionBuilder(sys, ["logic"]); + const solutionBuilder = createSolutionBuilder(sys, ["logic"]); solutionBuilder.build(); }, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + timeouts: checkSingleTimeoutQueueLengthAndRun }, ], baselineDependencies: true }); - function changeCompilerOpitonsPaths(sys: ts.tscWatch.WatchedSystem, config: string, newPaths: object) { + function changeCompilerOpitonsPaths(sys: WatchedSystem, config: string, newPaths: object) { const configJson = JSON.parse(sys.readFile(config)!); configJson.compilerOptions.paths = newPaths; sys.writeFile(config, JSON.stringify(configJson)); } - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "projectsWithReferences", subScenario: "on transitive references", - sys: () => ts.tscWatch.createSystemWithSolutionBuild( + sys: () => createSystemWithSolutionBuild( ["tsconfig.c.json"], [ - ts.tscWatch.libFile, - ts.TestFSWithWatch.getTsBuildProjectFile("transitiveReferences", "tsconfig.a.json"), - ts.TestFSWithWatch.getTsBuildProjectFile("transitiveReferences", "tsconfig.b.json"), - ts.TestFSWithWatch.getTsBuildProjectFile("transitiveReferences", "tsconfig.c.json"), - ts.TestFSWithWatch.getTsBuildProjectFile("transitiveReferences", "a.ts"), - ts.TestFSWithWatch.getTsBuildProjectFile("transitiveReferences", "b.ts"), - ts.TestFSWithWatch.getTsBuildProjectFile("transitiveReferences", "c.ts"), - ts.TestFSWithWatch.getTsBuildProjectFile("transitiveReferences", "refs/a.d.ts"), + libFile, + getTsBuildProjectFile("transitiveReferences", "tsconfig.a.json"), + getTsBuildProjectFile("transitiveReferences", "tsconfig.b.json"), + getTsBuildProjectFile("transitiveReferences", "tsconfig.c.json"), + getTsBuildProjectFile("transitiveReferences", "a.ts"), + getTsBuildProjectFile("transitiveReferences", "b.ts"), + getTsBuildProjectFile("transitiveReferences", "c.ts"), + getTsBuildProjectFile("transitiveReferences", "refs/a.d.ts"), ], - { currentDirectory: `${ts.TestFSWithWatch.tsbuildProjectsLocation}/transitiveReferences` } + { currentDirectory: `${tsbuildProjectsLocation}/transitiveReferences` } ), commandLineArgs: ["-w", "-p", "tsconfig.c.json"], changes: [ { caption: "non local edit b ts, and build b", change: sys => { - sys.appendFile(ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b.ts"), `export function gfoo() { }`); - const solutionBuilder = ts.tscWatch.createSolutionBuilder(sys, ["tsconfig.b.json"]); + sys.appendFile(getTsBuildProjectFilePath("transitiveReferences", "b.ts"), `export function gfoo() { }`); + const solutionBuilder = createSolutionBuilder(sys, ["tsconfig.b.json"]); solutionBuilder.build(); }, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "edit on config file", change: sys => { sys.ensureFileOrFolder({ - path: ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "nrefs/a.d.ts"), - content: sys.readFile(ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "refs/a.d.ts"))! + path: getTsBuildProjectFilePath("transitiveReferences", "nrefs/a.d.ts"), + content: sys.readFile(getTsBuildProjectFilePath("transitiveReferences", "refs/a.d.ts"))! }); - changeCompilerOpitonsPaths(sys, ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "tsconfig.c.json"), { "@ref/*": ["./nrefs/*"] }); + changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "tsconfig.c.json"), { "@ref/*": ["./nrefs/*"] }); }, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "Revert config file edit", - change: sys => changeCompilerOpitonsPaths(sys, ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "tsconfig.c.json"), { "@ref/*": ["./refs/*"] }), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + change: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "tsconfig.c.json"), { "@ref/*": ["./refs/*"] }), + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "edit in referenced config file", - change: sys => changeCompilerOpitonsPaths(sys, ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "tsconfig.b.json"), { "@ref/*": ["./nrefs/*"] }), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + change: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "tsconfig.b.json"), { "@ref/*": ["./nrefs/*"] }), + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "Revert referenced config file edit", - change: sys => changeCompilerOpitonsPaths(sys, ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "tsconfig.b.json"), { "@ref/*": ["./refs/*"] }), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + change: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "tsconfig.b.json"), { "@ref/*": ["./refs/*"] }), + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "deleting referenced config file", - change: sys => sys.deleteFile(ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "tsconfig.b.json")), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + change: sys => sys.deleteFile(getTsBuildProjectFilePath("transitiveReferences", "tsconfig.b.json")), + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "Revert deleting referenced config file", - change: sys => sys.ensureFileOrFolder(ts.TestFSWithWatch.getTsBuildProjectFile("transitiveReferences", "tsconfig.b.json")), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + change: sys => sys.ensureFileOrFolder(getTsBuildProjectFile("transitiveReferences", "tsconfig.b.json")), + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "deleting transitively referenced config file", - change: sys => sys.deleteFile(ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "tsconfig.a.json")), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + change: sys => sys.deleteFile(getTsBuildProjectFilePath("transitiveReferences", "tsconfig.a.json")), + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "Revert deleting transitively referenced config file", - change: sys => sys.ensureFileOrFolder(ts.TestFSWithWatch.getTsBuildProjectFile("transitiveReferences", "tsconfig.a.json")), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + change: sys => sys.ensureFileOrFolder(getTsBuildProjectFile("transitiveReferences", "tsconfig.a.json")), + timeouts: checkSingleTimeoutQueueLengthAndRun }, ], baselineDependencies: true, }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "projectsWithReferences", subScenario: "when referenced project uses different module resolution", - sys: () => ts.tscWatch.createSystemWithSolutionBuild( + sys: () => createSystemWithSolutionBuild( ["tsconfig.c.json"], [ - ts.tscWatch.libFile, - ts.TestFSWithWatch.getTsBuildProjectFile("transitiveReferences", "tsconfig.a.json"), + libFile, + getTsBuildProjectFile("transitiveReferences", "tsconfig.a.json"), { - path: ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "tsconfig.b.json"), + path: getTsBuildProjectFilePath("transitiveReferences", "tsconfig.b.json"), content: JSON.stringify({ compilerOptions: { composite: true, moduleResolution: "classic" }, files: ["b.ts"], references: [{ path: "tsconfig.a.json" }] }) }, - ts.TestFSWithWatch.getTsBuildProjectFile("transitiveReferences", "tsconfig.c.json"), - ts.TestFSWithWatch.getTsBuildProjectFile("transitiveReferences", "a.ts"), + getTsBuildProjectFile("transitiveReferences", "tsconfig.c.json"), + getTsBuildProjectFile("transitiveReferences", "a.ts"), { - path: ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b.ts"), + path: getTsBuildProjectFilePath("transitiveReferences", "b.ts"), content: `import {A} from "a";export const b = new A();` }, - ts.TestFSWithWatch.getTsBuildProjectFile("transitiveReferences", "c.ts"), - ts.TestFSWithWatch.getTsBuildProjectFile("transitiveReferences", "refs/a.d.ts"), + getTsBuildProjectFile("transitiveReferences", "c.ts"), + getTsBuildProjectFile("transitiveReferences", "refs/a.d.ts"), ], - { currentDirectory: `${ts.TestFSWithWatch.tsbuildProjectsLocation}/transitiveReferences` } + { currentDirectory: `${tsbuildProjectsLocation}/transitiveReferences` } ), commandLineArgs: ["-w", "-p", "tsconfig.c.json"], - changes: ts.emptyArray, + changes: emptyArray, baselineDependencies: true, }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "projectsWithReferences", subScenario: "on transitive references in different folders", - sys: () => ts.tscWatch.createSystemWithSolutionBuild( + sys: () => createSystemWithSolutionBuild( ["c"], [ - ts.tscWatch.libFile, + libFile, { - path: ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "a/tsconfig.json"), + path: getTsBuildProjectFilePath("transitiveReferences", "a/tsconfig.json"), content: JSON.stringify({ compilerOptions: { composite: true }, files: ["index.ts"] }), }, { - path: ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), + path: getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), content: JSON.stringify({ compilerOptions: { composite: true, baseUrl: "./", paths: { "@ref/*": ["../*"] } }, files: ["index.ts"], @@ -196,7 +203,7 @@ describe("unittests:: tsc-watch:: projects with references: invoking when refere }), }, { - path: ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), + path: getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), content: JSON.stringify({ compilerOptions: { baseUrl: "./", paths: { "@ref/*": ["../refs/*"] } }, files: ["index.ts"], @@ -204,71 +211,71 @@ describe("unittests:: tsc-watch:: projects with references: invoking when refere }), }, { - path: ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "a/index.ts"), + path: getTsBuildProjectFilePath("transitiveReferences", "a/index.ts"), content: `export class A {}`, }, { - path: ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/index.ts"), + path: getTsBuildProjectFilePath("transitiveReferences", "b/index.ts"), content: `import {A} from '@ref/a'; export const b = new A();`, }, { - path: ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "c/index.ts"), + path: getTsBuildProjectFilePath("transitiveReferences", "c/index.ts"), content: `import {b} from '../b'; import {X} from "@ref/a"; b; X;`, }, - ts.TestFSWithWatch.getTsBuildProjectFile("transitiveReferences", "refs/a.d.ts"), + getTsBuildProjectFile("transitiveReferences", "refs/a.d.ts"), ], - { currentDirectory: `${ts.TestFSWithWatch.tsbuildProjectsLocation}/transitiveReferences` } + { currentDirectory: `${tsbuildProjectsLocation}/transitiveReferences` } ), commandLineArgs: ["-w", "-p", "c"], changes: [ { caption: "non local edit b ts, and build b", change: sys => { - sys.appendFile(ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/index.ts"), `export function gfoo() { }`); - const solutionBuilder = ts.tscWatch.createSolutionBuilder(sys, ["b"]); + sys.appendFile(getTsBuildProjectFilePath("transitiveReferences", "b/index.ts"), `export function gfoo() { }`); + const solutionBuilder = createSolutionBuilder(sys, ["b"]); solutionBuilder.build(); }, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "edit on config file", change: sys => { sys.ensureFileOrFolder({ - path: ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "nrefs/a.d.ts"), - content: sys.readFile(ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "refs/a.d.ts"))! + path: getTsBuildProjectFilePath("transitiveReferences", "nrefs/a.d.ts"), + content: sys.readFile(getTsBuildProjectFilePath("transitiveReferences", "refs/a.d.ts"))! }); - changeCompilerOpitonsPaths(sys, ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), { "@ref/*": ["../nrefs/*"] }); + changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), { "@ref/*": ["../nrefs/*"] }); }, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "Revert config file edit", - change: sys => changeCompilerOpitonsPaths(sys, ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), { "@ref/*": ["../refs/*"] }), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + change: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), { "@ref/*": ["../refs/*"] }), + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "edit in referenced config file", - change: sys => changeCompilerOpitonsPaths(sys, ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), { "@ref/*": ["../nrefs/*"] }), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + change: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), { "@ref/*": ["../nrefs/*"] }), + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "Revert referenced config file edit", - change: sys => changeCompilerOpitonsPaths(sys, ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), { "@ref/*": ["../refs/*"] }), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + change: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), { "@ref/*": ["../refs/*"] }), + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "deleting referenced config file", - change: sys => sys.deleteFile(ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json")), + change: sys => sys.deleteFile(getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json")), timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2) }, { caption: "Revert deleting referenced config file", change: sys => sys.writeFile( - ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), + getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), JSON.stringify({ compilerOptions: { composite: true, baseUrl: "./", paths: { "@ref/*": ["../*"] } }, files: ["index.ts"], @@ -279,13 +286,13 @@ X;`, }, { caption: "deleting transitively referenced config file", - change: sys => sys.deleteFile(ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "a/tsconfig.json")), + change: sys => sys.deleteFile(getTsBuildProjectFilePath("transitiveReferences", "a/tsconfig.json")), timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2) }, { caption: "Revert deleting transitively referenced config file", change: sys => sys.writeFile( - ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "a/tsconfig.json"), + getTsBuildProjectFilePath("transitiveReferences", "a/tsconfig.json"), JSON.stringify({ compilerOptions: { composite: true }, files: ["index.ts"] @@ -297,97 +304,97 @@ X;`, baselineDependencies: true, }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario: "projectsWithReferences", subScenario: "on transitive references in different folders with no files clause", - sys: () => ts.tscWatch.createSystemWithSolutionBuild( + sys: () => createSystemWithSolutionBuild( ["c"], [ - ts.tscWatch.libFile, + libFile, { - path: ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "a/tsconfig.json"), + path: getTsBuildProjectFilePath("transitiveReferences", "a/tsconfig.json"), content: JSON.stringify({ compilerOptions: { composite: true } }), }, { - path: ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), + path: getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), content: JSON.stringify({ compilerOptions: { composite: true, baseUrl: "./", paths: { "@ref/*": ["../*"] } }, references: [{ path: `../a` }] }), }, { - path: ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), + path: getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), content: JSON.stringify({ compilerOptions: { baseUrl: "./", paths: { "@ref/*": ["../refs/*"] } }, references: [{ path: `../b` }] }), }, { - path: ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "a/index.ts"), + path: getTsBuildProjectFilePath("transitiveReferences", "a/index.ts"), content: `export class A {}`, }, { - path: ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/index.ts"), + path: getTsBuildProjectFilePath("transitiveReferences", "b/index.ts"), content: `import {A} from '@ref/a'; export const b = new A();`, }, { - path: ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "c/index.ts"), + path: getTsBuildProjectFilePath("transitiveReferences", "c/index.ts"), content: `import {b} from '../b'; import {X} from "@ref/a"; b; X;`, }, - ts.TestFSWithWatch.getTsBuildProjectFile("transitiveReferences", "refs/a.d.ts"), + getTsBuildProjectFile("transitiveReferences", "refs/a.d.ts"), ], - { currentDirectory: `${ts.TestFSWithWatch.tsbuildProjectsLocation}/transitiveReferences` } + { currentDirectory: `${tsbuildProjectsLocation}/transitiveReferences` } ), commandLineArgs: ["-w", "-p", "c"], changes: [ { caption: "non local edit b ts, and build b", change: sys => { - sys.appendFile(ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/index.ts"), `export function gfoo() { }`); - const solutionBuilder = ts.tscWatch.createSolutionBuilder(sys, ["b"]); + sys.appendFile(getTsBuildProjectFilePath("transitiveReferences", "b/index.ts"), `export function gfoo() { }`); + const solutionBuilder = createSolutionBuilder(sys, ["b"]); solutionBuilder.build(); }, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "edit on config file", change: sys => { sys.ensureFileOrFolder({ - path: ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "nrefs/a.d.ts"), - content: sys.readFile(ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "refs/a.d.ts"))! + path: getTsBuildProjectFilePath("transitiveReferences", "nrefs/a.d.ts"), + content: sys.readFile(getTsBuildProjectFilePath("transitiveReferences", "refs/a.d.ts"))! }); - changeCompilerOpitonsPaths(sys, ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), { "@ref/*": ["../nrefs/*"] }); + changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), { "@ref/*": ["../nrefs/*"] }); }, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "Revert config file edit", - change: sys => changeCompilerOpitonsPaths(sys, ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), { "@ref/*": ["../refs/*"] }), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + change: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), { "@ref/*": ["../refs/*"] }), + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "edit in referenced config file", - change: sys => changeCompilerOpitonsPaths(sys, ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), { "@ref/*": ["../nrefs/*"] }), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + change: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), { "@ref/*": ["../nrefs/*"] }), + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "Revert referenced config file edit", - change: sys => changeCompilerOpitonsPaths(sys, ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), { "@ref/*": ["../refs/*"] }), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun + change: sys => changeCompilerOpitonsPaths(sys, getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), { "@ref/*": ["../refs/*"] }), + timeouts: checkSingleTimeoutQueueLengthAndRun }, { caption: "deleting referenced config file", - change: sys => sys.deleteFile(ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json")), + change: sys => sys.deleteFile(getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json")), timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2) }, { caption: "Revert deleting referenced config file", change: sys => sys.writeFile( - ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), + getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), JSON.stringify({ compilerOptions: { composite: true, baseUrl: "./", paths: { "@ref/*": ["../*"] } }, references: [{ path: `../a` }] @@ -397,13 +404,13 @@ X;`, }, { caption: "deleting transitively referenced config file", - change: sys => sys.deleteFile(ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "a/tsconfig.json")), + change: sys => sys.deleteFile(getTsBuildProjectFilePath("transitiveReferences", "a/tsconfig.json")), timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2) }, { caption: "Revert deleting transitively referenced config file", change: sys => sys.writeFile( - ts.TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "a/tsconfig.json"), + getTsBuildProjectFilePath("transitiveReferences", "a/tsconfig.json"), JSON.stringify({ compilerOptions: { composite: true } }), ), timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2) diff --git a/src/testRunner/unittests/tscWatch/resolutionCache.ts b/src/testRunner/unittests/tscWatch/resolutionCache.ts index e611d2362fa4a..1aac3e4c33ce9 100644 --- a/src/testRunner/unittests/tscWatch/resolutionCache.ts +++ b/src/testRunner/unittests/tscWatch/resolutionCache.ts @@ -1,4 +1,11 @@ -import * as ts from "../../_namespaces/ts"; +import { EmitAndSemanticDiagnosticsBuilderProgram } from "../../../compiler/builderPublic"; +import { emptyArray, noop, notImplemented } from "../../../compiler/core"; +import { ModuleKind } from "../../../compiler/types"; +import { createWatchProgram, WatchOfConfigFile } from "../../../compiler/watchPublic"; +import { + createBaseline, createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline, createWatchedSystem, File, libFile, + projectRoot, runQueuedTimeoutCallbacks, runWatchBaseline, SymLink, verifyTscWatch, +} from "./helpers"; describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch module resolution caching", () => { const scenario = "resolutionCache"; @@ -12,18 +19,18 @@ describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch module resolution content: `foo()` }; - const { sys, baseline, oldSnap, cb, getPrograms } = ts.tscWatch.createBaseline(ts.tscWatch.createWatchedSystem([root, imported, ts.tscWatch.libFile])); - const host = ts.tscWatch.createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({ + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([root, imported, libFile])); + const host = createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({ rootFiles: [root.path], system: sys, - options: { module: ts.ModuleKind.AMD }, + options: { module: ModuleKind.AMD }, cb, watchOptions: undefined }); const originalFileExists = host.fileExists; - const watch = ts.createWatchProgram(host); + const watch = createWatchProgram(host); let fileExistsIsCalled = false; - ts.tscWatch.runWatchBaseline({ + runWatchBaseline({ scenario: "resolutionCache", subScenario: "caching works", commandLineArgs: ["--w", root.path], @@ -36,11 +43,11 @@ describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch module resolution caption: "Adding text doesnt re-resole the imports", change: sys => { // patch fileExists to make sure that disk is not touched - host.fileExists = ts.notImplemented; + host.fileExists = notImplemented; sys.writeFile(root.path, `import {x} from "f1" var x: string = 1;`); }, - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks + timeouts: runQueuedTimeoutCallbacks }, { caption: "Resolves f2", @@ -95,11 +102,11 @@ describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch module resolution content: `export const y = 1;` }; - const { sys, baseline, oldSnap, cb, getPrograms } = ts.tscWatch.createBaseline(ts.tscWatch.createWatchedSystem([root, ts.tscWatch.libFile])); - const host = ts.tscWatch.createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({ + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([root, libFile])); + const host = createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({ rootFiles: [root.path], system: sys, - options: { module: ts.ModuleKind.AMD }, + options: { module: ModuleKind.AMD }, cb, watchOptions: undefined }); @@ -116,9 +123,9 @@ describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch module resolution return originalFileExists.call(host, fileName); }; - const watch = ts.createWatchProgram(host); + const watch = createWatchProgram(host); assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called"); - ts.tscWatch.runWatchBaseline({ + runWatchBaseline({ scenario: "resolutionCache", subScenario: "loads missing files from disk", commandLineArgs: ["--w", root.path], @@ -153,11 +160,11 @@ describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch module resolution content: `export const y = 1;export const x = 10;` }; - const { sys, baseline, oldSnap, cb, getPrograms } = ts.tscWatch.createBaseline(ts.tscWatch.createWatchedSystem([root, imported, ts.tscWatch.libFile])); - const host = ts.tscWatch.createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({ + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([root, imported, libFile])); + const host = createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({ rootFiles: [root.path], system: sys, - options: { module: ts.ModuleKind.AMD }, + options: { module: ModuleKind.AMD }, cb, watchOptions: undefined }); @@ -172,9 +179,9 @@ describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch module resolution } return originalFileExists.call(host, fileName); }; - const watch = ts.createWatchProgram(host); + const watch = createWatchProgram(host); assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called"); - ts.tscWatch.runWatchBaseline({ + runWatchBaseline({ scenario: "resolutionCache", subScenario: "should compile correctly when resolved module goes missing and then comes back", commandLineArgs: ["--w", root.path], @@ -211,14 +218,14 @@ describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch module resolution }); }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "works when module resolution changes to ambient module", commandLineArgs: ["-w", "/a/b/foo.ts"], - sys: () => ts.tscWatch.createWatchedSystem([{ + sys: () => createWatchedSystem([{ path: "/a/b/foo.ts", content: `import * as fs from "fs";` - }, ts.tscWatch.libFile], { currentDirectory: "/a/b" }), + }, libFile], { currentDirectory: "/a/b" }), changes: [ { caption: "npm install node types", @@ -241,12 +248,12 @@ declare module "fs" { }` }); }, - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "works when included file with ambient module changes", commandLineArgs: ["--w", "/a/b/foo.ts", "/a/b/bar.d.ts"], @@ -269,7 +276,7 @@ declare module "url" { } ` }; - return ts.tscWatch.createWatchedSystem([root, file, ts.tscWatch.libFile], { currentDirectory: "/a/b" }); + return createWatchedSystem([root, file, libFile], { currentDirectory: "/a/b" }); }, changes: [ { @@ -281,30 +288,30 @@ declare module "fs" { } } `), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "works when reusing program with files from external library", commandLineArgs: ["--w", "-p", "/a/b/projects/myProject/src"], sys: () => { const configDir = "/a/b/projects/myProject/src/"; - const file1: ts.tscWatch.File = { + const file1: File = { path: configDir + "file1.ts", content: 'import module1 = require("module1");\nmodule1("hello");' }; - const file2: ts.tscWatch.File = { + const file2: File = { path: configDir + "file2.ts", content: 'import module11 = require("module1");\nmodule11("hello");' }; - const module1: ts.tscWatch.File = { + const module1: File = { path: "/a/b/projects/myProject/node_modules/module1/index.js", content: "module.exports = options => { return options.toString(); }" }; - const configFile: ts.tscWatch.File = { + const configFile: File = { path: configDir + "tsconfig.json", content: JSON.stringify({ compilerOptions: { @@ -316,67 +323,67 @@ declare module "fs" { } }) }; - return ts.tscWatch.createWatchedSystem([file1, file2, module1, ts.tscWatch.libFile, configFile], { currentDirectory: "/a/b/projects/myProject/" }); + return createWatchedSystem([file1, file2, module1, libFile, configFile], { currentDirectory: "/a/b/projects/myProject/" }); }, changes: [ { caption: "Add new line to file1", change: sys => sys.appendFile("/a/b/projects/myProject/src/file1.ts", "\n;"), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "works when renaming node_modules folder that already contains @types folder", - commandLineArgs: ["--w", `${ts.tscWatch.projectRoot}/a.ts`], + commandLineArgs: ["--w", `${projectRoot}/a.ts`], sys: () => { - const file: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const file: File = { + path: `${projectRoot}/a.ts`, content: `import * as q from "qqq";` }; - const module: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/node_modules2/@types/qqq/index.d.ts`, + const module: File = { + path: `${projectRoot}/node_modules2/@types/qqq/index.d.ts`, content: "export {}" }; - return ts.tscWatch.createWatchedSystem([file, ts.tscWatch.libFile, module], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([file, libFile, module], { currentDirectory: projectRoot }); }, changes: [ { caption: "npm install", - change: sys => sys.renameFolder(`${ts.tscWatch.projectRoot}/node_modules2`, `${ts.tscWatch.projectRoot}/node_modules`), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => sys.renameFolder(`${projectRoot}/node_modules2`, `${projectRoot}/node_modules`), + timeouts: runQueuedTimeoutCallbacks, } ] }); describe("ignores files/folder changes in node_modules that start with '.'", () => { function verifyIgnore(subScenario: string, commandLineArgs: readonly string[]) { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: `ignores changes in node_modules that start with dot/${subScenario}`, commandLineArgs, sys: () => { - const file1: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/test.ts`, + const file1: File = { + path: `${projectRoot}/test.ts`, content: `import { x } from "somemodule";` }; - const file2: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/node_modules/somemodule/index.d.ts`, + const file2: File = { + path: `${projectRoot}/node_modules/somemodule/index.d.ts`, content: `export const x = 10;` }; - const config: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: "{}" }; - return ts.tscWatch.createWatchedSystem([ts.tscWatch.libFile, file1, file2, config]); + return createWatchedSystem([libFile, file1, file2, config]); }, changes: [ { caption: "npm install file and folder that start with '.'", change: sys => sys.ensureFileOrFolder({ - path: `${ts.tscWatch.projectRoot}/node_modules/.cache/babel-loader/89c02171edab901b9926470ba6d5677e.ts`, + path: `${projectRoot}/node_modules/.cache/babel-loader/89c02171edab901b9926470ba6d5677e.ts`, content: JSON.stringify({ something: 10 }) }), timeouts: sys => sys.checkTimeoutQueueLength(0), @@ -384,21 +391,21 @@ declare module "fs" { ] }); } - verifyIgnore("watch without configFile", ["--w", `${ts.tscWatch.projectRoot}/test.ts`]); - verifyIgnore("watch with configFile", ["--w", "-p", `${ts.tscWatch.projectRoot}/tsconfig.json`]); + verifyIgnore("watch without configFile", ["--w", `${projectRoot}/test.ts`]); + verifyIgnore("watch with configFile", ["--w", "-p", `${projectRoot}/tsconfig.json`]); }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "when types in compiler option are global and installed at later point", - commandLineArgs: ["--w", "-p", `${ts.tscWatch.projectRoot}/tsconfig.json`], + commandLineArgs: ["--w", "-p", `${projectRoot}/tsconfig.json`], sys: () => { - const app: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/lib/app.ts`, + const app: File = { + path: `${projectRoot}/lib/app.ts`, content: `myapp.component("hello");` }; - const tsconfig: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { module: "none", @@ -406,21 +413,21 @@ declare module "fs" { } }) }; - return ts.tscWatch.createWatchedSystem([app, tsconfig, ts.tscWatch.libFile]); + return createWatchedSystem([app, tsconfig, libFile]); }, changes: [ { caption: "npm install ts-types", change: sys => { sys.ensureFileOrFolder({ - path: `${ts.tscWatch.projectRoot}/node_modules/@myapp/ts-types/package.json`, + path: `${projectRoot}/node_modules/@myapp/ts-types/package.json`, content: JSON.stringify({ version: "1.65.1", types: "types/somefile.define.d.ts" }) }); sys.ensureFileOrFolder({ - path: `${ts.tscWatch.projectRoot}/node_modules/@myapp/ts-types/types/somefile.define.d.ts`, + path: `${projectRoot}/node_modules/@myapp/ts-types/types/somefile.define.d.ts`, content: ` declare namespace myapp { function component(str: string): number; @@ -434,10 +441,10 @@ declare namespace myapp { }, { caption: "No change, just check program", - change: ts.noop, + change: noop, timeouts: (sys, [[oldProgram, oldBuilderProgram]], watchorSolution) => { sys.checkTimeoutQueueLength(0); - const newProgram = (watchorSolution as ts.WatchOfConfigFile).getProgram(); + const newProgram = (watchorSolution as WatchOfConfigFile).getProgram(); assert.strictEqual(newProgram, oldBuilderProgram, "No change so builder program should be same"); assert.strictEqual(newProgram.getProgram(), oldProgram, "No change so program should be same"); } @@ -445,63 +452,63 @@ declare namespace myapp { ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "with modules linked to sibling folder", commandLineArgs: ["-w"], sys: () => { - const mainPackageRoot = `${ts.tscWatch.projectRoot}/main`; - const linkedPackageRoot = `${ts.tscWatch.projectRoot}/linked-package`; - const mainFile: ts.tscWatch.File = { + const mainPackageRoot = `${projectRoot}/main`; + const linkedPackageRoot = `${projectRoot}/linked-package`; + const mainFile: File = { path: `${mainPackageRoot}/index.ts`, content: "import { Foo } from '@scoped/linked-package'" }; - const config: ts.tscWatch.File = { + const config: File = { path: `${mainPackageRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { module: "commonjs", moduleResolution: "node", baseUrl: ".", rootDir: "." }, files: ["index.ts"] }) }; - const linkedPackageInMain: ts.tscWatch.SymLink = { + const linkedPackageInMain: SymLink = { path: `${mainPackageRoot}/node_modules/@scoped/linked-package`, symLink: `${linkedPackageRoot}` }; - const linkedPackageJson: ts.tscWatch.File = { + const linkedPackageJson: File = { path: `${linkedPackageRoot}/package.json`, content: JSON.stringify({ name: "@scoped/linked-package", version: "0.0.1", types: "dist/index.d.ts", main: "dist/index.js" }) }; - const linkedPackageIndex: ts.tscWatch.File = { + const linkedPackageIndex: File = { path: `${linkedPackageRoot}/dist/index.d.ts`, content: "export * from './other';" }; - const linkedPackageOther: ts.tscWatch.File = { + const linkedPackageOther: File = { path: `${linkedPackageRoot}/dist/other.d.ts`, content: 'export declare const Foo = "BAR";' }; - const files = [ts.tscWatch.libFile, mainFile, config, linkedPackageInMain, linkedPackageJson, linkedPackageIndex, linkedPackageOther]; - return ts.tscWatch.createWatchedSystem(files, { currentDirectory: mainPackageRoot }); + const files = [libFile, mainFile, config, linkedPackageInMain, linkedPackageJson, linkedPackageIndex, linkedPackageOther]; + return createWatchedSystem(files, { currentDirectory: mainPackageRoot }); }, - changes: ts.emptyArray + changes: emptyArray }); describe("works when installing something in node_modules or @types when there is no notification from fs for index file", () => { function getNodeAtTypes() { - const nodeAtTypesIndex: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/node_modules/@types/node/index.d.ts`, + const nodeAtTypesIndex: File = { + path: `${projectRoot}/node_modules/@types/node/index.d.ts`, content: `/// ` }; - const nodeAtTypesBase: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/node_modules/@types/node/base.d.ts`, + const nodeAtTypesBase: File = { + path: `${projectRoot}/node_modules/@types/node/base.d.ts`, content: `// Base definitions for all NodeJS modules that are not specific to any version of TypeScript: /// ` }; - const nodeAtTypes36Base: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/node_modules/@types/node/ts3.6/base.d.ts`, + const nodeAtTypes36Base: File = { + path: `${projectRoot}/node_modules/@types/node/ts3.6/base.d.ts`, content: `/// ` }; - const nodeAtTypesGlobals: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/node_modules/@types/node/globals.d.ts`, + const nodeAtTypesGlobals: File = { + path: `${projectRoot}/node_modules/@types/node/globals.d.ts`, content: `declare var process: NodeJS.Process; declare namespace NodeJS { interface Process { @@ -511,40 +518,40 @@ declare namespace NodeJS { }; return { nodeAtTypesIndex, nodeAtTypesBase, nodeAtTypes36Base, nodeAtTypesGlobals }; } - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "works when installing something in node_modules or @types when there is no notification from fs for index file", commandLineArgs: ["--w", `--extendedDiagnostics`], sys: () => { - const file: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/worker.ts`, + const file: File = { + path: `${projectRoot}/worker.ts`, content: `process.on("uncaughtException");` }; - const tsconfig: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, content: "{}" }; const { nodeAtTypesIndex, nodeAtTypesBase, nodeAtTypes36Base, nodeAtTypesGlobals } = getNodeAtTypes(); - return ts.tscWatch.createWatchedSystem([file, ts.tscWatch.libFile, tsconfig, nodeAtTypesIndex, nodeAtTypesBase, nodeAtTypes36Base, nodeAtTypesGlobals], { currentDirectory: ts.tscWatch.projectRoot }); + return createWatchedSystem([file, libFile, tsconfig, nodeAtTypesIndex, nodeAtTypesBase, nodeAtTypes36Base, nodeAtTypesGlobals], { currentDirectory: projectRoot }); }, changes: [ { caption: "npm ci step one: remove all node_modules files", - change: sys => sys.deleteFolder(`${ts.tscWatch.projectRoot}/node_modules/@types`, /*recursive*/ true), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + change: sys => sys.deleteFolder(`${projectRoot}/node_modules/@types`, /*recursive*/ true), + timeouts: runQueuedTimeoutCallbacks, }, { caption: `npm ci step two: create atTypes but something else in the @types folder`, change: sys => sys.ensureFileOrFolder({ - path: `${ts.tscWatch.projectRoot}/node_modules/@types/mocha/index.d.ts`, + path: `${projectRoot}/node_modules/@types/mocha/index.d.ts`, content: `export const foo = 10;` }), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks + timeouts: runQueuedTimeoutCallbacks }, { caption: `npm ci step three: create atTypes node folder`, - change: sys => sys.ensureFileOrFolder({ path: `${ts.tscWatch.projectRoot}/node_modules/@types/node` }), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks + change: sys => sys.ensureFileOrFolder({ path: `${projectRoot}/node_modules/@types/node` }), + timeouts: runQueuedTimeoutCallbacks }, { caption: `npm ci step four: create atTypes write all the files but dont invoke watcher for index.d.ts`, diff --git a/src/testRunner/unittests/tscWatch/sourceOfProjectReferenceRedirect.ts b/src/testRunner/unittests/tscWatch/sourceOfProjectReferenceRedirect.ts index 50761f6ebcb44..e8f4ae888202b 100644 --- a/src/testRunner/unittests/tscWatch/sourceOfProjectReferenceRedirect.ts +++ b/src/testRunner/unittests/tscWatch/sourceOfProjectReferenceRedirect.ts @@ -1,29 +1,38 @@ -import * as ts from "../../_namespaces/ts"; +import { emptyArray, returnTrue } from "../../../compiler/core"; +import { CompilerOptions } from "../../../compiler/types"; +import { createWatchProgram } from "../../../compiler/watchPublic"; +import { + FileOrFolderOrSymLink, getTsBuildProjectFile as getFileFromProject, +} from "../../../harness/virtualFileSystemWithWatch"; +import { libContent } from "../tsbuild/helpers"; +import { + createBaseline, createWatchCompilerHostOfConfigFileForBaseline, createWatchedSystem, File, libFile, projectRoot, + runWatchBaseline, solutionBuildWithBaseline, SymLink, +} from "./helpers"; -import getFileFromProject = ts.TestFSWithWatch.getTsBuildProjectFile; describe("unittests:: tsc-watch:: watchAPI:: with sourceOfProjectReferenceRedirect", () => { interface VerifyWatchInput { - files: readonly ts.TestFSWithWatch.FileOrFolderOrSymLink[]; + files: readonly FileOrFolderOrSymLink[]; config: string; subScenario: string; } function verifyWatch({ files, config, subScenario }: VerifyWatchInput, alreadyBuilt: boolean) { - const { sys, baseline, oldSnap, cb, getPrograms } = ts.tscWatch.createBaseline( - ts.tscWatch.createWatchedSystem(files), + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline( + createWatchedSystem(files), alreadyBuilt ? (sys, originalRead) => { - ts.tscWatch.solutionBuildWithBaseline(sys, [config], originalRead); + solutionBuildWithBaseline(sys, [config], originalRead); sys.clearOutput(); } : undefined ); - const host = ts.tscWatch.createWatchCompilerHostOfConfigFileForBaseline({ + const host = createWatchCompilerHostOfConfigFileForBaseline({ configFileName: config, system: sys, cb, }); - host.useSourceOfProjectReferenceRedirect = ts.returnTrue; - const watch = ts.createWatchProgram(host); - ts.tscWatch.runWatchBaseline({ + host.useSourceOfProjectReferenceRedirect = returnTrue; + const watch = createWatchProgram(host); + runWatchBaseline({ scenario: "sourceOfProjectReferenceRedirect", subScenario: `${subScenario}${alreadyBuilt ? " when solution is already built" : ""}`, commandLineArgs: ["--w", "--p", config], @@ -31,7 +40,7 @@ describe("unittests:: tsc-watch:: watchAPI:: with sourceOfProjectReferenceRedire baseline, oldSnap, getPrograms, - changes: ts.emptyArray, + changes: emptyArray, watchOrSolution: watch }); } @@ -56,7 +65,7 @@ describe("unittests:: tsc-watch:: watchAPI:: with sourceOfProjectReferenceRedire const indexTs = getFileFromProject("demo", "animals/index.ts"); const animalsConfig = getFileFromProject("demo", "animals/tsconfig.json"); return { - files: [{ path: ts.tscWatch.libFile.path, content: ts.libContent }, baseConfig, coreTs, coreConfig, animalTs, dogTs, indexTs, animalsConfig], + files: [{ path: libFile.path, content: libContent }, baseConfig, coreTs, coreConfig, animalTs, dogTs, indexTs, animalsConfig], config: animalsConfig.path, subScenario: "with simple project" }; @@ -65,11 +74,11 @@ describe("unittests:: tsc-watch:: watchAPI:: with sourceOfProjectReferenceRedire describe("when references are monorepo like with symlinks", () => { interface Packages { - bPackageJson: ts.tscWatch.File; - aTest: ts.tscWatch.File; - bFoo: ts.tscWatch.File; - bBar: ts.tscWatch.File; - bSymlink: ts.tscWatch.SymLink; + bPackageJson: File; + aTest: File; + bFoo: File; + bBar: File; + bSymlink: SymLink; subScenario: string; } function verifySymlinkScenario(packages: () => Packages) { @@ -81,22 +90,22 @@ describe("unittests:: tsc-watch:: watchAPI:: with sourceOfProjectReferenceRedire }); } - function verifySymlinkScenarioWorker(packages: () => Packages, extraOptions: ts.CompilerOptions) { + function verifySymlinkScenarioWorker(packages: () => Packages, extraOptions: CompilerOptions) { verifyScenario(() => { const { bPackageJson, aTest, bFoo, bBar, bSymlink, subScenario } = packages(); const aConfig = config("A", extraOptions, ["../B"]); const bConfig = config("B", extraOptions); return { - files: [ts.tscWatch.libFile, bPackageJson, aConfig, bConfig, aTest, bFoo, bBar, bSymlink], + files: [libFile, bPackageJson, aConfig, bConfig, aTest, bFoo, bBar, bSymlink], config: aConfig.path, subScenario: `${subScenario}${extraOptions.preserveSymlinks ? " with preserveSymlinks" : ""}` }; }); } - function config(packageName: string, extraOptions: ts.CompilerOptions, references?: string[]): ts.tscWatch.File { + function config(packageName: string, extraOptions: CompilerOptions, references?: string[]): File { return { - path: `${ts.tscWatch.projectRoot}/packages/${packageName}/tsconfig.json`, + path: `${projectRoot}/packages/${packageName}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { outDir: "lib", @@ -110,9 +119,9 @@ describe("unittests:: tsc-watch:: watchAPI:: with sourceOfProjectReferenceRedire }; } - function file(packageName: string, fileName: string, content: string): ts.tscWatch.File { + function file(packageName: string, fileName: string, content: string): File { return { - path: `${ts.tscWatch.projectRoot}/packages/${packageName}/src/${fileName}`, + path: `${projectRoot}/packages/${packageName}/src/${fileName}`, content }; } @@ -121,7 +130,7 @@ describe("unittests:: tsc-watch:: watchAPI:: with sourceOfProjectReferenceRedire describe("when packageJson has types field", () => { verifySymlinkScenario(() => ({ bPackageJson: { - path: `${ts.tscWatch.projectRoot}/packages/B/package.json`, + path: `${projectRoot}/packages/B/package.json`, content: JSON.stringify({ main: "lib/index.js", types: "lib/index.d.ts" @@ -135,8 +144,8 @@ bar(); bFoo: file("B", "index.ts", `export function foo() { }`), bBar: file("B", "bar.ts", `export function bar() { }`), bSymlink: { - path: `${ts.tscWatch.projectRoot}/node_modules/${scope}b`, - symLink: `${ts.tscWatch.projectRoot}/packages/B` + path: `${projectRoot}/node_modules/${scope}b`, + symLink: `${projectRoot}/packages/B` }, subScenario: `when packageJson has types field${scope ? " with scoped package" : ""}` })); @@ -145,7 +154,7 @@ bar(); describe("when referencing file from subFolder", () => { verifySymlinkScenario(() => ({ bPackageJson: { - path: `${ts.tscWatch.projectRoot}/packages/B/package.json`, + path: `${projectRoot}/packages/B/package.json`, content: "{}" }, aTest: file("A", "test.ts", `import { foo } from '${scope}b/lib/foo'; @@ -156,8 +165,8 @@ bar(); bFoo: file("B", "foo.ts", `export function foo() { }`), bBar: file("B", "bar/foo.ts", `export function bar() { }`), bSymlink: { - path: `${ts.tscWatch.projectRoot}/node_modules/${scope}b`, - symLink: `${ts.tscWatch.projectRoot}/packages/B` + path: `${projectRoot}/node_modules/${scope}b`, + symLink: `${projectRoot}/packages/B` }, subScenario: `when referencing file from subFolder${scope ? " with scoped package" : ""}` })); diff --git a/src/testRunner/unittests/tscWatch/watchApi.ts b/src/testRunner/unittests/tscWatch/watchApi.ts index 3176486b2eeae..b6e45e23bf489 100644 --- a/src/testRunner/unittests/tscWatch/watchApi.ts +++ b/src/testRunner/unittests/tscWatch/watchApi.ts @@ -1,37 +1,58 @@ -import * as Harness from "../../_namespaces/Harness"; -import * as ts from "../../_namespaces/ts"; +import { + BuilderProgram, createEmitAndSemanticDiagnosticsBuilderProgram, createSemanticDiagnosticsBuilderProgram, +} from "../../../compiler/builderPublic"; +import { getParsedCommandLineOfConfigFile, parseJsonConfigFileContent } from "../../../compiler/commandLineParser"; +import { emptyArray, noop, returnTrue } from "../../../compiler/core"; +import { Set } from "../../../compiler/corePublic"; +import { resolveModuleName } from "../../../compiler/moduleNameResolver"; +import { System } from "../../../compiler/sys"; +import { CompilerOptions, ScriptKind } from "../../../compiler/types"; +import { createCompilerDiagnostic } from "../../../compiler/utilities"; +import { sortAndDeduplicateDiagnostics } from "../../../compiler/utilitiesPublic"; +import { + createDiagnosticReporter, createWatchCompilerHostOfConfigFile, createWatchStatusReporter, + getWatchErrorSummaryDiagnosticMessage, +} from "../../../compiler/watch"; +import { CreateProgram, createWatchProgram } from "../../../compiler/watchPublic"; +import { Baseline } from "../../../harness/harnessIO"; +import { TestServerHostTrackingWrittenFiles } from "../../../harness/virtualFileSystemWithWatch"; +import { commandLineCallbacks } from "../tsc/helpers"; +import { + applyChange, checkSingleTimeoutQueueLengthAndRun, createBaseline, createWatchCompilerHostOfConfigFileForBaseline, + createWatchedSystem, File, libFile, projectRoot, runQueuedTimeoutCallbacks, runWatchBaseline, watchBaseline, +} from "./helpers"; describe("unittests:: tsc-watch:: watchAPI:: tsc-watch with custom module resolution", () => { const configFileJson: any = { compilerOptions: { module: "commonjs", resolveJsonModule: true }, files: ["index.ts"] }; - const mainFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/index.ts`, + const mainFile: File = { + path: `${projectRoot}/index.ts`, content: "import settings from './settings.json';" }; - const config: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify(configFileJson) }; - const settingsJson: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/settings.json`, + const settingsJson: File = { + path: `${projectRoot}/settings.json`, content: JSON.stringify({ content: "Print this" }) }; it("verify that module resolution with json extension works when returned without extension", () => { - const { sys, baseline, oldSnap, cb, getPrograms } = ts.tscWatch.createBaseline(ts.tscWatch.createWatchedSystem( - [ts.tscWatch.libFile, mainFile, config, settingsJson], - { currentDirectory: ts.tscWatch.projectRoot }), + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem( + [libFile, mainFile, config, settingsJson], + { currentDirectory: projectRoot }), ); - const host = ts.tscWatch.createWatchCompilerHostOfConfigFileForBaseline({ + const host = createWatchCompilerHostOfConfigFileForBaseline({ configFileName: config.path, system: sys, cb, }); - const parsedCommandResult = ts.parseJsonConfigFileContent(configFileJson, sys, config.path); + const parsedCommandResult = parseJsonConfigFileContent(configFileJson, sys, config.path); host.resolveModuleNames = (moduleNames, containingFile) => moduleNames.map(m => { - const result = ts.resolveModuleName(m, containingFile, parsedCommandResult.options, host); + const result = resolveModuleName(m, containingFile, parsedCommandResult.options, host); const resolvedModule = result.resolvedModule!; return { resolvedFileName: resolvedModule.resolvedFileName, @@ -39,8 +60,8 @@ describe("unittests:: tsc-watch:: watchAPI:: tsc-watch with custom module resolu originalFileName: resolvedModule.originalPath, }; }); - const watch = ts.createWatchProgram(host); - ts.tscWatch.runWatchBaseline({ + const watch = createWatchProgram(host); + runWatchBaseline({ scenario: "watchApi", subScenario: "verify that module resolution with json extension works when returned without extension", commandLineArgs: ["--w", "--p", config.path], @@ -48,7 +69,7 @@ describe("unittests:: tsc-watch:: watchAPI:: tsc-watch with custom module resolu baseline, oldSnap, getPrograms, - changes: ts.emptyArray, + changes: emptyArray, watchOrSolution: watch }); }); @@ -56,22 +77,22 @@ describe("unittests:: tsc-watch:: watchAPI:: tsc-watch with custom module resolu describe("unittests:: tsc-watch:: watchAPI:: tsc-watch expose error count to watch status reporter", () => { it("verify that the error count is correctly passed down to the watch status reporter", () => { - const config: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { module: "commonjs" }, files: ["index.ts"] }) }; - const mainFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/index.ts`, + const mainFile: File = { + path: `${projectRoot}/index.ts`, content: "let compiler = new Compiler(); for (let i = 0; j < 5; i++) {}" }; - const { sys, baseline, oldSnap, cb, getPrograms } = ts.tscWatch.createBaseline(ts.tscWatch.createWatchedSystem( - [ts.tscWatch.libFile, mainFile, config], - { currentDirectory: ts.tscWatch.projectRoot }), + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem( + [libFile, mainFile, config], + { currentDirectory: projectRoot }), ); - const host = ts.tscWatch.createWatchCompilerHostOfConfigFileForBaseline({ + const host = createWatchCompilerHostOfConfigFileForBaseline({ configFileName: config.path, system: sys, cb, @@ -82,9 +103,9 @@ describe("unittests:: tsc-watch:: watchAPI:: tsc-watch expose error count to wat existing.call(host, diagnostic, newLine, options, errorCount); watchedErrorCount = errorCount; }; - const watch = ts.createWatchProgram(host); + const watch = createWatchProgram(host); assert.equal(watchedErrorCount, 2, "The error count was expected to be 2 for the file change"); - ts.tscWatch.runWatchBaseline({ + runWatchBaseline({ scenario: "watchApi", subScenario: "verify that the error count is correctly passed down to the watch status reporter", commandLineArgs: ["--w", "--p", config.path], @@ -92,7 +113,7 @@ describe("unittests:: tsc-watch:: watchAPI:: tsc-watch expose error count to wat baseline, oldSnap, getPrograms, - changes: ts.emptyArray, + changes: emptyArray, watchOrSolution: watch }); }); @@ -100,24 +121,24 @@ describe("unittests:: tsc-watch:: watchAPI:: tsc-watch expose error count to wat describe("unittests:: tsc-watch:: watchAPI:: when watchHost does not implement setTimeout or clearTimeout", () => { it("verifies that getProgram gets updated program if new file is added to the program", () => { - const config: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: "{}" }; - const mainFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/main.ts`, + const mainFile: File = { + path: `${projectRoot}/main.ts`, content: "const x = 10;" }; - const { sys, baseline, oldSnap, cb, getPrograms } = ts.tscWatch.createBaseline(ts.tscWatch.createWatchedSystem([config, mainFile, ts.tscWatch.libFile])); - const host = ts.tscWatch.createWatchCompilerHostOfConfigFileForBaseline({ + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([config, mainFile, libFile])); + const host = createWatchCompilerHostOfConfigFileForBaseline({ configFileName: config.path, system: sys, cb, }); host.setTimeout = undefined; host.clearTimeout = undefined; - const watch = ts.createWatchProgram(host); - ts.tscWatch.runWatchBaseline({ + const watch = createWatchProgram(host); + runWatchBaseline({ scenario: "watchApi", subScenario: "without timesouts on host program gets updated", commandLineArgs: ["--w", "--p", config.path], @@ -127,7 +148,7 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost does not implement s getPrograms, changes: [{ caption: "Write a file", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/bar.ts`, "const y =10;"), + change: sys => sys.writeFile(`${projectRoot}/bar.ts`, "const y =10;"), timeouts: sys => { sys.checkTimeoutQueueLength(0); watch.getProgram(); @@ -140,30 +161,30 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost does not implement s describe("unittests:: tsc-watch:: watchAPI:: when watchHost can add extraFileExtensions to process", () => { it("verifies that extraFileExtensions are supported to get the program with other extensions", () => { - const config: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: "{}" }; - const mainFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/main.ts`, + const mainFile: File = { + path: `${projectRoot}/main.ts`, content: "const x = 10;" }; - const otherFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/other.vue`, + const otherFile: File = { + path: `${projectRoot}/other.vue`, content: "" }; - const { sys, baseline, oldSnap, cb, getPrograms } = ts.tscWatch.createBaseline( - ts.tscWatch.createWatchedSystem([config, mainFile, otherFile, ts.tscWatch.libFile]) + const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline( + createWatchedSystem([config, mainFile, otherFile, libFile]) ); - const host = ts.tscWatch.createWatchCompilerHostOfConfigFileForBaseline({ + const host = createWatchCompilerHostOfConfigFileForBaseline({ configFileName: config.path, optionsToExtend: { allowNonTsExtensions: true }, - extraFileExtensions: [{ extension: ".vue", isMixedContent: true, scriptKind: ts.ScriptKind.Deferred }], + extraFileExtensions: [{ extension: ".vue", isMixedContent: true, scriptKind: ScriptKind.Deferred }], system: sys, cb, }); - const watch = ts.createWatchProgram(host); - ts.tscWatch.runWatchBaseline({ + const watch = createWatchProgram(host); + runWatchBaseline({ scenario: "watchApi", subScenario: "extraFileExtensions are supported", commandLineArgs: ["--w", "--p", config.path], @@ -173,8 +194,8 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost can add extraFileExt getPrograms, changes: [{ caption: "Write a file", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/other2.vue`, otherFile.content), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.writeFile(`${projectRoot}/other2.vue`, otherFile.content), + timeouts: checkSingleTimeoutQueueLengthAndRun, }], watchOrSolution: watch }); @@ -183,57 +204,57 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost can add extraFileExt describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticDiagnosticsBuilderProgram", () => { function createSystem(configText: string, mainText: string) { - const config: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: configText }; - const mainFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/main.ts`, + const mainFile: File = { + path: `${projectRoot}/main.ts`, content: mainText }; - const otherFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/other.ts`, + const otherFile: File = { + path: `${projectRoot}/other.ts`, content: "export const y = 10;" }; return { - ...ts.tscWatch.createBaseline(ts.tscWatch.createWatchedSystem([config, mainFile, otherFile, ts.tscWatch.libFile])), + ...createBaseline(createWatchedSystem([config, mainFile, otherFile, libFile])), config, mainFile, otherFile, }; } - function createWatch( + function createWatch( baseline: string[], - config: ts.tscWatch.File, - sys: ts.TestFSWithWatch.TestServerHostTrackingWrittenFiles, - createProgram: ts.CreateProgram, - optionsToExtend?: ts.CompilerOptions, + config: File, + sys: TestServerHostTrackingWrittenFiles, + createProgram: CreateProgram, + optionsToExtend?: CompilerOptions, ) { - const { cb, getPrograms } = ts.commandLineCallbacks(sys); + const { cb, getPrograms } = commandLineCallbacks(sys); baseline.push(`tsc --w${optionsToExtend?.noEmit ? " --noEmit" : ""}`); const oldSnap = sys.snap(); - const host = ts.tscWatch.createWatchCompilerHostOfConfigFileForBaseline({ + const host = createWatchCompilerHostOfConfigFileForBaseline({ configFileName: config.path, optionsToExtend, createProgram, system: sys, cb, }); - const watch = ts.createWatchProgram(host); - ts.tscWatch.watchBaseline({ + const watch = createWatchProgram(host); + watchBaseline({ baseline, getPrograms, - oldPrograms: ts.emptyArray, + oldPrograms: emptyArray, sys, oldSnap, }); watch.close(); } - function verifyOutputs(baseline: string[], sys: ts.System, emitSys: ts.System) { + function verifyOutputs(baseline: string[], sys: System, emitSys: System) { baseline.push("Checking if output is same as EmitAndSemanticDiagnosticsBuilderProgram::"); - for (const output of [`${ts.tscWatch.projectRoot}/main.js`, `${ts.tscWatch.projectRoot}/main.d.ts`, `${ts.tscWatch.projectRoot}/other.js`, `${ts.tscWatch.projectRoot}/other.d.ts`, `${ts.tscWatch.projectRoot}/tsconfig.tsbuildinfo`]) { + for (const output of [`${projectRoot}/main.js`, `${projectRoot}/main.d.ts`, `${projectRoot}/other.js`, `${projectRoot}/other.d.ts`, `${projectRoot}/tsconfig.tsbuildinfo`]) { baseline.push(`Output file text for ${output} is same:: ${sys.readFile(output) === emitSys.readFile(output)}`); } baseline.push(""); @@ -248,40 +269,40 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticD function applyChangeForBuilderTest( baseline: string[], emitBaseline: string[], - sys: ts.TestFSWithWatch.TestServerHostTrackingWrittenFiles, - emitSys: ts.TestFSWithWatch.TestServerHostTrackingWrittenFiles, - change: (sys: ts.TestFSWithWatch.TestServerHostTrackingWrittenFiles) => void, + sys: TestServerHostTrackingWrittenFiles, + emitSys: TestServerHostTrackingWrittenFiles, + change: (sys: TestServerHostTrackingWrittenFiles) => void, caption: string ) { // Change file - ts.tscWatch.applyChange(sys, baseline, change, caption); - ts.tscWatch.applyChange(emitSys, emitBaseline, change, caption); + applyChange(sys, baseline, change, caption); + applyChange(emitSys, emitBaseline, change, caption); } - function verifyBuilder( + function verifyBuilder( baseline: string[], emitBaseline: string[], - config: ts.tscWatch.File, - sys: ts.TestFSWithWatch.TestServerHostTrackingWrittenFiles, - emitSys: ts.TestFSWithWatch.TestServerHostTrackingWrittenFiles, - createProgram: ts.CreateProgram, - optionsToExtend?: ts.CompilerOptions) { + config: File, + sys: TestServerHostTrackingWrittenFiles, + emitSys: TestServerHostTrackingWrittenFiles, + createProgram: CreateProgram, + optionsToExtend?: CompilerOptions) { createWatch(baseline, config, sys, createProgram, optionsToExtend); - createWatch(emitBaseline, config, emitSys, ts.createEmitAndSemanticDiagnosticsBuilderProgram, optionsToExtend); + createWatch(emitBaseline, config, emitSys, createEmitAndSemanticDiagnosticsBuilderProgram, optionsToExtend); verifyOutputs(baseline, sys, emitSys); } it("verifies that noEmit is handled on createSemanticDiagnosticsBuilderProgram and typechecking happens only on affected files", () => { const { sys, baseline, oldSnap, cb, getPrograms, config, mainFile } = createSystem("{}", "export const x = 10;"); - const host = ts.tscWatch.createWatchCompilerHostOfConfigFileForBaseline({ + const host = createWatchCompilerHostOfConfigFileForBaseline({ configFileName: config.path, optionsToExtend: { noEmit: true }, - createProgram: ts.createSemanticDiagnosticsBuilderProgram, + createProgram: createSemanticDiagnosticsBuilderProgram, system: sys, cb, }); - const watch = ts.createWatchProgram(host); - ts.tscWatch.runWatchBaseline({ + const watch = createWatchProgram(host); + runWatchBaseline({ scenario: "watchApi", subScenario: "verifies that noEmit is handled on createSemanticDiagnosticsBuilderProgram", commandLineArgs: ["--w", "--p", config.path], @@ -292,7 +313,7 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticD changes: [{ caption: "Modify a file", change: sys => sys.appendFile(mainFile.path, "\n// SomeComment"), - timeouts: ts.tscWatch.runQueuedTimeoutCallbacks, + timeouts: runQueuedTimeoutCallbacks, }], watchOrSolution: watch }); @@ -310,35 +331,35 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticD const { sys, config, mainFile, emitSys } = result; // No Emit - verifyBuilder(baseline, emitBaseline, config, sys, emitSys, ts.createEmitAndSemanticDiagnosticsBuilderProgram, { noEmit: true }); + verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createEmitAndSemanticDiagnosticsBuilderProgram, { noEmit: true }); // Emit on both sys should result in same output - verifyBuilder(baseline, emitBaseline, config, sys, emitSys, ts.createEmitAndSemanticDiagnosticsBuilderProgram); + verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createEmitAndSemanticDiagnosticsBuilderProgram); // Change file applyChangeForBuilderTest(baseline, emitBaseline, sys, emitSys, sys => sys.appendFile(mainFile.path, "\n// SomeComment"), "Add comment"); // Verify noEmit results in same output - verifyBuilder(baseline, emitBaseline, config, sys, emitSys, ts.createSemanticDiagnosticsBuilderProgram, { noEmit: true }); + verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createSemanticDiagnosticsBuilderProgram, { noEmit: true }); // Emit on both sys should result in same output - verifyBuilder(baseline, emitBaseline, config, sys, emitSys, ts.createEmitAndSemanticDiagnosticsBuilderProgram); + verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createEmitAndSemanticDiagnosticsBuilderProgram); // Change file applyChangeForBuilderTest(baseline, emitBaseline, sys, emitSys, sys => sys.appendFile(mainFile.path, "\n// SomeComment"), "Add comment"); // Emit on both the builders should result in same files - verifyBuilder(baseline, emitBaseline, config, sys, emitSys, ts.createSemanticDiagnosticsBuilderProgram); + verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createSemanticDiagnosticsBuilderProgram); }); after(() => { baseline = undefined!; emitBaseline = undefined!; }); it("noEmit with composite writes the tsbuildinfo with pending affected files correctly", () => { - Harness.Baseline.runBaseline(`tscWatch/watchApi/noEmit-with-composite-with-semantic-builder.js`, baseline.join("\r\n")); + Baseline.runBaseline(`tscWatch/watchApi/noEmit-with-composite-with-semantic-builder.js`, baseline.join("\r\n")); }); it("baseline in createEmitAndSemanticDiagnosticsBuilderProgram:: noEmit with composite writes the tsbuildinfo with pending affected files correctly", () => { - Harness.Baseline.runBaseline(`tscWatch/watchApi/noEmit-with-composite-with-emit-builder.js`, emitBaseline.join("\r\n")); + Baseline.runBaseline(`tscWatch/watchApi/noEmit-with-composite-with-emit-builder.js`, emitBaseline.join("\r\n")); }); }); @@ -354,78 +375,78 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticD const { sys, config, mainFile, emitSys } = result; // Verify noEmit results in same output - verifyBuilder(baseline, emitBaseline, config, sys, emitSys, ts.createSemanticDiagnosticsBuilderProgram); + verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createSemanticDiagnosticsBuilderProgram); // Change file applyChangeForBuilderTest(baseline, emitBaseline, sys, emitSys, sys => sys.appendFile(mainFile.path, "\n// SomeComment"), "Add comment"); // Verify noEmit results in same output - verifyBuilder(baseline, emitBaseline, config, sys, emitSys, ts.createSemanticDiagnosticsBuilderProgram); + verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createSemanticDiagnosticsBuilderProgram); // Fix error const fixed = "export const x = 10;"; applyChangeForBuilderTest(baseline, emitBaseline, sys, emitSys, sys => sys.writeFile(mainFile.path, fixed), "Fix error"); // Emit on both the builders should result in same files - verifyBuilder(baseline, emitBaseline, config, sys, emitSys, ts.createSemanticDiagnosticsBuilderProgram); + verifyBuilder(baseline, emitBaseline, config, sys, emitSys, createSemanticDiagnosticsBuilderProgram); }); it("noEmitOnError with composite writes the tsbuildinfo with pending affected files correctly", () => { - Harness.Baseline.runBaseline(`tscWatch/watchApi/noEmitOnError-with-composite-with-semantic-builder.js`, baseline.join("\r\n")); + Baseline.runBaseline(`tscWatch/watchApi/noEmitOnError-with-composite-with-semantic-builder.js`, baseline.join("\r\n")); }); it("baseline in createEmitAndSemanticDiagnosticsBuilderProgram:: noEmitOnError with composite writes the tsbuildinfo with pending affected files correctly", () => { - Harness.Baseline.runBaseline(`tscWatch/watchApi/noEmitOnError-with-composite-with-emit-builder.js`, emitBaseline.join("\r\n")); + Baseline.runBaseline(`tscWatch/watchApi/noEmitOnError-with-composite-with-emit-builder.js`, emitBaseline.join("\r\n")); }); }); it("SemanticDiagnosticsBuilderProgram emitDtsOnly does not update affected files pending emit", () => { // Initial const { sys, baseline, config, mainFile } = createSystem(JSON.stringify({ compilerOptions: { composite: true, noEmitOnError: true } }), "export const x: string = 10;"); - createWatch(baseline, config, sys, ts.createSemanticDiagnosticsBuilderProgram); + createWatch(baseline, config, sys, createSemanticDiagnosticsBuilderProgram); // Fix error and emit - ts.tscWatch.applyChange(sys, baseline, sys => sys.writeFile(mainFile.path, "export const x = 10;"), "Fix error"); + applyChange(sys, baseline, sys => sys.writeFile(mainFile.path, "export const x = 10;"), "Fix error"); - const { cb, getPrograms } = ts.commandLineCallbacks(sys); + const { cb, getPrograms } = commandLineCallbacks(sys); const oldSnap = sys.snap(); - const reportDiagnostic = ts.createDiagnosticReporter(sys, /*pretty*/ true); - const reportWatchStatus = ts.createWatchStatusReporter(sys, /*pretty*/ true); - const host = ts.createWatchCompilerHostOfConfigFile({ + const reportDiagnostic = createDiagnosticReporter(sys, /*pretty*/ true); + const reportWatchStatus = createWatchStatusReporter(sys, /*pretty*/ true); + const host = createWatchCompilerHostOfConfigFile({ configFileName: config.path, - createProgram: ts.createSemanticDiagnosticsBuilderProgram, + createProgram: createSemanticDiagnosticsBuilderProgram, system: sys, reportDiagnostic, reportWatchStatus, }); host.afterProgramCreate = program => { - const diagnostics = ts.sortAndDeduplicateDiagnostics(program.getSemanticDiagnostics()); + const diagnostics = sortAndDeduplicateDiagnostics(program.getSemanticDiagnostics()); diagnostics.forEach(reportDiagnostic); // Buildinfo should still have affectedFilesPendingEmit since we are only emitting dts files program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDts*/ true); reportWatchStatus( - ts.createCompilerDiagnostic(ts.getWatchErrorSummaryDiagnosticMessage(diagnostics.length), diagnostics.length), + createCompilerDiagnostic(getWatchErrorSummaryDiagnosticMessage(diagnostics.length), diagnostics.length), sys.newLine, program.getCompilerOptions(), diagnostics.length ); cb(program); }; - ts.createWatchProgram(host); - ts.tscWatch.watchBaseline({ + createWatchProgram(host); + watchBaseline({ baseline, getPrograms, - oldPrograms: ts.emptyArray, + oldPrograms: emptyArray, sys, oldSnap, }); - Harness.Baseline.runBaseline(`tscWatch/watchApi/semantic-builder-emitOnlyDts.js`, baseline.join("\r\n")); + Baseline.runBaseline(`tscWatch/watchApi/semantic-builder-emitOnlyDts.js`, baseline.join("\r\n")); }); }); describe("unittests:: tsc-watch:: watchAPI:: when getParsedCommandLine is implemented", () => { function setup(useSourceOfProjectReferenceRedirect?: () => boolean) { - const config1: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/projects/project1/tsconfig.json`, + const config1: File = { + path: `${projectRoot}/projects/project1/tsconfig.json`, content: JSON.stringify({ compilerOptions: { module: "none", @@ -434,16 +455,16 @@ describe("unittests:: tsc-watch:: watchAPI:: when getParsedCommandLine is implem exclude: ["temp"] }) }; - const class1: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/projects/project1/class1.ts`, + const class1: File = { + path: `${projectRoot}/projects/project1/class1.ts`, content: `class class1 {}` }; - const class1Dts: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/projects/project1/class1.d.ts`, + const class1Dts: File = { + path: `${projectRoot}/projects/project1/class1.d.ts`, content: `declare class class1 {}` }; - const config2: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/projects/project2/tsconfig.json`, + const config2: File = { + path: `${projectRoot}/projects/project2/tsconfig.json`, content: JSON.stringify({ compilerOptions: { module: "none", @@ -454,39 +475,39 @@ describe("unittests:: tsc-watch:: watchAPI:: when getParsedCommandLine is implem ] }) }; - const class2: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/projects/project2/class2.ts`, + const class2: File = { + path: `${projectRoot}/projects/project2/class2.ts`, content: `class class2 {}` }; - const system = ts.tscWatch.createWatchedSystem([config1, class1, class1Dts, config2, class2, ts.tscWatch.libFile]); - const baseline = ts.tscWatch.createBaseline(system); - const compilerHost = ts.tscWatch.createWatchCompilerHostOfConfigFileForBaseline({ + const system = createWatchedSystem([config1, class1, class1Dts, config2, class2, libFile]); + const baseline = createBaseline(system); + const compilerHost = createWatchCompilerHostOfConfigFileForBaseline({ cb: baseline.cb, system, configFileName: config2.path, optionsToExtend: { extendedDiagnostics: true } }); compilerHost.useSourceOfProjectReferenceRedirect = useSourceOfProjectReferenceRedirect; - const calledGetParsedCommandLine = new ts.Set(); + const calledGetParsedCommandLine = new Set(); compilerHost.getParsedCommandLine = fileName => { assert.isFalse(calledGetParsedCommandLine.has(fileName), `Already called on ${fileName}`); calledGetParsedCommandLine.add(fileName); - return ts.getParsedCommandLineOfConfigFile(fileName, /*optionsToExtend*/ undefined, { + return getParsedCommandLineOfConfigFile(fileName, /*optionsToExtend*/ undefined, { useCaseSensitiveFileNames: true, fileExists: path => system.fileExists(path), readFile: path => system.readFile(path), getCurrentDirectory: () => system.getCurrentDirectory(), readDirectory: (path, extensions, excludes, includes, depth) => system.readDirectory(path, extensions, excludes, includes, depth), - onUnRecoverableConfigFileDiagnostic: ts.noop, + onUnRecoverableConfigFileDiagnostic: noop, }); }; - const watch = ts.createWatchProgram(compilerHost); + const watch = createWatchProgram(compilerHost); return { watch, baseline, config2, calledGetParsedCommandLine }; } it("when new file is added to the referenced project with host implementing getParsedCommandLine", () => { - const { watch, baseline, config2, calledGetParsedCommandLine } = setup(ts.returnTrue); - ts.tscWatch.runWatchBaseline({ + const { watch, baseline, config2, calledGetParsedCommandLine } = setup(returnTrue); + runWatchBaseline({ scenario: "watchApi", subScenario: "when new file is added to the referenced project with host implementing getParsedCommandLine", commandLineArgs: ["--w", "-p", config2.path, "--extendedDiagnostics"], @@ -496,18 +517,18 @@ describe("unittests:: tsc-watch:: watchAPI:: when getParsedCommandLine is implem caption: "Add class3 to project1", change: sys => { calledGetParsedCommandLine.clear(); - sys.writeFile(`${ts.tscWatch.projectRoot}/projects/project1/class3.ts`, `class class3 {}`); + sys.writeFile(`${projectRoot}/projects/project1/class3.ts`, `class class3 {}`); }, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "Add excluded file to project1", - change: sys => sys.ensureFileOrFolder({ path: `${ts.tscWatch.projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }), + change: sys => sys.ensureFileOrFolder({ path: `${projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }), timeouts: sys => sys.checkTimeoutQueueLength(0), }, { caption: "Add output of class3", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`), + change: sys => sys.writeFile(`${projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`), timeouts: sys => sys.checkTimeoutQueueLength(0), }, ], @@ -517,7 +538,7 @@ describe("unittests:: tsc-watch:: watchAPI:: when getParsedCommandLine is implem it("when new file is added to the referenced project with host implementing getParsedCommandLine without implementing useSourceOfProjectReferenceRedirect", () => { const { watch, baseline, config2, calledGetParsedCommandLine } = setup(); - ts.tscWatch.runWatchBaseline({ + runWatchBaseline({ scenario: "watchApi", subScenario: "when new file is added to the referenced project with host implementing getParsedCommandLine without implementing useSourceOfProjectReferenceRedirect", commandLineArgs: ["--w", "-p", config2.path, "--extendedDiagnostics"], @@ -527,29 +548,29 @@ describe("unittests:: tsc-watch:: watchAPI:: when getParsedCommandLine is implem caption: "Add class3 to project1", change: sys => { calledGetParsedCommandLine.clear(); - sys.writeFile(`${ts.tscWatch.projectRoot}/projects/project1/class3.ts`, `class class3 {}`); + sys.writeFile(`${projectRoot}/projects/project1/class3.ts`, `class class3 {}`); }, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "Add class3 output to project1", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.writeFile(`${projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`), + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "Add excluded file to project1", - change: sys => sys.ensureFileOrFolder({ path: `${ts.tscWatch.projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }), + change: sys => sys.ensureFileOrFolder({ path: `${projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }), timeouts: sys => sys.checkTimeoutQueueLength(0), }, { caption: "Delete output of class3", - change: sys => sys.deleteFile(`${ts.tscWatch.projectRoot}/projects/project1/class3.d.ts`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.deleteFile(`${projectRoot}/projects/project1/class3.d.ts`), + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "Add output of class3", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.writeFile(`${projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`), + timeouts: checkSingleTimeoutQueueLengthAndRun, }, ], watchOrSolution: watch diff --git a/src/testRunner/unittests/tscWatch/watchEnvironment.ts b/src/testRunner/unittests/tscWatch/watchEnvironment.ts index 5e2cae38ef40b..a18958d97b818 100644 --- a/src/testRunner/unittests/tscWatch/watchEnvironment.ts +++ b/src/testRunner/unittests/tscWatch/watchEnvironment.ts @@ -1,29 +1,36 @@ -import * as ts from "../../_namespaces/ts"; +import { emptyArray, noop } from "../../../compiler/core"; +import { Map } from "../../../compiler/corePublic"; +import { PollingInterval, unchangedPollThresholds } from "../../../compiler/sys"; +import { WatchFileKind, WatchOptions } from "../../../compiler/types"; +import { Tsc_WatchDirectory, Tsc_WatchFile } from "../../../harness/virtualFileSystemWithWatch"; +import { + checkSingleTimeoutQueueLengthAndRun, commonFile1, commonFile2, createWatchedSystem, File, libFile, noopChange, + projectRoot, replaceFileText, SymLink, verifyTscWatch, WatchedSystem, +} from "./helpers"; -import Tsc_WatchDirectory = ts.TestFSWithWatch.Tsc_WatchDirectory; describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different polling/non polling options", () => { const scenario = "watchEnvironment"; - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "watchFile/using dynamic priority polling", commandLineArgs: ["--w", `/a/username/project/typescript.ts`], sys: () => { const projectFolder = "/a/username/project"; - const file1: ts.tscWatch.File = { + const file1: File = { path: `${projectFolder}/typescript.ts`, content: "var z = 10;" }; - const environmentVariables = new ts.Map(); - environmentVariables.set("TSC_WATCHFILE", ts.TestFSWithWatch.Tsc_WatchFile.DynamicPolling); - return ts.tscWatch.createWatchedSystem([file1, ts.tscWatch.libFile], { environmentVariables }); + const environmentVariables = new Map(); + environmentVariables.set("TSC_WATCHFILE", Tsc_WatchFile.DynamicPolling); + return createWatchedSystem([file1, libFile], { environmentVariables }); }, changes: [ { caption: "Time spent to Transition libFile and file1 to low priority queue", - change: ts.noop, + change: noop, timeouts: (sys, programs) => { const initialProgram = programs[0][0]; - const mediumPollingIntervalThreshold = ts.unchangedPollThresholds[ts.PollingInterval.Medium]; + const mediumPollingIntervalThreshold = unchangedPollThresholds[PollingInterval.Medium]; for (let index = 0; index < mediumPollingIntervalThreshold; index++) { // Transition libFile and file1 to low priority queue sys.checkTimeoutQueueLengthAndRun(1); @@ -37,22 +44,22 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po // Make a change to file change: sys => sys.writeFile("/a/username/project/typescript.ts", "var zz30 = 100;"), // During this timeout the file would be detected as unchanged - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "Callbacks: medium priority + high priority queue and scheduled program update", - change: ts.noop, + change: noop, // Callbacks: medium priority + high priority queue and scheduled program update // This should detect change in the file timeouts: sys => sys.checkTimeoutQueueLengthAndRun(3), }, { caption: "Polling queues polled and everything is in the high polling queue", - change: ts.noop, + change: noop, timeouts: (sys, programs) => { const initialProgram = programs[0][0]; - const mediumPollingIntervalThreshold = ts.unchangedPollThresholds[ts.PollingInterval.Medium]; - const newThreshold = ts.unchangedPollThresholds[ts.PollingInterval.Low] + mediumPollingIntervalThreshold; + const mediumPollingIntervalThreshold = unchangedPollThresholds[PollingInterval.Medium]; + const newThreshold = unchangedPollThresholds[PollingInterval.Low] + mediumPollingIntervalThreshold; for (let fileUnchangeDetected = 1; fileUnchangeDetected < newThreshold; fileUnchangeDetected++) { // For high + Medium/low polling interval sys.checkTimeoutQueueLengthAndRun(2); @@ -67,12 +74,12 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "watchFile/using fixed chunk size polling", commandLineArgs: ["-w", "-p", "/a/b/tsconfig.json"], sys: () => { - const configFile: ts.tscWatch.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: JSON.stringify({ watchOptions: { @@ -80,13 +87,13 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po } }) }; - const files = [ts.tscWatch.libFile, ts.tscWatch.commonFile1, ts.tscWatch.commonFile2, configFile]; - return ts.tscWatch.createWatchedSystem(files); + const files = [libFile, commonFile1, commonFile2, configFile]; + return createWatchedSystem(files); }, changes: [ { caption: "The timeout is to check the status of all files", - change: ts.noop, + change: noop, timeouts: (sys, programs) => { // On each timeout file does not change const initialProgram = programs[0][0]; @@ -99,18 +106,18 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po { caption: "Make change to file but should detect as changed and schedule program update", // Make a change to file - change: sys => sys.writeFile(ts.tscWatch.commonFile1.path, "var zz30 = 100;"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.writeFile(commonFile1.path, "var zz30 = 100;"), + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "Callbacks: queue and scheduled program update", - change: ts.noop, + change: noop, // Callbacks: scheduled program update and queue for the polling timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2), }, { caption: "The timeout is to check the status of all files", - change: ts.noop, + change: noop, timeouts: (sys, programs) => { // On each timeout file does not change const initialProgram = programs[0][0]; @@ -121,30 +128,30 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "watchFile/setting default as fixed chunk size watch file works", commandLineArgs: ["-w", "-p", "/a/b/tsconfig.json"], sys: () => { - const configFile: ts.tscWatch.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: "{}" }; - const files = [ts.tscWatch.libFile, ts.tscWatch.commonFile1, ts.tscWatch.commonFile2, configFile]; - const sys = ts.tscWatch.createWatchedSystem(files); - sys.defaultWatchFileKind = () => ts.WatchFileKind.FixedChunkSizePolling; + const files = [libFile, commonFile1, commonFile2, configFile]; + const sys = createWatchedSystem(files); + sys.defaultWatchFileKind = () => WatchFileKind.FixedChunkSizePolling; return sys; }, changes: [ { caption: "Make change to file but should detect as changed and schedule program update", // Make a change to file - change: sys => sys.writeFile(ts.tscWatch.commonFile1.path, "var zz30 = 100;"), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, + change: sys => sys.writeFile(commonFile1.path, "var zz30 = 100;"), + timeouts: checkSingleTimeoutQueueLengthAndRun, }, { caption: "Callbacks: queue and scheduled program update", - change: ts.noop, + change: noop, // Callbacks: scheduled program update and queue for the polling timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2), }, @@ -155,7 +162,7 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po function verifyRenamingFileInSubFolder(subScenario: string, tscWatchDirectory: Tsc_WatchDirectory) { const projectFolder = "/a/username/project"; const projectSrcFolder = `${projectFolder}/src`; - const configFile: ts.tscWatch.File = { + const configFile: File = { path: `${projectFolder}/tsconfig.json`, content: JSON.stringify({ watchOptions: { @@ -163,19 +170,19 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po } }) }; - const file: ts.tscWatch.File = { + const file: File = { path: `${projectSrcFolder}/file1.ts`, content: "" }; - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: `watchDirectories/${subScenario}`, commandLineArgs: ["--w", "-p", configFile.path], sys: () => { - const files = [file, configFile, ts.tscWatch.libFile]; - const environmentVariables = new ts.Map(); + const files = [file, configFile, libFile]; + const environmentVariables = new Map(); environmentVariables.set("TSC_WATCHDIRECTORY", tscWatchDirectory); - return ts.tscWatch.createWatchedSystem(files, { environmentVariables }); + return createWatchedSystem(files, { environmentVariables }); }, changes: [ { @@ -202,76 +209,76 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po verifyRenamingFileInSubFolder("uses non recursive dynamic polling when renaming file in subfolder", Tsc_WatchDirectory.DynamicPolling); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "watchDirectories/when there are symlinks to folders in recursive folders", commandLineArgs: ["--w"], sys: () => { const cwd = "/home/user/projects/myproject"; - const file1: ts.tscWatch.File = { + const file1: File = { path: `${cwd}/src/file.ts`, content: `import * as a from "a"` }; - const tsconfig: ts.tscWatch.File = { + const tsconfig: File = { path: `${cwd}/tsconfig.json`, content: `{ "compilerOptions": { "extendedDiagnostics": true, "traceResolution": true }}` }; - const realA: ts.tscWatch.File = { + const realA: File = { path: `${cwd}/node_modules/reala/index.d.ts`, content: `export {}` }; - const realB: ts.tscWatch.File = { + const realB: File = { path: `${cwd}/node_modules/realb/index.d.ts`, content: `export {}` }; - const symLinkA: ts.tscWatch.SymLink = { + const symLinkA: SymLink = { path: `${cwd}/node_modules/a`, symLink: `${cwd}/node_modules/reala` }; - const symLinkB: ts.tscWatch.SymLink = { + const symLinkB: SymLink = { path: `${cwd}/node_modules/b`, symLink: `${cwd}/node_modules/realb` }; - const symLinkBInA: ts.tscWatch.SymLink = { + const symLinkBInA: SymLink = { path: `${cwd}/node_modules/reala/node_modules/b`, symLink: `${cwd}/node_modules/b` }; - const symLinkAInB: ts.tscWatch.SymLink = { + const symLinkAInB: SymLink = { path: `${cwd}/node_modules/realb/node_modules/a`, symLink: `${cwd}/node_modules/a` }; - const files = [ts.tscWatch.libFile, file1, tsconfig, realA, realB, symLinkA, symLinkB, symLinkBInA, symLinkAInB]; - const environmentVariables = new ts.Map(); + const files = [libFile, file1, tsconfig, realA, realB, symLinkA, symLinkB, symLinkBInA, symLinkAInB]; + const environmentVariables = new Map(); environmentVariables.set("TSC_WATCHDIRECTORY", Tsc_WatchDirectory.NonRecursiveWatchDirectory); - return ts.tscWatch.createWatchedSystem(files, { environmentVariables, currentDirectory: cwd }); + return createWatchedSystem(files, { environmentVariables, currentDirectory: cwd }); }, - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "watchDirectories/with non synchronous watch directory", - commandLineArgs: ["--w", "-p", `${ts.tscWatch.projectRoot}/tsconfig.json`], + commandLineArgs: ["--w", "-p", `${projectRoot}/tsconfig.json`], sys: () => { - const configFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const configFile: File = { + path: `${projectRoot}/tsconfig.json`, content: "{}" }; - const file1: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/src/file1.ts`, + const file1: File = { + path: `${projectRoot}/src/file1.ts`, content: `import { x } from "file2";` }; - const file2: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/node_modules/file2/index.d.ts`, + const file2: File = { + path: `${projectRoot}/node_modules/file2/index.d.ts`, content: `export const x = 10;` }; - const files = [ts.tscWatch.libFile, file1, file2, configFile]; - return ts.tscWatch.createWatchedSystem(files, { runWithoutRecursiveWatches: true }); + const files = [libFile, file1, file2, configFile]; + return createWatchedSystem(files, { runWithoutRecursiveWatches: true }); }, changes: [ { caption: "Directory watch updates because of file1.js creation", - change: ts.noop, + change: noop, timeouts: sys => { sys.checkTimeoutQueueLengthAndRun(1); // To update directory callbacks for file1.js output sys.checkTimeoutQueueLength(0); @@ -280,7 +287,7 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po { caption: "Remove directory node_modules", // Remove directory node_modules - change: sys => sys.deleteFolder(`${ts.tscWatch.projectRoot}/node_modules`, /*recursive*/ true), + change: sys => sys.deleteFolder(`${projectRoot}/node_modules`, /*recursive*/ true), timeouts: sys => { sys.checkTimeoutQueueLength(3); // 1. Failed lookup invalidation 2. For updating program and 3. for updating child watches sys.runQueuedTimeoutCallbacks(sys.getNextTimeoutId() - 2); // Update program @@ -288,7 +295,7 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po }, { caption: "Pending directory watchers and program update", - change: ts.noop, + change: noop, timeouts: sys => { sys.checkTimeoutQueueLengthAndRun(1); // To update directory watchers sys.checkTimeoutQueueLengthAndRun(2); // To Update program and failed lookup update @@ -299,22 +306,22 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po { caption: "Start npm install", // npm install - change: sys => sys.createDirectory(`${ts.tscWatch.projectRoot}/node_modules`), + change: sys => sys.createDirectory(`${projectRoot}/node_modules`), timeouts: sys => sys.checkTimeoutQueueLength(1), // To update folder structure }, { caption: "npm install folder creation of file2", - change: sys => sys.createDirectory(`${ts.tscWatch.projectRoot}/node_modules/file2`), + change: sys => sys.createDirectory(`${projectRoot}/node_modules/file2`), timeouts: sys => sys.checkTimeoutQueueLength(1), // To update folder structure }, { caption: "npm install index file in file2", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/node_modules/file2/index.d.ts`, `export const x = 10;`), + change: sys => sys.writeFile(`${projectRoot}/node_modules/file2/index.d.ts`, `export const x = 10;`), timeouts: sys => sys.checkTimeoutQueueLength(1), // To update folder structure }, { caption: "Updates the program", - change: ts.noop, + change: noop, timeouts: sys => { sys.runQueuedTimeoutCallbacks(); sys.checkTimeoutQueueLength(2); // To Update program and failed lookup update @@ -322,7 +329,7 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po }, { caption: "Invalidates module resolution cache", - change: ts.noop, + change: noop, timeouts: sys => { sys.runQueuedTimeoutCallbacks(); sys.checkTimeoutQueueLength(1); // To Update program @@ -330,7 +337,7 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po }, { caption: "Pending updates", - change: ts.noop, + change: noop, timeouts: sys => { sys.runQueuedTimeoutCallbacks(); sys.checkTimeoutQueueLength(0); @@ -339,72 +346,72 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po ], }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "watchDirectories/with non synchronous watch directory with outDir and declaration enabled", - commandLineArgs: ["--w", "-p", `${ts.tscWatch.projectRoot}/tsconfig.json`], + commandLineArgs: ["--w", "-p", `${projectRoot}/tsconfig.json`], sys: () => { - const configFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const configFile: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { outDir: "dist", declaration: true } }) }; - const file1: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/src/file1.ts`, + const file1: File = { + path: `${projectRoot}/src/file1.ts`, content: `import { x } from "file2";` }; - const file2: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/node_modules/file2/index.d.ts`, + const file2: File = { + path: `${projectRoot}/node_modules/file2/index.d.ts`, content: `export const x = 10;` }; - const files = [ts.tscWatch.libFile, file1, file2, configFile]; - return ts.tscWatch.createWatchedSystem(files, { runWithoutRecursiveWatches: true }); + const files = [libFile, file1, file2, configFile]; + return createWatchedSystem(files, { runWithoutRecursiveWatches: true }); }, changes: [ - ts.tscWatch.noopChange, + noopChange, { caption: "Add new file, should schedule and run timeout to update directory watcher", - change: sys => sys.writeFile(`${ts.tscWatch.projectRoot}/src/file3.ts`, `export const y = 10;`), - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, // Update the child watch + change: sys => sys.writeFile(`${projectRoot}/src/file3.ts`, `export const y = 10;`), + timeouts: checkSingleTimeoutQueueLengthAndRun, // Update the child watch }, { caption: "Actual program update to include new file", - change: ts.noop, + change: noop, timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2), // Scheduling failed lookup update and program update }, { caption: "After program emit with new file, should schedule and run timeout to update directory watcher", - change: ts.noop, - timeouts: ts.tscWatch.checkSingleTimeoutQueueLengthAndRun, // Update the child watch + change: noop, + timeouts: checkSingleTimeoutQueueLengthAndRun, // Update the child watch }, - ts.tscWatch.noopChange, + noopChange, ], }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "watchDirectories/with non synchronous watch directory renaming a file", - commandLineArgs: ["--w", "-p", `${ts.tscWatch.projectRoot}/tsconfig.json`], + commandLineArgs: ["--w", "-p", `${projectRoot}/tsconfig.json`], sys: () => { - const configFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const configFile: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { outDir: "dist" } }) }; - const file1: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/src/file1.ts`, + const file1: File = { + path: `${projectRoot}/src/file1.ts`, content: `import { x } from "./file2";` }; - const file2: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/src/file2.ts`, + const file2: File = { + path: `${projectRoot}/src/file2.ts`, content: `export const x = 10;` }; - const files = [ts.tscWatch.libFile, file1, file2, configFile]; - return ts.tscWatch.createWatchedSystem(files, { runWithoutRecursiveWatches: true }); + const files = [libFile, file1, file2, configFile]; + return createWatchedSystem(files, { runWithoutRecursiveWatches: true }); }, changes: [ - ts.tscWatch.noopChange, + noopChange, { caption: "rename the file", - change: sys => sys.renameFile(`${ts.tscWatch.projectRoot}/src/file2.ts`, `${ts.tscWatch.projectRoot}/src/renamed.ts`), + change: sys => sys.renameFile(`${projectRoot}/src/file2.ts`, `${projectRoot}/src/renamed.ts`), timeouts: sys => { sys.checkTimeoutQueueLength(2); // 1. For updating program and 2. for updating child watches sys.runQueuedTimeoutCallbacks(1); // Update program @@ -412,7 +419,7 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po }, { caption: "Pending directory watchers and program update", - change: ts.noop, + change: noop, timeouts: sys => { sys.checkTimeoutQueueLengthAndRun(1); // To update directory watchers sys.checkTimeoutQueueLengthAndRun(2); // To Update program and failed lookup update @@ -425,12 +432,12 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po }); describe("handles watch compiler options", () => { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "watchOptions/with watchFile option", commandLineArgs: ["-w", "-p", "/a/b/tsconfig.json"], sys: () => { - const configFile: ts.tscWatch.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: JSON.stringify({ watchOptions: { @@ -438,18 +445,18 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po } }) }; - const files = [ts.tscWatch.libFile, ts.tscWatch.commonFile1, ts.tscWatch.commonFile2, configFile]; - return ts.tscWatch.createWatchedSystem(files); + const files = [libFile, commonFile1, commonFile2, configFile]; + return createWatchedSystem(files); }, - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "watchOptions/with watchDirectory option", commandLineArgs: ["-w", "-p", "/a/b/tsconfig.json"], sys: () => { - const configFile: ts.tscWatch.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: JSON.stringify({ watchOptions: { @@ -457,18 +464,18 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po } }) }; - const files = [ts.tscWatch.libFile, ts.tscWatch.commonFile1, ts.tscWatch.commonFile2, configFile]; - return ts.tscWatch.createWatchedSystem(files, { runWithoutRecursiveWatches: true }); + const files = [libFile, commonFile1, commonFile2, configFile]; + return createWatchedSystem(files, { runWithoutRecursiveWatches: true }); }, - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "watchOptions/with fallbackPolling option", commandLineArgs: ["-w", "-p", "/a/b/tsconfig.json"], sys: () => { - const configFile: ts.tscWatch.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: JSON.stringify({ watchOptions: { @@ -476,59 +483,59 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po } }) }; - const files = [ts.tscWatch.libFile, ts.tscWatch.commonFile1, ts.tscWatch.commonFile2, configFile]; - return ts.tscWatch.createWatchedSystem(files, { runWithoutRecursiveWatches: true, runWithFallbackPolling: true }); + const files = [libFile, commonFile1, commonFile2, configFile]; + return createWatchedSystem(files, { runWithoutRecursiveWatches: true, runWithFallbackPolling: true }); }, - changes: ts.emptyArray + changes: emptyArray }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: "watchOptions/with watchFile as watch options to extend", commandLineArgs: ["-w", "-p", "/a/b/tsconfig.json", "--watchFile", "UseFsEvents"], sys: () => { - const configFile: ts.tscWatch.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: "{}" }; - const files = [ts.tscWatch.libFile, ts.tscWatch.commonFile1, ts.tscWatch.commonFile2, configFile]; - return ts.tscWatch.createWatchedSystem(files); + const files = [libFile, commonFile1, commonFile2, configFile]; + return createWatchedSystem(files); }, - changes: ts.emptyArray + changes: emptyArray }); describe("exclude options", () => { - function sys(watchOptions: ts.WatchOptions, runWithoutRecursiveWatches?: boolean): ts.tscWatch.WatchedSystem { - const configFile: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + function sys(watchOptions: WatchOptions, runWithoutRecursiveWatches?: boolean): WatchedSystem { + const configFile: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ exclude: ["node_modules"], watchOptions }) }; - const main: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/src/main.ts`, + const main: File = { + path: `${projectRoot}/src/main.ts`, content: `import { foo } from "bar"; foo();` }; - const bar: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/node_modules/bar/index.d.ts`, + const bar: File = { + path: `${projectRoot}/node_modules/bar/index.d.ts`, content: `export { foo } from "./foo";` }; - const foo: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/node_modules/bar/foo.d.ts`, + const foo: File = { + path: `${projectRoot}/node_modules/bar/foo.d.ts`, content: `export function foo(): string;` }; - const fooBar: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/node_modules/bar/fooBar.d.ts`, + const fooBar: File = { + path: `${projectRoot}/node_modules/bar/fooBar.d.ts`, content: `export function fooBar(): string;` }; - const temp: ts.tscWatch.File = { - path: `${ts.tscWatch.projectRoot}/node_modules/bar/temp/index.d.ts`, + const temp: File = { + path: `${projectRoot}/node_modules/bar/temp/index.d.ts`, content: "export function temp(): string;" }; - const files = [ts.tscWatch.libFile, main, bar, foo, fooBar, temp, configFile]; - return ts.tscWatch.createWatchedSystem(files, { currentDirectory: ts.tscWatch.projectRoot, runWithoutRecursiveWatches }); + const files = [libFile, main, bar, foo, fooBar, temp, configFile]; + return createWatchedSystem(files, { currentDirectory: projectRoot, runWithoutRecursiveWatches }); } function verifyWorker(...additionalFlags: string[]) { - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: `watchOptions/with excludeFiles option${additionalFlags.join("")}`, commandLineArgs: ["-w", ...additionalFlags], @@ -536,13 +543,13 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po changes: [ { caption: "Change foo", - change: sys => ts.tscWatch.replaceFileText(sys, `${ts.tscWatch.projectRoot}/node_modules/bar/foo.d.ts`, "foo", "fooBar"), + change: sys => replaceFileText(sys, `${projectRoot}/node_modules/bar/foo.d.ts`, "foo", "fooBar"), timeouts: sys => sys.checkTimeoutQueueLength(0), } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: `watchOptions/with excludeDirectories option${additionalFlags.join("")}`, commandLineArgs: ["-w", ...additionalFlags], @@ -550,12 +557,12 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po changes: [ { caption: "delete fooBar", - change: sys => sys.deleteFile(`${ts.tscWatch.projectRoot}/node_modules/bar/fooBar.d.ts`), + change: sys => sys.deleteFile(`${projectRoot}/node_modules/bar/fooBar.d.ts`), timeouts: sys => sys.checkTimeoutQueueLength(0), } ] }); - ts.tscWatch.verifyTscWatch({ + verifyTscWatch({ scenario, subScenario: `watchOptions/with excludeDirectories option with recursive directory watching${additionalFlags.join("")}`, commandLineArgs: ["-w", ...additionalFlags], @@ -563,7 +570,7 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po changes: [ { caption: "Directory watch updates because of main.js creation", - change: ts.noop, + change: noop, timeouts: sys => { sys.checkTimeoutQueueLengthAndRun(1); // To update directory callbacks for main.js output sys.checkTimeoutQueueLength(0); @@ -571,7 +578,7 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po }, { caption: "add new folder to temp", - change: sys => sys.ensureFileOrFolder({ path: `${ts.tscWatch.projectRoot}/node_modules/bar/temp/fooBar/index.d.ts`, content: "export function temp(): string;" }), + change: sys => sys.ensureFileOrFolder({ path: `${projectRoot}/node_modules/bar/temp/fooBar/index.d.ts`, content: "export function temp(): string;" }), timeouts: sys => sys.checkTimeoutQueueLength(0), } ] diff --git a/src/testRunner/unittests/tsserver/applyChangesToOpenFiles.ts b/src/testRunner/unittests/tsserver/applyChangesToOpenFiles.ts index 06a283de0cc04..24f13a44d0e25 100644 --- a/src/testRunner/unittests/tsserver/applyChangesToOpenFiles.ts +++ b/src/testRunner/unittests/tsserver/applyChangesToOpenFiles.ts @@ -1,52 +1,55 @@ -import * as ts from "../../_namespaces/ts"; +import { ProjectService } from "../../../server/editorServices"; +import { Project } from "../../../server/project"; +import { ApplyChangedToOpenFilesRequest, CommandTypes, OpenRequest, UpdateOpenRequest } from "../../../server/protocol"; +import { commonFile1, commonFile2, createServerHost, createSession, File, libFile, TestSession } from "./helpers"; describe("unittests:: tsserver:: applyChangesToOpenFiles", () => { - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: "{}" }; - const file3: ts.projectSystem.File = { + const file3: File = { path: "/a/b/file3.ts", content: "let xyz = 1;" }; - const app: ts.projectSystem.File = { + const app: File = { path: "/a/b/app.ts", content: "let z = 1;" }; - function fileContentWithComment(file: ts.projectSystem.File) { + function fileContentWithComment(file: File) { return `// some copy right notice ${file.content}`; } - function verifyText(service: ts.server.ProjectService, file: string, expected: string) { + function verifyText(service: ProjectService, file: string, expected: string) { const info = service.getScriptInfo(file)!; const snap = info.getSnapshot(); // Verified applied in reverse order assert.equal(snap.getText(0, snap.getLength()), expected, `Text of changed file: ${file}`); } - function verifyProjectVersion(project: ts.server.Project, expected: number) { + function verifyProjectVersion(project: Project, expected: number) { assert.equal(Number(project.getProjectVersion()), expected); } interface Verify { - applyChangesToOpen: (session: ts.projectSystem.TestSession) => void; - openFile1Again: (session: ts.projectSystem.TestSession) => void; + applyChangesToOpen: (session: TestSession) => void; + openFile1Again: (session: TestSession) => void; } function verify({ applyChangesToOpen, openFile1Again }: Verify) { - const host = ts.projectSystem.createServerHost([app, file3, ts.projectSystem.commonFile1, ts.projectSystem.commonFile2, ts.projectSystem.libFile, configFile]); - const session = ts.projectSystem.createSession(host); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Open, + const host = createServerHost([app, file3, commonFile1, commonFile2, libFile, configFile]); + const session = createSession(host); + session.executeCommandSeq({ + command: CommandTypes.Open, arguments: { file: app.path } }); const service = session.getProjectService(); const project = service.configuredProjects.get(configFile.path)!; assert.isDefined(project); verifyProjectVersion(project, 1); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Open, + session.executeCommandSeq({ + command: CommandTypes.Open, arguments: { file: file3.path, fileContent: fileContentWithComment(file3) @@ -55,8 +58,8 @@ ${file.content}`; verifyProjectVersion(project, 2); // Verify Texts - verifyText(service, ts.projectSystem.commonFile1.path, ts.projectSystem.commonFile1.content); - verifyText(service, ts.projectSystem.commonFile2.path, ts.projectSystem.commonFile2.content); + verifyText(service, commonFile1.path, commonFile1.content); + verifyText(service, commonFile2.path, commonFile2.content); verifyText(service, app.path, app.content); verifyText(service, file3.path, fileContentWithComment(file3)); @@ -66,36 +69,36 @@ ${file.content}`; // Verify again verifyProjectVersion(project, 3); // Open file contents - verifyText(service, ts.projectSystem.commonFile1.path, fileContentWithComment(ts.projectSystem.commonFile1)); - verifyText(service, ts.projectSystem.commonFile2.path, fileContentWithComment(ts.projectSystem.commonFile2)); + verifyText(service, commonFile1.path, fileContentWithComment(commonFile1)); + verifyText(service, commonFile2.path, fileContentWithComment(commonFile2)); verifyText(service, app.path, "let zzz = 10;let zz = 10;let z = 1;"); verifyText(service, file3.path, file3.content); // Open file1 again openFile1Again(session); - assert.isTrue(service.getScriptInfo(ts.projectSystem.commonFile1.path)!.isScriptOpen()); + assert.isTrue(service.getScriptInfo(commonFile1.path)!.isScriptOpen()); // Verify that file1 contents are changed verifyProjectVersion(project, 4); - verifyText(service, ts.projectSystem.commonFile1.path, ts.projectSystem.commonFile1.content); - verifyText(service, ts.projectSystem.commonFile2.path, fileContentWithComment(ts.projectSystem.commonFile2)); + verifyText(service, commonFile1.path, commonFile1.content); + verifyText(service, commonFile2.path, fileContentWithComment(commonFile2)); verifyText(service, app.path, "let zzz = 10;let zz = 10;let z = 1;"); verifyText(service, file3.path, file3.content); } it("with applyChangedToOpenFiles request", () => { verify({ - applyChangesToOpen: session => session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.ApplyChangedToOpenFiles, + applyChangesToOpen: session => session.executeCommandSeq({ + command: CommandTypes.ApplyChangedToOpenFiles, arguments: { openFiles: [ { - fileName: ts.projectSystem.commonFile1.path, - content: fileContentWithComment(ts.projectSystem.commonFile1) + fileName: commonFile1.path, + content: fileContentWithComment(commonFile1) }, { - fileName: ts.projectSystem.commonFile2.path, - content: fileContentWithComment(ts.projectSystem.commonFile2) + fileName: commonFile2.path, + content: fileContentWithComment(commonFile2) } ], changedFiles: [ @@ -118,12 +121,12 @@ ${file.content}`; ] } }), - openFile1Again: session => session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.ApplyChangedToOpenFiles, + openFile1Again: session => session.executeCommandSeq({ + command: CommandTypes.ApplyChangedToOpenFiles, arguments: { openFiles: [{ - fileName: ts.projectSystem.commonFile1.path, - content: ts.projectSystem.commonFile1.content + fileName: commonFile1.path, + content: commonFile1.content }] } }), @@ -132,17 +135,17 @@ ${file.content}`; it("with updateOpen request", () => { verify({ - applyChangesToOpen: session => session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.UpdateOpen, + applyChangesToOpen: session => session.executeCommandSeq({ + command: CommandTypes.UpdateOpen, arguments: { openFiles: [ { - file: ts.projectSystem.commonFile1.path, - fileContent: fileContentWithComment(ts.projectSystem.commonFile1) + file: commonFile1.path, + fileContent: fileContentWithComment(commonFile1) }, { - file: ts.projectSystem.commonFile2.path, - fileContent: fileContentWithComment(ts.projectSystem.commonFile2) + file: commonFile2.path, + fileContent: fileContentWithComment(commonFile2) } ], changedFiles: [ @@ -167,12 +170,12 @@ ${file.content}`; ] } }), - openFile1Again: session => session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.UpdateOpen, + openFile1Again: session => session.executeCommandSeq({ + command: CommandTypes.UpdateOpen, arguments: { openFiles: [{ - file: ts.projectSystem.commonFile1.path, - fileContent: ts.projectSystem.commonFile1.content + file: commonFile1.path, + fileContent: commonFile1.content }] } }), diff --git a/src/testRunner/unittests/tsserver/autoImportProvider.ts b/src/testRunner/unittests/tsserver/autoImportProvider.ts index 110a24ceb3c08..e5ef88ea7bce0 100644 --- a/src/testRunner/unittests/tsserver/autoImportProvider.ts +++ b/src/testRunner/unittests/tsserver/autoImportProvider.ts @@ -1,30 +1,39 @@ -import * as ts from "../../_namespaces/ts"; - -const angularFormsDts: ts.projectSystem.File = { +import { sourceFileAffectingCompilerOptions } from "../../../compiler/commandLineParser"; +import { flatten, hasProperty } from "../../../compiler/core"; +import { Debug } from "../../../compiler/debug"; +import { AutoImportProviderProject, ProjectKind } from "../../../server/project"; +import { ApplyChangedToOpenFilesRequest, CommandTypes, ReferencesRequest } from "../../../server/protocol"; +import { NormalizedPath } from "../../../server/utilitiesPublic"; +import { + checkNumberOfConfiguredProjects, checkNumberOfInferredProjects, createServerHost, createSession, File, + openFilesForSession, +} from "./helpers"; + +const angularFormsDts: File = { path: "/node_modules/@angular/forms/forms.d.ts", content: "export declare class PatternValidator {}", }; -const angularFormsPackageJson: ts.projectSystem.File = { +const angularFormsPackageJson: File = { path: "/node_modules/@angular/forms/package.json", content: `{ "name": "@angular/forms", "typings": "./forms.d.ts" }`, }; -const angularCoreDts: ts.projectSystem.File = { +const angularCoreDts: File = { path: "/node_modules/@angular/core/core.d.ts", content: "", }; -const angularCorePackageJson: ts.projectSystem.File = { +const angularCorePackageJson: File = { path: "/node_modules/@angular/core/package.json", content: `{ "name": "@angular/core", "typings": "./core.d.ts" }`, }; -const tsconfig: ts.projectSystem.File = { +const tsconfig: File = { path: "/tsconfig.json", content: `{ "compilerOptions": { "module": "commonjs" } }`, }; -const packageJson: ts.projectSystem.File = { +const packageJson: File = { path: "/package.json", content: `{ "dependencies": { "@angular/forms": "*", "@angular/core": "*" } }` }; -const indexTs: ts.projectSystem.File = { +const indexTs: File = { path: "/index.ts", content: "" }; @@ -38,7 +47,7 @@ describe("unittests:: tsserver:: autoImportProvider", () => { { path: packageJson.path, content: `{ "dependencies": {} }` }, indexTs ]); - ts.projectSystem.openFilesForSession([indexTs], session); + openFilesForSession([indexTs], session); assert.isUndefined(projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider()); }); @@ -50,7 +59,7 @@ describe("unittests:: tsserver:: autoImportProvider", () => { packageJson, { path: indexTs.path, content: "import '@angular/forms';" } ]); - ts.projectSystem.openFilesForSession([indexTs], session); + openFilesForSession([indexTs], session); assert.isUndefined(projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider()); }); @@ -64,28 +73,28 @@ describe("unittests:: tsserver:: autoImportProvider", () => { { path: "/node_modules/@angular/core/core.d.ts", content: `export namespace angular {};` }, ]); - ts.projectSystem.openFilesForSession([angularFormsDts], session); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 1); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 0); + openFilesForSession([angularFormsDts], session); + checkNumberOfInferredProjects(projectService, 1); + checkNumberOfConfiguredProjects(projectService, 0); assert.isUndefined(projectService - .getDefaultProjectForFile(angularFormsDts.path as ts.server.NormalizedPath, /*ensureProject*/ true)! + .getDefaultProjectForFile(angularFormsDts.path as NormalizedPath, /*ensureProject*/ true)! .getLanguageService() .getAutoImportProvider()); }); it("Auto-importable file is in inferred project until imported", () => { const { projectService, session, updateFile } = setup([angularFormsDts, angularFormsPackageJson, tsconfig, packageJson, indexTs]); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 0); - ts.projectSystem.openFilesForSession([angularFormsDts], session); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 1); + checkNumberOfInferredProjects(projectService, 0); + openFilesForSession([angularFormsDts], session); + checkNumberOfInferredProjects(projectService, 1); assert.equal( - projectService.getDefaultProjectForFile(angularFormsDts.path as ts.server.NormalizedPath, /*ensureProject*/ true)?.projectKind, - ts.server.ProjectKind.Inferred); + projectService.getDefaultProjectForFile(angularFormsDts.path as NormalizedPath, /*ensureProject*/ true)?.projectKind, + ProjectKind.Inferred); updateFile(indexTs.path, "import '@angular/forms'"); assert.equal( - projectService.getDefaultProjectForFile(angularFormsDts.path as ts.server.NormalizedPath, /*ensureProject*/ true)?.projectKind, - ts.server.ProjectKind.Configured); + projectService.getDefaultProjectForFile(angularFormsDts.path as NormalizedPath, /*ensureProject*/ true)?.projectKind, + ProjectKind.Configured); assert.isUndefined(projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider()); }); @@ -99,7 +108,7 @@ describe("unittests:: tsserver:: autoImportProvider", () => { indexTs ]); - ts.projectSystem.openFilesForSession([indexTs], session); + openFilesForSession([indexTs], session); assert.isUndefined(projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider()); host.writeFile(packageJson.path, packageJson.content); @@ -115,7 +124,7 @@ describe("unittests:: tsserver:: autoImportProvider", () => { indexTs ]); - ts.projectSystem.openFilesForSession([indexTs], session); + openFilesForSession([indexTs], session); const autoImportProvider = projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider(); assert.ok(autoImportProvider); @@ -134,7 +143,7 @@ describe("unittests:: tsserver:: autoImportProvider", () => { indexTs ]); - ts.projectSystem.openFilesForSession([indexTs], session); + openFilesForSession([indexTs], session); const hostProject = projectService.configuredProjects.get(tsconfig.path)!; hostProject.getPackageJsonAutoImportProvider(); const autoImportProviderProject = hostProject.autoImportProviderHost; @@ -154,7 +163,7 @@ describe("unittests:: tsserver:: autoImportProvider", () => { ]); // Create configured project only, ensure !projectService.pendingEnsureProjectForOpenFiles - ts.projectSystem.openFilesForSession([indexTs], session); + openFilesForSession([indexTs], session); const hostProject = projectService.configuredProjects.get(tsconfig.path)!; projectService.delayEnsureProjectForOpenFiles(); host.runQueuedTimeoutCallbacks(); @@ -177,7 +186,7 @@ describe("unittests:: tsserver:: autoImportProvider", () => { indexTs ]); - ts.projectSystem.openFilesForSession([indexTs], session); + openFilesForSession([indexTs], session); const project = projectService.configuredProjects.get(tsconfig.path)!; const completionsBefore = project.getLanguageService().getCompletionsAtPosition(indexTs.path, 0, { includeCompletionsForModuleExports: true }); assert.isTrue(completionsBefore?.entries.some(c => c.name === "PatternValidator")); @@ -204,7 +213,7 @@ describe("unittests:: tsserver:: autoImportProvider", () => { indexTs ]); - ts.projectSystem.openFilesForSession([indexTs, angularFormsDts], session); + openFilesForSession([indexTs, angularFormsDts], session); const project = projectService.configuredProjects.get(tsconfig.path)!; const completionsBefore = project.getLanguageService().getCompletionsAtPosition(indexTs.path, 0, { includeCompletionsForModuleExports: true }); assert.isTrue(completionsBefore?.entries.some(c => c.name === "PatternValidator")); @@ -224,7 +233,7 @@ describe("unittests:: tsserver:: autoImportProvider", () => { indexTs ]); - ts.projectSystem.openFilesForSession([indexTs], session); + openFilesForSession([indexTs], session); assert.isUndefined(projectService.configuredProjects.get(tsconfig.path)!.getLanguageService().getAutoImportProvider()); host.writeFile(packageJson.path, packageJson.content); @@ -232,7 +241,7 @@ describe("unittests:: tsserver:: autoImportProvider", () => { }); it("Does not create an auto import provider if there are too many dependencies", () => { - const createPackage = (i: number): ts.projectSystem.File[] => ([ + const createPackage = (i: number): File[] => ([ { path: `/node_modules/package${i}/package.json`, content: `{ "name": "package${i}" }` }, { path: `/node_modules/package${i}/index.d.ts`, content: `` } ]); @@ -243,10 +252,10 @@ describe("unittests:: tsserver:: autoImportProvider", () => { } const dependencies = packages.reduce((hash, p) => ({ ...hash, [JSON.parse(p[0].content).name]: "*" }), {}); - const packageJson: ts.projectSystem.File = { path: "/package.json", content: JSON.stringify(dependencies) }; - const { projectService, session } = setup([ ...ts.flatten(packages), indexTs, tsconfig, packageJson ]); + const packageJson: File = { path: "/package.json", content: JSON.stringify(dependencies) }; + const { projectService, session } = setup([ ...flatten(packages), indexTs, tsconfig, packageJson ]); - ts.projectSystem.openFilesForSession([indexTs], session); + openFilesForSession([indexTs], session); const project = projectService.configuredProjects.get(tsconfig.path)!; assert.isUndefined(project.getPackageJsonAutoImportProvider()); }); @@ -276,10 +285,10 @@ describe("unittests:: tsserver:: autoImportProvider - monorepo", () => { const { projectService, session, findAllReferences } = setup(files); - ts.projectSystem.openFilesForSession([files.find(f => f.path === "/packages/b/index.ts")!], session); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 2); // Solution (no files), B + openFilesForSession([files.find(f => f.path === "/packages/b/index.ts")!], session); + checkNumberOfConfiguredProjects(projectService, 2); // Solution (no files), B findAllReferences("/packages/b/index.ts", 1, "export class B".length - 1); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 3); // Solution (no files), A, B + checkNumberOfConfiguredProjects(projectService, 3); // Solution (no files), A, B // Project for A is created - ensure it doesn't have an autoImportProvider assert.isUndefined(projectService.configuredProjects.get("/packages/a/tsconfig.json")!.getLanguageService().getAutoImportProvider()); @@ -299,24 +308,24 @@ describe("unittests:: tsserver:: autoImportProvider - monorepo", () => { ]; const { projectService, session } = setup(files); - ts.projectSystem.openFilesForSession([files[2]], session); + openFilesForSession([files[2]], session); assert.isDefined(projectService.configuredProjects.get("/packages/a/tsconfig.json")!.getPackageJsonAutoImportProvider()); assert.isDefined(projectService.configuredProjects.get("/packages/a/tsconfig.json")!.getPackageJsonAutoImportProvider()); }); it("Can use the same document registry bucket key as main program", () => { - for (const option of ts.sourceFileAffectingCompilerOptions) { + for (const option of sourceFileAffectingCompilerOptions) { assert( - !ts.hasProperty(ts.server.AutoImportProviderProject.compilerOptionsOverrides, option.name), + !hasProperty(AutoImportProviderProject.compilerOptionsOverrides, option.name), `'${option.name}' may cause AutoImportProviderProject not to share source files with main program` ); } }); }); -function setup(files: ts.projectSystem.File[]) { - const host = ts.projectSystem.createServerHost(files); - const session = ts.projectSystem.createSession(host); +function setup(files: File[]) { + const host = createServerHost(files); + const session = createSession(host); const projectService = session.getProjectService(); return { host, @@ -327,9 +336,9 @@ function setup(files: ts.projectSystem.File[]) { }; function updateFile(path: string, newText: string) { - ts.Debug.assertIsDefined(files.find(f => f.path === path)); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.ApplyChangedToOpenFiles, + Debug.assertIsDefined(files.find(f => f.path === path)); + session.executeCommandSeq({ + command: CommandTypes.ApplyChangedToOpenFiles, arguments: { openFiles: [{ fileName: path, @@ -340,9 +349,9 @@ function setup(files: ts.projectSystem.File[]) { } function findAllReferences(file: string, line: number, offset: number) { - ts.Debug.assertIsDefined(files.find(f => f.path === file)); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.References, + Debug.assertIsDefined(files.find(f => f.path === file)); + session.executeCommandSeq({ + command: CommandTypes.References, arguments: { file, line, diff --git a/src/testRunner/unittests/tsserver/auxiliaryProject.ts b/src/testRunner/unittests/tsserver/auxiliaryProject.ts index c7f2aa44fb7ec..e9aaad3d82885 100644 --- a/src/testRunner/unittests/tsserver/auxiliaryProject.ts +++ b/src/testRunner/unittests/tsserver/auxiliaryProject.ts @@ -1,26 +1,28 @@ -import * as ts from "../../_namespaces/ts"; +import { Debug } from "../../../compiler/debug"; +import { ProjectKind } from "../../../server/project"; +import { checkNumberOfInferredProjects, createServerHost, createSession, File, openFilesForSession } from "./helpers"; -const aTs: ts.projectSystem.File = { +const aTs: File = { path: "/a.ts", content: `import { B } from "./b";` }; -const bDts: ts.projectSystem.File = { +const bDts: File = { path: "/b.d.ts", content: `export declare class B {}` }; -const bJs: ts.projectSystem.File = { +const bJs: File = { path: "/b.js", content: `export class B {}` }; describe("unittests:: tsserver:: auxiliaryProject", () => { it("AuxiliaryProject does not remove scrips from InferredProject", () => { - const host = ts.projectSystem.createServerHost([aTs, bDts, bJs]); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([aTs, bDts, bJs]); + const session = createSession(host); const projectService = session.getProjectService(); - ts.projectSystem.openFilesForSession([aTs], session); + openFilesForSession([aTs], session); // Open file is in inferred project - ts.projectSystem.checkNumberOfInferredProjects(projectService, 1); + checkNumberOfInferredProjects(projectService, 1); const inferredProject = projectService.inferredProjects[0]; // getNoDtsResolutionProject will create an AuxiliaryProject with a.ts and b.js @@ -31,7 +33,7 @@ describe("unittests:: tsserver:: auxiliaryProject", () => { // The AuxiliaryProject should never be the default project for anything, so // the ScriptInfo should still report being an orphan, and getting its default // project should throw. - const bJsScriptInfo = ts.Debug.checkDefined(projectService.getScriptInfo(bJs.path)); + const bJsScriptInfo = Debug.checkDefined(projectService.getScriptInfo(bJs.path)); assert(bJsScriptInfo.isOrphan()); assert(bJsScriptInfo.isContainedByBackgroundProject()); assert.deepEqual(bJsScriptInfo.containingProjects, [auxProject]); @@ -39,10 +41,10 @@ describe("unittests:: tsserver:: auxiliaryProject", () => { // When b.js is opened in the editor, it should be put into an InferredProject // even though it's still contained by the AuxiliaryProject. - ts.projectSystem.openFilesForSession([bJs], session); + openFilesForSession([bJs], session); assert(!bJsScriptInfo.isOrphan()); assert(bJsScriptInfo.isContainedByBackgroundProject()); - assert.equal(bJsScriptInfo.getDefaultProject().projectKind, ts.server.ProjectKind.Inferred); + assert.equal(bJsScriptInfo.getDefaultProject().projectKind, ProjectKind.Inferred); }); }); diff --git a/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts b/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts index 798f9ebc24570..3186ddeabf766 100644 --- a/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts +++ b/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts @@ -1,7 +1,26 @@ -import * as ts from "../../_namespaces/ts"; +import { + arrayFrom, countWhere, createMultiMap, filter, find, forEach, last, map, mapDefined, MultiMap, returnTrue, + startsWith, +} from "../../../compiler/core"; +import { ESMap, Map } from "../../../compiler/corePublic"; +import { Debug } from "../../../compiler/debug"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { combinePaths, directorySeparator, forEachAncestorDirectory, getDirectoryPath } from "../../../compiler/path"; +import { flattenDiagnosticMessageText } from "../../../compiler/program"; +import { ModuleKind, Path, ScriptTarget } from "../../../compiler/types"; +import { checkMap } from "../../../harness/virtualFileSystemWithWatch"; +import { CommandTypes, FileLocationRequestArgs, FileSpan } from "../../../server/protocol"; +import { NormalizedPath } from "../../../server/utilitiesPublic"; +import { projectRoot } from "../tscWatch/helpers"; +import { + checkNumberOfConfiguredProjects, checkNumberOfProjects, checkProjectActualFiles, checkWatchedDirectories, + checkWatchedFiles, createProjectService, createServerHost, createSession, File, getNodeModuleDirectories, + getTypeRootsFromLocation, libFile, makeSessionRequest, mapCombinedPathsInAncestor, nodeModules, nodeModulesAtTypes, + SymLink, TestServerHost, +} from "./helpers"; function getNumberOfWatchesInvokedForRecursiveWatches(recursiveWatchedDirs: string[], file: string) { - return ts.countWhere(recursiveWatchedDirs, dir => file.length > dir.length && ts.startsWith(file, dir) && file[dir.length] === ts.directorySeparator); + return countWhere(recursiveWatchedDirs, dir => file.length > dir.length && startsWith(file, dir) && file[dir.length] === directorySeparator); } describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectSystem CachingFileSystemInformation", () => { @@ -16,8 +35,8 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS } type CalledMaps = CalledMapsWithSingleArg | CalledMapsWithFiveArgs; type CalledWithFiveArgs = [readonly string[], readonly string[], readonly string[], number]; - function createCallsTrackingHost(host: ts.projectSystem.TestServerHost) { - const calledMaps: Record> & Record> = { + function createCallsTrackingHost(host: TestServerHost) { + const calledMaps: Record> & Record> = { fileExists: setCallsTrackingWithSingleArgFn(CalledMapsWithSingleArg.fileExists), directoryExists: setCallsTrackingWithSingleArgFn(CalledMapsWithSingleArg.directoryExists), getDirectories: setCallsTrackingWithSingleArgFn(CalledMapsWithSingleArg.getDirectories), @@ -36,7 +55,7 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS }; function setCallsTrackingWithSingleArgFn(prop: CalledMapsWithSingleArg) { - const calledMap = ts.createMultiMap(); + const calledMap = createMultiMap(); const cb = (host as any)[prop].bind(host); (host as any)[prop] = (f: string) => { calledMap.add(f, /*value*/ true); @@ -46,7 +65,7 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS } function setCallsTrackingWithFiveArgFn(prop: CalledMapsWithFiveArgs) { - const calledMap = ts.createMultiMap<[U, V, W, X]>(); + const calledMap = createMultiMap<[U, V, W, X]>(); const cb = (host as any)[prop].bind(host); (host as any)[prop] = (f: string, arg1?: U, arg2?: V, arg3?: W, arg4?: X) => { calledMap.add(f, [arg1!, arg2!, arg3!, arg4!]); // TODO: GH#18217 @@ -58,20 +77,20 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS function verifyCalledOn(callback: CalledMaps, name: string) { const calledMap = calledMaps[callback]; const result = calledMap.get(name); - assert.isTrue(result && !!result.length, `${callback} should be called with name: ${name}: ${ts.arrayFrom(calledMap.keys())}`); + assert.isTrue(result && !!result.length, `${callback} should be called with name: ${name}: ${arrayFrom(calledMap.keys())}`); } function verifyNoCall(callback: CalledMaps) { const calledMap = calledMaps[callback]; - assert.equal(calledMap.size, 0, `${callback} shouldn't be called: ${ts.arrayFrom(calledMap.keys())}`); + assert.equal(calledMap.size, 0, `${callback} shouldn't be called: ${arrayFrom(calledMap.keys())}`); } - function verifyCalledOnEachEntry(callback: CalledMaps, expectedKeys: ts.ESMap) { - ts.TestFSWithWatch.checkMap(callback, calledMaps[callback], expectedKeys); + function verifyCalledOnEachEntry(callback: CalledMaps, expectedKeys: ESMap) { + checkMap(callback, calledMaps[callback], expectedKeys); } function verifyCalledOnEachEntryNTimes(callback: CalledMaps, expectedKeys: readonly string[], nTimes: number) { - ts.TestFSWithWatch.checkMap(callback, calledMaps[callback], expectedKeys, nTimes); + checkMap(callback, calledMaps[callback], expectedKeys, nTimes); } function verifyNoHostCalls() { @@ -102,21 +121,21 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS it("works using legacy resolution logic", () => { let rootContent = `import {x} from "f1"`; - const root: ts.projectSystem.File = { + const root: File = { path: "/c/d/f0.ts", content: rootContent }; - const imported: ts.projectSystem.File = { + const imported: File = { path: "/c/f1.ts", content: `foo()` }; - const host = ts.projectSystem.createServerHost([root, imported]); - const projectService = ts.projectSystem.createProjectService(host); - projectService.setCompilerOptionsForInferredProjects({ module: ts.ModuleKind.AMD, noLib: true }); + const host = createServerHost([root, imported]); + const projectService = createProjectService(host); + projectService.setCompilerOptionsForInferredProjects({ module: ModuleKind.AMD, noLib: true }); projectService.openClientFile(root.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); const project = projectService.inferredProjects[0]; const rootScriptInfo = project.getRootScriptInfos()[0]; assert.equal(rootScriptInfo.fileName, root.path); @@ -155,12 +174,12 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS verifyImportedDiagnostics(); const f1Lookups = f2Lookups.map(s => s.replace("f2", "f1")); f1Lookups.length = f1Lookups.indexOf(imported.path) + 1; - const f1DirLookups = ["/c/d", "/c", ...ts.projectSystem.mapCombinedPathsInAncestor(ts.getDirectoryPath(root.path), ts.projectSystem.nodeModulesAtTypes, ts.returnTrue)]; + const f1DirLookups = ["/c/d", "/c", ...mapCombinedPathsInAncestor(getDirectoryPath(root.path), nodeModulesAtTypes, returnTrue)]; vertifyF1Lookups(); // setting compiler options discards module resolution cache callsTrackingHost.clear(); - projectService.setCompilerOptionsForInferredProjects({ module: ts.ModuleKind.AMD, noLib: true, target: ts.ScriptTarget.ES5 }); + projectService.setCompilerOptionsForInferredProjects({ module: ModuleKind.AMD, noLib: true, target: ScriptTarget.ES5 }); verifyImportedDiagnostics(); vertifyF1Lookups(); @@ -182,58 +201,58 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS const diags = project.getLanguageService().getSemanticDiagnostics(imported.path); assert.equal(diags.length, 1); const diag = diags[0]; - assert.equal(diag.code, ts.Diagnostics.Cannot_find_name_0.code); - assert.equal(ts.flattenDiagnosticMessageText(diag.messageText, "\n"), "Cannot find name 'foo'."); + assert.equal(diag.code, Diagnostics.Cannot_find_name_0.code); + assert.equal(flattenDiagnosticMessageText(diag.messageText, "\n"), "Cannot find name 'foo'."); } function getLocationsForModuleLookup(module: string) { const locations: string[] = []; - ts.forEachAncestorDirectory(ts.getDirectoryPath(root.path), ancestor => { + forEachAncestorDirectory(getDirectoryPath(root.path), ancestor => { locations.push( - ts.combinePaths(ancestor, `${module}.ts`), - ts.combinePaths(ancestor, `${module}.tsx`), - ts.combinePaths(ancestor, `${module}.d.ts`) + combinePaths(ancestor, `${module}.ts`), + combinePaths(ancestor, `${module}.tsx`), + combinePaths(ancestor, `${module}.d.ts`) ); }); - ts.forEachAncestorDirectory(ts.getDirectoryPath(root.path), ancestor => { + forEachAncestorDirectory(getDirectoryPath(root.path), ancestor => { locations.push( - ts.combinePaths(ancestor, `${module}.js`), - ts.combinePaths(ancestor, `${module}.jsx`) + combinePaths(ancestor, `${module}.js`), + combinePaths(ancestor, `${module}.jsx`) ); }); return locations; } function getLocationsForDirectoryLookup() { - const result = new ts.Map(); - ts.forEachAncestorDirectory(ts.getDirectoryPath(root.path), ancestor => { + const result = new Map(); + forEachAncestorDirectory(getDirectoryPath(root.path), ancestor => { // To resolve modules result.set(ancestor, 2); // for type roots - result.set(ts.combinePaths(ancestor, ts.projectSystem.nodeModules), 1); - result.set(ts.combinePaths(ancestor, ts.projectSystem.nodeModulesAtTypes), 1); + result.set(combinePaths(ancestor, nodeModules), 1); + result.set(combinePaths(ancestor, nodeModulesAtTypes), 1); }); return result; } }); it("loads missing files from disk", () => { - const root: ts.projectSystem.File = { + const root: File = { path: "/c/foo.ts", content: `import {y} from "bar"` }; - const imported: ts.projectSystem.File = { + const imported: File = { path: "/c/bar.d.ts", content: `export var y = 1` }; - const host = ts.projectSystem.createServerHost([root]); - const projectService = ts.projectSystem.createProjectService(host); - projectService.setCompilerOptionsForInferredProjects({ module: ts.ModuleKind.AMD, noLib: true }); + const host = createServerHost([root]); + const projectService = createProjectService(host); + projectService.setCompilerOptionsForInferredProjects({ module: ModuleKind.AMD, noLib: true }); const callsTrackingHost = createCallsTrackingHost(host); projectService.openClientFile(root.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); const project = projectService.inferredProjects[0]; const rootScriptInfo = project.getRootScriptInfos()[0]; assert.equal(rootScriptInfo.fileName, root.path); @@ -241,8 +260,8 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS let diags = project.getLanguageService().getSemanticDiagnostics(root.path); assert.equal(diags.length, 1); const diag = diags[0]; - assert.equal(diag.code, ts.Diagnostics.Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_node_or_to_add_aliases_to_the_paths_option.code); - assert.equal(ts.flattenDiagnosticMessageText(diag.messageText, "\n"), "Cannot find module 'bar'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option?"); + assert.equal(diag.code, Diagnostics.Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_node_or_to_add_aliases_to_the_paths_option.code); + assert.equal(flattenDiagnosticMessageText(diag.messageText, "\n"), "Cannot find module 'bar'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option?"); callsTrackingHost.verifyCalledOn(CalledMapsWithSingleArg.fileExists, imported.path); @@ -255,25 +274,25 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS }); it("when calling goto definition of module", () => { - const clientFile: ts.projectSystem.File = { + const clientFile: File = { path: "/a/b/controllers/vessels/client.ts", content: ` import { Vessel } from '~/models/vessel'; const v = new Vessel(); ` }; - const anotherModuleFile: ts.projectSystem.File = { + const anotherModuleFile: File = { path: "/a/b/utils/db.ts", content: "export class Bookshelf { }" }; - const moduleFile: ts.projectSystem.File = { + const moduleFile: File = { path: "/a/b/models/vessel.ts", content: ` import { Bookshelf } from '~/utils/db'; export class Vessel extends Bookshelf {} ` }; - const tsconfigFile: ts.projectSystem.File = { + const tsconfigFile: File = { path: "/a/b/tsconfig.json", content: JSON.stringify({ compilerOptions: { @@ -296,27 +315,27 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS }) }; const projectFiles = [clientFile, anotherModuleFile, moduleFile, tsconfigFile]; - const host = ts.projectSystem.createServerHost(projectFiles); - const session = ts.projectSystem.createSession(host); + const host = createServerHost(projectFiles); + const session = createSession(host); const projectService = session.getProjectService(); const { configFileName } = projectService.openClientFile(clientFile.path); assert.isDefined(configFileName, `should find config`); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); + checkNumberOfConfiguredProjects(projectService, 1); const project = projectService.configuredProjects.get(tsconfigFile.path)!; - ts.projectSystem.checkProjectActualFiles(project, ts.map(projectFiles, f => f.path)); + checkProjectActualFiles(project, map(projectFiles, f => f.path)); const callsTrackingHost = createCallsTrackingHost(host); // Get definitions shouldnt make host requests - const getDefinitionRequest = ts.projectSystem.makeSessionRequest(ts.projectSystem.protocol.CommandTypes.Definition, { + const getDefinitionRequest = makeSessionRequest(CommandTypes.Definition, { file: clientFile.path, position: clientFile.content.indexOf("/vessel") + 1, line: undefined!, // TODO: GH#18217 offset: undefined! // TODO: GH#18217 }); - const response = session.executeCommand(getDefinitionRequest).response as ts.server.protocol.FileSpan[]; + const response = session.executeCommand(getDefinitionRequest).response as FileSpan[]; assert.equal(response[0].file, moduleFile.path, "Should go to definition of vessel: response: " + JSON.stringify(response)); callsTrackingHost.verifyNoHostCalls(); @@ -325,34 +344,34 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS assert.equal(config2, configFileName); callsTrackingHost.verifyNoHostCallsExceptFileExistsOnce(["/a/b/models/tsconfig.json", "/a/b/models/jsconfig.json"]); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); + checkNumberOfConfiguredProjects(projectService, 1); assert.strictEqual(projectService.configuredProjects.get(tsconfigFile.path), project); }); describe("WatchDirectories for config file with", () => { function verifyWatchDirectoriesCaseSensitivity(useCaseSensitiveFileNames: boolean) { const frontendDir = "/Users/someuser/work/applications/frontend"; - const toCanonical: (s: string) => ts.Path = useCaseSensitiveFileNames ? s => s as ts.Path : s => s.toLowerCase() as ts.Path; + const toCanonical: (s: string) => Path = useCaseSensitiveFileNames ? s => s as Path : s => s.toLowerCase() as Path; const canonicalFrontendDir = toCanonical(frontendDir); - const file1: ts.projectSystem.File = { + const file1: File = { path: `${frontendDir}/src/app/utils/Analytic.ts`, content: "export class SomeClass { };" }; - const file2: ts.projectSystem.File = { + const file2: File = { path: `${frontendDir}/src/app/redux/configureStore.ts`, content: "export class configureStore { }" }; - const file3: ts.projectSystem.File = { + const file3: File = { path: `${frontendDir}/src/app/utils/Cookie.ts`, content: "export class Cookie { }" }; - const es2016LibFile: ts.projectSystem.File = { + const es2016LibFile: File = { path: "/a/lib/lib.es2016.full.d.ts", - content: ts.projectSystem.libFile.content + content: libFile.content }; const typeRoots = ["types", "node_modules/@types"]; const types = ["node", "jest"]; - const tsconfigFile: ts.projectSystem.File = { + const tsconfigFile: File = { path: `${frontendDir}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { @@ -386,13 +405,13 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS }) }; const projectFiles = [file1, file2, es2016LibFile, tsconfigFile]; - const host = ts.projectSystem.createServerHost(projectFiles, { useCaseSensitiveFileNames }); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost(projectFiles, { useCaseSensitiveFileNames }); + const projectService = createProjectService(host); const canonicalConfigPath = toCanonical(tsconfigFile.path); const { configFileName } = projectService.openClientFile(file1.path); - assert.equal(configFileName, tsconfigFile.path as ts.server.NormalizedPath, `should find config`); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); - const watchingRecursiveDirectories = [`${canonicalFrontendDir}/src`, `${canonicalFrontendDir}/types`, `${canonicalFrontendDir}/node_modules`].concat(ts.projectSystem.getNodeModuleDirectories(ts.getDirectoryPath(canonicalFrontendDir))); + assert.equal(configFileName, tsconfigFile.path as NormalizedPath, `should find config`); + checkNumberOfConfiguredProjects(projectService, 1); + const watchingRecursiveDirectories = [`${canonicalFrontendDir}/src`, `${canonicalFrontendDir}/types`, `${canonicalFrontendDir}/node_modules`].concat(getNodeModuleDirectories(getDirectoryPath(canonicalFrontendDir))); const project = projectService.configuredProjects.get(canonicalConfigPath)!; verifyProjectAndWatchedDirectories(); @@ -412,7 +431,7 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS callsTrackingHost.verifyCalledOnEachEntryNTimes(CalledMapsWithSingleArg.readFile, [file3.path], 1); callsTrackingHost.verifyNoCall(CalledMapsWithFiveArgs.readDirectory); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); + checkNumberOfConfiguredProjects(projectService, 1); assert.strictEqual(projectService.configuredProjects.get(canonicalConfigPath), project); verifyProjectAndWatchedDirectories(); @@ -421,22 +440,22 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS const { configFileName: configFile2 } = projectService.openClientFile(file3.path); assert.equal(configFile2, configFileName); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); + checkNumberOfConfiguredProjects(projectService, 1); assert.strictEqual(projectService.configuredProjects.get(canonicalConfigPath), project); verifyProjectAndWatchedDirectories(); callsTrackingHost.verifyNoHostCalls(); - function getFilePathIfNotOpen(f: ts.projectSystem.File) { + function getFilePathIfNotOpen(f: File) { const path = toCanonical(f.path); const info = projectService.getScriptInfoForPath(toCanonical(f.path)); return info && info.isScriptOpen() ? undefined : path; } function verifyProjectAndWatchedDirectories() { - ts.projectSystem.checkProjectActualFiles(project, ts.map(projectFiles, f => f.path)); - ts.projectSystem.checkWatchedFiles(host, ts.mapDefined(projectFiles, getFilePathIfNotOpen)); - ts.projectSystem.checkWatchedDirectories(host, watchingRecursiveDirectories, /*recursive*/ true); - ts.projectSystem.checkWatchedDirectories(host, [], /*recursive*/ false); + checkProjectActualFiles(project, map(projectFiles, f => f.path)); + checkWatchedFiles(host, mapDefined(projectFiles, getFilePathIfNotOpen)); + checkWatchedDirectories(host, watchingRecursiveDirectories, /*recursive*/ true); + checkWatchedDirectories(host, [], /*recursive*/ false); } } @@ -452,15 +471,15 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS describe("Subfolder invalidations correctly include parent folder failed lookup locations", () => { function runFailedLookupTest(resolution: "Node" | "Classic") { const projectLocation = "/proj"; - const file1: ts.projectSystem.File = { + const file1: File = { path: `${projectLocation}/foo/boo/app.ts`, content: `import * as debug from "debug"` }; - const file2: ts.projectSystem.File = { + const file2: File = { path: `${projectLocation}/foo/boo/moo/app.ts`, content: `import * as debug from "debug"` }; - const tsconfig: ts.projectSystem.File = { + const tsconfig: File = { path: `${projectLocation}/tsconfig.json`, content: JSON.stringify({ files: ["foo/boo/app.ts", "foo/boo/moo/app.ts"], @@ -468,17 +487,17 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS }) }; - const files = [file1, file2, tsconfig, ts.projectSystem.libFile]; - const host = ts.projectSystem.createServerHost(files); - const service = ts.projectSystem.createProjectService(host); + const files = [file1, file2, tsconfig, libFile]; + const host = createServerHost(files); + const service = createProjectService(host); service.openClientFile(file1.path); const project = service.configuredProjects.get(tsconfig.path)!; - ts.projectSystem.checkProjectActualFiles(project, files.map(f => f.path)); + checkProjectActualFiles(project, files.map(f => f.path)); assert.deepEqual(project.getLanguageService().getSemanticDiagnostics(file1.path).map(diag => diag.messageText), ["Cannot find module 'debug' or its corresponding type declarations."]); assert.deepEqual(project.getLanguageService().getSemanticDiagnostics(file2.path).map(diag => diag.messageText), ["Cannot find module 'debug' or its corresponding type declarations."]); - const debugTypesFile: ts.projectSystem.File = { + const debugTypesFile: File = { path: `${projectLocation}/node_modules/debug/index.d.ts`, content: "export {}" }; @@ -486,7 +505,7 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS host.writeFile(debugTypesFile.path, debugTypesFile.content); host.runQueuedTimeoutCallbacks(); // Scheduled invalidation of resolutions host.runQueuedTimeoutCallbacks(); // Actual update - ts.projectSystem.checkProjectActualFiles(project, files.map(f => f.path)); + checkProjectActualFiles(project, files.map(f => f.path)); assert.deepEqual(project.getLanguageService().getSemanticDiagnostics(file1.path).map(diag => diag.messageText), []); assert.deepEqual(project.getLanguageService().getSemanticDiagnostics(file2.path).map(diag => diag.messageText), []); } @@ -502,19 +521,19 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS describe("Verify npm install in directory with tsconfig file works when", () => { function verifyNpmInstall(timeoutDuringPartialInstallation: boolean) { const root = "/user/username/rootfolder/otherfolder"; - const getRootedFileOrFolder = (fileOrFolder: ts.projectSystem.File) => { + const getRootedFileOrFolder = (fileOrFolder: File) => { fileOrFolder.path = root + fileOrFolder.path; return fileOrFolder; }; - const app: ts.projectSystem.File = getRootedFileOrFolder({ + const app: File = getRootedFileOrFolder({ path: "/a/b/app.ts", content: "import _ from 'lodash';" }); - const tsconfigJson: ts.projectSystem.File = getRootedFileOrFolder({ + const tsconfigJson: File = getRootedFileOrFolder({ path: "/a/b/tsconfig.json", content: '{ "compilerOptions": { } }' }); - const packageJson: ts.projectSystem.File = getRootedFileOrFolder({ + const packageJson: File = getRootedFileOrFolder({ path: "/a/b/package.json", content: ` { @@ -539,22 +558,22 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS } ` }); - const appFolder = ts.getDirectoryPath(app.path); - const projectFiles = [app, ts.projectSystem.libFile, tsconfigJson]; - const typeRootDirectories = ts.projectSystem.getTypeRootsFromLocation(ts.getDirectoryPath(tsconfigJson.path)); + const appFolder = getDirectoryPath(app.path); + const projectFiles = [app, libFile, tsconfigJson]; + const typeRootDirectories = getTypeRootsFromLocation(getDirectoryPath(tsconfigJson.path)); const otherFiles = [packageJson]; - const host = ts.projectSystem.createServerHost(projectFiles.concat(otherFiles)); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost(projectFiles.concat(otherFiles)); + const projectService = createProjectService(host); projectService.setHostConfiguration({ preferences: { includePackageJsonAutoImports: "off" } }); const { configFileName } = projectService.openClientFile(app.path); - assert.equal(configFileName, tsconfigJson.path as ts.server.NormalizedPath, `should find config`); // TODO: GH#18217 - const recursiveWatchedDirectories: string[] = [`${appFolder}`, `${appFolder}/node_modules`].concat(ts.projectSystem.getNodeModuleDirectories(ts.getDirectoryPath(appFolder))); + assert.equal(configFileName, tsconfigJson.path as NormalizedPath, `should find config`); // TODO: GH#18217 + const recursiveWatchedDirectories: string[] = [`${appFolder}`, `${appFolder}/node_modules`].concat(getNodeModuleDirectories(getDirectoryPath(appFolder))); verifyProject(); let npmInstallComplete = false; // Simulate npm install - const filesAndFoldersToAdd: ts.projectSystem.File[] = [ + const filesAndFoldersToAdd: File[] = [ { path: "/a/b/node_modules" }, { path: "/a/b/node_modules/.staging/@types" }, { path: "/a/b/node_modules/.staging/lodash-b0733faa" }, @@ -584,7 +603,7 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS verifyAfterPartialOrCompleteNpmInstall(0); // Remove file "/a/b/node_modules/.staging/typescript-8493ea5d/package.json.3017591594" - host.deleteFile(ts.last(filesAndFoldersToAdd).path); + host.deleteFile(last(filesAndFoldersToAdd).path); filesAndFoldersToAdd.length--; verifyAfterPartialOrCompleteNpmInstall(0); @@ -606,7 +625,7 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS verifyAfterPartialOrCompleteNpmInstall(0); // remove /a/b/node_modules/.staging/rxjs-22375c61/package.json.2252192041 - host.deleteFile(ts.last(filesAndFoldersToAdd).path); + host.deleteFile(last(filesAndFoldersToAdd).path); filesAndFoldersToAdd.length--; // and add few more folders/files filesAndFoldersToAdd.push(...[ @@ -621,7 +640,7 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS // From the type root update verifyAfterPartialOrCompleteNpmInstall(2); - ts.forEach(filesAndFoldersToAdd, f => { + forEach(filesAndFoldersToAdd, f => { f.path = f.path .replace("/a/b/node_modules/.staging", "/a/b/node_modules") .replace(/[\-\.][\d\w][\d\w][\d\w][\d\w][\d\w][\d\w][\d\w][\d\w]/g, ""); @@ -629,7 +648,7 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS host.deleteFolder(root + "/a/b/node_modules/.staging", /*recursive*/ true); const lodashIndexPath = root + "/a/b/node_modules/@types/lodash/index.d.ts"; - projectFiles.push(ts.find(filesAndFoldersToAdd, f => f.path === lodashIndexPath)!); + projectFiles.push(find(filesAndFoldersToAdd, f => f.path === lodashIndexPath)!); // we would now not have failed lookup in the parent of appFolder since lodash is available recursiveWatchedDirectories.length = 2; // npm installation complete, timeout after reload fs @@ -655,16 +674,16 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS } function verifyProject() { - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); + checkNumberOfConfiguredProjects(projectService, 1); const project = projectService.configuredProjects.get(tsconfigJson.path)!; - const projectFilePaths = ts.map(projectFiles, f => f.path); - ts.projectSystem.checkProjectActualFiles(project, projectFilePaths); + const projectFilePaths = map(projectFiles, f => f.path); + checkProjectActualFiles(project, projectFilePaths); - const filesWatched = ts.filter(projectFilePaths, p => p !== app.path && p.indexOf("/a/b/node_modules") === -1); - ts.projectSystem.checkWatchedFiles(host, filesWatched); - ts.projectSystem.checkWatchedDirectories(host, typeRootDirectories.concat(recursiveWatchedDirectories), /*recursive*/ true); - ts.projectSystem.checkWatchedDirectories(host, [], /*recursive*/ false); + const filesWatched = filter(projectFilePaths, p => p !== app.path && p.indexOf("/a/b/node_modules") === -1); + checkWatchedFiles(host, filesWatched); + checkWatchedDirectories(host, typeRootDirectories.concat(recursiveWatchedDirectories), /*recursive*/ true); + checkWatchedDirectories(host, [], /*recursive*/ false); } } @@ -679,25 +698,25 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS it("when node_modules dont receive event for the @types file addition", () => { const projectLocation = "/user/username/folder/myproject"; - const app: ts.projectSystem.File = { + const app: File = { path: `${projectLocation}/app.ts`, content: `import * as debug from "debug"` }; - const tsconfig: ts.projectSystem.File = { + const tsconfig: File = { path: `${projectLocation}/tsconfig.json`, content: "" }; - const files = [app, tsconfig, ts.projectSystem.libFile]; - const host = ts.projectSystem.createServerHost(files); - const service = ts.projectSystem.createProjectService(host); + const files = [app, tsconfig, libFile]; + const host = createServerHost(files); + const service = createProjectService(host); service.openClientFile(app.path); const project = service.configuredProjects.get(tsconfig.path)!; - ts.projectSystem.checkProjectActualFiles(project, files.map(f => f.path)); + checkProjectActualFiles(project, files.map(f => f.path)); assert.deepEqual(project.getLanguageService().getSemanticDiagnostics(app.path).map(diag => diag.messageText), ["Cannot find module 'debug' or its corresponding type declarations."]); - const debugTypesFile: ts.projectSystem.File = { + const debugTypesFile: File = { path: `${projectLocation}/node_modules/@types/debug/index.d.ts`, content: "export {}" }; @@ -711,25 +730,25 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS }; host.writeFile(debugTypesFile.path, debugTypesFile.content); host.runQueuedTimeoutCallbacks(); - ts.projectSystem.checkProjectActualFiles(project, files.map(f => f.path)); + checkProjectActualFiles(project, files.map(f => f.path)); assert.deepEqual(project.getLanguageService().getSemanticDiagnostics(app.path).map(diag => diag.messageText), []); }); it("when creating new file in symlinked folder", () => { - const module1: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/client/folder1/module1.ts`, + const module1: File = { + path: `${projectRoot}/client/folder1/module1.ts`, content: `export class Module1Class { }` }; - const module2: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/folder2/module2.ts`, + const module2: File = { + path: `${projectRoot}/folder2/module2.ts`, content: `import * as M from "folder1/module1";` }; - const symlink: ts.projectSystem.SymLink = { - path: `${ts.tscWatch.projectRoot}/client/linktofolder2`, - symLink: `${ts.tscWatch.projectRoot}/folder2`, + const symlink: SymLink = { + path: `${projectRoot}/client/linktofolder2`, + symLink: `${projectRoot}/folder2`, }; - const config: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { baseUrl: "client", @@ -738,16 +757,16 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS include: ["client/**/*", "folder2"] }) }; - const host = ts.projectSystem.createServerHost([module1, module2, symlink, config, ts.projectSystem.libFile]); - const service = ts.projectSystem.createProjectService(host); + const host = createServerHost([module1, module2, symlink, config, libFile]); + const service = createProjectService(host); service.openClientFile(`${symlink.path}/module2.ts`); - ts.projectSystem.checkNumberOfProjects(service, { configuredProjects: 1 }); - const project = ts.Debug.checkDefined(service.configuredProjects.get(config.path)); - ts.projectSystem.checkProjectActualFiles(project, [module1.path, `${symlink.path}/module2.ts`, config.path, ts.projectSystem.libFile.path]); + checkNumberOfProjects(service, { configuredProjects: 1 }); + const project = Debug.checkDefined(service.configuredProjects.get(config.path)); + checkProjectActualFiles(project, [module1.path, `${symlink.path}/module2.ts`, config.path, libFile.path]); host.writeFile(`${symlink.path}/module3.ts`, `import * as M from "folder1/module1";`); host.runQueuedTimeoutCallbacks(); - ts.projectSystem.checkNumberOfProjects(service, { configuredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(project, [module1.path, `${symlink.path}/module2.ts`, config.path, ts.projectSystem.libFile.path, `${symlink.path}/module3.ts`]); + checkNumberOfProjects(service, { configuredProjects: 1 }); + checkProjectActualFiles(project, [module1.path, `${symlink.path}/module2.ts`, config.path, libFile.path, `${symlink.path}/module3.ts`]); }); }); diff --git a/src/testRunner/unittests/tsserver/cancellationToken.ts b/src/testRunner/unittests/tsserver/cancellationToken.ts index cf520bf9d6409..4b0b2f52d5488 100644 --- a/src/testRunner/unittests/tsserver/cancellationToken.ts +++ b/src/testRunner/unittests/tsserver/cancellationToken.ts @@ -1,8 +1,16 @@ -import * as ts from "../../_namespaces/ts"; +import { AnyFunction, noop } from "../../../compiler/core"; +import { OperationCanceledException } from "../../../compiler/types"; +import { extractMessage } from "../../../harness/client"; +import { + Event, GeterrRequest, NavBarRequest, OccurrencesRequest, OpenRequest, OutliningSpansRequestFull, ProjectInfoRequest, + Request, RequestCompletedEvent, +} from "../../../server/protocol"; +import { ServerCancellationToken } from "../../../server/session"; +import { createServerHost, createSession, TestServerCancellationToken } from "./helpers"; describe("unittests:: tsserver:: cancellationToken", () => { // Disable sourcemap support for the duration of the test, as sourcemapping the errors generated during this test is slow and not something we care to test - let oldPrepare: ts.AnyFunction; + let oldPrepare: AnyFunction; before(() => { oldPrepare = (Error as any).prepareStackTrace; delete (Error as any).prepareStackTrace; @@ -17,9 +25,9 @@ describe("unittests:: tsserver:: cancellationToken", () => { path: "/a/b/app.ts", content: "let xyz = 1;" }; - const host = ts.projectSystem.createServerHost([f1]); + const host = createServerHost([f1]); let expectedRequestId: number; - const cancellationToken: ts.server.ServerCancellationToken = { + const cancellationToken: ServerCancellationToken = { isCancellationRequested: () => false, setRequest: requestId => { if (expectedRequestId === undefined) { @@ -27,28 +35,28 @@ describe("unittests:: tsserver:: cancellationToken", () => { } assert.equal(requestId, expectedRequestId); }, - resetRequest: ts.noop + resetRequest: noop }; - const session = ts.projectSystem.createSession(host, { cancellationToken }); + const session = createSession(host, { cancellationToken }); expectedRequestId = session.getNextSeq(); session.executeCommandSeq({ command: "open", arguments: { file: f1.path } - } as ts.server.protocol.OpenRequest); + } as OpenRequest); expectedRequestId = session.getNextSeq(); session.executeCommandSeq({ command: "geterr", arguments: { files: [f1.path] } - } as ts.server.protocol.GeterrRequest); + } as GeterrRequest); expectedRequestId = session.getNextSeq(); session.executeCommandSeq({ command: "occurrences", arguments: { file: f1.path, line: 1, offset: 6 } - } as ts.server.protocol.OccurrencesRequest); + } as OccurrencesRequest); expectedRequestId = 2; host.runQueuedImmediateCallbacks(); @@ -68,23 +76,23 @@ describe("unittests:: tsserver:: cancellationToken", () => { }) }; - const cancellationToken = new ts.projectSystem.TestServerCancellationToken(); - const host = ts.projectSystem.createServerHost([f1, config]); - const session = ts.projectSystem.createSession(host, { + const cancellationToken = new TestServerCancellationToken(); + const host = createServerHost([f1, config]); + const session = createSession(host, { canUseEvents: true, - eventHandler: ts.noop, + eventHandler: noop, cancellationToken }); { session.executeCommandSeq({ command: "open", arguments: { file: f1.path } - } as ts.projectSystem.protocol.OpenRequest); + } as OpenRequest); // send geterr for missing file session.executeCommandSeq({ command: "geterr", arguments: { files: ["/a/missing"] } - } as ts.projectSystem.protocol.GeterrRequest); + } as GeterrRequest); // Queued files assert.equal(host.getOutput().length, 0, "expected 0 message"); host.checkTimeoutQueueLengthAndRun(1); @@ -98,7 +106,7 @@ describe("unittests:: tsserver:: cancellationToken", () => { session.executeCommandSeq({ command: "geterr", arguments: { files: [f1.path] } - } as ts.projectSystem.protocol.GeterrRequest); + } as GeterrRequest); assert.equal(host.getOutput().length, 0, "expect 0 messages"); @@ -106,7 +114,7 @@ describe("unittests:: tsserver:: cancellationToken", () => { session.executeCommandSeq({ command: "projectInfo", arguments: { file: f1.path } - } as ts.projectSystem.protocol.ProjectInfoRequest); + } as ProjectInfoRequest); session.clearMessages(); // cancel previously issued Geterr @@ -123,13 +131,13 @@ describe("unittests:: tsserver:: cancellationToken", () => { session.executeCommandSeq({ command: "geterr", arguments: { files: [f1.path] } - } as ts.projectSystem.protocol.GeterrRequest); + } as GeterrRequest); assert.equal(host.getOutput().length, 0, "expect 0 messages"); // run first step host.runQueuedTimeoutCallbacks(); assert.equal(host.getOutput().length, 1, "expect 1 message"); - const e1 = getMessage(0) as ts.projectSystem.protocol.Event; + const e1 = getMessage(0) as Event; assert.equal(e1.event, "syntaxDiag"); session.clearMessages(); @@ -145,26 +153,26 @@ describe("unittests:: tsserver:: cancellationToken", () => { session.executeCommandSeq({ command: "geterr", arguments: { files: [f1.path] } - } as ts.projectSystem.protocol.GeterrRequest); + } as GeterrRequest); assert.equal(host.getOutput().length, 0, "expect 0 messages"); // run first step host.runQueuedTimeoutCallbacks(); assert.equal(host.getOutput().length, 1, "expect 1 message"); - const e1 = getMessage(0) as ts.projectSystem.protocol.Event; + const e1 = getMessage(0) as Event; assert.equal(e1.event, "syntaxDiag"); session.clearMessages(); // the semanticDiag message host.runQueuedImmediateCallbacks(); assert.equal(host.getOutput().length, 1); - const e2 = getMessage(0) as ts.projectSystem.protocol.Event; + const e2 = getMessage(0) as Event; assert.equal(e2.event, "semanticDiag"); session.clearMessages(); host.runQueuedImmediateCallbacks(1); assert.equal(host.getOutput().length, 2); - const e3 = getMessage(0) as ts.projectSystem.protocol.Event; + const e3 = getMessage(0) as Event; assert.equal(e3.event, "suggestionDiag"); verifyRequestCompleted(getErrId, 1); @@ -175,32 +183,32 @@ describe("unittests:: tsserver:: cancellationToken", () => { session.executeCommandSeq({ command: "geterr", arguments: { files: [f1.path] } - } as ts.projectSystem.protocol.GeterrRequest); + } as GeterrRequest); assert.equal(host.getOutput().length, 0, "expect 0 messages"); // run first step host.runQueuedTimeoutCallbacks(); assert.equal(host.getOutput().length, 1, "expect 1 message"); - const e1 = getMessage(0) as ts.projectSystem.protocol.Event; + const e1 = getMessage(0) as Event; assert.equal(e1.event, "syntaxDiag"); session.clearMessages(); session.executeCommandSeq({ command: "geterr", arguments: { files: [f1.path] } - } as ts.projectSystem.protocol.GeterrRequest); + } as GeterrRequest); // make sure that getErr1 is completed verifyRequestCompleted(getErr1, 0); } function verifyRequestCompleted(expectedSeq: number, n: number) { - const event = getMessage(n) as ts.projectSystem.protocol.RequestCompletedEvent; + const event = getMessage(n) as RequestCompletedEvent; assert.equal(event.event, "requestCompleted"); assert.equal(event.body.request_seq, expectedSeq, "expectedSeq"); session.clearMessages(); } function getMessage(n: number) { - return JSON.parse(ts.server.extractMessage(host.getOutput()[n])); + return JSON.parse(extractMessage(host.getOutput()[n])); } }); @@ -215,11 +223,11 @@ describe("unittests:: tsserver:: cancellationToken", () => { compilerOptions: {} }) }; - const cancellationToken = new ts.projectSystem.TestServerCancellationToken(/*cancelAfterRequest*/ 3); - const host = ts.projectSystem.createServerHost([f1, config]); - const session = ts.projectSystem.createSession(host, { + const cancellationToken = new TestServerCancellationToken(/*cancelAfterRequest*/ 3); + const host = createServerHost([f1, config]); + const session = createSession(host, { canUseEvents: true, - eventHandler: ts.noop, + eventHandler: noop, cancellationToken, throttleWaitMilliseconds: 0 }); @@ -227,34 +235,34 @@ describe("unittests:: tsserver:: cancellationToken", () => { session.executeCommandSeq({ command: "open", arguments: { file: f1.path } - } as ts.projectSystem.protocol.OpenRequest); + } as OpenRequest); // send navbar request (normal priority) session.executeCommandSeq({ command: "navbar", arguments: { file: f1.path } - } as ts.projectSystem.protocol.NavBarRequest); + } as NavBarRequest); // ensure the nav bar request can be canceled verifyExecuteCommandSeqIsCancellable({ command: "navbar", arguments: { file: f1.path } - } as ts.projectSystem.protocol.NavBarRequest); + } as NavBarRequest); // send outlining spans request (normal priority) session.executeCommandSeq({ command: "outliningSpans", arguments: { file: f1.path } - } as ts.projectSystem.protocol.OutliningSpansRequestFull); + } as OutliningSpansRequestFull); // ensure the outlining spans request can be canceled verifyExecuteCommandSeqIsCancellable({ command: "outliningSpans", arguments: { file: f1.path } - } as ts.projectSystem.protocol.OutliningSpansRequestFull); + } as OutliningSpansRequestFull); } - function verifyExecuteCommandSeqIsCancellable(request: Partial) { + function verifyExecuteCommandSeqIsCancellable(request: Partial) { // Set the next request to be cancellable // The cancellation token will cancel the request the third time // isCancellationRequested() is called. @@ -265,7 +273,7 @@ describe("unittests:: tsserver:: cancellationToken", () => { session.executeCommandSeq(request); } catch (e) { - assert(e instanceof ts.OperationCanceledException); + assert(e instanceof OperationCanceledException); operationCanceledExceptionThrown = true; } assert(operationCanceledExceptionThrown, "Operation Canceled Exception not thrown for request: " + JSON.stringify(request)); diff --git a/src/testRunner/unittests/tsserver/compileOnSave.ts b/src/testRunner/unittests/tsserver/compileOnSave.ts index d2ebe94a9342f..b24155bd741c8 100644 --- a/src/testRunner/unittests/tsserver/compileOnSave.ts +++ b/src/testRunner/unittests/tsserver/compileOnSave.ts @@ -1,15 +1,30 @@ -import * as ts from "../../_namespaces/ts"; - -import CommandNames = ts.server.CommandNames; -function createTestTypingsInstaller(host: ts.server.ServerHost) { - return new ts.projectSystem.TestTypingsInstaller("/a/data/", /*throttleLimit*/5, host); +import { arrayIsEqualTo, compareStringsCaseSensitive, emptyArray, map, stringContains } from "../../../compiler/core"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { CompilerOptions, diagnosticCategoryName, Extension } from "../../../compiler/types"; +import { changeExtension, formatStringFromArgs } from "../../../compiler/utilities"; +import { + ChangeRequest, ChangeRequestArgs, CommandTypes, CompileOnSaveAffectedFileListRequest, + CompileOnSaveAffectedFileListSingleProject, CompileOnSaveEmitFileRequest, CompileOnSaveEmitFileRequestArgs, + FileRequestArgs, OpenRequest, Request, UpdateOpenRequest, +} from "../../../server/protocol"; +import { CommandNames, Session } from "../../../server/session"; +import { ServerHost } from "../../../server/types"; +import { projectRoot } from "../tscWatch/helpers"; +import { + checkNumberOfProjects, checkProjectActualFiles, checkProjectRootFiles, createServerHost, createSession, File, + libFile, makeSessionRequest, openFilesForSession, protocolTextSpanFromSubstring, TestSession, TestTypingsInstaller, + toExternalFiles, +} from "./helpers"; + +function createTestTypingsInstaller(host: ServerHost) { + return new TestTypingsInstaller("/a/data/", /*throttleLimit*/5, host); } describe("unittests:: tsserver:: compileOnSave:: affected list", () => { - function sendAffectedFileRequestAndCheckResult(session: ts.server.Session, request: ts.server.protocol.Request, expectedFileList: { projectFileName: string, files: ts.projectSystem.File[] }[]) { - const response = session.executeCommand(request).response as ts.server.protocol.CompileOnSaveAffectedFileListSingleProject[]; - const actualResult = response.sort((list1, list2) => ts.compareStringsCaseSensitive(list1.projectFileName, list2.projectFileName)); - expectedFileList = expectedFileList.sort((list1, list2) => ts.compareStringsCaseSensitive(list1.projectFileName, list2.projectFileName)); + function sendAffectedFileRequestAndCheckResult(session: Session, request: Request, expectedFileList: { projectFileName: string, files: File[] }[]) { + const response = session.executeCommand(request).response as CompileOnSaveAffectedFileListSingleProject[]; + const actualResult = response.sort((list1, list2) => compareStringsCaseSensitive(list1.projectFileName, list2.projectFileName)); + expectedFileList = expectedFileList.sort((list1, list2) => compareStringsCaseSensitive(list1.projectFileName, list2.projectFileName)); assert.equal(actualResult.length, expectedFileList.length, `Actual result project number is different from the expected project number`); @@ -19,24 +34,24 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { assert.equal(actualResultSingleProject.projectFileName, expectedResultSingleProject.projectFileName, `Actual result contains different projects than the expected result`); const actualResultSingleProjectFileNameList = actualResultSingleProject.fileNames.sort(); - const expectedResultSingleProjectFileNameList = ts.map(expectedResultSingleProject.files, f => f.path).sort(); + const expectedResultSingleProjectFileNameList = map(expectedResultSingleProject.files, f => f.path).sort(); assert.isTrue( - ts.arrayIsEqualTo(actualResultSingleProjectFileNameList, expectedResultSingleProjectFileNameList), + arrayIsEqualTo(actualResultSingleProjectFileNameList, expectedResultSingleProjectFileNameList), `For project ${actualResultSingleProject.projectFileName}, the actual result is ${actualResultSingleProjectFileNameList}, while expected ${expectedResultSingleProjectFileNameList}`); } } describe("for configured projects", () => { - let moduleFile1: ts.projectSystem.File; - let file1Consumer1: ts.projectSystem.File; - let file1Consumer2: ts.projectSystem.File; - let moduleFile2: ts.projectSystem.File; - let globalFile3: ts.projectSystem.File; - let configFile: ts.projectSystem.File; - let changeModuleFile1ShapeRequest1: ts.server.protocol.Request; - let changeModuleFile1InternalRequest1: ts.server.protocol.Request; + let moduleFile1: File; + let file1Consumer1: File; + let file1Consumer2: File; + let moduleFile2: File; + let globalFile3: File; + let configFile: File; + let changeModuleFile1ShapeRequest1: Request; + let changeModuleFile1InternalRequest1: Request; // A compile on save affected file request using file1 - let moduleFile1FileListRequest: ts.server.protocol.Request; + let moduleFile1FileListRequest: Request; beforeEach(() => { moduleFile1 = { @@ -72,7 +87,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }; // Change the content of file1 to `export var T: number;export function Foo() { };` - changeModuleFile1ShapeRequest1 = ts.projectSystem.makeSessionRequest(CommandNames.Change, { + changeModuleFile1ShapeRequest1 = makeSessionRequest(CommandNames.Change, { file: moduleFile1.path, line: 1, offset: 1, @@ -82,7 +97,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }); // Change the content of file1 to `export var T: number;export function Foo() { };` - changeModuleFile1InternalRequest1 = ts.projectSystem.makeSessionRequest(CommandNames.Change, { + changeModuleFile1InternalRequest1 = makeSessionRequest(CommandNames.Change, { file: moduleFile1.path, line: 1, offset: 1, @@ -91,15 +106,15 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { insertString: `var T1: number;` }); - moduleFile1FileListRequest = ts.projectSystem.makeSessionRequest(CommandNames.CompileOnSaveAffectedFileList, { file: moduleFile1.path, projectFileName: configFile.path }); + moduleFile1FileListRequest = makeSessionRequest(CommandNames.CompileOnSaveAffectedFileList, { file: moduleFile1.path, projectFileName: configFile.path }); }); it("should contains only itself if a module file's shape didn't change, and all files referencing it if its shape changed", () => { - const host = ts.projectSystem.createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, ts.projectSystem.libFile]); + const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]); const typingsInstaller = createTestTypingsInstaller(host); - const session = ts.projectSystem.createSession(host, { typingsInstaller }); + const session = createSession(host, { typingsInstaller }); - ts.projectSystem.openFilesForSession([moduleFile1, file1Consumer1], session); + openFilesForSession([moduleFile1, file1Consumer1], session); // Send an initial compileOnSave request sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer2] }]); @@ -107,7 +122,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer2] }]); // Change the content of file1 to `export var T: number;export function Foo() { console.log('hi'); };` - const changeFile1InternalRequest = ts.projectSystem.makeSessionRequest(CommandNames.Change, { + const changeFile1InternalRequest = makeSessionRequest(CommandNames.Change, { file: moduleFile1.path, line: 1, offset: 46, @@ -120,17 +135,17 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }); it("should be up-to-date with the reference map changes", () => { - const host = ts.projectSystem.createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, ts.projectSystem.libFile]); + const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]); const typingsInstaller = createTestTypingsInstaller(host); - const session = ts.projectSystem.createSession(host, { typingsInstaller }); + const session = createSession(host, { typingsInstaller }); - ts.projectSystem.openFilesForSession([moduleFile1, file1Consumer1], session); + openFilesForSession([moduleFile1, file1Consumer1], session); // Send an initial compileOnSave request sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer2] }]); // Change file2 content to `let y = Foo();` - const removeFile1Consumer1ImportRequest = ts.projectSystem.makeSessionRequest(CommandNames.Change, { + const removeFile1Consumer1ImportRequest = makeSessionRequest(CommandNames.Change, { file: file1Consumer1.path, line: 1, offset: 1, @@ -143,7 +158,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer2] }]); // Add the import statements back to file2 - const addFile2ImportRequest = ts.projectSystem.makeSessionRequest(CommandNames.Change, { + const addFile2ImportRequest = makeSessionRequest(CommandNames.Change, { file: file1Consumer1.path, line: 1, offset: 1, @@ -154,7 +169,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { session.executeCommand(addFile2ImportRequest); // Change the content of file1 to `export var T2: string;export var T: number;export function Foo() { };` - const changeModuleFile1ShapeRequest2 = ts.projectSystem.makeSessionRequest(CommandNames.Change, { + const changeModuleFile1ShapeRequest2 = makeSessionRequest(CommandNames.Change, { file: moduleFile1.path, line: 1, offset: 1, @@ -167,11 +182,11 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }); it("should be up-to-date with changes made in non-open files", () => { - const host = ts.projectSystem.createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, ts.projectSystem.libFile]); + const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]); const typingsInstaller = createTestTypingsInstaller(host); - const session = ts.projectSystem.createSession(host, { typingsInstaller }); + const session = createSession(host, { typingsInstaller }); - ts.projectSystem.openFilesForSession([moduleFile1], session); + openFilesForSession([moduleFile1], session); // Send an initial compileOnSave request sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer2] }]); @@ -183,11 +198,11 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }); it("should be up-to-date with deleted files", () => { - const host = ts.projectSystem.createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, ts.projectSystem.libFile]); + const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]); const typingsInstaller = createTestTypingsInstaller(host); - const session = ts.projectSystem.createSession(host, { typingsInstaller }); + const session = createSession(host, { typingsInstaller }); - ts.projectSystem.openFilesForSession([moduleFile1], session); + openFilesForSession([moduleFile1], session); sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer2] }]); session.executeCommand(changeModuleFile1ShapeRequest1); @@ -197,14 +212,14 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }); it("should be up-to-date with newly created files", () => { - const host = ts.projectSystem.createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, ts.projectSystem.libFile]); + const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]); const typingsInstaller = createTestTypingsInstaller(host); - const session = ts.projectSystem.createSession(host, { typingsInstaller }); + const session = createSession(host, { typingsInstaller }); - ts.projectSystem.openFilesForSession([moduleFile1], session); + openFilesForSession([moduleFile1], session); sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer2] }]); - const file1Consumer3: ts.projectSystem.File = { + const file1Consumer3: File = { path: "/a/b/file1Consumer3.ts", content: `import {Foo} from "./moduleFile1"; let y = Foo();` }; @@ -233,11 +248,11 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }` }; - const host = ts.projectSystem.createServerHost([moduleFile1, file1Consumer1, configFile, ts.projectSystem.libFile]); + const host = createServerHost([moduleFile1, file1Consumer1, configFile, libFile]); const typingsInstaller = createTestTypingsInstaller(host); - const session = ts.projectSystem.createSession(host, { typingsInstaller }); + const session = createSession(host, { typingsInstaller }); - ts.projectSystem.openFilesForSession([moduleFile1, file1Consumer1], session); + openFilesForSession([moduleFile1, file1Consumer1], session); sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1] }]); // change file1 shape now, and verify both files are affected @@ -250,12 +265,12 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }); it("should return all files if a global file changed shape", () => { - const host = ts.projectSystem.createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, ts.projectSystem.libFile]); + const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]); const typingsInstaller = createTestTypingsInstaller(host); - const session = ts.projectSystem.createSession(host, { typingsInstaller }); + const session = createSession(host, { typingsInstaller }); - ts.projectSystem.openFilesForSession([globalFile3], session); - const changeGlobalFile3ShapeRequest = ts.projectSystem.makeSessionRequest(CommandNames.Change, { + openFilesForSession([globalFile3], session); + const changeGlobalFile3ShapeRequest = makeSessionRequest(CommandNames.Change, { file: globalFile3.path, line: 1, offset: 1, @@ -266,7 +281,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { // check after file1 shape changes session.executeCommand(changeGlobalFile3ShapeRequest); - const globalFile3FileListRequest = ts.projectSystem.makeSessionRequest(CommandNames.CompileOnSaveAffectedFileList, { file: globalFile3.path }); + const globalFile3FileListRequest = makeSessionRequest(CommandNames.CompileOnSaveAffectedFileList, { file: globalFile3.path }); sendAffectedFileRequestAndCheckResult(session, globalFile3FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2] }]); }); @@ -276,10 +291,10 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { content: `{}` }; - const host = ts.projectSystem.createServerHost([moduleFile1, file1Consumer1, file1Consumer2, configFile, ts.projectSystem.libFile]); + const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, configFile, libFile]); const typingsInstaller = createTestTypingsInstaller(host); - const session = ts.projectSystem.createSession(host, { typingsInstaller }); - ts.projectSystem.openFilesForSession([moduleFile1], session); + const session = createSession(host, { typingsInstaller }); + openFilesForSession([moduleFile1], session); sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, []); }); @@ -294,10 +309,10 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }` }; - const host = ts.projectSystem.createServerHost([moduleFile1, file1Consumer1, file1Consumer2, configFile, ts.projectSystem.libFile]); + const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, configFile, libFile]); const typingsInstaller = createTestTypingsInstaller(host); - const session = ts.projectSystem.createSession(host, { typingsInstaller }); - ts.projectSystem.openFilesForSession([moduleFile1], session); + const session = createSession(host, { typingsInstaller }); + openFilesForSession([moduleFile1], session); sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, []); }); @@ -309,18 +324,18 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }` }; - const configFile2: ts.projectSystem.File = { + const configFile2: File = { path: "/a/tsconfig.json", content: `{ "compileOnSave": true }` }; - const host = ts.projectSystem.createServerHost([moduleFile1, file1Consumer1, file1Consumer2, configFile2, configFile, ts.projectSystem.libFile]); + const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, configFile2, configFile, libFile]); const typingsInstaller = createTestTypingsInstaller(host); - const session = ts.projectSystem.createSession(host, { typingsInstaller }); + const session = createSession(host, { typingsInstaller }); - ts.projectSystem.openFilesForSession([moduleFile1, file1Consumer1], session); + openFilesForSession([moduleFile1, file1Consumer1], session); sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer2] }]); }); @@ -335,12 +350,12 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }` }; - const host = ts.projectSystem.createServerHost([moduleFile1, file1Consumer1, configFile, ts.projectSystem.libFile]); + const host = createServerHost([moduleFile1, file1Consumer1, configFile, libFile]); const typingsInstaller = createTestTypingsInstaller(host); - const session = ts.projectSystem.createSession(host, { typingsInstaller }); - ts.projectSystem.openFilesForSession([moduleFile1], session); + const session = createSession(host, { typingsInstaller }); + openFilesForSession([moduleFile1], session); - const file1ChangeShapeRequest = ts.projectSystem.makeSessionRequest(CommandNames.Change, { + const file1ChangeShapeRequest = makeSessionRequest(CommandNames.Change, { file: moduleFile1.path, line: 1, offset: 27, @@ -364,12 +379,12 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }` }; - const host = ts.projectSystem.createServerHost([moduleFile1, file1Consumer1, configFile, ts.projectSystem.libFile]); + const host = createServerHost([moduleFile1, file1Consumer1, configFile, libFile]); const typingsInstaller = createTestTypingsInstaller(host); - const session = ts.projectSystem.createSession(host, { typingsInstaller }); - ts.projectSystem.openFilesForSession([moduleFile1], session); + const session = createSession(host, { typingsInstaller }); + openFilesForSession([moduleFile1], session); - const file1ChangeShapeRequest = ts.projectSystem.makeSessionRequest(CommandNames.Change, { + const file1ChangeShapeRequest = makeSessionRequest(CommandNames.Change, { file: moduleFile1.path, line: 1, offset: 27, @@ -382,18 +397,18 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }); it("should return cascaded affected file list", () => { - const file1Consumer1Consumer1: ts.projectSystem.File = { + const file1Consumer1Consumer1: File = { path: "/a/b/file1Consumer1Consumer1.ts", content: `import {y} from "./file1Consumer1";` }; - const host = ts.projectSystem.createServerHost([moduleFile1, file1Consumer1, file1Consumer1Consumer1, globalFile3, configFile, ts.projectSystem.libFile]); + const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer1Consumer1, globalFile3, configFile, libFile]); const typingsInstaller = createTestTypingsInstaller(host); - const session = ts.projectSystem.createSession(host, { typingsInstaller }); + const session = createSession(host, { typingsInstaller }); - ts.projectSystem.openFilesForSession([moduleFile1, file1Consumer1], session); + openFilesForSession([moduleFile1, file1Consumer1], session); sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer1Consumer1] }]); - const changeFile1Consumer1ShapeRequest = ts.projectSystem.makeSessionRequest(CommandNames.Change, { + const changeFile1Consumer1ShapeRequest = makeSessionRequest(CommandNames.Change, { file: file1Consumer1.path, line: 2, offset: 1, @@ -407,39 +422,39 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }); it("should work fine for files with circular references", () => { - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/b/file1.ts", content: ` /// export var t1 = 10;` }; - const file2: ts.projectSystem.File = { + const file2: File = { path: "/a/b/file2.ts", content: ` /// export var t2 = 10;` }; - const host = ts.projectSystem.createServerHost([file1, file2, configFile]); + const host = createServerHost([file1, file2, configFile]); const typingsInstaller = createTestTypingsInstaller(host); - const session = ts.projectSystem.createSession(host, { typingsInstaller }); + const session = createSession(host, { typingsInstaller }); - ts.projectSystem.openFilesForSession([file1, file2], session); - const file1AffectedListRequest = ts.projectSystem.makeSessionRequest(CommandNames.CompileOnSaveAffectedFileList, { file: file1.path }); + openFilesForSession([file1, file2], session); + const file1AffectedListRequest = makeSessionRequest(CommandNames.CompileOnSaveAffectedFileList, { file: file1.path }); sendAffectedFileRequestAndCheckResult(session, file1AffectedListRequest, [{ projectFileName: configFile.path, files: [file1, file2] }]); }); it("should return results for all projects if not specifying projectFileName", () => { - const file1: ts.projectSystem.File = { path: "/a/b/file1.ts", content: "export var t = 10;" }; - const file2: ts.projectSystem.File = { path: "/a/b/file2.ts", content: `import {t} from "./file1"; var t2 = 11;` }; - const file3: ts.projectSystem.File = { path: "/a/c/file2.ts", content: `import {t} from "../b/file1"; var t3 = 11;` }; - const configFile1: ts.projectSystem.File = { path: "/a/b/tsconfig.json", content: `{ "compileOnSave": true }` }; - const configFile2: ts.projectSystem.File = { path: "/a/c/tsconfig.json", content: `{ "compileOnSave": true }` }; + const file1: File = { path: "/a/b/file1.ts", content: "export var t = 10;" }; + const file2: File = { path: "/a/b/file2.ts", content: `import {t} from "./file1"; var t2 = 11;` }; + const file3: File = { path: "/a/c/file2.ts", content: `import {t} from "../b/file1"; var t3 = 11;` }; + const configFile1: File = { path: "/a/b/tsconfig.json", content: `{ "compileOnSave": true }` }; + const configFile2: File = { path: "/a/c/tsconfig.json", content: `{ "compileOnSave": true }` }; - const host = ts.projectSystem.createServerHost([file1, file2, file3, configFile1, configFile2]); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([file1, file2, file3, configFile1, configFile2]); + const session = createSession(host); - ts.projectSystem.openFilesForSession([file1, file2, file3], session); - const file1AffectedListRequest = ts.projectSystem.makeSessionRequest(CommandNames.CompileOnSaveAffectedFileList, { file: file1.path }); + openFilesForSession([file1, file2, file3], session); + const file1AffectedListRequest = makeSessionRequest(CommandNames.CompileOnSaveAffectedFileList, { file: file1.path }); sendAffectedFileRequestAndCheckResult(session, file1AffectedListRequest, [ { projectFileName: configFile1.path, files: [file1, file2] }, @@ -448,38 +463,38 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }); it("should detect removed code file", () => { - const referenceFile1: ts.projectSystem.File = { + const referenceFile1: File = { path: "/a/b/referenceFile1.ts", content: ` /// export var x = Foo();` }; - const host = ts.projectSystem.createServerHost([moduleFile1, referenceFile1, configFile]); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([moduleFile1, referenceFile1, configFile]); + const session = createSession(host); - ts.projectSystem.openFilesForSession([referenceFile1], session); + openFilesForSession([referenceFile1], session); host.deleteFile(moduleFile1.path); - const request = ts.projectSystem.makeSessionRequest(CommandNames.CompileOnSaveAffectedFileList, { file: referenceFile1.path }); + const request = makeSessionRequest(CommandNames.CompileOnSaveAffectedFileList, { file: referenceFile1.path }); sendAffectedFileRequestAndCheckResult(session, request, [ { projectFileName: configFile.path, files: [referenceFile1] } ]); - const requestForMissingFile = ts.projectSystem.makeSessionRequest(CommandNames.CompileOnSaveAffectedFileList, { file: moduleFile1.path }); + const requestForMissingFile = makeSessionRequest(CommandNames.CompileOnSaveAffectedFileList, { file: moduleFile1.path }); sendAffectedFileRequestAndCheckResult(session, requestForMissingFile, []); }); it("should detect non-existing code file", () => { - const referenceFile1: ts.projectSystem.File = { + const referenceFile1: File = { path: "/a/b/referenceFile1.ts", content: ` /// export var x = Foo();` }; - const host = ts.projectSystem.createServerHost([referenceFile1, configFile]); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([referenceFile1, configFile]); + const session = createSession(host); - ts.projectSystem.openFilesForSession([referenceFile1], session); - const request = ts.projectSystem.makeSessionRequest(CommandNames.CompileOnSaveAffectedFileList, { file: referenceFile1.path }); + openFilesForSession([referenceFile1], session); + const request = makeSessionRequest(CommandNames.CompileOnSaveAffectedFileList, { file: referenceFile1.path }); sendAffectedFileRequestAndCheckResult(session, request, [ { projectFileName: configFile.path, files: [referenceFile1] } ]); @@ -487,7 +502,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }); describe("for changes in declaration files", () => { - function testDTS(dtsFileContents: string, tsFileContents: string, opts: ts.CompilerOptions, expectDTSEmit: boolean) { + function testDTS(dtsFileContents: string, tsFileContents: string, opts: CompilerOptions, expectDTSEmit: boolean) { const dtsFile = { path: "/a/runtime/a.d.ts", content: dtsFileContents @@ -503,37 +518,37 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { compileOnSave: true }) }; - const host = ts.projectSystem.createServerHost([dtsFile, f2, config]); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([dtsFile, f2, config]); + const session = createSession(host); session.executeCommand({ seq: 1, type: "request", command: "open", arguments: { file: dtsFile.path } - } as ts.projectSystem.protocol.OpenRequest); + } as OpenRequest); const projectService = session.getProjectService(); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); const project = projectService.configuredProjects.get(config.path)!; - ts.projectSystem.checkProjectRootFiles(project, [dtsFile.path, f2.path]); + checkProjectRootFiles(project, [dtsFile.path, f2.path]); session.executeCommand({ seq: 2, type: "request", command: "open", arguments: { file: f2.path } - } as ts.projectSystem.protocol.OpenRequest); - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { configuredProjects: 1 }); + } as OpenRequest); + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 1 }); const { response } = session.executeCommand({ seq: 3, type: "request", command: "compileOnSaveAffectedFileList", arguments: { file: dtsFile.path } - } as ts.projectSystem.protocol.CompileOnSaveAffectedFileListRequest); + } as CompileOnSaveAffectedFileListRequest); if (expectDTSEmit) { - assert.equal((response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]).length, 1, "expected output from 1 project"); - assert.equal((response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[])[0].fileNames.length, 2, "expected to affect 2 files"); + assert.equal((response as CompileOnSaveAffectedFileListSingleProject[]).length, 1, "expected output from 1 project"); + assert.equal((response as CompileOnSaveAffectedFileListSingleProject[])[0].fileNames.length, 2, "expected to affect 2 files"); } else { - assert.equal((response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]).length, 0, "expected no output"); + assert.equal((response as CompileOnSaveAffectedFileListSingleProject[]).length, 0, "expected no output"); } @@ -542,8 +557,8 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { type: "request", command: "compileOnSaveAffectedFileList", arguments: { file: f2.path } - } as ts.projectSystem.protocol.CompileOnSaveAffectedFileListRequest); - assert.equal((response2 as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]).length, 1, "expected output from 1 project"); + } as CompileOnSaveAffectedFileListRequest); + assert.equal((response2 as CompileOnSaveAffectedFileListSingleProject[]).length, 1, "expected output from 1 project"); } it("should return empty array if change is made in a global declaration file", () => { @@ -593,7 +608,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { }); describe("tsserverProjectSystem emit with outFile or out setting", () => { - function test(opts: ts.CompilerOptions, expectedUsesOutFile: boolean) { + function test(opts: CompilerOptions, expectedUsesOutFile: boolean) { const f1 = { path: "/a/a.ts", content: "let x = 1" @@ -609,24 +624,24 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => { compileOnSave: true }) }; - const host = ts.projectSystem.createServerHost([f1, f2, config]); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([f1, f2, config]); + const session = createSession(host); session.executeCommand({ seq: 1, type: "request", command: "open", arguments: { file: f1.path } - } as ts.projectSystem.protocol.OpenRequest); - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { configuredProjects: 1 }); + } as OpenRequest); + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 1 }); const { response } = session.executeCommand({ seq: 2, type: "request", command: "compileOnSaveAffectedFileList", arguments: { file: f1.path } - } as ts.projectSystem.protocol.CompileOnSaveAffectedFileListRequest); - assert.equal((response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]).length, 1, "expected output for 1 project"); - assert.equal((response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[])[0].fileNames.length, 2, "expected output for 1 project"); - assert.equal((response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[])[0].projectUsesOutFile, expectedUsesOutFile, "usesOutFile"); + } as CompileOnSaveAffectedFileListRequest); + assert.equal((response as CompileOnSaveAffectedFileListSingleProject[]).length, 1, "expected output for 1 project"); + assert.equal((response as CompileOnSaveAffectedFileListSingleProject[])[0].fileNames.length, 2, "expected output for 1 project"); + assert.equal((response as CompileOnSaveAffectedFileListSingleProject[])[0].projectUsesOutFile, expectedUsesOutFile, "usesOutFile"); } it("projectUsesOutFile should not be returned if not set", () => { @@ -650,26 +665,26 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => { const lines = ["var x = 1;", "var y = 2;"]; const path = "/a/app"; const f = { - path: path + ts.Extension.Ts, + path: path + Extension.Ts, content: lines.join(newLine) }; - const host = ts.projectSystem.createServerHost([f], { newLine }); - const session = ts.projectSystem.createSession(host); - const openRequest: ts.server.protocol.OpenRequest = { + const host = createServerHost([f], { newLine }); + const session = createSession(host); + const openRequest: OpenRequest = { seq: 1, type: "request", - command: ts.server.protocol.CommandTypes.Open, + command: CommandTypes.Open, arguments: { file: f.path } }; session.executeCommand(openRequest); - const emitFileRequest: ts.server.protocol.CompileOnSaveEmitFileRequest = { + const emitFileRequest: CompileOnSaveEmitFileRequest = { seq: 2, type: "request", - command: ts.server.protocol.CommandTypes.CompileOnSaveEmitFile, + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: f.path } }; session.executeCommand(emitFileRequest); - const emitOutput = host.readFile(path + ts.Extension.Js); + const emitOutput = host.readFile(path + Extension.Js); assert.equal(emitOutput, f.content + newLine, "content of emit output should be identical with the input + newline"); } }); @@ -687,12 +702,12 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => { path: "/a/b/tsconfig.json", content: `{}` }; - const host = ts.projectSystem.createServerHost([file1, file2, configFile, ts.projectSystem.libFile], { newLine: "\r\n" }); + const host = createServerHost([file1, file2, configFile, libFile], { newLine: "\r\n" }); const typingsInstaller = createTestTypingsInstaller(host); - const session = ts.projectSystem.createSession(host, { typingsInstaller }); + const session = createSession(host, { typingsInstaller }); - ts.projectSystem.openFilesForSession([file1, file2], session); - const compileFileRequest = ts.projectSystem.makeSessionRequest(CommandNames.CompileOnSaveEmitFile, { file: file1.path, projectFileName: configFile.path }); + openFilesForSession([file1, file2], session); + const compileFileRequest = makeSessionRequest(CommandNames.CompileOnSaveEmitFile, { file: file1.path, projectFileName: configFile.path }); session.executeCommand(compileFileRequest); const expectedEmittedFileName = "/a/b/f1.js"; @@ -715,12 +730,12 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => { content: "console.log('file3');" }; const externalProjectName = "/a/b/externalproject"; - const host = ts.projectSystem.createServerHost([file1, file2, file3, ts.projectSystem.libFile]); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([file1, file2, file3, libFile]); + const session = createSession(host); const projectService = session.getProjectService(); projectService.openExternalProject({ - rootFiles: ts.projectSystem.toExternalFiles([file1.path, file2.path]), + rootFiles: toExternalFiles([file1.path, file2.path]), options: { allowJs: true, outFile: "dist.js", @@ -729,7 +744,7 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => { projectFileName: externalProjectName }); - const emitRequest = ts.projectSystem.makeSessionRequest(CommandNames.CompileOnSaveEmitFile, { file: file1.path }); + const emitRequest = makeSessionRequest(CommandNames.CompileOnSaveEmitFile, { file: file1.path }); session.executeCommand(emitRequest); const expectedOutFileName = "/a/b/dist.js"; @@ -747,13 +762,13 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => { content: "consonle.log('file1');" }; const externalProjectName = "/root/TypeScriptProject3/TypeScriptProject3/TypeScriptProject3.csproj"; - const host = ts.projectSystem.createServerHost([file1, ts.projectSystem.libFile]); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([file1, libFile]); + const session = createSession(host); const projectService = session.getProjectService(); const outFileName = "bar.js"; projectService.openExternalProject({ - rootFiles: ts.projectSystem.toExternalFiles([file1.path]), + rootFiles: toExternalFiles([file1.path]), options: { outFile: outFileName, sourceMap: true, @@ -762,7 +777,7 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => { projectFileName: externalProjectName }); - const emitRequest = ts.projectSystem.makeSessionRequest(CommandNames.CompileOnSaveEmitFile, { file: file1.path }); + const emitRequest = makeSessionRequest(CommandNames.CompileOnSaveEmitFile, { file: file1.path }); session.executeCommand(emitRequest); // Verify js file @@ -779,7 +794,7 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => { verifyContentHasString(mapFileContent, `"sources":["${inputFileName}"]`); function verifyContentHasString(content: string, str: string) { - assert.isTrue(ts.stringContains(content, str), `Expected "${content}" to have "${str}"`); + assert.isTrue(stringContains(content, str), `Expected "${content}" to have "${str}"`); } }); @@ -795,8 +810,8 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => { }); function verify(richResponse: boolean | undefined) { - const config: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compileOnSave: true, compilerOptions: { @@ -807,38 +822,38 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => { exclude: ["node_modules"] }) }; - const file1: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/file1.ts`, + const file1: File = { + path: `${projectRoot}/file1.ts`, content: "const x = 1;" }; - const file2: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/file2.ts`, + const file2: File = { + path: `${projectRoot}/file2.ts`, content: "const y = 2;" }; - const host = ts.projectSystem.createServerHost([file1, file2, config, ts.projectSystem.libFile]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([file1], session); + const host = createServerHost([file1, file2, config, libFile]); + const session = createSession(host); + openFilesForSession([file1], session); - const affectedFileResponse = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const affectedFileResponse = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: file1.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(affectedFileResponse, [ { fileNames: [file1.path, file2.path], projectFileName: config.path, projectUsesOutFile: false } ]); - const file1SaveResponse = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const file1SaveResponse = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: file1.path, richResponse } }).response; if (richResponse) { - assert.deepEqual(file1SaveResponse, { emitSkipped: false, diagnostics: ts.emptyArray }); + assert.deepEqual(file1SaveResponse, { emitSkipped: false, diagnostics: emptyArray }); } else { assert.isTrue(file1SaveResponse); } - assert.strictEqual(host.readFile(`${ts.tscWatch.projectRoot}/test/file1.d.ts`), "declare const x = 1;\n"); - const file2SaveResponse = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + assert.strictEqual(host.readFile(`${projectRoot}/test/file1.d.ts`), "declare const x = 1;\n"); + const file2SaveResponse = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: file2.path, richResponse } }).response; if (richResponse) { @@ -848,9 +863,9 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => { start: undefined, end: undefined, fileName: undefined, - text: ts.formatStringFromArgs(ts.Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file.message, [`${ts.tscWatch.projectRoot}/test/file1.d.ts`]), - code: ts.Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file.code, - category: ts.diagnosticCategoryName(ts.Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file), + text: formatStringFromArgs(Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file.message, [`${projectRoot}/test/file1.d.ts`]), + code: Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file.code, + category: diagnosticCategoryName(Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file), reportsUnnecessary: undefined, reportsDeprecated: undefined, relatedInformation: undefined, @@ -861,7 +876,7 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => { else { assert.isFalse(file2SaveResponse); } - assert.isFalse(host.fileExists(`${ts.tscWatch.projectRoot}/test/file2.d.ts`)); + assert.isFalse(host.fileExists(`${projectRoot}/test/file2.d.ts`)); } }); @@ -883,8 +898,8 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => { }); }); function verifyGlobalSave(declaration: boolean,hasModule: boolean) { - const config: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compileOnSave: true, compilerOptions: { @@ -893,37 +908,37 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => { }, }) }; - const file1: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/file1.ts`, + const file1: File = { + path: `${projectRoot}/file1.ts`, content: `const x = 1; function foo() { return "hello"; }` }; - const file2: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/file2.ts`, + const file2: File = { + path: `${projectRoot}/file2.ts`, content: `const y = 2; function bar() { return "world"; }` }; - const file3: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/file3.ts`, + const file3: File = { + path: `${projectRoot}/file3.ts`, content: "const xy = 3;" }; - const module: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/module.ts`, + const module: File = { + path: `${projectRoot}/module.ts`, content: "export const xyz = 4;" }; - const files = [file1, file2, file3, ...(hasModule ? [module] : ts.emptyArray)]; - const host = ts.projectSystem.createServerHost([...files, config, ts.projectSystem.libFile]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([file1, file2], session); + const files = [file1, file2, file3, ...(hasModule ? [module] : emptyArray)]; + const host = createServerHost([...files, config, libFile]); + const session = createSession(host); + openFilesForSession([file1, file2], session); - const affectedFileResponse = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const affectedFileResponse = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: file1.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(affectedFileResponse, [ { fileNames: files.map(f => f.path), projectFileName: config.path, projectUsesOutFile: false } ]); @@ -940,21 +955,21 @@ function bar() { // Change file2 get affected file list = will return only file2 if --declaration otherwise all files verifyLocalEdit(file2, "world", "hello", /*returnsAllFilesAsAffected*/ !declaration); - function verifyFileSave(file: ts.projectSystem.File) { - const response = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + function verifyFileSave(file: File) { + const response = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: file.path } }).response; assert.isTrue(response); assert.strictEqual( - host.readFile(ts.changeExtension(file.path, ".js")), + host.readFile(changeExtension(file.path, ".js")), file === module ? `"use strict";\nexports.__esModule = true;\nexports.xyz = void 0;\nexports.xyz = 4;\n` : `${file.content.replace("const", "var")}\n` ); if (declaration) { assert.strictEqual( - host.readFile(ts.changeExtension(file.path, ".d.ts")), + host.readFile(changeExtension(file.path, ".d.ts")), (file.content.substr(0, file.content.indexOf(" {") === -1 ? file.content.length : file.content.indexOf(" {")) .replace("const ", "declare const ") .replace("function ", "declare function ") @@ -963,26 +978,26 @@ function bar() { } } - function verifyLocalEdit(file: ts.projectSystem.File, oldText: string, newText: string, returnsAllFilesAsAffected?: boolean) { + function verifyLocalEdit(file: File, oldText: string, newText: string, returnsAllFilesAsAffected?: boolean) { // Change file1 get affected file list - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.UpdateOpen, + session.executeCommandSeq({ + command: CommandTypes.UpdateOpen, arguments: { changedFiles: [{ fileName: file.path, textChanges: [{ newText, - ...ts.projectSystem.protocolTextSpanFromSubstring(file.content, oldText) + ...protocolTextSpanFromSubstring(file.content, oldText) }] }] } }); - const affectedFileResponse = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const affectedFileResponse = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: file.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(affectedFileResponse, [ - { fileNames: [file.path, ...(returnsAllFilesAsAffected ? files.filter(f => f !== file).map(f => f.path) : ts.emptyArray)], projectFileName: config.path, projectUsesOutFile: false } + { fileNames: [file.path, ...(returnsAllFilesAsAffected ? files.filter(f => f !== file).map(f => f.path) : emptyArray)], projectFileName: config.path, projectUsesOutFile: false } ]); file.content = file.content.replace(oldText, newText); verifyFileSave(file); @@ -992,39 +1007,39 @@ function bar() { }); describe("unittests:: tsserver:: compileOnSave:: CompileOnSaveAffectedFileListRequest with and without projectFileName in request", () => { - const core: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/core/core.ts`, + const core: File = { + path: `${projectRoot}/core/core.ts`, content: "let z = 10;" }; - const app1: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/app1/app.ts`, + const app1: File = { + path: `${projectRoot}/app1/app.ts`, content: "let x = 10;" }; - const app2: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/app2/app.ts`, + const app2: File = { + path: `${projectRoot}/app2/app.ts`, content: "let y = 10;" }; - const app1Config: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/app1/tsconfig.json`, + const app1Config: File = { + path: `${projectRoot}/app1/tsconfig.json`, content: JSON.stringify({ files: ["app.ts", "../core/core.ts"], compilerOptions: { outFile: "build/output.js" }, compileOnSave: true }) }; - const app2Config: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/app2/tsconfig.json`, + const app2Config: File = { + path: `${projectRoot}/app2/tsconfig.json`, content: JSON.stringify({ files: ["app.ts", "../core/core.ts"], compilerOptions: { outFile: "build/output.js" }, compileOnSave: true }) }; - const files = [ts.projectSystem.libFile, core, app1, app2, app1Config, app2Config]; + const files = [libFile, core, app1, app2, app1Config, app2Config]; - function insertString(session: ts.projectSystem.TestSession, file: ts.projectSystem.File) { - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + function insertString(session: TestSession, file: File) { + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: file.path, line: 1, @@ -1037,15 +1052,15 @@ describe("unittests:: tsserver:: compileOnSave:: CompileOnSaveAffectedFileListRe } function getSession() { - const host = ts.projectSystem.createServerHost(files); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([app1, app2, core], session); + const host = createServerHost(files); + const session = createSession(host); + openFilesForSession([app1, app2, core], session); const service = session.getProjectService(); - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); const project1 = service.configuredProjects.get(app1Config.path)!; const project2 = service.configuredProjects.get(app2Config.path)!; - ts.projectSystem.checkProjectActualFiles(project1, [ts.projectSystem.libFile.path, app1.path, core.path, app1Config.path]); - ts.projectSystem.checkProjectActualFiles(project2, [ts.projectSystem.libFile.path, app2.path, core.path, app2Config.path]); + checkProjectActualFiles(project1, [libFile.path, app1.path, core.path, app1Config.path]); + checkProjectActualFiles(project2, [libFile.path, app2.path, core.path, app2Config.path]); insertString(session, app1); insertString(session, app2); assert.equal(project1.dirty, true); @@ -1055,8 +1070,8 @@ describe("unittests:: tsserver:: compileOnSave:: CompileOnSaveAffectedFileListRe it("when projectFile is specified", () => { const session = getSession(); - const response = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const response = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: core.path, projectFileName: app1Config.path @@ -1071,8 +1086,8 @@ describe("unittests:: tsserver:: compileOnSave:: CompileOnSaveAffectedFileListRe it("when projectFile is not specified", () => { const session = getSession(); - const response = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const response = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: core.path } diff --git a/src/testRunner/unittests/tsserver/completions.ts b/src/testRunner/unittests/tsserver/completions.ts index 606fc2c30253f..f987ad9cbb22a 100644 --- a/src/testRunner/unittests/tsserver/completions.ts +++ b/src/testRunner/unittests/tsserver/completions.ts @@ -1,45 +1,62 @@ +import { emptyArray } from "../../../compiler/core"; +import { SyntaxKind } from "../../../compiler/types"; +import { createTextSpan } from "../../../compiler/utilitiesPublic"; +import { + CommandTypes, CompletionDetailsRequest, CompletionDetailsRequestArgs, CompletionDetailsResponse, CompletionEntry, + CompletionEntryDetails, CompletionInfo, CompletionInfoResponse, CompletionsRequest, FileLocationRequest, + FileLocationRequestArgs, Response, +} from "../../../server/protocol"; +import { SortText } from "../../../services/completions"; +import { + CompletionInfoFlags, ScriptElementKind, ScriptElementKindModifier, SymbolDisplayPartKind, +} from "../../../services/types"; +import { createTextChange, displayPart, keywordPart, punctuationPart, spacePart } from "../../../services/utilities"; import * as ts from "../../_namespaces/ts"; +import { + checkNumberOfProjects, checkProjectActualFiles, createServerHost, createSession, executeSessionRequest, File, + libFile, openFilesForSession, TestTypingsInstaller, +} from "./helpers"; describe("unittests:: tsserver:: completions", () => { it("works", () => { - const aTs: ts.projectSystem.File = { + const aTs: File = { path: "/a.ts", content: "export const foo = 0;", }; - const bTs: ts.projectSystem.File = { + const bTs: File = { path: "/b.ts", content: "foo", }; - const tsconfig: ts.projectSystem.File = { + const tsconfig: File = { path: "/tsconfig.json", content: "{}", }; - const session = ts.projectSystem.createSession(ts.projectSystem.createServerHost([aTs, bTs, tsconfig])); - ts.projectSystem.openFilesForSession([aTs, bTs], session); + const session = createSession(createServerHost([aTs, bTs, tsconfig])); + openFilesForSession([aTs, bTs], session); - const requestLocation: ts.projectSystem.protocol.FileLocationRequestArgs = { + const requestLocation: FileLocationRequestArgs = { file: bTs.path, line: 1, offset: 3, }; - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.CompletionInfo, { + const response = executeSessionRequest(session, CommandTypes.CompletionInfo, { ...requestLocation, includeExternalModuleExports: true, prefix: "foo", }); - const entry: ts.projectSystem.protocol.CompletionEntry = { + const entry: CompletionEntry = { hasAction: true, insertText: undefined, isRecommended: undefined, - kind: ts.ScriptElementKind.constElement, - kindModifiers: ts.ScriptElementKindModifier.exportedModifier, + kind: ScriptElementKind.constElement, + kindModifiers: ScriptElementKindModifier.exportedModifier, name: "foo", replacementSpan: undefined, isPackageJsonImport: undefined, isImportStatementCompletion: undefined, - sortText: ts.Completions.SortText.AutoImportSuggestions, + sortText: SortText.AutoImportSuggestions, source: "/a", sourceDisplay: undefined, isSnippet: undefined, @@ -52,8 +69,8 @@ describe("unittests:: tsserver:: completions", () => { const exportMapKey = (response?.entries[0].data as any)?.exportMapKey; assert.isString(exportMapKey); delete (response?.entries[0].data as any).exportMapKey; - assert.deepEqual(response, { - flags: ts.CompletionInfoFlags.MayIncludeAutoImports, + assert.deepEqual(response, { + flags: CompletionInfoFlags.MayIncludeAutoImports, isGlobalCompletion: true, isIncomplete: undefined, isMemberCompletion: false, @@ -62,29 +79,29 @@ describe("unittests:: tsserver:: completions", () => { entries: [entry], }); - const detailsRequestArgs: ts.projectSystem.protocol.CompletionDetailsRequestArgs = { + const detailsRequestArgs: CompletionDetailsRequestArgs = { ...requestLocation, entryNames: [{ name: "foo", source: "/a", data: { exportName: "foo", fileName: "/a.ts", exportMapKey } }], }; - const detailsResponse = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.CompletionDetails, detailsRequestArgs); - const detailsCommon: ts.projectSystem.protocol.CompletionEntryDetails & ts.CompletionEntryDetails = { + const detailsResponse = executeSessionRequest(session, CommandTypes.CompletionDetails, detailsRequestArgs); + const detailsCommon: CompletionEntryDetails & ts.CompletionEntryDetails = { displayParts: [ - ts.keywordPart(ts.SyntaxKind.ConstKeyword), - ts.spacePart(), - ts.displayPart("foo", ts.SymbolDisplayPartKind.localName), - ts.punctuationPart(ts.SyntaxKind.ColonToken), - ts.spacePart(), - ts.displayPart("0", ts.SymbolDisplayPartKind.stringLiteral), + keywordPart(SyntaxKind.ConstKeyword), + spacePart(), + displayPart("foo", SymbolDisplayPartKind.localName), + punctuationPart(SyntaxKind.ColonToken), + spacePart(), + displayPart("0", SymbolDisplayPartKind.stringLiteral), ], - documentation: ts.emptyArray, - kind: ts.ScriptElementKind.constElement, - kindModifiers: ts.ScriptElementKindModifier.exportedModifier, + documentation: emptyArray, + kind: ScriptElementKind.constElement, + kindModifiers: ScriptElementKindModifier.exportedModifier, name: "foo", source: [{ text: "./a", kind: "text" }], sourceDisplay: [{ text: "./a", kind: "text" }], }; - assert.deepEqual(detailsResponse, [ + assert.deepEqual(detailsResponse, [ { codeActions: [ { @@ -109,14 +126,14 @@ describe("unittests:: tsserver:: completions", () => { }, ]); - interface CompletionDetailsFullRequest extends ts.projectSystem.protocol.FileLocationRequest { - readonly command: ts.projectSystem.protocol.CommandTypes.CompletionDetailsFull; - readonly arguments: ts.projectSystem.protocol.CompletionDetailsRequestArgs; + interface CompletionDetailsFullRequest extends FileLocationRequest { + readonly command: CommandTypes.CompletionDetailsFull; + readonly arguments: CompletionDetailsRequestArgs; } - interface CompletionDetailsFullResponse extends ts.projectSystem.protocol.Response { + interface CompletionDetailsFullResponse extends Response { readonly body?: readonly ts.CompletionEntryDetails[]; } - const detailsFullResponse = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.CompletionDetailsFull, detailsRequestArgs); + const detailsFullResponse = executeSessionRequest(session, CommandTypes.CompletionDetailsFull, detailsRequestArgs); assert.deepEqual(detailsFullResponse, [ { codeActions: [ @@ -125,7 +142,7 @@ describe("unittests:: tsserver:: completions", () => { changes: [ { fileName: "/b.ts", - textChanges: [ts.createTextChange(ts.createTextSpan(0, 0), 'import { foo } from "./a";\n\n')], + textChanges: [createTextChange(createTextSpan(0, 0), 'import { foo } from "./a";\n\n')], }, ], commands: undefined, @@ -139,7 +156,7 @@ describe("unittests:: tsserver:: completions", () => { it("works when files are included from two different drives of windows", () => { const projectRoot = "e:/myproject"; - const appPackage: ts.projectSystem.File = { + const appPackage: File = { path: `${projectRoot}/package.json`, content: JSON.stringify({ name: "test", @@ -150,7 +167,7 @@ describe("unittests:: tsserver:: completions", () => { } }) }; - const appFile: ts.projectSystem.File = { + const appFile: File = { path: `${projectRoot}/src/app.js`, content: `import React from 'react'; import { @@ -160,37 +177,37 @@ import { }; const localNodeModules = `${projectRoot}/node_modules`; const localAtTypes = `${localNodeModules}/@types`; - const localReactPackage: ts.projectSystem.File = { + const localReactPackage: File = { path: `${localAtTypes}/react/package.json`, content: JSON.stringify({ name: "@types/react", version: "16.9.14", }) }; - const localReact: ts.projectSystem.File = { + const localReact: File = { path: `${localAtTypes}/react/index.d.ts`, content: `import * as PropTypes from 'prop-types'; ` }; - const localReactRouterDomPackage: ts.projectSystem.File = { + const localReactRouterDomPackage: File = { path: `${localNodeModules}/react-router-dom/package.json`, content: JSON.stringify({ name: "react-router-dom", version: "5.1.2", }) }; - const localReactRouterDom: ts.projectSystem.File = { + const localReactRouterDom: File = { path: `${localNodeModules}/react-router-dom/index.js`, content: `export function foo() {}` }; - const localPropTypesPackage: ts.projectSystem.File = { + const localPropTypesPackage: File = { path: `${localAtTypes}/prop-types/package.json`, content: JSON.stringify({ name: "@types/prop-types", version: "15.7.3", }) }; - const localPropTypes: ts.projectSystem.File = { + const localPropTypes: File = { path: `${localAtTypes}/prop-types/index.d.ts`, content: `export type ReactComponentLike = | string @@ -201,14 +218,14 @@ import { const globalCacheLocation = `c:/typescript`; const globalAtTypes = `${globalCacheLocation}/node_modules/@types`; - const globalReactRouterDomPackage: ts.projectSystem.File = { + const globalReactRouterDomPackage: File = { path: `${globalAtTypes}/react-router-dom/package.json`, content: JSON.stringify({ name: "@types/react-router-dom", version: "5.1.2", }) }; - const globalReactRouterDom: ts.projectSystem.File = { + const globalReactRouterDom: File = { path: `${globalAtTypes}/react-router-dom/index.d.ts`, content: `import * as React from 'react'; export interface BrowserRouterProps { @@ -218,11 +235,11 @@ export interface BrowserRouterProps { keyLength?: number; }` }; - const globalReactPackage: ts.projectSystem.File = { + const globalReactPackage: File = { path: `${globalAtTypes}/react/package.json`, content: localReactPackage.content }; - const globalReact: ts.projectSystem.File = { + const globalReact: File = { path: `${globalAtTypes}/react/index.d.ts`, content: localReact.content }; @@ -236,7 +253,7 @@ export interface BrowserRouterProps { ]; const files = [ ...filesInProject, - appPackage, ts.projectSystem.libFile, + appPackage, libFile, localReactPackage, localReactRouterDomPackage, localReactRouterDom, localPropTypesPackage, @@ -244,17 +261,17 @@ export interface BrowserRouterProps { globalReactPackage, ]; - const host = ts.projectSystem.createServerHost(files, { windowsStyleRoot: "c:/" }); - const session = ts.projectSystem.createSession(host, { - typingsInstaller: new ts.projectSystem.TestTypingsInstaller(globalCacheLocation, /*throttleLimit*/ 5, host), + const host = createServerHost(files, { windowsStyleRoot: "c:/" }); + const session = createSession(host, { + typingsInstaller: new TestTypingsInstaller(globalCacheLocation, /*throttleLimit*/ 5, host), }); const service = session.getProjectService(); - ts.projectSystem.openFilesForSession([appFile], session); - ts.projectSystem.checkNumberOfProjects(service, { inferredProjects: 1 }); - const windowsStyleLibFilePath = "c:/" + ts.projectSystem.libFile.path.substring(1); - ts.projectSystem.checkProjectActualFiles(service.inferredProjects[0], filesInProject.map(f => f.path).concat(windowsStyleLibFilePath)); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompletionInfo, + openFilesForSession([appFile], session); + checkNumberOfProjects(service, { inferredProjects: 1 }); + const windowsStyleLibFilePath = "c:/" + libFile.path.substring(1); + checkProjectActualFiles(service.inferredProjects[0], filesInProject.map(f => f.path).concat(windowsStyleLibFilePath)); + session.executeCommandSeq({ + command: CommandTypes.CompletionInfo, arguments: { file: appFile.path, line: 5, diff --git a/src/testRunner/unittests/tsserver/completionsIncomplete.ts b/src/testRunner/unittests/tsserver/completionsIncomplete.ts index 3ff631a121033..dc1c8280f88eb 100644 --- a/src/testRunner/unittests/tsserver/completionsIncomplete.ts +++ b/src/testRunner/unittests/tsserver/completionsIncomplete.ts @@ -1,20 +1,31 @@ -import * as ts from "../../_namespaces/ts"; +import { fill, identity } from "../../../compiler/core"; +import { Debug } from "../../../compiler/debug"; +import { convertToRelativePath } from "../../../compiler/path"; +import { getLineAndCharacterOfPosition } from "../../../compiler/scanner"; +import { removeFileExtension } from "../../../compiler/utilities"; +import { + CommandTypes, CompletionDetailsRequest, CompletionEntry, CompletionEntryDetails, CompletionInfo, CompletionsRequest, + CompletionTriggerKind, ConfigureRequest, UpdateOpenRequest, +} from "../../../server/protocol"; +import { toNormalizedPath } from "../../../server/utilitiesPublic"; +import { moduleSpecifierResolutionLimit } from "../../../services/completions"; +import { createServerHost, createSession, File, openFilesForSession } from "./helpers"; -function createExportingModuleFile(path: string, exportPrefix: string, exportCount: number): ts.projectSystem.File { +function createExportingModuleFile(path: string, exportPrefix: string, exportCount: number): File { return { path, - content: ts.fill(exportCount, i => `export const ${exportPrefix}_${i} = ${i};`).join("\n"), + content: fill(exportCount, i => `export const ${exportPrefix}_${i} = ${i};`).join("\n"), }; } -function createExportingModuleFiles(pathPrefix: string, fileCount: number, exportCount: number, getExportPrefix: (fileIndex: number) => string): ts.projectSystem.File[] { - return ts.fill(fileCount, fileIndex => createExportingModuleFile( +function createExportingModuleFiles(pathPrefix: string, fileCount: number, exportCount: number, getExportPrefix: (fileIndex: number) => string): File[] { + return fill(fileCount, fileIndex => createExportingModuleFile( `${pathPrefix}_${fileIndex}.ts`, getExportPrefix(fileIndex), exportCount)); } -function createNodeModulesPackage(packageName: string, fileCount: number, exportCount: number, getExportPrefix: (fileIndex: number) => string): ts.projectSystem.File[] { +function createNodeModulesPackage(packageName: string, fileCount: number, exportCount: number, getExportPrefix: (fileIndex: number) => string): File[] { const exportingFiles = createExportingModuleFiles(`/node_modules/${packageName}/file`, fileCount, exportCount, getExportPrefix); return [ { @@ -24,43 +35,43 @@ function createNodeModulesPackage(packageName: string, fileCount: number, export { path: `/node_modules/${packageName}/index.d.ts`, content: exportingFiles - .map(f => `export * from "./${ts.removeFileExtension(ts.convertToRelativePath(f.path, `/node_modules/${packageName}/`, ts.identity))}";`) + .map(f => `export * from "./${removeFileExtension(convertToRelativePath(f.path, `/node_modules/${packageName}/`, identity))}";`) .join("\n") + `\nexport default function main(): void;`, }, ...exportingFiles, ]; } -const indexFile: ts.projectSystem.File = { +const indexFile: File = { path: "/index.ts", content: "" }; -const tsconfigFile: ts.projectSystem.File = { +const tsconfigFile: File = { path: "/tsconfig.json", content: `{ "compilerOptions": { "module": "commonjs" } }` }; -const packageJsonFile: ts.projectSystem.File = { +const packageJsonFile: File = { path: "/package.json", content: `{ "dependencies": { "dep-a": "*" } }`, }; describe("unittests:: tsserver:: completionsIncomplete", () => { it("works", () => { - const excessFileCount = ts.Completions.moduleSpecifierResolutionLimit + 50; - const exportingFiles = createExportingModuleFiles(`/lib/a`, ts.Completions.moduleSpecifierResolutionLimit + excessFileCount, 1, i => `aa_${i}_`); + const excessFileCount = moduleSpecifierResolutionLimit + 50; + const exportingFiles = createExportingModuleFiles(`/lib/a`, moduleSpecifierResolutionLimit + excessFileCount, 1, i => `aa_${i}_`); const { typeToTriggerCompletions, session } = setup([tsconfigFile, indexFile, ...exportingFiles]); - ts.projectSystem.openFilesForSession([indexFile], session); + openFilesForSession([indexFile], session); typeToTriggerCompletions(indexFile.path, "a", completions => { assert(completions.isIncomplete); - assert.lengthOf(completions.entries.filter(entry => (entry.data as any)?.moduleSpecifier), ts.Completions.moduleSpecifierResolutionLimit); + assert.lengthOf(completions.entries.filter(entry => (entry.data as any)?.moduleSpecifier), moduleSpecifierResolutionLimit); assert.lengthOf(completions.entries.filter(entry => entry.source && !(entry.data as any)?.moduleSpecifier), excessFileCount); }) .continueTyping("a", completions => { assert(completions.isIncomplete); - assert.lengthOf(completions.entries.filter(entry => (entry.data as any)?.moduleSpecifier), ts.Completions.moduleSpecifierResolutionLimit * 2); + assert.lengthOf(completions.entries.filter(entry => (entry.data as any)?.moduleSpecifier), moduleSpecifierResolutionLimit * 2); }) .continueTyping("_", completions => { assert(!completions.isIncomplete); @@ -71,7 +82,7 @@ describe("unittests:: tsserver:: completionsIncomplete", () => { it("resolves more when available from module specifier cache (1)", () => { const exportingFiles = createExportingModuleFiles(`/lib/a`, 50, 50, i => `aa_${i}_`); const { typeToTriggerCompletions, session } = setup([tsconfigFile, indexFile, ...exportingFiles]); - ts.projectSystem.openFilesForSession([indexFile], session); + openFilesForSession([indexFile], session); typeToTriggerCompletions(indexFile.path, "a", completions => { assert(!completions.isIncomplete); @@ -80,9 +91,9 @@ describe("unittests:: tsserver:: completionsIncomplete", () => { it("resolves more when available from module specifier cache (2)", () => { const excessFileCount = 50; - const exportingFiles = createExportingModuleFiles(`/lib/a`, ts.Completions.moduleSpecifierResolutionLimit + excessFileCount, 1, i => `aa_${i}_`); + const exportingFiles = createExportingModuleFiles(`/lib/a`, moduleSpecifierResolutionLimit + excessFileCount, 1, i => `aa_${i}_`); const { typeToTriggerCompletions, session } = setup([tsconfigFile, indexFile, ...exportingFiles]); - ts.projectSystem.openFilesForSession([indexFile], session); + openFilesForSession([indexFile], session); typeToTriggerCompletions(indexFile.path, "a", completions => assert(completions.isIncomplete)) .backspace() @@ -90,14 +101,14 @@ describe("unittests:: tsserver:: completionsIncomplete", () => { }); it("ambient module specifier resolutions do not count against the resolution limit", () => { - const ambientFiles = ts.fill(100, (i): ts.projectSystem.File => ({ + const ambientFiles = fill(100, (i): File => ({ path: `/lib/ambient_${i}.ts`, content: `declare module "ambient_${i}" { export const aa_${i} = ${i}; }`, })); - const exportingFiles = createExportingModuleFiles(`/lib/a`, ts.Completions.moduleSpecifierResolutionLimit, 5, i => `aa_${i}_`); + const exportingFiles = createExportingModuleFiles(`/lib/a`, moduleSpecifierResolutionLimit, 5, i => `aa_${i}_`); const { typeToTriggerCompletions, session } = setup([tsconfigFile, indexFile, ...ambientFiles, ...exportingFiles]); - ts.projectSystem.openFilesForSession([indexFile], session); + openFilesForSession([indexFile], session); typeToTriggerCompletions(indexFile.path, "a", completions => { assert(!completions.isIncomplete); @@ -106,10 +117,10 @@ describe("unittests:: tsserver:: completionsIncomplete", () => { }); it("works with PackageJsonAutoImportProvider", () => { - const exportingFiles = createExportingModuleFiles(`/lib/a`, ts.Completions.moduleSpecifierResolutionLimit, 1, i => `aa_${i}_`); + const exportingFiles = createExportingModuleFiles(`/lib/a`, moduleSpecifierResolutionLimit, 1, i => `aa_${i}_`); const nodeModulesPackage = createNodeModulesPackage("dep-a", 50, 1, i => `depA_${i}_`); const { typeToTriggerCompletions, assertCompletionDetailsOk, session } = setup([tsconfigFile, packageJsonFile, indexFile, ...exportingFiles, ...nodeModulesPackage]); - ts.projectSystem.openFilesForSession([indexFile], session); + openFilesForSession([indexFile], session); typeToTriggerCompletions(indexFile.path, "a", completions => assert(completions.isIncomplete)) .continueTyping("_", completions => { @@ -122,16 +133,16 @@ describe("unittests:: tsserver:: completionsIncomplete", () => { }); it("works for transient symbols between requests", () => { - const constantsDts: ts.projectSystem.File = { + const constantsDts: File = { path: "/lib/foo/constants.d.ts", content: ` type Signals = "SIGINT" | "SIGABRT"; declare const exp: {} & { [K in Signals]: K }; export = exp;`, }; - const exportingFiles = createExportingModuleFiles("/lib/a", ts.Completions.moduleSpecifierResolutionLimit, 1, i => `S${i}`); + const exportingFiles = createExportingModuleFiles("/lib/a", moduleSpecifierResolutionLimit, 1, i => `S${i}`); const { typeToTriggerCompletions, session } = setup([tsconfigFile, indexFile, ...exportingFiles, constantsDts]); - ts.projectSystem.openFilesForSession([indexFile], session); + openFilesForSession([indexFile], session); typeToTriggerCompletions(indexFile.path, "s", completions => { const sigint = completions.entries.find(e => e.name === "SIGINT"); @@ -145,12 +156,12 @@ describe("unittests:: tsserver:: completionsIncomplete", () => { }); }); -function setup(files: ts.projectSystem.File[]) { - const host = ts.projectSystem.createServerHost(files); - const session = ts.projectSystem.createSession(host); +function setup(files: File[]) { + const host = createServerHost(files); + const session = createSession(host); const projectService = session.getProjectService(); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Configure, + session.executeCommandSeq({ + command: CommandTypes.Configure, arguments: { preferences: { allowIncompleteCompletions: true, @@ -164,16 +175,16 @@ function setup(files: ts.projectSystem.File[]) { return { host, session, projectService, typeToTriggerCompletions, assertCompletionDetailsOk }; - function typeToTriggerCompletions(fileName: string, typedCharacters: string, cb?: (completions: ts.projectSystem.protocol.CompletionInfo) => void) { - const project = projectService.getDefaultProjectForFile(ts.server.toNormalizedPath(fileName), /*ensureProject*/ true)!; + function typeToTriggerCompletions(fileName: string, typedCharacters: string, cb?: (completions: CompletionInfo) => void) { + const project = projectService.getDefaultProjectForFile(toNormalizedPath(fileName), /*ensureProject*/ true)!; return type(typedCharacters, cb, /*isIncompleteContinuation*/ false); - function type(typedCharacters: string, cb: ((completions: ts.projectSystem.protocol.CompletionInfo) => void) | undefined, isIncompleteContinuation: boolean) { - const file = ts.Debug.checkDefined(project.getLanguageService(/*ensureSynchronized*/ true).getProgram()?.getSourceFile(fileName)); - const { line, character } = ts.getLineAndCharacterOfPosition(file, file.text.length); + function type(typedCharacters: string, cb: ((completions: CompletionInfo) => void) | undefined, isIncompleteContinuation: boolean) { + const file = Debug.checkDefined(project.getLanguageService(/*ensureSynchronized*/ true).getProgram()?.getSourceFile(fileName)); + const { line, character } = getLineAndCharacterOfPosition(file, file.text.length); const oneBasedEditPosition = { line: line + 1, offset: character + 1 }; - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.UpdateOpen, + session.executeCommandSeq({ + command: CommandTypes.UpdateOpen, arguments: { changedFiles: [{ fileName, @@ -186,35 +197,35 @@ function setup(files: ts.projectSystem.File[]) { }, }); - const response = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompletionInfo, + const response = session.executeCommandSeq({ + command: CommandTypes.CompletionInfo, arguments: { file: fileName, line: oneBasedEditPosition.line, offset: oneBasedEditPosition.offset, triggerKind: isIncompleteContinuation - ? ts.projectSystem.protocol.CompletionTriggerKind.TriggerForIncompleteCompletions + ? CompletionTriggerKind.TriggerForIncompleteCompletions : undefined, } - }).response as ts.projectSystem.protocol.CompletionInfo; + }).response as CompletionInfo; - cb?.(ts.Debug.checkDefined(response)); + cb?.(Debug.checkDefined(response)); return { backspace, - continueTyping: (typedCharacters: string, cb: (completions: ts.projectSystem.protocol.CompletionInfo) => void) => { + continueTyping: (typedCharacters: string, cb: (completions: CompletionInfo) => void) => { return type(typedCharacters, cb, !!response.isIncomplete); }, }; } function backspace(n = 1) { - const file = ts.Debug.checkDefined(project.getLanguageService(/*ensureSynchronized*/ true).getProgram()?.getSourceFile(fileName)); - const startLineCharacter = ts.getLineAndCharacterOfPosition(file, file.text.length - n); - const endLineCharacter = ts.getLineAndCharacterOfPosition(file, file.text.length); + const file = Debug.checkDefined(project.getLanguageService(/*ensureSynchronized*/ true).getProgram()?.getSourceFile(fileName)); + const startLineCharacter = getLineAndCharacterOfPosition(file, file.text.length - n); + const endLineCharacter = getLineAndCharacterOfPosition(file, file.text.length); const oneBasedStartPosition = { line: startLineCharacter.line + 1, offset: startLineCharacter.character + 1 }; const oneBasedEndPosition = { line: endLineCharacter.line + 1, offset: endLineCharacter.character + 1 }; - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.UpdateOpen, + session.executeCommandSeq({ + command: CommandTypes.UpdateOpen, arguments: { changedFiles: [{ fileName, @@ -229,19 +240,19 @@ function setup(files: ts.projectSystem.File[]) { return { backspace, - type: (typedCharacters: string, cb: (completions: ts.projectSystem.protocol.CompletionInfo) => void) => { + type: (typedCharacters: string, cb: (completions: CompletionInfo) => void) => { return type(typedCharacters, cb, /*isIncompleteContinuation*/ false); }, }; } } - function assertCompletionDetailsOk(fileName: string, entry: ts.projectSystem.protocol.CompletionEntry) { - const project = projectService.getDefaultProjectForFile(ts.server.toNormalizedPath(fileName), /*ensureProject*/ true)!; - const file = ts.Debug.checkDefined(project.getLanguageService(/*ensureSynchronized*/ true).getProgram()?.getSourceFile(fileName)); - const { line, character } = ts.getLineAndCharacterOfPosition(file, file.text.length - 1); - const details = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompletionDetails, + function assertCompletionDetailsOk(fileName: string, entry: CompletionEntry) { + const project = projectService.getDefaultProjectForFile(toNormalizedPath(fileName), /*ensureProject*/ true)!; + const file = Debug.checkDefined(project.getLanguageService(/*ensureSynchronized*/ true).getProgram()?.getSourceFile(fileName)); + const { line, character } = getLineAndCharacterOfPosition(file, file.text.length - 1); + const details = session.executeCommandSeq({ + command: CommandTypes.CompletionDetails, arguments: { file: fileName, line: line + 1, @@ -252,7 +263,7 @@ function setup(files: ts.projectSystem.File[]) { data: entry.data, }] } - }).response as ts.projectSystem.protocol.CompletionEntryDetails[]; + }).response as CompletionEntryDetails[]; assert(details[0]); assert(details[0].codeActions); diff --git a/src/testRunner/unittests/tsserver/configFileSearch.ts b/src/testRunner/unittests/tsserver/configFileSearch.ts index 7e746e46a54a5..b3ff9610786c3 100644 --- a/src/testRunner/unittests/tsserver/configFileSearch.ts +++ b/src/testRunner/unittests/tsserver/configFileSearch.ts @@ -1,4 +1,11 @@ -import * as ts from "../../_namespaces/ts"; +import { emptyArray } from "../../../compiler/core"; +import { Debug } from "../../../compiler/debug"; +import { getDirectoryPath } from "../../../compiler/path"; +import { + checkNumberOfConfiguredProjects, checkNumberOfInferredProjects, checkNumberOfProjects, checkProjectActualFiles, + checkWatchedDirectories, checkWatchedFiles, checkWatchedFilesDetailed, createProjectService, createServerHost, File, + getConfigFilesToWatch, getTypeRootsFromLocation, libFile, TestProjectService, TestServerHost, +} from "./helpers"; describe("unittests:: tsserver:: searching for config file", () => { it("should stop at projectRootPath if given", () => { @@ -10,17 +17,17 @@ describe("unittests:: tsserver:: searching for config file", () => { path: "/tsconfig.json", content: "{}" }; - const host = ts.projectSystem.createServerHost([f1, configFile]); - const service = ts.projectSystem.createProjectService(host); + const host = createServerHost([f1, configFile]); + const service = createProjectService(host); service.openClientFile(f1.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, "/a"); - ts.projectSystem.checkNumberOfConfiguredProjects(service, 0); - ts.projectSystem.checkNumberOfInferredProjects(service, 1); + checkNumberOfConfiguredProjects(service, 0); + checkNumberOfInferredProjects(service, 1); service.closeClientFile(f1.path); service.openClientFile(f1.path); - ts.projectSystem.checkNumberOfConfiguredProjects(service, 1); - ts.projectSystem.checkNumberOfInferredProjects(service, 0); + checkNumberOfConfiguredProjects(service, 1); + checkNumberOfInferredProjects(service, 0); }); it("should use projectRootPath when searching for inferred project again", () => { @@ -38,23 +45,23 @@ describe("unittests:: tsserver:: searching for config file", () => { path: "/a/b/projects/tsconfig.json", content: "{}" }; - const host = ts.projectSystem.createServerHost([f1, ts.projectSystem.libFile, configFile, configFile2]); - const service = ts.projectSystem.createProjectService(host); + const host = createServerHost([f1, libFile, configFile, configFile2]); + const service = createProjectService(host); service.openClientFile(f1.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, projectDir); - ts.projectSystem.checkNumberOfProjects(service, { configuredProjects: 1 }); + checkNumberOfProjects(service, { configuredProjects: 1 }); assert.isDefined(service.configuredProjects.get(configFile.path)); - ts.projectSystem.checkWatchedFiles(host, [ts.projectSystem.libFile.path, configFile.path]); - ts.projectSystem.checkWatchedDirectories(host, [], /*recursive*/ false); - const typeRootLocations = ts.projectSystem.getTypeRootsFromLocation(configFileLocation); - ts.projectSystem.checkWatchedDirectories(host, typeRootLocations.concat(configFileLocation), /*recursive*/ true); + checkWatchedFiles(host, [libFile.path, configFile.path]); + checkWatchedDirectories(host, [], /*recursive*/ false); + const typeRootLocations = getTypeRootsFromLocation(configFileLocation); + checkWatchedDirectories(host, typeRootLocations.concat(configFileLocation), /*recursive*/ true); // Delete config file - should create inferred project and not configured project host.deleteFile(configFile.path); host.runQueuedTimeoutCallbacks(); - ts.projectSystem.checkNumberOfProjects(service, { inferredProjects: 1 }); - ts.projectSystem.checkWatchedFiles(host, [ts.projectSystem.libFile.path, configFile.path, `${configFileLocation}/jsconfig.json`, `${projectDir}/tsconfig.json`, `${projectDir}/jsconfig.json`]); - ts.projectSystem.checkWatchedDirectories(host, [], /*recursive*/ false); - ts.projectSystem.checkWatchedDirectories(host, typeRootLocations, /*recursive*/ true); + checkNumberOfProjects(service, { inferredProjects: 1 }); + checkWatchedFiles(host, [libFile.path, configFile.path, `${configFileLocation}/jsconfig.json`, `${projectDir}/tsconfig.json`, `${projectDir}/jsconfig.json`]); + checkWatchedDirectories(host, [], /*recursive*/ false); + checkWatchedDirectories(host, typeRootLocations, /*recursive*/ true); }); it("should use projectRootPath when searching for inferred project again 2", () => { @@ -72,75 +79,75 @@ describe("unittests:: tsserver:: searching for config file", () => { path: "/a/b/projects/tsconfig.json", content: "{}" }; - const host = ts.projectSystem.createServerHost([f1, ts.projectSystem.libFile, configFile, configFile2]); - const service = ts.projectSystem.createProjectService(host, { useSingleInferredProject: true, useInferredProjectPerProjectRoot: true }); + const host = createServerHost([f1, libFile, configFile, configFile2]); + const service = createProjectService(host, { useSingleInferredProject: true, useInferredProjectPerProjectRoot: true }); service.openClientFile(f1.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, projectDir); - ts.projectSystem.checkNumberOfProjects(service, { configuredProjects: 1 }); + checkNumberOfProjects(service, { configuredProjects: 1 }); assert.isDefined(service.configuredProjects.get(configFile.path)); - ts.projectSystem.checkWatchedFiles(host, [ts.projectSystem.libFile.path, configFile.path]); - ts.projectSystem.checkWatchedDirectories(host, [], /*recursive*/ false); - ts.projectSystem.checkWatchedDirectories(host, ts.projectSystem.getTypeRootsFromLocation(configFileLocation).concat(configFileLocation), /*recursive*/ true); + checkWatchedFiles(host, [libFile.path, configFile.path]); + checkWatchedDirectories(host, [], /*recursive*/ false); + checkWatchedDirectories(host, getTypeRootsFromLocation(configFileLocation).concat(configFileLocation), /*recursive*/ true); // Delete config file - should create inferred project with project root path set host.deleteFile(configFile.path); host.runQueuedTimeoutCallbacks(); - ts.projectSystem.checkNumberOfProjects(service, { inferredProjects: 1 }); + checkNumberOfProjects(service, { inferredProjects: 1 }); assert.equal(service.inferredProjects[0].projectRootPath, projectDir); - ts.projectSystem.checkWatchedFiles(host, [ts.projectSystem.libFile.path, configFile.path, `${configFileLocation}/jsconfig.json`, `${projectDir}/tsconfig.json`, `${projectDir}/jsconfig.json`]); - ts.projectSystem.checkWatchedDirectories(host, [], /*recursive*/ false); - ts.projectSystem.checkWatchedDirectories(host, ts.projectSystem.getTypeRootsFromLocation(projectDir), /*recursive*/ true); + checkWatchedFiles(host, [libFile.path, configFile.path, `${configFileLocation}/jsconfig.json`, `${projectDir}/tsconfig.json`, `${projectDir}/jsconfig.json`]); + checkWatchedDirectories(host, [], /*recursive*/ false); + checkWatchedDirectories(host, getTypeRootsFromLocation(projectDir), /*recursive*/ true); }); describe("when the opened file is not from project root", () => { const projectRoot = "/a/b/projects/project"; - const file: ts.projectSystem.File = { + const file: File = { path: `${projectRoot}/src/index.ts`, content: "let y = 10" }; - const tsconfig: ts.projectSystem.File = { + const tsconfig: File = { path: `${projectRoot}/tsconfig.json`, content: "{}" }; - const dirOfFile = ts.getDirectoryPath(file.path); + const dirOfFile = getDirectoryPath(file.path); - function openClientFile(files: ts.projectSystem.File[]) { - const host = ts.projectSystem.createServerHost(files); - const projectService = ts.projectSystem.createProjectService(host); + function openClientFile(files: File[]) { + const host = createServerHost(files); + const projectService = createProjectService(host); projectService.openClientFile(file.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, "/a/b/projects/proj"); return { host, projectService }; } - function verifyConfiguredProject(host: ts.projectSystem.TestServerHost, projectService: ts.projectSystem.TestProjectService, orphanInferredProject?: boolean) { + function verifyConfiguredProject(host: TestServerHost, projectService: TestProjectService, orphanInferredProject?: boolean) { projectService.checkNumberOfProjects({ configuredProjects: 1, inferredProjects: orphanInferredProject ? 1 : 0 }); - const project = ts.Debug.checkDefined(projectService.configuredProjects.get(tsconfig.path)); + const project = Debug.checkDefined(projectService.configuredProjects.get(tsconfig.path)); if (orphanInferredProject) { const inferredProject = projectService.inferredProjects[0]; assert.isTrue(inferredProject.isOrphan()); } - ts.projectSystem.checkProjectActualFiles(project, [file.path, ts.projectSystem.libFile.path, tsconfig.path]); - ts.projectSystem.checkWatchedFiles(host, [ts.projectSystem.libFile.path, tsconfig.path]); - ts.projectSystem.checkWatchedDirectories(host, ts.emptyArray, /*recursive*/ false); - ts.projectSystem.checkWatchedDirectories(host, (orphanInferredProject ? [projectRoot, `${dirOfFile}/node_modules/@types`] : [projectRoot]).concat(ts.projectSystem.getTypeRootsFromLocation(projectRoot)), /*recursive*/ true); + checkProjectActualFiles(project, [file.path, libFile.path, tsconfig.path]); + checkWatchedFiles(host, [libFile.path, tsconfig.path]); + checkWatchedDirectories(host, emptyArray, /*recursive*/ false); + checkWatchedDirectories(host, (orphanInferredProject ? [projectRoot, `${dirOfFile}/node_modules/@types`] : [projectRoot]).concat(getTypeRootsFromLocation(projectRoot)), /*recursive*/ true); } - function verifyInferredProject(host: ts.projectSystem.TestServerHost, projectService: ts.projectSystem.TestProjectService) { + function verifyInferredProject(host: TestServerHost, projectService: TestProjectService) { projectService.checkNumberOfProjects({ inferredProjects: 1 }); const project = projectService.inferredProjects[0]; assert.isDefined(project); - const filesToWatch = [ts.projectSystem.libFile.path, ...ts.projectSystem.getConfigFilesToWatch(dirOfFile)]; + const filesToWatch = [libFile.path, ...getConfigFilesToWatch(dirOfFile)]; - ts.projectSystem.checkProjectActualFiles(project, [file.path, ts.projectSystem.libFile.path]); - ts.projectSystem.checkWatchedFiles(host, filesToWatch); - ts.projectSystem.checkWatchedDirectories(host, ts.emptyArray, /*recursive*/ false); - ts.projectSystem.checkWatchedDirectories(host, ts.projectSystem.getTypeRootsFromLocation(dirOfFile), /*recursive*/ true); + checkProjectActualFiles(project, [file.path, libFile.path]); + checkWatchedFiles(host, filesToWatch); + checkWatchedDirectories(host, emptyArray, /*recursive*/ false); + checkWatchedDirectories(host, getTypeRootsFromLocation(dirOfFile), /*recursive*/ true); } it("tsconfig for the file exists", () => { - const { host, projectService } = openClientFile([file, ts.projectSystem.libFile, tsconfig]); + const { host, projectService } = openClientFile([file, libFile, tsconfig]); verifyConfiguredProject(host, projectService); host.deleteFile(tsconfig.path); @@ -153,7 +160,7 @@ describe("unittests:: tsserver:: searching for config file", () => { }); it("tsconfig for the file does not exist", () => { - const { host, projectService } = openClientFile([file, ts.projectSystem.libFile]); + const { host, projectService } = openClientFile([file, libFile]); verifyInferredProject(host, projectService); host.writeFile(tsconfig.path, tsconfig.content); @@ -170,12 +177,12 @@ describe("unittests:: tsserver:: searching for config file", () => { const root = "/root/teams/VSCode68/Shared Documents/General/jt-ts-test-workspace"; function verifyConfigFileWatch(projectRootPath: string | undefined) { const path = `${root}/x.js`; - const host = ts.projectSystem.createServerHost([ts.projectSystem.libFile, { path, content: "const x = 10" }], { useCaseSensitiveFileNames: true }); - const service = ts.projectSystem.createProjectService(host); + const host = createServerHost([libFile, { path, content: "const x = 10" }], { useCaseSensitiveFileNames: true }); + const service = createProjectService(host); service.openClientFile(path, /*fileContent*/ undefined, /*scriptKind*/ undefined, projectRootPath); - ts.projectSystem.checkNumberOfProjects(service, { inferredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(service.inferredProjects[0], [path, ts.projectSystem.libFile.path]); - ts.projectSystem.checkWatchedFilesDetailed(host, [ts.projectSystem.libFile.path, ...ts.projectSystem.getConfigFilesToWatch(root)], 1); + checkNumberOfProjects(service, { inferredProjects: 1 }); + checkProjectActualFiles(service.inferredProjects[0], [path, libFile.path]); + checkWatchedFilesDetailed(host, [libFile.path, ...getConfigFilesToWatch(root)], 1); } it("when projectRootPath is not present", () => { diff --git a/src/testRunner/unittests/tsserver/configuredProjects.ts b/src/testRunner/unittests/tsserver/configuredProjects.ts index 897b2895812c1..f0f620b37c8c7 100644 --- a/src/testRunner/unittests/tsserver/configuredProjects.ts +++ b/src/testRunner/unittests/tsserver/configuredProjects.ts @@ -1,8 +1,27 @@ -import * as ts from "../../_namespaces/ts"; +import { emptyArray, find, map, mapDefined } from "../../../compiler/core"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { combinePaths, getDirectoryPath } from "../../../compiler/path"; +import { Path } from "../../../compiler/types"; +import { createCompilerDiagnostic } from "../../../compiler/utilities"; +import { createTextSpan } from "../../../compiler/utilitiesPublic"; +import { + ConfigFileDiagEvent, maxProgramSizeForNonTsFiles, ProjectLanguageServiceStateEvent, +} from "../../../server/editorServices"; +import { CommandTypes, GetApplicableRefactorsRequest, OpenRequest } from "../../../server/protocol"; +import { NormalizedPath, toNormalizedPath } from "../../../server/utilitiesPublic"; +import { ensureErrorFreeBuild, projectRoot } from "../tscWatch/helpers"; +import { + baselineTsserverLogs, checkNumberOfConfiguredProjects, checkNumberOfInferredProjects, checkNumberOfProjects, + checkOpenFiles, checkProjectActualFiles, checkProjectRootFiles, checkWatchedDirectories, + checkWatchedDirectoriesDetailed, checkWatchedFiles, commonFile1, commonFile2, configuredProjectAt, + createLoggerWithInMemoryLogs, createProjectService, createServerHost, createSession, createSessionWithEventTracking, + File, getConfigFilesToWatch, getTypeRootsFromLocation, libFile, nodeModulesAtTypes, openFilesForSession, SymLink, + verifyGetErrRequest, +} from "./helpers"; describe("unittests:: tsserver:: ConfiguredProjects", () => { it("create configured project without file list", () => { - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: ` { @@ -12,39 +31,39 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { ] }` }; - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/b/c/f1.ts", content: "let x = 1" }; - const file2: ts.projectSystem.File = { + const file2: File = { path: "/a/b/d/f2.ts", content: "let y = 1" }; - const file3: ts.projectSystem.File = { + const file3: File = { path: "/a/b/e/f3.ts", content: "let z = 1" }; - const host = ts.projectSystem.createServerHost([configFile, ts.projectSystem.libFile, file1, file2, file3]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([configFile, libFile, file1, file2, file3]); + const projectService = createProjectService(host); const { configFileName, configFileErrors } = projectService.openClientFile(file1.path); assert(configFileName, "should find config file"); assert.isTrue(!configFileErrors || configFileErrors.length === 0, `expect no errors in config file, got ${JSON.stringify(configFileErrors)}`); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 0); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); + checkNumberOfInferredProjects(projectService, 0); + checkNumberOfConfiguredProjects(projectService, 1); - const project = ts.projectSystem.configuredProjectAt(projectService, 0); - ts.projectSystem.checkProjectActualFiles(project, [file1.path, ts.projectSystem.libFile.path, file2.path, configFile.path]); - ts.projectSystem.checkProjectRootFiles(project, [file1.path, file2.path]); + const project = configuredProjectAt(projectService, 0); + checkProjectActualFiles(project, [file1.path, libFile.path, file2.path, configFile.path]); + checkProjectRootFiles(project, [file1.path, file2.path]); // watching all files except one that was open - ts.projectSystem.checkWatchedFiles(host, [configFile.path, file2.path, ts.projectSystem.libFile.path]); - const configFileDirectory = ts.getDirectoryPath(configFile.path); - ts.projectSystem.checkWatchedDirectories(host, [configFileDirectory, ts.combinePaths(configFileDirectory, ts.projectSystem.nodeModulesAtTypes)], /*recursive*/ true); + checkWatchedFiles(host, [configFile.path, file2.path, libFile.path]); + const configFileDirectory = getDirectoryPath(configFile.path); + checkWatchedDirectories(host, [configFileDirectory, combinePaths(configFileDirectory, nodeModulesAtTypes)], /*recursive*/ true); }); it("create configured project with the file list", () => { - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: ` { @@ -52,64 +71,64 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { "include": ["*.ts"] }` }; - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/b/f1.ts", content: "let x = 1" }; - const file2: ts.projectSystem.File = { + const file2: File = { path: "/a/b/f2.ts", content: "let y = 1" }; - const file3: ts.projectSystem.File = { + const file3: File = { path: "/a/b/c/f3.ts", content: "let z = 1" }; - const host = ts.projectSystem.createServerHost([configFile, ts.projectSystem.libFile, file1, file2, file3]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([configFile, libFile, file1, file2, file3]); + const projectService = createProjectService(host); const { configFileName, configFileErrors } = projectService.openClientFile(file1.path); assert(configFileName, "should find config file"); assert.isTrue(!configFileErrors || configFileErrors.length === 0, `expect no errors in config file, got ${JSON.stringify(configFileErrors)}`); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 0); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); + checkNumberOfInferredProjects(projectService, 0); + checkNumberOfConfiguredProjects(projectService, 1); - const project = ts.projectSystem.configuredProjectAt(projectService, 0); - ts.projectSystem.checkProjectActualFiles(project, [file1.path, ts.projectSystem.libFile.path, file2.path, configFile.path]); - ts.projectSystem.checkProjectRootFiles(project, [file1.path, file2.path]); + const project = configuredProjectAt(projectService, 0); + checkProjectActualFiles(project, [file1.path, libFile.path, file2.path, configFile.path]); + checkProjectRootFiles(project, [file1.path, file2.path]); // watching all files except one that was open - ts.projectSystem.checkWatchedFiles(host, [configFile.path, file2.path, ts.projectSystem.libFile.path]); - ts.projectSystem.checkWatchedDirectories(host, [ts.getDirectoryPath(configFile.path)], /*recursive*/ false); + checkWatchedFiles(host, [configFile.path, file2.path, libFile.path]); + checkWatchedDirectories(host, [getDirectoryPath(configFile.path)], /*recursive*/ false); }); it("add and then remove a config file in a folder with loose files", () => { - const configFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const configFile: File = { + path: `${projectRoot}/tsconfig.json`, content: `{ "files": ["commonFile1.ts"] }` }; - const commonFile1: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/commonFile1.ts`, + const commonFile1: File = { + path: `${projectRoot}/commonFile1.ts`, content: "let x = 1" }; - const commonFile2: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/commonFile2.ts`, + const commonFile2: File = { + path: `${projectRoot}/commonFile2.ts`, content: "let y = 1" }; - const host = ts.projectSystem.createServerHost([ts.projectSystem.libFile, commonFile1, commonFile2]); + const host = createServerHost([libFile, commonFile1, commonFile2]); - const projectService = ts.projectSystem.createProjectService(host); + const projectService = createProjectService(host); projectService.openClientFile(commonFile1.path); projectService.openClientFile(commonFile2.path); projectService.checkNumberOfProjects({ inferredProjects: 2 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [commonFile1.path, ts.projectSystem.libFile.path]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [commonFile2.path, ts.projectSystem.libFile.path]); + checkProjectActualFiles(projectService.inferredProjects[0], [commonFile1.path, libFile.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [commonFile2.path, libFile.path]); - const watchedFiles = ts.projectSystem.getConfigFilesToWatch(ts.tscWatch.projectRoot).concat(ts.projectSystem.libFile.path); - ts.projectSystem.checkWatchedFiles(host, watchedFiles); + const watchedFiles = getConfigFilesToWatch(projectRoot).concat(libFile.path); + checkWatchedFiles(host, watchedFiles); // Add a tsconfig file host.writeFile(configFile.path, configFile.content); @@ -117,50 +136,50 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { projectService.checkNumberOfProjects({ inferredProjects: 2, configuredProjects: 1 }); assert.isTrue(projectService.inferredProjects[0].isOrphan()); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [commonFile2.path, ts.projectSystem.libFile.path]); - ts.projectSystem.checkProjectActualFiles(projectService.configuredProjects.get(configFile.path)!, [ts.projectSystem.libFile.path, commonFile1.path, configFile.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [commonFile2.path, libFile.path]); + checkProjectActualFiles(projectService.configuredProjects.get(configFile.path)!, [libFile.path, commonFile1.path, configFile.path]); - ts.projectSystem.checkWatchedFiles(host, watchedFiles); + checkWatchedFiles(host, watchedFiles); // remove the tsconfig file host.deleteFile(configFile.path); projectService.checkNumberOfProjects({ inferredProjects: 2 }); assert.isTrue(projectService.inferredProjects[0].isOrphan()); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [commonFile2.path, ts.projectSystem.libFile.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [commonFile2.path, libFile.path]); host.checkTimeoutQueueLengthAndRun(1); // Refresh inferred projects projectService.checkNumberOfProjects({ inferredProjects: 2 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [commonFile1.path, ts.projectSystem.libFile.path]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [commonFile2.path, ts.projectSystem.libFile.path]); - ts.projectSystem.checkWatchedFiles(host, watchedFiles); + checkProjectActualFiles(projectService.inferredProjects[0], [commonFile1.path, libFile.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [commonFile2.path, libFile.path]); + checkWatchedFiles(host, watchedFiles); }); it("add new files to a configured project without file list", () => { - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{}` }; - const host = ts.projectSystem.createServerHost([ts.projectSystem.commonFile1, ts.projectSystem.libFile, configFile]); - const projectService = ts.projectSystem.createProjectService(host); - projectService.openClientFile(ts.projectSystem.commonFile1.path); - const configFileDir = ts.getDirectoryPath(configFile.path); - ts.projectSystem.checkWatchedDirectories(host, [configFileDir, ts.combinePaths(configFileDir, ts.projectSystem.nodeModulesAtTypes)], /*recursive*/ true); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); + const host = createServerHost([commonFile1, libFile, configFile]); + const projectService = createProjectService(host); + projectService.openClientFile(commonFile1.path); + const configFileDir = getDirectoryPath(configFile.path); + checkWatchedDirectories(host, [configFileDir, combinePaths(configFileDir, nodeModulesAtTypes)], /*recursive*/ true); + checkNumberOfConfiguredProjects(projectService, 1); - const project = ts.projectSystem.configuredProjectAt(projectService, 0); - ts.projectSystem.checkProjectRootFiles(project, [ts.projectSystem.commonFile1.path]); + const project = configuredProjectAt(projectService, 0); + checkProjectRootFiles(project, [commonFile1.path]); // add a new ts file - host.writeFile(ts.projectSystem.commonFile2.path, ts.projectSystem.commonFile2.content); + host.writeFile(commonFile2.path, commonFile2.content); host.checkTimeoutQueueLengthAndRun(2); // project service waits for 250ms to update the project structure, therefore the assertion needs to wait longer. - ts.projectSystem.checkProjectRootFiles(project, [ts.projectSystem.commonFile1.path, ts.projectSystem.commonFile2.path]); + checkProjectRootFiles(project, [commonFile1.path, commonFile2.path]); }); it("should ignore non-existing files specified in the config file", () => { - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": {}, @@ -170,83 +189,83 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { ] }` }; - const host = ts.projectSystem.createServerHost([ts.projectSystem.commonFile1, ts.projectSystem.commonFile2, configFile]); - const projectService = ts.projectSystem.createProjectService(host); - projectService.openClientFile(ts.projectSystem.commonFile1.path); - projectService.openClientFile(ts.projectSystem.commonFile2.path); + const host = createServerHost([commonFile1, commonFile2, configFile]); + const projectService = createProjectService(host); + projectService.openClientFile(commonFile1.path); + projectService.openClientFile(commonFile2.path); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); - const project = ts.projectSystem.configuredProjectAt(projectService, 0); - ts.projectSystem.checkProjectRootFiles(project, [ts.projectSystem.commonFile1.path]); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 1); + checkNumberOfConfiguredProjects(projectService, 1); + const project = configuredProjectAt(projectService, 0); + checkProjectRootFiles(project, [commonFile1.path]); + checkNumberOfInferredProjects(projectService, 1); }); it("handle recreated files correctly", () => { - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{}` }; - const host = ts.projectSystem.createServerHost([ts.projectSystem.commonFile1, ts.projectSystem.commonFile2, configFile]); - const projectService = ts.projectSystem.createProjectService(host); - projectService.openClientFile(ts.projectSystem.commonFile1.path); + const host = createServerHost([commonFile1, commonFile2, configFile]); + const projectService = createProjectService(host); + projectService.openClientFile(commonFile1.path); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); - const project = ts.projectSystem.configuredProjectAt(projectService, 0); - ts.projectSystem.checkProjectRootFiles(project, [ts.projectSystem.commonFile1.path, ts.projectSystem.commonFile2.path]); + checkNumberOfConfiguredProjects(projectService, 1); + const project = configuredProjectAt(projectService, 0); + checkProjectRootFiles(project, [commonFile1.path, commonFile2.path]); // delete commonFile2 - host.deleteFile(ts.projectSystem.commonFile2.path); + host.deleteFile(commonFile2.path); host.checkTimeoutQueueLengthAndRun(2); - ts.projectSystem.checkProjectRootFiles(project, [ts.projectSystem.commonFile1.path]); + checkProjectRootFiles(project, [commonFile1.path]); // re-add commonFile2 - host.writeFile(ts.projectSystem.commonFile2.path, ts.projectSystem.commonFile2.content); + host.writeFile(commonFile2.path, commonFile2.content); host.checkTimeoutQueueLengthAndRun(2); - ts.projectSystem.checkProjectRootFiles(project, [ts.projectSystem.commonFile1.path, ts.projectSystem.commonFile2.path]); + checkProjectRootFiles(project, [commonFile1.path, commonFile2.path]); }); it("files explicitly excluded in config file", () => { - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": {}, "exclude": ["/a/c"] }` }; - const excludedFile1: ts.projectSystem.File = { + const excludedFile1: File = { path: "/a/c/excluedFile1.ts", content: `let t = 1;` }; - const host = ts.projectSystem.createServerHost([ts.projectSystem.commonFile1, ts.projectSystem.commonFile2, excludedFile1, configFile]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([commonFile1, commonFile2, excludedFile1, configFile]); + const projectService = createProjectService(host); - projectService.openClientFile(ts.projectSystem.commonFile1.path); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); - const project = ts.projectSystem.configuredProjectAt(projectService, 0); - ts.projectSystem.checkProjectRootFiles(project, [ts.projectSystem.commonFile1.path, ts.projectSystem.commonFile2.path]); + projectService.openClientFile(commonFile1.path); + checkNumberOfConfiguredProjects(projectService, 1); + const project = configuredProjectAt(projectService, 0); + checkProjectRootFiles(project, [commonFile1.path, commonFile2.path]); projectService.openClientFile(excludedFile1.path); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 1); + checkNumberOfInferredProjects(projectService, 1); }); it("should properly handle module resolution changes in config file", () => { - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/b/file1.ts", content: `import { T } from "module1";` }; - const nodeModuleFile: ts.projectSystem.File = { + const nodeModuleFile: File = { path: "/a/b/node_modules/module1.ts", content: `export interface T {}` }; - const classicModuleFile: ts.projectSystem.File = { + const classicModuleFile: File = { path: "/a/module1.ts", content: `export interface T {}` }; - const randomFile: ts.projectSystem.File = { + const randomFile: File = { path: "/a/file1.ts", content: `export interface T {}` }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -256,17 +275,17 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { }` }; const files = [file1, nodeModuleFile, classicModuleFile, configFile, randomFile]; - const host = ts.projectSystem.createServerHost(files); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost(files); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); projectService.openClientFile(nodeModuleFile.path); projectService.openClientFile(classicModuleFile.path); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 1 }); - const project = ts.projectSystem.configuredProjectAt(projectService, 0); + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 1 }); + const project = configuredProjectAt(projectService, 0); const inferredProject0 = projectService.inferredProjects[0]; - ts.projectSystem.checkProjectActualFiles(project, [file1.path, nodeModuleFile.path, configFile.path]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [classicModuleFile.path]); + checkProjectActualFiles(project, [file1.path, nodeModuleFile.path, configFile.path]); + checkProjectActualFiles(projectService.inferredProjects[0], [classicModuleFile.path]); host.writeFile(configFile.path, `{ "compilerOptions": { @@ -276,33 +295,33 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { }`); host.checkTimeoutQueueLengthAndRun(2); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); // will not remove project 1 - ts.projectSystem.checkProjectActualFiles(project, [file1.path, classicModuleFile.path, configFile.path]); + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); // will not remove project 1 + checkProjectActualFiles(project, [file1.path, classicModuleFile.path, configFile.path]); assert.strictEqual(projectService.inferredProjects[0], inferredProject0); assert.isTrue(projectService.inferredProjects[0].isOrphan()); const inferredProject1 = projectService.inferredProjects[1]; - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [nodeModuleFile.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [nodeModuleFile.path]); // Open random file and it will reuse first inferred project projectService.openClientFile(randomFile.path); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); - ts.projectSystem.checkProjectActualFiles(project, [file1.path, classicModuleFile.path, configFile.path]); + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); + checkProjectActualFiles(project, [file1.path, classicModuleFile.path, configFile.path]); assert.strictEqual(projectService.inferredProjects[0], inferredProject0); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [randomFile.path]); // Reuses first inferred project + checkProjectActualFiles(projectService.inferredProjects[0], [randomFile.path]); // Reuses first inferred project assert.strictEqual(projectService.inferredProjects[1], inferredProject1); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [nodeModuleFile.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [nodeModuleFile.path]); }); it("should keep the configured project when the opened file is referenced by the project but not its root", () => { - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/b/main.ts", content: "import { objA } from './obj-a';" }; - const file2: ts.projectSystem.File = { + const file2: File = { path: "/a/b/obj-a.ts", content: `export const objA = Object.assign({foo: "bar"}, {bar: "baz"});` }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -311,25 +330,25 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { "files": [ "main.ts" ] }` }; - const host = ts.projectSystem.createServerHost([file1, file2, configFile]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2, configFile]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); projectService.closeClientFile(file1.path); projectService.openClientFile(file2.path); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 0); + checkNumberOfConfiguredProjects(projectService, 1); + checkNumberOfInferredProjects(projectService, 0); }); it("should keep the configured project when the opened file is referenced by the project but not its root", () => { - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/b/main.ts", content: "import { objA } from './obj-a';" }; - const file2: ts.projectSystem.File = { + const file2: File = { path: "/a/b/obj-a.ts", content: `export const objA = Object.assign({foo: "bar"}, {bar: "baz"});` }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -338,17 +357,17 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { "files": [ "main.ts" ] }` }; - const host = ts.projectSystem.createServerHost([file1, file2, configFile]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2, configFile]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); projectService.closeClientFile(file1.path); projectService.openClientFile(file2.path); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 0); + checkNumberOfConfiguredProjects(projectService, 1); + checkNumberOfInferredProjects(projectService, 0); }); it("should tolerate config file errors and still try to build a project", () => { - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -358,11 +377,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { "someOtherProperty": {} }` }; - const host = ts.projectSystem.createServerHost([ts.projectSystem.commonFile1, ts.projectSystem.commonFile2, ts.projectSystem.libFile, configFile]); - const projectService = ts.projectSystem.createProjectService(host); - projectService.openClientFile(ts.projectSystem.commonFile1.path); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); - ts.projectSystem.checkProjectRootFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [ts.projectSystem.commonFile1.path, ts.projectSystem.commonFile2.path]); + const host = createServerHost([commonFile1, commonFile2, libFile, configFile]); + const projectService = createProjectService(host); + projectService.openClientFile(commonFile1.path); + checkNumberOfConfiguredProjects(projectService, 1); + checkProjectRootFiles(configuredProjectAt(projectService, 0), [commonFile1.path, commonFile2.path]); }); it("should reuse same project if file is opened from the configured project that has no open files", () => { @@ -374,7 +393,7 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { path: "/a/b/main2.ts", content: "let y =1;" }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -383,21 +402,21 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { "files": [ "main.ts", "main2.ts" ] }` }; - const host = ts.projectSystem.createServerHost([file1, file2, configFile, ts.projectSystem.libFile]); - const projectService = ts.projectSystem.createProjectService(host, { useSingleInferredProject: true }); + const host = createServerHost([file1, file2, configFile, libFile]); + const projectService = createProjectService(host, { useSingleInferredProject: true }); projectService.openClientFile(file1.path); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); + checkNumberOfConfiguredProjects(projectService, 1); const project = projectService.configuredProjects.get(configFile.path)!; assert.isTrue(project.hasOpenRef()); // file1 projectService.closeClientFile(file1.path); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); + checkNumberOfConfiguredProjects(projectService, 1); assert.strictEqual(projectService.configuredProjects.get(configFile.path), project); assert.isFalse(project.hasOpenRef()); // No open files assert.isFalse(project.isClosed()); projectService.openClientFile(file2.path); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); + checkNumberOfConfiguredProjects(projectService, 1); assert.strictEqual(projectService.configuredProjects.get(configFile.path), project); assert.isTrue(project.hasOpenRef()); // file2 assert.isFalse(project.isClosed()); @@ -408,7 +427,7 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { path: "/a/b/main.ts", content: "let x =1;" }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -417,59 +436,59 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { "files": [ "main.ts" ] }` }; - const host = ts.projectSystem.createServerHost([file1, configFile, ts.projectSystem.libFile]); - const projectService = ts.projectSystem.createProjectService(host, { useSingleInferredProject: true }); + const host = createServerHost([file1, configFile, libFile]); + const projectService = createProjectService(host, { useSingleInferredProject: true }); projectService.openClientFile(file1.path); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); + checkNumberOfConfiguredProjects(projectService, 1); const project = projectService.configuredProjects.get(configFile.path)!; assert.isTrue(project.hasOpenRef()); // file1 projectService.closeClientFile(file1.path); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); + checkNumberOfConfiguredProjects(projectService, 1); assert.strictEqual(projectService.configuredProjects.get(configFile.path), project); assert.isFalse(project.hasOpenRef()); // No files assert.isFalse(project.isClosed()); - projectService.openClientFile(ts.projectSystem.libFile.path); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 0); + projectService.openClientFile(libFile.path); + checkNumberOfConfiguredProjects(projectService, 0); assert.isFalse(project.hasOpenRef()); // No files + project closed assert.isTrue(project.isClosed()); }); it("open file become a part of configured project if it is referenced from root file", () => { const file1 = { - path: `${ts.tscWatch.projectRoot}/a/b/f1.ts`, + path: `${projectRoot}/a/b/f1.ts`, content: "export let x = 5" }; const file2 = { - path: `${ts.tscWatch.projectRoot}/a/c/f2.ts`, + path: `${projectRoot}/a/c/f2.ts`, content: `import {x} from "../b/f1"` }; const file3 = { - path: `${ts.tscWatch.projectRoot}/a/c/f3.ts`, + path: `${projectRoot}/a/c/f3.ts`, content: "export let y = 1" }; const configFile = { - path: `${ts.tscWatch.projectRoot}/a/c/tsconfig.json`, + path: `${projectRoot}/a/c/tsconfig.json`, content: JSON.stringify({ compilerOptions: {}, files: ["f2.ts", "f3.ts"] }) }; - const host = ts.projectSystem.createServerHost([file1, file2, file3]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2, file3]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file1.path]); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkProjectActualFiles(projectService.inferredProjects[0], [file1.path]); projectService.openClientFile(file3.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 2 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file1.path]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [file3.path]); + checkNumberOfProjects(projectService, { inferredProjects: 2 }); + checkProjectActualFiles(projectService.inferredProjects[0], [file1.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [file3.path]); host.writeFile(configFile.path, configFile.content); host.checkTimeoutQueueLengthAndRun(2); // load configured project from disk + ensureProjectsForOpenFiles - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [file1.path, file2.path, file3.path, configFile.path]); + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); + checkProjectActualFiles(configuredProjectAt(projectService, 0), [file1.path, file2.path, file3.path, configFile.path]); assert.isTrue(projectService.inferredProjects[0].isOrphan()); assert.isTrue(projectService.inferredProjects[1].isOrphan()); }); @@ -488,19 +507,19 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { content: JSON.stringify({ compilerOptions: {} }) }; - const host = ts.projectSystem.createServerHost([file1, configFile]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, configFile]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [file1.path, configFile.path]); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkProjectActualFiles(configuredProjectAt(projectService, 0), [file1.path, configFile.path]); host.writeFile(file2.path, file2.content); host.checkTimeoutQueueLengthAndRun(2); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); - ts.projectSystem.checkProjectRootFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [file1.path, file2.path]); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkProjectRootFiles(configuredProjectAt(projectService, 0), [file1.path, file2.path]); }); it("can correctly update configured project when set of root files has changed (new file in list of files)", () => { @@ -517,18 +536,18 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { content: JSON.stringify({ compilerOptions: {}, files: ["f1.ts"] }) }; - const host = ts.projectSystem.createServerHost([file1, file2, configFile]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2, configFile]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [file1.path, configFile.path]); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkProjectActualFiles(configuredProjectAt(projectService, 0), [file1.path, configFile.path]); host.writeFile(configFile.path, JSON.stringify({ compilerOptions: {}, files: ["f1.ts", "f2.ts"] })); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); host.checkTimeoutQueueLengthAndRun(2); - ts.projectSystem.checkProjectRootFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [file1.path, file2.path]); + checkProjectRootFiles(configuredProjectAt(projectService, 0), [file1.path, file2.path]); }); it("can update configured project when set of root files was not changed", () => { @@ -545,33 +564,33 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { content: JSON.stringify({ compilerOptions: {}, files: ["f1.ts", "f2.ts"] }) }; - const host = ts.projectSystem.createServerHost([file1, file2, configFile]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2, configFile]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [file1.path, file2.path, configFile.path]); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkProjectActualFiles(configuredProjectAt(projectService, 0), [file1.path, file2.path, configFile.path]); host.writeFile(configFile.path, JSON.stringify({ compilerOptions: { outFile: "out.js" }, files: ["f1.ts", "f2.ts"] })); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); - ts.projectSystem.checkProjectRootFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [file1.path, file2.path]); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkProjectRootFiles(configuredProjectAt(projectService, 0), [file1.path, file2.path]); }); it("Open ref of configured project when open file gets added to the project as part of configured file update", () => { - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/b/src/file1.ts", content: "let x = 1;" }; - const file2: ts.projectSystem.File = { + const file2: File = { path: "/a/b/src/file2.ts", content: "let y = 1;" }; - const file3: ts.projectSystem.File = { + const file3: File = { path: "/a/b/file3.ts", content: "let z = 1;" }; - const file4: ts.projectSystem.File = { + const file4: File = { path: "/a/file4.ts", content: "let z = 1;" }; @@ -581,34 +600,34 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { }; const files = [file1, file2, file3, file4]; - const host = ts.projectSystem.createServerHost(files.concat(configFile)); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost(files.concat(configFile)); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); projectService.openClientFile(file2.path); projectService.openClientFile(file3.path); projectService.openClientFile(file4.path); - const infos = files.map(file => projectService.getScriptInfoForPath(file.path as ts.Path)!); - ts.projectSystem.checkOpenFiles(projectService, files); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); + const infos = files.map(file => projectService.getScriptInfoForPath(file.path as Path)!); + checkOpenFiles(projectService, files); + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); const configProject1 = projectService.configuredProjects.get(configFile.path)!; assert.isTrue(configProject1.hasOpenRef()); // file1 and file3 - ts.projectSystem.checkProjectActualFiles(configProject1, [file1.path, file3.path, configFile.path]); + checkProjectActualFiles(configProject1, [file1.path, file3.path, configFile.path]); const inferredProject1 = projectService.inferredProjects[0]; - ts.projectSystem.checkProjectActualFiles(inferredProject1, [file2.path]); + checkProjectActualFiles(inferredProject1, [file2.path]); const inferredProject2 = projectService.inferredProjects[1]; - ts.projectSystem.checkProjectActualFiles(inferredProject2, [file4.path]); + checkProjectActualFiles(inferredProject2, [file4.path]); host.writeFile(configFile.path, "{}"); host.runQueuedTimeoutCallbacks(); verifyScriptInfos(); - ts.projectSystem.checkOpenFiles(projectService, files); + checkOpenFiles(projectService, files); verifyConfiguredProjectStateAfterUpdate(/*hasOpenRef*/ true, 2); // file1, file2, file3 assert.isTrue(projectService.inferredProjects[0].isOrphan()); const inferredProject3 = projectService.inferredProjects[1]; - ts.projectSystem.checkProjectActualFiles(inferredProject3, [file4.path]); + checkProjectActualFiles(inferredProject3, [file4.path]); assert.strictEqual(inferredProject3, inferredProject2); projectService.closeClientFile(file1.path); @@ -616,73 +635,73 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { projectService.closeClientFile(file4.path); verifyScriptInfos(); - ts.projectSystem.checkOpenFiles(projectService, [file3]); + checkOpenFiles(projectService, [file3]); verifyConfiguredProjectStateAfterUpdate(/*hasOpenRef*/ true, 2); // file3 assert.isTrue(projectService.inferredProjects[0].isOrphan()); assert.isTrue(projectService.inferredProjects[1].isOrphan()); projectService.openClientFile(file4.path); verifyScriptInfos(); - ts.projectSystem.checkOpenFiles(projectService, [file3, file4]); + checkOpenFiles(projectService, [file3, file4]); verifyConfiguredProjectStateAfterUpdate(/*hasOpenRef*/ true, 1); // file3 const inferredProject4 = projectService.inferredProjects[0]; - ts.projectSystem.checkProjectActualFiles(inferredProject4, [file4.path]); + checkProjectActualFiles(inferredProject4, [file4.path]); projectService.closeClientFile(file3.path); verifyScriptInfos(); - ts.projectSystem.checkOpenFiles(projectService, [file4]); + checkOpenFiles(projectService, [file4]); verifyConfiguredProjectStateAfterUpdate(/*hasOpenRef*/ false, 1); // No open files const inferredProject5 = projectService.inferredProjects[0]; - ts.projectSystem.checkProjectActualFiles(inferredProject4, [file4.path]); + checkProjectActualFiles(inferredProject4, [file4.path]); assert.strictEqual(inferredProject5, inferredProject4); - const file5: ts.projectSystem.File = { + const file5: File = { path: "/file5.ts", content: "let zz = 1;" }; host.writeFile(file5.path, file5.content); projectService.openClientFile(file5.path); verifyScriptInfosAreUndefined([file1, file2, file3]); - assert.strictEqual(projectService.getScriptInfoForPath(file4.path as ts.Path), ts.find(infos, info => info.path === file4.path)); - assert.isDefined(projectService.getScriptInfoForPath(file5.path as ts.Path)); - ts.projectSystem.checkOpenFiles(projectService, [file4, file5]); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 2 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file4.path]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [file5.path]); + assert.strictEqual(projectService.getScriptInfoForPath(file4.path as Path), find(infos, info => info.path === file4.path)); + assert.isDefined(projectService.getScriptInfoForPath(file5.path as Path)); + checkOpenFiles(projectService, [file4, file5]); + checkNumberOfProjects(projectService, { inferredProjects: 2 }); + checkProjectActualFiles(projectService.inferredProjects[0], [file4.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [file5.path]); function verifyScriptInfos() { infos.forEach(info => assert.strictEqual(projectService.getScriptInfoForPath(info.path), info)); } - function verifyScriptInfosAreUndefined(files: ts.projectSystem.File[]) { + function verifyScriptInfosAreUndefined(files: File[]) { for (const file of files) { - assert.isUndefined(projectService.getScriptInfoForPath(file.path as ts.Path)); + assert.isUndefined(projectService.getScriptInfoForPath(file.path as Path)); } } function verifyConfiguredProjectStateAfterUpdate(hasOpenRef: boolean, inferredProjects: number) { - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects }); + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects }); const configProject2 = projectService.configuredProjects.get(configFile.path)!; assert.strictEqual(configProject2, configProject1); - ts.projectSystem.checkProjectActualFiles(configProject2, [file1.path, file2.path, file3.path, configFile.path]); + checkProjectActualFiles(configProject2, [file1.path, file2.path, file3.path, configFile.path]); assert.equal(configProject2.hasOpenRef(), hasOpenRef); } }); it("Open ref of configured project when open file gets added to the project as part of configured file update buts its open file references are all closed when the update happens", () => { - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/b/src/file1.ts", content: "let x = 1;" }; - const file2: ts.projectSystem.File = { + const file2: File = { path: "/a/b/src/file2.ts", content: "let y = 1;" }; - const file3: ts.projectSystem.File = { + const file3: File = { path: "/a/b/file3.ts", content: "let z = 1;" }; - const file4: ts.projectSystem.File = { + const file4: File = { path: "/a/file4.ts", content: "let z = 1;" }; @@ -693,19 +712,19 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { const files = [file1, file2, file3]; const hostFiles = files.concat(file4, configFile); - const host = ts.projectSystem.createServerHost(hostFiles); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost(hostFiles); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); projectService.openClientFile(file2.path); projectService.openClientFile(file3.path); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 1 }); const configuredProject = projectService.configuredProjects.get(configFile.path)!; assert.isTrue(configuredProject.hasOpenRef()); // file1 and file3 - ts.projectSystem.checkProjectActualFiles(configuredProject, [file1.path, file3.path, configFile.path]); + checkProjectActualFiles(configuredProject, [file1.path, file3.path, configFile.path]); const inferredProject1 = projectService.inferredProjects[0]; - ts.projectSystem.checkProjectActualFiles(inferredProject1, [file2.path]); + checkProjectActualFiles(inferredProject1, [file2.path]); projectService.closeClientFile(file1.path); projectService.closeClientFile(file3.path); @@ -717,22 +736,22 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { projectService.openClientFile(file4.path); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); assert.strictEqual(projectService.configuredProjects.get(configFile.path), configuredProject); assert.isTrue(configuredProject.hasOpenRef()); // Pending update and F2 might get into the project assert.strictEqual(projectService.inferredProjects[0], inferredProject1); const inferredProject2 = projectService.inferredProjects[1]; - ts.projectSystem.checkProjectActualFiles(inferredProject2, [file4.path]); + checkProjectActualFiles(inferredProject2, [file4.path]); host.runQueuedTimeoutCallbacks(); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 2 }); assert.strictEqual(projectService.configuredProjects.get(configFile.path), configuredProject); assert.isTrue(configuredProject.hasOpenRef()); // file2 - ts.projectSystem.checkProjectActualFiles(configuredProject, [file1.path, file2.path, file3.path, configFile.path]); + checkProjectActualFiles(configuredProject, [file1.path, file2.path, file3.path, configFile.path]); assert.strictEqual(projectService.inferredProjects[0], inferredProject1); assert.isTrue(inferredProject1.isOrphan()); assert.strictEqual(projectService.inferredProjects[1], inferredProject2); - ts.projectSystem.checkProjectActualFiles(inferredProject2, [file4.path]); + checkProjectActualFiles(inferredProject2, [file4.path]); }); it("files are properly detached when language service is disabled", () => { @@ -752,12 +771,12 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { path: "/a/tsconfig.json", content: JSON.stringify({ compilerOptions: { allowJs: true } }) }; - const host = ts.projectSystem.createServerHost([f1, f2, f3, config]); + const host = createServerHost([f1, f2, f3, config]); const originalGetFileSize = host.getFileSize; host.getFileSize = (filePath: string) => - filePath === f2.path ? ts.server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); + filePath === f2.path ? maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); - const projectService = ts.projectSystem.createProjectService(host); + const projectService = createProjectService(host); projectService.openClientFile(f1.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); const project = projectService.configuredProjects.get(config.path)!; @@ -772,7 +791,7 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { for (const f of [f1, f2, f3]) { // All the script infos should be present and contain the project since it is still alive. - const scriptInfo = projectService.getScriptInfoForNormalizedPath(ts.server.toNormalizedPath(f.path))!; + const scriptInfo = projectService.getScriptInfoForNormalizedPath(toNormalizedPath(f.path))!; assert.equal(scriptInfo.containingProjects.length, 1, `expect 1 containing projects for '${f.path}'`); assert.equal(scriptInfo.containingProjects[0], project, `expect configured project to be the only containing project for '${f.path}'`); } @@ -789,7 +808,7 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { for (const f of [f1, f2, f3]) { // All the script infos should not be present since the project is closed and orphan script infos are collected - assert.isUndefined(projectService.getScriptInfoForNormalizedPath(ts.server.toNormalizedPath(f.path))); + assert.isUndefined(projectService.getScriptInfoForNormalizedPath(toNormalizedPath(f.path))); } }); @@ -806,34 +825,34 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { path: "/a/jsconfig.json", content: "{}" }; - const host = ts.projectSystem.createServerHost([f1, f2, config]); + const host = createServerHost([f1, f2, config]); const originalGetFileSize = host.getFileSize; host.getFileSize = (filePath: string) => - filePath === f2.path ? ts.server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); - const { session, events } = ts.projectSystem.createSessionWithEventTracking(host, ts.server.ProjectLanguageServiceStateEvent); + filePath === f2.path ? maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); + const { session, events } = createSessionWithEventTracking(host, ProjectLanguageServiceStateEvent); session.executeCommand({ seq: 0, type: "request", command: "open", arguments: { file: f1.path } - } as ts.projectSystem.protocol.OpenRequest); + } as OpenRequest); const projectService = session.getProjectService(); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); - const project = ts.projectSystem.configuredProjectAt(projectService, 0); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + const project = configuredProjectAt(projectService, 0); assert.isFalse(project.languageServiceEnabled, "Language service enabled"); assert.equal(events.length, 1, "should receive event"); assert.equal(events[0].data.project, project, "project name"); assert.isFalse(events[0].data.languageServiceEnabled, "Language service state"); - const options = projectService.getFormatCodeOptions(f1.path as ts.server.NormalizedPath); + const options = projectService.getFormatCodeOptions(f1.path as NormalizedPath); const edits = project.getLanguageService().getFormattingEditsForDocument(f1.path, options); - assert.deepEqual(edits, [{ span: ts.createTextSpan(/*start*/ 7, /*length*/ 3), newText: " " }]); + assert.deepEqual(edits, [{ span: createTextSpan(/*start*/ 7, /*length*/ 3), newText: " " }]); }); it("when multiple projects are open, detects correct default project", () => { - const barConfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/bar/tsconfig.json`, + const barConfig: File = { + path: `${projectRoot}/bar/tsconfig.json`, content: JSON.stringify({ include: ["index.ts"], compilerOptions: { @@ -841,15 +860,15 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => { } }) }; - const barIndex: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/bar/index.ts`, + const barIndex: File = { + path: `${projectRoot}/bar/index.ts`, content: ` export function bar() { console.log("hello world"); }` }; - const fooConfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/foo/tsconfig.json`, + const fooConfig: File = { + path: `${projectRoot}/foo/tsconfig.json`, content: JSON.stringify({ include: ["index.ts"], compilerOptions: { @@ -857,75 +876,75 @@ export function bar() { } }) }; - const fooIndex: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/foo/index.ts`, + const fooIndex: File = { + path: `${projectRoot}/foo/index.ts`, content: ` import { bar } from "bar"; bar();` }; - const barSymLink: ts.projectSystem.SymLink = { - path: `${ts.tscWatch.projectRoot}/foo/node_modules/bar`, - symLink: `${ts.tscWatch.projectRoot}/bar` + const barSymLink: SymLink = { + path: `${projectRoot}/foo/node_modules/bar`, + symLink: `${projectRoot}/bar` }; - const lib2017: ts.projectSystem.File = { - path: `${ts.getDirectoryPath(ts.projectSystem.libFile.path)}/lib.es2017.d.ts`, - content: ts.projectSystem.libFile.content + const lib2017: File = { + path: `${getDirectoryPath(libFile.path)}/lib.es2017.d.ts`, + content: libFile.content }; - const libDom: ts.projectSystem.File = { - path: `${ts.getDirectoryPath(ts.projectSystem.libFile.path)}/lib.dom.d.ts`, + const libDom: File = { + path: `${getDirectoryPath(libFile.path)}/lib.dom.d.ts`, content: ` declare var console: { log(...args: any[]): void; };` }; - const host = ts.projectSystem.createServerHost([barConfig, barIndex, fooConfig, fooIndex, barSymLink, lib2017, libDom]); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([fooIndex, barIndex], session); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [barIndex, fooIndex] }); - ts.projectSystem.baselineTsserverLogs("configuredProjects", "when multiple projects are open detects correct default project", session); + const host = createServerHost([barConfig, barIndex, fooConfig, fooIndex, barSymLink, lib2017, libDom]); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([fooIndex, barIndex], session); + verifyGetErrRequest({ session, host, files: [barIndex, fooIndex] }); + baselineTsserverLogs("configuredProjects", "when multiple projects are open detects correct default project", session); }); it("when file name starts with ^", () => { - const file: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/file.ts`, + const file: File = { + path: `${projectRoot}/file.ts`, content: "const x = 10;" }; - const app: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/^app.ts`, + const app: File = { + path: `${projectRoot}/^app.ts`, content: "const y = 10;" }; - const tsconfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, content: "{}" }; - const host = ts.projectSystem.createServerHost([file, app, tsconfig, ts.projectSystem.libFile]); - const service = ts.projectSystem.createProjectService(host); + const host = createServerHost([file, app, tsconfig, libFile]); + const service = createProjectService(host); service.openClientFile(file.path); }); describe("when creating new file", () => { - const foo: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/src/foo.ts`, + const foo: File = { + path: `${projectRoot}/src/foo.ts`, content: "export function foo() { }" }; - const bar: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/src/bar.ts`, + const bar: File = { + path: `${projectRoot}/src/bar.ts`, content: "export function bar() { }" }; - const config: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ include: ["./src"] }) }; - const fooBar: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/src/sub/fooBar.ts`, + const fooBar: File = { + path: `${projectRoot}/src/sub/fooBar.ts`, content: "export function fooBar() { }" }; function verifySessionWorker({ withExclude, openFileBeforeCreating }: VerifySession, errorOnNewFileBeforeOldFile: boolean) { - const host = ts.projectSystem.createServerHost([ - foo, bar, ts.projectSystem.libFile, { path: `${ts.tscWatch.projectRoot}/src/sub` }, + const host = createServerHost([ + foo, bar, libFile, { path: `${projectRoot}/src/sub` }, withExclude ? { path: config.path, @@ -936,33 +955,33 @@ declare var console: { } : config ]); - const session = ts.projectSystem.createSession(host, { + const session = createSession(host, { canUseEvents: true, - logger: ts.projectSystem.createLoggerWithInMemoryLogs(), + logger: createLoggerWithInMemoryLogs(), }); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Open, + session.executeCommandSeq({ + command: CommandTypes.Open, arguments: { file: foo.path, fileContent: foo.content, - projectRootPath: ts.tscWatch.projectRoot + projectRootPath: projectRoot } }); if (!openFileBeforeCreating) { host.writeFile(fooBar.path, fooBar.content); } - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Open, + session.executeCommandSeq({ + command: CommandTypes.Open, arguments: { file: fooBar.path, fileContent: fooBar.content, - projectRootPath: ts.tscWatch.projectRoot + projectRootPath: projectRoot } }); if (openFileBeforeCreating) { host.writeFile(fooBar.path, fooBar.content); } - ts.projectSystem.verifyGetErrRequest({ + verifyGetErrRequest({ session, host, files: errorOnNewFileBeforeOldFile ? @@ -970,7 +989,7 @@ declare var console: { [foo, fooBar], existingTimeouts: withExclude ? 0 : 2 }); - ts.projectSystem.baselineTsserverLogs("configuredProjects", `creating new file and then open it ${openFileBeforeCreating ? "before" : "after"} watcher is invoked, ask errors on it ${errorOnNewFileBeforeOldFile ? "before" : "after"} old one${withExclude ? " without file being in config" : ""}`, session); + baselineTsserverLogs("configuredProjects", `creating new file and then open it ${openFileBeforeCreating ? "before" : "after"} watcher is invoked, ask errors on it ${errorOnNewFileBeforeOldFile ? "before" : "after"} old one${withExclude ? " without file being in config" : ""}`, session); } interface VerifySession { withExclude?: boolean; @@ -1011,25 +1030,25 @@ declare var console: { }); it("when default configured project does not contain the file", () => { - const barConfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/bar/tsconfig.json`, + const barConfig: File = { + path: `${projectRoot}/bar/tsconfig.json`, content: "{}" }; - const barIndex: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/bar/index.ts`, + const barIndex: File = { + path: `${projectRoot}/bar/index.ts`, content: `import {foo} from "../foo/lib"; foo();` }; - const fooBarConfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/foobar/tsconfig.json`, + const fooBarConfig: File = { + path: `${projectRoot}/foobar/tsconfig.json`, content: barConfig.path }; - const fooBarIndex: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/foobar/index.ts`, + const fooBarIndex: File = { + path: `${projectRoot}/foobar/index.ts`, content: barIndex.content }; - const fooConfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/foo/tsconfig.json`, + const fooConfig: File = { + path: `${projectRoot}/foo/tsconfig.json`, content: JSON.stringify({ include: ["index.ts"], compilerOptions: { @@ -1038,25 +1057,25 @@ foo();` } }) }; - const fooIndex: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/foo/index.ts`, + const fooIndex: File = { + path: `${projectRoot}/foo/index.ts`, content: `export function foo() {}` }; - const host = ts.projectSystem.createServerHost([barConfig, barIndex, fooBarConfig, fooBarIndex, fooConfig, fooIndex, ts.projectSystem.libFile]); - ts.tscWatch.ensureErrorFreeBuild(host, [fooConfig.path]); - const fooDts = `${ts.tscWatch.projectRoot}/foo/lib/index.d.ts`; + const host = createServerHost([barConfig, barIndex, fooBarConfig, fooBarIndex, fooConfig, fooIndex, libFile]); + ensureErrorFreeBuild(host, [fooConfig.path]); + const fooDts = `${projectRoot}/foo/lib/index.d.ts`; assert.isTrue(host.fileExists(fooDts)); - const session = ts.projectSystem.createSession(host); + const session = createSession(host); const service = session.getProjectService(); service.openClientFile(barIndex.path); - ts.projectSystem.checkProjectActualFiles(service.configuredProjects.get(barConfig.path)!, [barIndex.path, fooDts, ts.projectSystem.libFile.path, barConfig.path]); + checkProjectActualFiles(service.configuredProjects.get(barConfig.path)!, [barIndex.path, fooDts, libFile.path, barConfig.path]); service.openClientFile(fooBarIndex.path); - ts.projectSystem.checkProjectActualFiles(service.configuredProjects.get(fooBarConfig.path)!, [fooBarIndex.path, fooDts, ts.projectSystem.libFile.path, fooBarConfig.path]); + checkProjectActualFiles(service.configuredProjects.get(fooBarConfig.path)!, [fooBarIndex.path, fooDts, libFile.path, fooBarConfig.path]); service.openClientFile(fooIndex.path); - ts.projectSystem.checkProjectActualFiles(service.configuredProjects.get(fooConfig.path)!, [fooIndex.path, ts.projectSystem.libFile.path, fooConfig.path]); + checkProjectActualFiles(service.configuredProjects.get(fooConfig.path)!, [fooIndex.path, libFile.path, fooConfig.path]); service.openClientFile(fooDts); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.GetApplicableRefactors, + session.executeCommandSeq({ + command: CommandTypes.GetApplicableRefactors, arguments: { file: fooDts, startLine: 1, @@ -1065,46 +1084,46 @@ foo();` endOffset: 1 } }); - assert.equal(service.tryGetDefaultProjectForFile(ts.server.toNormalizedPath(fooDts)), service.configuredProjects.get(barConfig.path)); + assert.equal(service.tryGetDefaultProjectForFile(toNormalizedPath(fooDts)), service.configuredProjects.get(barConfig.path)); }); describe("watches extended config files", () => { - function getService(additionalFiles?: ts.projectSystem.File[]) { - const alphaExtendedConfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/extended/alpha.tsconfig.json`, + function getService(additionalFiles?: File[]) { + const alphaExtendedConfig: File = { + path: `${projectRoot}/extended/alpha.tsconfig.json`, content: "{}" }; - const bravoExtendedConfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/extended/bravo.tsconfig.json`, + const bravoExtendedConfig: File = { + path: `${projectRoot}/extended/bravo.tsconfig.json`, content: JSON.stringify({ extends: "./alpha.tsconfig.json" }) }; - const aConfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/a/tsconfig.json`, + const aConfig: File = { + path: `${projectRoot}/a/tsconfig.json`, content: JSON.stringify({ extends: "../extended/alpha.tsconfig.json", files: ["a.ts"] }) }; - const aFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/a/a.ts`, + const aFile: File = { + path: `${projectRoot}/a/a.ts`, content: `let a = 1;` }; - const bConfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/b/tsconfig.json`, + const bConfig: File = { + path: `${projectRoot}/b/tsconfig.json`, content: JSON.stringify({ extends: "../extended/bravo.tsconfig.json", files: ["b.ts"] }) }; - const bFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/b/b.ts`, + const bFile: File = { + path: `${projectRoot}/b/b.ts`, content: `let b = 1;` }; - const host = ts.projectSystem.createServerHost([alphaExtendedConfig, aConfig, aFile, bravoExtendedConfig, bConfig, bFile, ...(additionalFiles || ts.emptyArray)]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([alphaExtendedConfig, aConfig, aFile, bravoExtendedConfig, bConfig, bFile, ...(additionalFiles || emptyArray)]); + const projectService = createProjectService(host); return { host, projectService, aFile, bFile, aConfig, bConfig, alphaExtendedConfig, bravoExtendedConfig }; } @@ -1113,14 +1132,14 @@ foo();` projectService.openClientFile(aFile.path); projectService.openClientFile(bFile.path); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 2); + checkNumberOfConfiguredProjects(projectService, 2); const aProject = projectService.configuredProjects.get(aConfig.path)!; const bProject = projectService.configuredProjects.get(bConfig.path)!; - ts.projectSystem.checkProjectActualFiles(aProject, [aFile.path, aConfig.path, alphaExtendedConfig.path]); - ts.projectSystem.checkProjectActualFiles(bProject, [bFile.path, bConfig.path, bravoExtendedConfig.path, alphaExtendedConfig.path]); + checkProjectActualFiles(aProject, [aFile.path, aConfig.path, alphaExtendedConfig.path]); + checkProjectActualFiles(bProject, [bFile.path, bConfig.path, bravoExtendedConfig.path, alphaExtendedConfig.path]); assert.isUndefined(aProject.getCompilerOptions().strict); assert.isUndefined(bProject.getCompilerOptions().strict); - ts.projectSystem.checkWatchedFiles(host, [aConfig.path, bConfig.path, ts.projectSystem.libFile.path, bravoExtendedConfig.path, alphaExtendedConfig.path]); + checkWatchedFiles(host, [aConfig.path, bConfig.path, libFile.path, bravoExtendedConfig.path, alphaExtendedConfig.path]); host.writeFile(alphaExtendedConfig.path, JSON.stringify({ compilerOptions: { @@ -1132,7 +1151,7 @@ foo();` host.checkTimeoutQueueLengthAndRun(3); assert.isTrue(aProject.getCompilerOptions().strict); assert.isTrue(bProject.getCompilerOptions().strict); - ts.projectSystem.checkWatchedFiles(host, [aConfig.path, bConfig.path, ts.projectSystem.libFile.path, bravoExtendedConfig.path, alphaExtendedConfig.path]); + checkWatchedFiles(host, [aConfig.path, bConfig.path, libFile.path, bravoExtendedConfig.path, alphaExtendedConfig.path]); host.writeFile(bravoExtendedConfig.path, JSON.stringify({ extends: "./alpha.tsconfig.json", @@ -1145,7 +1164,7 @@ foo();` host.checkTimeoutQueueLengthAndRun(2); assert.isTrue(aProject.getCompilerOptions().strict); assert.isFalse(bProject.getCompilerOptions().strict); - ts.projectSystem.checkWatchedFiles(host, [aConfig.path, bConfig.path, ts.projectSystem.libFile.path, bravoExtendedConfig.path, alphaExtendedConfig.path]); + checkWatchedFiles(host, [aConfig.path, bConfig.path, libFile.path, bravoExtendedConfig.path, alphaExtendedConfig.path]); host.writeFile(bConfig.path, JSON.stringify({ extends: "../extended/alpha.tsconfig.json", @@ -1155,7 +1174,7 @@ foo();` host.checkTimeoutQueueLengthAndRun(2); assert.isTrue(aProject.getCompilerOptions().strict); assert.isTrue(bProject.getCompilerOptions().strict); - ts.projectSystem.checkWatchedFiles(host, [aConfig.path, bConfig.path, ts.projectSystem.libFile.path, alphaExtendedConfig.path]); + checkWatchedFiles(host, [aConfig.path, bConfig.path, libFile.path, alphaExtendedConfig.path]); host.writeFile(alphaExtendedConfig.path, "{}"); assert.isTrue(projectService.hasPendingProjectUpdate(aProject)); @@ -1163,16 +1182,16 @@ foo();` host.checkTimeoutQueueLengthAndRun(3); assert.isUndefined(aProject.getCompilerOptions().strict); assert.isUndefined(bProject.getCompilerOptions().strict); - ts.projectSystem.checkWatchedFiles(host, [aConfig.path, bConfig.path, ts.projectSystem.libFile.path, alphaExtendedConfig.path]); + checkWatchedFiles(host, [aConfig.path, bConfig.path, libFile.path, alphaExtendedConfig.path]); }); it("should stop watching the extended configs of closed projects", () => { - const dummy: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/dummy/dummy.ts`, + const dummy: File = { + path: `${projectRoot}/dummy/dummy.ts`, content: `let dummy = 1;` }; - const dummyConfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/dummy/tsconfig.json`, + const dummyConfig: File = { + path: `${projectRoot}/dummy/tsconfig.json`, content: "{}" }; const { host, projectService, aFile, bFile, aConfig, bConfig, alphaExtendedConfig, bravoExtendedConfig } = getService([dummy, dummyConfig]); @@ -1180,22 +1199,22 @@ foo();` projectService.openClientFile(aFile.path); projectService.openClientFile(bFile.path); projectService.openClientFile(dummy.path); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 3); - ts.projectSystem.checkWatchedFiles(host, [aConfig.path, bConfig.path, ts.projectSystem.libFile.path, bravoExtendedConfig.path, alphaExtendedConfig.path, dummyConfig.path]); + checkNumberOfConfiguredProjects(projectService, 3); + checkWatchedFiles(host, [aConfig.path, bConfig.path, libFile.path, bravoExtendedConfig.path, alphaExtendedConfig.path, dummyConfig.path]); projectService.closeClientFile(bFile.path); projectService.closeClientFile(dummy.path); projectService.openClientFile(dummy.path); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 2); - ts.projectSystem.checkWatchedFiles(host, [aConfig.path, ts.projectSystem.libFile.path, alphaExtendedConfig.path, dummyConfig.path]); + checkNumberOfConfiguredProjects(projectService, 2); + checkWatchedFiles(host, [aConfig.path, libFile.path, alphaExtendedConfig.path, dummyConfig.path]); projectService.closeClientFile(aFile.path); projectService.closeClientFile(dummy.path); projectService.openClientFile(dummy.path); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); - ts.projectSystem.checkWatchedFiles(host, [ts.projectSystem.libFile.path, dummyConfig.path]); + checkNumberOfConfiguredProjects(projectService, 1); + checkWatchedFiles(host, [libFile.path, dummyConfig.path]); }); }); }); @@ -1214,16 +1233,16 @@ describe("unittests:: tsserver:: ConfiguredProjects:: non-existing directories l content: "let t = 10;" }; - const host = ts.projectSystem.createServerHost([file1, configFile]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, configFile]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); host.runQueuedTimeoutCallbacks(); // Since file1 refers to config file as the default project, it needs to be kept alive - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1, configuredProjects: 1 }); + checkNumberOfProjects(projectService, { inferredProjects: 1, configuredProjects: 1 }); const inferredProject = projectService.inferredProjects[0]; - assert.isTrue(inferredProject.containsFile(file1.path as ts.server.NormalizedPath)); - assert.isFalse(projectService.configuredProjects.get(configFile.path)!.containsFile(file1.path as ts.server.NormalizedPath)); + assert.isTrue(inferredProject.containsFile(file1.path as NormalizedPath)); + assert.isFalse(projectService.configuredProjects.get(configFile.path)!.containsFile(file1.path as NormalizedPath)); }); it("should be able to handle @types if input file list is empty", () => { @@ -1246,8 +1265,8 @@ describe("unittests:: tsserver:: ConfiguredProjects:: non-existing directories l path: "/a/node_modules/@types/typings/lib.d.ts", content: `export const x: number` }; - const host = ts.projectSystem.createServerHost([f, config, t1, t2], { currentDirectory: ts.getDirectoryPath(f.path) }); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([f, config, t1, t2], { currentDirectory: getDirectoryPath(f.path) }); + const projectService = createProjectService(host); projectService.openClientFile(f.path); // Since f refers to config file as the default project, it needs to be kept alive @@ -1256,11 +1275,11 @@ describe("unittests:: tsserver:: ConfiguredProjects:: non-existing directories l it("should tolerate invalid include files that start in subDirectory", () => { const f = { - path: `${ts.tscWatch.projectRoot}/src/server/index.ts`, + path: `${projectRoot}/src/server/index.ts`, content: "let x = 1" }; const config = { - path: `${ts.tscWatch.projectRoot}/src/server/tsconfig.json`, + path: `${projectRoot}/src/server/tsconfig.json`, content: JSON.stringify({ compiler: { module: "commonjs", @@ -1271,8 +1290,8 @@ describe("unittests:: tsserver:: ConfiguredProjects:: non-existing directories l ] }) }; - const host = ts.projectSystem.createServerHost([f, config, ts.projectSystem.libFile], { useCaseSensitiveFileNames: true }); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([f, config, libFile], { useCaseSensitiveFileNames: true }); + const projectService = createProjectService(host); projectService.openClientFile(f.path); // Since f refers to config file as the default project, it needs to be kept alive @@ -1280,124 +1299,124 @@ describe("unittests:: tsserver:: ConfiguredProjects:: non-existing directories l }); it("Changed module resolution reflected when specifying files list", () => { - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/b/file1.ts", content: 'import classc from "file2"' }; - const file2a: ts.projectSystem.File = { + const file2a: File = { path: "/a/file2.ts", content: "export classc { method2a() { return 10; } }" }; - const file2: ts.projectSystem.File = { + const file2: File = { path: "/a/b/file2.ts", content: "export classc { method2() { return 10; } }" }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: JSON.stringify({ files: [file1.path], compilerOptions: { module: "amd" } }) }; - const files = [file1, file2a, configFile, ts.projectSystem.libFile]; - const host = ts.projectSystem.createServerHost(files); - const projectService = ts.projectSystem.createProjectService(host); + const files = [file1, file2a, configFile, libFile]; + const host = createServerHost(files); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); const project = projectService.configuredProjects.get(configFile.path)!; assert.isDefined(project); - ts.projectSystem.checkProjectActualFiles(project, ts.map(files, file => file.path)); - ts.projectSystem.checkWatchedFiles(host, ts.mapDefined(files, file => file === file1 ? undefined : file.path)); - ts.projectSystem.checkWatchedDirectoriesDetailed(host, ["/a/b"], 1, /*recursive*/ false); - ts.projectSystem.checkWatchedDirectoriesDetailed(host, ["/a/b/node_modules/@types"], 1, /*recursive*/ true); + checkProjectActualFiles(project, map(files, file => file.path)); + checkWatchedFiles(host, mapDefined(files, file => file === file1 ? undefined : file.path)); + checkWatchedDirectoriesDetailed(host, ["/a/b"], 1, /*recursive*/ false); + checkWatchedDirectoriesDetailed(host, ["/a/b/node_modules/@types"], 1, /*recursive*/ true); files.push(file2); host.writeFile(file2.path, file2.content); host.runQueuedTimeoutCallbacks(); // Scheduled invalidation of resolutions host.runQueuedTimeoutCallbacks(); // Actual update - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); assert.strictEqual(projectService.configuredProjects.get(configFile.path), project); - ts.projectSystem.checkProjectActualFiles(project, ts.mapDefined(files, file => file === file2a ? undefined : file.path)); - ts.projectSystem.checkWatchedFiles(host, ts.mapDefined(files, file => file === file1 ? undefined : file.path)); - ts.projectSystem.checkWatchedDirectories(host, ts.emptyArray, /*recursive*/ false); - ts.projectSystem.checkWatchedDirectoriesDetailed(host, ["/a/b/node_modules/@types"], 1, /*recursive*/ true); + checkProjectActualFiles(project, mapDefined(files, file => file === file2a ? undefined : file.path)); + checkWatchedFiles(host, mapDefined(files, file => file === file1 ? undefined : file.path)); + checkWatchedDirectories(host, emptyArray, /*recursive*/ false); + checkWatchedDirectoriesDetailed(host, ["/a/b/node_modules/@types"], 1, /*recursive*/ true); // On next file open the files file2a should be closed and not watched any more projectService.openClientFile(file2.path); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); assert.strictEqual(projectService.configuredProjects.get(configFile.path), project); - ts.projectSystem.checkProjectActualFiles(project, ts.mapDefined(files, file => file === file2a ? undefined : file.path)); - ts.projectSystem.checkWatchedFiles(host, [ts.projectSystem.libFile.path, configFile.path]); - ts.projectSystem.checkWatchedDirectories(host, ts.emptyArray, /*recursive*/ false); - ts.projectSystem.checkWatchedDirectoriesDetailed(host, ["/a/b/node_modules/@types"], 1, /*recursive*/ true); + checkProjectActualFiles(project, mapDefined(files, file => file === file2a ? undefined : file.path)); + checkWatchedFiles(host, [libFile.path, configFile.path]); + checkWatchedDirectories(host, emptyArray, /*recursive*/ false); + checkWatchedDirectoriesDetailed(host, ["/a/b/node_modules/@types"], 1, /*recursive*/ true); }); it("Failed lookup locations uses parent most node_modules directory", () => { const root = "/user/username/rootfolder"; - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/b/src/file1.ts", content: 'import { classc } from "module1"' }; - const module1: ts.projectSystem.File = { + const module1: File = { path: "/a/b/node_modules/module1/index.d.ts", content: `import { class2 } from "module2"; export classc { method2a(): class2; }` }; - const module2: ts.projectSystem.File = { + const module2: File = { path: "/a/b/node_modules/module2/index.d.ts", content: "export class2 { method2() { return 10; } }" }; - const module3: ts.projectSystem.File = { + const module3: File = { path: "/a/b/node_modules/module/node_modules/module3/index.d.ts", content: "export class3 { method2() { return 10; } }" }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/src/tsconfig.json", content: JSON.stringify({ files: ["file1.ts"] }) }; const nonLibFiles = [file1, module1, module2, module3, configFile]; nonLibFiles.forEach(f => f.path = root + f.path); - const files = nonLibFiles.concat(ts.projectSystem.libFile); - const host = ts.projectSystem.createServerHost(files); - const projectService = ts.projectSystem.createProjectService(host); + const files = nonLibFiles.concat(libFile); + const host = createServerHost(files); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); const project = projectService.configuredProjects.get(configFile.path)!; assert.isDefined(project); - ts.projectSystem.checkProjectActualFiles(project, [file1.path, ts.projectSystem.libFile.path, module1.path, module2.path, configFile.path]); - ts.projectSystem.checkWatchedFiles(host, [ts.projectSystem.libFile.path, configFile.path]); - ts.projectSystem.checkWatchedDirectories(host, [], /*recursive*/ false); - const watchedRecursiveDirectories = ts.projectSystem.getTypeRootsFromLocation(root + "/a/b/src"); + checkProjectActualFiles(project, [file1.path, libFile.path, module1.path, module2.path, configFile.path]); + checkWatchedFiles(host, [libFile.path, configFile.path]); + checkWatchedDirectories(host, [], /*recursive*/ false); + const watchedRecursiveDirectories = getTypeRootsFromLocation(root + "/a/b/src"); watchedRecursiveDirectories.push(`${root}/a/b/src/node_modules`, `${root}/a/b/node_modules`); - ts.projectSystem.checkWatchedDirectories(host, watchedRecursiveDirectories, /*recursive*/ true); + checkWatchedDirectories(host, watchedRecursiveDirectories, /*recursive*/ true); }); }); describe("unittests:: tsserver:: ConfiguredProjects:: when reading tsconfig file fails", () => { it("should be tolerated without crashing the server", () => { const configFile = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + path: `${projectRoot}/tsconfig.json`, content: "" }; const file1 = { - path: `${ts.tscWatch.projectRoot}/file1.ts`, + path: `${projectRoot}/file1.ts`, content: "let t = 10;" }; - const host = ts.projectSystem.createServerHost([file1, ts.projectSystem.libFile, configFile]); - const { session, events } = ts.projectSystem.createSessionWithEventTracking(host, ts.server.ConfigFileDiagEvent); + const host = createServerHost([file1, libFile, configFile]); + const { session, events } = createSessionWithEventTracking(host, ConfigFileDiagEvent); const originalReadFile = host.readFile; host.readFile = f => { return f === configFile.path ? undefined : originalReadFile.call(host, f); }; - ts.projectSystem.openFilesForSession([file1], session); + openFilesForSession([file1], session); assert.deepEqual(events, [{ - eventName: ts.server.ConfigFileDiagEvent, + eventName: ConfigFileDiagEvent, data: { triggerFile: file1.path, configFileName: configFile.path, diagnostics: [ - ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_read_file_0, configFile.path) + createCompilerDiagnostic(Diagnostics.Cannot_read_file_0, configFile.path) ] } }]); diff --git a/src/testRunner/unittests/tsserver/declarationFileMaps.ts b/src/testRunner/unittests/tsserver/declarationFileMaps.ts index 576a6607ba0ff..5e1296487929f 100644 --- a/src/testRunner/unittests/tsserver/declarationFileMaps.ts +++ b/src/testRunner/unittests/tsserver/declarationFileMaps.ts @@ -1,23 +1,47 @@ -import * as ts from "../../_namespaces/ts"; - -function documentSpanFromSubstring({ file, text, contextText, options, contextOptions }: ts.projectSystem.DocumentSpanFromSubstring): ts.DocumentSpan { +import { getFileEmitOutput } from "../../../compiler/builderState"; +import { OutputFile } from "../../../compiler/builderStatePublic"; +import { Debug } from "../../../compiler/debug"; +import { CompilerOptions, RawSourceMap, SyntaxKind } from "../../../compiler/types"; +import { + CommandTypes, DefinitionAndBoundSpanRequest, DefinitionAndBoundSpanResponse, DefinitionRequest, DefinitionResponse, + FileCodeEdits, FileLocationRequest, GetEditsForFileRenameRequest, GetEditsForFileRenameResponse, + ImplementationRequest, ImplementationResponse, NavtoItem, NavtoRequest, NavtoResponse, ReferencesRequest, + ReferencesResponse, ReferencesResponseBody, ReferencesResponseItem, RenameFullRequest, RenameFullResponse, + RenameRequest, RenameResponse, RenameResponseBody, Response, SpanGroup, TypeDefinitionRequest, + TypeDefinitionResponse, +} from "../../../server/protocol"; +import { NormalizedPath } from "../../../server/utilitiesPublic"; +import { + DocumentSpan, ReferencedSymbol, ReferencedSymbolEntry, RenameLocation, ScriptElementKind, ScriptElementKindModifier, + SymbolDisplayPartKind, +} from "../../../services/types"; +import { displayPart, keywordPart, punctuationPart, spacePart } from "../../../services/utilities"; +import { + checkNumberOfProjects, checkProjectActualFiles, closeFilesForSession, CommandNames, createServerHost, createSession, + DocumentSpanFromSubstring, executeSessionRequest, File, makeReferenceItem, openFilesForSession, + protocolFileLocationFromSubstring, protocolFileSpanFromSubstring, protocolFileSpanWithContextFromSubstring, + protocolLocationFromSubstring, protocolRenameSpanFromSubstring, protocolTextSpanFromSubstring, TestSession, + textSpanFromSubstring, +} from "./helpers"; + +function documentSpanFromSubstring({ file, text, contextText, options, contextOptions }: DocumentSpanFromSubstring): DocumentSpan { const contextSpan = contextText !== undefined ? documentSpanFromSubstring({ file, text: contextText, options: contextOptions }) : undefined; return { fileName: file.path, - textSpan: ts.projectSystem.textSpanFromSubstring(file.content, text, options), + textSpan: textSpanFromSubstring(file.content, text, options), ...contextSpan && { contextSpan: contextSpan.textSpan } }; } -function renameLocation(input: ts.projectSystem.DocumentSpanFromSubstring): ts.RenameLocation { +function renameLocation(input: DocumentSpanFromSubstring): RenameLocation { return documentSpanFromSubstring(input); } -interface MakeReferenceEntry extends ts.projectSystem.DocumentSpanFromSubstring { +interface MakeReferenceEntry extends DocumentSpanFromSubstring { isDefinition?: boolean; isWriteAccess?: boolean; } -function makeReferencedSymbolEntry({ isDefinition, isWriteAccess, ...rest }: MakeReferenceEntry): ts.ReferencedSymbolEntry { +function makeReferencedSymbolEntry({ isDefinition, isWriteAccess, ...rest }: MakeReferenceEntry): ReferencedSymbolEntry { const result = { ...documentSpanFromSubstring(rest), isDefinition, @@ -30,32 +54,32 @@ function makeReferencedSymbolEntry({ isDefinition, isWriteAccess, ...rest }: Mak return result; } -function checkDeclarationFiles(file: ts.projectSystem.File, session: ts.projectSystem.TestSession, expectedFiles: readonly ts.projectSystem.File[]): void { - ts.projectSystem.openFilesForSession([file], session); - const project = ts.Debug.checkDefined(session.getProjectService().getDefaultProjectForFile(file.path as ts.server.NormalizedPath, /*ensureProject*/ false)); +function checkDeclarationFiles(file: File, session: TestSession, expectedFiles: readonly File[]): void { + openFilesForSession([file], session); + const project = Debug.checkDefined(session.getProjectService().getDefaultProjectForFile(file.path as NormalizedPath, /*ensureProject*/ false)); const program = project.getCurrentProgram()!; - const output = ts.getFileEmitOutput(program, ts.Debug.checkDefined(program.getSourceFile(file.path)), /*emitOnlyDtsFiles*/ true); - ts.projectSystem.closeFilesForSession([file], session); + const output = getFileEmitOutput(program, Debug.checkDefined(program.getSourceFile(file.path)), /*emitOnlyDtsFiles*/ true); + closeFilesForSession([file], session); - ts.Debug.assert(!output.emitSkipped); - assert.deepEqual(output.outputFiles, expectedFiles.map((e): ts.OutputFile => ({ name: e.path, text: e.content, writeByteOrderMark: false }))); + Debug.assert(!output.emitSkipped); + assert.deepEqual(output.outputFiles, expectedFiles.map((e): OutputFile => ({ name: e.path, text: e.content, writeByteOrderMark: false }))); } describe("unittests:: tsserver:: with declaration file maps:: project references", () => { - const aTs: ts.projectSystem.File = { + const aTs: File = { path: "/a/a.ts", content: "export function fnA() {}\nexport interface IfaceA {}\nexport const instanceA: IfaceA = {};", }; - const compilerOptions: ts.CompilerOptions = { + const compilerOptions: CompilerOptions = { outDir: "bin", declaration: true, declarationMap: true, composite: true, }; const configContent = JSON.stringify({ compilerOptions }); - const aTsconfig: ts.projectSystem.File = { path: "/a/tsconfig.json", content: configContent }; + const aTsconfig: File = { path: "/a/tsconfig.json", content: configContent }; - const aDtsMapContent: ts.RawSourceMap = { + const aDtsMapContent: RawSourceMap = { version: 3, file: "a.d.ts", sourceRoot: "", @@ -63,23 +87,23 @@ describe("unittests:: tsserver:: with declaration file maps:: project references names: [], mappings: "AAAA,wBAAgB,GAAG,SAAK;AACxB,MAAM,WAAW,MAAM;CAAG;AAC1B,eAAO,MAAM,SAAS,EAAE,MAAW,CAAC" }; - const aDtsMap: ts.projectSystem.File = { + const aDtsMap: File = { path: "/a/bin/a.d.ts.map", content: JSON.stringify(aDtsMapContent), }; - const aDts: ts.projectSystem.File = { + const aDts: File = { path: "/a/bin/a.d.ts", // ${""} is needed to mangle the sourceMappingURL part or it breaks the build content: `export declare function fnA(): void;\nexport interface IfaceA {\n}\nexport declare const instanceA: IfaceA;\n//# source${""}MappingURL=a.d.ts.map`, }; - const bTs: ts.projectSystem.File = { + const bTs: File = { path: "/b/b.ts", content: "export function fnB() {}", }; - const bTsconfig: ts.projectSystem.File = { path: "/b/tsconfig.json", content: configContent }; + const bTsconfig: File = { path: "/b/tsconfig.json", content: configContent }; - const bDtsMapContent: ts.RawSourceMap = { + const bDtsMapContent: RawSourceMap = { version: 3, file: "b.d.ts", sourceRoot: "", @@ -87,32 +111,32 @@ describe("unittests:: tsserver:: with declaration file maps:: project references names: [], mappings: "AAAA,wBAAgB,GAAG,SAAK", }; - const bDtsMap: ts.projectSystem.File = { + const bDtsMap: File = { path: "/b/bin/b.d.ts.map", content: JSON.stringify(bDtsMapContent), }; - const bDts: ts.projectSystem.File = { + const bDts: File = { // ${""} is need to mangle the sourceMappingURL part so it doesn't break the build path: "/b/bin/b.d.ts", content: `export declare function fnB(): void;\n//# source${""}MappingURL=b.d.ts.map`, }; - const dummyFile: ts.projectSystem.File = { + const dummyFile: File = { path: "/dummy/dummy.ts", content: "let a = 10;" }; - const userTs: ts.projectSystem.File = { + const userTs: File = { path: "/user/user.ts", content: 'import * as a from "../a/bin/a";\nimport * as b from "../b/bin/b";\nexport function fnUser() { a.fnA(); b.fnB(); a.instanceA; }', }; - const userTsForConfigProject: ts.projectSystem.File = { + const userTsForConfigProject: File = { path: "/user/user.ts", content: 'import * as a from "../a/a";\nimport * as b from "../b/b";\nexport function fnUser() { a.fnA(); b.fnB(); a.instanceA; }', }; - const userTsconfig: ts.projectSystem.File = { + const userTsconfig: File = { path: "/user/tsconfig.json", content: JSON.stringify({ file: ["user.ts"], @@ -121,8 +145,8 @@ describe("unittests:: tsserver:: with declaration file maps:: project references }; function makeSampleProjects(addUserTsConfig?: boolean, keepAllFiles?: boolean) { - const host = ts.projectSystem.createServerHost([aTs, aTsconfig, aDtsMap, aDts, bTsconfig, bTs, bDtsMap, bDts, ...(addUserTsConfig ? [userTsForConfigProject, userTsconfig] : [userTs]), dummyFile]); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([aTs, aTsconfig, aDtsMap, aDts, bTsconfig, bTs, bDtsMap, bDts, ...(addUserTsConfig ? [userTsForConfigProject, userTsconfig] : [userTs]), dummyFile]); + const session = createSession(host); checkDeclarationFiles(aTs, session, [aDtsMap, aDts]); checkDeclarationFiles(bTs, session, [bDtsMap, bDts]); @@ -132,70 +156,70 @@ describe("unittests:: tsserver:: with declaration file maps:: project references host.deleteFile(bTs.path); } - ts.projectSystem.openFilesForSession([userTs], session); + openFilesForSession([userTs], session); const service = session.getProjectService(); // If config file then userConfig project and bConfig project since it is referenced - ts.projectSystem.checkNumberOfProjects(service, addUserTsConfig ? { configuredProjects: 2 } : { inferredProjects: 1 }); + checkNumberOfProjects(service, addUserTsConfig ? { configuredProjects: 2 } : { inferredProjects: 1 }); return session; } - function verifyInferredProjectUnchanged(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkProjectActualFiles(session.getProjectService().inferredProjects[0], [userTs.path, aDts.path, bDts.path]); + function verifyInferredProjectUnchanged(session: TestSession) { + checkProjectActualFiles(session.getProjectService().inferredProjects[0], [userTs.path, aDts.path, bDts.path]); } - function verifyDummyProject(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkProjectActualFiles(session.getProjectService().inferredProjects[0], [dummyFile.path]); + function verifyDummyProject(session: TestSession) { + checkProjectActualFiles(session.getProjectService().inferredProjects[0], [dummyFile.path]); } - function verifyOnlyOrphanInferredProject(session: ts.projectSystem.TestSession) { - ts.projectSystem.openFilesForSession([dummyFile], session); - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { inferredProjects: 1 }); + function verifyOnlyOrphanInferredProject(session: TestSession) { + openFilesForSession([dummyFile], session); + checkNumberOfProjects(session.getProjectService(), { inferredProjects: 1 }); verifyDummyProject(session); } - function verifySingleInferredProject(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { inferredProjects: 1 }); + function verifySingleInferredProject(session: TestSession) { + checkNumberOfProjects(session.getProjectService(), { inferredProjects: 1 }); verifyInferredProjectUnchanged(session); // Close user file should close all the projects after opening dummy file - ts.projectSystem.closeFilesForSession([userTs], session); + closeFilesForSession([userTs], session); verifyOnlyOrphanInferredProject(session); } - function verifyATsConfigProject(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkProjectActualFiles(session.getProjectService().configuredProjects.get(aTsconfig.path)!, [aTs.path, aTsconfig.path]); + function verifyATsConfigProject(session: TestSession) { + checkProjectActualFiles(session.getProjectService().configuredProjects.get(aTsconfig.path)!, [aTs.path, aTsconfig.path]); } - function verifyATsConfigOriginalProject(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { inferredProjects: 1, configuredProjects: 1 }); + function verifyATsConfigOriginalProject(session: TestSession) { + checkNumberOfProjects(session.getProjectService(), { inferredProjects: 1, configuredProjects: 1 }); verifyInferredProjectUnchanged(session); verifyATsConfigProject(session); // Close user file should close all the projects - ts.projectSystem.closeFilesForSession([userTs], session); + closeFilesForSession([userTs], session); verifyOnlyOrphanInferredProject(session); } - function verifyATsConfigWhenOpened(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { inferredProjects: 1, configuredProjects: 1 }); + function verifyATsConfigWhenOpened(session: TestSession) { + checkNumberOfProjects(session.getProjectService(), { inferredProjects: 1, configuredProjects: 1 }); verifyInferredProjectUnchanged(session); verifyATsConfigProject(session); - ts.projectSystem.closeFilesForSession([userTs], session); - ts.projectSystem.openFilesForSession([dummyFile], session); - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { inferredProjects: 1, configuredProjects: 1 }); + closeFilesForSession([userTs], session); + openFilesForSession([dummyFile], session); + checkNumberOfProjects(session.getProjectService(), { inferredProjects: 1, configuredProjects: 1 }); verifyDummyProject(session); verifyATsConfigProject(session); // ATsConfig should still be alive } - function verifyUserTsConfigProject(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkProjectActualFiles(session.getProjectService().configuredProjects.get(userTsconfig.path)!, [userTs.path, aTs.path, userTsconfig.path]); + function verifyUserTsConfigProject(session: TestSession) { + checkProjectActualFiles(session.getProjectService().configuredProjects.get(userTsconfig.path)!, [userTs.path, aTs.path, userTsconfig.path]); } it("goToDefinition", () => { const session = makeSampleProjects(); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.Definition, ts.projectSystem.protocolFileLocationFromSubstring(userTs, "fnA()")); + const response = executeSessionRequest(session, CommandTypes.Definition, protocolFileLocationFromSubstring(userTs, "fnA()")); assert.deepEqual(response, [ - ts.projectSystem.protocolFileSpanWithContextFromSubstring({ + protocolFileSpanWithContextFromSubstring({ file: aTs, text: "fnA", contextText: "export function fnA() {}" @@ -206,11 +230,11 @@ describe("unittests:: tsserver:: with declaration file maps:: project references it("getDefinitionAndBoundSpan", () => { const session = makeSampleProjects(); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.DefinitionAndBoundSpan, ts.projectSystem.protocolFileLocationFromSubstring(userTs, "fnA()")); + const response = executeSessionRequest(session, CommandTypes.DefinitionAndBoundSpan, protocolFileLocationFromSubstring(userTs, "fnA()")); assert.deepEqual(response, { - textSpan: ts.projectSystem.protocolTextSpanFromSubstring(userTs.content, "fnA"), + textSpan: protocolTextSpanFromSubstring(userTs.content, "fnA"), definitions: [ - ts.projectSystem.protocolFileSpanWithContextFromSubstring({ + protocolFileSpanWithContextFromSubstring({ file: aTs, text: "fnA", contextText: "export function fnA() {}" @@ -222,38 +246,38 @@ describe("unittests:: tsserver:: with declaration file maps:: project references it("getDefinitionAndBoundSpan with file navigation", () => { const session = makeSampleProjects(/*addUserTsConfig*/ true); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.DefinitionAndBoundSpan, ts.projectSystem.protocolFileLocationFromSubstring(userTs, "fnA()")); + const response = executeSessionRequest(session, CommandTypes.DefinitionAndBoundSpan, protocolFileLocationFromSubstring(userTs, "fnA()")); assert.deepEqual(response, { - textSpan: ts.projectSystem.protocolTextSpanFromSubstring(userTs.content, "fnA"), + textSpan: protocolTextSpanFromSubstring(userTs.content, "fnA"), definitions: [ - ts.projectSystem.protocolFileSpanWithContextFromSubstring({ + protocolFileSpanWithContextFromSubstring({ file: aTs, text: "fnA", contextText: "export function fnA() {}" }) ], }); - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); verifyUserTsConfigProject(session); // Navigate to the definition - ts.projectSystem.closeFilesForSession([userTs], session); - ts.projectSystem.openFilesForSession([aTs], session); + closeFilesForSession([userTs], session); + openFilesForSession([aTs], session); // UserTs configured project should be alive - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { configuredProjects: 3 }); + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 3 }); verifyUserTsConfigProject(session); verifyATsConfigProject(session); - ts.projectSystem.closeFilesForSession([aTs], session); + closeFilesForSession([aTs], session); verifyOnlyOrphanInferredProject(session); }); it("goToType", () => { const session = makeSampleProjects(); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.TypeDefinition, ts.projectSystem.protocolFileLocationFromSubstring(userTs, "instanceA")); + const response = executeSessionRequest(session, CommandTypes.TypeDefinition, protocolFileLocationFromSubstring(userTs, "instanceA")); assert.deepEqual(response, [ - ts.projectSystem.protocolFileSpanWithContextFromSubstring({ + protocolFileSpanWithContextFromSubstring({ file: aTs, text: "IfaceA", contextText: "export interface IfaceA {}" @@ -264,9 +288,9 @@ describe("unittests:: tsserver:: with declaration file maps:: project references it("goToImplementation", () => { const session = makeSampleProjects(); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.Implementation, ts.projectSystem.protocolFileLocationFromSubstring(userTs, "fnA()")); + const response = executeSessionRequest(session, CommandTypes.Implementation, protocolFileLocationFromSubstring(userTs, "fnA()")); assert.deepEqual(response, [ - ts.projectSystem.protocolFileSpanWithContextFromSubstring({ + protocolFileSpanWithContextFromSubstring({ file: aTs, text: "fnA", contextText: "export function fnA() {}" @@ -276,10 +300,10 @@ describe("unittests:: tsserver:: with declaration file maps:: project references it("goToDefinition -- target does not exist", () => { const session = makeSampleProjects(); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.CommandNames.Definition, ts.projectSystem.protocolFileLocationFromSubstring(userTs, "fnB()")); + const response = executeSessionRequest(session, CommandNames.Definition, protocolFileLocationFromSubstring(userTs, "fnB()")); // bTs does not exist, so stick with bDts assert.deepEqual(response, [ - ts.projectSystem.protocolFileSpanWithContextFromSubstring({ + protocolFileSpanWithContextFromSubstring({ file: bDts, text: "fnB", contextText: "export declare function fnB(): void;" @@ -290,30 +314,30 @@ describe("unittests:: tsserver:: with declaration file maps:: project references it("navigateTo", () => { const session = makeSampleProjects(); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.CommandNames.Navto, { file: userTs.path, searchValue: "fn" }); - assert.deepEqual(response, [ + const response = executeSessionRequest(session, CommandNames.Navto, { file: userTs.path, searchValue: "fn" }); + assert.deepEqual(response, [ // Keep the .d.ts file since the .ts file no longer exists // (otherwise it would be treated as not in the project) { - ...ts.projectSystem.protocolFileSpanFromSubstring({ + ...protocolFileSpanFromSubstring({ file: bDts, text: "export declare function fnB(): void;" }), name: "fnB", matchKind: "prefix", isCaseSensitive: true, - kind: ts.ScriptElementKind.functionElement, + kind: ScriptElementKind.functionElement, kindModifiers: "export,declare", }, { - ...ts.projectSystem.protocolFileSpanFromSubstring({ + ...protocolFileSpanFromSubstring({ file: userTs, text: "export function fnUser() { a.fnA(); b.fnB(); a.instanceA; }" }), name: "fnUser", matchKind: "prefix", isCaseSensitive: true, - kind: ts.ScriptElementKind.functionElement, + kind: ScriptElementKind.functionElement, kindModifiers: "export", }, ]); @@ -323,39 +347,39 @@ describe("unittests:: tsserver:: with declaration file maps:: project references it("navigateToAll -- when neither file nor project is specified", () => { const session = makeSampleProjects(/*addUserTsConfig*/ true, /*keepAllFiles*/ true); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.CommandNames.Navto, { file: undefined, searchValue: "fn" }); - assert.deepEqual(response, [ + const response = executeSessionRequest(session, CommandNames.Navto, { file: undefined, searchValue: "fn" }); + assert.deepEqual(response, [ { - ...ts.projectSystem.protocolFileSpanFromSubstring({ + ...protocolFileSpanFromSubstring({ file: bTs, text: "export function fnB() {}" }), name: "fnB", matchKind: "prefix", isCaseSensitive: true, - kind: ts.ScriptElementKind.functionElement, + kind: ScriptElementKind.functionElement, kindModifiers: "export", }, { - ...ts.projectSystem.protocolFileSpanFromSubstring({ + ...protocolFileSpanFromSubstring({ file: aTs, text: "export function fnA() {}" }), name: "fnA", matchKind: "prefix", isCaseSensitive: true, - kind: ts.ScriptElementKind.functionElement, + kind: ScriptElementKind.functionElement, kindModifiers: "export", }, { - ...ts.projectSystem.protocolFileSpanFromSubstring({ + ...protocolFileSpanFromSubstring({ file: userTs, text: "export function fnUser() { a.fnA(); b.fnB(); a.instanceA; }" }), name: "fnUser", matchKind: "prefix", isCaseSensitive: true, - kind: ts.ScriptElementKind.functionElement, + kind: ScriptElementKind.functionElement, kindModifiers: "export", } ]); @@ -363,23 +387,23 @@ describe("unittests:: tsserver:: with declaration file maps:: project references it("navigateToAll -- when file is not specified but project is", () => { const session = makeSampleProjects(/*addUserTsConfig*/ true, /*keepAllFiles*/ true); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.CommandNames.Navto, { projectFileName: bTsconfig.path, file: undefined, searchValue: "fn" }); - assert.deepEqual(response, [ + const response = executeSessionRequest(session, CommandNames.Navto, { projectFileName: bTsconfig.path, file: undefined, searchValue: "fn" }); + assert.deepEqual(response, [ { - ...ts.projectSystem.protocolFileSpanFromSubstring({ + ...protocolFileSpanFromSubstring({ file: bTs, text: "export function fnB() {}" }), name: "fnB", matchKind: "prefix", isCaseSensitive: true, - kind: ts.ScriptElementKind.functionElement, + kind: ScriptElementKind.functionElement, kindModifiers: "export", } ]); }); - const referenceATs = (aTs: ts.projectSystem.File, isDefinition: true | undefined): ts.projectSystem.protocol.ReferencesResponseItem => ts.projectSystem.makeReferenceItem({ + const referenceATs = (aTs: File, isDefinition: true | undefined): ReferencesResponseItem => makeReferenceItem({ file: aTs, isDefinition, isWriteAccess: true, @@ -387,8 +411,8 @@ describe("unittests:: tsserver:: with declaration file maps:: project references contextText: "export function fnA() {}", lineText: "export function fnA() {}" }); - const referencesUserTs = (userTs: ts.projectSystem.File, isDefinition: false | undefined): readonly ts.projectSystem.protocol.ReferencesResponseItem[] => [ - ts.projectSystem.makeReferenceItem({ + const referencesUserTs = (userTs: File, isDefinition: false | undefined): readonly ReferencesResponseItem[] => [ + makeReferenceItem({ file: userTs, isDefinition, text: "fnA", @@ -399,11 +423,11 @@ describe("unittests:: tsserver:: with declaration file maps:: project references it("findAllReferences", () => { const session = makeSampleProjects(); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.References, ts.projectSystem.protocolFileLocationFromSubstring(userTs, "fnA()")); - assert.deepEqual(response, { + const response = executeSessionRequest(session, CommandTypes.References, protocolFileLocationFromSubstring(userTs, "fnA()")); + assert.deepEqual(response, { refs: [...referencesUserTs(userTs, /*isDefinition*/ undefined), referenceATs(aTs, /*isDefinition*/ true)], // Presently inconsistent across projects symbolName: "fnA", - symbolStartOffset: ts.projectSystem.protocolLocationFromSubstring(userTs.content, "fnA()").offset, + symbolStartOffset: protocolLocationFromSubstring(userTs.content, "fnA()").offset, symbolDisplayString: "function fnA(): void", }); @@ -412,26 +436,26 @@ describe("unittests:: tsserver:: with declaration file maps:: project references it("findAllReferences -- starting at definition", () => { const session = makeSampleProjects(); - ts.projectSystem.openFilesForSession([aTs], session); // If it's not opened, the reference isn't found. - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.References, ts.projectSystem.protocolFileLocationFromSubstring(aTs, "fnA")); - assert.deepEqual(response, { + openFilesForSession([aTs], session); // If it's not opened, the reference isn't found. + const response = executeSessionRequest(session, CommandTypes.References, protocolFileLocationFromSubstring(aTs, "fnA")); + assert.deepEqual(response, { refs: [referenceATs(aTs, /*isDefinition*/ true), ...referencesUserTs(userTs, /*isDefinition*/ false)], symbolName: "fnA", - symbolStartOffset: ts.projectSystem.protocolLocationFromSubstring(aTs.content, "fnA").offset, + symbolStartOffset: protocolLocationFromSubstring(aTs.content, "fnA").offset, symbolDisplayString: "function fnA(): void", }); verifyATsConfigWhenOpened(session); }); - interface ReferencesFullRequest extends ts.projectSystem.protocol.FileLocationRequest { readonly command: ts.projectSystem.protocol.CommandTypes.ReferencesFull; } - interface ReferencesFullResponse extends ts.projectSystem.protocol.Response { readonly body: readonly ts.ReferencedSymbol[]; } + interface ReferencesFullRequest extends FileLocationRequest { readonly command: CommandTypes.ReferencesFull; } + interface ReferencesFullResponse extends Response { readonly body: readonly ReferencedSymbol[]; } it("findAllReferencesFull", () => { const session = makeSampleProjects(); - const responseFull = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.ReferencesFull, ts.projectSystem.protocolFileLocationFromSubstring(userTs, "fnA()")); + const responseFull = executeSessionRequest(session, CommandTypes.ReferencesFull, protocolFileLocationFromSubstring(userTs, "fnA()")); - assert.deepEqual(responseFull, [ + assert.deepEqual(responseFull, [ { definition: { ...documentSpanFromSubstring({ @@ -439,19 +463,19 @@ describe("unittests:: tsserver:: with declaration file maps:: project references text: "fnA", contextText: "export function fnA() {}" }), - kind: ts.ScriptElementKind.functionElement, + kind: ScriptElementKind.functionElement, name: "function fnA(): void", - containerKind: ts.ScriptElementKind.unknown, + containerKind: ScriptElementKind.unknown, containerName: "", displayParts: [ - ts.keywordPart(ts.SyntaxKind.FunctionKeyword), - ts.spacePart(), - ts.displayPart("fnA", ts.SymbolDisplayPartKind.functionName), - ts.punctuationPart(ts.SyntaxKind.OpenParenToken), - ts.punctuationPart(ts.SyntaxKind.CloseParenToken), - ts.punctuationPart(ts.SyntaxKind.ColonToken), - ts.spacePart(), - ts.keywordPart(ts.SyntaxKind.VoidKeyword), + keywordPart(SyntaxKind.FunctionKeyword), + spacePart(), + displayPart("fnA", SymbolDisplayPartKind.functionName), + punctuationPart(SyntaxKind.OpenParenToken), + punctuationPart(SyntaxKind.CloseParenToken), + punctuationPart(SyntaxKind.ColonToken), + spacePart(), + keywordPart(SyntaxKind.VoidKeyword), ], }, references: [ @@ -464,27 +488,27 @@ describe("unittests:: tsserver:: with declaration file maps:: project references }); it("findAllReferencesFull definition is in mapped file", () => { - const aTs: ts.projectSystem.File = { path: "/a/a.ts", content: `function f() {}` }; - const aTsconfig: ts.projectSystem.File = { + const aTs: File = { path: "/a/a.ts", content: `function f() {}` }; + const aTsconfig: File = { path: "/a/tsconfig.json", content: JSON.stringify({ compilerOptions: { declaration: true, declarationMap: true, outFile: "../bin/a.js" } }), }; - const bTs: ts.projectSystem.File = { path: "/b/b.ts", content: `f();` }; - const bTsconfig: ts.projectSystem.File = { path: "/b/tsconfig.json", content: JSON.stringify({ references: [{ path: "../a" }] }) }; - const aDts: ts.projectSystem.File = { path: "/bin/a.d.ts", content: `declare function f(): void;\n//# sourceMappingURL=a.d.ts.map` }; - const aDtsMap: ts.projectSystem.File = { + const bTs: File = { path: "/b/b.ts", content: `f();` }; + const bTsconfig: File = { path: "/b/tsconfig.json", content: JSON.stringify({ references: [{ path: "../a" }] }) }; + const aDts: File = { path: "/bin/a.d.ts", content: `declare function f(): void;\n//# sourceMappingURL=a.d.ts.map` }; + const aDtsMap: File = { path: "/bin/a.d.ts.map", content: JSON.stringify({ version: 3, file: "a.d.ts", sourceRoot: "", sources: ["../a/a.ts"], names: [], mappings: "AAAA,iBAAS,CAAC,SAAK" }), }; - const session = ts.projectSystem.createSession(ts.projectSystem.createServerHost([aTs, aTsconfig, bTs, bTsconfig, aDts, aDtsMap])); + const session = createSession(createServerHost([aTs, aTsconfig, bTs, bTsconfig, aDts, aDtsMap])); checkDeclarationFiles(aTs, session, [aDtsMap, aDts]); - ts.projectSystem.openFilesForSession([bTs], session); - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); // configured project of b is alive since a references b + openFilesForSession([bTs], session); + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); // configured project of b is alive since a references b - const responseFull = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.ReferencesFull, ts.projectSystem.protocolFileLocationFromSubstring(bTs, "f()")); + const responseFull = executeSessionRequest(session, CommandTypes.ReferencesFull, protocolFileLocationFromSubstring(bTs, "f()")); - assert.deepEqual(responseFull, [ + assert.deepEqual(responseFull, [ { definition: { ...documentSpanFromSubstring({ @@ -493,19 +517,19 @@ describe("unittests:: tsserver:: with declaration file maps:: project references options: { index: 1 }, contextText: "function f() {}" }), - containerKind: ts.ScriptElementKind.unknown, + containerKind: ScriptElementKind.unknown, containerName: "", displayParts: [ - ts.keywordPart(ts.SyntaxKind.FunctionKeyword), - ts.spacePart(), - ts.displayPart("f", ts.SymbolDisplayPartKind.functionName), - ts.punctuationPart(ts.SyntaxKind.OpenParenToken), - ts.punctuationPart(ts.SyntaxKind.CloseParenToken), - ts.punctuationPart(ts.SyntaxKind.ColonToken), - ts.spacePart(), - ts.keywordPart(ts.SyntaxKind.VoidKeyword), + keywordPart(SyntaxKind.FunctionKeyword), + spacePart(), + displayPart("f", SymbolDisplayPartKind.functionName), + punctuationPart(SyntaxKind.OpenParenToken), + punctuationPart(SyntaxKind.CloseParenToken), + punctuationPart(SyntaxKind.ColonToken), + spacePart(), + keywordPart(SyntaxKind.VoidKeyword), ], - kind: ts.ScriptElementKind.functionElement, + kind: ScriptElementKind.functionElement, name: "function f(): void", }, references: [ @@ -530,43 +554,43 @@ describe("unittests:: tsserver:: with declaration file maps:: project references it("findAllReferences -- target does not exist", () => { const session = makeSampleProjects(); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.References, ts.projectSystem.protocolFileLocationFromSubstring(userTs, "fnB()")); - assert.deepEqual(response, { + const response = executeSessionRequest(session, CommandTypes.References, protocolFileLocationFromSubstring(userTs, "fnB()")); + assert.deepEqual(response, { refs: [ - ts.projectSystem.makeReferenceItem({ + makeReferenceItem({ file: bDts, isWriteAccess: true, text: "fnB", contextText: "export declare function fnB(): void;", lineText: "export declare function fnB(): void;" }), - ts.projectSystem.makeReferenceItem({ + makeReferenceItem({ file: userTs, text: "fnB", lineText: "export function fnUser() { a.fnA(); b.fnB(); a.instanceA; }" }), ], symbolName: "fnB", - symbolStartOffset: ts.projectSystem.protocolLocationFromSubstring(userTs.content, "fnB()").offset, + symbolStartOffset: protocolLocationFromSubstring(userTs.content, "fnB()").offset, symbolDisplayString: "function fnB(): void", }); verifySingleInferredProject(session); }); - const renameATs = (aTs: ts.projectSystem.File): ts.projectSystem.protocol.SpanGroup => ({ + const renameATs = (aTs: File): SpanGroup => ({ file: aTs.path, locs: [ - ts.projectSystem.protocolRenameSpanFromSubstring({ + protocolRenameSpanFromSubstring({ fileText: aTs.content, text: "fnA", contextText: "export function fnA() {}" }) ], }); - const renameUserTs = (userTs: ts.projectSystem.File): ts.projectSystem.protocol.SpanGroup => ({ + const renameUserTs = (userTs: File): SpanGroup => ({ file: userTs.path, locs: [ - ts.projectSystem.protocolRenameSpanFromSubstring({ + protocolRenameSpanFromSubstring({ fileText: userTs.content, text: "fnA" }) @@ -575,16 +599,16 @@ describe("unittests:: tsserver:: with declaration file maps:: project references it("renameLocations", () => { const session = makeSampleProjects(); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.Rename, ts.projectSystem.protocolFileLocationFromSubstring(userTs, "fnA()")); - assert.deepEqual(response, { + const response = executeSessionRequest(session, CommandTypes.Rename, protocolFileLocationFromSubstring(userTs, "fnA()")); + assert.deepEqual(response, { info: { canRename: true, displayName: "fnA", fileToRename: undefined, fullDisplayName: '"/a/bin/a".fnA', // Ideally this would use the original source's path instead of the declaration file's path. - kind: ts.ScriptElementKind.functionElement, - kindModifiers: [ts.ScriptElementKindModifier.exportedModifier, ts.ScriptElementKindModifier.ambientModifier].join(","), - triggerSpan: ts.projectSystem.protocolTextSpanFromSubstring(userTs.content, "fnA"), + kind: ScriptElementKind.functionElement, + kindModifiers: [ScriptElementKindModifier.exportedModifier, ScriptElementKindModifier.ambientModifier].join(","), + triggerSpan: protocolTextSpanFromSubstring(userTs.content, "fnA"), }, locs: [renameUserTs(userTs), renameATs(aTs)], }); @@ -593,17 +617,17 @@ describe("unittests:: tsserver:: with declaration file maps:: project references it("renameLocations -- starting at definition", () => { const session = makeSampleProjects(); - ts.projectSystem.openFilesForSession([aTs], session); // If it's not opened, the reference isn't found. - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.Rename, ts.projectSystem.protocolFileLocationFromSubstring(aTs, "fnA")); - assert.deepEqual(response, { + openFilesForSession([aTs], session); // If it's not opened, the reference isn't found. + const response = executeSessionRequest(session, CommandTypes.Rename, protocolFileLocationFromSubstring(aTs, "fnA")); + assert.deepEqual(response, { info: { canRename: true, displayName: "fnA", fileToRename: undefined, fullDisplayName: '"/a/a".fnA', - kind: ts.ScriptElementKind.functionElement, - kindModifiers: ts.ScriptElementKindModifier.exportedModifier, - triggerSpan: ts.projectSystem.protocolTextSpanFromSubstring(aTs.content, "fnA"), + kind: ScriptElementKind.functionElement, + kindModifiers: ScriptElementKindModifier.exportedModifier, + triggerSpan: protocolTextSpanFromSubstring(aTs.content, "fnA"), }, locs: [renameATs(aTs), renameUserTs(userTs)], }); @@ -612,8 +636,8 @@ describe("unittests:: tsserver:: with declaration file maps:: project references it("renameLocationsFull", () => { const session = makeSampleProjects(); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.RenameLocationsFull, ts.projectSystem.protocolFileLocationFromSubstring(userTs, "fnA()")); - assert.deepEqual(response, [ + const response = executeSessionRequest(session, CommandTypes.RenameLocationsFull, protocolFileLocationFromSubstring(userTs, "fnA()")); + assert.deepEqual(response, [ renameLocation({ file: userTs, text: "fnA" }), renameLocation({ file: aTs, text: "fnA", contextText: "export function fnA() {}" }), ]); @@ -622,22 +646,22 @@ describe("unittests:: tsserver:: with declaration file maps:: project references it("renameLocations -- target does not exist", () => { const session = makeSampleProjects(); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.Rename, ts.projectSystem.protocolFileLocationFromSubstring(userTs, "fnB()")); - assert.deepEqual(response, { + const response = executeSessionRequest(session, CommandTypes.Rename, protocolFileLocationFromSubstring(userTs, "fnB()")); + assert.deepEqual(response, { info: { canRename: true, displayName: "fnB", fileToRename: undefined, fullDisplayName: '"/b/bin/b".fnB', - kind: ts.ScriptElementKind.functionElement, - kindModifiers: [ts.ScriptElementKindModifier.exportedModifier, ts.ScriptElementKindModifier.ambientModifier].join(","), - triggerSpan: ts.projectSystem.protocolTextSpanFromSubstring(userTs.content, "fnB"), + kind: ScriptElementKind.functionElement, + kindModifiers: [ScriptElementKindModifier.exportedModifier, ScriptElementKindModifier.ambientModifier].join(","), + triggerSpan: protocolTextSpanFromSubstring(userTs.content, "fnB"), }, locs: [ { file: bDts.path, locs: [ - ts.projectSystem.protocolRenameSpanFromSubstring({ + protocolRenameSpanFromSubstring({ fileText: bDts.content, text: "fnB", contextText: "export declare function fnB(): void;" @@ -647,7 +671,7 @@ describe("unittests:: tsserver:: with declaration file maps:: project references { file: userTs.path, locs: [ - ts.projectSystem.protocolRenameSpanFromSubstring({ + protocolRenameSpanFromSubstring({ fileText: userTs.content, text: "fnB" }) @@ -660,15 +684,15 @@ describe("unittests:: tsserver:: with declaration file maps:: project references it("getEditsForFileRename", () => { const session = makeSampleProjects(); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.GetEditsForFileRename, { + const response = executeSessionRequest(session, CommandTypes.GetEditsForFileRename, { oldFilePath: aTs.path, newFilePath: "/a/aNew.ts", }); - assert.deepEqual(response, [ + assert.deepEqual(response, [ { fileName: userTs.path, textChanges: [ - { ...ts.projectSystem.protocolTextSpanFromSubstring(userTs.content, "../a/bin/a"), newText: "../a/bin/aNew" }, + { ...protocolTextSpanFromSubstring(userTs.content, "../a/bin/a"), newText: "../a/bin/aNew" }, ], }, ]); @@ -676,8 +700,8 @@ describe("unittests:: tsserver:: with declaration file maps:: project references }); it("getEditsForFileRename when referencing project doesnt include file and its renamed", () => { - const aTs: ts.projectSystem.File = { path: "/a/src/a.ts", content: "" }; - const aTsconfig: ts.projectSystem.File = { + const aTs: File = { path: "/a/src/a.ts", content: "" }; + const aTsconfig: File = { path: "/a/tsconfig.json", content: JSON.stringify({ compilerOptions: { @@ -688,8 +712,8 @@ describe("unittests:: tsserver:: with declaration file maps:: project references } }), }; - const bTs: ts.projectSystem.File = { path: "/b/src/b.ts", content: "" }; - const bTsconfig: ts.projectSystem.File = { + const bTs: File = { path: "/b/src/b.ts", content: "" }; + const bTsconfig: File = { path: "/b/tsconfig.json", content: JSON.stringify({ compilerOptions: { @@ -701,44 +725,44 @@ describe("unittests:: tsserver:: with declaration file maps:: project references }), }; - const host = ts.projectSystem.createServerHost([aTs, aTsconfig, bTs, bTsconfig]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([aTs, bTs], session); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.CommandNames.GetEditsForFileRename, { + const host = createServerHost([aTs, aTsconfig, bTs, bTsconfig]); + const session = createSession(host); + openFilesForSession([aTs, bTs], session); + const response = executeSessionRequest(session, CommandNames.GetEditsForFileRename, { oldFilePath: aTs.path, newFilePath: "/a/src/a1.ts", }); - assert.deepEqual(response, []); // Should not change anything + assert.deepEqual(response, []); // Should not change anything }); it("does not jump to source if inlined sources", () => { - const aDtsInlinedSources: ts.RawSourceMap = { + const aDtsInlinedSources: RawSourceMap = { ...aDtsMapContent, sourcesContent: [aTs.content] }; - const aDtsMapInlinedSources: ts.projectSystem.File = { + const aDtsMapInlinedSources: File = { path: aDtsMap.path, content: JSON.stringify(aDtsInlinedSources) }; - const host = ts.projectSystem.createServerHost([aTs, aDtsMapInlinedSources, aDts, bTs, bDtsMap, bDts, userTs, dummyFile]); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([aTs, aDtsMapInlinedSources, aDts, bTs, bDtsMap, bDts, userTs, dummyFile]); + const session = createSession(host); - ts.projectSystem.openFilesForSession([userTs], session); + openFilesForSession([userTs], session); const service = session.getProjectService(); // If config file then userConfig project and bConfig project since it is referenced - ts.projectSystem.checkNumberOfProjects(service, { inferredProjects: 1 }); + checkNumberOfProjects(service, { inferredProjects: 1 }); // Inlined so does not jump to aTs assert.deepEqual( - ts.projectSystem.executeSessionRequest( + executeSessionRequest( session, - ts.projectSystem.protocol.CommandTypes.DefinitionAndBoundSpan, - ts.projectSystem.protocolFileLocationFromSubstring(userTs, "fnA()") + CommandTypes.DefinitionAndBoundSpan, + protocolFileLocationFromSubstring(userTs, "fnA()") ), { - textSpan: ts.projectSystem.protocolTextSpanFromSubstring(userTs.content, "fnA"), + textSpan: protocolTextSpanFromSubstring(userTs.content, "fnA"), definitions: [ - ts.projectSystem.protocolFileSpanWithContextFromSubstring({ + protocolFileSpanWithContextFromSubstring({ file: aDts, text: "fnA", contextText: "export declare function fnA(): void;" @@ -749,15 +773,15 @@ describe("unittests:: tsserver:: with declaration file maps:: project references // Not inlined, jumps to bTs assert.deepEqual( - ts.projectSystem.executeSessionRequest( + executeSessionRequest( session, - ts.projectSystem.protocol.CommandTypes.DefinitionAndBoundSpan, - ts.projectSystem.protocolFileLocationFromSubstring(userTs, "fnB()") + CommandTypes.DefinitionAndBoundSpan, + protocolFileLocationFromSubstring(userTs, "fnB()") ), { - textSpan: ts.projectSystem.protocolTextSpanFromSubstring(userTs.content, "fnB"), + textSpan: protocolTextSpanFromSubstring(userTs.content, "fnB"), definitions: [ - ts.projectSystem.protocolFileSpanWithContextFromSubstring({ + protocolFileSpanWithContextFromSubstring({ file: bTs, text: "fnB", contextText: "export function fnB() {}" diff --git a/src/testRunner/unittests/tsserver/documentRegistry.ts b/src/testRunner/unittests/tsserver/documentRegistry.ts index ceeae4f15abf3..8ca678d319e84 100644 --- a/src/testRunner/unittests/tsserver/documentRegistry.ts +++ b/src/testRunner/unittests/tsserver/documentRegistry.ts @@ -1,29 +1,33 @@ -import * as ts from "../../_namespaces/ts"; +import { singleIterator } from "../../../compiler/core"; +import { projectRoot } from "../tscWatch/helpers"; +import { + checkProjectActualFiles, createProjectService, createServerHost, File, libFile, TestProjectService, +} from "./helpers"; describe("unittests:: tsserver:: document registry in project service", () => { const importModuleContent = `import {a} from "./module1"`; - const file: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/index.ts`, + const file: File = { + path: `${projectRoot}/index.ts`, content: importModuleContent }; - const moduleFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/module1.d.ts`, + const moduleFile: File = { + path: `${projectRoot}/module1.d.ts`, content: "export const a: number;" }; - const configFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const configFile: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ files: ["index.ts"] }) }; - function getProject(service: ts.projectSystem.TestProjectService) { + function getProject(service: TestProjectService) { return service.configuredProjects.get(configFile.path)!; } - function checkProject(service: ts.projectSystem.TestProjectService, moduleIsOrphan: boolean) { + function checkProject(service: TestProjectService, moduleIsOrphan: boolean) { // Update the project const project = getProject(service); project.getLanguageService(); - ts.projectSystem.checkProjectActualFiles(project, [file.path, ts.projectSystem.libFile.path, configFile.path, ...(moduleIsOrphan ? [] : [moduleFile.path])]); + checkProjectActualFiles(project, [file.path, libFile.path, configFile.path, ...(moduleIsOrphan ? [] : [moduleFile.path])]); const moduleInfo = service.getScriptInfo(moduleFile.path)!; assert.isDefined(moduleInfo); assert.equal(moduleInfo.isOrphan(), moduleIsOrphan); @@ -32,22 +36,22 @@ describe("unittests:: tsserver:: document registry in project service", () => { } function createServiceAndHost() { - const host = ts.projectSystem.createServerHost([file, moduleFile, ts.projectSystem.libFile, configFile]); - const service = ts.projectSystem.createProjectService(host); + const host = createServerHost([file, moduleFile, libFile, configFile]); + const service = createProjectService(host); service.openClientFile(file.path); checkProject(service, /*moduleIsOrphan*/ false); return { host, service }; } - function changeFileToNotImportModule(service: ts.projectSystem.TestProjectService) { + function changeFileToNotImportModule(service: TestProjectService) { const info = service.getScriptInfo(file.path)!; - service.applyChangesToFile(info, ts.singleIterator({ span: { start: 0, length: importModuleContent.length }, newText: "" })); + service.applyChangesToFile(info, singleIterator({ span: { start: 0, length: importModuleContent.length }, newText: "" })); checkProject(service, /*moduleIsOrphan*/ true); } - function changeFileToImportModule(service: ts.projectSystem.TestProjectService) { + function changeFileToImportModule(service: TestProjectService) { const info = service.getScriptInfo(file.path)!; - service.applyChangesToFile(info, ts.singleIterator({ span: { start: 0, length: 0 }, newText: importModuleContent })); + service.applyChangesToFile(info, singleIterator({ span: { start: 0, length: 0 }, newText: importModuleContent })); checkProject(service, /*moduleIsOrphan*/ false); } diff --git a/src/testRunner/unittests/tsserver/duplicatePackages.ts b/src/testRunner/unittests/tsserver/duplicatePackages.ts index 06af082b77b81..548bbe28f55b5 100644 --- a/src/testRunner/unittests/tsserver/duplicatePackages.ts +++ b/src/testRunner/unittests/tsserver/duplicatePackages.ts @@ -1,38 +1,40 @@ -import * as ts from "../../_namespaces/ts"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { CodeFixAction, CodeFixRequest, CodeFixResponse, CommandTypes } from "../../../server/protocol"; +import { createServerHost, createSession, executeSessionRequest, File, openFilesForSession } from "./helpers"; describe("unittests:: tsserver:: duplicate packages", () => { // Tests that 'moduleSpecifiers.ts' will import from the redirecting file, and not from the file it redirects to, if that can provide a global module specifier. it("works with import fixes", () => { const packageContent = "export const foo: number;"; const packageJsonContent = JSON.stringify({ name: "foo", version: "1.2.3" }); - const aFooIndex: ts.projectSystem.File = { path: "/a/node_modules/foo/index.d.ts", content: packageContent }; - const aFooPackage: ts.projectSystem.File = { path: "/a/node_modules/foo/package.json", content: packageJsonContent }; - const bFooIndex: ts.projectSystem.File = { path: "/b/node_modules/foo/index.d.ts", content: packageContent }; - const bFooPackage: ts.projectSystem.File = { path: "/b/node_modules/foo/package.json", content: packageJsonContent }; + const aFooIndex: File = { path: "/a/node_modules/foo/index.d.ts", content: packageContent }; + const aFooPackage: File = { path: "/a/node_modules/foo/package.json", content: packageJsonContent }; + const bFooIndex: File = { path: "/b/node_modules/foo/index.d.ts", content: packageContent }; + const bFooPackage: File = { path: "/b/node_modules/foo/package.json", content: packageJsonContent }; const userContent = 'import("foo");\nfoo'; - const aUser: ts.projectSystem.File = { path: "/a/user.ts", content: userContent }; - const bUser: ts.projectSystem.File = { path: "/b/user.ts", content: userContent }; - const tsconfig: ts.projectSystem.File = { + const aUser: File = { path: "/a/user.ts", content: userContent }; + const bUser: File = { path: "/b/user.ts", content: userContent }; + const tsconfig: File = { path: "/tsconfig.json", content: "{}", }; - const host = ts.projectSystem.createServerHost([aFooIndex, aFooPackage, bFooIndex, bFooPackage, aUser, bUser, tsconfig]); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([aFooIndex, aFooPackage, bFooIndex, bFooPackage, aUser, bUser, tsconfig]); + const session = createSession(host); - ts.projectSystem.openFilesForSession([aUser, bUser], session); + openFilesForSession([aUser, bUser], session); for (const user of [aUser, bUser]) { - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.GetCodeFixes, { + const response = executeSessionRequest(session, CommandTypes.GetCodeFixes, { file: user.path, startLine: 2, startOffset: 1, endLine: 2, endOffset: 4, - errorCodes: [ts.Diagnostics.Cannot_find_name_0.code], + errorCodes: [Diagnostics.Cannot_find_name_0.code], }); - assert.deepEqual(response, [ + assert.deepEqual(response, [ { description: `Add import from "foo"`, fixName: "import", diff --git a/src/testRunner/unittests/tsserver/dynamicFiles.ts b/src/testRunner/unittests/tsserver/dynamicFiles.ts index 19398777e39e6..c8d0d3f6e4416 100644 --- a/src/testRunner/unittests/tsserver/dynamicFiles.ts +++ b/src/testRunner/unittests/tsserver/dynamicFiles.ts @@ -1,53 +1,67 @@ -import * as ts from "../../_namespaces/ts"; +import { arrayFrom } from "../../../compiler/core"; +import { Debug } from "../../../compiler/debug"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { ModuleKind, ScriptKind } from "../../../compiler/types"; +import { ProjectService } from "../../../server/editorServices"; +import { + CodeFixAction, CodeFixRequest, CodeFixResponse, CommandTypes, OpenRequest, OutliningSpansRequest, +} from "../../../server/protocol"; +import { toNormalizedPath } from "../../../server/utilitiesPublic"; +import { ScriptElementKind } from "../../../services/types"; +import { projectRoot } from "../tscWatch/helpers"; +import { + checkNumberOfProjects, checkProjectActualFiles, checkProjectRootFiles, createProjectService, createServerHost, + createSession, executeSessionRequest, executeSessionRequestNoResponse, File, libFile, openFilesForSession, +} from "./helpers"; -export function verifyDynamic(service: ts.server.ProjectService, path: string) { - const info = ts.Debug.checkDefined(service.filenameToScriptInfo.get(path), `Expected ${path} in :: ${JSON.stringify(ts.arrayFrom(service.filenameToScriptInfo.entries(), ([key, f]) => ({ key, fileName: f.fileName, path: f.path })))}`); +export function verifyDynamic(service: ProjectService, path: string) { + const info = Debug.checkDefined(service.filenameToScriptInfo.get(path), `Expected ${path} in :: ${JSON.stringify(arrayFrom(service.filenameToScriptInfo.entries(), ([key, f]) => ({ key, fileName: f.fileName, path: f.path })))}`); assert.isTrue(info.isDynamic); } function verifyPathRecognizedAsDynamic(path: string) { - const file: ts.projectSystem.File = { + const file: File = { path, content: `/// /// var x = 10;` }; - const host = ts.projectSystem.createServerHost([ts.projectSystem.libFile]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([libFile]); + const projectService = createProjectService(host); projectService.openClientFile(file.path, file.content); verifyDynamic(projectService, projectService.toPath(file.path)); projectService.checkNumberOfProjects({ inferredProjects: 1 }); const project = projectService.inferredProjects[0]; - ts.projectSystem.checkProjectRootFiles(project, [file.path]); - ts.projectSystem.checkProjectActualFiles(project, [file.path, ts.projectSystem.libFile.path]); + checkProjectRootFiles(project, [file.path]); + checkProjectActualFiles(project, [file.path, libFile.path]); } describe("unittests:: tsserver:: dynamicFiles:: Untitled files", () => { const untitledFile = "untitled:^Untitled-1"; it("Can convert positions to locations", () => { - const aTs: ts.projectSystem.File = { path: "/proj/a.ts", content: "" }; - const tsconfig: ts.projectSystem.File = { path: "/proj/tsconfig.json", content: "{}" }; - const session = ts.projectSystem.createSession(ts.projectSystem.createServerHost([aTs, tsconfig]), { useInferredProjectPerProjectRoot: true }); + const aTs: File = { path: "/proj/a.ts", content: "" }; + const tsconfig: File = { path: "/proj/tsconfig.json", content: "{}" }; + const session = createSession(createServerHost([aTs, tsconfig]), { useInferredProjectPerProjectRoot: true }); - ts.projectSystem.openFilesForSession([aTs], session); + openFilesForSession([aTs], session); - ts.projectSystem.executeSessionRequestNoResponse(session, ts.projectSystem.protocol.CommandTypes.Open, { + executeSessionRequestNoResponse(session, CommandTypes.Open, { file: untitledFile, fileContent: `/// \nlet foo = 1;\nfooo/**/`, scriptKindName: "TS", projectRootPath: "/proj", }); verifyDynamic(session.getProjectService(), `/proj/untitled:^untitled-1`); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.GetCodeFixes, { + const response = executeSessionRequest(session, CommandTypes.GetCodeFixes, { file: untitledFile, startLine: 3, startOffset: 1, endLine: 3, endOffset: 5, - errorCodes: [ts.Diagnostics.Cannot_find_name_0_Did_you_mean_1.code], + errorCodes: [Diagnostics.Cannot_find_name_0_Did_you_mean_1.code], }); - assert.deepEqual(response, [ + assert.deepEqual(response, [ { description: "Change spelling to 'foo'", fixName: "spelling", @@ -67,68 +81,68 @@ describe("unittests:: tsserver:: dynamicFiles:: Untitled files", () => { }); it("opening untitled files", () => { - const config: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: "{}" }; - const host = ts.projectSystem.createServerHost([config, ts.projectSystem.libFile], { useCaseSensitiveFileNames: true, currentDirectory: ts.tscWatch.projectRoot }); - const service = ts.projectSystem.createProjectService(host); - service.openClientFile(untitledFile, "const x = 10;", /*scriptKind*/ undefined, ts.tscWatch.projectRoot); - ts.projectSystem.checkNumberOfProjects(service, { inferredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(service.inferredProjects[0], [untitledFile, ts.projectSystem.libFile.path]); - verifyDynamic(service, `${ts.tscWatch.projectRoot}/${untitledFile}`); + const host = createServerHost([config, libFile], { useCaseSensitiveFileNames: true, currentDirectory: projectRoot }); + const service = createProjectService(host); + service.openClientFile(untitledFile, "const x = 10;", /*scriptKind*/ undefined, projectRoot); + checkNumberOfProjects(service, { inferredProjects: 1 }); + checkProjectActualFiles(service.inferredProjects[0], [untitledFile, libFile.path]); + verifyDynamic(service, `${projectRoot}/${untitledFile}`); - const untitled: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/Untitled-1.ts`, + const untitled: File = { + path: `${projectRoot}/Untitled-1.ts`, content: "const x = 10;" }; host.writeFile(untitled.path, untitled.content); host.checkTimeoutQueueLength(0); - service.openClientFile(untitled.path, untitled.content, /*scriptKind*/ undefined, ts.tscWatch.projectRoot); - ts.projectSystem.checkNumberOfProjects(service, { configuredProjects: 1, inferredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(service.configuredProjects.get(config.path)!, [untitled.path, ts.projectSystem.libFile.path, config.path]); - ts.projectSystem.checkProjectActualFiles(service.inferredProjects[0], [untitledFile, ts.projectSystem.libFile.path]); + service.openClientFile(untitled.path, untitled.content, /*scriptKind*/ undefined, projectRoot); + checkNumberOfProjects(service, { configuredProjects: 1, inferredProjects: 1 }); + checkProjectActualFiles(service.configuredProjects.get(config.path)!, [untitled.path, libFile.path, config.path]); + checkProjectActualFiles(service.inferredProjects[0], [untitledFile, libFile.path]); service.closeClientFile(untitledFile); - ts.projectSystem.checkProjectActualFiles(service.configuredProjects.get(config.path)!, [untitled.path, ts.projectSystem.libFile.path, config.path]); - ts.projectSystem.checkProjectActualFiles(service.inferredProjects[0], [untitledFile, ts.projectSystem.libFile.path]); + checkProjectActualFiles(service.configuredProjects.get(config.path)!, [untitled.path, libFile.path, config.path]); + checkProjectActualFiles(service.inferredProjects[0], [untitledFile, libFile.path]); - service.openClientFile(untitledFile, "const x = 10;", /*scriptKind*/ undefined, ts.tscWatch.projectRoot); - verifyDynamic(service, `${ts.tscWatch.projectRoot}/${untitledFile}`); - ts.projectSystem.checkProjectActualFiles(service.configuredProjects.get(config.path)!, [untitled.path, ts.projectSystem.libFile.path, config.path]); - ts.projectSystem.checkProjectActualFiles(service.inferredProjects[0], [untitledFile, ts.projectSystem.libFile.path]); + service.openClientFile(untitledFile, "const x = 10;", /*scriptKind*/ undefined, projectRoot); + verifyDynamic(service, `${projectRoot}/${untitledFile}`); + checkProjectActualFiles(service.configuredProjects.get(config.path)!, [untitled.path, libFile.path, config.path]); + checkProjectActualFiles(service.inferredProjects[0], [untitledFile, libFile.path]); }); it("opening and closing untitled files when projectRootPath is different from currentDirectory", () => { - const config: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: "{}" }; - const file: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/file.ts`, + const file: File = { + path: `${projectRoot}/file.ts`, content: "const y = 10" }; - const host = ts.projectSystem.createServerHost([config, file, ts.projectSystem.libFile], { useCaseSensitiveFileNames: true }); - const service = ts.projectSystem.createProjectService(host, { useInferredProjectPerProjectRoot: true }); - service.openClientFile(untitledFile, "const x = 10;", /*scriptKind*/ undefined, ts.tscWatch.projectRoot); - ts.projectSystem.checkNumberOfProjects(service, { inferredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(service.inferredProjects[0], [untitledFile, ts.projectSystem.libFile.path]); - verifyDynamic(service, `${ts.tscWatch.projectRoot}/${untitledFile}`); + const host = createServerHost([config, file, libFile], { useCaseSensitiveFileNames: true }); + const service = createProjectService(host, { useInferredProjectPerProjectRoot: true }); + service.openClientFile(untitledFile, "const x = 10;", /*scriptKind*/ undefined, projectRoot); + checkNumberOfProjects(service, { inferredProjects: 1 }); + checkProjectActualFiles(service.inferredProjects[0], [untitledFile, libFile.path]); + verifyDynamic(service, `${projectRoot}/${untitledFile}`); // Close untitled file service.closeClientFile(untitledFile); // Open file from configured project which should collect inferredProject service.openClientFile(file.path); - ts.projectSystem.checkNumberOfProjects(service, { configuredProjects: 1 }); + checkNumberOfProjects(service, { configuredProjects: 1 }); }); it("when changing scriptKind of the untitled files", () => { - const host = ts.projectSystem.createServerHost([ts.projectSystem.libFile], { useCaseSensitiveFileNames: true }); - const service = ts.projectSystem.createProjectService(host, { useInferredProjectPerProjectRoot: true }); - service.openClientFile(untitledFile, "const x = 10;", ts.ScriptKind.TS, ts.tscWatch.projectRoot); - ts.projectSystem.checkNumberOfProjects(service, { inferredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(service.inferredProjects[0], [untitledFile, ts.projectSystem.libFile.path]); + const host = createServerHost([libFile], { useCaseSensitiveFileNames: true }); + const service = createProjectService(host, { useInferredProjectPerProjectRoot: true }); + service.openClientFile(untitledFile, "const x = 10;", ScriptKind.TS, projectRoot); + checkNumberOfProjects(service, { inferredProjects: 1 }); + checkProjectActualFiles(service.inferredProjects[0], [untitledFile, libFile.path]); const program = service.inferredProjects[0].getCurrentProgram()!; const sourceFile = program.getSourceFile(untitledFile)!; @@ -136,9 +150,9 @@ describe("unittests:: tsserver:: dynamicFiles:: Untitled files", () => { service.closeClientFile(untitledFile); // Open untitled file with different mode - service.openClientFile(untitledFile, "const x = 10;", ts.ScriptKind.TSX, ts.tscWatch.projectRoot); - ts.projectSystem.checkNumberOfProjects(service, { inferredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(service.inferredProjects[0], [untitledFile, ts.projectSystem.libFile.path]); + service.openClientFile(untitledFile, "const x = 10;", ScriptKind.TSX, projectRoot); + checkNumberOfProjects(service, { inferredProjects: 1 }); + checkProjectActualFiles(service.inferredProjects[0], [untitledFile, libFile.path]); const newProgram = service.inferredProjects[0].getCurrentProgram()!; const newSourceFile = newProgram.getSourceFile(untitledFile)!; assert.notStrictEqual(newProgram, program); @@ -148,14 +162,14 @@ describe("unittests:: tsserver:: dynamicFiles:: Untitled files", () => { describe("unittests:: tsserver:: dynamicFiles:: ", () => { it("dynamic file without external project", () => { - const file: ts.projectSystem.File = { + const file: File = { path: "^walkThroughSnippet:/Users/UserName/projects/someProject/out/someFile#1.js", content: "var x = 10;" }; - const host = ts.projectSystem.createServerHost([ts.projectSystem.libFile], { useCaseSensitiveFileNames: true }); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([libFile], { useCaseSensitiveFileNames: true }); + const projectService = createProjectService(host); projectService.setCompilerOptionsForInferredProjects({ - module: ts.ModuleKind.CommonJS, + module: ModuleKind.CommonJS, allowJs: true, allowSyntheticDefaultImports: true, allowNonTsExtensions: true @@ -164,14 +178,14 @@ describe("unittests:: tsserver:: dynamicFiles:: ", () => { projectService.checkNumberOfProjects({ inferredProjects: 1 }); const project = projectService.inferredProjects[0]; - ts.projectSystem.checkProjectRootFiles(project, [file.path]); - ts.projectSystem.checkProjectActualFiles(project, [file.path, ts.projectSystem.libFile.path]); + checkProjectRootFiles(project, [file.path]); + checkProjectActualFiles(project, [file.path, libFile.path]); verifyDynamic(projectService, `/${file.path}`); - assert.strictEqual(projectService.ensureDefaultProjectForFile(ts.server.toNormalizedPath(file.path)), project); + assert.strictEqual(projectService.ensureDefaultProjectForFile(toNormalizedPath(file.path)), project); const indexOfX = file.content.indexOf("x"); assert.deepEqual(project.getLanguageService(/*ensureSynchronized*/ true).getQuickInfoAtPosition(file.path, indexOfX), { - kind: ts.ScriptElementKind.variableElement, + kind: ScriptElementKind.variableElement, kindModifiers: "", textSpan: { start: indexOfX, length: 1 }, displayParts: [ @@ -192,30 +206,30 @@ describe("unittests:: tsserver:: dynamicFiles:: ", () => { }); describe("dynamic file with projectRootPath", () => { - const file: ts.projectSystem.File = { + const file: File = { path: "^walkThroughSnippet:/Users/UserName/projects/someProject/out/someFile#1.js", content: "var x = 10;" }; - const configFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const configFile: File = { + path: `${projectRoot}/tsconfig.json`, content: "{}" }; - const configProjectFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const configProjectFile: File = { + path: `${projectRoot}/a.ts`, content: "let y = 10;" }; it("with useInferredProjectPerProjectRoot", () => { - const host = ts.projectSystem.createServerHost([ts.projectSystem.libFile, configFile, configProjectFile], { useCaseSensitiveFileNames: true }); - const session = ts.projectSystem.createSession(host, { useInferredProjectPerProjectRoot: true }); - ts.projectSystem.openFilesForSession([{ file: file.path, projectRootPath: ts.tscWatch.projectRoot }], session); + const host = createServerHost([libFile, configFile, configProjectFile], { useCaseSensitiveFileNames: true }); + const session = createSession(host, { useInferredProjectPerProjectRoot: true }); + openFilesForSession([{ file: file.path, projectRootPath: projectRoot }], session); const projectService = session.getProjectService(); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file.path, ts.projectSystem.libFile.path]); - verifyDynamic(projectService, `${ts.tscWatch.projectRoot}/${file.path}`); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkProjectActualFiles(projectService.inferredProjects[0], [file.path, libFile.path]); + verifyDynamic(projectService, `${projectRoot}/${file.path}`); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.GetOutliningSpans, + session.executeCommandSeq({ + command: CommandTypes.GetOutliningSpans, arguments: { file: file.path } @@ -224,16 +238,16 @@ describe("unittests:: tsserver:: dynamicFiles:: ", () => { // Without project root const file2Path = file.path.replace("#1", "#2"); projectService.openClientFile(file2Path, file.content); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 2 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file.path, ts.projectSystem.libFile.path]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [file2Path, ts.projectSystem.libFile.path]); + checkNumberOfProjects(projectService, { inferredProjects: 2 }); + checkProjectActualFiles(projectService.inferredProjects[0], [file.path, libFile.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [file2Path, libFile.path]); }); it("fails when useInferredProjectPerProjectRoot is false", () => { - const host = ts.projectSystem.createServerHost([ts.projectSystem.libFile, configFile, configProjectFile], { useCaseSensitiveFileNames: true }); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([libFile, configFile, configProjectFile], { useCaseSensitiveFileNames: true }); + const projectService = createProjectService(host); try { - projectService.openClientFile(file.path, file.content, /*scriptKind*/ undefined, ts.tscWatch.projectRoot); + projectService.openClientFile(file.path, file.content, /*scriptKind*/ undefined, projectRoot); } catch (e) { assert.strictEqual( @@ -244,7 +258,7 @@ describe("unittests:: tsserver:: dynamicFiles:: ", () => { const file2Path = file.path.replace("#1", "#2"); projectService.openClientFile(file2Path, file.content); projectService.checkNumberOfProjects({ inferredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file2Path, ts.projectSystem.libFile.path]); + checkProjectActualFiles(projectService.inferredProjects[0], [file2Path, libFile.path]); }); }); diff --git a/src/testRunner/unittests/tsserver/events/largeFileReferenced.ts b/src/testRunner/unittests/tsserver/events/largeFileReferenced.ts index 951f5304a6b66..bad7287c7861c 100644 --- a/src/testRunner/unittests/tsserver/events/largeFileReferenced.ts +++ b/src/testRunner/unittests/tsserver/events/largeFileReferenced.ts @@ -1,4 +1,11 @@ -import * as ts from "../../../_namespaces/ts"; +import { emptyArray } from "../../../../compiler/core"; +import { LargeFileReferencedEvent, maxFileSize } from "../../../../server/editorServices"; +import { Project } from "../../../../server/project"; +import { projectRoot } from "../../tscWatch/helpers"; +import { + checkNumberOfProjects, checkProjectActualFiles, createServerHost, createSessionWithEventTracking, File, libFile, + openFilesForSession, +} from "../helpers"; describe("unittests:: tsserver:: events:: LargeFileReferencedEvent with large file", () => { @@ -6,61 +13,61 @@ describe("unittests:: tsserver:: events:: LargeFileReferencedEvent with large fi return `src/large.${useLargeTsFile ? "ts" : "js"}`; } - function createSessionWithEventHandler(files: ts.projectSystem.File[], useLargeTsFile: boolean) { - const largeFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/${getLargeFile(useLargeTsFile)}`, + function createSessionWithEventHandler(files: File[], useLargeTsFile: boolean) { + const largeFile: File = { + path: `${projectRoot}/${getLargeFile(useLargeTsFile)}`, content: "export var x = 10;", - fileSize: ts.server.maxFileSize + 1 + fileSize: maxFileSize + 1 }; files.push(largeFile); - const host = ts.projectSystem.createServerHost(files); - const { session, events: largeFileReferencedEvents } = ts.projectSystem.createSessionWithEventTracking(host, ts.server.LargeFileReferencedEvent); + const host = createServerHost(files); + const { session, events: largeFileReferencedEvents } = createSessionWithEventTracking(host, LargeFileReferencedEvent); return { session, verifyLargeFile }; - function verifyLargeFile(project: ts.server.Project) { - ts.projectSystem.checkProjectActualFiles(project, files.map(f => f.path)); + function verifyLargeFile(project: Project) { + checkProjectActualFiles(project, files.map(f => f.path)); // large file for non ts file should be empty and for ts file should have content const service = session.getProjectService(); const info = service.getScriptInfo(largeFile.path)!; assert.equal(info.cacheSourceFile!.sourceFile.text, useLargeTsFile ? largeFile.content : ""); - assert.deepEqual(largeFileReferencedEvents, useLargeTsFile ? ts.emptyArray : [{ - eventName: ts.server.LargeFileReferencedEvent, - data: { file: largeFile.path, fileSize: largeFile.fileSize, maxFileSize: ts.server.maxFileSize } + assert.deepEqual(largeFileReferencedEvents, useLargeTsFile ? emptyArray : [{ + eventName: LargeFileReferencedEvent, + data: { file: largeFile.path, fileSize: largeFile.fileSize, maxFileSize: maxFileSize } }]); } } function verifyLargeFile(useLargeTsFile: boolean) { it("when large file is included by tsconfig", () => { - const file: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/src/file.ts`, + const file: File = { + path: `${projectRoot}/src/file.ts`, content: "export var y = 10;" }; - const tsconfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ files: ["src/file.ts", getLargeFile(useLargeTsFile)], compilerOptions: { target: 1, allowJs: true } }) }; - const files = [file, ts.projectSystem.libFile, tsconfig]; + const files = [file, libFile, tsconfig]; const { session, verifyLargeFile } = createSessionWithEventHandler(files, useLargeTsFile); const service = session.getProjectService(); - ts.projectSystem.openFilesForSession([file], session); - ts.projectSystem.checkNumberOfProjects(service, { configuredProjects: 1 }); + openFilesForSession([file], session); + checkNumberOfProjects(service, { configuredProjects: 1 }); verifyLargeFile(service.configuredProjects.get(tsconfig.path)!); }); it("when large file is included by module resolution", () => { - const file: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/src/file.ts`, + const file: File = { + path: `${projectRoot}/src/file.ts`, content: `export var y = 10;import {x} from "./large"` }; - const files = [file, ts.projectSystem.libFile]; + const files = [file, libFile]; const { session, verifyLargeFile } = createSessionWithEventHandler(files, useLargeTsFile); const service = session.getProjectService(); - ts.projectSystem.openFilesForSession([file], session); - ts.projectSystem.checkNumberOfProjects(service, { inferredProjects: 1 }); + openFilesForSession([file], session); + checkNumberOfProjects(service, { inferredProjects: 1 }); verifyLargeFile(service.inferredProjects[0]); }); } diff --git a/src/testRunner/unittests/tsserver/events/projectLanguageServiceState.ts b/src/testRunner/unittests/tsserver/events/projectLanguageServiceState.ts index 76ad720bee1a4..0de2800e485c3 100644 --- a/src/testRunner/unittests/tsserver/events/projectLanguageServiceState.ts +++ b/src/testRunner/unittests/tsserver/events/projectLanguageServiceState.ts @@ -1,4 +1,9 @@ -import * as ts from "../../../_namespaces/ts"; +import { maxProgramSizeForNonTsFiles, ProjectLanguageServiceStateEvent } from "../../../../server/editorServices"; +import { OpenRequest } from "../../../../server/protocol"; +import { + baselineTsserverLogs, checkNumberOfProjects, configuredProjectAt, createLoggerWithInMemoryLogs, + createProjectService, createServerHost, createSessionWithEventTracking, File, libFile, +} from "../helpers"; describe("unittests:: tsserver:: events:: ProjectLanguageServiceStateEvent", () => { it("language service disabled events are triggered", () => { @@ -18,21 +23,21 @@ describe("unittests:: tsserver:: events:: ProjectLanguageServiceStateEvent", () path: config.path, content: JSON.stringify({ exclude: ["largefile.js"] }) }; - const host = ts.projectSystem.createServerHost([f1, f2, config]); + const host = createServerHost([f1, f2, config]); const originalGetFileSize = host.getFileSize; host.getFileSize = (filePath: string) => - filePath === f2.path ? ts.server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); + filePath === f2.path ? maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); - const { session, events } = ts.projectSystem.createSessionWithEventTracking(host, ts.server.ProjectLanguageServiceStateEvent); + const { session, events } = createSessionWithEventTracking(host, ProjectLanguageServiceStateEvent); session.executeCommand({ seq: 0, type: "request", command: "open", arguments: { file: f1.path } - } as ts.projectSystem.protocol.OpenRequest); + } as OpenRequest); const projectService = session.getProjectService(); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); - const project = ts.projectSystem.configuredProjectAt(projectService, 0); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + const project = configuredProjectAt(projectService, 0); assert.isFalse(project.languageServiceEnabled, "Language service enabled"); assert.equal(events.length, 1, "should receive event"); assert.equal(events[0].data.project, project, "project name"); @@ -41,7 +46,7 @@ describe("unittests:: tsserver:: events:: ProjectLanguageServiceStateEvent", () host.writeFile(configWithExclude.path, configWithExclude.content); host.checkTimeoutQueueLengthAndRun(2); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); assert.isTrue(project.languageServiceEnabled, "Language service enabled"); assert.equal(events.length, 2, "should receive event"); assert.equal(events[1].data.project, project, "project"); @@ -50,31 +55,31 @@ describe("unittests:: tsserver:: events:: ProjectLanguageServiceStateEvent", () }); it("Large file size is determined correctly", () => { - const f1: ts.projectSystem.File = { + const f1: File = { path: "/a/app.js", content: "let x = 1;" }; - const f2: ts.projectSystem.File = { + const f2: File = { path: "/a/largefile.js", content: "", - fileSize: ts.server.maxProgramSizeForNonTsFiles + 1 + fileSize: maxProgramSizeForNonTsFiles + 1 }; - const f3: ts.projectSystem.File = { + const f3: File = { path: "/a/extremlylarge.d.ts", content: "", - fileSize: ts.server.maxProgramSizeForNonTsFiles + 100 + fileSize: maxProgramSizeForNonTsFiles + 100 }; const config = { path: "/a/jsconfig.json", content: "{}" }; - const host = ts.projectSystem.createServerHost([f1, f2, f3, ts.projectSystem.libFile, config]); - const service = ts.projectSystem.createProjectService(host, { logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); + const host = createServerHost([f1, f2, f3, libFile, config]); + const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs() }); service.openClientFile(f1.path); const project = service.configuredProjects.get(config.path)!; service.logger.logs.push(`languageServiceEnabled: ${project.languageServiceEnabled}`); service.logger.logs.push(`lastFileExceededProgramSize: ${project.lastFileExceededProgramSize}`); - ts.projectSystem.baselineTsserverLogs("projectLanguageServiceStateEvent", "large file size is determined correctly", service); + baselineTsserverLogs("projectLanguageServiceStateEvent", "large file size is determined correctly", service); }); }); diff --git a/src/testRunner/unittests/tsserver/events/projectLoading.ts b/src/testRunner/unittests/tsserver/events/projectLoading.ts index 4a2620fd4faba..74105dc1d892b 100644 --- a/src/testRunner/unittests/tsserver/events/projectLoading.ts +++ b/src/testRunner/unittests/tsserver/events/projectLoading.ts @@ -1,26 +1,33 @@ -import * as ts from "../../../_namespaces/ts"; +import { ProjectLoadingFinishEvent, ProjectLoadingStartEvent } from "../../../../server/editorServices"; +import { Project } from "../../../../server/project"; +import { CommandTypes, ExternalProject, ReferencesRequest } from "../../../../server/protocol"; +import { projects } from "../../tscWatch/helpers"; +import { + checkNumberOfProjects, createServerHost, createSessionWithDefaultEventHandler, createSessionWithEventTracking, File, + libFile, openFilesForSession, protocol, protocolLocationFromSubstring, TestServerHost, TestSession, toExternalFiles, +} from "../helpers"; describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoadingFinish events", () => { - const aTs: ts.projectSystem.File = { - path: `${ts.tscWatch.projects}/a/a.ts`, + const aTs: File = { + path: `${projects}/a/a.ts`, content: "export class A { }" }; - const configA: ts.projectSystem.File = { - path: `${ts.tscWatch.projects}/a/tsconfig.json`, + const configA: File = { + path: `${projects}/a/tsconfig.json`, content: "{}" }; - const bTsPath = `${ts.tscWatch.projects}/b/b.ts`; - const configBPath = `${ts.tscWatch.projects}/b/tsconfig.json`; - const files = [ts.projectSystem.libFile, aTs, configA]; + const bTsPath = `${projects}/b/b.ts`; + const configBPath = `${projects}/b/tsconfig.json`; + const files = [libFile, aTs, configA]; - function verifyProjectLoadingStartAndFinish(createSession: (host: ts.projectSystem.TestServerHost) => { - session: ts.projectSystem.TestSession; + function verifyProjectLoadingStartAndFinish(createSession: (host: TestServerHost) => { + session: TestSession; getNumberOfEvents: () => number; clearEvents: () => void; - verifyProjectLoadEvents: (expected: [ts.server.ProjectLoadingStartEvent, ts.server.ProjectLoadingFinishEvent]) => void; + verifyProjectLoadEvents: (expected: [ProjectLoadingStartEvent, ProjectLoadingFinishEvent]) => void; }) { - function createSessionToVerifyEvent(files: readonly ts.projectSystem.File[]) { - const host = ts.projectSystem.createServerHost(files); + function createSessionToVerifyEvent(files: readonly File[]) { + const host = createServerHost(files); const originalReadFile = host.readFile; const { session, getNumberOfEvents, clearEvents, verifyProjectLoadEvents } = createSession(host); host.readFile = file => { @@ -32,17 +39,17 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading const service = session.getProjectService(); return { host, session, verifyEvent, verifyEventWithOpenTs, service, getNumberOfEvents }; - function verifyEvent(project: ts.server.Project, reason: string) { + function verifyEvent(project: Project, reason: string) { verifyProjectLoadEvents([ - { eventName: ts.server.ProjectLoadingStartEvent, data: { project, reason } }, - { eventName: ts.server.ProjectLoadingFinishEvent, data: { project } } + { eventName: ProjectLoadingStartEvent, data: { project, reason } }, + { eventName: ProjectLoadingFinishEvent, data: { project } } ]); clearEvents(); } - function verifyEventWithOpenTs(file: ts.projectSystem.File, configPath: string, configuredProjects: number) { - ts.projectSystem.openFilesForSession([file], session); - ts.projectSystem.checkNumberOfProjects(service, { configuredProjects }); + function verifyEventWithOpenTs(file: File, configPath: string, configuredProjects: number) { + openFilesForSession([file], session); + checkNumberOfProjects(service, { configuredProjects }); const project = service.configuredProjects.get(configPath)!; assert.isDefined(project); verifyEvent(project, `Creating possible configured project for ${file.path} to open`); @@ -50,11 +57,11 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading } it("when project is created by open file", () => { - const bTs: ts.projectSystem.File = { + const bTs: File = { path: bTsPath, content: "export class B {}" }; - const configB: ts.projectSystem.File = { + const configB: File = { path: configBPath, content: "{}" }; @@ -74,11 +81,11 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading }); it("when change is detected in an extended config file", () => { - const bTs: ts.projectSystem.File = { + const bTs: File = { path: bTsPath, content: "export class B {}" }; - const configB: ts.projectSystem.File = { + const configB: File = { path: configBPath, content: JSON.stringify({ extends: "../a/tsconfig.json", @@ -103,22 +110,22 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading }); function verify(disableSourceOfProjectReferenceRedirect?: true) { - const aDTs: ts.projectSystem.File = { - path: `${ts.tscWatch.projects}/a/a.d.ts`, + const aDTs: File = { + path: `${projects}/a/a.d.ts`, content: `export declare class A { } //# sourceMappingURL=a.d.ts.map ` }; - const aDTsMap: ts.projectSystem.File = { - path: `${ts.tscWatch.projects}/a/a.d.ts.map`, + const aDTsMap: File = { + path: `${projects}/a/a.d.ts.map`, content: `{"version":3,"file":"a.d.ts","sourceRoot":"","sources":["./a.ts"],"names":[],"mappings":"AAAA,qBAAa,CAAC;CAAI"}` }; - const bTs: ts.projectSystem.File = { + const bTs: File = { path: bTsPath, content: `import {A} from "../a/a"; new A();` }; - const configB: ts.projectSystem.File = { + const configB: File = { path: configBPath, content: JSON.stringify({ ...(disableSourceOfProjectReferenceRedirect && { @@ -133,15 +140,15 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading const { service, session, verifyEventWithOpenTs, verifyEvent } = createSessionToVerifyEvent(files.concat(aDTs, aDTsMap, bTs, configB)); verifyEventWithOpenTs(bTs, configB.path, 1); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.References, + session.executeCommandSeq({ + command: CommandTypes.References, arguments: { file: bTs.path, - ...ts.projectSystem.protocolLocationFromSubstring(bTs.content, "A()") + ...protocolLocationFromSubstring(bTs.content, "A()") } }); - ts.projectSystem.checkNumberOfProjects(service, { configuredProjects: 2 }); + checkNumberOfProjects(service, { configuredProjects: 2 }); const project = service.configuredProjects.get(configA.path)!; assert.isDefined(project); verifyEvent( @@ -154,17 +161,17 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading }); describe("with external projects and config files ", () => { - const projectFileName = `${ts.tscWatch.projects}/a/project.csproj`; + const projectFileName = `${projects}/a/project.csproj`; function createSession(lazyConfiguredProjectsFromExternalProject: boolean) { const { session, service, verifyEvent: verifyEventWorker, getNumberOfEvents } = createSessionToVerifyEvent(files); service.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject } }); service.openExternalProject({ projectFileName, - rootFiles: ts.projectSystem.toExternalFiles([aTs.path, configA.path]), + rootFiles: toExternalFiles([aTs.path, configA.path]), options: {} - } as ts.projectSystem.protocol.ExternalProject); - ts.projectSystem.checkNumberOfProjects(service, { configuredProjects: 1 }); + } as ExternalProject); + checkNumberOfProjects(service, { configuredProjects: 1 }); return { session, service, verifyEvent, getNumberOfEvents }; function verifyEvent() { @@ -183,7 +190,7 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading const { verifyEvent, getNumberOfEvents, session } = createSession(/*lazyConfiguredProjectsFromExternalProject*/ true); assert.equal(getNumberOfEvents(), 0); - ts.projectSystem.openFilesForSession([aTs], session); + openFilesForSession([aTs], session); verifyEvent(); }); @@ -199,7 +206,7 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading describe("when using event handler", () => { verifyProjectLoadingStartAndFinish(host => { - const { session, events } = ts.projectSystem.createSessionWithEventTracking(host, ts.server.ProjectLoadingStartEvent, ts.server.ProjectLoadingFinishEvent); + const { session, events } = createSessionWithEventTracking(host, ProjectLoadingStartEvent, ProjectLoadingFinishEvent); return { session, getNumberOfEvents: () => events.length, @@ -211,7 +218,7 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading describe("when using default event handler", () => { verifyProjectLoadingStartAndFinish(host => { - const { session, getEvents, clearEvents } = ts.projectSystem.createSessionWithDefaultEventHandler(host, [ts.server.ProjectLoadingStartEvent, ts.server.ProjectLoadingFinishEvent]); + const { session, getEvents, clearEvents } = createSessionWithDefaultEventHandler(host, [ProjectLoadingStartEvent, ProjectLoadingFinishEvent]); return { session, getNumberOfEvents: () => getEvents().length, @@ -219,7 +226,7 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading verifyProjectLoadEvents }; - function verifyProjectLoadEvents(expected: [ts.server.ProjectLoadingStartEvent, ts.server.ProjectLoadingFinishEvent]) { + function verifyProjectLoadEvents(expected: [ProjectLoadingStartEvent, ProjectLoadingFinishEvent]) { const actual = getEvents().map(e => ({ eventName: e.event, data: e.body })); const mappedExpected = expected.map(e => { const { project, ...rest } = e.data; diff --git a/src/testRunner/unittests/tsserver/events/projectUpdatedInBackground.ts b/src/testRunner/unittests/tsserver/events/projectUpdatedInBackground.ts index 90b4a6c98b3a3..08fc4dc3d75b3 100644 --- a/src/testRunner/unittests/tsserver/events/projectUpdatedInBackground.ts +++ b/src/testRunner/unittests/tsserver/events/projectUpdatedInBackground.ts @@ -1,61 +1,71 @@ -import * as ts from "../../../_namespaces/ts"; +import { contains, find, forEach, map } from "../../../../compiler/core"; +import { Map } from "../../../../compiler/corePublic"; +import { CompilerOptions } from "../../../../compiler/types"; +import { ProjectsUpdatedInBackgroundEvent } from "../../../../server/editorServices"; +import { ChangeRequest, OpenRequest, ProjectsUpdatedInBackgroundEventBody } from "../../../../server/protocol"; +import { CommandNames } from "../../../../server/session"; +import { + checkNumberOfProjects, checkProjectActualFiles, checkWatchedDirectories, createServerHost, + createSessionWithDefaultEventHandler, createSessionWithEventTracking, File, libFile, protocol, TestServerHost, + TestSession, +} from "../helpers"; describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { function verifyFiles(caption: string, actual: readonly string[], expected: readonly string[]) { assert.equal(actual.length, expected.length, `Incorrect number of ${caption}. Actual: ${actual} Expected: ${expected}`); - const seen = new ts.Map(); - ts.forEach(actual, f => { + const seen = new Map(); + forEach(actual, f => { assert.isFalse(seen.has(f), `${caption}: Found duplicate ${f}. Actual: ${actual} Expected: ${expected}`); seen.set(f, true); - assert.isTrue(ts.contains(expected, f), `${caption}: Expected not to contain ${f}. Actual: ${actual} Expected: ${expected}`); + assert.isTrue(contains(expected, f), `${caption}: Expected not to contain ${f}. Actual: ${actual} Expected: ${expected}`); }); } - function createVerifyInitialOpen(session: ts.projectSystem.TestSession, verifyProjectsUpdatedInBackgroundEventHandler: (events: ts.server.ProjectsUpdatedInBackgroundEvent[]) => void) { - return (file: ts.projectSystem.File) => { + function createVerifyInitialOpen(session: TestSession, verifyProjectsUpdatedInBackgroundEventHandler: (events: ProjectsUpdatedInBackgroundEvent[]) => void) { + return (file: File) => { session.executeCommandSeq({ - command: ts.server.CommandNames.Open, + command: CommandNames.Open, arguments: { file: file.path } - } as ts.projectSystem.protocol.OpenRequest); + } as OpenRequest); verifyProjectsUpdatedInBackgroundEventHandler([]); }; } interface ProjectsUpdatedInBackgroundEventVerifier { - session: ts.projectSystem.TestSession; - verifyProjectsUpdatedInBackgroundEventHandler(events: ts.server.ProjectsUpdatedInBackgroundEvent[]): void; - verifyInitialOpen(file: ts.projectSystem.File): void; + session: TestSession; + verifyProjectsUpdatedInBackgroundEventHandler(events: ProjectsUpdatedInBackgroundEvent[]): void; + verifyInitialOpen(file: File): void; } - function verifyProjectsUpdatedInBackgroundEvent(createSession: (host: ts.projectSystem.TestServerHost) => ProjectsUpdatedInBackgroundEventVerifier) { + function verifyProjectsUpdatedInBackgroundEvent(createSession: (host: TestServerHost) => ProjectsUpdatedInBackgroundEventVerifier) { it("when adding new file", () => { - const commonFile1: ts.projectSystem.File = { + const commonFile1: File = { path: "/a/b/file1.ts", content: "export var x = 10;" }; - const commonFile2: ts.projectSystem.File = { + const commonFile2: File = { path: "/a/b/file2.ts", content: "export var y = 10;" }; - const commonFile3: ts.projectSystem.File = { + const commonFile3: File = { path: "/a/b/file3.ts", content: "export var z = 10;" }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{}` }; const openFiles = [commonFile1.path]; - const host = ts.projectSystem.createServerHost([commonFile1, ts.projectSystem.libFile, configFile]); + const host = createServerHost([commonFile1, libFile, configFile]); const { verifyProjectsUpdatedInBackgroundEventHandler, verifyInitialOpen } = createSession(host); verifyInitialOpen(commonFile1); host.writeFile(commonFile2.path, commonFile2.content); host.runQueuedTimeoutCallbacks(); verifyProjectsUpdatedInBackgroundEventHandler([{ - eventName: ts.server.ProjectsUpdatedInBackgroundEvent, + eventName: ProjectsUpdatedInBackgroundEvent, data: { openFiles } @@ -64,7 +74,7 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { host.writeFile(commonFile3.path, commonFile3.content); host.runQueuedTimeoutCallbacks(); verifyProjectsUpdatedInBackgroundEventHandler([{ - eventName: ts.server.ProjectsUpdatedInBackgroundEvent, + eventName: ProjectsUpdatedInBackgroundEvent, data: { openFiles } @@ -72,26 +82,26 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { }); describe("with --out or --outFile setting", () => { - function verifyEventWithOutSettings(compilerOptions: ts.CompilerOptions = {}) { - const config: ts.projectSystem.File = { + function verifyEventWithOutSettings(compilerOptions: CompilerOptions = {}) { + const config: File = { path: "/a/tsconfig.json", content: JSON.stringify({ compilerOptions }) }; - const f1: ts.projectSystem.File = { + const f1: File = { path: "/a/a.ts", content: "export let x = 1" }; - const f2: ts.projectSystem.File = { + const f2: File = { path: "/a/b.ts", content: "export let y = 1" }; const openFiles = [f1.path]; - const files = [f1, config, ts.projectSystem.libFile]; - const host = ts.projectSystem.createServerHost(files); + const files = [f1, config, libFile]; + const host = createServerHost(files); const { verifyInitialOpen, verifyProjectsUpdatedInBackgroundEventHandler } = createSession(host); verifyInitialOpen(f1); @@ -99,7 +109,7 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { host.runQueuedTimeoutCallbacks(); verifyProjectsUpdatedInBackgroundEventHandler([{ - eventName: ts.server.ProjectsUpdatedInBackgroundEvent, + eventName: ProjectsUpdatedInBackgroundEvent, data: { openFiles } @@ -108,7 +118,7 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { host.writeFile(f2.path, "export let x = 11"); host.runQueuedTimeoutCallbacks(); verifyProjectsUpdatedInBackgroundEventHandler([{ - eventName: ts.server.ProjectsUpdatedInBackgroundEvent, + eventName: ProjectsUpdatedInBackgroundEvent, data: { openFiles } @@ -138,32 +148,32 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { /** custom config file options */ configObj?: any; /** Additional files and folders to add */ - getAdditionalFileOrFolder?(): ts.projectSystem.File[]; + getAdditionalFileOrFolder?(): File[]; /** initial list of files to reload in fs and first file in this list being the file to open */ firstReloadFileList?: string[]; } function getInitialState({ configObj = {}, getAdditionalFileOrFolder, firstReloadFileList }: InitialStateParams = {}) { - const moduleFile1: ts.projectSystem.File = { + const moduleFile1: File = { path: moduleFile1Path, content: "export function Foo() { };", }; - const file1Consumer1: ts.projectSystem.File = { + const file1Consumer1: File = { path: file1Consumer1Path, content: `import {Foo} from "./moduleFile1"; export var y = 10;`, }; - const file1Consumer2: ts.projectSystem.File = { + const file1Consumer2: File = { path: "/a/b/file1Consumer2.ts", content: `import {Foo} from "./moduleFile1"; let z = 10;`, }; - const moduleFile2: ts.projectSystem.File = { + const moduleFile2: File = { path: "/a/b/moduleFile2.ts", content: `export var Foo4 = 10;`, }; - const globalFile3: ts.projectSystem.File = { + const globalFile3: File = { path: "/a/b/globalFile3.ts", content: `interface GlobalFoo { age: number }` }; @@ -174,10 +184,10 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { content: JSON.stringify(configObj || { compilerOptions: {} }) }; - const files: ts.projectSystem.File[] = [file1Consumer1, moduleFile1, file1Consumer2, moduleFile2, ...additionalFiles, globalFile3, ts.projectSystem.libFile, configFile]; + const files: File[] = [file1Consumer1, moduleFile1, file1Consumer2, moduleFile2, ...additionalFiles, globalFile3, libFile, configFile]; const filesToReload = firstReloadFileList && getFiles(firstReloadFileList) || files; - const host = ts.projectSystem.createServerHost([filesToReload[0], configFile]); + const host = createServerHost([filesToReload[0], configFile]); // Initial project creation const { session, verifyProjectsUpdatedInBackgroundEventHandler, verifyInitialOpen } = createSession(host); @@ -198,11 +208,11 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { }; function getFiles(filelist: string[]) { - return ts.map(filelist, getFile); + return map(filelist, getFile); } function getFile(fileName: string) { - return ts.find(files, file => file.path === fileName)!; + return find(files, file => file.path === fileName)!; } function verifyNoProjectsUpdatedInBackgroundEvent() { @@ -213,16 +223,16 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { function verifyProjectsUpdatedInBackgroundEvent() { host.runQueuedTimeoutCallbacks(); verifyProjectsUpdatedInBackgroundEventHandler([{ - eventName: ts.server.ProjectsUpdatedInBackgroundEvent, + eventName: ProjectsUpdatedInBackgroundEvent, data: { openFiles } }]); } - function updateContentOfOpenFile(file: ts.projectSystem.File, newContent: string) { - session.executeCommandSeq({ - command: ts.server.CommandNames.Change, + function updateContentOfOpenFile(file: File, newContent: string) { + session.executeCommandSeq({ + command: CommandNames.Change, arguments: { file: file.path, insertString: newContent, @@ -335,7 +345,7 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { }); it("should return cascaded affected file list", () => { - const file1Consumer1Consumer1: ts.projectSystem.File = { + const file1Consumer1Consumer1: File = { path: "/a/b/file1Consumer1Consumer1.ts", content: `import {y} from "./file1Consumer1";` }; @@ -357,13 +367,13 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { }); it("should work fine for files with circular references", () => { - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/b/file1.ts", content: ` /// export var t1 = 10;` }; - const file2: ts.projectSystem.File = { + const file2: File = { path: "/a/b/file2.ts", content: ` /// @@ -371,7 +381,7 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { }; const { host, verifyProjectsUpdatedInBackgroundEvent } = getInitialState({ getAdditionalFileOrFolder: () => [file1, file2], - firstReloadFileList: [file1.path, ts.projectSystem.libFile.path, file2.path, configFilePath] + firstReloadFileList: [file1.path, libFile.path, file2.path, configFilePath] }); host.writeFile(file2.path, file2.content + "export var t3 = 10;"); @@ -379,7 +389,7 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { }); it("should detect removed code file", () => { - const referenceFile1: ts.projectSystem.File = { + const referenceFile1: File = { path: "/a/b/referenceFile1.ts", content: ` /// @@ -387,7 +397,7 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { }; const { host, verifyProjectsUpdatedInBackgroundEvent } = getInitialState({ getAdditionalFileOrFolder: () => [referenceFile1], - firstReloadFileList: [referenceFile1.path, ts.projectSystem.libFile.path, moduleFile1Path, configFilePath] + firstReloadFileList: [referenceFile1.path, libFile.path, moduleFile1Path, configFilePath] }); host.deleteFile(moduleFile1Path); @@ -395,7 +405,7 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { }); it("should detect non-existing code file", () => { - const referenceFile1: ts.projectSystem.File = { + const referenceFile1: File = { path: "/a/b/referenceFile1.ts", content: ` /// @@ -403,7 +413,7 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { }; const { host, moduleFile2, updateContentOfOpenFile, verifyNoProjectsUpdatedInBackgroundEvent, verifyProjectsUpdatedInBackgroundEvent } = getInitialState({ getAdditionalFileOrFolder: () => [referenceFile1], - firstReloadFileList: [referenceFile1.path, ts.projectSystem.libFile.path, configFilePath] + firstReloadFileList: [referenceFile1.path, libFile.path, configFilePath] }); updateContentOfOpenFile(referenceFile1, referenceFile1.content + "export var yy = Foo();"); @@ -418,35 +428,35 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { describe("resolution when resolution cache size", () => { function verifyWithMaxCacheLimit(useSlashRootAsSomeNotRootFolderInUserDirectory: boolean) { const rootFolder = useSlashRootAsSomeNotRootFolderInUserDirectory ? "/user/username/rootfolder/otherfolder/" : "/"; - const file1: ts.projectSystem.File = { + const file1: File = { path: rootFolder + "a/b/project/file1.ts", content: 'import a from "file2"' }; - const file2: ts.projectSystem.File = { + const file2: File = { path: rootFolder + "a/b/node_modules/file2.d.ts", content: "export class a { }" }; - const file3: ts.projectSystem.File = { + const file3: File = { path: rootFolder + "a/b/project/file3.ts", content: "export class c { }" }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: rootFolder + "a/b/project/tsconfig.json", content: JSON.stringify({ compilerOptions: { typeRoots: [] } }) }; - const projectFiles = [file1, file3, ts.projectSystem.libFile, configFile]; + const projectFiles = [file1, file3, libFile, configFile]; const openFiles = [file1.path]; const watchedRecursiveDirectories = useSlashRootAsSomeNotRootFolderInUserDirectory ? // Folders of node_modules lookup not in changedRoot ["a/b/project", "a/b/project/node_modules", "a/b/node_modules", "a/node_modules", "node_modules"].map(v => rootFolder + v) : // Folder of tsconfig ["/a/b/project", "/a/b/project/node_modules"]; - const host = ts.projectSystem.createServerHost(projectFiles); + const host = createServerHost(projectFiles); const { session, verifyInitialOpen, verifyProjectsUpdatedInBackgroundEventHandler } = createSession(host); const projectService = session.getProjectService(); verifyInitialOpen(file1); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); const project = projectService.configuredProjects.get(configFile.path)!; verifyProject(); @@ -457,7 +467,7 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { // Since this is first event verifyProject(); verifyProjectsUpdatedInBackgroundEventHandler([{ - eventName: ts.server.ProjectsUpdatedInBackgroundEvent, + eventName: ProjectsUpdatedInBackgroundEvent, data: { openFiles } @@ -478,16 +488,16 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { verifyProject(); verifyProjectsUpdatedInBackgroundEventHandler(useSlashRootAsSomeNotRootFolderInUserDirectory ? [{ - eventName: ts.server.ProjectsUpdatedInBackgroundEvent, + eventName: ProjectsUpdatedInBackgroundEvent, data: { openFiles } }] : []); function verifyProject() { - ts.projectSystem.checkProjectActualFiles(project, ts.map(projectFiles, file => file.path)); - ts.projectSystem.checkWatchedDirectories(host, [], /*recursive*/ false); - ts.projectSystem.checkWatchedDirectories(host, watchedRecursiveDirectories, /*recursive*/ true); + checkProjectActualFiles(project, map(projectFiles, file => file.path)); + checkWatchedDirectories(host, [], /*recursive*/ false); + checkWatchedDirectories(host, watchedRecursiveDirectories, /*recursive*/ true); } } @@ -504,25 +514,25 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { describe("when event handler is set in the session", () => { verifyProjectsUpdatedInBackgroundEvent(createSessionWithProjectChangedEventHandler); - function createSessionWithProjectChangedEventHandler(host: ts.projectSystem.TestServerHost): ProjectsUpdatedInBackgroundEventVerifier { - const { session, events: projectChangedEvents } = ts.projectSystem.createSessionWithEventTracking(host, ts.server.ProjectsUpdatedInBackgroundEvent); + function createSessionWithProjectChangedEventHandler(host: TestServerHost): ProjectsUpdatedInBackgroundEventVerifier { + const { session, events: projectChangedEvents } = createSessionWithEventTracking(host, ProjectsUpdatedInBackgroundEvent); return { session, verifyProjectsUpdatedInBackgroundEventHandler, verifyInitialOpen: createVerifyInitialOpen(session, verifyProjectsUpdatedInBackgroundEventHandler) }; - function eventToString(event: ts.server.ProjectsUpdatedInBackgroundEvent) { + function eventToString(event: ProjectsUpdatedInBackgroundEvent) { return JSON.stringify(event && { eventName: event.eventName, data: event.data }); } - function eventsToString(events: readonly ts.server.ProjectsUpdatedInBackgroundEvent[]) { - return "[" + ts.map(events, eventToString).join(",") + "]"; + function eventsToString(events: readonly ProjectsUpdatedInBackgroundEvent[]) { + return "[" + map(events, eventToString).join(",") + "]"; } - function verifyProjectsUpdatedInBackgroundEventHandler(expectedEvents: readonly ts.server.ProjectsUpdatedInBackgroundEvent[]) { + function verifyProjectsUpdatedInBackgroundEventHandler(expectedEvents: readonly ProjectsUpdatedInBackgroundEvent[]) { assert.equal(projectChangedEvents.length, expectedEvents.length, `Incorrect number of events Actual: ${eventsToString(projectChangedEvents)} Expected: ${eventsToString(expectedEvents)}`); - ts.forEach(projectChangedEvents, (actualEvent, i) => { + forEach(projectChangedEvents, (actualEvent, i) => { const expectedEvent = expectedEvents[i]; assert.strictEqual(actualEvent.eventName, expectedEvent.eventName); verifyFiles("openFiles", actualEvent.data.openFiles, expectedEvent.data.openFiles); @@ -544,8 +554,8 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { }); - function createSessionThatUsesEvents(host: ts.projectSystem.TestServerHost, noGetErrOnBackgroundUpdate?: boolean): ProjectsUpdatedInBackgroundEventVerifier { - const { session, getEvents, clearEvents } = ts.projectSystem.createSessionWithDefaultEventHandler(host, ts.server.ProjectsUpdatedInBackgroundEvent, { noGetErrOnBackgroundUpdate }); + function createSessionThatUsesEvents(host: TestServerHost, noGetErrOnBackgroundUpdate?: boolean): ProjectsUpdatedInBackgroundEventVerifier { + const { session, getEvents, clearEvents } = createSessionWithDefaultEventHandler(host, ProjectsUpdatedInBackgroundEvent, { noGetErrOnBackgroundUpdate }); return { session, @@ -553,15 +563,15 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => { verifyInitialOpen: createVerifyInitialOpen(session, verifyProjectsUpdatedInBackgroundEventHandler) }; - function verifyProjectsUpdatedInBackgroundEventHandler(expected: readonly ts.server.ProjectsUpdatedInBackgroundEvent[]) { - const expectedEvents: ts.projectSystem.protocol.ProjectsUpdatedInBackgroundEventBody[] = ts.map(expected, e => { + function verifyProjectsUpdatedInBackgroundEventHandler(expected: readonly ProjectsUpdatedInBackgroundEvent[]) { + const expectedEvents: ProjectsUpdatedInBackgroundEventBody[] = map(expected, e => { return { openFiles: e.data.openFiles }; }); const events = getEvents(); - assert.equal(events.length, expectedEvents.length, `Incorrect number of events Actual: ${ts.map(events, e => e.body)} Expected: ${expectedEvents}`); - ts.forEach(events, (actualEvent, i) => { + assert.equal(events.length, expectedEvents.length, `Incorrect number of events Actual: ${map(events, e => e.body)} Expected: ${expectedEvents}`); + forEach(events, (actualEvent, i) => { const expectedEvent = expectedEvents[i]; verifyFiles("openFiles", actualEvent.body.openFiles, expectedEvent.openFiles); }); diff --git a/src/testRunner/unittests/tsserver/exportMapCache.ts b/src/testRunner/unittests/tsserver/exportMapCache.ts index 2f201f4f11ff8..0d1d1568f8c64 100644 --- a/src/testRunner/unittests/tsserver/exportMapCache.ts +++ b/src/testRunner/unittests/tsserver/exportMapCache.ts @@ -1,34 +1,43 @@ -import * as ts from "../../_namespaces/ts"; +import { getSymbolId } from "../../../compiler/checker"; +import { returnTrue } from "../../../compiler/core"; +import { Path, SymbolFlags } from "../../../compiler/types"; +import { + CommandTypes, CompletionInfoResponse, CompletionsRequest, FileLocationRequestArgs, UpdateOpenRequest, +} from "../../../server/protocol"; +import { SymbolExportInfo } from "../../../services/exportInfoMap"; +import { + configuredProjectAt, createServerHost, createSession, executeSessionRequest, File, openFilesForSession, +} from "./helpers"; -const packageJson: ts.projectSystem.File = { +const packageJson: File = { path: "/package.json", content: `{ "dependencies": { "mobx": "*" } }` }; -const aTs: ts.projectSystem.File = { +const aTs: File = { path: "/a.ts", content: "export const foo = 0;", }; -const bTs: ts.projectSystem.File = { +const bTs: File = { path: "/b.ts", content: "foo", }; -const tsconfig: ts.projectSystem.File = { +const tsconfig: File = { path: "/tsconfig.json", content: "{}", }; -const ambientDeclaration: ts.projectSystem.File = { +const ambientDeclaration: File = { path: "/ambient.d.ts", content: "declare module 'ambient' {}" }; -const mobxPackageJson: ts.projectSystem.File = { +const mobxPackageJson: File = { path: "/node_modules/mobx/package.json", content: `{ "name": "mobx", "version": "1.0.0" }` }; -const mobxDts: ts.projectSystem.File = { +const mobxDts: File = { path: "/node_modules/mobx/index.d.ts", content: "export declare function observable(): unknown;" }; -const exportEqualsMappedType: ts.projectSystem.File = { +const exportEqualsMappedType: File = { path: "/lib/foo/constants.d.ts", content: ` type Signals = "SIGINT" | "SIGABRT"; @@ -39,7 +48,7 @@ const exportEqualsMappedType: ts.projectSystem.File = { describe("unittests:: tsserver:: exportMapCache", () => { it("caches auto-imports in the same file", () => { const { exportMapCache } = setup(); - assert.ok(exportMapCache.isUsableByFile(bTs.path as ts.Path)); + assert.ok(exportMapCache.isUsableByFile(bTs.path as Path)); assert.ok(!exportMapCache.isEmpty()); }); @@ -47,7 +56,7 @@ describe("unittests:: tsserver:: exportMapCache", () => { const { host, exportMapCache } = setup(); host.writeFile("/src/a2.ts", aTs.content); host.runQueuedTimeoutCallbacks(); - assert.ok(!exportMapCache.isUsableByFile(bTs.path as ts.Path)); + assert.ok(!exportMapCache.isUsableByFile(bTs.path as Path)); assert.ok(exportMapCache.isEmpty()); }); @@ -56,7 +65,7 @@ describe("unittests:: tsserver:: exportMapCache", () => { projectService.closeClientFile(aTs.path); host.deleteFile(aTs.path); host.runQueuedTimeoutCallbacks(); - assert.ok(!exportMapCache.isUsableByFile(bTs.path as ts.Path)); + assert.ok(!exportMapCache.isUsableByFile(bTs.path as Path)); assert.ok(exportMapCache.isEmpty()); }); @@ -65,7 +74,7 @@ describe("unittests:: tsserver:: exportMapCache", () => { host.writeFile("/package.json", `{ "name": "blah", "dependencies": { "mobx": "*" } }`); host.runQueuedTimeoutCallbacks(); project.getPackageJsonAutoImportProvider(); - assert.ok(exportMapCache.isUsableByFile(bTs.path as ts.Path)); + assert.ok(exportMapCache.isUsableByFile(bTs.path as Path)); assert.ok(!exportMapCache.isEmpty()); }); @@ -74,7 +83,7 @@ describe("unittests:: tsserver:: exportMapCache", () => { host.writeFile("/package.json", `{}`); host.runQueuedTimeoutCallbacks(); project.getPackageJsonAutoImportProvider(); - assert.ok(!exportMapCache.isUsableByFile(bTs.path as ts.Path)); + assert.ok(!exportMapCache.isUsableByFile(bTs.path as Path)); assert.ok(exportMapCache.isEmpty()); }); @@ -87,17 +96,17 @@ describe("unittests:: tsserver:: exportMapCache", () => { // accessing a transient symbol with two different checkers results in different symbol identities, since // transient symbols are recreated with every new checker. const programBefore = project.getCurrentProgram()!; - let sigintPropBefore: readonly ts.SymbolExportInfo[] | undefined; - exportMapCache.search(bTs.path as ts.Path, /*preferCapitalized*/ false, ts.returnTrue, (info, symbolName) => { + let sigintPropBefore: readonly SymbolExportInfo[] | undefined; + exportMapCache.search(bTs.path as Path, /*preferCapitalized*/ false, returnTrue, (info, symbolName) => { if (symbolName === "SIGINT") sigintPropBefore = info; }); assert.ok(sigintPropBefore); - assert.ok(sigintPropBefore![0].symbol.flags & ts.SymbolFlags.Transient); - const symbolIdBefore = ts.getSymbolId(sigintPropBefore![0].symbol); + assert.ok(sigintPropBefore![0].symbol.flags & SymbolFlags.Transient); + const symbolIdBefore = getSymbolId(sigintPropBefore![0].symbol); // Update program without clearing cache - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.UpdateOpen, + session.executeCommandSeq({ + command: CommandTypes.UpdateOpen, arguments: { changedFiles: [{ fileName: bTs.path, @@ -113,32 +122,32 @@ describe("unittests:: tsserver:: exportMapCache", () => { assert.notEqual(programBefore, project.getCurrentProgram()!); // Get same info from cache again - let sigintPropAfter: readonly ts.SymbolExportInfo[] | undefined; - exportMapCache.search(bTs.path as ts.Path, /*preferCapitalized*/ false, ts.returnTrue, (info, symbolName) => { + let sigintPropAfter: readonly SymbolExportInfo[] | undefined; + exportMapCache.search(bTs.path as Path, /*preferCapitalized*/ false, returnTrue, (info, symbolName) => { if (symbolName === "SIGINT") sigintPropAfter = info; }); assert.ok(sigintPropAfter); - assert.notEqual(symbolIdBefore, ts.getSymbolId(sigintPropAfter![0].symbol)); + assert.notEqual(symbolIdBefore, getSymbolId(sigintPropAfter![0].symbol)); }); }); function setup() { - const host = ts.projectSystem.createServerHost([aTs, bTs, ambientDeclaration, tsconfig, packageJson, mobxPackageJson, mobxDts, exportEqualsMappedType]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([aTs, bTs], session); + const host = createServerHost([aTs, bTs, ambientDeclaration, tsconfig, packageJson, mobxPackageJson, mobxDts, exportEqualsMappedType]); + const session = createSession(host); + openFilesForSession([aTs, bTs], session); const projectService = session.getProjectService(); - const project = ts.projectSystem.configuredProjectAt(projectService, 0); + const project = configuredProjectAt(projectService, 0); triggerCompletions(); const checker = project.getLanguageService().getProgram()!.getTypeChecker(); return { host, project, projectService, session, exportMapCache: project.getCachedExportInfoMap(), checker, triggerCompletions }; function triggerCompletions() { - const requestLocation: ts.projectSystem.protocol.FileLocationRequestArgs = { + const requestLocation: FileLocationRequestArgs = { file: bTs.path, line: 1, offset: 3, }; - ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.CompletionInfo, { + executeSessionRequest(session, CommandTypes.CompletionInfo, { ...requestLocation, includeExternalModuleExports: true, prefix: "foo", diff --git a/src/testRunner/unittests/tsserver/externalProjects.ts b/src/testRunner/unittests/tsserver/externalProjects.ts index 55f705af6a709..a8595fc5346fd 100644 --- a/src/testRunner/unittests/tsserver/externalProjects.ts +++ b/src/testRunner/unittests/tsserver/externalProjects.ts @@ -1,5 +1,20 @@ -import * as Harness from "../../_namespaces/Harness"; -import * as ts from "../../_namespaces/ts"; +import { arrayIterator, createGetCanonicalFileName, emptyArray, map, singleIterator } from "../../../compiler/core"; +import { combinePaths, getBaseFileName, getDirectoryPath, toPath } from "../../../compiler/path"; +import { DiagnosticCategory, ModuleResolutionKind, ScriptKind, SourceFile } from "../../../compiler/types"; +import { ConfigFileProgramReloadLevel } from "../../../compiler/watchUtilities"; +import { makeDefaultProxy } from "../../../harness/harnessLanguageService"; +import { maxProgramSizeForNonTsFiles } from "../../../server/editorServices"; +import { PluginCreateInfo } from "../../../server/project"; +import { + Diagnostic, ExternalProject, OpenExternalProjectsRequest, SemanticDiagnosticsSyncRequest, +} from "../../../server/protocol"; +import { projectRoot } from "../tscWatch/helpers"; +import { verifyDynamic } from "./dynamicFiles"; +import { + checkNumberOfExternalProjects, checkNumberOfInferredProjects, checkNumberOfProjects, checkProjectActualFiles, + checkProjectRootFiles, configuredProjectAt, createProjectService, createServerHost, createSession, File, libFile, + toExternalFile, toExternalFiles, +} from "./helpers"; describe("unittests:: tsserver:: ExternalProjects", () => { describe("can handle tsconfig file name with difference casing", () => { @@ -15,32 +30,32 @@ describe("unittests:: tsserver:: ExternalProjects", () => { }) }; - const host = ts.projectSystem.createServerHost([f1, config], { useCaseSensitiveFileNames: false }); - const service = ts.projectSystem.createProjectService(host); + const host = createServerHost([f1, config], { useCaseSensitiveFileNames: false }); + const service = createProjectService(host); service.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject } }); - const upperCaseConfigFilePath = ts.combinePaths(ts.getDirectoryPath(config.path).toUpperCase(), ts.getBaseFileName(config.path)); + const upperCaseConfigFilePath = combinePaths(getDirectoryPath(config.path).toUpperCase(), getBaseFileName(config.path)); service.openExternalProject({ projectFileName: "/a/b/project.csproj", - rootFiles: ts.projectSystem.toExternalFiles([f1.path, upperCaseConfigFilePath]), + rootFiles: toExternalFiles([f1.path, upperCaseConfigFilePath]), options: {} - } as ts.projectSystem.protocol.ExternalProject); + } as ExternalProject); service.checkNumberOfProjects({ configuredProjects: 1 }); const project = service.configuredProjects.get(config.path)!; if (lazyConfiguredProjectsFromExternalProject) { - assert.equal(project.pendingReload, ts.ConfigFileProgramReloadLevel.Full); // External project referenced configured project pending to be reloaded - ts.projectSystem.checkProjectActualFiles(project, ts.emptyArray); + assert.equal(project.pendingReload, ConfigFileProgramReloadLevel.Full); // External project referenced configured project pending to be reloaded + checkProjectActualFiles(project, emptyArray); } else { - assert.equal(project.pendingReload, ts.ConfigFileProgramReloadLevel.None); // External project referenced configured project loaded - ts.projectSystem.checkProjectActualFiles(project, [upperCaseConfigFilePath]); + assert.equal(project.pendingReload, ConfigFileProgramReloadLevel.None); // External project referenced configured project loaded + checkProjectActualFiles(project, [upperCaseConfigFilePath]); } service.openClientFile(f1.path); service.checkNumberOfProjects({ configuredProjects: 1, inferredProjects: 1 }); - assert.equal(project.pendingReload, ts.ConfigFileProgramReloadLevel.None); // External project referenced configured project is updated - ts.projectSystem.checkProjectActualFiles(project, [upperCaseConfigFilePath]); - ts.projectSystem.checkProjectActualFiles(service.inferredProjects[0], [f1.path]); + assert.equal(project.pendingReload, ConfigFileProgramReloadLevel.None); // External project referenced configured project is updated + checkProjectActualFiles(project, [upperCaseConfigFilePath]); + checkProjectActualFiles(service.inferredProjects[0], [f1.path]); } it("when lazyConfiguredProjectsFromExternalProject not set", () => { @@ -57,20 +72,20 @@ describe("unittests:: tsserver:: ExternalProjects", () => { path: "/a/file1.ts", content: "let x = [1, 2];" }; - const p1 = { projectFileName: "/a/proj1.csproj", rootFiles: [ts.projectSystem.toExternalFile(f1.path)], options: {} }; + const p1 = { projectFileName: "/a/proj1.csproj", rootFiles: [toExternalFile(f1.path)], options: {} }; - const host = ts.projectSystem.createServerHost([f1]); + const host = createServerHost([f1]); host.require = (_initialPath, moduleName) => { assert.equal(moduleName, "myplugin"); return { module: () => ({ - create(info: ts.server.PluginCreateInfo) { - const proxy = Harness.LanguageService.makeDefaultProxy(info); + create(info: PluginCreateInfo) { + const proxy = makeDefaultProxy(info); proxy.getSemanticDiagnostics = filename => { const prev = info.languageService.getSemanticDiagnostics(filename); - const sourceFile: ts.SourceFile = info.project.getSourceFile(ts.toPath(filename, /*basePath*/ undefined, ts.createGetCanonicalFileName(info.serverHost.useCaseSensitiveFileNames)))!; + const sourceFile: SourceFile = info.project.getSourceFile(toPath(filename, /*basePath*/ undefined, createGetCanonicalFileName(info.serverHost.useCaseSensitiveFileNames)))!; prev.push({ - category: ts.DiagnosticCategory.Warning, + category: DiagnosticCategory.Warning, file: sourceFile, code: 9999, length: 3, @@ -85,17 +100,17 @@ describe("unittests:: tsserver:: ExternalProjects", () => { error: undefined }; }; - const session = ts.projectSystem.createSession(host, { globalPlugins: ["myplugin"] }); + const session = createSession(host, { globalPlugins: ["myplugin"] }); session.executeCommand({ seq: 1, type: "request", command: "openExternalProjects", arguments: { projects: [p1] } - } as ts.projectSystem.protocol.OpenExternalProjectsRequest); + } as OpenExternalProjectsRequest); const projectService = session.getProjectService(); - ts.projectSystem.checkNumberOfProjects(projectService, { externalProjects: 1 }); + checkNumberOfProjects(projectService, { externalProjects: 1 }); assert.equal(projectService.externalProjects[0].getProjectName(), p1.projectFileName); const handlerResponse = session.executeCommand({ @@ -106,10 +121,10 @@ describe("unittests:: tsserver:: ExternalProjects", () => { file: f1.path, projectFileName: p1.projectFileName } - } as ts.projectSystem.protocol.SemanticDiagnosticsSyncRequest); + } as SemanticDiagnosticsSyncRequest); assert.isDefined(handlerResponse.response); - const response = handlerResponse.response as ts.projectSystem.protocol.Diagnostic[]; + const response = handlerResponse.response as Diagnostic[]; assert.equal(response.length, 1); assert.equal(response[0].text, "Plugin diagnostic"); }); @@ -127,23 +142,23 @@ describe("unittests:: tsserver:: ExternalProjects", () => { path: "/c/app.ts", content: "let x = 1" }; - const makeProject = (f: ts.projectSystem.File) => ({ projectFileName: f.path + ".csproj", rootFiles: [ts.projectSystem.toExternalFile(f.path)], options: {} }); + const makeProject = (f: File) => ({ projectFileName: f.path + ".csproj", rootFiles: [toExternalFile(f.path)], options: {} }); const p1 = makeProject(f1); const p2 = makeProject(f2); const p3 = makeProject(f3); - const host = ts.projectSystem.createServerHost([f1, f2, f3]); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([f1, f2, f3]); + const session = createSession(host); session.executeCommand({ seq: 1, type: "request", command: "openExternalProjects", arguments: { projects: [p1, p2] } - } as ts.projectSystem.protocol.OpenExternalProjectsRequest); + } as OpenExternalProjectsRequest); const projectService = session.getProjectService(); - ts.projectSystem.checkNumberOfProjects(projectService, { externalProjects: 2 }); + checkNumberOfProjects(projectService, { externalProjects: 2 }); assert.equal(projectService.externalProjects[0].getProjectName(), p1.projectFileName); assert.equal(projectService.externalProjects[1].getProjectName(), p2.projectFileName); @@ -152,8 +167,8 @@ describe("unittests:: tsserver:: ExternalProjects", () => { type: "request", command: "openExternalProjects", arguments: { projects: [p1, p3] } - } as ts.projectSystem.protocol.OpenExternalProjectsRequest); - ts.projectSystem.checkNumberOfProjects(projectService, { externalProjects: 2 }); + } as OpenExternalProjectsRequest); + checkNumberOfProjects(projectService, { externalProjects: 2 }); assert.equal(projectService.externalProjects[0].getProjectName(), p1.projectFileName); assert.equal(projectService.externalProjects[1].getProjectName(), p3.projectFileName); @@ -162,15 +177,15 @@ describe("unittests:: tsserver:: ExternalProjects", () => { type: "request", command: "openExternalProjects", arguments: { projects: [] } - } as ts.projectSystem.protocol.OpenExternalProjectsRequest); - ts.projectSystem.checkNumberOfProjects(projectService, { externalProjects: 0 }); + } as OpenExternalProjectsRequest); + checkNumberOfProjects(projectService, { externalProjects: 0 }); session.executeCommand({ seq: 3, type: "request", command: "openExternalProjects", arguments: { projects: [p2] } - } as ts.projectSystem.protocol.OpenExternalProjectsRequest); + } as OpenExternalProjectsRequest); assert.equal(projectService.externalProjects[0].getProjectName(), p2.projectFileName); }); @@ -184,67 +199,67 @@ describe("unittests:: tsserver:: ExternalProjects", () => { content: "let y =1;" }; const externalProjectName = "externalproject"; - const host = ts.projectSystem.createServerHost([file1, file2]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2]); + const projectService = createProjectService(host); projectService.openExternalProject({ - rootFiles: ts.projectSystem.toExternalFiles([file1.path, file2.path]), + rootFiles: toExternalFiles([file1.path, file2.path]), options: {}, projectFileName: externalProjectName }); - ts.projectSystem.checkNumberOfExternalProjects(projectService, 1); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 0); + checkNumberOfExternalProjects(projectService, 1); + checkNumberOfInferredProjects(projectService, 0); // open client file - should not lead to creation of inferred project projectService.openClientFile(file1.path, file1.content); - ts.projectSystem.checkNumberOfExternalProjects(projectService, 1); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 0); + checkNumberOfExternalProjects(projectService, 1); + checkNumberOfInferredProjects(projectService, 0); // close client file - external project should still exists projectService.closeClientFile(file1.path); - ts.projectSystem.checkNumberOfExternalProjects(projectService, 1); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 0); + checkNumberOfExternalProjects(projectService, 1); + checkNumberOfInferredProjects(projectService, 0); projectService.closeExternalProject(externalProjectName); - ts.projectSystem.checkNumberOfExternalProjects(projectService, 0); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 0); + checkNumberOfExternalProjects(projectService, 0); + checkNumberOfInferredProjects(projectService, 0); }); it("external project for dynamic file", () => { const externalProjectName = "^ScriptDocument1 file1.ts"; - const externalFiles = ts.projectSystem.toExternalFiles(["^ScriptDocument1 file1.ts"]); - const host = ts.projectSystem.createServerHost([]); - const projectService = ts.projectSystem.createProjectService(host); + const externalFiles = toExternalFiles(["^ScriptDocument1 file1.ts"]); + const host = createServerHost([]); + const projectService = createProjectService(host); projectService.openExternalProject({ rootFiles: externalFiles, options: {}, projectFileName: externalProjectName }); - ts.projectSystem.checkNumberOfExternalProjects(projectService, 1); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 0); - ts.projectSystem.verifyDynamic(projectService, "/^scriptdocument1 file1.ts"); + checkNumberOfExternalProjects(projectService, 1); + checkNumberOfInferredProjects(projectService, 0); + verifyDynamic(projectService, "/^scriptdocument1 file1.ts"); externalFiles[0].content = "let x =1;"; - projectService.applyChangesInOpenFiles(ts.arrayIterator(externalFiles)); + projectService.applyChangesInOpenFiles(arrayIterator(externalFiles)); }); it("when file name starts with ^", () => { - const file: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/file.ts`, + const file: File = { + path: `${projectRoot}/file.ts`, content: "const x = 10;" }; - const app: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/^app.ts`, + const app: File = { + path: `${projectRoot}/^app.ts`, content: "const y = 10;" }; - const host = ts.projectSystem.createServerHost([file, app, ts.projectSystem.libFile]); - const service = ts.projectSystem.createProjectService(host); + const host = createServerHost([file, app, libFile]); + const service = createProjectService(host); service.openExternalProjects([{ - projectFileName: `${ts.tscWatch.projectRoot}/myproject.njsproj`, + projectFileName: `${projectRoot}/myproject.njsproj`, rootFiles: [ - ts.projectSystem.toExternalFile(file.path), - ts.projectSystem.toExternalFile(app.path) + toExternalFile(file.path), + toExternalFile(app.path) ], options: { }, }]); @@ -282,15 +297,15 @@ describe("unittests:: tsserver:: ExternalProjects", () => { content: "let z =1;" }; const externalProjectName = "externalproject"; - const host = ts.projectSystem.createServerHost([file1, file2, file3, config1, config2]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2, file3, config1, config2]); + const projectService = createProjectService(host); projectService.openExternalProject({ - rootFiles: ts.projectSystem.toExternalFiles([config1.path, config2.path, file3.path]), + rootFiles: toExternalFiles([config1.path, config2.path, file3.path]), options: {}, projectFileName: externalProjectName }); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 2 }); + checkNumberOfProjects(projectService, { configuredProjects: 2 }); const proj1 = projectService.configuredProjects.get(config1.path); const proj2 = projectService.configuredProjects.get(config2.path); assert.isDefined(proj1); @@ -298,35 +313,35 @@ describe("unittests:: tsserver:: ExternalProjects", () => { // open client file - should not lead to creation of inferred project projectService.openClientFile(file1.path, file1.content); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 2 }); + checkNumberOfProjects(projectService, { configuredProjects: 2 }); assert.strictEqual(projectService.configuredProjects.get(config1.path), proj1); assert.strictEqual(projectService.configuredProjects.get(config2.path), proj2); projectService.openClientFile(file3.path, file3.content); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 2, inferredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 2, inferredProjects: 1 }); assert.strictEqual(projectService.configuredProjects.get(config1.path), proj1); assert.strictEqual(projectService.configuredProjects.get(config2.path), proj2); projectService.closeExternalProject(externalProjectName); // open file 'file1' from configured project keeps project alive - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 1 }); assert.strictEqual(projectService.configuredProjects.get(config1.path), proj1); assert.isUndefined(projectService.configuredProjects.get(config2.path)); projectService.closeClientFile(file3.path); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 1 }); assert.strictEqual(projectService.configuredProjects.get(config1.path), proj1); assert.isUndefined(projectService.configuredProjects.get(config2.path)); assert.isTrue(projectService.inferredProjects[0].isOrphan()); projectService.closeClientFile(file1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1, inferredProjects: 1 }); assert.strictEqual(projectService.configuredProjects.get(config1.path), proj1); assert.isUndefined(projectService.configuredProjects.get(config2.path)); assert.isTrue(projectService.inferredProjects[0].isOrphan()); projectService.openClientFile(file2.path, file2.content); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); assert.isUndefined(projectService.configuredProjects.get(config1.path)); assert.isDefined(projectService.configuredProjects.get(config2.path)); }); @@ -341,26 +356,26 @@ describe("unittests:: tsserver:: ExternalProjects", () => { content: JSON.stringify({ compilerOptions: {} }) }; const externalProjectName = "externalproject"; - const host = ts.projectSystem.createServerHost([file1, configFile]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, configFile]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); projectService.openExternalProject({ - rootFiles: ts.projectSystem.toExternalFiles([configFile.path]), + rootFiles: toExternalFiles([configFile.path]), options: {}, projectFileName: externalProjectName }); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); projectService.closeClientFile(file1.path); // configured project is alive since it is opened as part of external project - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); projectService.closeExternalProject(externalProjectName); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 0 }); + checkNumberOfProjects(projectService, { configuredProjects: 0 }); }); it("external project with included config file opened after configured project and then closed", () => { @@ -377,33 +392,33 @@ describe("unittests:: tsserver:: ExternalProjects", () => { content: JSON.stringify({ compilerOptions: {} }) }; const externalProjectName = "externalproject"; - const host = ts.projectSystem.createServerHost([file1, file2, ts.projectSystem.libFile, configFile]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2, libFile, configFile]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); const project = projectService.configuredProjects.get(configFile.path); projectService.openExternalProject({ - rootFiles: ts.projectSystem.toExternalFiles([configFile.path]), + rootFiles: toExternalFiles([configFile.path]), options: {}, projectFileName: externalProjectName }); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); assert.strictEqual(projectService.configuredProjects.get(configFile.path), project); projectService.closeExternalProject(externalProjectName); // configured project is alive since file is still open - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); assert.strictEqual(projectService.configuredProjects.get(configFile.path), project); projectService.closeClientFile(file1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); assert.strictEqual(projectService.configuredProjects.get(configFile.path), project); projectService.openClientFile(file2.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); assert.isUndefined(projectService.configuredProjects.get(configFile.path)); }); @@ -416,16 +431,16 @@ describe("unittests:: tsserver:: ExternalProjects", () => { path: "/a/b/f2.ts", content: "let y = 1" }; - const host = ts.projectSystem.createServerHost([file1, file2]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2]); + const projectService = createProjectService(host); - projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: ts.projectSystem.toExternalFiles([file1.path]) }); - ts.projectSystem.checkNumberOfProjects(projectService, { externalProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(projectService.externalProjects[0], [file1.path]); + projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path]) }); + checkNumberOfProjects(projectService, { externalProjects: 1 }); + checkProjectActualFiles(projectService.externalProjects[0], [file1.path]); - projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: ts.projectSystem.toExternalFiles([file1.path, file2.path]) }); - ts.projectSystem.checkNumberOfProjects(projectService, { externalProjects: 1 }); - ts.projectSystem.checkProjectRootFiles(projectService.externalProjects[0], [file1.path, file2.path]); + projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path, file2.path]) }); + checkNumberOfProjects(projectService, { externalProjects: 1 }); + checkProjectRootFiles(projectService.externalProjects[0], [file1.path, file2.path]); }); it("can update external project when set of root files was not changed", () => { @@ -442,18 +457,18 @@ describe("unittests:: tsserver:: ExternalProjects", () => { content: "export let y = 1" }; - const host = ts.projectSystem.createServerHost([file1, file2, file3]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2, file3]); + const projectService = createProjectService(host); - projectService.openExternalProject({ projectFileName: "project", options: { moduleResolution: ts.ModuleResolutionKind.NodeJs }, rootFiles: ts.projectSystem.toExternalFiles([file1.path, file2.path]) }); - ts.projectSystem.checkNumberOfProjects(projectService, { externalProjects: 1 }); - ts.projectSystem.checkProjectRootFiles(projectService.externalProjects[0], [file1.path, file2.path]); - ts.projectSystem.checkProjectActualFiles(projectService.externalProjects[0], [file1.path, file2.path]); + projectService.openExternalProject({ projectFileName: "project", options: { moduleResolution: ModuleResolutionKind.NodeJs }, rootFiles: toExternalFiles([file1.path, file2.path]) }); + checkNumberOfProjects(projectService, { externalProjects: 1 }); + checkProjectRootFiles(projectService.externalProjects[0], [file1.path, file2.path]); + checkProjectActualFiles(projectService.externalProjects[0], [file1.path, file2.path]); - projectService.openExternalProject({ projectFileName: "project", options: { moduleResolution: ts.ModuleResolutionKind.Classic }, rootFiles: ts.projectSystem.toExternalFiles([file1.path, file2.path]) }); - ts.projectSystem.checkNumberOfProjects(projectService, { externalProjects: 1 }); - ts.projectSystem.checkProjectRootFiles(projectService.externalProjects[0], [file1.path, file2.path]); - ts.projectSystem.checkProjectActualFiles(projectService.externalProjects[0], [file1.path, file2.path, file3.path]); + projectService.openExternalProject({ projectFileName: "project", options: { moduleResolution: ModuleResolutionKind.Classic }, rootFiles: toExternalFiles([file1.path, file2.path]) }); + checkNumberOfProjects(projectService, { externalProjects: 1 }); + checkProjectRootFiles(projectService.externalProjects[0], [file1.path, file2.path]); + checkProjectActualFiles(projectService.externalProjects[0], [file1.path, file2.path, file3.path]); }); it("language service disabled state is updated in external projects", () => { @@ -465,17 +480,17 @@ describe("unittests:: tsserver:: ExternalProjects", () => { path: "/a/largefile.js", content: "" }; - const host = ts.projectSystem.createServerHost([f1, f2]); + const host = createServerHost([f1, f2]); const originalGetFileSize = host.getFileSize; host.getFileSize = (filePath: string) => - filePath === f2.path ? ts.server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); + filePath === f2.path ? maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath); - const service = ts.projectSystem.createProjectService(host); + const service = createProjectService(host); const projectFileName = "/a/proj.csproj"; service.openExternalProject({ projectFileName, - rootFiles: ts.projectSystem.toExternalFiles([f1.path, f2.path]), + rootFiles: toExternalFiles([f1.path, f2.path]), options: {} }); service.checkNumberOfProjects({ externalProjects: 1 }); @@ -483,7 +498,7 @@ describe("unittests:: tsserver:: ExternalProjects", () => { service.openExternalProject({ projectFileName, - rootFiles: ts.projectSystem.toExternalFiles([f1.path]), + rootFiles: toExternalFiles([f1.path]), options: {} }); service.checkNumberOfProjects({ externalProjects: 1 }); @@ -491,7 +506,7 @@ describe("unittests:: tsserver:: ExternalProjects", () => { service.openExternalProject({ projectFileName, - rootFiles: ts.projectSystem.toExternalFiles([f1.path, f2.path]), + rootFiles: toExternalFiles([f1.path, f2.path]), options: {} }); service.checkNumberOfProjects({ externalProjects: 1 }); @@ -509,13 +524,13 @@ describe("unittests:: tsserver:: ExternalProjects", () => { content: "{}" }; const projectFileName = "/user/someuser/project/WebApplication6.csproj"; - const host = ts.projectSystem.createServerHost([ts.projectSystem.libFile, site, configFile]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([libFile, site, configFile]); + const projectService = createProjectService(host); projectService.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject } }); - const externalProject: ts.projectSystem.protocol.ExternalProject = { + const externalProject: ExternalProject = { projectFileName, - rootFiles: [ts.projectSystem.toExternalFile(site.path), ts.projectSystem.toExternalFile(configFile.path)], + rootFiles: [toExternalFile(site.path), toExternalFile(configFile.path)], options: { allowJs: false }, typeAcquisition: { include: [] } }; @@ -523,23 +538,23 @@ describe("unittests:: tsserver:: ExternalProjects", () => { projectService.openExternalProjects([externalProject]); let knownProjects = projectService.synchronizeProjectList([]); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1, externalProjects: 0, inferredProjects: 0 }); + checkNumberOfProjects(projectService, { configuredProjects: 1, externalProjects: 0, inferredProjects: 0 }); - const configProject = ts.projectSystem.configuredProjectAt(projectService, 0); - ts.projectSystem.checkProjectActualFiles(configProject, lazyConfiguredProjectsFromExternalProject ? - ts.emptyArray : // Since no files opened from this project, its not loaded + const configProject = configuredProjectAt(projectService, 0); + checkProjectActualFiles(configProject, lazyConfiguredProjectsFromExternalProject ? + emptyArray : // Since no files opened from this project, its not loaded [configFile.path]); host.deleteFile(configFile.path); - knownProjects = projectService.synchronizeProjectList(ts.map(knownProjects, proj => proj.info!)); // TODO: GH#18217 GH#20039 - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 0, externalProjects: 0, inferredProjects: 0 }); + knownProjects = projectService.synchronizeProjectList(map(knownProjects, proj => proj.info!)); // TODO: GH#18217 GH#20039 + checkNumberOfProjects(projectService, { configuredProjects: 0, externalProjects: 0, inferredProjects: 0 }); externalProject.rootFiles.length = 1; projectService.openExternalProjects([externalProject]); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 0, externalProjects: 1, inferredProjects: 0 }); - ts.projectSystem.checkProjectActualFiles(projectService.externalProjects[0], [site.path, ts.projectSystem.libFile.path]); + checkNumberOfProjects(projectService, { configuredProjects: 0, externalProjects: 1, inferredProjects: 0 }); + checkProjectActualFiles(projectService.externalProjects[0], [site.path, libFile.path]); } it("when lazyConfiguredProjectsFromExternalProject not set", () => { verifyDeletingConfigFile(/*lazyConfiguredProjectsFromExternalProject*/ false); @@ -563,45 +578,45 @@ describe("unittests:: tsserver:: ExternalProjects", () => { path: "/a/b/tsconfig.json", content: "" }; - const host = ts.projectSystem.createServerHost([f1, f2]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([f1, f2]); + const projectService = createProjectService(host); projectService.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject } }); // open external project const projectName = "/a/b/proj1"; projectService.openExternalProject({ projectFileName: projectName, - rootFiles: ts.projectSystem.toExternalFiles([f1.path, f2.path]), + rootFiles: toExternalFiles([f1.path, f2.path]), options: {} }); projectService.openClientFile(f1.path); projectService.checkNumberOfProjects({ externalProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(projectService.externalProjects[0], [f1.path, f2.path]); + checkProjectActualFiles(projectService.externalProjects[0], [f1.path, f2.path]); // rename lib.ts to tsconfig.json host.renameFile(f2.path, tsconfig.path); projectService.openExternalProject({ projectFileName: projectName, - rootFiles: ts.projectSystem.toExternalFiles([f1.path, tsconfig.path]), + rootFiles: toExternalFiles([f1.path, tsconfig.path]), options: {} }); projectService.checkNumberOfProjects({ configuredProjects: 1 }); if (lazyConfiguredProjectsFromExternalProject) { - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), ts.emptyArray); // Configured project created but not loaded till actually needed + checkProjectActualFiles(configuredProjectAt(projectService, 0), emptyArray); // Configured project created but not loaded till actually needed projectService.ensureInferredProjectsUpToDate_TestOnly(); } - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [f1.path, tsconfig.path]); + checkProjectActualFiles(configuredProjectAt(projectService, 0), [f1.path, tsconfig.path]); // rename tsconfig.json back to lib.ts host.renameFile(tsconfig.path, f2.path); projectService.openExternalProject({ projectFileName: projectName, - rootFiles: ts.projectSystem.toExternalFiles([f1.path, f2.path]), + rootFiles: toExternalFiles([f1.path, f2.path]), options: {} }); projectService.checkNumberOfProjects({ externalProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(projectService.externalProjects[0], [f1.path, f2.path]); + checkProjectActualFiles(projectService.externalProjects[0], [f1.path, f2.path]); } it("when lazyConfiguredProjectsFromExternalProject not set", () => { verifyAddRemoveConfig(/*lazyConfiguredProjectsFromExternalProject*/ false); @@ -633,71 +648,71 @@ describe("unittests:: tsserver:: ExternalProjects", () => { path: "/a/b/d/tsconfig.json", content: "{}" }; - const host = ts.projectSystem.createServerHost([f1, cLib, cTsconfig, dLib, dTsconfig]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([f1, cLib, cTsconfig, dLib, dTsconfig]); + const projectService = createProjectService(host); projectService.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject } }); // open external project const projectName = "/a/b/proj1"; projectService.openExternalProject({ projectFileName: projectName, - rootFiles: ts.projectSystem.toExternalFiles([f1.path]), + rootFiles: toExternalFiles([f1.path]), options: {} }); projectService.checkNumberOfProjects({ externalProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(projectService.externalProjects[0], [f1.path]); + checkProjectActualFiles(projectService.externalProjects[0], [f1.path]); // add two config file as root files projectService.openExternalProject({ projectFileName: projectName, - rootFiles: ts.projectSystem.toExternalFiles([f1.path, cTsconfig.path, dTsconfig.path]), + rootFiles: toExternalFiles([f1.path, cTsconfig.path, dTsconfig.path]), options: {} }); projectService.checkNumberOfProjects({ configuredProjects: 2 }); if (lazyConfiguredProjectsFromExternalProject) { - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), ts.emptyArray); // Configured project created but not loaded till actually needed - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 1), ts.emptyArray); // Configured project created but not loaded till actually needed + checkProjectActualFiles(configuredProjectAt(projectService, 0), emptyArray); // Configured project created but not loaded till actually needed + checkProjectActualFiles(configuredProjectAt(projectService, 1), emptyArray); // Configured project created but not loaded till actually needed projectService.ensureInferredProjectsUpToDate_TestOnly(); } - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [cLib.path, cTsconfig.path]); - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 1), [dLib.path, dTsconfig.path]); + checkProjectActualFiles(configuredProjectAt(projectService, 0), [cLib.path, cTsconfig.path]); + checkProjectActualFiles(configuredProjectAt(projectService, 1), [dLib.path, dTsconfig.path]); // remove one config file projectService.openExternalProject({ projectFileName: projectName, - rootFiles: ts.projectSystem.toExternalFiles([f1.path, dTsconfig.path]), + rootFiles: toExternalFiles([f1.path, dTsconfig.path]), options: {} }); projectService.checkNumberOfProjects({ configuredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [dLib.path, dTsconfig.path]); + checkProjectActualFiles(configuredProjectAt(projectService, 0), [dLib.path, dTsconfig.path]); // remove second config file projectService.openExternalProject({ projectFileName: projectName, - rootFiles: ts.projectSystem.toExternalFiles([f1.path]), + rootFiles: toExternalFiles([f1.path]), options: {} }); projectService.checkNumberOfProjects({ externalProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(projectService.externalProjects[0], [f1.path]); + checkProjectActualFiles(projectService.externalProjects[0], [f1.path]); // open two config files // add two config file as root files projectService.openExternalProject({ projectFileName: projectName, - rootFiles: ts.projectSystem.toExternalFiles([f1.path, cTsconfig.path, dTsconfig.path]), + rootFiles: toExternalFiles([f1.path, cTsconfig.path, dTsconfig.path]), options: {} }); projectService.checkNumberOfProjects({ configuredProjects: 2 }); if (lazyConfiguredProjectsFromExternalProject) { - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), ts.emptyArray); // Configured project created but not loaded till actually needed - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 1), ts.emptyArray); // Configured project created but not loaded till actually needed + checkProjectActualFiles(configuredProjectAt(projectService, 0), emptyArray); // Configured project created but not loaded till actually needed + checkProjectActualFiles(configuredProjectAt(projectService, 1), emptyArray); // Configured project created but not loaded till actually needed projectService.ensureInferredProjectsUpToDate_TestOnly(); } - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [cLib.path, cTsconfig.path]); - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 1), [dLib.path, dTsconfig.path]); + checkProjectActualFiles(configuredProjectAt(projectService, 0), [cLib.path, cTsconfig.path]); + checkProjectActualFiles(configuredProjectAt(projectService, 1), [dLib.path, dTsconfig.path]); // close all projects - no projects should be opened projectService.closeExternalProject(projectName); @@ -756,18 +771,18 @@ describe("unittests:: tsserver:: ExternalProjects", () => { } }) }; - const host = ts.projectSystem.createServerHost([libES5, libES2015Promise, app, config1], { executingFilePath: "/compiler/tsc.js" }); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([libES5, libES2015Promise, app, config1], { executingFilePath: "/compiler/tsc.js" }); + const projectService = createProjectService(host); projectService.openClientFile(app.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [libES5.path, app.path, config1.path]); + checkProjectActualFiles(configuredProjectAt(projectService, 0), [libES5.path, app.path, config1.path]); host.writeFile(config2.path, config2.content); host.checkTimeoutQueueLengthAndRun(2); projectService.checkNumberOfProjects({ configuredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [libES5.path, libES2015Promise.path, app.path, config2.path]); + checkProjectActualFiles(configuredProjectAt(projectService, 0), [libES5.path, libES2015Promise.path, app.path, config2.path]); }); it("should handle non-existing directories in config file", () => { @@ -785,8 +800,8 @@ describe("unittests:: tsserver:: ExternalProjects", () => { ] }) }; - const host = ts.projectSystem.createServerHost([f, config]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([f, config]); + const projectService = createProjectService(host); projectService.openClientFile(f.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); const project = projectService.configuredProjects.get(config.path)!; @@ -815,46 +830,46 @@ describe("unittests:: tsserver:: ExternalProjects", () => { content: JSON.stringify({}) }; const projectFileName = "/a/b/project.csproj"; - const host = ts.projectSystem.createServerHost([f1, config]); - const service = ts.projectSystem.createProjectService(host); + const host = createServerHost([f1, config]); + const service = createProjectService(host); service.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject: true } }); service.openExternalProject({ projectFileName, - rootFiles: ts.projectSystem.toExternalFiles([f1.path, config.path]), + rootFiles: toExternalFiles([f1.path, config.path]), options: {} - } as ts.projectSystem.protocol.ExternalProject); + } as ExternalProject); service.checkNumberOfProjects({ configuredProjects: 1 }); const project = service.configuredProjects.get(config.path)!; - assert.equal(project.pendingReload, ts.ConfigFileProgramReloadLevel.Full); // External project referenced configured project pending to be reloaded - ts.projectSystem.checkProjectActualFiles(project, ts.emptyArray); + assert.equal(project.pendingReload, ConfigFileProgramReloadLevel.Full); // External project referenced configured project pending to be reloaded + checkProjectActualFiles(project, emptyArray); service.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject: false } }); - assert.equal(project.pendingReload, ts.ConfigFileProgramReloadLevel.None); // External project referenced configured project loaded - ts.projectSystem.checkProjectActualFiles(project, [config.path, f1.path]); + assert.equal(project.pendingReload, ConfigFileProgramReloadLevel.None); // External project referenced configured project loaded + checkProjectActualFiles(project, [config.path, f1.path]); service.closeExternalProject(projectFileName); service.checkNumberOfProjects({}); service.openExternalProject({ projectFileName, - rootFiles: ts.projectSystem.toExternalFiles([f1.path, config.path]), + rootFiles: toExternalFiles([f1.path, config.path]), options: {} - } as ts.projectSystem.protocol.ExternalProject); + } as ExternalProject); service.checkNumberOfProjects({ configuredProjects: 1 }); const project2 = service.configuredProjects.get(config.path)!; - assert.equal(project2.pendingReload, ts.ConfigFileProgramReloadLevel.None); // External project referenced configured project loaded - ts.projectSystem.checkProjectActualFiles(project2, [config.path, f1.path]); + assert.equal(project2.pendingReload, ConfigFileProgramReloadLevel.None); // External project referenced configured project loaded + checkProjectActualFiles(project2, [config.path, f1.path]); }); it("handles creation of external project with jsconfig before jsconfig creation watcher is invoked", () => { - const projectFileName = `${ts.tscWatch.projectRoot}/WebApplication36.csproj`; - const tsconfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const projectFileName = `${projectRoot}/WebApplication36.csproj`; + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, content: "{}" }; - const files = [ts.projectSystem.libFile, tsconfig]; - const host = ts.projectSystem.createServerHost(files); - const service = ts.projectSystem.createProjectService(host); + const files = [libFile, tsconfig]; + const host = createServerHost(files); + const service = createProjectService(host); // Create external project service.openExternalProjects([{ @@ -862,27 +877,27 @@ describe("unittests:: tsserver:: ExternalProjects", () => { rootFiles: [{ fileName: tsconfig.path }], options: { allowJs: false } }]); - ts.projectSystem.checkNumberOfProjects(service, { configuredProjects: 1 }); + checkNumberOfProjects(service, { configuredProjects: 1 }); const configProject = service.configuredProjects.get(tsconfig.path.toLowerCase())!; - ts.projectSystem.checkProjectActualFiles(configProject, [tsconfig.path]); + checkProjectActualFiles(configProject, [tsconfig.path]); // write js file, open external project and open it for edit - const jsFilePath = `${ts.tscWatch.projectRoot}/javascript.js`; + const jsFilePath = `${projectRoot}/javascript.js`; host.writeFile(jsFilePath, ""); service.openExternalProjects([{ projectFileName, rootFiles: [{ fileName: tsconfig.path }, { fileName: jsFilePath }], options: { allowJs: false } }]); - service.applyChangesInOpenFiles(ts.singleIterator({ fileName: jsFilePath, scriptKind: ts.ScriptKind.JS, content: "" })); - ts.projectSystem.checkNumberOfProjects(service, { configuredProjects: 1, inferredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(configProject, [tsconfig.path]); + service.applyChangesInOpenFiles(singleIterator({ fileName: jsFilePath, scriptKind: ScriptKind.JS, content: "" })); + checkNumberOfProjects(service, { configuredProjects: 1, inferredProjects: 1 }); + checkProjectActualFiles(configProject, [tsconfig.path]); const inferredProject = service.inferredProjects[0]; - ts.projectSystem.checkProjectActualFiles(inferredProject, [ts.projectSystem.libFile.path, jsFilePath]); + checkProjectActualFiles(inferredProject, [libFile.path, jsFilePath]); // write jsconfig file - const jsConfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/jsconfig.json`, + const jsConfig: File = { + path: `${projectRoot}/jsconfig.json`, content: "{}" }; // Dont invoke file creation watchers as the repro suggests @@ -894,11 +909,11 @@ describe("unittests:: tsserver:: ExternalProjects", () => { rootFiles: [{ fileName: jsConfig.path }, { fileName: tsconfig.path }, { fileName: jsFilePath }], options: { allowJs: false } }]); - ts.projectSystem.checkNumberOfProjects(service, { configuredProjects: 2, inferredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(configProject, [tsconfig.path]); + checkNumberOfProjects(service, { configuredProjects: 2, inferredProjects: 1 }); + checkProjectActualFiles(configProject, [tsconfig.path]); assert.isTrue(inferredProject.isOrphan()); const jsConfigProject = service.configuredProjects.get(jsConfig.path.toLowerCase())!; - ts.projectSystem.checkProjectActualFiles(jsConfigProject, [jsConfig.path, jsFilePath, ts.projectSystem.libFile.path]); + checkProjectActualFiles(jsConfigProject, [jsConfig.path, jsFilePath, libFile.path]); }); it("does not crash if external file does not exist", () => { @@ -908,17 +923,17 @@ describe("unittests:: tsserver:: ExternalProjects", () => { }; const p1 = { projectFileName: "/a/proj1.csproj", - rootFiles: [ts.projectSystem.toExternalFile(f1.path)], + rootFiles: [toExternalFile(f1.path)], options: {}, }; - const host = ts.projectSystem.createServerHost([f1]); + const host = createServerHost([f1]); host.require = (_initialPath, moduleName) => { assert.equal(moduleName, "myplugin"); return { module: () => ({ - create(info: ts.server.PluginCreateInfo) { - return Harness.LanguageService.makeDefaultProxy(info); + create(info: PluginCreateInfo) { + return makeDefaultProxy(info); }, getExternalFiles() { return ["/does/not/exist"]; @@ -927,7 +942,7 @@ describe("unittests:: tsserver:: ExternalProjects", () => { error: undefined, }; }; - const session = ts.projectSystem.createSession(host, { + const session = createSession(host, { globalPlugins: ["myplugin"], }); const projectService = session.getProjectService(); @@ -937,7 +952,7 @@ describe("unittests:: tsserver:: ExternalProjects", () => { // info for it. If tsserver does not handle this case, the following // method call will crash. projectService.openExternalProject(p1); - ts.projectSystem.checkNumberOfProjects(projectService, { externalProjects: 1 }); + checkNumberOfProjects(projectService, { externalProjects: 1 }); }); }); diff --git a/src/testRunner/unittests/tsserver/forceConsistentCasingInFileNames.ts b/src/testRunner/unittests/tsserver/forceConsistentCasingInFileNames.ts index 6f5d4f4b43888..41d5a3354c3b8 100644 --- a/src/testRunner/unittests/tsserver/forceConsistentCasingInFileNames.ts +++ b/src/testRunner/unittests/tsserver/forceConsistentCasingInFileNames.ts @@ -1,21 +1,27 @@ -import * as ts from "../../_namespaces/ts"; +import { CommandTypes, UpdateOpenRequest } from "../../../server/protocol"; +import { projectRoot } from "../tscWatch/helpers"; +import { + baselineTsserverLogs, checkNumberOfProjects, closeFilesForSession, configuredProjectAt, + createLoggerWithInMemoryLogs, createServerHost, createSession, File, libFile, openFilesForSession, + protocolTextSpanFromSubstring, verifyGetErrRequest, +} from "./helpers"; describe("unittests:: tsserver:: forceConsistentCasingInFileNames", () => { it("works when extends is specified with a case insensitive file system", () => { const rootPath = "/Users/username/dev/project"; - const file1: ts.projectSystem.File = { + const file1: File = { path: `${rootPath}/index.ts`, content: 'import {x} from "file2";', }; - const file2: ts.projectSystem.File = { + const file2: File = { path: `${rootPath}/file2.js`, content: "", }; - const file2Dts: ts.projectSystem.File = { + const file2Dts: File = { path: `${rootPath}/types/file2/index.d.ts`, content: "export declare const x: string;", }; - const tsconfigAll: ts.projectSystem.File = { + const tsconfigAll: File = { path: `${rootPath}/tsconfig.all.json`, content: JSON.stringify({ compilerOptions: { @@ -26,59 +32,59 @@ describe("unittests:: tsserver:: forceConsistentCasingInFileNames", () => { }, }), }; - const tsconfig: ts.projectSystem.File = { + const tsconfig: File = { path: `${rootPath}/tsconfig.json`, content: JSON.stringify({ extends: "./tsconfig.all.json" }), }; - const host = ts.projectSystem.createServerHost([file1, file2, file2Dts, ts.projectSystem.libFile, tsconfig, tsconfigAll], { useCaseSensitiveFileNames: false }); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([file1, file2, file2Dts, libFile, tsconfig, tsconfigAll], { useCaseSensitiveFileNames: false }); + const session = createSession(host); - ts.projectSystem.openFilesForSession([file1], session); + openFilesForSession([file1], session); const projectService = session.getProjectService(); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); - const diagnostics = ts.projectSystem.configuredProjectAt(projectService, 0).getLanguageService().getCompilerOptionsDiagnostics(); + const diagnostics = configuredProjectAt(projectService, 0).getLanguageService().getCompilerOptionsDiagnostics(); assert.deepEqual(diagnostics, []); }); it("works when renaming file with different casing", () => { - const loggerFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/Logger.ts`, + const loggerFile: File = { + path: `${projectRoot}/Logger.ts`, content: `export class logger { }` }; - const anotherFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/another.ts`, + const anotherFile: File = { + path: `${projectRoot}/another.ts`, content: `import { logger } from "./Logger"; new logger();` }; - const tsconfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { forceConsistentCasingInFileNames: true } }) }; - const host = ts.projectSystem.createServerHost([loggerFile, anotherFile, tsconfig, ts.projectSystem.libFile, tsconfig]); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([{ file: loggerFile, projectRootPath: ts.tscWatch.projectRoot }], session); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [loggerFile] }); + const host = createServerHost([loggerFile, anotherFile, tsconfig, libFile, tsconfig]); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([{ file: loggerFile, projectRootPath: projectRoot }], session); + verifyGetErrRequest({ session, host, files: [loggerFile] }); const newLoggerPath = loggerFile.path.toLowerCase(); host.renameFile(loggerFile.path, newLoggerPath); - ts.projectSystem.closeFilesForSession([loggerFile], session); - ts.projectSystem.openFilesForSession([{ file: newLoggerPath, content: loggerFile.content, projectRootPath: ts.tscWatch.projectRoot }], session); + closeFilesForSession([loggerFile], session); + openFilesForSession([{ file: newLoggerPath, content: loggerFile.content, projectRootPath: projectRoot }], session); // Apply edits for rename - ts.projectSystem.openFilesForSession([{ file: anotherFile, projectRootPath: ts.tscWatch.projectRoot }], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.UpdateOpen, + openFilesForSession([{ file: anotherFile, projectRootPath: projectRoot }], session); + session.executeCommandSeq({ + command: CommandTypes.UpdateOpen, arguments: { changedFiles: [{ fileName: anotherFile.path, textChanges: [{ newText: "./logger", - ...ts.projectSystem.protocolTextSpanFromSubstring( + ...protocolTextSpanFromSubstring( anotherFile.content, "./Logger" ) @@ -88,39 +94,39 @@ describe("unittests:: tsserver:: forceConsistentCasingInFileNames", () => { }); // Check errors in both files - ts.projectSystem.verifyGetErrRequest({ session, host, files: [newLoggerPath, anotherFile] }); - ts.projectSystem.baselineTsserverLogs("forceConsistentCasingInFileNames", "works when renaming file with different casing", session); + verifyGetErrRequest({ session, host, files: [newLoggerPath, anotherFile] }); + baselineTsserverLogs("forceConsistentCasingInFileNames", "works when renaming file with different casing", session); }); it("when changing module name with different casing", () => { - const loggerFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/Logger.ts`, + const loggerFile: File = { + path: `${projectRoot}/Logger.ts`, content: `export class logger { }` }; - const anotherFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/another.ts`, + const anotherFile: File = { + path: `${projectRoot}/another.ts`, content: `import { logger } from "./Logger"; new logger();` }; - const tsconfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { forceConsistentCasingInFileNames: true } }) }; - const host = ts.projectSystem.createServerHost([loggerFile, anotherFile, tsconfig, ts.projectSystem.libFile, tsconfig]); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([{ file: anotherFile, projectRootPath: ts.tscWatch.projectRoot }], session); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [anotherFile] }); + const host = createServerHost([loggerFile, anotherFile, tsconfig, libFile, tsconfig]); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([{ file: anotherFile, projectRootPath: projectRoot }], session); + verifyGetErrRequest({ session, host, files: [anotherFile] }); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.UpdateOpen, + session.executeCommandSeq({ + command: CommandTypes.UpdateOpen, arguments: { changedFiles: [{ fileName: anotherFile.path, textChanges: [{ newText: "./logger", - ...ts.projectSystem.protocolTextSpanFromSubstring( + ...protocolTextSpanFromSubstring( anotherFile.content, "./Logger" ) @@ -130,8 +136,8 @@ describe("unittests:: tsserver:: forceConsistentCasingInFileNames", () => { }); // Check errors in both files - ts.projectSystem.verifyGetErrRequest({ host, session, files: [anotherFile] }); - ts.projectSystem.baselineTsserverLogs("forceConsistentCasingInFileNames", "when changing module name with different casing", session); + verifyGetErrRequest({ host, session, files: [anotherFile] }); + baselineTsserverLogs("forceConsistentCasingInFileNames", "when changing module name with different casing", session); }); }); diff --git a/src/testRunner/unittests/tsserver/formatSettings.ts b/src/testRunner/unittests/tsserver/formatSettings.ts index 5299a37926bcf..0c110466a6543 100644 --- a/src/testRunner/unittests/tsserver/formatSettings.ts +++ b/src/testRunner/unittests/tsserver/formatSettings.ts @@ -1,4 +1,5 @@ -import * as ts from "../../_namespaces/ts"; +import { NormalizedPath, toNormalizedPath } from "../../../server/utilitiesPublic"; +import { createProjectService, createServerHost } from "./helpers"; describe("unittests:: tsserver:: format settings", () => { it("can be set globally", () => { @@ -6,18 +7,18 @@ describe("unittests:: tsserver:: format settings", () => { path: "/a/b/app.ts", content: "let x;" }; - const host = ts.projectSystem.createServerHost([f1]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([f1]); + const projectService = createProjectService(host); projectService.openClientFile(f1.path); - const defaultSettings = projectService.getFormatCodeOptions(f1.path as ts.server.NormalizedPath); + const defaultSettings = projectService.getFormatCodeOptions(f1.path as NormalizedPath); // set global settings const newGlobalSettings1 = { ...defaultSettings, placeOpenBraceOnNewLineForControlBlocks: !defaultSettings.placeOpenBraceOnNewLineForControlBlocks }; projectService.setHostConfiguration({ formatOptions: newGlobalSettings1 }); // get format options for file - should be equal to new global settings - const s1 = projectService.getFormatCodeOptions(ts.server.toNormalizedPath(f1.path)); + const s1 = projectService.getFormatCodeOptions(toNormalizedPath(f1.path)); assert.deepEqual(s1, newGlobalSettings1, "file settings should be the same with global settings"); // set per file format options @@ -25,7 +26,7 @@ describe("unittests:: tsserver:: format settings", () => { projectService.setHostConfiguration({ formatOptions: newPerFileSettings, file: f1.path }); // get format options for file - should be equal to new per-file settings - const s2 = projectService.getFormatCodeOptions(ts.server.toNormalizedPath(f1.path)); + const s2 = projectService.getFormatCodeOptions(toNormalizedPath(f1.path)); assert.deepEqual(s2, newPerFileSettings, "file settings should be the same with per-file settings"); // set new global settings - they should not affect ones that were set per-file @@ -33,7 +34,7 @@ describe("unittests:: tsserver:: format settings", () => { projectService.setHostConfiguration({ formatOptions: newGlobalSettings2 }); // get format options for file - should be equal to new per-file settings - const s3 = projectService.getFormatCodeOptions(ts.server.toNormalizedPath(f1.path)); + const s3 = projectService.getFormatCodeOptions(toNormalizedPath(f1.path)); assert.deepEqual(s3, newPerFileSettings, "file settings should still be the same with per-file settings"); }); }); diff --git a/src/testRunner/unittests/tsserver/getApplicableRefactors.ts b/src/testRunner/unittests/tsserver/getApplicableRefactors.ts index 6f0aa6cfb18af..cf550fb4d07a6 100644 --- a/src/testRunner/unittests/tsserver/getApplicableRefactors.ts +++ b/src/testRunner/unittests/tsserver/getApplicableRefactors.ts @@ -1,13 +1,16 @@ -import * as ts from "../../_namespaces/ts"; +import { + ApplicableRefactorInfo, CommandTypes, GetApplicableRefactorsRequest, GetApplicableRefactorsResponse, +} from "../../../server/protocol"; +import { createServerHost, createSession, executeSessionRequest, File, openFilesForSession } from "./helpers"; describe("unittests:: tsserver:: getApplicableRefactors", () => { it("works when taking position", () => { - const aTs: ts.projectSystem.File = { path: "/a.ts", content: "" }; - const session = ts.projectSystem.createSession(ts.projectSystem.createServerHost([aTs])); - ts.projectSystem.openFilesForSession([aTs], session); - const response = ts.projectSystem.executeSessionRequest( - session, ts.projectSystem.protocol.CommandTypes.GetApplicableRefactors, { file: aTs.path, line: 1, offset: 1 }); - assert.deepEqual(response, []); + const aTs: File = { path: "/a.ts", content: "" }; + const session = createSession(createServerHost([aTs])); + openFilesForSession([aTs], session); + const response = executeSessionRequest( + session, CommandTypes.GetApplicableRefactors, { file: aTs.path, line: 1, offset: 1 }); + assert.deepEqual(response, []); }); }); diff --git a/src/testRunner/unittests/tsserver/getEditsForFileRename.ts b/src/testRunner/unittests/tsserver/getEditsForFileRename.ts index d18e35b1a4afe..96fcd8b906a77 100644 --- a/src/testRunner/unittests/tsserver/getEditsForFileRename.ts +++ b/src/testRunner/unittests/tsserver/getEditsForFileRename.ts @@ -1,104 +1,110 @@ -import * as ts from "../../_namespaces/ts"; +import { Debug } from "../../../compiler/debug"; +import { FileCodeEdits, GetEditsForFileRenameRequest, GetEditsForFileRenameResponse } from "../../../server/protocol"; +import { emptyOptions, FileTextChanges, testFormatSettings } from "../../../services/types"; +import { + CommandNames, createProjectService, createServerHost, createSession, executeSessionRequest, File, + openFilesForSession, protocolTextSpanFromSubstring, textSpanFromSubstring, +} from "./helpers"; describe("unittests:: tsserver:: getEditsForFileRename", () => { it("works for host implementing 'resolveModuleNames' and 'getResolvedModuleWithFailedLookupLocationsFromCache'", () => { - const userTs: ts.projectSystem.File = { + const userTs: File = { path: "/user.ts", content: 'import { x } from "./old";', }; - const newTs: ts.projectSystem.File = { + const newTs: File = { path: "/new.ts", content: "export const x = 0;", }; - const tsconfig: ts.projectSystem.File = { + const tsconfig: File = { path: "/tsconfig.json", content: "{}", }; - const host = ts.projectSystem.createServerHost([userTs, newTs, tsconfig]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([userTs, newTs, tsconfig]); + const projectService = createProjectService(host); projectService.openClientFile(userTs.path); const project = projectService.configuredProjects.get(tsconfig.path)!; - ts.Debug.assert(!!project.resolveModuleNames); + Debug.assert(!!project.resolveModuleNames); - const edits = project.getLanguageService().getEditsForFileRename("/old.ts", "/new.ts", ts.testFormatSettings, ts.emptyOptions); - assert.deepEqual(edits, [{ + const edits = project.getLanguageService().getEditsForFileRename("/old.ts", "/new.ts", testFormatSettings, emptyOptions); + assert.deepEqual(edits, [{ fileName: "/user.ts", textChanges: [{ - span: ts.projectSystem.textSpanFromSubstring(userTs.content, "./old"), + span: textSpanFromSubstring(userTs.content, "./old"), newText: "./new", }], }]); }); it("works with multiple projects", () => { - const aUserTs: ts.projectSystem.File = { + const aUserTs: File = { path: "/a/user.ts", content: 'import { x } from "./old";', }; - const aOldTs: ts.projectSystem.File = { + const aOldTs: File = { path: "/a/old.ts", content: "export const x = 0;", }; - const aTsconfig: ts.projectSystem.File = { + const aTsconfig: File = { path: "/a/tsconfig.json", content: JSON.stringify({ files: ["./old.ts", "./user.ts"] }), }; - const bUserTs: ts.projectSystem.File = { + const bUserTs: File = { path: "/b/user.ts", content: 'import { x } from "../a/old";', }; - const bTsconfig: ts.projectSystem.File = { + const bTsconfig: File = { path: "/b/tsconfig.json", content: "{}", }; - const host = ts.projectSystem.createServerHost([aUserTs, aOldTs, aTsconfig, bUserTs, bTsconfig]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([aUserTs, bUserTs], session); + const host = createServerHost([aUserTs, aOldTs, aTsconfig, bUserTs, bTsconfig]); + const session = createSession(host); + openFilesForSession([aUserTs, bUserTs], session); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.CommandNames.GetEditsForFileRename, { + const response = executeSessionRequest(session, CommandNames.GetEditsForFileRename, { oldFilePath: aOldTs.path, newFilePath: "/a/new.ts", }); - assert.deepEqual(response, [ + assert.deepEqual(response, [ { fileName: aTsconfig.path, - textChanges: [{ ...ts.projectSystem.protocolTextSpanFromSubstring(aTsconfig.content, "./old.ts"), newText: "new.ts" }], + textChanges: [{ ...protocolTextSpanFromSubstring(aTsconfig.content, "./old.ts"), newText: "new.ts" }], }, { fileName: aUserTs.path, - textChanges: [{ ...ts.projectSystem.protocolTextSpanFromSubstring(aUserTs.content, "./old"), newText: "./new" }], + textChanges: [{ ...protocolTextSpanFromSubstring(aUserTs.content, "./old"), newText: "./new" }], }, { fileName: bUserTs.path, - textChanges: [{ ...ts.projectSystem.protocolTextSpanFromSubstring(bUserTs.content, "../a/old"), newText: "../a/new" }], + textChanges: [{ ...protocolTextSpanFromSubstring(bUserTs.content, "../a/old"), newText: "../a/new" }], }, ]); }); it("works with file moved to inferred project", () => { - const aTs: ts.projectSystem.File = { path: "/a.ts", content: 'import {} from "./b";' }; - const cTs: ts.projectSystem.File = { path: "/c.ts", content: "export {};" }; - const tsconfig: ts.projectSystem.File = { path: "/tsconfig.json", content: JSON.stringify({ files: ["./a.ts", "./b.ts"] }) }; + const aTs: File = { path: "/a.ts", content: 'import {} from "./b";' }; + const cTs: File = { path: "/c.ts", content: "export {};" }; + const tsconfig: File = { path: "/tsconfig.json", content: JSON.stringify({ files: ["./a.ts", "./b.ts"] }) }; - const host = ts.projectSystem.createServerHost([aTs, cTs, tsconfig]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([aTs, cTs], session); + const host = createServerHost([aTs, cTs, tsconfig]); + const session = createSession(host); + openFilesForSession([aTs, cTs], session); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.CommandNames.GetEditsForFileRename, { + const response = executeSessionRequest(session, CommandNames.GetEditsForFileRename, { oldFilePath: "/b.ts", newFilePath: cTs.path, }); - assert.deepEqual(response, [ + assert.deepEqual(response, [ { fileName: "/tsconfig.json", - textChanges: [{ ...ts.projectSystem.protocolTextSpanFromSubstring(tsconfig.content, "./b.ts"), newText: "c.ts" }], + textChanges: [{ ...protocolTextSpanFromSubstring(tsconfig.content, "./b.ts"), newText: "c.ts" }], }, { fileName: "/a.ts", - textChanges: [{ ...ts.projectSystem.protocolTextSpanFromSubstring(aTs.content, "./b"), newText: "./c" }], + textChanges: [{ ...protocolTextSpanFromSubstring(aTs.content, "./b"), newText: "./c" }], }, ]); }); diff --git a/src/testRunner/unittests/tsserver/getExportReferences.ts b/src/testRunner/unittests/tsserver/getExportReferences.ts index 3569272545684..2231b212ad90b 100644 --- a/src/testRunner/unittests/tsserver/getExportReferences.ts +++ b/src/testRunner/unittests/tsserver/getExportReferences.ts @@ -1,4 +1,8 @@ -import * as ts from "../../_namespaces/ts"; +import { CommandTypes, ReferencesRequest, ReferencesResponse, ReferencesResponseItem } from "../../../server/protocol"; +import { + createServerHost, createSession, executeSessionRequest, File, makeReferenceItem, MakeReferenceItem, + openFilesForSession, protocolFileLocationFromSubstring, protocolLocationFromSubstring, +} from "./helpers"; describe("unittests:: tsserver:: getExportReferences", () => { const exportVariable = "export const value = 0;"; @@ -6,11 +10,11 @@ describe("unittests:: tsserver:: getExportReferences", () => { const exportObjectDestructured = "export const { valueC, valueD: renamedD } = { valueC: 0, valueD: 1 };"; const exportNestedObject = "export const { nest: [valueE, { valueF }] } = { nest: [0, { valueF: 1 }] };"; - const mainTs: ts.projectSystem.File = { + const mainTs: File = { path: "/main.ts", content: 'import { value, valueA, valueB, valueC, renamedD, valueE, valueF } from "./mod";', }; - const modTs: ts.projectSystem.File = { + const modTs: File = { path: "/mod.ts", content: `${exportVariable} ${exportArrayDestructured} @@ -18,20 +22,20 @@ ${exportObjectDestructured} ${exportNestedObject} `, }; - const tsconfig: ts.projectSystem.File = { + const tsconfig: File = { path: "/tsconfig.json", content: "{}", }; function makeSampleSession() { - const host = ts.projectSystem.createServerHost([mainTs, modTs, tsconfig]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([mainTs, modTs], session); + const host = createServerHost([mainTs, modTs, tsconfig]); + const session = createSession(host); + openFilesForSession([mainTs, modTs], session); return session; } - const referenceMainTs = (mainTs: ts.projectSystem.File, text: string): ts.projectSystem.protocol.ReferencesResponseItem => - ts.projectSystem.makeReferenceItem({ + const referenceMainTs = (mainTs: File, text: string): ReferencesResponseItem => + makeReferenceItem({ file: mainTs, isDefinition: false, isWriteAccess: true, @@ -42,9 +46,9 @@ ${exportNestedObject} const referenceModTs = ( texts: { text: string; lineText: string; contextText?: string }, - override: Partial = {}, - ): ts.projectSystem.protocol.ReferencesResponseItem => - ts.projectSystem.makeReferenceItem({ + override: Partial = {}, + ): ReferencesResponseItem => + makeReferenceItem({ file: modTs, isDefinition: true, ...texts, @@ -54,10 +58,10 @@ ${exportNestedObject} it("should get const variable declaration references", () => { const session = makeSampleSession(); - const response = ts.projectSystem.executeSessionRequest( + const response = executeSessionRequest( session, - ts.projectSystem.protocol.CommandTypes.References, - ts.projectSystem.protocolFileLocationFromSubstring(modTs, "value"), + CommandTypes.References, + protocolFileLocationFromSubstring(modTs, "value"), ); const expectResponse = { @@ -67,7 +71,7 @@ ${exportNestedObject} ], symbolDisplayString: "const value: 0", symbolName: "value", - symbolStartOffset: ts.projectSystem.protocolLocationFromSubstring(modTs.content, "value").offset, + symbolStartOffset: protocolLocationFromSubstring(modTs.content, "value").offset, }; assert.deepEqual(response, expectResponse); @@ -75,10 +79,10 @@ ${exportNestedObject} it("should get array destructuring declaration references", () => { const session = makeSampleSession(); - const response = ts.projectSystem.executeSessionRequest( + const response = executeSessionRequest( session, - ts.projectSystem.protocol.CommandTypes.References, - ts.projectSystem.protocolFileLocationFromSubstring(modTs, "valueA"), + CommandTypes.References, + protocolFileLocationFromSubstring(modTs, "valueA"), ); const expectResponse = { @@ -92,7 +96,7 @@ ${exportNestedObject} ], symbolDisplayString: "const valueA: number", symbolName: "valueA", - symbolStartOffset: ts.projectSystem.protocolLocationFromSubstring(modTs.content, "valueA").offset, + symbolStartOffset: protocolLocationFromSubstring(modTs.content, "valueA").offset, }; assert.deepEqual(response, expectResponse); @@ -100,10 +104,10 @@ ${exportNestedObject} it("should get object destructuring declaration references", () => { const session = makeSampleSession(); - const response = ts.projectSystem.executeSessionRequest( + const response = executeSessionRequest( session, - ts.projectSystem.protocol.CommandTypes.References, - ts.projectSystem.protocolFileLocationFromSubstring(modTs, "valueC"), + CommandTypes.References, + protocolFileLocationFromSubstring(modTs, "valueC"), ); const expectResponse = { refs: [ @@ -123,7 +127,7 @@ ${exportNestedObject} ], symbolDisplayString: "const valueC: number", symbolName: "valueC", - symbolStartOffset: ts.projectSystem.protocolLocationFromSubstring(modTs.content, "valueC").offset, + symbolStartOffset: protocolLocationFromSubstring(modTs.content, "valueC").offset, }; assert.deepEqual(response, expectResponse); @@ -131,10 +135,10 @@ ${exportNestedObject} it("should get object declaration references that renames destructured property", () => { const session = makeSampleSession(); - const response = ts.projectSystem.executeSessionRequest( + const response = executeSessionRequest( session, - ts.projectSystem.protocol.CommandTypes.References, - ts.projectSystem.protocolFileLocationFromSubstring(modTs, "renamedD"), + CommandTypes.References, + protocolFileLocationFromSubstring(modTs, "renamedD"), ); const expectResponse = { @@ -148,7 +152,7 @@ ${exportNestedObject} ], symbolDisplayString: "const renamedD: number", symbolName: "renamedD", - symbolStartOffset: ts.projectSystem.protocolLocationFromSubstring(modTs.content, "renamedD").offset, + symbolStartOffset: protocolLocationFromSubstring(modTs.content, "renamedD").offset, }; assert.deepEqual(response, expectResponse); @@ -156,10 +160,10 @@ ${exportNestedObject} it("should get nested object declaration references", () => { const session = makeSampleSession(); - const response = ts.projectSystem.executeSessionRequest( + const response = executeSessionRequest( session, - ts.projectSystem.protocol.CommandTypes.References, - ts.projectSystem.protocolFileLocationFromSubstring(modTs, "valueF"), + CommandTypes.References, + protocolFileLocationFromSubstring(modTs, "valueF"), ); const expectResponse = { @@ -185,7 +189,7 @@ ${exportNestedObject} ], symbolDisplayString: "const valueF: number", symbolName: "valueF", - symbolStartOffset: ts.projectSystem.protocolLocationFromSubstring(modTs.content, "valueF").offset, + symbolStartOffset: protocolLocationFromSubstring(modTs.content, "valueF").offset, }; assert.deepEqual(response, expectResponse); diff --git a/src/testRunner/unittests/tsserver/getFileReferences.ts b/src/testRunner/unittests/tsserver/getFileReferences.ts index 2f5ca041474cd..bab21337d38fb 100644 --- a/src/testRunner/unittests/tsserver/getFileReferences.ts +++ b/src/testRunner/unittests/tsserver/getFileReferences.ts @@ -1,4 +1,9 @@ -import * as ts from "../../_namespaces/ts"; +import { + CommandTypes, FileReferencesRequest, FileReferencesResponse, FileReferencesResponseBody, +} from "../../../server/protocol"; +import { + createServerHost, createSession, executeSessionRequest, File, makeReferenceItem, openFilesForSession, +} from "./helpers"; describe("unittests:: tsserver:: getFileReferences", () => { const importA = `import "./a";`; @@ -6,49 +11,49 @@ describe("unittests:: tsserver:: getFileReferences", () => { const importAFromA = `import { a } from "/project/a";`; const typeofImportA = `type T = typeof import("./a").a;`; - const aTs: ts.projectSystem.File = { + const aTs: File = { path: "/project/a.ts", content: "export const a = {};", }; - const bTs: ts.projectSystem.File = { + const bTs: File = { path: "/project/b.ts", content: importA, }; - const cTs: ts.projectSystem.File = { + const cTs: File = { path: "/project/c.ts", content: importCurlyFromA }; - const dTs: ts.projectSystem.File = { + const dTs: File = { path: "/project/d.ts", content: [importAFromA, typeofImportA].join("\n") }; - const tsconfig: ts.projectSystem.File = { + const tsconfig: File = { path: "/project/tsconfig.json", content: "{}", }; function makeSampleSession() { - const host = ts.projectSystem.createServerHost([aTs, bTs, cTs, dTs, tsconfig]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([aTs, bTs, cTs, dTs], session); + const host = createServerHost([aTs, bTs, cTs, dTs, tsconfig]); + const session = createSession(host); + openFilesForSession([aTs, bTs, cTs, dTs], session); return session; } it("should get file references", () => { const session = makeSampleSession(); - const response = ts.projectSystem.executeSessionRequest( + const response = executeSessionRequest( session, - ts.projectSystem.protocol.CommandTypes.FileReferences, + CommandTypes.FileReferences, { file: aTs.path }, ); - const expectResponse: ts.projectSystem.protocol.FileReferencesResponseBody = { + const expectResponse: FileReferencesResponseBody = { refs: [ - ts.projectSystem.makeReferenceItem({ file: bTs, text: "./a", lineText: importA, contextText: importA, isWriteAccess: false }), - ts.projectSystem.makeReferenceItem({ file: cTs, text: "./a", lineText: importCurlyFromA, contextText: importCurlyFromA, isWriteAccess: false }), - ts.projectSystem.makeReferenceItem({ file: dTs, text: "/project/a", lineText: importAFromA, contextText: importAFromA, isWriteAccess: false }), - ts.projectSystem.makeReferenceItem({ file: dTs, text: "./a", lineText: typeofImportA, contextText: typeofImportA, isWriteAccess: false }), + makeReferenceItem({ file: bTs, text: "./a", lineText: importA, contextText: importA, isWriteAccess: false }), + makeReferenceItem({ file: cTs, text: "./a", lineText: importCurlyFromA, contextText: importCurlyFromA, isWriteAccess: false }), + makeReferenceItem({ file: dTs, text: "/project/a", lineText: importAFromA, contextText: importAFromA, isWriteAccess: false }), + makeReferenceItem({ file: dTs, text: "./a", lineText: typeofImportA, contextText: typeofImportA, isWriteAccess: false }), ], symbolName: `"${aTs.path}"`, }; diff --git a/src/testRunner/unittests/tsserver/helpers.ts b/src/testRunner/unittests/tsserver/helpers.ts index a781e1bdc2a83..c6fd0ad893228 100644 --- a/src/testRunner/unittests/tsserver/helpers.ts +++ b/src/testRunner/unittests/tsserver/helpers.ts @@ -1,36 +1,78 @@ -import * as Harness from "../../_namespaces/Harness"; +import { convertToObject } from "../../../compiler/commandLineParser"; +import { + arrayFrom, clear, filterMutate, isArray, isString, map, mapDefined, mapDefinedIterator, noop, notImplemented, + returnFalse, returnTrue, returnUndefined, +} from "../../../compiler/core"; +import { ESMap, Map, MapLike, SortedReadonlyArray, version } from "../../../compiler/corePublic"; +import { Debug } from "../../../compiler/debug"; +import { parseJsonText } from "../../../compiler/parser"; +import { combinePaths, directorySeparator, forEachAncestorDirectory, normalizePath } from "../../../compiler/path"; +import { computeLineAndCharacterOfPosition, computeLineStarts } from "../../../compiler/scanner"; +import { sys } from "../../../compiler/sys"; +import { Path, TypeAcquisition } from "../../../compiler/types"; +import { createTextSpan, textSpanEnd } from "../../../compiler/utilitiesPublic"; +import { TestFSWithWatch } from "../../../harness/_namespaces/ts"; +import { Baseline } from "../../../harness/harnessIO"; +import { byteLength } from "../../../harness/harnessUtils"; +import { + checkArray, checkWatchedDirectories, checkWatchedDirectoriesDetailed, checkWatchedFiles, checkWatchedFilesDetailed, + createServerHost, libFile, safeList, TestServerHost, +} from "../../../harness/virtualFileSystemWithWatch"; +import { InvalidateCachedTypings, SetTypings } from "../../../jsTyping/types"; +import { protocol } from "../../../server/_namespaces/ts.server"; +import { + FileStats, OpenFileInfo, OpenFileInfoTelemetryEvent, OpenFileInfoTelemetryEventData, ProjectInfoTelemetryEvent, + ProjectInfoTelemetryEventData, ProjectService, ProjectServiceEvent, ProjectServiceOptions, +} from "../../../server/editorServices"; +import { Project, ProjectKind } from "../../../server/project"; +import { + AnyEvent, CommandTypes, Event, ExternalFile, FileLocationRequestArgs, FileRequestArgs, FileSpan, + FileSpanWithContext, GeterrForProjectRequest, GeterrRequest, Location, OpenRequestArgs, ReferencesResponseItem, + RenameTextSpan, Request, Response, SemanticDiagnosticsSyncRequest, SuggestionDiagnosticsSyncRequest, + SyntacticDiagnosticsSyncRequest, TextSpan, TextSpanWithContext, +} from "../../../server/protocol"; +import { + CommandNames, nullCancellationToken, ServerCancellationToken, Session, SessionOptions, toEvent, +} from "../../../server/session"; +import { ServerHost } from "../../../server/types"; +import { ITypingsInstaller, nullTypingsInstaller } from "../../../server/typingsCache"; +import { createInstallTypingsRequest, LogLevel } from "../../../server/utilitiesPublic"; +import { HostCancellationToken } from "../../../services/types"; +import { typingsInstaller as TI } from "../../../typingsInstallerCore/_namespaces/ts.server"; +import { Log, RequestCompletedAction, TypingsInstaller } from "../../../typingsInstallerCore/typingsInstaller"; import * as ts from "../../_namespaces/ts"; -import * as Utils from "../../_namespaces/Utils"; - -export import TI = ts.server.typingsInstaller; -export import protocol = ts.server.protocol; -export import CommandNames = ts.server.CommandNames; - -export import TestServerHost = ts.TestFSWithWatch.TestServerHost; -export type File = ts.TestFSWithWatch.File; -export type SymLink = ts.TestFSWithWatch.SymLink; -export type Folder = ts.TestFSWithWatch.Folder; -export import createServerHost = ts.TestFSWithWatch.createServerHost; -export import checkArray = ts.TestFSWithWatch.checkArray; -export import libFile = ts.TestFSWithWatch.libFile; -export import checkWatchedFiles = ts.TestFSWithWatch.checkWatchedFiles; -export import checkWatchedFilesDetailed = ts.TestFSWithWatch.checkWatchedFilesDetailed; -export import checkWatchedDirectories = ts.TestFSWithWatch.checkWatchedDirectories; -export import checkWatchedDirectoriesDetailed = ts.TestFSWithWatch.checkWatchedDirectoriesDetailed; - -export import commonFile1 = ts.tscWatch.commonFile1; -export import commonFile2 = ts.tscWatch.commonFile2; +import { server } from "../../_namespaces/ts"; +import { commonFile1, commonFile2 } from "../tscWatch/helpers"; + +export { TI }; +export { protocol }; +export { CommandNames }; + +export { TestServerHost }; +export type File = TestFSWithWatch.File; +export type SymLink = TestFSWithWatch.SymLink; +export type Folder = TestFSWithWatch.Folder; +export { createServerHost }; +export { checkArray }; +export { libFile }; +export { checkWatchedFiles }; +export { checkWatchedFilesDetailed }; +export { checkWatchedDirectories }; +export { checkWatchedDirectoriesDetailed }; + +export { commonFile1 }; +export { commonFile2 }; const outputEventRegex = /Content\-Length: [\d]+\r\n\r\n/; export function mapOutputToJson(s: string) { - return ts.convertToObject( - ts.parseJsonText("json.json", s.replace(outputEventRegex, "")), + return convertToObject( + parseJsonText("json.json", s.replace(outputEventRegex, "")), [] ); } export const customTypesMap = { - path: "/typesMap.json" as ts.Path, + path: "/typesMap.json" as Path, content: `{ "typesMap": { "jquery": { @@ -55,24 +97,24 @@ export const customTypesMap = { export interface PostExecAction { readonly success: boolean; - readonly callback: TI.RequestCompletedAction; + readonly callback: RequestCompletedAction; } -export interface Logger extends ts.server.Logger { +export interface Logger extends server.Logger { logs: string[]; } export function nullLogger(): Logger { return { - 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, + close: noop, + hasLevel: returnFalse, + loggingEnabled: returnFalse, + perftrc: noop, + info: noop, + msg: noop, + startGroup: noop, + endGroup: noop, + getLogFileName: returnUndefined, logs: [], }; } @@ -80,15 +122,15 @@ export function nullLogger(): Logger { export function createHasErrorMessageLogger(): Logger { return { ...nullLogger(), - msg: (s, type) => ts.Debug.fail(`Error: ${s}, type: ${type}`), + msg: (s, type) => Debug.fail(`Error: ${s}, type: ${type}`), }; } export function createLoggerWritingToConsole(): Logger { return { ...nullLogger(), - hasLevel: ts.returnTrue, - loggingEnabled: ts.returnTrue, + hasLevel: returnTrue, + loggingEnabled: returnTrue, perftrc: s => console.log(s), info: s => console.log(s), msg: (s, type) => console.log(`${type}:: ${s}`), @@ -99,30 +141,30 @@ export function createLoggerWithInMemoryLogs(): Logger { const logger = createHasErrorMessageLogger(); return { ...logger, - hasLevel: ts.returnTrue, - loggingEnabled: ts.returnTrue, + hasLevel: returnTrue, + loggingEnabled: returnTrue, info: s => logger.logs.push( s.replace(/Elapsed::?\s*\d+(?:\.\d+)?ms/g, "Elapsed:: *ms") .replace(/\"updateGraphDurationMs\"\:\d+(?:\.\d+)?/g, `"updateGraphDurationMs":*`) .replace(/\"createAutoImportProviderProgramDurationMs\"\:\d+(?:\.\d+)?/g, `"createAutoImportProviderProgramDurationMs":*`) - .replace(`"version":"${ts.version}"`, `"version":"FakeVersion"`) + .replace(`"version":"${version}"`, `"version":"FakeVersion"`) ) }; } export function baselineTsserverLogs(scenario: string, subScenario: string, sessionOrService: TestSession | TestProjectService) { - ts.Debug.assert(sessionOrService.logger.logs.length); // Ensure caller used in memory logger - Harness.Baseline.runBaseline(`tsserver/${scenario}/${subScenario.split(" ").join("-")}.js`, sessionOrService.logger.logs.join("\r\n")); + Debug.assert(sessionOrService.logger.logs.length); // Ensure caller used in memory logger + Baseline.runBaseline(`tsserver/${scenario}/${subScenario.split(" ").join("-")}.js`, sessionOrService.logger.logs.join("\r\n")); } -export function appendAllScriptInfos(service: ts.server.ProjectService, logs: string[]) { +export function appendAllScriptInfos(service: ProjectService, logs: string[]) { logs.push(""); logs.push(`ScriptInfos:`); service.filenameToScriptInfo.forEach(info => logs.push(`path: ${info.path} fileName: ${info.fileName}`)); logs.push(""); } -export function appendProjectFileText(project: ts.server.Project, logs: string[]) { +export function appendProjectFileText(project: Project, logs: string[]) { logs.push(""); logs.push(`Project: ${project.getProjectName()}`); project.getCurrentProgram()?.getSourceFiles().forEach(f => { @@ -133,22 +175,22 @@ export function appendProjectFileText(project: ts.server.Project, logs: string[] logs.push(""); } -export class TestTypingsInstaller extends TI.TypingsInstaller implements ts.server.ITypingsInstaller { - protected projectService!: ts.server.ProjectService; +export class TestTypingsInstaller extends TypingsInstaller implements ITypingsInstaller { + protected projectService!: ProjectService; constructor( readonly globalTypingsCacheLocation: string, throttleLimit: number, - installTypingHost: ts.server.ServerHost, - readonly typesRegistry = new ts.Map>(), - log?: TI.Log) { - super(installTypingHost, globalTypingsCacheLocation, ts.TestFSWithWatch.safeList.path, customTypesMap.path, throttleLimit, log); + installTypingHost: ServerHost, + readonly typesRegistry = new Map>(), + log?: Log) { + super(installTypingHost, globalTypingsCacheLocation, safeList.path, customTypesMap.path, throttleLimit, log); } protected postExecActions: PostExecAction[] = []; - isKnownTypesPackageName = ts.notImplemented; - installPackage = ts.notImplemented; - inspectValue = ts.notImplemented; + isKnownTypesPackageName = notImplemented; + installPackage = notImplemented; + inspectValue = notImplemented; executePendingCommands() { const actionsToRun = this.postExecActions; @@ -162,9 +204,9 @@ export class TestTypingsInstaller extends TI.TypingsInstaller implements ts.serv assert.equal(this.postExecActions.length, expectedCount, `Expected ${expectedCount} post install actions`); } - onProjectClosed = ts.noop; + onProjectClosed = noop; - attach(projectService: ts.server.ProjectService) { + attach(projectService: ProjectService) { this.projectService = projectService; } @@ -172,21 +214,21 @@ export class TestTypingsInstaller extends TI.TypingsInstaller implements ts.serv return this.installTypingHost; } - installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { + installWorker(_requestId: number, _args: string[], _cwd: string, cb: RequestCompletedAction): void { this.addPostExecAction("success", cb); } - sendResponse(response: ts.server.SetTypings | ts.server.InvalidateCachedTypings) { + sendResponse(response: SetTypings | InvalidateCachedTypings) { this.projectService.updateTypingsForProject(response); } - enqueueInstallTypingsRequest(project: ts.server.Project, typeAcquisition: ts.TypeAcquisition, unresolvedImports: ts.SortedReadonlyArray) { - const request = ts.server.createInstallTypingsRequest(project, typeAcquisition, unresolvedImports, this.globalTypingsCacheLocation); + enqueueInstallTypingsRequest(project: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray) { + const request = createInstallTypingsRequest(project, typeAcquisition, unresolvedImports, this.globalTypingsCacheLocation); this.install(request); } - addPostExecAction(stdout: string | string[], cb: TI.RequestCompletedAction) { - const out = ts.isString(stdout) ? stdout : createNpmPackageJsonString(stdout); + addPostExecAction(stdout: string | string[], cb: RequestCompletedAction) { + const out = isString(stdout) ? stdout : createNpmPackageJsonString(stdout); const action: PostExecAction = { success: !!out, callback: cb @@ -196,14 +238,14 @@ export class TestTypingsInstaller extends TI.TypingsInstaller implements ts.serv } function createNpmPackageJsonString(installedTypings: string[]): string { - const dependencies: ts.MapLike = {}; + const dependencies: MapLike = {}; for (const typing of installedTypings) { dependencies[typing] = "1.0.0"; } return JSON.stringify({ dependencies }); } -export function createTypesRegistry(...list: string[]): ts.ESMap> { +export function createTypesRegistry(...list: string[]): ESMap> { const versionMap = { "latest": "1.3.0", "ts2.0": "1.0.0", @@ -215,29 +257,29 @@ export function createTypesRegistry(...list: string[]): ts.ESMap>(); + const map = new Map>(); for (const l of list) { map.set(l, versionMap); } return map; } -export function toExternalFile(fileName: string): protocol.ExternalFile { +export function toExternalFile(fileName: string): ExternalFile { return { fileName }; } export function toExternalFiles(fileNames: string[]) { - return ts.map(fileNames, toExternalFile); + return map(fileNames, toExternalFile); } -export function fileStats(nonZeroStats: Partial): ts.server.FileStats { +export function fileStats(nonZeroStats: Partial): FileStats { return { ts: 0, tsSize: 0, tsx: 0, tsxSize: 0, dts: 0, dtsSize: 0, js: 0, jsSize: 0, jsx: 0, jsxSize: 0, deferred: 0, deferredSize: 0, ...nonZeroStats }; } export class TestServerEventManager { - private events: ts.server.ProjectServiceEvent[] = []; + private events: ProjectServiceEvent[] = []; readonly session: TestSession; - readonly service: ts.server.ProjectService; + readonly service: ProjectService; readonly host: TestServerHost; constructor(files: File[], suppressDiagnosticEvents?: boolean) { this.host = createServerHost(files); @@ -249,15 +291,15 @@ export class TestServerEventManager { this.service = this.session.getProjectService(); } - getEvents(): readonly ts.server.ProjectServiceEvent[] { + getEvents(): readonly ProjectServiceEvent[] { const events = this.events; this.events = []; return events; } - getEvent(eventName: T["eventName"]): T["data"] { + getEvent(eventName: T["eventName"]): T["data"] { let eventData: T["data"] | undefined; - ts.filterMutate(this.events, e => { + filterMutate(this.events, e => { if (e.eventName === eventName) { if (eventData !== undefined) { assert(false, "more than one event found"); @@ -267,16 +309,16 @@ export class TestServerEventManager { } return true; }); - return ts.Debug.checkDefined(eventData); + return Debug.checkDefined(eventData); } - hasZeroEvent(eventName: T["eventName"]) { + hasZeroEvent(eventName: T["eventName"]) { this.events.forEach(event => assert.notEqual(event.eventName, eventName)); } - assertProjectInfoTelemetryEvent(partial: Partial, configFile = "/tsconfig.json"): void { - assert.deepEqual(this.getEvent(ts.server.ProjectInfoTelemetryEvent), { - projectId: ts.sys.createSHA256Hash!(configFile), + assertProjectInfoTelemetryEvent(partial: Partial, configFile = "/tsconfig.json"): void { + assert.deepEqual(this.getEvent(ProjectInfoTelemetryEvent), { + projectId: sys.createSHA256Hash!(configFile), fileStats: fileStats({ ts: 1 }), compilerOptions: {}, extends: false, @@ -292,26 +334,26 @@ export class TestServerEventManager { configFileName: "tsconfig.json", projectType: "configured", languageServiceEnabled: true, - version: ts.version, // eslint-disable-line @typescript-eslint/no-unnecessary-qualifier + version: version, // eslint-disable-line @typescript-eslint/no-unnecessary-qualifier ...partial, }); } - assertOpenFileTelemetryEvent(info: ts.server.OpenFileInfo): void { - assert.deepEqual(this.getEvent(ts.server.OpenFileInfoTelemetryEvent), { info }); + assertOpenFileTelemetryEvent(info: OpenFileInfo): void { + assert.deepEqual(this.getEvent(OpenFileInfoTelemetryEvent), { info }); } assertNoOpenFilesTelemetryEvent(): void { - this.hasZeroEvent(ts.server.OpenFileInfoTelemetryEvent); + this.hasZeroEvent(OpenFileInfoTelemetryEvent); } } -export interface TestSessionOptions extends ts.server.SessionOptions { +export interface TestSessionOptions extends SessionOptions { logger: Logger; } -export class TestSession extends ts.server.Session { +export class TestSession extends Session { private seq = 0; - public events: protocol.Event[] = []; + public events: Event[] = []; public testhost: TestServerHost = this.host as TestServerHost; public logger: Logger; @@ -332,15 +374,15 @@ export class TestSession extends ts.server.Session { return this.seq + 1; } - public executeCommand(request: protocol.Request) { - const verboseLogging = this.logger.hasLevel(ts.server.LogLevel.verbose); + public executeCommand(request: Request) { + const verboseLogging = this.logger.hasLevel(LogLevel.verbose); if (verboseLogging) this.logger.info(`request:${JSON.stringify(request)}`); const result = super.executeCommand(request); if (verboseLogging) this.logger.info(`response:${JSON.stringify(result)}`); return result; } - public executeCommandSeq(request: Partial) { + public executeCommandSeq(request: Partial) { this.seq++; request.seq = this.seq; request.type = "request"; @@ -348,17 +390,17 @@ export class TestSession extends ts.server.Session { } public event(body: T, eventName: string) { - this.events.push(ts.server.toEvent(eventName, body)); + this.events.push(toEvent(eventName, body)); super.event(body, eventName); } public clearMessages() { - ts.clear(this.events); + clear(this.events); this.testhost.clearOutput(); } } -export function createSession(host: ts.server.ServerHost, opts: Partial = {}) { +export function createSession(host: ServerHost, opts: Partial = {}) { if (opts.typingsInstaller === undefined) { opts.typingsInstaller = new TestTypingsInstaller("/a/data/", /*throttleLimit*/ 5, host); } @@ -369,11 +411,11 @@ export function createSession(host: ts.server.ServerHost, opts: Partial(host: ts.server.ServerHost, eventName: T["eventName"], ...eventNames: T["eventName"][]) { +export function createSessionWithEventTracking(host: ServerHost, eventName: T["eventName"], ...eventNames: T["eventName"][]) { const events: T[] = []; const session = createSession(host, { eventHandler: e => { @@ -395,7 +437,7 @@ export function createSessionWithEventTracking(host: TestServerHost, eventNames: T["event"] | T["event"][], opts: Partial = {}) { +export function createSessionWithDefaultEventHandler(host: TestServerHost, eventNames: T["event"] | T["event"][], opts: Partial = {}) { const session = createSession(host, { canUseEvents: true, ...opts }); return { @@ -405,9 +447,9 @@ export function createSessionWithDefaultEventHandler { + return mapDefined(host.getOutput(), s => { const e = mapOutputToJson(s); - return (ts.isArray(eventNames) ? eventNames.some(eventName => e.event === eventName) : e.event === eventNames) ? e as T : undefined; + return (isArray(eventNames) ? eventNames.some(eventName => e.event === eventName) : e.event === eventNames) ? e as T : undefined; }); } @@ -416,13 +458,13 @@ export function createSessionWithDefaultEventHandler = {}) { +export class TestProjectService extends ProjectService { + constructor(host: ServerHost, public logger: Logger, cancellationToken: HostCancellationToken, useSingleInferredProject: boolean, + typingsInstaller: ITypingsInstaller, opts: Partial = {}) { super({ host, logger, @@ -441,71 +483,71 @@ export class TestProjectService extends ts.server.ProjectService { } } -export function createProjectService(host: ts.server.ServerHost, options?: Partial) { - const cancellationToken = options?.cancellationToken || ts.server.nullCancellationToken; +export function createProjectService(host: ServerHost, options?: Partial) { + const cancellationToken = options?.cancellationToken || nullCancellationToken; const logger = options?.logger || createHasErrorMessageLogger(); const useSingleInferredProject = options?.useSingleInferredProject !== undefined ? options.useSingleInferredProject : false; - return new TestProjectService(host, logger, cancellationToken, useSingleInferredProject, options?.typingsInstaller || ts.server.nullTypingsInstaller, options); + return new TestProjectService(host, logger, cancellationToken, useSingleInferredProject, options?.typingsInstaller || nullTypingsInstaller, options); } -export function checkNumberOfConfiguredProjects(projectService: ts.server.ProjectService, expected: number) { +export function checkNumberOfConfiguredProjects(projectService: ProjectService, expected: number) { assert.equal(projectService.configuredProjects.size, expected, `expected ${expected} configured project(s)`); } -export function checkNumberOfExternalProjects(projectService: ts.server.ProjectService, expected: number) { +export function checkNumberOfExternalProjects(projectService: ProjectService, expected: number) { assert.equal(projectService.externalProjects.length, expected, `expected ${expected} external project(s)`); } -export function checkNumberOfInferredProjects(projectService: ts.server.ProjectService, expected: number) { +export function checkNumberOfInferredProjects(projectService: ProjectService, expected: number) { assert.equal(projectService.inferredProjects.length, expected, `expected ${expected} inferred project(s)`); } -export function checkNumberOfProjects(projectService: ts.server.ProjectService, count: { inferredProjects?: number, configuredProjects?: number, externalProjects?: number }) { +export function checkNumberOfProjects(projectService: ProjectService, count: { inferredProjects?: number, configuredProjects?: number, externalProjects?: number }) { checkNumberOfConfiguredProjects(projectService, count.configuredProjects || 0); checkNumberOfExternalProjects(projectService, count.externalProjects || 0); checkNumberOfInferredProjects(projectService, count.inferredProjects || 0); } -export function configuredProjectAt(projectService: ts.server.ProjectService, index: number) { +export function configuredProjectAt(projectService: ProjectService, index: number) { const values = projectService.configuredProjects.values(); while (index > 0) { const iterResult = values.next(); - if (iterResult.done) return ts.Debug.fail("Expected a result."); + if (iterResult.done) return Debug.fail("Expected a result."); index--; } const iterResult = values.next(); - if (iterResult.done) return ts.Debug.fail("Expected a result."); + if (iterResult.done) return Debug.fail("Expected a result."); return iterResult.value; } -export function checkOrphanScriptInfos(service: ts.server.ProjectService, expectedFiles: readonly string[]) { - checkArray("Orphan ScriptInfos:", ts.arrayFrom(ts.mapDefinedIterator( +export function checkOrphanScriptInfos(service: ProjectService, expectedFiles: readonly string[]) { + checkArray("Orphan ScriptInfos:", arrayFrom(mapDefinedIterator( service.filenameToScriptInfo.values(), v => v.containingProjects.length === 0 ? v.fileName : undefined )), expectedFiles); } -export function checkProjectActualFiles(project: ts.server.Project, expectedFiles: readonly string[]) { - checkArray(`${ts.server.ProjectKind[project.projectKind]} project: ${project.getProjectName()}:: actual files`, project.getFileNames(), expectedFiles); +export function checkProjectActualFiles(project: Project, expectedFiles: readonly string[]) { + checkArray(`${ProjectKind[project.projectKind]} project: ${project.getProjectName()}:: actual files`, project.getFileNames(), expectedFiles); } -export function checkProjectRootFiles(project: ts.server.Project, expectedFiles: readonly string[]) { - checkArray(`${ts.server.ProjectKind[project.projectKind]} project: ${project.getProjectName()}::, rootFileNames`, project.getRootFiles(), expectedFiles); +export function checkProjectRootFiles(project: Project, expectedFiles: readonly string[]) { + checkArray(`${ProjectKind[project.projectKind]} project: ${project.getProjectName()}::, rootFileNames`, project.getRootFiles(), expectedFiles); } export function mapCombinedPathsInAncestor(dir: string, path2: string, mapAncestor: (ancestor: string) => boolean) { - dir = ts.normalizePath(dir); + dir = normalizePath(dir); const result: string[] = []; - ts.forEachAncestorDirectory(dir, ancestor => { + forEachAncestorDirectory(dir, ancestor => { if (mapAncestor(ancestor)) { - result.push(ts.combinePaths(ancestor, path2)); + result.push(combinePaths(ancestor, path2)); } }); return result; } export function getRootsToWatchWithAncestorDirectory(dir: string, path2: string) { - return mapCombinedPathsInAncestor(dir, path2, ancestor => ancestor.split(ts.directorySeparator).length > 4); + return mapCombinedPathsInAncestor(dir, path2, ancestor => ancestor.split(directorySeparator).length > 4); } export const nodeModules = "node_modules"; @@ -525,32 +567,32 @@ export function getConfigFilesToWatch(folder: string) { ]; } -export function checkOpenFiles(projectService: ts.server.ProjectService, expectedFiles: File[]) { - checkArray("Open files", ts.arrayFrom(projectService.openFiles.keys(), path => projectService.getScriptInfoForPath(path as ts.Path)!.fileName), expectedFiles.map(file => file.path)); +export function checkOpenFiles(projectService: ProjectService, expectedFiles: File[]) { + checkArray("Open files", arrayFrom(projectService.openFiles.keys(), path => projectService.getScriptInfoForPath(path as Path)!.fileName), expectedFiles.map(file => file.path)); } -export function checkScriptInfos(projectService: ts.server.ProjectService, expectedFiles: readonly string[], additionInfo?: string) { - checkArray(`ScriptInfos files: ${additionInfo || ""}`, ts.arrayFrom(projectService.filenameToScriptInfo.values(), info => info.fileName), expectedFiles); +export function checkScriptInfos(projectService: ProjectService, expectedFiles: readonly string[], additionInfo?: string) { + checkArray(`ScriptInfos files: ${additionInfo || ""}`, arrayFrom(projectService.filenameToScriptInfo.values(), info => info.fileName), expectedFiles); } -export function protocolLocationFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): protocol.Location { +export function protocolLocationFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): Location { const start = nthIndexOf(str, substring, options ? options.index : 0); - ts.Debug.assert(start !== -1); + Debug.assert(start !== -1); return protocolToLocation(str)(start); } -export function protocolToLocation(text: string): (pos: number) => protocol.Location { - const lineStarts = ts.computeLineStarts(text); +export function protocolToLocation(text: string): (pos: number) => Location { + const lineStarts = computeLineStarts(text); return pos => { - const x = ts.computeLineAndCharacterOfPosition(lineStarts, pos); + const x = computeLineAndCharacterOfPosition(lineStarts, pos); return { line: x.line + 1, offset: x.character + 1 }; }; } -export function protocolTextSpanFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): protocol.TextSpan { +export function protocolTextSpanFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): TextSpan { const span = textSpanFromSubstring(str, substring, options); const toLocation = protocolToLocation(str); - return { start: toLocation(span.start), end: toLocation(ts.textSpanEnd(span)) }; + return { start: toLocation(span.start), end: toLocation(textSpanEnd(span)) }; } export interface DocumentSpanFromSubstring { @@ -560,7 +602,7 @@ export interface DocumentSpanFromSubstring { contextText?: string; contextOptions?: SpanFromSubstringOptions; } -export function protocolFileSpanFromSubstring({ file, text, options }: DocumentSpanFromSubstring): protocol.FileSpan { +export function protocolFileSpanFromSubstring({ file, text, options }: DocumentSpanFromSubstring): FileSpan { return { file: file.path, ...protocolTextSpanFromSubstring(file.content, text, options) }; } @@ -571,7 +613,7 @@ interface FileSpanWithContextFromSubString { contextText?: string; contextOptions?: SpanFromSubstringOptions; } -export function protocolFileSpanWithContextFromSubstring({ contextText, contextOptions, ...rest }: FileSpanWithContextFromSubString): protocol.FileSpanWithContext { +export function protocolFileSpanWithContextFromSubstring({ contextText, contextOptions, ...rest }: FileSpanWithContextFromSubString): FileSpanWithContext { const result = protocolFileSpanFromSubstring(rest); const contextSpan = contextText !== undefined ? protocolFileSpanFromSubstring({ file: rest.file, text: contextText, options: contextOptions }) : @@ -592,16 +634,16 @@ export interface ProtocolTextSpanWithContextFromString { contextText?: string; contextOptions?: SpanFromSubstringOptions; } -export function protocolTextSpanWithContextFromSubstring({ fileText, text, options, contextText, contextOptions }: ProtocolTextSpanWithContextFromString): protocol.TextSpanWithContext { +export function protocolTextSpanWithContextFromSubstring({ fileText, text, options, contextText, contextOptions }: ProtocolTextSpanWithContextFromString): TextSpanWithContext { const span = textSpanFromSubstring(fileText, text, options); const toLocation = protocolToLocation(fileText); const contextSpan = contextText !== undefined ? textSpanFromSubstring(fileText, contextText, contextOptions) : undefined; return { start: toLocation(span.start), - end: toLocation(ts.textSpanEnd(span)), + end: toLocation(textSpanEnd(span)), ...contextSpan && { contextStart: toLocation(contextSpan.start), - contextEnd: toLocation(ts.textSpanEnd(contextSpan)) + contextEnd: toLocation(textSpanEnd(contextSpan)) } }; } @@ -612,7 +654,7 @@ export interface ProtocolRenameSpanFromSubstring extends ProtocolTextSpanWithCon readonly suffixText?: string; }; } -export function protocolRenameSpanFromSubstring({ prefixSuffixText, ...rest }: ProtocolRenameSpanFromSubstring): protocol.RenameTextSpan { +export function protocolRenameSpanFromSubstring({ prefixSuffixText, ...rest }: ProtocolRenameSpanFromSubstring): RenameTextSpan { return { ...protocolTextSpanWithContextFromSubstring(rest), ...prefixSuffixText @@ -621,11 +663,11 @@ export function protocolRenameSpanFromSubstring({ prefixSuffixText, ...rest }: P export function textSpanFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): ts.TextSpan { const start = nthIndexOf(str, substring, options ? options.index : 0); - ts.Debug.assert(start !== -1); - return ts.createTextSpan(start, substring.length); + Debug.assert(start !== -1); + return createTextSpan(start, substring.length); } -export function protocolFileLocationFromSubstring(file: File, substring: string, options?: SpanFromSubstringOptions): protocol.FileLocationRequestArgs { +export function protocolFileLocationFromSubstring(file: File, substring: string, options?: SpanFromSubstringOptions): FileLocationRequestArgs { return { file: file.path, ...protocolLocationFromSubstring(file.content, substring, options) }; } @@ -648,7 +690,7 @@ function nthIndexOf(str: string, substr: string, n: number): number { * should be made before canceling the token. The id of the request to cancel should be set with * setRequestToCancel(); */ -export class TestServerCancellationToken implements ts.server.ServerCancellationToken { +export class TestServerCancellationToken implements ServerCancellationToken { private currentId: number | undefined = -1; private requestToCancel = -1; private isCancellationRequestedCount = 0; @@ -685,7 +727,7 @@ export class TestServerCancellationToken implements ts.server.ServerCancellation } } -export function makeSessionRequest(command: string, args: T): protocol.Request { +export function makeSessionRequest(command: string, args: T): Request { return { seq: 0, type: "request", @@ -694,24 +736,24 @@ export function makeSessionRequest(command: string, args: T): protocol.Reques }; } -export function executeSessionRequest(session: ts.server.Session, command: TRequest["command"], args: TRequest["arguments"]): TResponse["body"] { +export function executeSessionRequest(session: Session, command: TRequest["command"], args: TRequest["arguments"]): TResponse["body"] { return session.executeCommand(makeSessionRequest(command, args)).response as TResponse["body"]; } -export function executeSessionRequestNoResponse(session: ts.server.Session, command: TRequest["command"], args: TRequest["arguments"]): void { +export function executeSessionRequestNoResponse(session: Session, command: TRequest["command"], args: TRequest["arguments"]): void { session.executeCommand(makeSessionRequest(command, args)); } -export function openFilesForSession(files: readonly (File | { readonly file: File | string, readonly projectRootPath: string, content?: string })[], session: ts.server.Session): void { +export function openFilesForSession(files: readonly (File | { readonly file: File | string, readonly projectRootPath: string, content?: string })[], session: Session): void { for (const file of files) { - session.executeCommand(makeSessionRequest(CommandNames.Open, + session.executeCommand(makeSessionRequest(CommandNames.Open, "projectRootPath" in file ? { file: typeof file.file === "string" ? file.file : file.file.path, projectRootPath: file.projectRootPath } : { file: file.path })); // eslint-disable-line no-in-operator } } -export function closeFilesForSession(files: readonly File[], session: ts.server.Session): void { +export function closeFilesForSession(files: readonly File[], session: Session): void { for (const file of files) { - session.executeCommand(makeSessionRequest(CommandNames.Close, { file: file.path })); + session.executeCommand(makeSessionRequest(CommandNames.Close, { file: file.path })); } } @@ -721,7 +763,7 @@ export interface MakeReferenceItem extends DocumentSpanFromSubstring { lineText: string; } -export function makeReferenceItem({ isDefinition, isWriteAccess, lineText, ...rest }: MakeReferenceItem): protocol.ReferencesResponseItem { +export function makeReferenceItem({ isDefinition, isWriteAccess, lineText, ...rest }: MakeReferenceItem): ReferencesResponseItem { return { ...protocolFileSpanWithContextFromSubstring(rest), isDefinition, @@ -741,8 +783,8 @@ export interface VerifyGetErrRequest extends VerifyGetErrRequestBase { } export function verifyGetErrRequest(request: VerifyGetErrRequest) { const { session, files } = request; - session.executeCommandSeq({ - command: protocol.CommandTypes.Geterr, + session.executeCommandSeq({ + command: CommandTypes.Geterr, arguments: { delay: 0, files: files.map(filePath) } }); checkAllErrors(request); @@ -754,7 +796,7 @@ export interface CheckAllErrors extends VerifyGetErrRequestBase { skip?: readonly (SkipErrors | undefined)[]; } function checkAllErrors({ session, host, existingTimeouts, files, skip }: CheckAllErrors) { - ts.Debug.assert(session.logger.logs.length); + Debug.assert(session.logger.logs.length); for (let i = 0; i < files.length; i++) { if (existingTimeouts !== undefined) { host.checkTimeoutQueueLength(existingTimeouts + 1); @@ -769,7 +811,7 @@ function checkAllErrors({ session, host, existingTimeouts, files, skip }: CheckA } function filePath(file: string | File) { - return ts.isString(file) ? file : file.path; + return isString(file) ? file : file.path; } function verifyErrorsUsingGeterr({scenario, subScenario, allFiles, openFiles, getErrRequest }: VerifyGetErrScenario) { @@ -790,8 +832,8 @@ function verifyErrorsUsingGeterrForProject({ scenario, subScenario, allFiles, op openFilesForSession(openFiles(), session); for (const expected of getErrForProjectRequest()) { - session.executeCommandSeq({ - command: protocol.CommandTypes.GeterrForProject, + session.executeCommandSeq({ + command: CommandTypes.GeterrForProject, arguments: { delay: 0, file: filePath(expected.project) } }); checkAllErrors({ session, host, files: expected.files }); @@ -807,16 +849,16 @@ function verifyErrorsUsingSyncMethods({ scenario, subScenario, allFiles, openFil openFilesForSession(openFiles(), session); for (const { file, project } of syncDiagnostics()) { const reqArgs = { file: filePath(file), projectFileName: project && filePath(project) }; - session.executeCommandSeq({ - command: protocol.CommandTypes.SyntacticDiagnosticsSync, + session.executeCommandSeq({ + command: CommandTypes.SyntacticDiagnosticsSync, arguments: reqArgs }); - session.executeCommandSeq({ - command: protocol.CommandTypes.SemanticDiagnosticsSync, + session.executeCommandSeq({ + command: CommandTypes.SemanticDiagnosticsSync, arguments: reqArgs }); - session.executeCommandSeq({ - command: protocol.CommandTypes.SuggestionDiagnosticsSync, + session.executeCommandSeq({ + command: CommandTypes.SuggestionDiagnosticsSync, arguments: reqArgs }); } diff --git a/src/testRunner/unittests/tsserver/importHelpers.ts b/src/testRunner/unittests/tsserver/importHelpers.ts index 8e761c5d25a90..9bd9cddd748e9 100644 --- a/src/testRunner/unittests/tsserver/importHelpers.ts +++ b/src/testRunner/unittests/tsserver/importHelpers.ts @@ -1,4 +1,4 @@ -import * as ts from "../../_namespaces/ts"; +import { createProjectService, createServerHost, toExternalFile } from "./helpers"; describe("unittests:: tsserver:: import helpers", () => { it("should not crash in tsserver", () => { @@ -10,9 +10,9 @@ describe("unittests:: tsserver:: import helpers", () => { path: "/a/node_modules/tslib/index.d.ts", content: "" }; - const host = ts.projectSystem.createServerHost([f1, tslib]); - const service = ts.projectSystem.createProjectService(host); - service.openExternalProject({ projectFileName: "p", rootFiles: [ts.projectSystem.toExternalFile(f1.path)], options: { importHelpers: true } }); + const host = createServerHost([f1, tslib]); + const service = createProjectService(host); + service.openExternalProject({ projectFileName: "p", rootFiles: [toExternalFile(f1.path)], options: { importHelpers: true } }); service.checkNumberOfProjects({ externalProjects: 1 }); }); }); diff --git a/src/testRunner/unittests/tsserver/inferredProjects.ts b/src/testRunner/unittests/tsserver/inferredProjects.ts index 7a2fef15200de..76ea85e1cdaea 100644 --- a/src/testRunner/unittests/tsserver/inferredProjects.ts +++ b/src/testRunner/unittests/tsserver/inferredProjects.ts @@ -1,42 +1,52 @@ -import * as ts from "../../_namespaces/ts"; +import { Map } from "../../../compiler/corePublic"; +import { combinePaths } from "../../../compiler/path"; +import { ModuleResolutionKind, ScriptKind, ScriptTarget } from "../../../compiler/types"; +import { InferredProject } from "../../../server/project"; +import { OpenRequest, SetCompilerOptionsForInferredProjectsRequest } from "../../../server/protocol"; +import { projectRoot } from "../tscWatch/helpers"; +import { + checkArray, checkNumberOfConfiguredProjects, checkNumberOfInferredProjects, checkNumberOfProjects, + checkProjectActualFiles, checkWatchedDirectories, checkWatchedFiles, CommandNames, commonFile1, + createProjectService, createServerHost, createSession, File, getConfigFilesToWatch, libFile, nodeModulesAtTypes, +} from "./helpers"; describe("unittests:: tsserver:: Inferred projects", () => { it("create inferred project", () => { - const appFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/app.ts`, + const appFile: File = { + path: `${projectRoot}/app.ts`, content: ` import {f} from "./module" console.log(f) ` }; - const moduleFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/module.d.ts`, + const moduleFile: File = { + path: `${projectRoot}/module.d.ts`, content: `export let x: number` }; - const host = ts.projectSystem.createServerHost([appFile, moduleFile, ts.projectSystem.libFile]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([appFile, moduleFile, libFile]); + const projectService = createProjectService(host); const { configFileName } = projectService.openClientFile(appFile.path); assert(!configFileName, `should not find config, got: '${configFileName}`); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 0); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 1); + checkNumberOfConfiguredProjects(projectService, 0); + checkNumberOfInferredProjects(projectService, 1); const project = projectService.inferredProjects[0]; - ts.projectSystem.checkArray("inferred project", project.getFileNames(), [appFile.path, ts.projectSystem.libFile.path, moduleFile.path]); - ts.projectSystem.checkWatchedFiles(host, ts.projectSystem.getConfigFilesToWatch(ts.tscWatch.projectRoot).concat(ts.projectSystem.libFile.path, moduleFile.path)); - ts.projectSystem.checkWatchedDirectories(host, [ts.tscWatch.projectRoot], /*recursive*/ false); - ts.projectSystem.checkWatchedDirectories(host, [ts.combinePaths(ts.tscWatch.projectRoot, ts.projectSystem.nodeModulesAtTypes)], /*recursive*/ true); + checkArray("inferred project", project.getFileNames(), [appFile.path, libFile.path, moduleFile.path]); + checkWatchedFiles(host, getConfigFilesToWatch(projectRoot).concat(libFile.path, moduleFile.path)); + checkWatchedDirectories(host, [projectRoot], /*recursive*/ false); + checkWatchedDirectories(host, [combinePaths(projectRoot, nodeModulesAtTypes)], /*recursive*/ true); }); it("should use only one inferred project if 'useOneInferredProject' is set", () => { const file1 = { - path: `${ts.tscWatch.projectRoot}/a/b/main.ts`, + path: `${projectRoot}/a/b/main.ts`, content: "let x =1;" }; - const configFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/a/b/tsconfig.json`, + const configFile: File = { + path: `${projectRoot}/a/b/tsconfig.json`, content: `{ "compilerOptions": { "target": "es6" @@ -45,31 +55,31 @@ describe("unittests:: tsserver:: Inferred projects", () => { }` }; const file2 = { - path: `${ts.tscWatch.projectRoot}/a/c/main.ts`, + path: `${projectRoot}/a/c/main.ts`, content: "let x =1;" }; const file3 = { - path: `${ts.tscWatch.projectRoot}/a/d/main.ts`, + path: `${projectRoot}/a/d/main.ts`, content: "let x =1;" }; - const host = ts.projectSystem.createServerHost([file1, file2, file3, ts.projectSystem.libFile]); - const projectService = ts.projectSystem.createProjectService(host, { useSingleInferredProject: true }); + const host = createServerHost([file1, file2, file3, libFile]); + const projectService = createProjectService(host, { useSingleInferredProject: true }); projectService.openClientFile(file1.path); projectService.openClientFile(file2.path); projectService.openClientFile(file3.path); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 0); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 1); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file1.path, file2.path, file3.path, ts.projectSystem.libFile.path]); + checkNumberOfConfiguredProjects(projectService, 0); + checkNumberOfInferredProjects(projectService, 1); + checkProjectActualFiles(projectService.inferredProjects[0], [file1.path, file2.path, file3.path, libFile.path]); host.writeFile(configFile.path, configFile.content); host.checkTimeoutQueueLengthAndRun(2); // load configured project from disk + ensureProjectsForOpenFiles - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 1); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file2.path, file3.path, ts.projectSystem.libFile.path]); + checkNumberOfConfiguredProjects(projectService, 1); + checkNumberOfInferredProjects(projectService, 1); + checkProjectActualFiles(projectService.inferredProjects[0], [file2.path, file3.path, libFile.path]); }); it("disable inferred project", () => { @@ -78,12 +88,12 @@ describe("unittests:: tsserver:: Inferred projects", () => { content: "let x =1;" }; - const host = ts.projectSystem.createServerHost([file1]); - const projectService = ts.projectSystem.createProjectService(host, { useSingleInferredProject: true, syntaxOnly: true }); + const host = createServerHost([file1]); + const projectService = createProjectService(host, { useSingleInferredProject: true, syntaxOnly: true }); projectService.openClientFile(file1.path, file1.content); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); const proj = projectService.inferredProjects[0]; assert.isDefined(proj); @@ -99,23 +109,23 @@ describe("unittests:: tsserver:: Inferred projects", () => { path: "/a/mod.ts", content: "export let x: number" }; - const host = ts.projectSystem.createServerHost([file1, modFile]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, modFile]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); projectService.openClientFile(modFile.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 2 }); + checkNumberOfProjects(projectService, { inferredProjects: 2 }); const inferredProjects = projectService.inferredProjects.slice(); - ts.projectSystem.checkProjectActualFiles(inferredProjects[0], [file1.path]); - ts.projectSystem.checkProjectActualFiles(inferredProjects[1], [modFile.path]); + checkProjectActualFiles(inferredProjects[0], [file1.path]); + checkProjectActualFiles(inferredProjects[1], [modFile.path]); - projectService.setCompilerOptionsForInferredProjects({ moduleResolution: ts.ModuleResolutionKind.Classic }); + projectService.setCompilerOptionsForInferredProjects({ moduleResolution: ModuleResolutionKind.Classic }); host.checkTimeoutQueueLengthAndRun(3); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 2 }); + checkNumberOfProjects(projectService, { inferredProjects: 2 }); assert.strictEqual(projectService.inferredProjects[0], inferredProjects[0]); assert.strictEqual(projectService.inferredProjects[1], inferredProjects[1]); - ts.projectSystem.checkProjectActualFiles(inferredProjects[0], [file1.path, modFile.path]); + checkProjectActualFiles(inferredProjects[0], [file1.path, modFile.path]); assert.isTrue(inferredProjects[1].isOrphan()); }); @@ -124,8 +134,8 @@ describe("unittests:: tsserver:: Inferred projects", () => { path: "/a/compile", content: "let x = 1" }; - const host = ts.projectSystem.createServerHost([f]); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([f]); + const session = createSession(host); session.executeCommand({ seq: 1, type: "request", @@ -135,7 +145,7 @@ describe("unittests:: tsserver:: Inferred projects", () => { allowJs: true } } - } as ts.server.protocol.SetCompilerOptionsForInferredProjectsRequest); + } as SetCompilerOptionsForInferredProjectsRequest); session.executeCommand({ seq: 2, type: "request", @@ -145,10 +155,10 @@ describe("unittests:: tsserver:: Inferred projects", () => { fileContent: f.content, scriptKindName: "JS" } - } as ts.server.protocol.OpenRequest); + } as OpenRequest); const projectService = session.getProjectService(); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [f.path]); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkProjectActualFiles(projectService.inferredProjects[0], [f.path]); }); it("inferred projects per project root", () => { @@ -156,171 +166,171 @@ describe("unittests:: tsserver:: Inferred projects", () => { const file2 = { path: "/a/file2.ts", content: "let y = 2;", projectRootPath: "/a" }; const file3 = { path: "/b/file2.ts", content: "let x = 3;", projectRootPath: "/b" }; const file4 = { path: "/c/file3.ts", content: "let z = 4;" }; - const host = ts.projectSystem.createServerHost([file1, file2, file3, file4]); - const session = ts.projectSystem.createSession(host, { + const host = createServerHost([file1, file2, file3, file4]); + const session = createSession(host, { useSingleInferredProject: true, useInferredProjectPerProjectRoot: true }); session.executeCommand({ seq: 1, type: "request", - command: ts.projectSystem.CommandNames.CompilerOptionsForInferredProjects, + command: CommandNames.CompilerOptionsForInferredProjects, arguments: { options: { allowJs: true, - target: ts.ScriptTarget.ESNext + target: ScriptTarget.ESNext } } - } as ts.server.protocol.SetCompilerOptionsForInferredProjectsRequest); + } as SetCompilerOptionsForInferredProjectsRequest); session.executeCommand({ seq: 2, type: "request", - command: ts.projectSystem.CommandNames.CompilerOptionsForInferredProjects, + command: CommandNames.CompilerOptionsForInferredProjects, arguments: { options: { allowJs: true, - target: ts.ScriptTarget.ES2015 + target: ScriptTarget.ES2015 }, projectRootPath: "/b" } - } as ts.server.protocol.SetCompilerOptionsForInferredProjectsRequest); + } as SetCompilerOptionsForInferredProjectsRequest); session.executeCommand({ seq: 3, type: "request", - command: ts.projectSystem.CommandNames.Open, + command: CommandNames.Open, arguments: { file: file1.path, fileContent: file1.content, scriptKindName: "JS", projectRootPath: file1.projectRootPath } - } as ts.server.protocol.OpenRequest); + } as OpenRequest); session.executeCommand({ seq: 4, type: "request", - command: ts.projectSystem.CommandNames.Open, + command: CommandNames.Open, arguments: { file: file2.path, fileContent: file2.content, scriptKindName: "JS", projectRootPath: file2.projectRootPath } - } as ts.server.protocol.OpenRequest); + } as OpenRequest); session.executeCommand({ seq: 5, type: "request", - command: ts.projectSystem.CommandNames.Open, + command: CommandNames.Open, arguments: { file: file3.path, fileContent: file3.content, scriptKindName: "JS", projectRootPath: file3.projectRootPath } - } as ts.server.protocol.OpenRequest); + } as OpenRequest); session.executeCommand({ seq: 6, type: "request", - command: ts.projectSystem.CommandNames.Open, + command: CommandNames.Open, arguments: { file: file4.path, fileContent: file4.content, scriptKindName: "JS" } - } as ts.server.protocol.OpenRequest); + } as OpenRequest); const projectService = session.getProjectService(); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 3 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file4.path]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [file1.path, file2.path]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[2], [file3.path]); - assert.equal(projectService.inferredProjects[0].getCompilationSettings().target, ts.ScriptTarget.ESNext); - assert.equal(projectService.inferredProjects[1].getCompilationSettings().target, ts.ScriptTarget.ESNext); - assert.equal(projectService.inferredProjects[2].getCompilationSettings().target, ts.ScriptTarget.ES2015); + checkNumberOfProjects(projectService, { inferredProjects: 3 }); + checkProjectActualFiles(projectService.inferredProjects[0], [file4.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [file1.path, file2.path]); + checkProjectActualFiles(projectService.inferredProjects[2], [file3.path]); + assert.equal(projectService.inferredProjects[0].getCompilationSettings().target, ScriptTarget.ESNext); + assert.equal(projectService.inferredProjects[1].getCompilationSettings().target, ScriptTarget.ESNext); + assert.equal(projectService.inferredProjects[2].getCompilationSettings().target, ScriptTarget.ES2015); }); - function checkInferredProject(inferredProject: ts.server.InferredProject, actualFiles: ts.projectSystem.File[], target: ts.ScriptTarget) { - ts.projectSystem.checkProjectActualFiles(inferredProject, actualFiles.map(f => f.path)); + function checkInferredProject(inferredProject: InferredProject, actualFiles: File[], target: ScriptTarget) { + checkProjectActualFiles(inferredProject, actualFiles.map(f => f.path)); assert.equal(inferredProject.getCompilationSettings().target, target); } function verifyProjectRootWithCaseSensitivity(useCaseSensitiveFileNames: boolean) { - const files: [ts.projectSystem.File, ts.projectSystem.File, ts.projectSystem.File, ts.projectSystem.File] = [ + const files: [File, File, File, File] = [ { path: "/a/file1.ts", content: "let x = 1;" }, { path: "/A/file2.ts", content: "let y = 2;" }, { path: "/b/file2.ts", content: "let x = 3;" }, { path: "/c/file3.ts", content: "let z = 4;" } ]; - const host = ts.projectSystem.createServerHost(files, { useCaseSensitiveFileNames }); - const projectService = ts.projectSystem.createProjectService(host, { useSingleInferredProject: true, useInferredProjectPerProjectRoot: true }); + const host = createServerHost(files, { useCaseSensitiveFileNames }); + const projectService = createProjectService(host, { useSingleInferredProject: true, useInferredProjectPerProjectRoot: true }); projectService.setCompilerOptionsForInferredProjects({ allowJs: true, - target: ts.ScriptTarget.ESNext + target: ScriptTarget.ESNext }); projectService.setCompilerOptionsForInferredProjects({ allowJs: true, - target: ts.ScriptTarget.ES2015 + target: ScriptTarget.ES2015 }, "/a"); openClientFiles(["/a", "/a", "/b", undefined]); verifyInferredProjectsState([ - [[files[3]], ts.ScriptTarget.ESNext], - [[files[0], files[1]], ts.ScriptTarget.ES2015], - [[files[2]], ts.ScriptTarget.ESNext] + [[files[3]], ScriptTarget.ESNext], + [[files[0], files[1]], ScriptTarget.ES2015], + [[files[2]], ScriptTarget.ESNext] ]); closeClientFiles(); openClientFiles(["/a", "/A", "/b", undefined]); if (useCaseSensitiveFileNames) { verifyInferredProjectsState([ - [[files[3]], ts.ScriptTarget.ESNext], - [[files[0]], ts.ScriptTarget.ES2015], - [[files[1]], ts.ScriptTarget.ESNext], - [[files[2]], ts.ScriptTarget.ESNext] + [[files[3]], ScriptTarget.ESNext], + [[files[0]], ScriptTarget.ES2015], + [[files[1]], ScriptTarget.ESNext], + [[files[2]], ScriptTarget.ESNext] ]); } else { verifyInferredProjectsState([ - [[files[3]], ts.ScriptTarget.ESNext], - [[files[0], files[1]], ts.ScriptTarget.ES2015], - [[files[2]], ts.ScriptTarget.ESNext] + [[files[3]], ScriptTarget.ESNext], + [[files[0], files[1]], ScriptTarget.ES2015], + [[files[2]], ScriptTarget.ESNext] ]); } closeClientFiles(); projectService.setCompilerOptionsForInferredProjects({ allowJs: true, - target: ts.ScriptTarget.ES2017 + target: ScriptTarget.ES2017 }, "/A"); openClientFiles(["/a", "/a", "/b", undefined]); verifyInferredProjectsState([ - [[files[3]], ts.ScriptTarget.ESNext], - [[files[0], files[1]], useCaseSensitiveFileNames ? ts.ScriptTarget.ES2015 : ts.ScriptTarget.ES2017], - [[files[2]], ts.ScriptTarget.ESNext] + [[files[3]], ScriptTarget.ESNext], + [[files[0], files[1]], useCaseSensitiveFileNames ? ScriptTarget.ES2015 : ScriptTarget.ES2017], + [[files[2]], ScriptTarget.ESNext] ]); closeClientFiles(); openClientFiles(["/a", "/A", "/b", undefined]); if (useCaseSensitiveFileNames) { verifyInferredProjectsState([ - [[files[3]], ts.ScriptTarget.ESNext], - [[files[0]], ts.ScriptTarget.ES2015], - [[files[1]], ts.ScriptTarget.ES2017], - [[files[2]], ts.ScriptTarget.ESNext] + [[files[3]], ScriptTarget.ESNext], + [[files[0]], ScriptTarget.ES2015], + [[files[1]], ScriptTarget.ES2017], + [[files[2]], ScriptTarget.ESNext] ]); } else { verifyInferredProjectsState([ - [[files[3]], ts.ScriptTarget.ESNext], - [[files[0], files[1]], ts.ScriptTarget.ES2017], - [[files[2]], ts.ScriptTarget.ESNext] + [[files[3]], ScriptTarget.ESNext], + [[files[0], files[1]], ScriptTarget.ES2017], + [[files[2]], ScriptTarget.ESNext] ]); } closeClientFiles(); function openClientFiles(projectRoots: [string | undefined, string | undefined, string | undefined, string | undefined]) { files.forEach((file, index) => { - projectService.openClientFile(file.path, file.content, ts.ScriptKind.JS, projectRoots[index]); + projectService.openClientFile(file.path, file.content, ScriptKind.JS, projectRoots[index]); }); } @@ -328,8 +338,8 @@ describe("unittests:: tsserver:: Inferred projects", () => { files.forEach(file => projectService.closeClientFile(file.path)); } - function verifyInferredProjectsState(expected: [ts.projectSystem.File[], ts.ScriptTarget][]) { - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: expected.length }); + function verifyInferredProjectsState(expected: [File[], ScriptTarget][]) { + checkNumberOfProjects(projectService, { inferredProjects: expected.length }); projectService.inferredProjects.forEach((p, index) => { const [actualFiles, target] = expected[index]; checkInferredProject(p, actualFiles, target); @@ -346,28 +356,28 @@ describe("unittests:: tsserver:: Inferred projects", () => { }); it("should still retain configured project created while opening the file", () => { - const appFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/app.ts`, + const appFile: File = { + path: `${projectRoot}/app.ts`, content: `const app = 20;` }; - const config: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: "{}" }; - const jsFile1: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/jsFile1.js`, + const jsFile1: File = { + path: `${projectRoot}/jsFile1.js`, content: `const jsFile1 = 10;` }; - const jsFile2: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/jsFile2.js`, + const jsFile2: File = { + path: `${projectRoot}/jsFile2.js`, content: `const jsFile2 = 10;` }; - const host = ts.projectSystem.createServerHost([appFile, ts.projectSystem.libFile, config, jsFile1, jsFile2]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([appFile, libFile, config, jsFile1, jsFile2]); + const projectService = createProjectService(host); const originalSet = projectService.configuredProjects.set; const originalDelete = projectService.configuredProjects.delete; - const configuredCreated = new ts.Map(); - const configuredRemoved = new ts.Map(); + const configuredCreated = new Map(); + const configuredRemoved = new Map(); projectService.configuredProjects.set = (key, value) => { assert.isFalse(configuredCreated.has(key)); configuredCreated.set(key, true); @@ -381,34 +391,34 @@ describe("unittests:: tsserver:: Inferred projects", () => { // Do not remove config project when opening jsFile that is not present as part of config project projectService.openClientFile(jsFile1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1, configuredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [jsFile1.path, ts.projectSystem.libFile.path]); + checkNumberOfProjects(projectService, { inferredProjects: 1, configuredProjects: 1 }); + checkProjectActualFiles(projectService.inferredProjects[0], [jsFile1.path, libFile.path]); const project = projectService.configuredProjects.get(config.path)!; - ts.projectSystem.checkProjectActualFiles(project, [appFile.path, config.path, ts.projectSystem.libFile.path]); + checkProjectActualFiles(project, [appFile.path, config.path, libFile.path]); checkConfiguredProjectCreatedAndNotDeleted(); // Do not remove config project when opening jsFile that is not present as part of config project projectService.closeClientFile(jsFile1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1, configuredProjects: 1 }); + checkNumberOfProjects(projectService, { inferredProjects: 1, configuredProjects: 1 }); projectService.openClientFile(jsFile2.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1, configuredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [jsFile2.path, ts.projectSystem.libFile.path]); - ts.projectSystem.checkProjectActualFiles(project, [appFile.path, config.path, ts.projectSystem.libFile.path]); + checkNumberOfProjects(projectService, { inferredProjects: 1, configuredProjects: 1 }); + checkProjectActualFiles(projectService.inferredProjects[0], [jsFile2.path, libFile.path]); + checkProjectActualFiles(project, [appFile.path, config.path, libFile.path]); checkConfiguredProjectNotCreatedAndNotDeleted(); // Do not remove config project when opening jsFile that is not present as part of config project projectService.openClientFile(jsFile1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 2, configuredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [jsFile2.path, ts.projectSystem.libFile.path]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [jsFile1.path, ts.projectSystem.libFile.path]); - ts.projectSystem.checkProjectActualFiles(project, [appFile.path, config.path, ts.projectSystem.libFile.path]); + checkNumberOfProjects(projectService, { inferredProjects: 2, configuredProjects: 1 }); + checkProjectActualFiles(projectService.inferredProjects[0], [jsFile2.path, libFile.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [jsFile1.path, libFile.path]); + checkProjectActualFiles(project, [appFile.path, config.path, libFile.path]); checkConfiguredProjectNotCreatedAndNotDeleted(); // When opening file that doesnt fall back to the config file, we remove the config project - projectService.openClientFile(ts.projectSystem.libFile.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 2 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [jsFile2.path, ts.projectSystem.libFile.path]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [jsFile1.path, ts.projectSystem.libFile.path]); + projectService.openClientFile(libFile.path); + checkNumberOfProjects(projectService, { inferredProjects: 2 }); + checkProjectActualFiles(projectService.inferredProjects[0], [jsFile2.path, libFile.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [jsFile1.path, libFile.path]); checkConfiguredProjectNotCreatedButDeleted(); function checkConfiguredProjectCreatedAndNotDeleted() { @@ -433,15 +443,15 @@ describe("unittests:: tsserver:: Inferred projects", () => { it("regression test - should infer typeAcquisition for inferred projects when set undefined", () => { const file1 = { path: "/a/file1.js", content: "" }; - const host = ts.projectSystem.createServerHost([file1]); + const host = createServerHost([file1]); - const projectService = ts.projectSystem.createProjectService(host); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); const inferredProject = projectService.inferredProjects[0]; - ts.projectSystem.checkProjectActualFiles(inferredProject, [file1.path]); + checkProjectActualFiles(inferredProject, [file1.path]); inferredProject.setTypeAcquisition(undefined); const expected = { @@ -453,11 +463,11 @@ describe("unittests:: tsserver:: Inferred projects", () => { }); it("Setting compiler options for inferred projects when there are no open files should not schedule any refresh", () => { - const host = ts.projectSystem.createServerHost([ts.projectSystem.commonFile1, ts.projectSystem.libFile]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([commonFile1, libFile]); + const projectService = createProjectService(host); projectService.setCompilerOptionsForInferredProjects({ allowJs: true, - target: ts.ScriptTarget.ES2015 + target: ScriptTarget.ES2015 }); host.checkTimeoutQueueLength(0); }); diff --git a/src/testRunner/unittests/tsserver/inlayHints.ts b/src/testRunner/unittests/tsserver/inlayHints.ts index 5efb091e978c4..989e2bb593cd4 100644 --- a/src/testRunner/unittests/tsserver/inlayHints.ts +++ b/src/testRunner/unittests/tsserver/inlayHints.ts @@ -1,63 +1,68 @@ -import * as ts from "../../_namespaces/ts"; +import { Debug } from "../../../compiler/debug"; +import { UserPreferences } from "../../../compiler/types"; +import { + CommandTypes, ConfigureRequest, InlayHintItem, InlayHintsRequest, OpenRequest, UpdateOpenRequest, +} from "../../../server/protocol"; +import { commonFile1, commonFile2, createServerHost, createSession, File, libFile, TestSession } from "./helpers"; describe("unittests:: tsserver:: inlayHints", () => { - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: "{}" }; - const app: ts.projectSystem.File = { + const app: File = { path: "/a/b/app.ts", content: "declare function foo(param: any): void;\nfoo(12);" }; it("with updateOpen request does not corrupt documents", () => { - const host = ts.projectSystem.createServerHost([app, ts.projectSystem.commonFile1, ts.projectSystem.commonFile2, ts.projectSystem.libFile, configFile]); - const session = ts.projectSystem.createSession(host); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Open, + const host = createServerHost([app, commonFile1, commonFile2, libFile, configFile]); + const session = createSession(host); + session.executeCommandSeq({ + command: CommandTypes.Open, arguments: { file: app.path } }); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Configure, + session.executeCommandSeq({ + command: CommandTypes.Configure, arguments: { preferences: { includeInlayParameterNameHints: "all" - } as ts.UserPreferences + } as UserPreferences } }); verifyInlayHintResponse(session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.UpdateOpen, + session.executeCommandSeq({ + command: CommandTypes.UpdateOpen, arguments: { changedFiles: [{ fileName: app.path, textChanges: [{ start: { line: 1, offset: 39 }, end: { line: 1, offset: 39 }, newText: "//" }] }] } }); verifyInlayHintResponse(session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.UpdateOpen, + session.executeCommandSeq({ + command: CommandTypes.UpdateOpen, arguments: { changedFiles: [{ fileName: app.path, textChanges: [{ start: { line: 1, offset: 41 }, end: { line: 1, offset: 41 }, newText: "c" }] }] } }); verifyInlayHintResponse(session); - function verifyInlayHintResponse(session: ts.projectSystem.TestSession) { - verifyParamInlayHint(session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.ProvideInlayHints, + function verifyInlayHintResponse(session: TestSession) { + verifyParamInlayHint(session.executeCommandSeq({ + command: CommandTypes.ProvideInlayHints, arguments: { file: app.path, start: 0, length: app.content.length, } - }).response as ts.projectSystem.protocol.InlayHintItem[] | undefined); + }).response as InlayHintItem[] | undefined); } - function verifyParamInlayHint(response: ts.projectSystem.protocol.InlayHintItem[] | undefined) { - ts.Debug.assert(response); - ts.Debug.assert(response[0]); - ts.Debug.assertEqual(response[0].text, "param:"); - ts.Debug.assertEqual(response[0].position.line, 2); - ts.Debug.assertEqual(response[0].position.offset, 5); + function verifyParamInlayHint(response: InlayHintItem[] | undefined) { + Debug.assert(response); + Debug.assert(response[0]); + Debug.assertEqual(response[0].text, "param:"); + Debug.assertEqual(response[0].position.line, 2); + Debug.assertEqual(response[0].position.offset, 5); } }); }); diff --git a/src/testRunner/unittests/tsserver/jsdocTag.ts b/src/testRunner/unittests/tsserver/jsdocTag.ts index 74e42c619aec4..8ed37a0fbb9a1 100644 --- a/src/testRunner/unittests/tsserver/jsdocTag.ts +++ b/src/testRunner/unittests/tsserver/jsdocTag.ts @@ -1,7 +1,11 @@ -import * as ts from "../../_namespaces/ts"; +import { + CommandTypes, CompletionDetailsRequest, CompletionDetailsRequestArgs, FileLocationRequestArgs, QuickInfoRequest, + SignatureHelpRequest, SignatureHelpRequestArgs, +} from "../../../server/protocol"; +import { createServerHost, createSession, File, openFilesForSession } from "./helpers"; describe("unittests:: tsserver:: jsdoc @link ", () => { - const config: ts.projectSystem.File = { + const config: File = { path: "/a/tsconfig.json", content: `{ "compilerOptions": { @@ -12,26 +16,26 @@ describe("unittests:: tsserver:: jsdoc @link ", () => { } ` }; - function assertQuickInfoJSDoc(file: ts.projectSystem.File, options: { + function assertQuickInfoJSDoc(file: File, options: { displayPartsForJSDoc: boolean, - command: ts.projectSystem.protocol.CommandTypes, + command: CommandTypes, tags: string | unknown[] | undefined, documentation: string | unknown[] }) { const { command, displayPartsForJSDoc, tags, documentation } = options; - const session = ts.projectSystem.createSession(ts.projectSystem.createServerHost([file, config])); + const session = createSession(createServerHost([file, config])); session.getProjectService().setHostConfiguration({ preferences: { displayPartsForJSDoc } }); - ts.projectSystem.openFilesForSession([file], session); + openFilesForSession([file], session); const indexOfX = file.content.indexOf("x"); - const quickInfo = session.executeCommandSeq({ - command: command as ts.projectSystem.protocol.CommandTypes.Quickinfo, + const quickInfo = session.executeCommandSeq({ + command: command as CommandTypes.Quickinfo, arguments: { file: file.path, position: indexOfX, - } as ts.projectSystem.protocol.FileLocationRequestArgs + } as FileLocationRequestArgs }).response; - const summaryAndLocation = command === ts.projectSystem.protocol.CommandTypes.Quickinfo ? { + const summaryAndLocation = command === CommandTypes.Quickinfo ? { displayString: "var x: number", start: { line: 3, @@ -75,13 +79,13 @@ describe("unittests:: tsserver:: jsdoc @link ", () => { }); } - const linkInTag: ts.projectSystem.File = { + const linkInTag: File = { path: "/a/someFile1.js", content: `class C { } /** @wat {@link C} */ var x = 1` }; - const linkInComment: ts.projectSystem.File = { + const linkInComment: File = { path: "/a/someFile1.js", content: `class C { } /** {@link C} */ @@ -91,7 +95,7 @@ var x = 1 it("for quickinfo, should provide display parts plus a span for a working link in a tag", () => { assertQuickInfoJSDoc(linkInTag, { - command: ts.projectSystem.protocol.CommandTypes.Quickinfo, + command: CommandTypes.Quickinfo, displayPartsForJSDoc: true, documentation: [], tags: [{ @@ -125,7 +129,7 @@ var x = 1 }); it("for quickinfo, should provide a string for a working link in a tag", () => { assertQuickInfoJSDoc(linkInTag, { - command: ts.projectSystem.protocol.CommandTypes.Quickinfo, + command: CommandTypes.Quickinfo, displayPartsForJSDoc: false, documentation: "", tags: [{ @@ -136,7 +140,7 @@ var x = 1 }); it("for quickinfo, should provide display parts for a working link in a comment", () => { assertQuickInfoJSDoc(linkInComment, { - command: ts.projectSystem.protocol.CommandTypes.Quickinfo, + command: CommandTypes.Quickinfo, displayPartsForJSDoc: true, documentation: [{ kind: "text", @@ -167,7 +171,7 @@ var x = 1 }); it("for quickinfo, should provide a string for a working link in a comment", () => { assertQuickInfoJSDoc(linkInComment, { - command: ts.projectSystem.protocol.CommandTypes.Quickinfo, + command: CommandTypes.Quickinfo, displayPartsForJSDoc: false, documentation: "{@link C}", tags: [], @@ -176,7 +180,7 @@ var x = 1 it("for quickinfo-full, should provide display parts plus a span for a working link in a tag", () => { assertQuickInfoJSDoc(linkInTag, { - command: ts.projectSystem.protocol.CommandTypes.QuickinfoFull, + command: CommandTypes.QuickinfoFull, displayPartsForJSDoc: true, documentation: [], tags: [{ @@ -206,7 +210,7 @@ var x = 1 }); it("for quickinfo-full, should provide a string for a working link in a tag", () => { assertQuickInfoJSDoc(linkInTag, { - command: ts.projectSystem.protocol.CommandTypes.QuickinfoFull, + command: CommandTypes.QuickinfoFull, displayPartsForJSDoc: false, documentation: [], tags: [{ @@ -217,7 +221,7 @@ var x = 1 }); it("for quickinfo-full, should provide display parts plus a span for a working link in a comment", () => { assertQuickInfoJSDoc(linkInComment, { - command: ts.projectSystem.protocol.CommandTypes.QuickinfoFull, + command: CommandTypes.QuickinfoFull, displayPartsForJSDoc: true, documentation: [{ kind: "text", @@ -244,7 +248,7 @@ var x = 1 }); it("for quickinfo-full, should provide a string for a working link in a comment", () => { assertQuickInfoJSDoc(linkInComment, { - command: ts.projectSystem.protocol.CommandTypes.QuickinfoFull, + command: CommandTypes.QuickinfoFull, displayPartsForJSDoc: false, documentation: [{ kind: "text", @@ -272,11 +276,11 @@ var x = 1 function assertSignatureHelpJSDoc(options: { displayPartsForJSDoc: boolean, - command: ts.projectSystem.protocol.CommandTypes, + command: CommandTypes, documentation: string | unknown[], tags: unknown[] }) { - const linkInParamTag: ts.projectSystem.File = { + const linkInParamTag: File = { path: "/a/someFile1.js", content: `class C { } /** @param y - {@link C} */ @@ -285,21 +289,21 @@ x(1)` }; const { command, displayPartsForJSDoc, documentation, tags } = options; - const session = ts.projectSystem.createSession(ts.projectSystem.createServerHost([linkInParamTag, config])); + const session = createSession(createServerHost([linkInParamTag, config])); session.getProjectService().setHostConfiguration({ preferences: { displayPartsForJSDoc } }); - ts.projectSystem.openFilesForSession([linkInParamTag], session); + openFilesForSession([linkInParamTag], session); const indexOfX = linkInParamTag.content.lastIndexOf("1"); - const signatureHelp = session.executeCommandSeq({ - command: command as ts.projectSystem.protocol.CommandTypes.SignatureHelp, + const signatureHelp = session.executeCommandSeq({ + command: command as CommandTypes.SignatureHelp, arguments: { triggerReason: { kind: "invoked" }, file: linkInParamTag.path, position: indexOfX, - } as ts.projectSystem.protocol.SignatureHelpRequestArgs + } as SignatureHelpRequestArgs }).response; - const applicableSpan = command === ts.projectSystem.protocol.CommandTypes.SignatureHelp ? { + const applicableSpan = command === CommandTypes.SignatureHelp ? { end: { line: 4, offset: 4 @@ -383,7 +387,7 @@ x(1)` } it("for signature help, should provide a string for a working link in a comment", () => { assertSignatureHelpJSDoc({ - command: ts.projectSystem.protocol.CommandTypes.SignatureHelp, + command: CommandTypes.SignatureHelp, displayPartsForJSDoc: false, tags: [{ name: "param", @@ -450,7 +454,7 @@ x(1)` }] }]; assertSignatureHelpJSDoc({ - command: ts.projectSystem.protocol.CommandTypes.SignatureHelp, + command: CommandTypes.SignatureHelp, displayPartsForJSDoc: true, tags, documentation: tags[0].text.slice(2) @@ -458,7 +462,7 @@ x(1)` }); it("for signature help-full, should provide a string for a working link in a comment", () => { assertSignatureHelpJSDoc({ - command: ts.projectSystem.protocol.CommandTypes.SignatureHelpFull, + command: CommandTypes.SignatureHelpFull, displayPartsForJSDoc: false, tags: [{ name: "param", @@ -517,7 +521,7 @@ x(1)` }] }]; assertSignatureHelpJSDoc({ - command: ts.projectSystem.protocol.CommandTypes.SignatureHelpFull, + command: CommandTypes.SignatureHelpFull, displayPartsForJSDoc: true, tags, documentation: tags[0].text.slice(2), @@ -526,10 +530,10 @@ x(1)` function assertCompletionsJSDoc(options: { displayPartsForJSDoc: boolean, - command: ts.projectSystem.protocol.CommandTypes, + command: CommandTypes, tags: unknown[] }) { - const linkInParamJSDoc: ts.projectSystem.File = { + const linkInParamJSDoc: File = { path: "/a/someFile1.js", content: `class C { } /** @param x - see {@link C} */ @@ -537,17 +541,17 @@ function foo (x) { } foo` }; const { command, displayPartsForJSDoc, tags } = options; - const session = ts.projectSystem.createSession(ts.projectSystem.createServerHost([linkInParamJSDoc, config])); + const session = createSession(createServerHost([linkInParamJSDoc, config])); session.getProjectService().setHostConfiguration({ preferences: { displayPartsForJSDoc } }); - ts.projectSystem.openFilesForSession([linkInParamJSDoc], session); + openFilesForSession([linkInParamJSDoc], session); const indexOfFoo = linkInParamJSDoc.content.lastIndexOf("fo"); - const completions = session.executeCommandSeq({ - command: command as ts.projectSystem.protocol.CommandTypes.CompletionDetails, + const completions = session.executeCommandSeq({ + command: command as CommandTypes.CompletionDetails, arguments: { entryNames: ["foo"], file: linkInParamJSDoc.path, position: indexOfFoo, - } as ts.projectSystem.protocol.CompletionDetailsRequestArgs + } as CompletionDetailsRequestArgs }).response; assert.deepEqual(completions, [{ codeActions: undefined, @@ -599,7 +603,7 @@ foo` } it("for completions, should provide display parts for a working link in a comment", () => { assertCompletionsJSDoc({ - command: ts.projectSystem.protocol.CommandTypes.CompletionDetails, + command: CommandTypes.CompletionDetails, displayPartsForJSDoc: true, tags: [{ name: "param", @@ -638,7 +642,7 @@ foo` }); it("for completions, should provide a string for a working link in a comment", () => { assertCompletionsJSDoc({ - command: ts.projectSystem.protocol.CommandTypes.CompletionDetails, + command: CommandTypes.CompletionDetails, displayPartsForJSDoc: false, tags: [{ name: "param", @@ -648,7 +652,7 @@ foo` }); it("for completions-full, should provide display parts for a working link in a comment", () => { assertCompletionsJSDoc({ - command: ts.projectSystem.protocol.CommandTypes.CompletionDetailsFull, + command: CommandTypes.CompletionDetailsFull, displayPartsForJSDoc: true, tags: [{ name: "param", @@ -683,7 +687,7 @@ foo` }); it("for completions-full, should provide a string for a working link in a comment", () => { assertCompletionsJSDoc({ - command: ts.projectSystem.protocol.CommandTypes.CompletionDetailsFull, + command: CommandTypes.CompletionDetailsFull, displayPartsForJSDoc: false, tags: [{ name: "param", diff --git a/src/testRunner/unittests/tsserver/languageService.ts b/src/testRunner/unittests/tsserver/languageService.ts index e6970521b17e6..ef93c42e4eaf4 100644 --- a/src/testRunner/unittests/tsserver/languageService.ts +++ b/src/testRunner/unittests/tsserver/languageService.ts @@ -1,5 +1,6 @@ -import * as ts from "../../_namespaces/ts"; -import * as Utils from "../../_namespaces/Utils"; +import { Debug } from "../../../compiler/debug"; +import { dedent } from "../../../harness/util"; +import { createProjectService, createServerHost } from "./helpers"; describe("unittests:: tsserver:: languageService", () => { it("should work correctly on case-sensitive file systems", () => { @@ -11,8 +12,8 @@ describe("unittests:: tsserver:: languageService", () => { path: "/a/b/app.ts", content: "let x = 1;" }; - const host = ts.projectSystem.createServerHost([lib, f], { executingFilePath: "/a/Lib/tsc.js", useCaseSensitiveFileNames: true }); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([lib, f], { executingFilePath: "/a/Lib/tsc.js", useCaseSensitiveFileNames: true }); + const projectService = createProjectService(host); projectService.openClientFile(f.path); projectService.checkNumberOfProjects({ inferredProjects: 1 }); projectService.inferredProjects[0].getLanguageService().getProgram(); @@ -22,7 +23,7 @@ describe("unittests:: tsserver:: languageService", () => { const files = [ { path: "/project/shared.ts", - content: Utils.dedent` + content: dedent` import {foo_a} from "foo"; ` }, @@ -32,7 +33,7 @@ describe("unittests:: tsserver:: languageService", () => { }, { path: `/project/a/foo.d.ts`, - content: Utils.dedent` + content: dedent` export const foo_a = 1; ` }, @@ -46,7 +47,7 @@ describe("unittests:: tsserver:: languageService", () => { }, { path: `/project/b/foo.d.ts`, - content: Utils.dedent` + content: dedent` export const foo_b = 1; ` }, @@ -56,15 +57,15 @@ describe("unittests:: tsserver:: languageService", () => { } ]; - const host = ts.projectSystem.createServerHost(files, { executingFilePath: "/project/tsc.js", useCaseSensitiveFileNames: true }); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost(files, { executingFilePath: "/project/tsc.js", useCaseSensitiveFileNames: true }); + const projectService = createProjectService(host); projectService.openClientFile(files[3].path); projectService.openClientFile(files[6].path); projectService.checkNumberOfProjects({ configuredProjects: 2 }); const proj1Diags = projectService.configuredProjects.get(files[1].path)!.getLanguageService().getProgram()!.getSemanticDiagnostics(); - ts.Debug.assertEqual(proj1Diags.length, 0); + Debug.assertEqual(proj1Diags.length, 0); const proj2Diags = projectService.configuredProjects.get(files[4].path)!.getLanguageService().getProgram()!.getSemanticDiagnostics(); - ts.Debug.assertEqual(proj2Diags.length, 1); + Debug.assertEqual(proj2Diags.length, 1); }); }); diff --git a/src/testRunner/unittests/tsserver/maxNodeModuleJsDepth.ts b/src/testRunner/unittests/tsserver/maxNodeModuleJsDepth.ts index d69ee55a0cc29..13fbce365da89 100644 --- a/src/testRunner/unittests/tsserver/maxNodeModuleJsDepth.ts +++ b/src/testRunner/unittests/tsserver/maxNodeModuleJsDepth.ts @@ -1,18 +1,19 @@ -import * as ts from "../../_namespaces/ts"; +import { ScriptTarget } from "../../../compiler/types"; +import { checkNumberOfInferredProjects, createProjectService, createServerHost, File, libFile } from "./helpers"; describe("unittests:: tsserver:: maxNodeModuleJsDepth for inferred projects", () => { it("should be set to 2 if the project has js root files", () => { - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/b/file1.js", content: `var t = require("test"); t.` }; - const moduleFile: ts.projectSystem.File = { + const moduleFile: File = { path: "/a/b/node_modules/test/index.js", content: `var v = 10; module.exports = v;` }; - const host = ts.projectSystem.createServerHost([file1, moduleFile]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, moduleFile]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); let project = projectService.inferredProjects[0]; @@ -20,7 +21,7 @@ describe("unittests:: tsserver:: maxNodeModuleJsDepth for inferred projects", () assert.isTrue(options.maxNodeModuleJsDepth === 2); // Assert the option sticks - projectService.setCompilerOptionsForInferredProjects({ target: ts.ScriptTarget.ES2016 }); + projectService.setCompilerOptionsForInferredProjects({ target: ScriptTarget.ES2016 }); project = projectService.inferredProjects[0]; options = project.getCompilationSettings(); assert.isTrue(options.maxNodeModuleJsDepth === 2); @@ -36,11 +37,11 @@ describe("unittests:: tsserver:: maxNodeModuleJsDepth for inferred projects", () content: "let x =1;" }; - const host = ts.projectSystem.createServerHost([file1, file2, ts.projectSystem.libFile]); - const projectService = ts.projectSystem.createProjectService(host, { useSingleInferredProject: true }); + const host = createServerHost([file1, file2, libFile]); + const projectService = createProjectService(host, { useSingleInferredProject: true }); projectService.openClientFile(file1.path); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 1); + checkNumberOfInferredProjects(projectService, 1); let project = projectService.inferredProjects[0]; assert.isUndefined(project.getCompilationSettings().maxNodeModuleJsDepth); diff --git a/src/testRunner/unittests/tsserver/metadataInResponse.ts b/src/testRunner/unittests/tsserver/metadataInResponse.ts index 9918449a896d2..ba13fec386934 100644 --- a/src/testRunner/unittests/tsserver/metadataInResponse.ts +++ b/src/testRunner/unittests/tsserver/metadataInResponse.ts @@ -1,15 +1,23 @@ -import * as Harness from "../../_namespaces/Harness"; -import * as ts from "../../_namespaces/ts"; +import { makeDefaultProxy } from "../../../harness/harnessLanguageService"; +import { PluginCreateInfo } from "../../../server/project"; +import { + CommandTypes, CompletionEntry, CompletionInfo, CompletionsRequest, CompletionsRequestArgs, Request, Response, +} from "../../../server/protocol"; +import { SortText } from "../../../services/completions"; +import { ScriptElementKind } from "../../../services/types"; +import { + createServerHost, createSession, File, mapOutputToJson, openFilesForSession, TestServerHost, TestSession, +} from "./helpers"; describe("unittests:: tsserver:: with metadata in response", () => { const metadata = "Extra Info"; - function verifyOutput(host: ts.projectSystem.TestServerHost, expectedResponse: ts.projectSystem.protocol.Response) { - const output = host.getOutput().map(ts.projectSystem.mapOutputToJson); + function verifyOutput(host: TestServerHost, expectedResponse: Response) { + const output = host.getOutput().map(mapOutputToJson); assert.deepEqual(output, [expectedResponse]); host.clearOutput(); } - function verifyCommandWithMetadata(session: ts.projectSystem.TestSession, host: ts.projectSystem.TestServerHost, command: Partial, expectedResponseBody: U) { + function verifyCommandWithMetadata(session: TestSession, host: TestServerHost, command: Partial, expectedResponseBody: U) { command.seq = session.getSeq(); command.type = "request"; session.onMessage(JSON.stringify(command)); @@ -19,21 +27,21 @@ describe("unittests:: tsserver:: with metadata in response", () => { ); } - const aTs: ts.projectSystem.File = { path: "/a.ts", content: `class c { prop = "hello"; foo() { return this.prop; } }` }; - const tsconfig: ts.projectSystem.File = { + const aTs: File = { path: "/a.ts", content: `class c { prop = "hello"; foo() { return this.prop; } }` }; + const tsconfig: File = { path: "/tsconfig.json", content: JSON.stringify({ compilerOptions: { plugins: [{ name: "myplugin" }] } }) }; - function createHostWithPlugin(files: readonly ts.projectSystem.File[]) { - const host = ts.projectSystem.createServerHost(files); + function createHostWithPlugin(files: readonly File[]) { + const host = createServerHost(files); host.require = (_initialPath, moduleName) => { assert.equal(moduleName, "myplugin"); return { module: () => ({ - create(info: ts.server.PluginCreateInfo) { - const proxy = Harness.LanguageService.makeDefaultProxy(info); + create(info: PluginCreateInfo) { + const proxy = makeDefaultProxy(info); proxy.getCompletionsAtPosition = (filename, position, options) => { const result = info.languageService.getCompletionsAtPosition(filename, position, options); if (result) { @@ -51,32 +59,32 @@ describe("unittests:: tsserver:: with metadata in response", () => { } describe("With completion requests", () => { - const completionRequestArgs: ts.projectSystem.protocol.CompletionsRequestArgs = { + const completionRequestArgs: CompletionsRequestArgs = { file: aTs.path, line: 1, offset: aTs.content.indexOf("this.") + 1 + "this.".length }; - const expectedCompletionEntries: readonly ts.projectSystem.protocol.CompletionEntry[] = [ - { name: "foo", kind: ts.ScriptElementKind.memberFunctionElement, kindModifiers: "", sortText: ts.Completions.SortText.LocationPriority }, - { name: "prop", kind: ts.ScriptElementKind.memberVariableElement, kindModifiers: "", sortText: ts.Completions.SortText.LocationPriority } + const expectedCompletionEntries: readonly CompletionEntry[] = [ + { name: "foo", kind: ScriptElementKind.memberFunctionElement, kindModifiers: "", sortText: SortText.LocationPriority }, + { name: "prop", kind: ScriptElementKind.memberVariableElement, kindModifiers: "", sortText: SortText.LocationPriority } ]; it("can pass through metadata when the command returns array", () => { const host = createHostWithPlugin([aTs, tsconfig]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([aTs], session); - verifyCommandWithMetadata(session, host, { - command: ts.projectSystem.protocol.CommandTypes.Completions, + const session = createSession(host); + openFilesForSession([aTs], session); + verifyCommandWithMetadata(session, host, { + command: CommandTypes.Completions, arguments: completionRequestArgs }, expectedCompletionEntries); }); it("can pass through metadata when the command returns object", () => { const host = createHostWithPlugin([aTs, tsconfig]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([aTs], session); - verifyCommandWithMetadata(session, host, { - command: ts.projectSystem.protocol.CommandTypes.CompletionInfo, + const session = createSession(host); + openFilesForSession([aTs], session); + verifyCommandWithMetadata(session, host, { + command: CommandTypes.CompletionInfo, arguments: completionRequestArgs }, { flags: 0, @@ -92,12 +100,12 @@ describe("unittests:: tsserver:: with metadata in response", () => { }); it("returns undefined correctly", () => { - const aTs: ts.projectSystem.File = { path: "/a.ts", content: `class c { prop = "hello"; foo() { const x = 0; } }` }; + const aTs: File = { path: "/a.ts", content: `class c { prop = "hello"; foo() { const x = 0; } }` }; const host = createHostWithPlugin([aTs, tsconfig]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([aTs], session); - verifyCommandWithMetadata(session, host, { - command: ts.projectSystem.protocol.CommandTypes.Completions, + const session = createSession(host); + openFilesForSession([aTs], session); + verifyCommandWithMetadata(session, host, { + command: CommandTypes.Completions, arguments: { file: aTs.path, line: 1, offset: aTs.content.indexOf("x") + 1 } }, /*expectedResponseBody*/ undefined); }); diff --git a/src/testRunner/unittests/tsserver/moduleSpecifierCache.ts b/src/testRunner/unittests/tsserver/moduleSpecifierCache.ts index 604e95c1c9059..f8c2c7ff2a26a 100644 --- a/src/testRunner/unittests/tsserver/moduleSpecifierCache.ts +++ b/src/testRunner/unittests/tsserver/moduleSpecifierCache.ts @@ -1,38 +1,46 @@ -import * as ts from "../../_namespaces/ts"; - -const packageJson: ts.projectSystem.File = { +import { Path, UserPreferences } from "../../../compiler/types"; +import { + CommandTypes, CompletionInfoResponse, CompletionsRequest, ConfigureRequest, ConfigureResponse, + FileLocationRequestArgs, +} from "../../../server/protocol"; +import { + checkWatchedDirectories, configuredProjectAt, createServerHost, createSession, executeSessionRequest, File, + openFilesForSession, SymLink, +} from "./helpers"; + +const packageJson: File = { path: "/package.json", content: `{ "dependencies": { "mobx": "*" } }` }; -const aTs: ts.projectSystem.File = { +const aTs: File = { path: "/src/a.ts", content: "export const foo = 0;", }; -const bTs: ts.projectSystem.File = { +const bTs: File = { path: "/src/b.ts", content: "foo", }; -const cTs: ts.projectSystem.File = { +const cTs: File = { path: "/src/c.ts", content: "import ", }; -const bSymlink: ts.projectSystem.SymLink = { +const bSymlink: SymLink = { path: "/src/b-link.ts", symLink: "./b.ts", }; -const tsconfig: ts.projectSystem.File = { +const tsconfig: File = { path: "/tsconfig.json", content: `{ "include": ["src"] }`, }; -const ambientDeclaration: ts.projectSystem.File = { +const ambientDeclaration: File = { path: "/src/ambient.d.ts", content: "declare module 'ambient' {}" }; -const mobxPackageJson: ts.projectSystem.File = { +const mobxPackageJson: File = { path: "/node_modules/mobx/package.json", content: `{ "name": "mobx", "version": "1.0.0" }` }; -const mobxDts: ts.projectSystem.File = { +const mobxDts: File = { path: "/node_modules/mobx/index.d.ts", content: "export declare function observable(): unknown;" }; @@ -40,14 +48,14 @@ const mobxDts: ts.projectSystem.File = { describe("unittests:: tsserver:: moduleSpecifierCache", () => { it("caches importability within a file", () => { const { moduleSpecifierCache } = setup(); - assert.isFalse(moduleSpecifierCache.get(bTs.path as ts.Path, aTs.path as ts.Path, {}, {})?.isBlockedByPackageJsonDependencies); + assert.isFalse(moduleSpecifierCache.get(bTs.path as Path, aTs.path as Path, {}, {})?.isBlockedByPackageJsonDependencies); }); it("caches module specifiers within a file", () => { const { moduleSpecifierCache, triggerCompletions } = setup(); // Completion at an import statement will calculate and cache module specifiers triggerCompletions({ file: cTs.path, line: 1, offset: cTs.content.length + 1 }); - const mobxCache = moduleSpecifierCache.get(cTs.path as ts.Path, mobxDts.path as ts.Path, {}, {}); + const mobxCache = moduleSpecifierCache.get(cTs.path as Path, mobxDts.path as Path, {}, {}); assert.deepEqual(mobxCache, { modulePaths: [{ path: mobxDts.path, @@ -63,7 +71,7 @@ describe("unittests:: tsserver:: moduleSpecifierCache", () => { const { host, moduleSpecifierCache, triggerCompletions } = setup(); // Completion at an import statement will calculate and cache module specifiers triggerCompletions({ file: cTs.path, line: 1, offset: cTs.content.length + 1 }); - ts.projectSystem.checkWatchedDirectories(host, ["/src", "/node_modules"], /*recursive*/ true); + checkWatchedDirectories(host, ["/src", "/node_modules"], /*recursive*/ true); host.writeFile("/node_modules/.staging/mobx-12345678/package.json", "{}"); host.runQueuedTimeoutCallbacks(); assert.equal(moduleSpecifierCache.count(), 0); @@ -73,7 +81,7 @@ describe("unittests:: tsserver:: moduleSpecifierCache", () => { const { host, moduleSpecifierCache } = setup(); host.writeFile("/src/a2.ts", aTs.content); host.runQueuedTimeoutCallbacks(); - assert.isFalse(moduleSpecifierCache.get(bTs.path as ts.Path, aTs.path as ts.Path, {}, {})?.isBlockedByPackageJsonDependencies); + assert.isFalse(moduleSpecifierCache.get(bTs.path as Path, aTs.path as Path, {}, {})?.isBlockedByPackageJsonDependencies); }); it("invalidates the cache when symlinks are added or removed", () => { @@ -99,10 +107,10 @@ describe("unittests:: tsserver:: moduleSpecifierCache", () => { it("invalidates the cache when user preferences change", () => { const { moduleSpecifierCache, session, triggerCompletions } = setup(); - const preferences: ts.UserPreferences = { importModuleSpecifierPreference: "project-relative" }; + const preferences: UserPreferences = { importModuleSpecifierPreference: "project-relative" }; assert.ok(getWithPreferences({})); - ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.Configure, { preferences }); + executeSessionRequest(session, CommandTypes.Configure, { preferences }); // Nothing changes yet assert.ok(getWithPreferences({})); assert.isUndefined(getWithPreferences(preferences)); @@ -112,25 +120,25 @@ describe("unittests:: tsserver:: moduleSpecifierCache", () => { assert.ok(getWithPreferences(preferences)); // Test other affecting preference - ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.Configure, { + executeSessionRequest(session, CommandTypes.Configure, { preferences: { importModuleSpecifierEnding: "js" }, }); triggerCompletions({ file: bTs.path, line: 1, offset: 3 }); assert.isUndefined(getWithPreferences(preferences)); - function getWithPreferences(preferences: ts.UserPreferences) { - return moduleSpecifierCache.get(bTs.path as ts.Path, aTs.path as ts.Path, preferences, {}); + function getWithPreferences(preferences: UserPreferences) { + return moduleSpecifierCache.get(bTs.path as Path, aTs.path as Path, preferences, {}); } }); }); function setup() { - const host = ts.projectSystem.createServerHost([aTs, bTs, cTs, bSymlink, ambientDeclaration, tsconfig, packageJson, mobxPackageJson, mobxDts]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([aTs, bTs, cTs], session); + const host = createServerHost([aTs, bTs, cTs, bSymlink, ambientDeclaration, tsconfig, packageJson, mobxPackageJson, mobxDts]); + const session = createSession(host); + openFilesForSession([aTs, bTs, cTs], session); const projectService = session.getProjectService(); - const project = ts.projectSystem.configuredProjectAt(projectService, 0); - ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.Configure, { + const project = configuredProjectAt(projectService, 0); + executeSessionRequest(session, CommandTypes.Configure, { preferences: { includeCompletionsForImportStatements: true, includeCompletionsForModuleExports: true, @@ -142,8 +150,8 @@ function setup() { return { host, project, projectService, session, moduleSpecifierCache: project.getModuleSpecifierCache(), triggerCompletions }; - function triggerCompletions(requestLocation: ts.projectSystem.protocol.FileLocationRequestArgs) { - ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.CompletionInfo, { + function triggerCompletions(requestLocation: FileLocationRequestArgs) { + executeSessionRequest(session, CommandTypes.CompletionInfo, { ...requestLocation, }); } diff --git a/src/testRunner/unittests/tsserver/navTo.ts b/src/testRunner/unittests/tsserver/navTo.ts index 8882634915bb2..bcc235169273b 100644 --- a/src/testRunner/unittests/tsserver/navTo.ts +++ b/src/testRunner/unittests/tsserver/navTo.ts @@ -1,39 +1,44 @@ -import * as ts from "../../_namespaces/ts"; +import { find } from "../../../compiler/core"; +import { NavtoItem, NavtoRequestArgs } from "../../../server/protocol"; +import { + baselineTsserverLogs, CommandNames, createLoggerWithInMemoryLogs, createServerHost, createSession, File, libFile, + makeSessionRequest, openFilesForSession, +} from "./helpers"; describe("unittests:: tsserver:: navigate-to for javascript project", () => { - function findNavToItem(items: ts.projectSystem.protocol.NavtoItem[], itemName: string, itemKind: string) { - return ts.find(items, item => item.name === itemName && item.kind === itemKind); + function findNavToItem(items: NavtoItem[], itemName: string, itemKind: string) { + return find(items, item => item.name === itemName && item.kind === itemKind); } - function containsNavToItem(items: ts.projectSystem.protocol.NavtoItem[], itemName: string, itemKind: string) { + function containsNavToItem(items: NavtoItem[], itemName: string, itemKind: string) { return findNavToItem(items, itemName, itemKind) !== undefined; } it("should not include type symbols", () => { - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/b/file1.js", content: "function foo() {}" }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/jsconfig.json", content: "{}" }; - const host = ts.projectSystem.createServerHost([file1, configFile, ts.projectSystem.libFile]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([file1], session); + const host = createServerHost([file1, configFile, libFile]); + const session = createSession(host); + openFilesForSession([file1], session); // Try to find some interface type defined in lib.d.ts - const libTypeNavToRequest = ts.projectSystem.makeSessionRequest(ts.projectSystem.CommandNames.Navto, { searchValue: "Document", file: file1.path, projectFileName: configFile.path }); - const items = session.executeCommand(libTypeNavToRequest).response as ts.projectSystem.protocol.NavtoItem[]; + const libTypeNavToRequest = makeSessionRequest(CommandNames.Navto, { searchValue: "Document", file: file1.path, projectFileName: configFile.path }); + const items = session.executeCommand(libTypeNavToRequest).response as NavtoItem[]; assert.isFalse(containsNavToItem(items, "Document", "interface"), `Found lib.d.ts symbol in JavaScript project nav to request result.`); - const localFunctionNavToRequst = ts.projectSystem.makeSessionRequest(ts.projectSystem.CommandNames.Navto, { searchValue: "foo", file: file1.path, projectFileName: configFile.path }); - const items2 = session.executeCommand(localFunctionNavToRequst).response as ts.projectSystem.protocol.NavtoItem[]; + const localFunctionNavToRequst = makeSessionRequest(CommandNames.Navto, { searchValue: "foo", file: file1.path, projectFileName: configFile.path }); + const items2 = session.executeCommand(localFunctionNavToRequst).response as NavtoItem[]; assert.isTrue(containsNavToItem(items2, "foo", "function"), `Cannot find function symbol "foo".`); }); it("should de-duplicate symbols", () => { - const configFile1: ts.projectSystem.File = { + const configFile1: File = { path: "/a/tsconfig.json", content: `{ "compilerOptions": { @@ -41,11 +46,11 @@ describe("unittests:: tsserver:: navigate-to for javascript project", () => { } }` }; - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/index.ts", content: "export const abcdef = 1;" }; - const configFile2: ts.projectSystem.File = { + const configFile2: File = { path: "/b/tsconfig.json", content: `{ "compilerOptions": { @@ -56,30 +61,30 @@ describe("unittests:: tsserver:: navigate-to for javascript project", () => { ] }` }; - const file2: ts.projectSystem.File = { + const file2: File = { path: "/b/index.ts", content: `import a = require("../a"); export const ghijkl = a.abcdef;` }; - const host = ts.projectSystem.createServerHost([configFile1, file1, configFile2, file2]); - const session = ts.projectSystem.createSession(host, { logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([file1, file2], session); + const host = createServerHost([configFile1, file1, configFile2, file2]); + const session = createSession(host, { logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([file1, file2], session); - const request = ts.projectSystem.makeSessionRequest(ts.projectSystem.CommandNames.Navto, { searchValue: "abcdef", file: file1.path }); - session.executeCommand(request).response as ts.projectSystem.protocol.NavtoItem[]; + const request = makeSessionRequest(CommandNames.Navto, { searchValue: "abcdef", file: file1.path }); + session.executeCommand(request).response as NavtoItem[]; - ts.projectSystem.baselineTsserverLogs("navTo", "should de-duplicate symbols", session); + baselineTsserverLogs("navTo", "should de-duplicate symbols", session); }); it("should de-duplicate symbols when searching all projects", () => { - const solutionConfig: ts.projectSystem.File = { + const solutionConfig: File = { path: "/tsconfig.json", content: JSON.stringify({ references: [{ path: "./a" }, { path: "./b" }], files: [], }) }; - const configFile1: ts.projectSystem.File = { + const configFile1: File = { path: "/a/tsconfig.json", content: `{ "compilerOptions": { @@ -87,11 +92,11 @@ export const ghijkl = a.abcdef;` } }` }; - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/index.ts", content: "export const abcdef = 1;" }; - const configFile2: ts.projectSystem.File = { + const configFile2: File = { path: "/b/tsconfig.json", content: `{ "compilerOptions": { @@ -102,36 +107,36 @@ export const ghijkl = a.abcdef;` ] }` }; - const file2: ts.projectSystem.File = { + const file2: File = { path: "/b/index.ts", content: `import a = require("../a"); export const ghijkl = a.abcdef;` }; - const host = ts.projectSystem.createServerHost([configFile1, file1, configFile2, file2, solutionConfig]); - const session = ts.projectSystem.createSession(host, { logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([file1], session); + const host = createServerHost([configFile1, file1, configFile2, file2, solutionConfig]); + const session = createSession(host, { logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([file1], session); - const request = ts.projectSystem.makeSessionRequest(ts.projectSystem.CommandNames.Navto, { searchValue: "abcdef" }); - session.executeCommand(request).response as ts.projectSystem.protocol.NavtoItem[]; - ts.projectSystem.baselineTsserverLogs("navTo", "should de-duplicate symbols when searching all projects", session); + const request = makeSessionRequest(CommandNames.Navto, { searchValue: "abcdef" }); + session.executeCommand(request).response as NavtoItem[]; + baselineTsserverLogs("navTo", "should de-duplicate symbols when searching all projects", session); }); it("should work with Deprecated", () => { - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/b/file1.js", content: "/** @deprecated */\nfunction foo () {}" }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/jsconfig.json", content: "{}" }; - const host = ts.projectSystem.createServerHost([file1, configFile, ts.projectSystem.libFile]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([file1], session); + const host = createServerHost([file1, configFile, libFile]); + const session = createSession(host); + openFilesForSession([file1], session); // Try to find some interface type defined in lib.d.ts - const libTypeNavToRequest = ts.projectSystem.makeSessionRequest(ts.projectSystem.CommandNames.Navto, { searchValue: "foo", file: file1.path, projectFileName: configFile.path }); - const items = session.executeCommand(libTypeNavToRequest).response as ts.projectSystem.protocol.NavtoItem[]; + const libTypeNavToRequest = makeSessionRequest(CommandNames.Navto, { searchValue: "foo", file: file1.path, projectFileName: configFile.path }); + const items = session.executeCommand(libTypeNavToRequest).response as NavtoItem[]; const fooItem = findNavToItem(items, "foo", "function"); assert.isNotNull(fooItem, `Cannot find function symbol "foo".`); assert.isTrue(fooItem?.kindModifiers?.includes("deprecated")); diff --git a/src/testRunner/unittests/tsserver/occurences.ts b/src/testRunner/unittests/tsserver/occurences.ts index 8b03241d48fa3..d6f8ff5298087 100644 --- a/src/testRunner/unittests/tsserver/occurences.ts +++ b/src/testRunner/unittests/tsserver/occurences.ts @@ -1,44 +1,45 @@ -import * as ts from "../../_namespaces/ts"; +import { FileLocationRequestArgs, OccurrencesResponseItem } from "../../../server/protocol"; +import { CommandNames, createServerHost, createSession, File, makeSessionRequest } from "./helpers"; describe("unittests:: tsserver:: occurrence highlight on string", () => { it("should be marked if only on string values", () => { - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/b/file1.ts", content: `let t1 = "div";\nlet t2 = "div";\nlet t3 = { "div": 123 };\nlet t4 = t3["div"];` }; - const host = ts.projectSystem.createServerHost([file1]); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([file1]); + const session = createSession(host); const projectService = session.getProjectService(); projectService.openClientFile(file1.path); { - const highlightRequest = ts.projectSystem.makeSessionRequest( - ts.projectSystem.CommandNames.Occurrences, + const highlightRequest = makeSessionRequest( + CommandNames.Occurrences, { file: file1.path, line: 1, offset: 11 } ); - const highlightResponse = session.executeCommand(highlightRequest).response as ts.projectSystem.protocol.OccurrencesResponseItem[]; + const highlightResponse = session.executeCommand(highlightRequest).response as OccurrencesResponseItem[]; const firstOccurence = highlightResponse[0]; assert.isTrue(firstOccurence.isInString, "Highlights should be marked with isInString"); } { - const highlightRequest = ts.projectSystem.makeSessionRequest( - ts.projectSystem.CommandNames.Occurrences, + const highlightRequest = makeSessionRequest( + CommandNames.Occurrences, { file: file1.path, line: 3, offset: 13 } ); - const highlightResponse = session.executeCommand(highlightRequest).response as ts.projectSystem.protocol.OccurrencesResponseItem[]; + const highlightResponse = session.executeCommand(highlightRequest).response as OccurrencesResponseItem[]; assert.isTrue(highlightResponse.length === 2); const firstOccurence = highlightResponse[0]; assert.isUndefined(firstOccurence.isInString, "Highlights should not be marked with isInString if on property name"); } { - const highlightRequest = ts.projectSystem.makeSessionRequest( - ts.projectSystem.CommandNames.Occurrences, + const highlightRequest = makeSessionRequest( + CommandNames.Occurrences, { file: file1.path, line: 4, offset: 14 } ); - const highlightResponse = session.executeCommand(highlightRequest).response as ts.projectSystem.protocol.OccurrencesResponseItem[]; + const highlightResponse = session.executeCommand(highlightRequest).response as OccurrencesResponseItem[]; assert.isTrue(highlightResponse.length === 2); const firstOccurence = highlightResponse[0]; assert.isUndefined(firstOccurence.isInString, "Highlights should not be marked with isInString if on indexer"); diff --git a/src/testRunner/unittests/tsserver/openFile.ts b/src/testRunner/unittests/tsserver/openFile.ts index 4e8a014fb6408..e94f259eb517c 100644 --- a/src/testRunner/unittests/tsserver/openFile.ts +++ b/src/testRunner/unittests/tsserver/openFile.ts @@ -1,4 +1,12 @@ -import * as ts from "../../_namespaces/ts"; +import { ScriptKind } from "../../../compiler/types"; +import { CommandTypes, UpdateOpenRequest } from "../../../server/protocol"; +import { IScriptSnapshot } from "../../../services/types"; +import { projectRoot } from "../tscWatch/helpers"; +import { + baselineTsserverLogs, checkProjectActualFiles, createLoggerWithInMemoryLogs, createProjectService, createServerHost, + createSession, File, libFile, openFilesForSession, protocolTextSpanFromSubstring, toExternalFile, + verifyGetErrRequest, +} from "./helpers"; describe("unittests:: tsserver:: Open-file", () => { it("can be reloaded with empty content", () => { @@ -7,10 +15,10 @@ describe("unittests:: tsserver:: Open-file", () => { content: "let x = 1" }; const projectFileName = "externalProject"; - const host = ts.projectSystem.createServerHost([f]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([f]); + const projectService = createProjectService(host); // create a project - projectService.openExternalProject({ projectFileName, rootFiles: [ts.projectSystem.toExternalFile(f.path)], options: {} }); + projectService.openExternalProject({ projectFileName, rootFiles: [toExternalFile(f.path)], options: {} }); projectService.checkNumberOfProjects({ externalProjects: 1 }); const p = projectService.externalProjects[0]; @@ -24,31 +32,31 @@ describe("unittests:: tsserver:: Open-file", () => { projectService.openClientFile(f.path, ""); checkSnapLength(scriptInfo.getSnapshot(), 0); }); - function checkSnapLength(snap: ts.IScriptSnapshot, expectedLength: number) { + function checkSnapLength(snap: IScriptSnapshot, expectedLength: number) { assert.equal(snap.getLength(), expectedLength, "Incorrect snapshot size"); } function verifyOpenFileWorks(useCaseSensitiveFileNames: boolean) { - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/b/src/app.ts", content: "let x = 10;" }; - const file2: ts.projectSystem.File = { + const file2: File = { path: "/a/B/lib/module2.ts", content: "let z = 10;" }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: "" }; - const configFile2: ts.projectSystem.File = { + const configFile2: File = { path: "/a/tsconfig.json", content: "" }; - const host = ts.projectSystem.createServerHost([file1, file2, configFile, configFile2], { + const host = createServerHost([file1, file2, configFile, configFile2], { useCaseSensitiveFileNames }); - const service = ts.projectSystem.createProjectService(host); + const service = createProjectService(host); // Open file1 -> configFile verifyConfigFileName(file1, "/a", configFile); @@ -60,7 +68,7 @@ describe("unittests:: tsserver:: Open-file", () => { verifyConfigFileName(file2, "/a/b", useCaseSensitiveFileNames ? configFile2 : configFile); verifyConfigFileName(file2, "/a/B", useCaseSensitiveFileNames ? undefined : configFile); - function verifyConfigFileName(file: ts.projectSystem.File, projectRoot: string, expectedConfigFile: ts.projectSystem.File | undefined) { + function verifyConfigFileName(file: File, projectRoot: string, expectedConfigFile: File | undefined) { const { configFileName } = service.openClientFile(file.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, projectRoot); assert.equal(configFileName, expectedConfigFile && expectedConfigFile.path); service.closeClientFile(file.path); @@ -76,63 +84,63 @@ describe("unittests:: tsserver:: Open-file", () => { it("uses existing project even if project refresh is pending", () => { const projectFolder = "/user/someuser/projects/myproject"; - const aFile: ts.projectSystem.File = { + const aFile: File = { path: `${projectFolder}/src/a.ts`, content: "export const x = 0;" }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: `${projectFolder}/tsconfig.json`, content: "{}" }; - const files = [aFile, configFile, ts.projectSystem.libFile]; - const host = ts.projectSystem.createServerHost(files); - const service = ts.projectSystem.createProjectService(host); - service.openClientFile(aFile.path, /*fileContent*/ undefined, ts.ScriptKind.TS, projectFolder); + const files = [aFile, configFile, libFile]; + const host = createServerHost(files); + const service = createProjectService(host); + service.openClientFile(aFile.path, /*fileContent*/ undefined, ScriptKind.TS, projectFolder); verifyProject(); - const bFile: ts.projectSystem.File = { + const bFile: File = { path: `${projectFolder}/src/b.ts`, content: `export {}; declare module "./a" { export const y: number; }` }; files.push(bFile); host.writeFile(bFile.path, bFile.content); - service.openClientFile(bFile.path, /*fileContent*/ undefined, ts.ScriptKind.TS, projectFolder); + service.openClientFile(bFile.path, /*fileContent*/ undefined, ScriptKind.TS, projectFolder); verifyProject(); function verifyProject() { assert.isDefined(service.configuredProjects.get(configFile.path)); const project = service.configuredProjects.get(configFile.path)!; - ts.projectSystem.checkProjectActualFiles(project, files.map(f => f.path)); + checkProjectActualFiles(project, files.map(f => f.path)); } }); it("can open same file again", () => { const projectFolder = "/user/someuser/projects/myproject"; - const aFile: ts.projectSystem.File = { + const aFile: File = { path: `${projectFolder}/src/a.ts`, content: "export const x = 0;" }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: `${projectFolder}/tsconfig.json`, content: "{}" }; - const files = [aFile, configFile, ts.projectSystem.libFile]; - const host = ts.projectSystem.createServerHost(files); - const service = ts.projectSystem.createProjectService(host); + const files = [aFile, configFile, libFile]; + const host = createServerHost(files); + const service = createProjectService(host); verifyProject(aFile.content); verifyProject(`${aFile.content}export const y = 10;`); function verifyProject(aFileContent: string) { - service.openClientFile(aFile.path, aFileContent, ts.ScriptKind.TS, projectFolder); + service.openClientFile(aFile.path, aFileContent, ScriptKind.TS, projectFolder); const project = service.configuredProjects.get(configFile.path)!; - ts.projectSystem.checkProjectActualFiles(project, files.map(f => f.path)); + checkProjectActualFiles(project, files.map(f => f.path)); assert.equal(project.getCurrentProgram()?.getSourceFile(aFile.path)!.text, aFileContent); } }); it("when file makes edits to add/remove comment directives, they are handled correcrly", () => { - const file: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/file.ts`, + const file: File = { + path: `${projectRoot}/file.ts`, content: `const x = 10; function foo() { // @ts-ignore @@ -147,16 +155,16 @@ function bar() { foo(); bar();` }; - const host = ts.projectSystem.createServerHost([file, ts.projectSystem.libFile]); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([file], session); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [file] }); + const host = createServerHost([file, libFile]); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([file], session); + verifyGetErrRequest({ session, host, files: [file] }); // Remove first ts-ignore and check only first error is reported const tsIgnoreComment = `// @ts-ignore`; - const locationOfTsIgnore = ts.projectSystem.protocolTextSpanFromSubstring(file.content, tsIgnoreComment); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.UpdateOpen, + const locationOfTsIgnore = protocolTextSpanFromSubstring(file.content, tsIgnoreComment); + session.executeCommandSeq({ + command: CommandTypes.UpdateOpen, arguments: { changedFiles: [{ fileName: file.path, @@ -167,10 +175,10 @@ bar();` }] } }); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [file] }); + verifyGetErrRequest({ session, host, files: [file] }); // Revert the change and no errors should be reported - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.UpdateOpen, + session.executeCommandSeq({ + command: CommandTypes.UpdateOpen, arguments: { changedFiles: [{ fileName: file.path, @@ -181,8 +189,8 @@ bar();` }] } }); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [file] }); - ts.projectSystem.baselineTsserverLogs("openfile", "when file makes edits to add/remove comment directives, they are handled correcrly", session); + verifyGetErrRequest({ session, host, files: [file] }); + baselineTsserverLogs("openfile", "when file makes edits to add/remove comment directives, they are handled correcrly", session); }); }); diff --git a/src/testRunner/unittests/tsserver/packageJsonInfo.ts b/src/testRunner/unittests/tsserver/packageJsonInfo.ts index 091f212671cd9..472227b503847 100644 --- a/src/testRunner/unittests/tsserver/packageJsonInfo.ts +++ b/src/testRunner/unittests/tsserver/packageJsonInfo.ts @@ -1,6 +1,7 @@ -import * as ts from "../../_namespaces/ts"; +import { Path } from "../../../compiler/types"; +import { configuredProjectAt, createServerHost, createSession, File } from "./helpers"; -const tsConfig: ts.projectSystem.File = { +const tsConfig: File = { path: "/tsconfig.json", content: "{}" }; @@ -18,7 +19,7 @@ const packageJsonContent = { webpack: "*" } }; -const packageJson: ts.projectSystem.File = { +const packageJson: File = { path: "/package.json", content: JSON.stringify(packageJsonContent, undefined, 2) }; @@ -27,11 +28,11 @@ describe("unittests:: tsserver:: packageJsonInfo", () => { it("detects new package.json files that are added, caches them, and watches them", () => { // Initialize project without package.json const { projectService, host } = setup([tsConfig]); - assert.isUndefined(projectService.packageJsonCache.getInDirectory("/" as ts.Path)); + assert.isUndefined(projectService.packageJsonCache.getInDirectory("/" as Path)); // Add package.json host.writeFile(packageJson.path, packageJson.content); - let packageJsonInfo = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!; + let packageJsonInfo = projectService.packageJsonCache.getInDirectory("/" as Path)!; assert.ok(packageJsonInfo); assert.ok(packageJsonInfo.dependencies); assert.ok(packageJsonInfo.devDependencies); @@ -43,19 +44,19 @@ describe("unittests:: tsserver:: packageJsonInfo", () => { ...packageJsonContent, dependencies: undefined })); - packageJsonInfo = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!; + packageJsonInfo = projectService.packageJsonCache.getInDirectory("/" as Path)!; assert.isUndefined(packageJsonInfo.dependencies); }); it("finds package.json on demand, watches for deletion, and removes them from cache", () => { // Initialize project with package.json const { projectService, host } = setup(); - projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as ts.Path); - assert.ok(projectService.packageJsonCache.getInDirectory("/" as ts.Path)); + projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as Path); + assert.ok(projectService.packageJsonCache.getInDirectory("/" as Path)); // Delete package.json host.deleteFile(packageJson.path); - assert.isUndefined(projectService.packageJsonCache.getInDirectory("/" as ts.Path)); + assert.isUndefined(projectService.packageJsonCache.getInDirectory("/" as Path)); }); it("finds multiple package.json files when present", () => { @@ -63,20 +64,20 @@ describe("unittests:: tsserver:: packageJsonInfo", () => { const { projectService, host } = setup(); // Add package.json in /src host.writeFile("/src/package.json", packageJson.content); - assert.lengthOf(projectService.getPackageJsonsVisibleToFile("/a.ts" as ts.Path), 1); - assert.lengthOf(projectService.getPackageJsonsVisibleToFile("/src/b.ts" as ts.Path), 2); + assert.lengthOf(projectService.getPackageJsonsVisibleToFile("/a.ts" as Path), 1); + assert.lengthOf(projectService.getPackageJsonsVisibleToFile("/src/b.ts" as Path), 2); }); it("handles errors in json parsing of package.json", () => { const packageJsonContent = `{ "mod" }`; const { projectService, host } = setup([tsConfig, { path: packageJson.path, content: packageJsonContent }]); - projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as ts.Path); - const packageJsonInfo = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!; + projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as Path); + const packageJsonInfo = projectService.packageJsonCache.getInDirectory("/" as Path)!; assert.isFalse(packageJsonInfo.parseable); host.writeFile(packageJson.path, packageJson.content); - projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as ts.Path); - const packageJsonInfo2 = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!; + projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as Path); + const packageJsonInfo2 = projectService.packageJsonCache.getInDirectory("/" as Path)!; assert.ok(packageJsonInfo2); assert.ok(packageJsonInfo2.dependencies); assert.ok(packageJsonInfo2.devDependencies); @@ -87,13 +88,13 @@ describe("unittests:: tsserver:: packageJsonInfo", () => { it("handles empty package.json", () => { const packageJsonContent = ""; const { projectService, host } = setup([tsConfig, { path: packageJson.path, content: packageJsonContent }]); - projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as ts.Path); - const packageJsonInfo = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!; + projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as Path); + const packageJsonInfo = projectService.packageJsonCache.getInDirectory("/" as Path)!; assert.isFalse(packageJsonInfo.parseable); host.writeFile(packageJson.path, packageJson.content); - projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as ts.Path); - const packageJsonInfo2 = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!; + projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as Path); + const packageJsonInfo2 = projectService.packageJsonCache.getInDirectory("/" as Path)!; assert.ok(packageJsonInfo2); assert.ok(packageJsonInfo2.dependencies); assert.ok(packageJsonInfo2.devDependencies); @@ -102,12 +103,12 @@ describe("unittests:: tsserver:: packageJsonInfo", () => { }); }); -function setup(files: readonly ts.projectSystem.File[] = [tsConfig, packageJson]) { - const host = ts.projectSystem.createServerHost(files); - const session = ts.projectSystem.createSession(host); +function setup(files: readonly File[] = [tsConfig, packageJson]) { + const host = createServerHost(files); + const session = createSession(host); const projectService = session.getProjectService(); projectService.openClientFile(files[0].path); - const project = ts.projectSystem.configuredProjectAt(projectService, 0); + const project = configuredProjectAt(projectService, 0); return { host, session, project, projectService }; } diff --git a/src/testRunner/unittests/tsserver/partialSemanticServer.ts b/src/testRunner/unittests/tsserver/partialSemanticServer.ts index 2844b737fc3bd..e2e8c7cbf1e93 100644 --- a/src/testRunner/unittests/tsserver/partialSemanticServer.ts +++ b/src/testRunner/unittests/tsserver/partialSemanticServer.ts @@ -1,71 +1,83 @@ -import * as ts from "../../_namespaces/ts"; +import { emptyArray } from "../../../compiler/core"; +import { + CommandTypes, CompletionEntry, CompletionsRequest, DefinitionAndBoundSpanRequest, DefinitionInfoAndBoundSpan, + Diagnostic, SemanticDiagnosticsSyncRequest, SyntacticDiagnosticsSyncRequest, SyntacticDiagnosticsSyncResponse, +} from "../../../server/protocol"; +import { SortText } from "../../../services/completions"; +import { LanguageServiceMode, ScriptElementKind } from "../../../services/types"; +import { projectRoot } from "../tscWatch/helpers"; +import { + baselineTsserverLogs, checkNumberOfProjects, checkProjectActualFiles, checkWatchedDirectories, checkWatchedFiles, + closeFilesForSession, createLoggerWithInMemoryLogs, createServerHost, createSession, File, libFile, + openFilesForSession, protocolFileLocationFromSubstring, verifyGetErrRequest, +} from "./helpers"; describe("unittests:: tsserver:: Semantic operations on partialSemanticServer", () => { function setup() { - const file1: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const file1: File = { + path: `${projectRoot}/a.ts`, content: `import { y, cc } from "./b"; import { something } from "something"; class c { prop = "hello"; foo() { return this.prop; } }` }; - const file2: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/b.ts`, + const file2: File = { + path: `${projectRoot}/b.ts`, content: `export { cc } from "./c"; import { something } from "something"; export const y = 10;` }; - const file3: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/c.ts`, + const file3: File = { + path: `${projectRoot}/c.ts`, content: `export const cc = 10;` }; - const something: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/node_modules/something/index.d.ts`, + const something: File = { + path: `${projectRoot}/node_modules/something/index.d.ts`, content: "export const something = 10;" }; - const configFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const configFile: File = { + path: `${projectRoot}/tsconfig.json`, content: "{}" }; - const host = ts.projectSystem.createServerHost([file1, file2, file3, something, ts.projectSystem.libFile, configFile]); - const session = ts.projectSystem.createSession(host, { serverMode: ts.LanguageServiceMode.PartialSemantic, useSingleInferredProject: true }); + const host = createServerHost([file1, file2, file3, something, libFile, configFile]); + const session = createSession(host, { serverMode: LanguageServiceMode.PartialSemantic, useSingleInferredProject: true }); return { host, session, file1, file2, file3, something, configFile }; } it("open files are added to inferred project even if config file is present and semantic operations succeed", () => { const { host, session, file1, file2 } = setup(); const service = session.getProjectService(); - ts.projectSystem.openFilesForSession([file1], session); - ts.projectSystem.checkNumberOfProjects(service, { inferredProjects: 1 }); + openFilesForSession([file1], session); + checkNumberOfProjects(service, { inferredProjects: 1 }); const project = service.inferredProjects[0]; - ts.projectSystem.checkProjectActualFiles(project, [ts.projectSystem.libFile.path, file1.path]); // no imports are resolved + checkProjectActualFiles(project, [libFile.path, file1.path]); // no imports are resolved verifyCompletions(); - ts.projectSystem.openFilesForSession([file2], session); - ts.projectSystem.checkNumberOfProjects(service, { inferredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(project, [ts.projectSystem.libFile.path, file1.path, file2.path]); + openFilesForSession([file2], session); + checkNumberOfProjects(service, { inferredProjects: 1 }); + checkProjectActualFiles(project, [libFile.path, file1.path, file2.path]); verifyCompletions(); function verifyCompletions() { assert.isTrue(project.languageServiceEnabled); - ts.projectSystem.checkWatchedFiles(host, ts.emptyArray); - ts.projectSystem.checkWatchedDirectories(host, ts.emptyArray, /*recursive*/ true); - ts.projectSystem.checkWatchedDirectories(host, ts.emptyArray, /*recursive*/ false); - const response = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Completions, - arguments: ts.projectSystem.protocolFileLocationFromSubstring(file1, "prop", { index: 1 }) - }).response as ts.projectSystem.protocol.CompletionEntry[]; + checkWatchedFiles(host, emptyArray); + checkWatchedDirectories(host, emptyArray, /*recursive*/ true); + checkWatchedDirectories(host, emptyArray, /*recursive*/ false); + const response = session.executeCommandSeq({ + command: CommandTypes.Completions, + arguments: protocolFileLocationFromSubstring(file1, "prop", { index: 1 }) + }).response as CompletionEntry[]; assert.deepEqual(response, [ - completionEntry("foo", ts.ScriptElementKind.memberFunctionElement), - completionEntry("prop", ts.ScriptElementKind.memberVariableElement), + completionEntry("foo", ScriptElementKind.memberFunctionElement), + completionEntry("prop", ScriptElementKind.memberVariableElement), ]); } - function completionEntry(name: string, kind: ts.ScriptElementKind): ts.projectSystem.protocol.CompletionEntry { + function completionEntry(name: string, kind: ScriptElementKind): CompletionEntry { return { name, kind, kindModifiers: "", - sortText: ts.Completions.SortText.LocationPriority, + sortText: SortText.LocationPriority, hasAction: undefined, insertText: undefined, isPackageJsonImport: undefined, @@ -84,12 +96,12 @@ import { something } from "something"; it("throws on unsupported commands", () => { const { session, file1 } = setup(); const service = session.getProjectService(); - ts.projectSystem.openFilesForSession([file1], session); + openFilesForSession([file1], session); let hasException = false; - const request: ts.projectSystem.protocol.SemanticDiagnosticsSyncRequest = { + const request: SemanticDiagnosticsSyncRequest = { type: "request", seq: 1, - command: ts.projectSystem.protocol.CommandTypes.SemanticDiagnosticsSync, + command: CommandTypes.SemanticDiagnosticsSync, arguments: { file: file1.path } }; try { @@ -114,149 +126,149 @@ import { something } from "something"; }); it("allows syntactic diagnostic commands", () => { - const file1: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const file1: File = { + path: `${projectRoot}/a.ts`, content: `if (a < (b + c) { }` }; - const configFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const configFile: File = { + path: `${projectRoot}/tsconfig.json`, content: `{}` }; const expectedErrorMessage = "')' expected."; - const host = ts.projectSystem.createServerHost([file1, ts.projectSystem.libFile, configFile]); - const session = ts.projectSystem.createSession(host, { - serverMode: ts.LanguageServiceMode.PartialSemantic, + const host = createServerHost([file1, libFile, configFile]); + const session = createSession(host, { + serverMode: LanguageServiceMode.PartialSemantic, useSingleInferredProject: true, - logger: ts.projectSystem.createLoggerWithInMemoryLogs() + logger: createLoggerWithInMemoryLogs() }); const service = session.getProjectService(); - ts.projectSystem.openFilesForSession([file1], session); - const request: ts.projectSystem.protocol.SyntacticDiagnosticsSyncRequest = { + openFilesForSession([file1], session); + const request: SyntacticDiagnosticsSyncRequest = { type: "request", seq: 1, - command: ts.projectSystem.protocol.CommandTypes.SyntacticDiagnosticsSync, + command: CommandTypes.SyntacticDiagnosticsSync, arguments: { file: file1.path } }; - const response = session.executeCommandSeq(request).response as ts.projectSystem.protocol.SyntacticDiagnosticsSyncResponse["body"]; + const response = session.executeCommandSeq(request).response as SyntacticDiagnosticsSyncResponse["body"]; assert.isDefined(response); assert.equal(response!.length, 1); - assert.equal((response![0] as ts.projectSystem.protocol.Diagnostic).text, expectedErrorMessage); + assert.equal((response![0] as Diagnostic).text, expectedErrorMessage); const project = service.inferredProjects[0]; const diagnostics = project.getLanguageService().getSyntacticDiagnostics(file1.path); assert.isTrue(diagnostics.length === 1); assert.equal(diagnostics[0].messageText, expectedErrorMessage); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [file1], skip: [{ semantic: true, suggestion: true }] }); - ts.projectSystem.baselineTsserverLogs("partialSemanticServer", "syntactic diagnostics are returned with no error", session); + verifyGetErrRequest({ session, host, files: [file1], skip: [{ semantic: true, suggestion: true }] }); + baselineTsserverLogs("partialSemanticServer", "syntactic diagnostics are returned with no error", session); }); it("should not include auto type reference directives", () => { const { host, session, file1 } = setup(); - const atTypes: ts.projectSystem.File = { + const atTypes: File = { path: `/node_modules/@types/somemodule/index.d.ts`, content: "export const something = 10;" }; host.ensureFileOrFolder(atTypes); const service = session.getProjectService(); - ts.projectSystem.openFilesForSession([file1], session); - ts.projectSystem.checkNumberOfProjects(service, { inferredProjects: 1 }); + openFilesForSession([file1], session); + checkNumberOfProjects(service, { inferredProjects: 1 }); const project = service.inferredProjects[0]; - ts.projectSystem.checkProjectActualFiles(project, [ts.projectSystem.libFile.path, file1.path]); // Should not contain atTypes + checkProjectActualFiles(project, [libFile.path, file1.path]); // Should not contain atTypes }); it("should not include referenced files from unopened files", () => { - const file1: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/a.ts`, + const file1: File = { + path: `${projectRoot}/a.ts`, content: `/// -/// +/// function fooA() { }` }; - const file2: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/b.ts`, + const file2: File = { + path: `${projectRoot}/b.ts`, content: `/// -/// +/// function fooB() { }` }; - const file3: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/c.ts`, + const file3: File = { + path: `${projectRoot}/c.ts`, content: `function fooC() { }` }; - const something: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/node_modules/something/index.d.ts`, + const something: File = { + path: `${projectRoot}/node_modules/something/index.d.ts`, content: "function something() {}" }; - const configFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const configFile: File = { + path: `${projectRoot}/tsconfig.json`, content: "{}" }; - const host = ts.projectSystem.createServerHost([file1, file2, file3, something, ts.projectSystem.libFile, configFile]); - const session = ts.projectSystem.createSession(host, { serverMode: ts.LanguageServiceMode.PartialSemantic, useSingleInferredProject: true }); + const host = createServerHost([file1, file2, file3, something, libFile, configFile]); + const session = createSession(host, { serverMode: LanguageServiceMode.PartialSemantic, useSingleInferredProject: true }); const service = session.getProjectService(); - ts.projectSystem.openFilesForSession([file1], session); - ts.projectSystem.checkNumberOfProjects(service, { inferredProjects: 1 }); + openFilesForSession([file1], session); + checkNumberOfProjects(service, { inferredProjects: 1 }); const project = service.inferredProjects[0]; - ts.projectSystem.checkProjectActualFiles(project, [ts.projectSystem.libFile.path, file1.path]); // no resolve + checkProjectActualFiles(project, [libFile.path, file1.path]); // no resolve }); it("should not crash when external module name resolution is reused", () => { const { session, file1, file2, file3 } = setup(); const service = session.getProjectService(); - ts.projectSystem.openFilesForSession([file1], session); - ts.projectSystem.checkNumberOfProjects(service, { inferredProjects: 1 }); + openFilesForSession([file1], session); + checkNumberOfProjects(service, { inferredProjects: 1 }); const project = service.inferredProjects[0]; - ts.projectSystem.checkProjectActualFiles(project, [ts.projectSystem.libFile.path, file1.path]); + checkProjectActualFiles(project, [libFile.path, file1.path]); // Close the file that contains non relative external module name and open some file that doesnt have non relative external module import - ts.projectSystem.closeFilesForSession([file1], session); - ts.projectSystem.openFilesForSession([file3], session); - ts.projectSystem.checkProjectActualFiles(project, [ts.projectSystem.libFile.path, file3.path]); + closeFilesForSession([file1], session); + openFilesForSession([file3], session); + checkProjectActualFiles(project, [libFile.path, file3.path]); // Open file with non relative external module name - ts.projectSystem.openFilesForSession([file2], session); - ts.projectSystem.checkProjectActualFiles(project, [ts.projectSystem.libFile.path, file2.path, file3.path]); + openFilesForSession([file2], session); + checkProjectActualFiles(project, [libFile.path, file2.path, file3.path]); }); it("should not create autoImportProvider or handle package jsons", () => { - const angularFormsDts: ts.projectSystem.File = { + const angularFormsDts: File = { path: "/node_modules/@angular/forms/forms.d.ts", content: "export declare class PatternValidator {}", }; - const angularFormsPackageJson: ts.projectSystem.File = { + const angularFormsPackageJson: File = { path: "/node_modules/@angular/forms/package.json", content: `{ "name": "@angular/forms", "typings": "./forms.d.ts" }`, }; - const tsconfig: ts.projectSystem.File = { + const tsconfig: File = { path: "/tsconfig.json", content: `{ "compilerOptions": { "module": "commonjs" } }`, }; - const packageJson: ts.projectSystem.File = { + const packageJson: File = { path: "/package.json", content: `{ "dependencies": { "@angular/forms": "*", "@angular/core": "*" } }` }; - const indexTs: ts.projectSystem.File = { + const indexTs: File = { path: "/index.ts", content: "" }; - const host = ts.projectSystem.createServerHost([angularFormsDts, angularFormsPackageJson, tsconfig, packageJson, indexTs, ts.projectSystem.libFile]); - const session = ts.projectSystem.createSession(host, { serverMode: ts.LanguageServiceMode.PartialSemantic, useSingleInferredProject: true }); + const host = createServerHost([angularFormsDts, angularFormsPackageJson, tsconfig, packageJson, indexTs, libFile]); + const session = createSession(host, { serverMode: LanguageServiceMode.PartialSemantic, useSingleInferredProject: true }); const service = session.getProjectService(); - ts.projectSystem.openFilesForSession([indexTs], session); + openFilesForSession([indexTs], session); const project = service.inferredProjects[0]; assert.isFalse(project.autoImportProviderHost); assert.isUndefined(project.getPackageJsonAutoImportProvider()); - assert.deepEqual(project.getPackageJsonsForAutoImport(), ts.emptyArray); + assert.deepEqual(project.getPackageJsonsForAutoImport(), emptyArray); }); it("should support go-to-definition on module specifiers", () => { const { session, file1, file2 } = setup(); - ts.projectSystem.openFilesForSession([file1], session); - const response = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.DefinitionAndBoundSpan, - arguments: ts.projectSystem.protocolFileLocationFromSubstring(file1, `"./b"`) - }).response as ts.projectSystem.protocol.DefinitionInfoAndBoundSpan; + openFilesForSession([file1], session); + const response = session.executeCommandSeq({ + command: CommandTypes.DefinitionAndBoundSpan, + arguments: protocolFileLocationFromSubstring(file1, `"./b"`) + }).response as DefinitionInfoAndBoundSpan; assert.isDefined(response); assert.deepEqual(response.definitions, [{ file: file2.path, diff --git a/src/testRunner/unittests/tsserver/plugins.ts b/src/testRunner/unittests/tsserver/plugins.ts index 4e830d105fad2..2e385ef5e2d62 100644 --- a/src/testRunner/unittests/tsserver/plugins.ts +++ b/src/testRunner/unittests/tsserver/plugins.ts @@ -1,27 +1,29 @@ -import * as Harness from "../../_namespaces/Harness"; -import * as ts from "../../_namespaces/ts"; +import { makeDefaultProxy } from "../../../harness/harnessLanguageService"; +import { PluginCreateInfo } from "../../../server/project"; +import { HandlerResponse } from "../../../server/session"; +import { createProjectService, createServerHost, createSession, File, libFile } from "./helpers"; describe("unittests:: tsserver:: plugins loading", () => { const testProtocolCommand = "testProtocolCommand"; const testProtocolCommandRequest = "testProtocolCommandRequest"; const testProtocolCommandResponse = "testProtocolCommandResponse"; - function createHostWithPlugin(files: readonly ts.projectSystem.File[]) { - const host = ts.projectSystem.createServerHost(files); + function createHostWithPlugin(files: readonly File[]) { + const host = createServerHost(files); const pluginsLoaded: string[] = []; const protocolHandlerRequests: [string, string][] = []; host.require = (_initialPath, moduleName) => { pluginsLoaded.push(moduleName); return { module: () => ({ - create(info: ts.server.PluginCreateInfo) { + create(info: PluginCreateInfo) { info.session?.addProtocolHandler(testProtocolCommand, request => { protocolHandlerRequests.push([request.command, request.arguments]); return { response: testProtocolCommandResponse }; }); - return Harness.LanguageService.makeDefaultProxy(info); + return makeDefaultProxy(info); } }), error: undefined @@ -33,8 +35,8 @@ describe("unittests:: tsserver:: plugins loading", () => { it("With local plugins", () => { const expectedToLoad = ["@myscoped/plugin", "unscopedPlugin"]; const notToLoad = ["../myPlugin", "myPlugin/../malicious"]; - const aTs: ts.projectSystem.File = { path: "/a.ts", content: `class c { prop = "hello"; foo() { return this.prop; } }` }; - const tsconfig: ts.projectSystem.File = { + const aTs: File = { path: "/a.ts", content: `class c { prop = "hello"; foo() { return this.prop; } }` }; + const tsconfig: File = { path: "/tsconfig.json", content: JSON.stringify({ compilerOptions: { @@ -45,8 +47,8 @@ describe("unittests:: tsserver:: plugins loading", () => { } }) }; - const { host, pluginsLoaded } = createHostWithPlugin([aTs, tsconfig, ts.projectSystem.libFile]); - const service = ts.projectSystem.createProjectService(host); + const { host, pluginsLoaded } = createHostWithPlugin([aTs, tsconfig, libFile]); + const service = createProjectService(host); service.openClientFile(aTs.path); assert.deepEqual(pluginsLoaded, expectedToLoad); }); @@ -54,13 +56,13 @@ describe("unittests:: tsserver:: plugins loading", () => { it("With global plugins", () => { const expectedToLoad = ["@myscoped/plugin", "unscopedPlugin"]; const notToLoad = ["../myPlugin", "myPlugin/../malicious"]; - const aTs: ts.projectSystem.File = { path: "/a.ts", content: `class c { prop = "hello"; foo() { return this.prop; } }` }; - const tsconfig: ts.projectSystem.File = { + const aTs: File = { path: "/a.ts", content: `class c { prop = "hello"; foo() { return this.prop; } }` }; + const tsconfig: File = { path: "/tsconfig.json", content: "{}" }; - const { host, pluginsLoaded } = createHostWithPlugin([aTs, tsconfig, ts.projectSystem.libFile]); - const service = ts.projectSystem.createProjectService(host, { globalPlugins: [...expectedToLoad, ...notToLoad] }); + const { host, pluginsLoaded } = createHostWithPlugin([aTs, tsconfig, libFile]); + const service = createProjectService(host, { globalPlugins: [...expectedToLoad, ...notToLoad] }); service.openClientFile(aTs.path); assert.deepEqual(pluginsLoaded, expectedToLoad); }); @@ -68,8 +70,8 @@ describe("unittests:: tsserver:: plugins loading", () => { it("With session and custom protocol message", () => { const pluginName = "some-plugin"; const expectedToLoad = [pluginName]; - const aTs: ts.projectSystem.File = { path: "/a.ts", content: `class c { prop = "hello"; foo() { return this.prop; } }` }; - const tsconfig: ts.projectSystem.File = { + const aTs: File = { path: "/a.ts", content: `class c { prop = "hello"; foo() { return this.prop; } }` }; + const tsconfig: File = { path: "/tsconfig.json", content: JSON.stringify({ compilerOptions: { @@ -80,10 +82,10 @@ describe("unittests:: tsserver:: plugins loading", () => { }) }; - const { host, pluginsLoaded, protocolHandlerRequests } = createHostWithPlugin([aTs, tsconfig, ts.projectSystem.libFile]); - const session = ts.projectSystem.createSession(host); + const { host, pluginsLoaded, protocolHandlerRequests } = createHostWithPlugin([aTs, tsconfig, libFile]); + const session = createSession(host); - const service = ts.projectSystem.createProjectService(host, { session }); + const service = createProjectService(host, { session }); service.openClientFile(aTs.path); assert.deepEqual(pluginsLoaded, expectedToLoad); @@ -97,7 +99,7 @@ describe("unittests:: tsserver:: plugins loading", () => { assert.strictEqual(command, testProtocolCommand); assert.strictEqual(args, testProtocolCommandRequest); - const expectedResp: ts.server.HandlerResponse = { + const expectedResp: HandlerResponse = { response: testProtocolCommandResponse }; assert.deepEqual(resp, expectedResp); diff --git a/src/testRunner/unittests/tsserver/projectErrors.ts b/src/testRunner/unittests/tsserver/projectErrors.ts index 18a0ecdf3b7b4..48a649af5f134 100644 --- a/src/testRunner/unittests/tsserver/projectErrors.ts +++ b/src/testRunner/unittests/tsserver/projectErrors.ts @@ -1,27 +1,45 @@ -import * as ts from "../../_namespaces/ts"; +import { find, startsWith, zipWith } from "../../../compiler/core"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { getBaseFileName } from "../../../compiler/path"; +import { flattenDiagnosticMessageText } from "../../../compiler/program"; +import { Diagnostic, ModuleKind } from "../../../compiler/types"; +import { ProjectFilesWithTSDiagnostics } from "../../../server/project"; +import { + ChangeRequest, CommandTypes, CompilerOptionsDiagnosticsRequest, DiagnosticWithLinePosition, ExternalProject, + GeterrRequest, OpenExternalProjectRequest, OpenRequest, SemanticDiagnosticsSyncRequest, + SemanticDiagnosticsSyncResponse, SetCompilerOptionsForInferredProjectsRequest, +} from "../../../server/protocol"; +import { CommandNames } from "../../../server/session"; +import { projectRoot } from "../tscWatch/helpers"; +import { + appendAllScriptInfos, baselineTsserverLogs, checkNumberOfProjects, checkProjectRootFiles, closeFilesForSession, + configuredProjectAt, createLoggerWithInMemoryLogs, createProjectService, createServerHost, createSession, + executeSessionRequest, File, Folder, libFile, openFilesForSession, protocol, toExternalFiles, verifyGetErrRequest, + verifyGetErrScenario, +} from "./helpers"; describe("unittests:: tsserver:: Project Errors", () => { - function checkProjectErrors(projectFiles: ts.server.ProjectFilesWithTSDiagnostics, expectedErrors: readonly string[]): void { + function checkProjectErrors(projectFiles: ProjectFilesWithTSDiagnostics, expectedErrors: readonly string[]): void { assert.isTrue(projectFiles !== undefined, "missing project files"); checkProjectErrorsWorker(projectFiles.projectErrors, expectedErrors); } - function checkProjectErrorsWorker(errors: readonly ts.Diagnostic[], expectedErrors: readonly string[]): void { + function checkProjectErrorsWorker(errors: readonly Diagnostic[], expectedErrors: readonly string[]): void { assert.equal(errors ? errors.length : 0, expectedErrors.length, `expected ${expectedErrors.length} error in the list`); if (expectedErrors.length) { for (let i = 0; i < errors.length; i++) { - const actualMessage = ts.flattenDiagnosticMessageText(errors[i].messageText, "\n"); + const actualMessage = flattenDiagnosticMessageText(errors[i].messageText, "\n"); const expectedMessage = expectedErrors[i]; assert.isTrue(actualMessage.indexOf(expectedMessage) === 0, `error message does not match, expected ${actualMessage} to start with ${expectedMessage}`); } } } - function checkDiagnosticsWithLinePos(errors: ts.server.protocol.DiagnosticWithLinePosition[], expectedErrors: string[]) { + function checkDiagnosticsWithLinePos(errors: DiagnosticWithLinePosition[], expectedErrors: string[]) { assert.equal(errors ? errors.length : 0, expectedErrors.length, `expected ${expectedErrors.length} error in the list`); if (expectedErrors.length) { - ts.zipWith(errors, expectedErrors, ({ message: actualMessage }, expectedMessage) => { - assert.isTrue(ts.startsWith(actualMessage, actualMessage), `error message does not match, expected ${actualMessage} to start with ${expectedMessage}`); + zipWith(errors, expectedErrors, ({ message: actualMessage }, expectedMessage) => { + assert.isTrue(startsWith(actualMessage, actualMessage), `error message does not match, expected ${actualMessage} to start with ${expectedMessage}`); }); } } @@ -35,13 +53,13 @@ describe("unittests:: tsserver:: Project Errors", () => { path: "/a/b/applib.ts", content: "" }; - const host = ts.projectSystem.createServerHost([file1, ts.projectSystem.libFile]); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([file1, libFile]); + const session = createSession(host); const projectService = session.getProjectService(); const projectFileName = "/a/b/test.csproj"; - const compilerOptionsRequest: ts.server.protocol.CompilerOptionsDiagnosticsRequest = { + const compilerOptionsRequest: CompilerOptionsDiagnosticsRequest = { type: "request", - command: ts.server.CommandNames.CompilerOptionsDiagnosticsFull, + command: CommandNames.CompilerOptionsDiagnosticsFull, seq: 2, arguments: { projectFileName } }; @@ -50,27 +68,27 @@ describe("unittests:: tsserver:: Project Errors", () => { projectService.openExternalProject({ projectFileName, options: {}, - rootFiles: ts.projectSystem.toExternalFiles([file1.path, file2.path]) + rootFiles: toExternalFiles([file1.path, file2.path]) }); - ts.projectSystem.checkNumberOfProjects(projectService, { externalProjects: 1 }); - const diags = session.executeCommand(compilerOptionsRequest).response as ts.server.protocol.DiagnosticWithLinePosition[]; + checkNumberOfProjects(projectService, { externalProjects: 1 }); + const diags = session.executeCommand(compilerOptionsRequest).response as DiagnosticWithLinePosition[]; // only file1 exists - expect error checkDiagnosticsWithLinePos(diags, ["File '/a/b/applib.ts' not found."]); } host.renameFile(file1.path, file2.path); { // only file2 exists - expect error - ts.projectSystem.checkNumberOfProjects(projectService, { externalProjects: 1 }); - const diags = session.executeCommand(compilerOptionsRequest).response as ts.server.protocol.DiagnosticWithLinePosition[]; + checkNumberOfProjects(projectService, { externalProjects: 1 }); + const diags = session.executeCommand(compilerOptionsRequest).response as DiagnosticWithLinePosition[]; checkDiagnosticsWithLinePos(diags, ["File '/a/b/app.ts' not found."]); } host.writeFile(file1.path, file1.content); { // both files exist - expect no errors - ts.projectSystem.checkNumberOfProjects(projectService, { externalProjects: 1 }); - const diags = session.executeCommand(compilerOptionsRequest).response as ts.server.protocol.DiagnosticWithLinePosition[]; + checkNumberOfProjects(projectService, { externalProjects: 1 }); + const diags = session.executeCommand(compilerOptionsRequest).response as DiagnosticWithLinePosition[]; checkDiagnosticsWithLinePos(diags, []); } }); @@ -86,27 +104,27 @@ describe("unittests:: tsserver:: Project Errors", () => { }; const config = { path: "/a/b/tsconfig.json", - content: JSON.stringify({ files: [file1, file2].map(f => ts.getBaseFileName(f.path)) }) + content: JSON.stringify({ files: [file1, file2].map(f => getBaseFileName(f.path)) }) }; - const host = ts.projectSystem.createServerHost([file1, config, ts.projectSystem.libFile]); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([file1, config, libFile]); + const session = createSession(host); const projectService = session.getProjectService(); - ts.projectSystem.openFilesForSession([file1], session); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); - const project = ts.projectSystem.configuredProjectAt(projectService, 0); - const compilerOptionsRequest: ts.server.protocol.CompilerOptionsDiagnosticsRequest = { + openFilesForSession([file1], session); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + const project = configuredProjectAt(projectService, 0); + const compilerOptionsRequest: CompilerOptionsDiagnosticsRequest = { type: "request", - command: ts.server.CommandNames.CompilerOptionsDiagnosticsFull, + command: CommandNames.CompilerOptionsDiagnosticsFull, seq: 2, arguments: { projectFileName: project.getProjectName() } }; - let diags = session.executeCommand(compilerOptionsRequest).response as ts.server.protocol.DiagnosticWithLinePosition[]; + let diags = session.executeCommand(compilerOptionsRequest).response as DiagnosticWithLinePosition[]; checkDiagnosticsWithLinePos(diags, ["File '/a/b/applib.ts' not found."]); host.writeFile(file2.path, file2.content); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); - diags = session.executeCommand(compilerOptionsRequest).response as ts.server.protocol.DiagnosticWithLinePosition[]; + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + diags = session.executeCommand(compilerOptionsRequest).response as DiagnosticWithLinePosition[]; checkDiagnosticsWithLinePos(diags, []); }); @@ -121,22 +139,22 @@ describe("unittests:: tsserver:: Project Errors", () => { }; const correctConfig = { path: "/a/b/tsconfig.json", - content: JSON.stringify({ files: [file1, file2].map(f => ts.getBaseFileName(f.path)) }) + content: JSON.stringify({ files: [file1, file2].map(f => getBaseFileName(f.path)) }) }; const corruptedConfig = { path: correctConfig.path, content: correctConfig.content.substr(1) }; - const host = ts.projectSystem.createServerHost([file1, file2, corruptedConfig]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2, corruptedConfig]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); { projectService.checkNumberOfProjects({ configuredProjects: 1 }); - const configuredProject = ts.find(projectService.synchronizeProjectList([]), f => f.info!.projectName === corruptedConfig.path)!; + const configuredProject = find(projectService.synchronizeProjectList([]), f => f.info!.projectName === corruptedConfig.path)!; assert.isTrue(configuredProject !== undefined, "should find configured project"); checkProjectErrors(configuredProject, []); - const projectErrors = ts.projectSystem.configuredProjectAt(projectService, 0).getAllProjectErrors(); + const projectErrors = configuredProjectAt(projectService, 0).getAllProjectErrors(); checkProjectErrorsWorker(projectErrors, [ "'{' expected." ]); @@ -147,10 +165,10 @@ describe("unittests:: tsserver:: Project Errors", () => { host.writeFile(correctConfig.path, correctConfig.content); { projectService.checkNumberOfProjects({ configuredProjects: 1 }); - const configuredProject = ts.find(projectService.synchronizeProjectList([]), f => f.info!.projectName === corruptedConfig.path)!; + const configuredProject = find(projectService.synchronizeProjectList([]), f => f.info!.projectName === corruptedConfig.path)!; assert.isTrue(configuredProject !== undefined, "should find configured project"); checkProjectErrors(configuredProject, []); - const projectErrors = ts.projectSystem.configuredProjectAt(projectService, 0).getAllProjectErrors(); + const projectErrors = configuredProjectAt(projectService, 0).getAllProjectErrors(); checkProjectErrorsWorker(projectErrors, []); } }); @@ -166,32 +184,32 @@ describe("unittests:: tsserver:: Project Errors", () => { }; const correctConfig = { path: "/a/b/tsconfig.json", - content: JSON.stringify({ files: [file1, file2].map(f => ts.getBaseFileName(f.path)) }) + content: JSON.stringify({ files: [file1, file2].map(f => getBaseFileName(f.path)) }) }; const corruptedConfig = { path: correctConfig.path, content: correctConfig.content.substr(1) }; - const host = ts.projectSystem.createServerHost([file1, file2, correctConfig]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2, correctConfig]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); { projectService.checkNumberOfProjects({ configuredProjects: 1 }); - const configuredProject = ts.find(projectService.synchronizeProjectList([]), f => f.info!.projectName === corruptedConfig.path)!; + const configuredProject = find(projectService.synchronizeProjectList([]), f => f.info!.projectName === corruptedConfig.path)!; assert.isTrue(configuredProject !== undefined, "should find configured project"); checkProjectErrors(configuredProject, []); - const projectErrors = ts.projectSystem.configuredProjectAt(projectService, 0).getAllProjectErrors(); + const projectErrors = configuredProjectAt(projectService, 0).getAllProjectErrors(); checkProjectErrorsWorker(projectErrors, []); } // break config and trigger watcher host.writeFile(corruptedConfig.path, corruptedConfig.content); { projectService.checkNumberOfProjects({ configuredProjects: 1 }); - const configuredProject = ts.find(projectService.synchronizeProjectList([]), f => f.info!.projectName === corruptedConfig.path)!; + const configuredProject = find(projectService.synchronizeProjectList([]), f => f.info!.projectName === corruptedConfig.path)!; assert.isTrue(configuredProject !== undefined, "should find configured project"); checkProjectErrors(configuredProject, []); - const projectErrors = ts.projectSystem.configuredProjectAt(projectService, 0).getAllProjectErrors(); + const projectErrors = configuredProjectAt(projectService, 0).getAllProjectErrors(); checkProjectErrorsWorker(projectErrors, [ "'{' expected." ]); @@ -211,37 +229,37 @@ describe("unittests:: tsserver:: Project Errors are reported as appropriate", () path: "/a/b/tsconfig.json", content: "{" }; - const host = ts.projectSystem.createServerHost([file1, corruptedConfig]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, corruptedConfig]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); const project = projectService.findProject(corruptedConfig.path)!; - ts.projectSystem.checkProjectRootFiles(project, [file1.path]); + checkProjectRootFiles(project, [file1.path]); }); describe("when opening new file that doesnt exist on disk yet", () => { function verifyNonExistentFile(useProjectRoot: boolean) { const folderPath = "/user/someuser/projects/someFolder"; - const fileInRoot: ts.projectSystem.File = { + const fileInRoot: File = { path: `/src/somefile.d.ts`, content: "class c { }" }; - const fileInProjectRoot: ts.projectSystem.File = { + const fileInProjectRoot: File = { path: `${folderPath}/src/somefile.d.ts`, content: "class c { }" }; - const host = ts.projectSystem.createServerHost([ts.projectSystem.libFile, fileInRoot, fileInProjectRoot]); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs(), useInferredProjectPerProjectRoot: true }); + const host = createServerHost([libFile, fileInRoot, fileInProjectRoot]); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(), useInferredProjectPerProjectRoot: true }); const untitledFile = "untitled:Untitled-1"; const refPathNotFound1 = "../../../../../../typings/@epic/Core.d.ts"; const refPathNotFound2 = "./src/somefile.d.ts"; const fileContent = `/// /// `; - session.executeCommandSeq({ - command: ts.server.CommandNames.Open, + session.executeCommandSeq({ + command: CommandNames.Open, arguments: { file: untitledFile, fileContent, @@ -249,12 +267,12 @@ describe("unittests:: tsserver:: Project Errors are reported as appropriate", () projectRootPath: useProjectRoot ? folderPath : undefined } }); - ts.projectSystem.appendAllScriptInfos(session.getProjectService(), session.logger.logs); + appendAllScriptInfos(session.getProjectService(), session.logger.logs); // Since this is not js project so no typings are queued host.checkTimeoutQueueLength(0); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [untitledFile] }); - ts.projectSystem.baselineTsserverLogs("projectErrors", `when opening new file that doesnt exist on disk yet ${useProjectRoot ? "with projectRoot" : "without projectRoot"}`, session); + verifyGetErrRequest({ session, host, files: [untitledFile] }); + baselineTsserverLogs("projectErrors", `when opening new file that doesnt exist on disk yet ${useProjectRoot ? "with projectRoot" : "without projectRoot"}`, session); } it("has projectRoot", () => { @@ -268,43 +286,43 @@ describe("unittests:: tsserver:: Project Errors are reported as appropriate", () it("folder rename updates project structure and reports no errors", () => { const projectDir = "/a/b/projects/myproject"; - const app: ts.projectSystem.File = { + const app: File = { path: `${projectDir}/bar/app.ts`, content: "class Bar implements foo.Foo { getFoo() { return ''; } get2() { return 1; } }" }; - const foo: ts.projectSystem.File = { + const foo: File = { path: `${projectDir}/foo/foo.ts`, content: "declare namespace foo { interface Foo { get2(): number; getFoo(): string; } }" }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: `${projectDir}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { module: "none", targer: "es5" }, exclude: ["node_modules"] }) }; - const host = ts.projectSystem.createServerHost([app, foo, configFile]); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); + const host = createServerHost([app, foo, configFile]); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); - session.executeCommandSeq({ - command: ts.server.CommandNames.Open, + session.executeCommandSeq({ + command: CommandNames.Open, arguments: { file: app.path, } }); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [app] }); + verifyGetErrRequest({ session, host, files: [app] }); host.renameFolder(`${projectDir}/foo`, `${projectDir}/foo2`); host.runQueuedTimeoutCallbacks(); host.runQueuedTimeoutCallbacks(); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [app] }); - ts.projectSystem.baselineTsserverLogs("projectErrors", `folder rename updates project structure and reports no errors`, session); + verifyGetErrRequest({ session, host, files: [app] }); + baselineTsserverLogs("projectErrors", `folder rename updates project structure and reports no errors`, session); }); it("Getting errors before opening file", () => { - const file: ts.projectSystem.File = { + const file: File = { path: "/a/b/project/file.ts", content: "let x: number = false;" }; - const host = ts.projectSystem.createServerHost([file, ts.projectSystem.libFile]); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - session.executeCommandSeq({ - command: ts.server.CommandNames.Geterr, + const host = createServerHost([file, libFile]); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); + session.executeCommandSeq({ + command: CommandNames.Geterr, arguments: { delay: 0, files: [file.path] @@ -312,69 +330,69 @@ describe("unittests:: tsserver:: Project Errors are reported as appropriate", () }); host.checkTimeoutQueueLengthAndRun(1); - ts.projectSystem.baselineTsserverLogs("projectErrors", "getting errors before opening file", session); + baselineTsserverLogs("projectErrors", "getting errors before opening file", session); }); it("Reports errors correctly when file referenced by inferred project root, is opened right after closing the root file", () => { - const app: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/src/client/app.js`, + const app: File = { + path: `${projectRoot}/src/client/app.js`, content: "" }; - const serverUtilities: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/src/server/utilities.js`, + const serverUtilities: File = { + path: `${projectRoot}/src/server/utilities.js`, content: `function getHostName() { return "hello"; } export { getHostName };` }; - const backendTest: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/test/backend/index.js`, + const backendTest: File = { + path: `${projectRoot}/test/backend/index.js`, content: `import { getHostName } from '../../src/server/utilities';export default getHostName;` }; - const files = [ts.projectSystem.libFile, app, serverUtilities, backendTest]; - const host = ts.projectSystem.createServerHost(files); - const session = ts.projectSystem.createSession(host, { useInferredProjectPerProjectRoot: true, canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([{ file: app, projectRootPath: ts.tscWatch.projectRoot }], session); - ts.projectSystem.openFilesForSession([{ file: backendTest, projectRootPath: ts.tscWatch.projectRoot }], session); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [backendTest.path, app.path] }); - ts.projectSystem.closeFilesForSession([backendTest], session); - ts.projectSystem.openFilesForSession([{ file: serverUtilities.path, projectRootPath: ts.tscWatch.projectRoot }], session); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [serverUtilities.path, app.path] }); - ts.projectSystem.baselineTsserverLogs("projectErrors", `reports errors correctly when file referenced by inferred project root, is opened right after closing the root file`, session); + const files = [libFile, app, serverUtilities, backendTest]; + const host = createServerHost(files); + const session = createSession(host, { useInferredProjectPerProjectRoot: true, canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([{ file: app, projectRootPath: projectRoot }], session); + openFilesForSession([{ file: backendTest, projectRootPath: projectRoot }], session); + verifyGetErrRequest({ session, host, files: [backendTest.path, app.path] }); + closeFilesForSession([backendTest], session); + openFilesForSession([{ file: serverUtilities.path, projectRootPath: projectRoot }], session); + verifyGetErrRequest({ session, host, files: [serverUtilities.path, app.path] }); + baselineTsserverLogs("projectErrors", `reports errors correctly when file referenced by inferred project root, is opened right after closing the root file`, session); }); it("Correct errors when resolution resolves to file that has same ambient module and is also module", () => { const projectRootPath = "/users/username/projects/myproject"; - const aFile: ts.projectSystem.File = { + const aFile: File = { path: `${projectRootPath}/src/a.ts`, content: `import * as myModule from "@custom/plugin"; function foo() { // hello }` }; - const config: ts.projectSystem.File = { + const config: File = { path: `${projectRootPath}/tsconfig.json`, content: JSON.stringify({ include: ["src"] }) }; - const plugin: ts.projectSystem.File = { + const plugin: File = { path: `${projectRootPath}/node_modules/@custom/plugin/index.d.ts`, content: `import './proposed'; declare module '@custom/plugin' { export const version: string; }` }; - const pluginProposed: ts.projectSystem.File = { + const pluginProposed: File = { path: `${projectRootPath}/node_modules/@custom/plugin/proposed.d.ts`, content: `declare module '@custom/plugin' { export const bar = 10; }` }; - const files = [ts.projectSystem.libFile, aFile, config, plugin, pluginProposed]; - const host = ts.projectSystem.createServerHost(files); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([aFile], session); + const files = [libFile, aFile, config, plugin, pluginProposed]; + const host = createServerHost(files); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([aFile], session); checkErrors(); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: aFile.path, line: 3, @@ -385,28 +403,28 @@ declare module '@custom/plugin' { } }); checkErrors(); - ts.projectSystem.baselineTsserverLogs("projectErrors", `correct errors when resolution resolves to file that has same ambient module and is also module`, session); + baselineTsserverLogs("projectErrors", `correct errors when resolution resolves to file that has same ambient module and is also module`, session); function checkErrors() { host.checkTimeoutQueueLength(0); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [aFile] }); + verifyGetErrRequest({ session, host, files: [aFile] }); } }); describe("when semantic error returns includes global error", () => { - const file: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/ui.ts`, + const file: File = { + path: `${projectRoot}/ui.ts`, content: `const x = async (_action: string) => { };` }; - const config: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: "{}" }; - ts.projectSystem.verifyGetErrScenario({ + verifyGetErrScenario({ scenario: "projectErrors", subScenario: "when semantic error returns includes global error", - allFiles: () => [ts.projectSystem.libFile, file, config], + allFiles: () => [libFile, file, config], openFiles: () => [file], getErrRequest: () => [file], getErrForProjectRequest: () => [{ project: file, files: [file] }], @@ -417,11 +435,11 @@ declare module '@custom/plugin' { describe("unittests:: tsserver:: Project Errors for Configure file diagnostics events", () => { it("are generated when the config file has errors", () => { - const file: ts.projectSystem.File = { + const file: File = { path: "/a/b/app.ts", content: "let x = 10" }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -430,31 +448,31 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e } }` }; - const host = ts.projectSystem.createServerHost([file, ts.projectSystem.libFile, configFile]); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([file], session); - ts.projectSystem.baselineTsserverLogs("projectErrors", "configFileDiagnostic events are generated when the config file has errors", session); + const host = createServerHost([file, libFile, configFile]); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([file], session); + baselineTsserverLogs("projectErrors", "configFileDiagnostic events are generated when the config file has errors", session); }); it("are generated when the config file doesn't have errors", () => { - const file: ts.projectSystem.File = { + const file: File = { path: "/a/b/app.ts", content: "let x = 10" }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": {} }` }; - const host = ts.projectSystem.createServerHost([file, ts.projectSystem.libFile, configFile]); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([file], session); - ts.projectSystem.baselineTsserverLogs("projectErrors", "configFileDiagnostic events are generated when the config file doesnt have errors", session); + const host = createServerHost([file, libFile, configFile]); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([file], session); + baselineTsserverLogs("projectErrors", "configFileDiagnostic events are generated when the config file doesnt have errors", session); }); it("are generated when the config file changes", () => { - const file: ts.projectSystem.File = { + const file: File = { path: "/a/b/app.ts", content: "let x = 10" }; @@ -465,9 +483,9 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e }` }; - const host = ts.projectSystem.createServerHost([file, ts.projectSystem.libFile, configFile]); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([file], session); + const host = createServerHost([file, libFile, configFile]); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([file], session); configFile.content = `{ "compilerOptions": { @@ -482,23 +500,23 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e }`; host.writeFile(configFile.path, configFile.content); host.runQueuedTimeoutCallbacks(); - ts.projectSystem.baselineTsserverLogs("projectErrors", "configFileDiagnostic events are generated when the config file changes", session); + baselineTsserverLogs("projectErrors", "configFileDiagnostic events are generated when the config file changes", session); }); it("are not generated when the config file does not include file opened and config file has errors", () => { - const file: ts.projectSystem.File = { + const file: File = { path: "/a/b/app.ts", content: "let x = 10" }; - const file2: ts.projectSystem.File = { + const file2: File = { path: "/a/b/test.ts", content: "let x = 10" }; - const file3: ts.projectSystem.File = { + const file3: File = { path: "/a/b/test2.ts", content: "let xy = 10" }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -508,21 +526,21 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e "files": ["app.ts"] }` }; - const host = ts.projectSystem.createServerHost([file, ts.projectSystem.libFile, configFile]); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([file2], session); - ts.projectSystem.openFilesForSession([file], session); + const host = createServerHost([file, libFile, configFile]); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([file2], session); + openFilesForSession([file], session); // We generate only if project is created when opening file from the project - ts.projectSystem.openFilesForSession([file3], session); - ts.projectSystem.baselineTsserverLogs("projectErrors", "configFileDiagnostic events are not generated when the config file does not include file opened and config file has errors", session); + openFilesForSession([file3], session); + baselineTsserverLogs("projectErrors", "configFileDiagnostic events are not generated when the config file does not include file opened and config file has errors", session); }); it("are not generated when the config file has errors but suppressDiagnosticEvents is true", () => { - const file: ts.projectSystem.File = { + const file: File = { path: "/a/b/app.ts", content: "let x = 10" }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": { @@ -531,48 +549,48 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e } }` }; - const host = ts.projectSystem.createServerHost([file, ts.projectSystem.libFile, configFile]); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, suppressDiagnosticEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([file], session); - ts.projectSystem.baselineTsserverLogs("projectErrors", "configFileDiagnostic events are not generated when the config file has errors but suppressDiagnosticEvents is true", session); + const host = createServerHost([file, libFile, configFile]); + const session = createSession(host, { canUseEvents: true, suppressDiagnosticEvents: true, logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([file], session); + baselineTsserverLogs("projectErrors", "configFileDiagnostic events are not generated when the config file has errors but suppressDiagnosticEvents is true", session); }); it("are not generated when the config file does not include file opened and doesnt contain any errors", () => { - const file: ts.projectSystem.File = { + const file: File = { path: "/a/b/app.ts", content: "let x = 10" }; - const file2: ts.projectSystem.File = { + const file2: File = { path: "/a/b/test.ts", content: "let x = 10" }; - const file3: ts.projectSystem.File = { + const file3: File = { path: "/a/b/test2.ts", content: "let xy = 10" }; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "files": ["app.ts"] }` }; - const host = ts.projectSystem.createServerHost([file, file2, file3, ts.projectSystem.libFile, configFile]); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([file2], session); - ts.projectSystem.openFilesForSession([file], session); + const host = createServerHost([file, file2, file3, libFile, configFile]); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([file2], session); + openFilesForSession([file], session); // We generate only if project is created when opening file from the project - ts.projectSystem.openFilesForSession([file3], session); - ts.projectSystem.baselineTsserverLogs("projectErrors", "configFileDiagnostic events are not generated when the config file does not include file opened and doesnt contain any errors", session); + openFilesForSession([file3], session); + baselineTsserverLogs("projectErrors", "configFileDiagnostic events are not generated when the config file does not include file opened and doesnt contain any errors", session); }); it("contains the project reference errors", () => { - const file: ts.projectSystem.File = { + const file: File = { path: "/a/b/app.ts", content: "let x = 10" }; const noSuchTsconfig = "no-such-tsconfig.json"; - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "files": ["app.ts"], @@ -580,10 +598,10 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e }` }; - const host = ts.projectSystem.createServerHost([file, ts.projectSystem.libFile, configFile]); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([file], session); - ts.projectSystem.baselineTsserverLogs("projectErrors", "configFileDiagnostic events contains the project reference errors", session); + const host = createServerHost([file, libFile, configFile]); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([file], session); + baselineTsserverLogs("projectErrors", "configFileDiagnostic events contains the project reference errors", session); }); }); @@ -593,34 +611,34 @@ describe("unittests:: tsserver:: Project Errors dont include overwrite emit erro path: "/a/b/f1.js", content: "function test1() { }" }; - const host = ts.projectSystem.createServerHost([f1, ts.projectSystem.libFile]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([f1], session); + const host = createServerHost([f1, libFile]); + const session = createSession(host); + openFilesForSession([f1], session); const projectService = session.getProjectService(); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); const projectName = projectService.inferredProjects[0].getProjectName(); const diags = session.executeCommand({ type: "request", - command: ts.server.CommandNames.CompilerOptionsDiagnosticsFull, + command: CommandNames.CompilerOptionsDiagnosticsFull, seq: 2, arguments: { projectFileName: projectName } - } as ts.server.protocol.CompilerOptionsDiagnosticsRequest).response as readonly ts.projectSystem.protocol.DiagnosticWithLinePosition[]; + } as CompilerOptionsDiagnosticsRequest).response as readonly DiagnosticWithLinePosition[]; assert.isTrue(diags.length === 0); session.executeCommand({ type: "request", - command: ts.server.CommandNames.CompilerOptionsForInferredProjects, + command: CommandNames.CompilerOptionsForInferredProjects, seq: 3, - arguments: { options: { module: ts.ModuleKind.CommonJS } } - } as ts.server.protocol.SetCompilerOptionsForInferredProjectsRequest); + arguments: { options: { module: ModuleKind.CommonJS } } + } as SetCompilerOptionsForInferredProjectsRequest); const diagsAfterUpdate = session.executeCommand({ type: "request", - command: ts.server.CommandNames.CompilerOptionsDiagnosticsFull, + command: CommandNames.CompilerOptionsDiagnosticsFull, seq: 4, arguments: { projectFileName: projectName } - } as ts.server.protocol.CompilerOptionsDiagnosticsRequest).response as readonly ts.projectSystem.protocol.DiagnosticWithLinePosition[]; + } as CompilerOptionsDiagnosticsRequest).response as readonly DiagnosticWithLinePosition[]; assert.isTrue(diagsAfterUpdate.length === 0); }); @@ -629,43 +647,43 @@ describe("unittests:: tsserver:: Project Errors dont include overwrite emit erro path: "/a/b/f1.js", content: "function test1() { }" }; - const host = ts.projectSystem.createServerHost([f1, ts.projectSystem.libFile]); - const session = ts.projectSystem.createSession(host); + const host = createServerHost([f1, libFile]); + const session = createSession(host); const projectService = session.getProjectService(); const projectFileName = "/a/b/project.csproj"; - const externalFiles = ts.projectSystem.toExternalFiles([f1.path]); + const externalFiles = toExternalFiles([f1.path]); projectService.openExternalProject({ projectFileName, rootFiles: externalFiles, options: {} - } as ts.projectSystem.protocol.ExternalProject); + } as ExternalProject); - ts.projectSystem.checkNumberOfProjects(projectService, { externalProjects: 1 }); + checkNumberOfProjects(projectService, { externalProjects: 1 }); const diags = session.executeCommand({ type: "request", - command: ts.server.CommandNames.CompilerOptionsDiagnosticsFull, + command: CommandNames.CompilerOptionsDiagnosticsFull, seq: 2, arguments: { projectFileName } - } as ts.server.protocol.CompilerOptionsDiagnosticsRequest).response as readonly ts.server.protocol.DiagnosticWithLinePosition[]; + } as CompilerOptionsDiagnosticsRequest).response as readonly DiagnosticWithLinePosition[]; assert.isTrue(diags.length === 0); session.executeCommand({ type: "request", - command: ts.server.CommandNames.OpenExternalProject, + command: CommandNames.OpenExternalProject, seq: 3, arguments: { projectFileName, rootFiles: externalFiles, - options: { module: ts.ModuleKind.CommonJS } + options: { module: ModuleKind.CommonJS } } - } as ts.server.protocol.OpenExternalProjectRequest); + } as OpenExternalProjectRequest); const diagsAfterUpdate = session.executeCommand({ type: "request", - command: ts.server.CommandNames.CompilerOptionsDiagnosticsFull, + command: CommandNames.CompilerOptionsDiagnosticsFull, seq: 4, arguments: { projectFileName } - } as ts.server.protocol.CompilerOptionsDiagnosticsRequest).response as readonly ts.server.protocol.DiagnosticWithLinePosition[]; + } as CompilerOptionsDiagnosticsRequest).response as readonly DiagnosticWithLinePosition[]; assert.isTrue(diagsAfterUpdate.length === 0); }); }); @@ -692,20 +710,20 @@ describe("unittests:: tsserver:: Project Errors reports Options Diagnostic locat path: "/a/b/tsconfig.json", content: configFileContentWithComment }; - const host = ts.projectSystem.createServerHost([file, ts.projectSystem.libFile, configFile]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([file], session); + const host = createServerHost([file, libFile, configFile]); + const session = createSession(host); + openFilesForSession([file], session); const projectService = session.getProjectService(); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); - const projectName = ts.projectSystem.configuredProjectAt(projectService, 0).getProjectName(); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + const projectName = configuredProjectAt(projectService, 0).getProjectName(); const diags = session.executeCommand({ type: "request", - command: ts.server.CommandNames.SemanticDiagnosticsSync, + command: CommandNames.SemanticDiagnosticsSync, seq: 2, arguments: { file: configFile.path, projectFileName: projectName, includeLinePosition: true } - } as ts.server.protocol.SemanticDiagnosticsSyncRequest).response as readonly ts.server.protocol.DiagnosticWithLinePosition[]; + } as SemanticDiagnosticsSyncRequest).response as readonly DiagnosticWithLinePosition[]; assert.isTrue(diags.length === 3); configFile.content = configFileContentWithoutCommentLine; @@ -713,17 +731,17 @@ describe("unittests:: tsserver:: Project Errors reports Options Diagnostic locat const diagsAfterEdit = session.executeCommand({ type: "request", - command: ts.server.CommandNames.SemanticDiagnosticsSync, + command: CommandNames.SemanticDiagnosticsSync, seq: 2, arguments: { file: configFile.path, projectFileName: projectName, includeLinePosition: true } - } as ts.server.protocol.SemanticDiagnosticsSyncRequest).response as readonly ts.server.protocol.DiagnosticWithLinePosition[]; + } as SemanticDiagnosticsSyncRequest).response as readonly DiagnosticWithLinePosition[]; assert.isTrue(diagsAfterEdit.length === 3); verifyDiagnostic(diags[0], diagsAfterEdit[0]); verifyDiagnostic(diags[1], diagsAfterEdit[1]); verifyDiagnostic(diags[2], diagsAfterEdit[2]); - function verifyDiagnostic(beforeEditDiag: ts.server.protocol.DiagnosticWithLinePosition, afterEditDiag: ts.server.protocol.DiagnosticWithLinePosition) { + function verifyDiagnostic(beforeEditDiag: DiagnosticWithLinePosition, afterEditDiag: DiagnosticWithLinePosition) { assert.equal(beforeEditDiag.message, afterEditDiag.message); assert.equal(beforeEditDiag.code, afterEditDiag.code); assert.equal(beforeEditDiag.category, afterEditDiag.category); @@ -737,25 +755,25 @@ describe("unittests:: tsserver:: Project Errors reports Options Diagnostic locat describe("unittests:: tsserver:: Project Errors with config file change", () => { it("Updates diagnostics when '--noUnusedLabels' changes", () => { - const aTs: ts.projectSystem.File = { path: "/a.ts", content: "label: while (1) {}" }; + const aTs: File = { path: "/a.ts", content: "label: while (1) {}" }; const options = (allowUnusedLabels: boolean) => `{ "compilerOptions": { "allowUnusedLabels": ${allowUnusedLabels} } }`; - const tsconfig: ts.projectSystem.File = { path: "/tsconfig.json", content: options(/*allowUnusedLabels*/ true) }; + const tsconfig: File = { path: "/tsconfig.json", content: options(/*allowUnusedLabels*/ true) }; - const host = ts.projectSystem.createServerHost([aTs, tsconfig]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([aTs], session); + const host = createServerHost([aTs, tsconfig]); + const session = createSession(host); + openFilesForSession([aTs], session); host.modifyFile(tsconfig.path, options(/*allowUnusedLabels*/ false)); host.runQueuedTimeoutCallbacks(); - const response = ts.projectSystem.executeSessionRequest(session, ts.projectSystem.protocol.CommandTypes.SemanticDiagnosticsSync, { file: aTs.path }) as ts.projectSystem.protocol.Diagnostic[] | undefined; - assert.deepEqual(response, [ + const response = executeSessionRequest(session, CommandTypes.SemanticDiagnosticsSync, { file: aTs.path }) as protocol.Diagnostic[] | undefined; + assert.deepEqual(response, [ { start: { line: 1, offset: 1 }, end: { line: 1, offset: 1 + "label".length }, text: "Unused label.", category: "error", - code: ts.Diagnostics.Unused_label.code, + code: Diagnostics.Unused_label.code, relatedInformation: undefined, reportsUnnecessary: true, reportsDeprecated: undefined, @@ -767,18 +785,18 @@ describe("unittests:: tsserver:: Project Errors with config file change", () => describe("unittests:: tsserver:: Project Errors with resolveJsonModule", () => { function createSessionForTest({ include }: { include: readonly string[]; }) { - const test: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/src/test.ts`, + const test: File = { + path: `${projectRoot}/src/test.ts`, content: `import * as blabla from "./blabla.json"; declare var console: any; console.log(blabla);` }; - const blabla: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/src/blabla.json`, + const blabla: File = { + path: `${projectRoot}/src/blabla.json`, content: "{}" }; - const tsconfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const tsconfig: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { resolveJsonModule: true, @@ -788,9 +806,9 @@ console.log(blabla);` }) }; - const host = ts.projectSystem.createServerHost([test, blabla, ts.projectSystem.libFile, tsconfig]); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([test], session); + const host = createServerHost([test, blabla, libFile, tsconfig]); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([test], session); return { host, session, test, blabla, tsconfig }; } @@ -798,56 +816,56 @@ console.log(blabla);` const { host, session, test } = createSessionForTest({ include: ["./src/*.ts", "./src/*.json"] }); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [test] }); - ts.projectSystem.baselineTsserverLogs("projectErrors", `should not report incorrect error when json is root file found by tsconfig`, session); + verifyGetErrRequest({ session, host, files: [test] }); + baselineTsserverLogs("projectErrors", `should not report incorrect error when json is root file found by tsconfig`, session); }); it("should report error when json is not root file found by tsconfig", () => { const { host, session, test } = createSessionForTest({ include: ["./src/*.ts"] }); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [test] }); - ts.projectSystem.baselineTsserverLogs("projectErrors", `should report error when json is not root file found by tsconfig`, session); + verifyGetErrRequest({ session, host, files: [test] }); + baselineTsserverLogs("projectErrors", `should report error when json is not root file found by tsconfig`, session); }); }); describe("unittests:: tsserver:: Project Errors with npm install when", () => { function verifyNpmInstall(timeoutDuringPartialInstallation: boolean) { - const main: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/src/main.ts`, + const main: File = { + path: `${projectRoot}/src/main.ts`, content: "import * as _a from '@angular/core';" }; - const config: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/tsconfig.json`, content: "{}" }; // Move things from staging to node_modules without triggering watch - const moduleFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/node_modules/@angular/core/index.d.ts`, + const moduleFile: File = { + path: `${projectRoot}/node_modules/@angular/core/index.d.ts`, content: `export const y = 10;` }; - const projectFiles = [main, ts.projectSystem.libFile, config]; - const host = ts.projectSystem.createServerHost(projectFiles); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([{ file: main, projectRootPath: ts.tscWatch.projectRoot }], session); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [main] }); + const projectFiles = [main, libFile, config]; + const host = createServerHost(projectFiles); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([{ file: main, projectRootPath: projectRoot }], session); + verifyGetErrRequest({ session, host, files: [main] }); let npmInstallComplete = false; // Simulate npm install - let filesAndFoldersToAdd: (ts.projectSystem.File | ts.projectSystem.Folder)[] = [ - { path: `${ts.tscWatch.projectRoot}/node_modules` }, // This should queue update - { path: `${ts.tscWatch.projectRoot}/node_modules/.staging` }, - { path: `${ts.tscWatch.projectRoot}/node_modules/.staging/@babel` }, - { path: `${ts.tscWatch.projectRoot}/node_modules/.staging/@babel/helper-plugin-utils-a06c629f` }, - { path: `${ts.tscWatch.projectRoot}/node_modules/.staging/core-js-db53158d` }, + let filesAndFoldersToAdd: (File | Folder)[] = [ + { path: `${projectRoot}/node_modules` }, // This should queue update + { path: `${projectRoot}/node_modules/.staging` }, + { path: `${projectRoot}/node_modules/.staging/@babel` }, + { path: `${projectRoot}/node_modules/.staging/@babel/helper-plugin-utils-a06c629f` }, + { path: `${projectRoot}/node_modules/.staging/core-js-db53158d` }, ]; verifyWhileNpmInstall(3); filesAndFoldersToAdd = [ - { path: `${ts.tscWatch.projectRoot}/node_modules/.staging/@angular/platform-browser-dynamic-5efaaa1a` }, - { path: `${ts.tscWatch.projectRoot}/node_modules/.staging/@angular/cli-c1e44b05/models/analytics.d.ts`, content: `export const x = 10;` }, - { path: `${ts.tscWatch.projectRoot}/node_modules/.staging/@angular/core-0963aebf/index.d.ts`, content: `export const y = 10;` }, + { path: `${projectRoot}/node_modules/.staging/@angular/platform-browser-dynamic-5efaaa1a` }, + { path: `${projectRoot}/node_modules/.staging/@angular/cli-c1e44b05/models/analytics.d.ts`, content: `export const x = 10;` }, + { path: `${projectRoot}/node_modules/.staging/@angular/core-0963aebf/index.d.ts`, content: `export const y = 10;` }, ]; // Since we added/removed in .staging no timeout verifyWhileNpmInstall(0); @@ -858,13 +876,13 @@ describe("unittests:: tsserver:: Project Errors with npm install when", () => { verifyWhileNpmInstall(0); // Remove staging folder to remove errors - host.deleteFolder(`${ts.tscWatch.projectRoot}/node_modules/.staging`, /*recursive*/ true); + host.deleteFolder(`${projectRoot}/node_modules/.staging`, /*recursive*/ true); npmInstallComplete = true; projectFiles.push(moduleFile); // Additional watch for watching script infos from node_modules verifyWhileNpmInstall(3); - ts.projectSystem.baselineTsserverLogs("projectErrors", `npm install when timeout occurs ${timeoutDuringPartialInstallation ? "inbetween" : "after"} installation`, session); + baselineTsserverLogs("projectErrors", `npm install when timeout occurs ${timeoutDuringPartialInstallation ? "inbetween" : "after"} installation`, session); function verifyWhileNpmInstall(timeouts: number) { filesAndFoldersToAdd.forEach(f => host.ensureFileOrFolder(f)); @@ -877,7 +895,7 @@ describe("unittests:: tsserver:: Project Errors with npm install when", () => { else { host.checkTimeoutQueueLength(timeouts ? 3 : 2); } - ts.projectSystem.verifyGetErrRequest({ session, host, files: [main], existingTimeouts: !npmInstallComplete && !timeoutDuringPartialInstallation ? timeouts ? 3 : 2 : undefined }); + verifyGetErrRequest({ session, host, files: [main], existingTimeouts: !npmInstallComplete && !timeoutDuringPartialInstallation ? timeouts ? 3 : 2 : undefined }); } } diff --git a/src/testRunner/unittests/tsserver/projectReferenceCompileOnSave.ts b/src/testRunner/unittests/tsserver/projectReferenceCompileOnSave.ts index a6637f7aa0588..b0f8ad42d7e63 100644 --- a/src/testRunner/unittests/tsserver/projectReferenceCompileOnSave.ts +++ b/src/testRunner/unittests/tsserver/projectReferenceCompileOnSave.ts @@ -1,22 +1,32 @@ -import * as ts from "../../_namespaces/ts"; +import { EmitOutput } from "../../../compiler/builderStatePublic"; +import { emptyArray } from "../../../compiler/core"; +import { Path } from "../../../compiler/types"; +import { changeExtension } from "../../../compiler/utilities"; +import { changeToHostTrackingWrittenFiles } from "../../../harness/virtualFileSystemWithWatch"; +import { + ChangeRequest, CommandTypes, CompileOnSaveAffectedFileListRequest, CompileOnSaveAffectedFileListSingleProject, + CompileOnSaveEmitFileRequest, EmitOutputRequest, +} from "../../../server/protocol"; +import { ensureErrorFreeBuild, projectRoot } from "../tscWatch/helpers"; +import { createServerHost, createSession, File, libFile, openFilesForSession, protocolToLocation } from "./helpers"; describe("unittests:: tsserver:: with project references and compile on save", () => { - const dependecyLocation = `${ts.tscWatch.projectRoot}/dependency`; - const usageLocation = `${ts.tscWatch.projectRoot}/usage`; - const dependencyTs: ts.projectSystem.File = { + const dependecyLocation = `${projectRoot}/dependency`; + const usageLocation = `${projectRoot}/usage`; + const dependencyTs: File = { path: `${dependecyLocation}/fns.ts`, content: `export function fn1() { } export function fn2() { } ` }; - const dependencyConfig: ts.projectSystem.File = { + const dependencyConfig: File = { path: `${dependecyLocation}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, declarationDir: "../decls" }, compileOnSave: true }) }; - const usageTs: ts.projectSystem.File = { + const usageTs: File = { path: `${usageLocation}/usage.ts`, content: `import { fn1, @@ -26,7 +36,7 @@ fn1(); fn2(); ` }; - const usageConfig: ts.projectSystem.File = { + const usageConfig: File = { path: `${usageLocation}/tsconfig.json`, content: JSON.stringify({ compileOnSave: true, @@ -40,7 +50,7 @@ fn2(); exports.fn3 = fn3;`; const changeDts = "export declare function fn3(): void;"; - function expectedAffectedFiles(config: ts.projectSystem.File, fileNames: readonly ts.projectSystem.File[]): ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject { + function expectedAffectedFiles(config: File, fileNames: readonly File[]): CompileOnSaveAffectedFileListSingleProject { return { projectFileName: config.path, fileNames: fileNames.map(f => f.path), @@ -48,7 +58,7 @@ exports.fn3 = fn3;`; }; } - function expectedUsageEmitFiles(appendJsText?: string): readonly ts.projectSystem.File[] { + function expectedUsageEmitFiles(appendJsText?: string): readonly File[] { const appendJs = appendJsText ? `${appendJsText} ` : ""; return [{ @@ -62,7 +72,7 @@ ${appendJs}` }]; } - function expectedEmitOutput(expectedFiles: readonly ts.projectSystem.File[]): ts.EmitOutput { + function expectedEmitOutput(expectedFiles: readonly File[]): EmitOutput { return { outputFiles: expectedFiles.map(({ path, content }) => ({ name: path, @@ -70,19 +80,19 @@ ${appendJs}` writeByteOrderMark: false })), emitSkipped: false, - diagnostics: ts.emptyArray + diagnostics: emptyArray }; } - function noEmitOutput(): ts.EmitOutput { + function noEmitOutput(): EmitOutput { return { emitSkipped: true, outputFiles: [], - diagnostics: ts.emptyArray + diagnostics: emptyArray }; } - function expectedDependencyEmitFiles(appendJsText?: string, appendDtsText?: string): readonly ts.projectSystem.File[] { + function expectedDependencyEmitFiles(appendJsText?: string, appendDtsText?: string): readonly File[] { const appendJs = appendJsText ? `${appendJsText} ` : ""; const appendDts = appendDtsText ? `${appendDtsText} @@ -100,7 +110,7 @@ exports.fn2 = fn2; ${appendJs}` }, { - path: `${ts.tscWatch.projectRoot}/decls/fns.d.ts`, + path: `${projectRoot}/decls/fns.d.ts`, content: `export declare function fn1(): void; export declare function fn2(): void; ${appendDts}` @@ -111,24 +121,24 @@ ${appendDts}` describe("when dependency project is not open", () => { describe("Of usageTs", () => { it("with initial file open, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -136,35 +146,35 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with initial file open, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -172,42 +182,42 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with local change to dependency, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); host.writeFile(dependencyTs.path, `${dependencyTs.content}${localChange}`); host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -215,42 +225,42 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with local change to dependency, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); host.writeFile(dependencyTs.path, `${dependencyTs.content}${localChange}`); host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -258,31 +268,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with local change to usage, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -294,17 +304,17 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -312,31 +322,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with local change to usage, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -348,17 +358,17 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -366,42 +376,42 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with change to dependency, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); host.writeFile(dependencyTs.path, `${dependencyTs.content}${change}`); host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -409,42 +419,42 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with change to dependency, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); host.writeFile(dependencyTs.path, `${dependencyTs.content}${change}`); host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -452,31 +462,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with change to usage, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -488,17 +498,17 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -506,31 +516,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with change to usage, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -542,17 +552,17 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -560,172 +570,172 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); }); describe("Of dependencyTs in usage project", () => { it("with initial file open, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path } }).response; assert.isFalse(actualEmit, "Emit files"); assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); }); it("with initial file open, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response; assert.isFalse(actualEmit, "Emit files"); assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); }); it("with local change to dependency, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); host.writeFile(dependencyTs.path, `${dependencyTs.content}${localChange}`); host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ - expectedAffectedFiles(usageConfig, ts.emptyArray) + expectedAffectedFiles(usageConfig, emptyArray) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path } }).response; assert.isFalse(actualEmit, "Emit files"); assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); }); it("with local change to dependency, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); host.writeFile(dependencyTs.path, `${dependencyTs.content}${localChange}`); host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ - expectedAffectedFiles(usageConfig, ts.emptyArray) + expectedAffectedFiles(usageConfig, emptyArray) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response; assert.isFalse(actualEmit, "Emit files"); assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); }); it("with local change to usage, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -737,44 +747,44 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ - expectedAffectedFiles(usageConfig, ts.emptyArray) + expectedAffectedFiles(usageConfig, emptyArray) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path } }).response; assert.isFalse(actualEmit, "Emit files"); assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); }); it("with local change to usage, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -786,120 +796,120 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ - expectedAffectedFiles(usageConfig, ts.emptyArray) + expectedAffectedFiles(usageConfig, emptyArray) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response; assert.isFalse(actualEmit, "Emit files"); assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); }); it("with change to dependency, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); host.writeFile(dependencyTs.path, `${dependencyTs.content}${change}`); host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path } }).response; assert.isFalse(actualEmit, "Emit files"); assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); }); it("with change to dependency, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); host.writeFile(dependencyTs.path, `${dependencyTs.content}${change}`); host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response; assert.isFalse(actualEmit, "Emit files"); assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); }); it("with change to usage, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -911,44 +921,44 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ - expectedAffectedFiles(usageConfig, ts.emptyArray) + expectedAffectedFiles(usageConfig, emptyArray) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path } }).response; assert.isFalse(actualEmit, "Emit files"); assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); }); it("with change to usage, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs], session); + const session = createSession(host); + openFilesForSession([usageTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -960,27 +970,27 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ - expectedAffectedFiles(usageConfig, ts.emptyArray) + expectedAffectedFiles(usageConfig, emptyArray) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response; assert.isFalse(actualEmit, "Emit files"); assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); }); }); @@ -989,24 +999,24 @@ ${appendDts}` describe("when the depedency file is open", () => { describe("Of usageTs", () => { it("with initial file open, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -1014,35 +1024,35 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with initial file open, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -1050,31 +1060,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with local change to dependency, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(dependencyTs.content); + const toLocation = protocolToLocation(dependencyTs.content); const location = toLocation(dependencyTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: dependencyTs.path, ...location, @@ -1086,17 +1096,17 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -1104,31 +1114,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with local change to dependency, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(dependencyTs.content); + const toLocation = protocolToLocation(dependencyTs.content); const location = toLocation(dependencyTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: dependencyTs.path, ...location, @@ -1140,17 +1150,17 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -1158,31 +1168,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with local change to usage, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -1194,17 +1204,17 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -1212,31 +1222,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with local change to usage, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -1248,17 +1258,17 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -1266,31 +1276,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with change to dependency, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(dependencyTs.content); + const toLocation = protocolToLocation(dependencyTs.content); const location = toLocation(dependencyTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: dependencyTs.path, ...location, @@ -1302,17 +1312,17 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -1320,31 +1330,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with change to dependency, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(dependencyTs.content); + const toLocation = protocolToLocation(dependencyTs.content); const location = toLocation(dependencyTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: dependencyTs.path, ...location, @@ -1356,17 +1366,17 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -1374,31 +1384,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with change to usage, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -1410,17 +1420,17 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -1428,31 +1438,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with change to usage, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -1464,17 +1474,17 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: usageTs.path, projectFileName: usageConfig.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -1482,65 +1492,65 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: usageTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); }); describe("Of dependencyTs in usage project", () => { it("with initial file open, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response; assert.isFalse(actualEmit, "Emit files"); assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); }); it("with local change to dependency, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(dependencyTs.content); + const toLocation = protocolToLocation(dependencyTs.content); const location = toLocation(dependencyTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: dependencyTs.path, ...location, @@ -1552,44 +1562,44 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ - expectedAffectedFiles(usageConfig, ts.emptyArray) + expectedAffectedFiles(usageConfig, emptyArray) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response; assert.isFalse(actualEmit, "Emit files"); assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); }); it("with local change to usage, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -1601,44 +1611,44 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ - expectedAffectedFiles(usageConfig, ts.emptyArray) + expectedAffectedFiles(usageConfig, emptyArray) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response; assert.isFalse(actualEmit, "Emit files"); assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); }); it("with change to dependency, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(dependencyTs.content); + const toLocation = protocolToLocation(dependencyTs.content); const location = toLocation(dependencyTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: dependencyTs.path, ...location, @@ -1650,44 +1660,44 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response; assert.isFalse(actualEmit, "Emit files"); assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); }); it("with change to usage, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -1699,52 +1709,52 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ - expectedAffectedFiles(usageConfig, ts.emptyArray) + expectedAffectedFiles(usageConfig, emptyArray) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } }).response; assert.isFalse(actualEmit, "Emit files"); assert.equal(host.writtenFiles.size, 0); // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: usageConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, noEmitOutput(), "Emit output"); }); }); describe("Of dependencyTs", () => { it("with initial file open, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]), expectedAffectedFiles(dependencyConfig, [dependencyTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -1752,35 +1762,35 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with initial file open, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(dependencyConfig, [dependencyTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -1788,31 +1798,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with local change to dependency, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(dependencyTs.content); + const toLocation = protocolToLocation(dependencyTs.content); const location = toLocation(dependencyTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: dependencyTs.path, ...location, @@ -1824,18 +1834,18 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ - expectedAffectedFiles(usageConfig, ts.emptyArray), + expectedAffectedFiles(usageConfig, emptyArray), expectedAffectedFiles(dependencyConfig, [dependencyTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -1843,31 +1853,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with local change to dependency, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(dependencyTs.content); + const toLocation = protocolToLocation(dependencyTs.content); const location = toLocation(dependencyTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: dependencyTs.path, ...location, @@ -1879,17 +1889,17 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(dependencyConfig, [dependencyTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -1897,31 +1907,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with local change to usage, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -1933,18 +1943,18 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ - expectedAffectedFiles(usageConfig, ts.emptyArray), + expectedAffectedFiles(usageConfig, emptyArray), expectedAffectedFiles(dependencyConfig, [dependencyTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -1952,31 +1962,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with local change to usage, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -1988,17 +1998,17 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(dependencyConfig, [dependencyTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -2006,31 +2016,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with change to dependency, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(dependencyTs.content); + const toLocation = protocolToLocation(dependencyTs.content); const location = toLocation(dependencyTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: dependencyTs.path, ...location, @@ -2042,18 +2052,18 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(usageConfig, [usageTs]), expectedAffectedFiles(dependencyConfig, [dependencyTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -2061,31 +2071,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with change to dependency, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(dependencyTs.content); + const toLocation = protocolToLocation(dependencyTs.content); const location = toLocation(dependencyTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: dependencyTs.path, ...location, @@ -2097,17 +2107,17 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(dependencyConfig, [dependencyTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -2115,31 +2125,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with change to usage, without specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -2151,18 +2161,18 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ - expectedAffectedFiles(usageConfig, ts.emptyArray), + expectedAffectedFiles(usageConfig, emptyArray), expectedAffectedFiles(dependencyConfig, [dependencyTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -2170,31 +2180,31 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); it("with change to usage, with specifying project file", () => { - const host = ts.TestFSWithWatch.changeToHostTrackingWrittenFiles( - ts.projectSystem.createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, ts.projectSystem.libFile]) + const host = changeToHostTrackingWrittenFiles( + createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]) ); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([usageTs, dependencyTs], session); + const session = createSession(host); + openFilesForSession([usageTs, dependencyTs], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path } }); - const toLocation = ts.projectSystem.protocolToLocation(usageTs.content); + const toLocation = protocolToLocation(usageTs.content); const location = toLocation(usageTs.content.length); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: usageTs.path, ...location, @@ -2206,17 +2216,17 @@ ${appendDts}` host.writtenFiles.clear(); // Verify CompileOnSaveAffectedFileList - const actualAffectedFiles = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveAffectedFileList, + const actualAffectedFiles = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveAffectedFileList, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } - }).response as ts.projectSystem.protocol.CompileOnSaveAffectedFileListSingleProject[]; + }).response as CompileOnSaveAffectedFileListSingleProject[]; assert.deepEqual(actualAffectedFiles, [ expectedAffectedFiles(dependencyConfig, [dependencyTs]) ], "Affected files"); // Verify CompileOnSaveEmit - const actualEmit = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + const actualEmit = session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } }).response; assert.isTrue(actualEmit, "Emit files"); @@ -2224,14 +2234,14 @@ ${appendDts}` assert.equal(host.writtenFiles.size, expectedFiles.length); for (const file of expectedFiles) { assert.equal(host.readFile(file.path), file.content, `Expected to write ${file.path}`); - assert.isTrue(host.writtenFiles.has(file.path as ts.Path), `${file.path} is newly written`); + assert.isTrue(host.writtenFiles.has(file.path as Path), `${file.path} is newly written`); } // Verify EmitOutput - const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.EmitOutput, + const { exportedModulesFromDeclarationEmit: _1, ...actualEmitOutput } = session.executeCommandSeq({ + command: CommandTypes.EmitOutput, arguments: { file: dependencyTs.path, projectFileName: dependencyConfig.path } - }).response as ts.EmitOutput; + }).response as EmitOutput; assert.deepEqual(actualEmitOutput, expectedEmitOutput(expectedFiles), "Emit output"); }); }); @@ -2240,8 +2250,8 @@ ${appendDts}` describe("unittests:: tsserver:: with project references and compile on save with external projects", () => { it("compile on save emits same output as project build", () => { - const tsbaseJson: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsbase.json`, + const tsbaseJson: File = { + path: `${projectRoot}/tsbase.json`, content: JSON.stringify({ compileOnSave: true, compilerOptions: { @@ -2250,8 +2260,8 @@ describe("unittests:: tsserver:: with project references and compile on save wit } }) }; - const buttonClass = `${ts.tscWatch.projectRoot}/buttonClass`; - const buttonConfig: ts.projectSystem.File = { + const buttonClass = `${projectRoot}/buttonClass`; + const buttonConfig: File = { path: `${buttonClass}/tsconfig.json`, content: JSON.stringify({ extends: "../tsbase.json", @@ -2261,7 +2271,7 @@ describe("unittests:: tsserver:: with project references and compile on save wit files: ["Source.ts"] }) }; - const buttonSource: ts.projectSystem.File = { + const buttonSource: File = { path: `${buttonClass}/Source.ts`, content: `module Hmi { export class Button { @@ -2271,8 +2281,8 @@ describe("unittests:: tsserver:: with project references and compile on save wit }` }; - const siblingClass = `${ts.tscWatch.projectRoot}/SiblingClass`; - const siblingConfig: ts.projectSystem.File = { + const siblingClass = `${projectRoot}/SiblingClass`; + const siblingConfig: File = { path: `${siblingClass}/tsconfig.json`, content: JSON.stringify({ extends: "../tsbase.json", @@ -2285,7 +2295,7 @@ describe("unittests:: tsserver:: with project references and compile on save wit files: ["Source.ts"] }) }; - const siblingSource: ts.projectSystem.File = { + const siblingSource: File = { path: `${siblingClass}/Source.ts`, content: `module Hmi { export class Sibling { @@ -2294,18 +2304,18 @@ describe("unittests:: tsserver:: with project references and compile on save wit } }` }; - const host = ts.projectSystem.createServerHost([ts.projectSystem.libFile, tsbaseJson, buttonConfig, buttonSource, siblingConfig, siblingSource], { useCaseSensitiveFileNames: true }); + const host = createServerHost([libFile, tsbaseJson, buttonConfig, buttonSource, siblingConfig, siblingSource], { useCaseSensitiveFileNames: true }); // ts build should succeed - ts.tscWatch.ensureErrorFreeBuild(host, [siblingConfig.path]); - const sourceJs = ts.changeExtension(siblingSource.path, ".js"); + ensureErrorFreeBuild(host, [siblingConfig.path]); + const sourceJs = changeExtension(siblingSource.path, ".js"); const expectedSiblingJs = host.readFile(sourceJs); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([siblingSource], session); + const session = createSession(host); + openFilesForSession([siblingSource], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompileOnSaveEmitFile, + session.executeCommandSeq({ + command: CommandTypes.CompileOnSaveEmitFile, arguments: { file: siblingSource.path, projectFileName: siblingConfig.path diff --git a/src/testRunner/unittests/tsserver/projectReferenceErrors.ts b/src/testRunner/unittests/tsserver/projectReferenceErrors.ts index 3d9b401b3e8ac..0d6facbe2044a 100644 --- a/src/testRunner/unittests/tsserver/projectReferenceErrors.ts +++ b/src/testRunner/unittests/tsserver/projectReferenceErrors.ts @@ -1,20 +1,21 @@ -import * as ts from "../../_namespaces/ts"; +import { projectRoot } from "../tscWatch/helpers"; +import { File, GetErrForProjectDiagnostics, verifyGetErrScenario } from "./helpers"; describe("unittests:: tsserver:: with project references and error reporting", () => { - const dependecyLocation = `${ts.tscWatch.projectRoot}/dependency`; - const usageLocation = `${ts.tscWatch.projectRoot}/usage`; + const dependecyLocation = `${projectRoot}/dependency`; + const usageLocation = `${projectRoot}/usage`; - function verifyUsageAndDependency(scenario: string, dependencyTs: ts.projectSystem.File, dependencyConfig: ts.projectSystem.File, usageTs: ts.projectSystem.File, usageConfig: ts.projectSystem.File) { - function usageProjectDiagnostics(): ts.projectSystem.GetErrForProjectDiagnostics { + function verifyUsageAndDependency(scenario: string, dependencyTs: File, dependencyConfig: File, usageTs: File, usageConfig: File) { + function usageProjectDiagnostics(): GetErrForProjectDiagnostics { return { project: usageTs, files: [usageTs, dependencyTs] }; } - function dependencyProjectDiagnostics(): ts.projectSystem.GetErrForProjectDiagnostics { + function dependencyProjectDiagnostics(): GetErrForProjectDiagnostics { return { project: dependencyTs, files: [dependencyTs] }; } describe("when dependency project is not open", () => { - ts.projectSystem.verifyGetErrScenario({ + verifyGetErrScenario({ scenario: "projectReferenceErrors", subScenario: `${scenario} when dependency project is not open`, allFiles: () => [dependencyTs, dependencyConfig, usageTs, usageConfig], @@ -39,7 +40,7 @@ describe("unittests:: tsserver:: with project references and error reporting", ( }); describe("when the depedency file is open", () => { - ts.projectSystem.verifyGetErrScenario({ + verifyGetErrScenario({ scenario: "projectReferenceErrors", subScenario: `${scenario} when the depedency file is open`, allFiles: () => [dependencyTs, dependencyConfig, usageTs, usageConfig], @@ -63,7 +64,7 @@ describe("unittests:: tsserver:: with project references and error reporting", ( } describe("with module scenario", () => { - const dependencyTs: ts.projectSystem.File = { + const dependencyTs: File = { path: `${dependecyLocation}/fns.ts`, content: `export function fn1() { } export function fn2() { } @@ -72,11 +73,11 @@ export function fn2() { } // Error in dependency ts file export let x: string = 10;` }; - const dependencyConfig: ts.projectSystem.File = { + const dependencyConfig: File = { path: `${dependecyLocation}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, declarationDir: "../decls" } }) }; - const usageTs: ts.projectSystem.File = { + const usageTs: File = { path: `${usageLocation}/usage.ts`, content: `import { fn1, @@ -88,7 +89,7 @@ fn2(); fnErr(); ` }; - const usageConfig: ts.projectSystem.File = { + const usageConfig: File = { path: `${usageLocation}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true }, @@ -99,7 +100,7 @@ fnErr(); }); describe("with non module --out", () => { - const dependencyTs: ts.projectSystem.File = { + const dependencyTs: File = { path: `${dependecyLocation}/fns.ts`, content: `function fn1() { } function fn2() { } @@ -108,18 +109,18 @@ function fn2() { } // Error in dependency ts file let x: string = 10;` }; - const dependencyConfig: ts.projectSystem.File = { + const dependencyConfig: File = { path: `${dependecyLocation}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, outFile: "../dependency.js" } }) }; - const usageTs: ts.projectSystem.File = { + const usageTs: File = { path: `${usageLocation}/usage.ts`, content: `fn1(); fn2(); fnErr(); ` }; - const usageConfig: ts.projectSystem.File = { + const usageConfig: File = { path: `${usageLocation}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, outFile: "../usage.js" }, diff --git a/src/testRunner/unittests/tsserver/projectReferences.ts b/src/testRunner/unittests/tsserver/projectReferences.ts index bbe550b802e6e..098ccbedbac66 100644 --- a/src/testRunner/unittests/tsserver/projectReferences.ts +++ b/src/testRunner/unittests/tsserver/projectReferences.ts @@ -1,18 +1,34 @@ -import * as ts from "../../_namespaces/ts"; - -export function createHostWithSolutionBuild(files: readonly ts.TestFSWithWatch.FileOrFolderOrSymLink[], rootNames: readonly string[]) { - const host = ts.projectSystem.createServerHost(files); +import { emptyArray, endsWith } from "../../../compiler/core"; +import { Diagnostics } from "../../../compiler/diagnosticInformationMap.generated"; +import { CompilerOptions, Path } from "../../../compiler/types"; +import { + FileOrFolderOrSymLink, getTsBuildProjectFile, getTsBuildProjectFilePath, +} from "../../../harness/virtualFileSystemWithWatch"; +import { + CodeFixRequest, CommandTypes, CompilerOptionsDiagnosticsRequest, FileRequestArgs, ReferencesRequest, + ReferencesResponseBody, RenameRequest, SemanticDiagnosticsSyncRequest, SyntacticDiagnosticsSyncRequest, + UpdateOpenRequest, +} from "../../../server/protocol"; +import { ensureErrorFreeBuild, projectRoot, solutionBuildWithBaseline } from "../tscWatch/helpers"; +import { + baselineTsserverLogs, checkProjectActualFiles, createLoggerWithInMemoryLogs, createProjectService, createServerHost, + createSession, File, libFile, makeReferenceItem, openFilesForSession, protocolFileLocationFromSubstring, + protocolLocationFromSubstring, SymLink, verifyGetErrRequest, +} from "./helpers"; + +export function createHostWithSolutionBuild(files: readonly FileOrFolderOrSymLink[], rootNames: readonly string[]) { + const host = createServerHost(files); // ts build should succeed - ts.tscWatch.ensureErrorFreeBuild(host, rootNames); + ensureErrorFreeBuild(host, rootNames); return host; } describe("unittests:: tsserver:: with project references and tsbuild", () => { describe("with container project", () => { - function getProjectFiles(project: string): [ts.projectSystem.File, ts.projectSystem.File] { + function getProjectFiles(project: string): [File, File] { return [ - ts.TestFSWithWatch.getTsBuildProjectFile(project, "tsconfig.json"), - ts.TestFSWithWatch.getTsBuildProjectFile(project, "index.ts"), + getTsBuildProjectFile(project, "tsconfig.json"), + getTsBuildProjectFile(project, "index.ts"), ]; } @@ -20,72 +36,72 @@ describe("unittests:: tsserver:: with project references and tsbuild", () => { const containerLib = getProjectFiles("container/lib"); const containerExec = getProjectFiles("container/exec"); const containerCompositeExec = getProjectFiles("container/compositeExec"); - const containerConfig = ts.TestFSWithWatch.getTsBuildProjectFile(project, "tsconfig.json"); - const files = [ts.projectSystem.libFile, ...containerLib, ...containerExec, ...containerCompositeExec, containerConfig]; + const containerConfig = getTsBuildProjectFile(project, "tsconfig.json"); + const files = [libFile, ...containerLib, ...containerExec, ...containerCompositeExec, containerConfig]; it("does not error on container only project", () => { const host = createHostWithSolutionBuild(files, [containerConfig.path]); // Open external project for the folder - const session = ts.projectSystem.createSession(host, { logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); + const session = createSession(host, { logger: createLoggerWithInMemoryLogs() }); const service = session.getProjectService(); service.openExternalProjects([{ - projectFileName: ts.TestFSWithWatch.getTsBuildProjectFilePath(project, project), + projectFileName: getTsBuildProjectFilePath(project, project), rootFiles: files.map(f => ({ fileName: f.path })), options: {} }]); files.forEach(f => { - const args: ts.projectSystem.protocol.FileRequestArgs = { + const args: FileRequestArgs = { file: f.path, - projectFileName: ts.endsWith(f.path, "tsconfig.json") ? f.path : undefined + projectFileName: endsWith(f.path, "tsconfig.json") ? f.path : undefined }; - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.SyntacticDiagnosticsSync, + session.executeCommandSeq({ + command: CommandTypes.SyntacticDiagnosticsSync, arguments: args }); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.SemanticDiagnosticsSync, + session.executeCommandSeq({ + command: CommandTypes.SemanticDiagnosticsSync, arguments: args }); }); const containerProject = service.configuredProjects.get(containerConfig.path)!; - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.CompilerOptionsDiagnosticsFull, + session.executeCommandSeq({ + command: CommandTypes.CompilerOptionsDiagnosticsFull, arguments: { projectFileName: containerProject.projectName } }); - ts.projectSystem.baselineTsserverLogs("projectReferences", `does not error on container only project`, session); + baselineTsserverLogs("projectReferences", `does not error on container only project`, session); }); it("can successfully find references with --out options", () => { const host = createHostWithSolutionBuild(files, [containerConfig.path]); - const session = ts.projectSystem.createSession(host, { logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([containerCompositeExec[1]], session); - const myConstStart = ts.projectSystem.protocolLocationFromSubstring(containerCompositeExec[1].content, "myConst"); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Rename, + const session = createSession(host, { logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([containerCompositeExec[1]], session); + const myConstStart = protocolLocationFromSubstring(containerCompositeExec[1].content, "myConst"); + session.executeCommandSeq({ + command: CommandTypes.Rename, arguments: { file: containerCompositeExec[1].path, ...myConstStart } }); - ts.projectSystem.baselineTsserverLogs("projectReferences", `can successfully find references with out option`, session); + baselineTsserverLogs("projectReferences", `can successfully find references with out option`, session); }); it("ancestor and project ref management", () => { - const tempFile: ts.projectSystem.File = { + const tempFile: File = { path: `/user/username/projects/temp/temp.ts`, content: "let x = 10" }; const host = createHostWithSolutionBuild(files.concat([tempFile]), [containerConfig.path]); - const session = ts.projectSystem.createSession(host, { logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([containerCompositeExec[1]], session); + const session = createSession(host, { logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([containerCompositeExec[1]], session); const service = session.getProjectService(); // Open temp file and verify all projects alive - ts.projectSystem.openFilesForSession([tempFile], session); + openFilesForSession([tempFile], session); // Ref projects are loaded after as part of this command - const locationOfMyConst = ts.projectSystem.protocolLocationFromSubstring(containerCompositeExec[1].content, "myConst"); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Rename, + const locationOfMyConst = protocolLocationFromSubstring(containerCompositeExec[1].content, "myConst"); + session.executeCommandSeq({ + command: CommandTypes.Rename, arguments: { file: containerCompositeExec[1].path, ...locationOfMyConst @@ -94,20 +110,20 @@ describe("unittests:: tsserver:: with project references and tsbuild", () => { // Open temp file and verify all projects alive service.closeClientFile(tempFile.path); - ts.projectSystem.openFilesForSession([tempFile], session); + openFilesForSession([tempFile], session); // Close all files and open temp file, only inferred project should be alive service.closeClientFile(containerCompositeExec[1].path); service.closeClientFile(tempFile.path); - ts.projectSystem.openFilesForSession([tempFile], session); - ts.projectSystem.baselineTsserverLogs("projectReferences", `ancestor and project ref management`, session); + openFilesForSession([tempFile], session); + baselineTsserverLogs("projectReferences", `ancestor and project ref management`, session); }); }); describe("when root file is file from referenced project", () => { function verify(disableSourceOfProjectReferenceRedirect: boolean) { const projectLocation = `/user/username/projects/project`; - const commonConfig: ts.projectSystem.File = { + const commonConfig: File = { path: `${projectLocation}/src/common/tsconfig.json`, content: JSON.stringify({ compilerOptions: { @@ -120,12 +136,12 @@ describe("unittests:: tsserver:: with project references and tsbuild", () => { include: ["./**/*"] }) }; - const keyboardTs: ts.projectSystem.File = { + const keyboardTs: File = { path: `${projectLocation}/src/common/input/keyboard.ts`, content: `function bar() { return "just a random function so .d.ts location doesnt match"; } export function evaluateKeyboardEvent() { }` }; - const keyboardTestTs: ts.projectSystem.File = { + const keyboardTestTs: File = { path: `${projectLocation}/src/common/input/keyboard.test.ts`, content: `import { evaluateKeyboardEvent } from 'common/input/keyboard'; function testEvaluateKeyboardEvent() { @@ -133,7 +149,7 @@ function testEvaluateKeyboardEvent() { } ` }; - const srcConfig: ts.projectSystem.File = { + const srcConfig: File = { path: `${projectLocation}/src/tsconfig.json`, content: JSON.stringify({ compilerOptions: { @@ -153,7 +169,7 @@ function testEvaluateKeyboardEvent() { ] }) }; - const terminalTs: ts.projectSystem.File = { + const terminalTs: File = { path: `${projectLocation}/src/terminal.ts`, content: `import { evaluateKeyboardEvent } from 'common/input/keyboard'; function foo() { @@ -162,28 +178,28 @@ function foo() { ` }; const host = createHostWithSolutionBuild( - [commonConfig, keyboardTs, keyboardTestTs, srcConfig, terminalTs, ts.projectSystem.libFile], + [commonConfig, keyboardTs, keyboardTestTs, srcConfig, terminalTs, libFile], [srcConfig.path] ); - const session = ts.projectSystem.createSession(host, { logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([keyboardTs, terminalTs], session); + const session = createSession(host, { logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([keyboardTs, terminalTs], session); const searchStr = "evaluateKeyboardEvent"; const importStr = `import { evaluateKeyboardEvent } from 'common/input/keyboard';`; - const result = session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.References, - arguments: ts.projectSystem.protocolFileLocationFromSubstring(keyboardTs, searchStr) - }).response as ts.projectSystem.protocol.ReferencesResponseBody; + const result = session.executeCommandSeq({ + command: CommandTypes.References, + arguments: protocolFileLocationFromSubstring(keyboardTs, searchStr) + }).response as ReferencesResponseBody; assert.deepEqual(result, { refs: [ - ts.projectSystem.makeReferenceItem({ + makeReferenceItem({ file: keyboardTs, text: searchStr, contextText: `export function evaluateKeyboardEvent() { }`, isDefinition: true, lineText: `export function evaluateKeyboardEvent() { }` }), - ts.projectSystem.makeReferenceItem({ + makeReferenceItem({ file: keyboardTestTs, text: searchStr, contextText: importStr, @@ -191,14 +207,14 @@ function foo() { isWriteAccess: true, lineText: importStr }), - ts.projectSystem.makeReferenceItem({ + makeReferenceItem({ file: keyboardTestTs, text: searchStr, options: { index: 1 }, isDefinition: false, lineText: ` return evaluateKeyboardEvent();` }), - ts.projectSystem.makeReferenceItem({ + makeReferenceItem({ file: terminalTs, text: searchStr, contextText: importStr, @@ -206,7 +222,7 @@ function foo() { isWriteAccess: true, lineText: importStr }), - ts.projectSystem.makeReferenceItem({ + makeReferenceItem({ file: terminalTs, text: searchStr, options: { index: 1 }, @@ -215,10 +231,10 @@ function foo() { }), ], symbolName: searchStr, - symbolStartOffset: ts.projectSystem.protocolLocationFromSubstring(keyboardTs.content, searchStr).offset, + symbolStartOffset: protocolLocationFromSubstring(keyboardTs.content, searchStr).offset, symbolDisplayString: "function evaluateKeyboardEvent(): void" }); - ts.projectSystem.baselineTsserverLogs("projectReferences", `root file is file from referenced project${disableSourceOfProjectReferenceRedirect ? " and using declaration maps" : ""}`, session); + baselineTsserverLogs("projectReferences", `root file is file from referenced project${disableSourceOfProjectReferenceRedirect ? " and using declaration maps" : ""}`, session); } it(`when using declaration file maps to navigate between projects`, () => { @@ -230,8 +246,8 @@ function foo() { }); it("reusing d.ts files from composite and non composite projects", () => { - const configA: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/compositea/tsconfig.json`, + const configA: File = { + path: `${projectRoot}/compositea/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, @@ -242,28 +258,28 @@ function foo() { } }) }; - const aTs: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/compositea/a.ts`, + const aTs: File = { + path: `${projectRoot}/compositea/a.ts`, content: `import { b } from "@ref/compositeb/b";` }; - const a2Ts: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/compositea/a2.ts`, + const a2Ts: File = { + path: `${projectRoot}/compositea/a2.ts`, content: `export const x = 10;` }; - const configB: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/compositeb/tsconfig.json`, + const configB: File = { + path: `${projectRoot}/compositeb/tsconfig.json`, content: configA.content }; - const bTs: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/compositeb/b.ts`, + const bTs: File = { + path: `${projectRoot}/compositeb/b.ts`, content: "export function b() {}" }; - const bDts: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/dist/compositeb/b.d.ts`, + const bDts: File = { + path: `${projectRoot}/dist/compositeb/b.d.ts`, content: "export declare function b(): void;" }; - const configC: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/compositec/tsconfig.json`, + const configC: File = { + path: `${projectRoot}/compositec/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, @@ -275,27 +291,27 @@ function foo() { references: [{ path: "../compositeb" }] }) }; - const cTs: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/compositec/c.ts`, + const cTs: File = { + path: `${projectRoot}/compositec/c.ts`, content: aTs.content }; - const files = [ts.projectSystem.libFile, aTs, a2Ts, configA, bDts, bTs, configB, cTs, configC]; - const host = ts.projectSystem.createServerHost(files); - const service = ts.projectSystem.createProjectService(host); + const files = [libFile, aTs, a2Ts, configA, bDts, bTs, configB, cTs, configC]; + const host = createServerHost(files); + const service = createProjectService(host); service.openClientFile(aTs.path); service.checkNumberOfProjects({ configuredProjects: 1 }); // project A referencing b.d.ts without project reference const projectA = service.configuredProjects.get(configA.path)!; assert.isDefined(projectA); - ts.projectSystem.checkProjectActualFiles(projectA, [aTs.path, a2Ts.path, bDts.path, ts.projectSystem.libFile.path, configA.path]); + checkProjectActualFiles(projectA, [aTs.path, a2Ts.path, bDts.path, libFile.path, configA.path]); // reuses b.d.ts but sets the path and resolved path since projectC has project references // as the real resolution was to b.ts service.openClientFile(cTs.path); service.checkNumberOfProjects({ configuredProjects: 2 }); const projectC = service.configuredProjects.get(configC.path)!; - ts.projectSystem.checkProjectActualFiles(projectC, [cTs.path, bTs.path, ts.projectSystem.libFile.path, configC.path]); + checkProjectActualFiles(projectC, [cTs.path, bTs.path, libFile.path, configC.path]); // Now new project for project A tries to reuse b but there is no filesByName mapping for b's source location host.writeFile(a2Ts.path, `${a2Ts.content}export const y = 30;`); @@ -305,11 +321,11 @@ function foo() { describe("when references are monorepo like with symlinks", () => { interface Packages { - bPackageJson: ts.projectSystem.File; - aTest: ts.projectSystem.File; - bFoo: ts.projectSystem.File; - bBar: ts.projectSystem.File; - bSymlink: ts.projectSystem.SymLink; + bPackageJson: File; + aTest: File; + bFoo: File; + bBar: File; + bSymlink: SymLink; } function verifySymlinkScenario(scenario: string, packages: () => Packages) { describe(`${scenario}: when solution is not built`, () => { @@ -333,20 +349,20 @@ function foo() { }); } - function verifySession(scenario: string, { bPackageJson, aTest, bFoo, bBar, bSymlink }: Packages, alreadyBuilt: boolean, extraOptions: ts.CompilerOptions) { + function verifySession(scenario: string, { bPackageJson, aTest, bFoo, bBar, bSymlink }: Packages, alreadyBuilt: boolean, extraOptions: CompilerOptions) { const aConfig = config("A", extraOptions, ["../B"]); const bConfig = config("B", extraOptions); - const files = [ts.projectSystem.libFile, bPackageJson, aConfig, bConfig, aTest, bFoo, bBar, bSymlink]; + const files = [libFile, bPackageJson, aConfig, bConfig, aTest, bFoo, bBar, bSymlink]; const host = alreadyBuilt ? createHostWithSolutionBuild(files, [aConfig.path]) : - ts.projectSystem.createServerHost(files); + createServerHost(files); // Create symlink in node module - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([aTest], session); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [aTest] }); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.UpdateOpen, + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([aTest], session); + verifyGetErrRequest({ session, host, files: [aTest] }); + session.executeCommandSeq({ + command: CommandTypes.UpdateOpen, arguments: { changedFiles: [{ fileName: aTest.path, @@ -358,13 +374,13 @@ function foo() { }] } }); - ts.projectSystem.verifyGetErrRequest({ session, host, files: [aTest] }); - ts.projectSystem.baselineTsserverLogs("projectReferences", `monorepo like with symlinks ${scenario} and solution is ${alreadyBuilt ? "built" : "not built"}${extraOptions.preserveSymlinks ? " with preserveSymlinks" : ""}`, session); + verifyGetErrRequest({ session, host, files: [aTest] }); + baselineTsserverLogs("projectReferences", `monorepo like with symlinks ${scenario} and solution is ${alreadyBuilt ? "built" : "not built"}${extraOptions.preserveSymlinks ? " with preserveSymlinks" : ""}`, session); } - function config(packageName: string, extraOptions: ts.CompilerOptions, references?: string[]): ts.projectSystem.File { + function config(packageName: string, extraOptions: CompilerOptions, references?: string[]): File { return { - path: `${ts.tscWatch.projectRoot}/packages/${packageName}/tsconfig.json`, + path: `${projectRoot}/packages/${packageName}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { outDir: "lib", @@ -378,9 +394,9 @@ function foo() { }; } - function file(packageName: string, fileName: string, content: string): ts.projectSystem.File { + function file(packageName: string, fileName: string, content: string): File { return { - path: `${ts.tscWatch.projectRoot}/packages/${packageName}/src/${fileName}`, + path: `${projectRoot}/packages/${packageName}/src/${fileName}`, content }; } @@ -388,7 +404,7 @@ function foo() { function verifyMonoRepoLike(scope = "") { verifySymlinkScenario(`when packageJson has types field and has index.ts${scope ? " with scoped package" : ""}`, () => ({ bPackageJson: { - path: `${ts.tscWatch.projectRoot}/packages/B/package.json`, + path: `${projectRoot}/packages/B/package.json`, content: JSON.stringify({ main: "lib/index.js", types: "lib/index.d.ts" @@ -402,14 +418,14 @@ bar(); bFoo: file("B", "index.ts", `export function foo() { }`), bBar: file("B", "bar.ts", `export function bar() { }`), bSymlink: { - path: `${ts.tscWatch.projectRoot}/node_modules/${scope}b`, - symLink: `${ts.tscWatch.projectRoot}/packages/B` + path: `${projectRoot}/node_modules/${scope}b`, + symLink: `${projectRoot}/packages/B` } })); verifySymlinkScenario(`when referencing file from subFolder${scope ? " with scoped package" : ""}`, () => ({ bPackageJson: { - path: `${ts.tscWatch.projectRoot}/packages/B/package.json`, + path: `${projectRoot}/packages/B/package.json`, content: "{}" }, aTest: file("A", "test.ts", `import { foo } from '${scope}b/lib/foo'; @@ -420,8 +436,8 @@ bar(); bFoo: file("B", "foo.ts", `export function foo() { }`), bBar: file("B", "bar/foo.ts", `export function bar() { }`), bSymlink: { - path: `${ts.tscWatch.projectRoot}/node_modules/${scope}b`, - symLink: `${ts.tscWatch.projectRoot}/packages/B` + path: `${projectRoot}/node_modules/${scope}b`, + symLink: `${projectRoot}/packages/B` } })); } @@ -435,8 +451,8 @@ bar(); }); it("when the referenced projects have allowJs and emitDeclarationOnly", () => { - const compositeConfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/packages/emit-composite/tsconfig.json`, + const compositeConfig: File = { + path: `${projectRoot}/packages/emit-composite/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, @@ -448,8 +464,8 @@ bar(); include: ["src"] }) }; - const compositePackageJson: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/packages/emit-composite/package.json`, + const compositePackageJson: File = { + path: `${projectRoot}/packages/emit-composite/package.json`, content: JSON.stringify({ name: "emit-composite", version: "1.0.0", @@ -457,15 +473,15 @@ bar(); typings: "lib/index.d.ts" }) }; - const compositeIndex: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/packages/emit-composite/src/index.js`, + const compositeIndex: File = { + path: `${projectRoot}/packages/emit-composite/src/index.js`, content: `const testModule = require('./testModule'); module.exports = { ...testModule }` }; - const compositeTestModule: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/packages/emit-composite/src/testModule.js`, + const compositeTestModule: File = { + path: `${projectRoot}/packages/emit-composite/src/testModule.js`, content: `/** * @param {string} arg */ @@ -475,33 +491,33 @@ module.exports = { testCompositeFunction }` }; - const consumerConfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/packages/consumer/tsconfig.json`, + const consumerConfig: File = { + path: `${projectRoot}/packages/consumer/tsconfig.json`, content: JSON.stringify({ include: ["src"], references: [{ path: "../emit-composite" }] }) }; - const consumerIndex: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/packages/consumer/src/index.ts`, + const consumerIndex: File = { + path: `${projectRoot}/packages/consumer/src/index.ts`, content: `import { testCompositeFunction } from 'emit-composite'; testCompositeFunction('why hello there'); testCompositeFunction('why hello there', 42);` }; - const symlink: ts.projectSystem.SymLink = { - path: `${ts.tscWatch.projectRoot}/node_modules/emit-composite`, - symLink: `${ts.tscWatch.projectRoot}/packages/emit-composite` + const symlink: SymLink = { + path: `${projectRoot}/node_modules/emit-composite`, + symLink: `${projectRoot}/packages/emit-composite` }; - const host = ts.projectSystem.createServerHost([ts.projectSystem.libFile, compositeConfig, compositePackageJson, compositeIndex, compositeTestModule, consumerConfig, consumerIndex, symlink], { useCaseSensitiveFileNames: true }); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([consumerIndex], session); - ts.projectSystem.verifyGetErrRequest({ host, session, files: [consumerIndex] }); - ts.projectSystem.baselineTsserverLogs("projectReferences", `when the referenced projects have allowJs and emitDeclarationOnly`, session); + const host = createServerHost([libFile, compositeConfig, compositePackageJson, compositeIndex, compositeTestModule, consumerConfig, consumerIndex, symlink], { useCaseSensitiveFileNames: true }); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([consumerIndex], session); + verifyGetErrRequest({ host, session, files: [consumerIndex] }); + baselineTsserverLogs("projectReferences", `when the referenced projects have allowJs and emitDeclarationOnly`, session); }); it("when finding local reference doesnt load ancestor/sibling projects", () => { const solutionLocation = "/user/username/projects/solution"; - const solution: ts.projectSystem.File = { + const solution: File = { path: `${solutionLocation}/tsconfig.json`, content: JSON.stringify({ files: [], @@ -512,7 +528,7 @@ testCompositeFunction('why hello there', 42);` ] }) }; - const compilerConfig: ts.projectSystem.File = { + const compilerConfig: File = { path: `${solutionLocation}/compiler/tsconfig.json`, content: JSON.stringify({ compilerOptions: { @@ -522,7 +538,7 @@ testCompositeFunction('why hello there', 42);` files: ["./types.ts", "./program.ts"] }) }; - const typesFile: ts.projectSystem.File = { + const typesFile: File = { path: `${solutionLocation}/compiler/types.ts`, content: ` namespace ts { @@ -531,7 +547,7 @@ testCompositeFunction('why hello there', 42);` } }` }; - const programFile: ts.projectSystem.File = { + const programFile: File = { path: `${solutionLocation}/compiler/program.ts`, content: ` namespace ts { @@ -541,7 +557,7 @@ testCompositeFunction('why hello there', 42);` function getSourceFile() { return "something"; } }` }; - const servicesConfig: ts.projectSystem.File = { + const servicesConfig: File = { path: `${solutionLocation}/services/tsconfig.json`, content: JSON.stringify({ compilerOptions: { @@ -553,7 +569,7 @@ testCompositeFunction('why hello there', 42);` ] }) }; - const servicesFile: ts.projectSystem.File = { + const servicesFile: File = { path: `${solutionLocation}/services/services.ts`, content: ` namespace ts { @@ -561,32 +577,32 @@ testCompositeFunction('why hello there', 42);` }` }; - const files = [ts.projectSystem.libFile, solution, compilerConfig, typesFile, programFile, servicesConfig, servicesFile, ts.projectSystem.libFile]; - const host = ts.projectSystem.createServerHost(files); - const session = ts.projectSystem.createSession(host, { logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([programFile], session); + const files = [libFile, solution, compilerConfig, typesFile, programFile, servicesConfig, servicesFile, libFile]; + const host = createServerHost(files); + const session = createSession(host, { logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([programFile], session); // Find all references for getSourceFile // Shouldnt load more projects - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.References, - arguments: ts.projectSystem.protocolFileLocationFromSubstring(programFile, "getSourceFile", { index: 1 }) + session.executeCommandSeq({ + command: CommandTypes.References, + arguments: protocolFileLocationFromSubstring(programFile, "getSourceFile", { index: 1 }) }); // Find all references for getSourceFiles // Should load more projects - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.References, - arguments: ts.projectSystem.protocolFileLocationFromSubstring(programFile, "getSourceFiles") + session.executeCommandSeq({ + command: CommandTypes.References, + arguments: protocolFileLocationFromSubstring(programFile, "getSourceFiles") }); - ts.projectSystem.baselineTsserverLogs("projectReferences", `finding local reference doesnt load ancestor/sibling projects`, session); + baselineTsserverLogs("projectReferences", `finding local reference doesnt load ancestor/sibling projects`, session); }); describe("special handling of localness of the definitions for findAllRefs", () => { function verify(scenario: string, definition: string, usage: string, referenceTerm: string) { it(scenario, () => { const solutionLocation = "/user/username/projects/solution"; - const solution: ts.projectSystem.File = { + const solution: File = { path: `${solutionLocation}/tsconfig.json`, content: JSON.stringify({ files: [], @@ -596,7 +612,7 @@ testCompositeFunction('why hello there', 42);` ] }) }; - const apiConfig: ts.projectSystem.File = { + const apiConfig: File = { path: `${solutionLocation}/api/tsconfig.json`, content: JSON.stringify({ compilerOptions: { @@ -608,20 +624,20 @@ testCompositeFunction('why hello there', 42);` references: [{ path: "../shared" }] }) }; - const apiFile: ts.projectSystem.File = { + const apiFile: File = { path: `${solutionLocation}/api/src/server.ts`, content: `import * as shared from "../../shared/dist"; ${usage}` }; - const appConfig: ts.projectSystem.File = { + const appConfig: File = { path: `${solutionLocation}/app/tsconfig.json`, content: apiConfig.content }; - const appFile: ts.projectSystem.File = { + const appFile: File = { path: `${solutionLocation}/app/src/app.ts`, content: apiFile.content }; - const sharedConfig: ts.projectSystem.File = { + const sharedConfig: File = { path: `${solutionLocation}/shared/tsconfig.json`, content: JSON.stringify({ compilerOptions: { @@ -632,21 +648,21 @@ ${usage}` include: ["src"] }) }; - const sharedFile: ts.projectSystem.File = { + const sharedFile: File = { path: `${solutionLocation}/shared/src/index.ts`, content: definition }; - const host = ts.projectSystem.createServerHost([ts.projectSystem.libFile, solution, ts.projectSystem.libFile, apiConfig, apiFile, appConfig, appFile, sharedConfig, sharedFile]); - const session = ts.projectSystem.createSession(host, { logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([apiFile], session); + const host = createServerHost([libFile, solution, libFile, apiConfig, apiFile, appConfig, appFile, sharedConfig, sharedFile]); + const session = createSession(host, { logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([apiFile], session); // Find all references - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.References, - arguments: ts.projectSystem.protocolFileLocationFromSubstring(apiFile, referenceTerm) + session.executeCommandSeq({ + command: CommandTypes.References, + arguments: protocolFileLocationFromSubstring(apiFile, referenceTerm) }); - ts.projectSystem.baselineTsserverLogs("projectReferences", `special handling of localness ${scenario}`, session); + baselineTsserverLogs("projectReferences", `special handling of localness ${scenario}`, session); }); } @@ -692,7 +708,7 @@ export const foo = local;`, it("when disableSolutionSearching is true, solution and siblings are not loaded", () => { const solutionLocation = "/user/username/projects/solution"; - const solution: ts.projectSystem.File = { + const solution: File = { path: `${solutionLocation}/tsconfig.json`, content: JSON.stringify({ files: [], @@ -703,7 +719,7 @@ export const foo = local;`, ] }) }; - const compilerConfig: ts.projectSystem.File = { + const compilerConfig: File = { path: `${solutionLocation}/compiler/tsconfig.json`, content: JSON.stringify({ compilerOptions: { @@ -714,7 +730,7 @@ export const foo = local;`, files: ["./types.ts", "./program.ts"] }) }; - const typesFile: ts.projectSystem.File = { + const typesFile: File = { path: `${solutionLocation}/compiler/types.ts`, content: ` namespace ts { @@ -723,7 +739,7 @@ export const foo = local;`, } }` }; - const programFile: ts.projectSystem.File = { + const programFile: File = { path: `${solutionLocation}/compiler/program.ts`, content: ` namespace ts { @@ -733,7 +749,7 @@ export const foo = local;`, function getSourceFile() { return "something"; } }` }; - const servicesConfig: ts.projectSystem.File = { + const servicesConfig: File = { path: `${solutionLocation}/services/tsconfig.json`, content: JSON.stringify({ compilerOptions: { @@ -745,7 +761,7 @@ export const foo = local;`, ] }) }; - const servicesFile: ts.projectSystem.File = { + const servicesFile: File = { path: `${solutionLocation}/services/services.ts`, content: ` namespace ts { @@ -753,75 +769,75 @@ export const foo = local;`, }` }; - const files = [ts.projectSystem.libFile, solution, compilerConfig, typesFile, programFile, servicesConfig, servicesFile, ts.projectSystem.libFile]; - const host = ts.projectSystem.createServerHost(files); - const session = ts.projectSystem.createSession(host, { logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([programFile], session); + const files = [libFile, solution, compilerConfig, typesFile, programFile, servicesConfig, servicesFile, libFile]; + const host = createServerHost(files); + const session = createSession(host, { logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([programFile], session); // Find all references // No new solutions/projects loaded - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.References, - arguments: ts.projectSystem.protocolFileLocationFromSubstring(programFile, "getSourceFiles") + session.executeCommandSeq({ + command: CommandTypes.References, + arguments: protocolFileLocationFromSubstring(programFile, "getSourceFiles") }); - ts.projectSystem.baselineTsserverLogs("projectReferences", `with disableSolutionSearching solution and siblings are not loaded`, session); + baselineTsserverLogs("projectReferences", `with disableSolutionSearching solution and siblings are not loaded`, session); }); describe("when default project is solution project", () => { interface Setup { scenario: string; - solutionOptions?: ts.CompilerOptions; + solutionOptions?: CompilerOptions; solutionFiles?: string[]; configRefs: string[]; - additionalFiles: readonly ts.projectSystem.File[]; + additionalFiles: readonly File[]; } - const main: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/src/main.ts`, + const main: File = { + path: `${projectRoot}/src/main.ts`, content: `import { foo } from 'helpers/functions'; export { foo };` }; - const helper: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/src/helpers/functions.ts`, + const helper: File = { + path: `${projectRoot}/src/helpers/functions.ts`, content: `export const foo = 1;` }; - const mainDts: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/target/src/main.d.ts`, + const mainDts: File = { + path: `${projectRoot}/target/src/main.d.ts`, content: `import { foo } from 'helpers/functions'; export { foo }; //# sourceMappingURL=main.d.ts.map` }; - const mainDtsMap: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/target/src/main.d.ts.map`, + const mainDtsMap: File = { + path: `${projectRoot}/target/src/main.d.ts.map`, content: `{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAExC,OAAO,EAAC,GAAG,EAAC,CAAC"}` }; - const helperDts: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/target/src/helpers/functions.d.ts`, + const helperDts: File = { + path: `${projectRoot}/target/src/helpers/functions.d.ts`, content: `export declare const foo = 1; //# sourceMappingURL=functions.d.ts.map` }; - const helperDtsMap: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/target/src/helpers/functions.d.ts.map`, + const helperDtsMap: File = { + path: `${projectRoot}/target/src/helpers/functions.d.ts.map`, content: `{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../../../src/helpers/functions.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,GAAG,IAAI,CAAC"}` }; - const tsconfigIndirect3: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/indirect3/tsconfig.json`, + const tsconfigIndirect3: File = { + path: `${projectRoot}/indirect3/tsconfig.json`, content: JSON.stringify({ compilerOptions: { baseUrl: "../target/src/" }, }) }; - const fileResolvingToMainDts: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/indirect3/main.ts`, + const fileResolvingToMainDts: File = { + path: `${projectRoot}/indirect3/main.ts`, content: `import { foo } from 'main'; foo; export function bar() {}` }; - const tsconfigSrcPath = `${ts.tscWatch.projectRoot}/tsconfig-src.json`; - const tsconfigPath = `${ts.tscWatch.projectRoot}/tsconfig.json`; + const tsconfigSrcPath = `${projectRoot}/tsconfig-src.json`; + const tsconfigPath = `${projectRoot}/tsconfig.json`; const dummyFilePath = "/dummy/dummy.ts"; function setup({ solutionFiles, solutionOptions, configRefs, additionalFiles }: Setup) { - const tsconfigSrc: ts.projectSystem.File = { + const tsconfigSrc: File = { path: tsconfigSrcPath, content: JSON.stringify({ compilerOptions: { @@ -832,7 +848,7 @@ export function bar() {}` include: ["./src/**/*"] }) }; - const tsconfig: ts.projectSystem.File = { + const tsconfig: File = { path: tsconfigPath, content: JSON.stringify({ ... (solutionOptions ? { compilerOptions: solutionOptions } : {}), @@ -840,17 +856,17 @@ export function bar() {}` files: solutionFiles || [] }) }; - const dummyFile: ts.projectSystem.File = { + const dummyFile: File = { path: dummyFilePath, content: "let a = 10;" }; - const host = ts.projectSystem.createServerHost([ + const host = createServerHost([ tsconfigSrc, tsconfig, main, helper, - ts.projectSystem.libFile, dummyFile, + libFile, dummyFile, mainDts, mainDtsMap, helperDts, helperDtsMap, tsconfigIndirect3, fileResolvingToMainDts, ...additionalFiles]); - const session = ts.projectSystem.createSession(host, { canUseEvents: true, logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); + const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs() }); const service = session.getProjectService(); service.openClientFile(main.path); return { session, service, host }; @@ -859,14 +875,14 @@ export function bar() {}` function verifySolutionScenario(input: Setup) { const { session, service, host } = setup(input); - const info = service.getScriptInfoForPath(main.path as ts.Path)!; + const info = service.getScriptInfoForPath(main.path as Path)!; session.logger.logs.push(""); session.logger.logs.push(`getDefaultProject for ${main.path}: ${info.getDefaultProject().projectName}`); session.logger.logs.push(`findDefaultConfiguredProject for ${main.path}: ${service.findDefaultConfiguredProject(info)!.projectName}`); session.logger.logs.push(""); // Verify errors - ts.projectSystem.verifyGetErrRequest({ session, host, files: [main] }); + verifyGetErrRequest({ session, host, files: [main] }); // Verify collection of script infos service.openClientFile(dummyFilePath); @@ -883,10 +899,10 @@ export function bar() {}` service.reloadProjects(); // Find all refs - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.References, - arguments: ts.projectSystem.protocolFileLocationFromSubstring(main, "foo", { index: 1 }) - }).response as ts.projectSystem.protocol.ReferencesResponseBody; + session.executeCommandSeq({ + command: CommandTypes.References, + arguments: protocolFileLocationFromSubstring(main, "foo", { index: 1 }) + }).response as ReferencesResponseBody; service.closeClientFile(main.path); service.closeClientFile(dummyFilePath); @@ -895,16 +911,16 @@ export function bar() {}` service.openClientFile(fileResolvingToMainDts.path); // Find all refs from dts include - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.References, - arguments: ts.projectSystem.protocolFileLocationFromSubstring(fileResolvingToMainDts, "foo") - }).response as ts.projectSystem.protocol.ReferencesResponseBody; - ts.projectSystem.baselineTsserverLogs("projectReferences", input.scenario, session); + session.executeCommandSeq({ + command: CommandTypes.References, + arguments: protocolFileLocationFromSubstring(fileResolvingToMainDts, "foo") + }).response as ReferencesResponseBody; + baselineTsserverLogs("projectReferences", input.scenario, session); } - function getIndirectProject(postfix: string, optionsToExtend?: ts.CompilerOptions) { - const tsconfigIndirect: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig-indirect${postfix}.json`, + function getIndirectProject(postfix: string, optionsToExtend?: CompilerOptions) { + const tsconfigIndirect: File = { + path: `${projectRoot}/tsconfig-indirect${postfix}.json`, content: JSON.stringify({ compilerOptions: { composite: true, @@ -916,8 +932,8 @@ export function bar() {}` references: [{ path: "./tsconfig-src.json" }] }) }; - const indirect: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/indirect${postfix}/main.ts`, + const indirect: File = { + path: `${projectRoot}/indirect${postfix}/main.ts`, content: fileResolvingToMainDts.content }; return { tsconfigIndirect, indirect }; @@ -926,7 +942,7 @@ export function bar() {}` function verifyDisableReferencedProjectLoad(input: Setup) { const { session, service } = setup(input); - const info = service.getScriptInfoForPath(main.path as ts.Path)!; + const info = service.getScriptInfoForPath(main.path as Path)!; session.logger.logs.push(""); session.logger.logs.push(`getDefaultProject for ${main.path}: ${info.getDefaultProject().projectName}`); session.logger.logs.push(`findDefaultConfiguredProject for ${main.path}: ${service.findDefaultConfiguredProject(info)?.projectName}`); @@ -943,14 +959,14 @@ export function bar() {}` // Verify Reload projects service.reloadProjects(); - ts.projectSystem.baselineTsserverLogs("projectReferences", input.scenario, session); + baselineTsserverLogs("projectReferences", input.scenario, session); } it("when project is directly referenced by solution", () => { verifySolutionScenario({ scenario: "project is directly referenced by solution", configRefs: ["./tsconfig-src.json"], - additionalFiles: ts.emptyArray, + additionalFiles: emptyArray, }); }); @@ -969,7 +985,7 @@ export function bar() {}` scenario: "disables looking into the child project if disableReferencedProjectLoad is set", solutionOptions: { disableReferencedProjectLoad: true }, configRefs: ["./tsconfig-src.json"], - additionalFiles: ts.emptyArray, + additionalFiles: emptyArray, }); }); @@ -994,8 +1010,8 @@ export function bar() {}` describe("when solution is project that contains its own files", () => { it("when the project found is not solution but references open file through project reference", () => { - const ownMain: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/own/main.ts`, + const ownMain: File = { + path: `${projectRoot}/own/main.ts`, content: fileResolvingToMainDts.content }; verifySolutionScenario({ @@ -1011,8 +1027,8 @@ export function bar() {}` }); it("when project is indirectly referenced by solution", () => { - const ownMain: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/own/main.ts`, + const ownMain: File = { + path: `${projectRoot}/own/main.ts`, content: `import { bar } from 'main'; bar;` }; @@ -1031,8 +1047,8 @@ bar;` }); it("disables looking into the child project if disableReferencedProjectLoad is set", () => { - const ownMain: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/own/main.ts`, + const ownMain: File = { + path: `${projectRoot}/own/main.ts`, content: fileResolvingToMainDts.content }; verifyDisableReferencedProjectLoad({ @@ -1049,8 +1065,8 @@ bar;` }); it("disables looking into the child project if disableReferencedProjectLoad is set in indirect project", () => { - const ownMain: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/own/main.ts`, + const ownMain: File = { + path: `${projectRoot}/own/main.ts`, content: `import { bar } from 'main'; bar;` }; @@ -1068,8 +1084,8 @@ bar;` }); it("disables looking into the child project if disableReferencedProjectLoad is set in first indirect project but not in another one", () => { - const ownMain: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/own/main.ts`, + const ownMain: File = { + path: `${projectRoot}/own/main.ts`, content: `import { bar } from 'main'; bar;` }; @@ -1090,9 +1106,9 @@ bar;` }); describe("when new file is added to the referenced project", () => { - function setup(extendOptionsProject2?: ts.CompilerOptions) { - const config1: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/projects/project1/tsconfig.json`, + function setup(extendOptionsProject2?: CompilerOptions) { + const config1: File = { + path: `${projectRoot}/projects/project1/tsconfig.json`, content: JSON.stringify({ compilerOptions: { module: "none", @@ -1101,16 +1117,16 @@ bar;` exclude: ["temp"] }) }; - const class1: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/projects/project1/class1.ts`, + const class1: File = { + path: `${projectRoot}/projects/project1/class1.ts`, content: `class class1 {}` }; - const class1Dts: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/projects/project1/class1.d.ts`, + const class1Dts: File = { + path: `${projectRoot}/projects/project1/class1.d.ts`, content: `declare class class1 {}` }; - const config2: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/projects/project2/tsconfig.json`, + const config2: File = { + path: `${projectRoot}/projects/project2/tsconfig.json`, content: JSON.stringify({ compilerOptions: { module: "none", @@ -1122,13 +1138,13 @@ bar;` ] }) }; - const class2: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/projects/project2/class2.ts`, + const class2: File = { + path: `${projectRoot}/projects/project2/class2.ts`, content: `class class2 {}` }; - const host = ts.projectSystem.createServerHost([config1, class1, class1Dts, config2, class2, ts.projectSystem.libFile]); - const session = ts.projectSystem.createSession(host, { logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([class2], session); + const host = createServerHost([config1, class1, class1Dts, config2, class2, libFile]); + const session = createSession(host, { logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([class2], session); return { host, session, class1 }; } @@ -1136,52 +1152,52 @@ bar;` const { host, session } = setup(); // Add new class to referenced project - const class3 = `${ts.tscWatch.projectRoot}/projects/project1/class3.ts`; + const class3 = `${projectRoot}/projects/project1/class3.ts`; host.writeFile(class3, `class class3 {}`); host.checkTimeoutQueueLengthAndRun(2); // Add excluded file to referenced project - host.ensureFileOrFolder({ path: `${ts.tscWatch.projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + host.ensureFileOrFolder({ path: `${projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); host.checkTimeoutQueueLengthAndRun(0); // Add output from new class to referenced project - const class3Dts = `${ts.tscWatch.projectRoot}/projects/project1/class3.d.ts`; + const class3Dts = `${projectRoot}/projects/project1/class3.d.ts`; host.writeFile(class3Dts, `declare class class3 {}`); host.checkTimeoutQueueLengthAndRun(0); - ts.projectSystem.baselineTsserverLogs("projectReferences", `new file is added to the referenced project when referenced project is not open`, session); + baselineTsserverLogs("projectReferences", `new file is added to the referenced project when referenced project is not open`, session); }); it("when referenced project is open", () => { const { host, session, class1 } = setup(); - ts.projectSystem.openFilesForSession([class1], session); + openFilesForSession([class1], session); // Add new class to referenced project - const class3 = `${ts.tscWatch.projectRoot}/projects/project1/class3.ts`; + const class3 = `${projectRoot}/projects/project1/class3.ts`; host.writeFile(class3, `class class3 {}`); host.checkTimeoutQueueLengthAndRun(3); // Add excluded file to referenced project - host.ensureFileOrFolder({ path: `${ts.tscWatch.projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + host.ensureFileOrFolder({ path: `${projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); host.checkTimeoutQueueLengthAndRun(0); // Add output from new class to referenced project - const class3Dts = `${ts.tscWatch.projectRoot}/projects/project1/class3.d.ts`; + const class3Dts = `${projectRoot}/projects/project1/class3.d.ts`; host.writeFile(class3Dts, `declare class class3 {}`); host.checkTimeoutQueueLengthAndRun(0); - ts.projectSystem.baselineTsserverLogs("projectReferences", `new file is added to the referenced project when referenced project is open`, session); + baselineTsserverLogs("projectReferences", `new file is added to the referenced project when referenced project is open`, session); }); it("when referenced project is not open with disableSourceOfProjectReferenceRedirect", () => { const { host, session } = setup({ disableSourceOfProjectReferenceRedirect: true }); // Add new class to referenced project - const class3 = `${ts.tscWatch.projectRoot}/projects/project1/class3.ts`; + const class3 = `${projectRoot}/projects/project1/class3.ts`; host.writeFile(class3, `class class3 {}`); host.checkTimeoutQueueLengthAndRun(2); // Add output of new class to referenced project - const class3Dts = `${ts.tscWatch.projectRoot}/projects/project1/class3.d.ts`; + const class3Dts = `${projectRoot}/projects/project1/class3.d.ts`; host.writeFile(class3Dts, `declare class class3 {}`); host.checkTimeoutQueueLengthAndRun(2); // Add excluded file to referenced project - host.ensureFileOrFolder({ path: `${ts.tscWatch.projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + host.ensureFileOrFolder({ path: `${projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); host.checkTimeoutQueueLengthAndRun(0); // Delete output from new class to referenced project host.deleteFile(class3Dts); @@ -1189,23 +1205,23 @@ bar;` // Write back output of new class to referenced project host.writeFile(class3Dts, `declare class class3 {}`); host.checkTimeoutQueueLengthAndRun(2); - ts.projectSystem.baselineTsserverLogs("projectReferences", `new file is added to the referenced project when referenced project is not open with disableSourceOfProjectReferenceRedirect`, session); + baselineTsserverLogs("projectReferences", `new file is added to the referenced project when referenced project is not open with disableSourceOfProjectReferenceRedirect`, session); }); it("when referenced project is open with disableSourceOfProjectReferenceRedirect", () => { const { host, session, class1 } = setup({ disableSourceOfProjectReferenceRedirect: true }); - ts.projectSystem.openFilesForSession([class1], session); + openFilesForSession([class1], session); // Add new class to referenced project - const class3 = `${ts.tscWatch.projectRoot}/projects/project1/class3.ts`; + const class3 = `${projectRoot}/projects/project1/class3.ts`; host.writeFile(class3, `class class3 {}`); host.checkTimeoutQueueLengthAndRun(3); // Add output of new class to referenced project - const class3Dts = `${ts.tscWatch.projectRoot}/projects/project1/class3.d.ts`; + const class3Dts = `${projectRoot}/projects/project1/class3.d.ts`; host.writeFile(class3Dts, `declare class class3 {}`); host.checkTimeoutQueueLengthAndRun(2); // Add excluded file to referenced project - host.ensureFileOrFolder({ path: `${ts.tscWatch.projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + host.ensureFileOrFolder({ path: `${projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); host.checkTimeoutQueueLengthAndRun(0); // Delete output from new class to referenced project host.deleteFile(class3Dts); @@ -1213,14 +1229,14 @@ bar;` // Write back output of new class to referenced project host.writeFile(class3Dts, `declare class class3 {}`); host.checkTimeoutQueueLengthAndRun(2); - ts.projectSystem.baselineTsserverLogs("projectReferences", `new file is added to the referenced project when referenced project is open with disableSourceOfProjectReferenceRedirect`, session); + baselineTsserverLogs("projectReferences", `new file is added to the referenced project when referenced project is open with disableSourceOfProjectReferenceRedirect`, session); }); }); describe("auto import with referenced project", () => { function verifyAutoImport(built: boolean, disableSourceOfProjectReferenceRedirect?: boolean) { - const solnConfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/tsconfig.json`, + const solnConfig: File = { + path: `${projectRoot}/tsconfig.json`, content: JSON.stringify({ files: [], references: [ @@ -1229,8 +1245,8 @@ bar;` ] }) }; - const sharedConfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/shared/src/library/tsconfig.json`, + const sharedConfig: File = { + path: `${projectRoot}/shared/src/library/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, @@ -1238,12 +1254,12 @@ bar;` } }) }; - const sharedIndex: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/shared/src/library/index.ts`, + const sharedIndex: File = { + path: `${projectRoot}/shared/src/library/index.ts`, content: `export function foo() {}` }; - const sharedPackage: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/shared/package.json`, + const sharedPackage: File = { + path: `${projectRoot}/shared/package.json`, content: JSON.stringify({ name: "shared", version: "1.0.0", @@ -1251,8 +1267,8 @@ bar;` types: "bld/library/index.d.ts" }) }; - const appConfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/app/src/program/tsconfig.json`, + const appConfig: File = { + path: `${projectRoot}/app/src/program/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, @@ -1264,38 +1280,38 @@ bar;` ] }) }; - const appBar: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/app/src/program/bar.ts`, + const appBar: File = { + path: `${projectRoot}/app/src/program/bar.ts`, content: `import {foo} from "shared";` }; - const appIndex: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/app/src/program/index.ts`, + const appIndex: File = { + path: `${projectRoot}/app/src/program/index.ts`, content: `foo` }; - const sharedSymlink: ts.projectSystem.SymLink = { - path: `${ts.tscWatch.projectRoot}/node_modules/shared`, - symLink: `${ts.tscWatch.projectRoot}/shared` + const sharedSymlink: SymLink = { + path: `${projectRoot}/node_modules/shared`, + symLink: `${projectRoot}/shared` }; - const files = [solnConfig, sharedConfig, sharedIndex, sharedPackage, appConfig, appBar, appIndex, sharedSymlink, ts.projectSystem.libFile]; - const host = ts.projectSystem.createServerHost(files); + const files = [solnConfig, sharedConfig, sharedIndex, sharedPackage, appConfig, appBar, appIndex, sharedSymlink, libFile]; + const host = createServerHost(files); if (built) { - ts.tscWatch.solutionBuildWithBaseline(host, [solnConfig.path]); + solutionBuildWithBaseline(host, [solnConfig.path]); host.clearOutput(); } - const session = ts.projectSystem.createSession(host, { logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([appIndex], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.GetCodeFixes, + const session = createSession(host, { logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([appIndex], session); + session.executeCommandSeq({ + command: CommandTypes.GetCodeFixes, arguments: { file: appIndex.path, startLine: 1, startOffset: 1, endLine: 1, endOffset: 4, - errorCodes: [ts.Diagnostics.Cannot_find_name_0.code], + errorCodes: [Diagnostics.Cannot_find_name_0.code], } }); - ts.projectSystem.baselineTsserverLogs("projectReferences", `auto import with referenced project${built ? " when built" : ""}${disableSourceOfProjectReferenceRedirect ? " with disableSourceOfProjectReferenceRedirect": ""}`, session); + baselineTsserverLogs("projectReferences", `auto import with referenced project${built ? " when built" : ""}${disableSourceOfProjectReferenceRedirect ? " with disableSourceOfProjectReferenceRedirect": ""}`, session); } it("when project is built", () => { @@ -1310,13 +1326,13 @@ bar;` }); it("when files from two projects are open and one project references", () => { - function getPackageAndFile(packageName: string, references?: string[], optionsToExtend?: ts.CompilerOptions): [file: ts.projectSystem.File, config: ts.projectSystem.File] { - const file: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/${packageName}/src/file1.ts`, + function getPackageAndFile(packageName: string, references?: string[], optionsToExtend?: CompilerOptions): [file: File, config: File] { + const file: File = { + path: `${projectRoot}/${packageName}/src/file1.ts`, content: `export const ${packageName}Const = 10;` }; - const config: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/${packageName}/tsconfig.json`, + const config: File = { + path: `${projectRoot}/${packageName}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, ...optionsToExtend || {} }, references: references?.map(path => ({ path: `../${path}` })) @@ -1337,35 +1353,35 @@ bar;` const [indirectNoCoreRefFile, indirectNoCoreRefConfig] = getPackageAndFile("indirectNoCoreRef", ["noCoreRef2"]); const [noCoreRef2File, noCoreRef2Config] = getPackageAndFile("noCoreRef2"); - const host = ts.projectSystem.createServerHost([ - ts.projectSystem.libFile, mainFile, mainConfig, coreFile, coreConfig, noCoreRef1File, noCoreRef1Config, + const host = createServerHost([ + libFile, mainFile, mainConfig, coreFile, coreConfig, noCoreRef1File, noCoreRef1Config, indirectFile, indirectConfig, coreRef1File, coreRef1Config, indirectDisabledChildLoad1File, indirectDisabledChildLoad1Config, coreRef2File, coreRef2Config, indirectDisabledChildLoad2File, indirectDisabledChildLoad2Config, coreRef3File, coreRef3Config, refToCoreRef3File, refToCoreRef3Config, indirectNoCoreRefFile, indirectNoCoreRefConfig, noCoreRef2File, noCoreRef2Config ], { useCaseSensitiveFileNames: true }); - const session = ts.projectSystem.createSession(host, { logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([mainFile, coreFile], session); + const session = createSession(host, { logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([mainFile, coreFile], session); // Find all refs in coreFile - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.References, - arguments: ts.projectSystem.protocolFileLocationFromSubstring(coreFile, `coreConst`) + session.executeCommandSeq({ + command: CommandTypes.References, + arguments: protocolFileLocationFromSubstring(coreFile, `coreConst`) }); - ts.projectSystem.baselineTsserverLogs("projectReferences", `when files from two projects are open and one project references`, session); + baselineTsserverLogs("projectReferences", `when files from two projects are open and one project references`, session); }); describe("find refs to decl in other proj", () => { - const indexA: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/a/index.ts`, + const indexA: File = { + path: `${projectRoot}/a/index.ts`, content: `import { B } from "../b/lib"; const b: B = new B();` }; - const configB: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/b/tsconfig.json`, + const configB: File = { + path: `${projectRoot}/b/tsconfig.json`, content: `{ "compilerOptions": { "declarationMap": true, @@ -1375,30 +1391,30 @@ const b: B = new B();` }` }; - const indexB: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/b/index.ts`, + const indexB: File = { + path: `${projectRoot}/b/index.ts`, content: `export class B { M() {} }` }; - const helperB: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/b/helper.ts`, + const helperB: File = { + path: `${projectRoot}/b/helper.ts`, content: `import { B } from "."; const b: B = new B();` }; - const dtsB: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/b/lib/index.d.ts`, + const dtsB: File = { + path: `${projectRoot}/b/lib/index.d.ts`, content: `export declare class B { M(): void; } //# sourceMappingURL=index.d.ts.map` }; - const dtsMapB: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/b/lib/index.d.ts.map`, + const dtsMapB: File = { + path: `${projectRoot}/b/lib/index.d.ts.map`, content: `{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,qBAAa,CAAC;IACV,CAAC;CACJ"}` }; @@ -1414,30 +1430,30 @@ const b: B = new B();` ` and refd proj loading is ${disableReferencedProjectLoad ? "disabled" : "enabled"}` + ` and proj ref redirects are ${disableSourceOfProjectReferenceRedirect ? "disabled" : "enabled"}` + ` and a decl map is ${dtsMapPresent ? "present" : "missing"}`; - const compilerOptions: ts.CompilerOptions = { + const compilerOptions: CompilerOptions = { disableReferencedProjectLoad, disableSourceOfProjectReferenceRedirect, composite: true }; it(subScenario, () => { - const configA: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/a/tsconfig.json`, + const configA: File = { + path: `${projectRoot}/a/tsconfig.json`, content: `{ "compilerOptions": ${JSON.stringify(compilerOptions)}, "references": [{ "path": "../b" }] }` }; - const host = ts.projectSystem.createServerHost([configA, indexA, configB, indexB, helperB, dtsB, ...(dtsMapPresent ? [dtsMapB] : [])]); - const session = ts.projectSystem.createSession(host, { logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([indexA, ...(projectAlreadyLoaded ? [helperB] : [])], session); + const host = createServerHost([configA, indexA, configB, indexB, helperB, dtsB, ...(dtsMapPresent ? [dtsMapB] : [])]); + const session = createSession(host, { logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([indexA, ...(projectAlreadyLoaded ? [helperB] : [])], session); - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.References, - arguments: ts.projectSystem.protocolFileLocationFromSubstring(indexA, `B`, { index: 1 }) + session.executeCommandSeq({ + command: CommandTypes.References, + arguments: protocolFileLocationFromSubstring(indexA, `B`, { index: 1 }) }); - ts.projectSystem.baselineTsserverLogs("projectReferences", `find refs to decl in other proj ${subScenario}`, session); + baselineTsserverLogs("projectReferences", `find refs to decl in other proj ${subScenario}`, session); }); } diff --git a/src/testRunner/unittests/tsserver/projectReferencesSourcemap.ts b/src/testRunner/unittests/tsserver/projectReferencesSourcemap.ts index 44e12759aaad0..55c68156684b3 100644 --- a/src/testRunner/unittests/tsserver/projectReferencesSourcemap.ts +++ b/src/testRunner/unittests/tsserver/projectReferencesSourcemap.ts @@ -1,10 +1,22 @@ -import * as ts from "../../_namespaces/ts"; +import { Path } from "../../../compiler/types"; +import { + ChangeRequest, CommandTypes, DefinitionAndBoundSpanRequest, DefinitionInfoAndBoundSpan, FileSpan, RenameInfoSuccess, + RenameRequest, RenameResponseBody, Request, TextSpan, TextSpanWithContext, +} from "../../../server/protocol"; +import { ScriptInfo } from "../../../server/scriptInfo"; +import { ScriptElementKind } from "../../../services/types"; +import { projectRoot } from "../tscWatch/helpers"; +import { + checkNumberOfProjects, checkProjectActualFiles, checkScriptInfos, checkWatchedFiles, closeFilesForSession, + createServerHost, createSession, File, libFile, openFilesForSession, TestServerHost, TestSession, +} from "./helpers"; +import { createHostWithSolutionBuild } from "./projectReferences"; describe("unittests:: tsserver:: with project references and tsbuild source map", () => { - const dependecyLocation = `${ts.tscWatch.projectRoot}/dependency`; - const dependecyDeclsLocation = `${ts.tscWatch.projectRoot}/decls`; - const mainLocation = `${ts.tscWatch.projectRoot}/main`; - const dependencyTs: ts.projectSystem.File = { + const dependecyLocation = `${projectRoot}/dependency`; + const dependecyDeclsLocation = `${projectRoot}/decls`; + const mainLocation = `${projectRoot}/main`; + const dependencyTs: File = { path: `${dependecyLocation}/FnS.ts`, content: `export function fn1() { } export function fn2() { } @@ -14,12 +26,12 @@ export function fn5() { } ` }; const dependencyTsPath = dependencyTs.path.toLowerCase(); - const dependencyConfig: ts.projectSystem.File = { + const dependencyConfig: File = { path: `${dependecyLocation}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, declarationMap: true, declarationDir: "../decls" } }) }; - const mainTs: ts.projectSystem.File = { + const mainTs: File = { path: `${mainLocation}/main.ts`, content: `import { fn1, @@ -36,7 +48,7 @@ fn4(); fn5(); ` }; - const mainConfig: ts.projectSystem.File = { + const mainConfig: File = { path: `${mainLocation}/tsconfig.json`, content: JSON.stringify({ compilerOptions: { composite: true, declarationMap: true }, @@ -44,22 +56,22 @@ fn5(); }) }; - const randomFile: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/random/random.ts`, + const randomFile: File = { + path: `${projectRoot}/random/random.ts`, content: "let a = 10;" }; - const randomConfig: ts.projectSystem.File = { - path: `${ts.tscWatch.projectRoot}/random/tsconfig.json`, + const randomConfig: File = { + path: `${projectRoot}/random/tsconfig.json`, content: "{}" }; const dtsLocation = `${dependecyDeclsLocation}/FnS.d.ts`; - const dtsPath = dtsLocation.toLowerCase() as ts.Path; + const dtsPath = dtsLocation.toLowerCase() as Path; const dtsMapLocation = `${dependecyDeclsLocation}/FnS.d.ts.map`; - const dtsMapPath = dtsMapLocation.toLowerCase() as ts.Path; + const dtsMapPath = dtsMapLocation.toLowerCase() as Path; - const files = [dependencyTs, dependencyConfig, mainTs, mainConfig, ts.projectSystem.libFile, randomFile, randomConfig]; + const files = [dependencyTs, dependencyConfig, mainTs, mainConfig, libFile, randomFile, randomConfig]; - function changeDtsFile(host: ts.projectSystem.TestServerHost) { + function changeDtsFile(host: TestServerHost) { host.writeFile( dtsLocation, host.readFile(dtsLocation)!.replace( @@ -70,23 +82,23 @@ fn5(); ); } - function changeDtsMapFile(host: ts.projectSystem.TestServerHost) { + function changeDtsMapFile(host: TestServerHost) { host.writeFile( dtsMapLocation, `{"version":3,"file":"FnS.d.ts","sourceRoot":"","sources":["../dependency/FnS.ts"],"names":[],"mappings":"AAAA,wBAAgB,GAAG,SAAM;AACzB,wBAAgB,GAAG,SAAM;AACzB,wBAAgB,GAAG,SAAM;AACzB,wBAAgB,GAAG,SAAM;AACzB,wBAAgB,GAAG,SAAM;AACzB,eAAO,MAAM,CAAC,KAAK,CAAC"}` ); } - function verifyScriptInfos(session: ts.projectSystem.TestSession, host: ts.projectSystem.TestServerHost, openInfos: readonly string[], closedInfos: readonly string[], otherWatchedFiles: readonly string[], additionalInfo?: string) { - ts.projectSystem.checkScriptInfos(session.getProjectService(), openInfos.concat(closedInfos), additionalInfo); - ts.projectSystem.checkWatchedFiles(host, closedInfos.concat(otherWatchedFiles).map(f => f.toLowerCase()), additionalInfo); + function verifyScriptInfos(session: TestSession, host: TestServerHost, openInfos: readonly string[], closedInfos: readonly string[], otherWatchedFiles: readonly string[], additionalInfo?: string) { + checkScriptInfos(session.getProjectService(), openInfos.concat(closedInfos), additionalInfo); + checkWatchedFiles(host, closedInfos.concat(otherWatchedFiles).map(f => f.toLowerCase()), additionalInfo); } - function verifyOnlyRandomInfos(session: ts.projectSystem.TestSession, host: ts.projectSystem.TestServerHost) { - verifyScriptInfos(session, host, [randomFile.path], [ts.projectSystem.libFile.path], [randomConfig.path], "Random"); + function verifyOnlyRandomInfos(session: TestSession, host: TestServerHost) { + verifyScriptInfos(session, host, [randomFile.path], [libFile.path], [randomConfig.path], "Random"); } - function declarationSpan(fn: number): ts.projectSystem.protocol.TextSpanWithContext { + function declarationSpan(fn: number): TextSpanWithContext { return { start: { line: fn, offset: 17 }, end: { line: fn, offset: 20 }, @@ -94,7 +106,7 @@ fn5(); contextEnd: { line: fn, offset: 26 } }; } - function importSpan(fn: number): ts.projectSystem.protocol.TextSpanWithContext { + function importSpan(fn: number): TextSpanWithContext { return { start: { line: fn + 1, offset: 5 }, end: { line: fn + 1, offset: 8 }, @@ -102,17 +114,17 @@ fn5(); contextEnd: { line: 7, offset: 22 } }; } - function usageSpan(fn: number): ts.projectSystem.protocol.TextSpan { + function usageSpan(fn: number): TextSpan { return { start: { line: fn + 8, offset: 1 }, end: { line: fn + 8, offset: 4 } }; } - function goToDefFromMainTs(fn: number): Action { + function goToDefFromMainTs(fn: number): Action { const textSpan = usageSpan(fn); - const definition: ts.projectSystem.protocol.FileSpan = { file: dependencyTs.path, ...declarationSpan(fn) }; + const definition: FileSpan = { file: dependencyTs.path, ...declarationSpan(fn) }; return { reqName: "goToDef", request: { - command: ts.projectSystem.protocol.CommandTypes.DefinitionAndBoundSpan, + command: CommandTypes.DefinitionAndBoundSpan, arguments: { file: mainTs.path, ...textSpan.start } }, expectedResponse: { @@ -123,14 +135,14 @@ fn5(); }; } - function goToDefFromMainTsWithNoMap(fn: number): Action { + function goToDefFromMainTsWithNoMap(fn: number): Action { const textSpan = usageSpan(fn); const definition = declarationSpan(fn); const declareSpaceLength = "declare ".length; return { reqName: "goToDef", request: { - command: ts.projectSystem.protocol.CommandTypes.DefinitionAndBoundSpan, + command: CommandTypes.DefinitionAndBoundSpan, arguments: { file: mainTs.path, ...textSpan.start } }, expectedResponse: { @@ -147,12 +159,12 @@ fn5(); }; } - function goToDefFromMainTsWithNoDts(fn: number): Action { + function goToDefFromMainTsWithNoDts(fn: number): Action { const textSpan = usageSpan(fn); return { reqName: "goToDef", request: { - command: ts.projectSystem.protocol.CommandTypes.DefinitionAndBoundSpan, + command: CommandTypes.DefinitionAndBoundSpan, arguments: { file: mainTs.path, ...textSpan.start } }, expectedResponse: { @@ -163,12 +175,12 @@ fn5(); }; } - function goToDefFromMainTsWithDependencyChange(fn: number): Action { + function goToDefFromMainTsWithDependencyChange(fn: number): Action { const textSpan = usageSpan(fn); return { reqName: "goToDef", request: { - command: ts.projectSystem.protocol.CommandTypes.DefinitionAndBoundSpan, + command: CommandTypes.DefinitionAndBoundSpan, arguments: { file: mainTs.path, ...textSpan.start } }, expectedResponse: { @@ -179,13 +191,13 @@ fn5(); }; } - function renameFromDependencyTs(fn: number): Action { + function renameFromDependencyTs(fn: number): Action { const defSpan = declarationSpan(fn); const { contextStart: _, contextEnd: _1, ...triggerSpan } = defSpan; return { reqName: "rename", request: { - command: ts.projectSystem.protocol.CommandTypes.Rename, + command: CommandTypes.Rename, arguments: { file: dependencyTs.path, ...triggerSpan.start } }, expectedResponse: { @@ -194,7 +206,7 @@ fn5(); fileToRename: undefined, displayName: `fn${fn}`, fullDisplayName: `"${dependecyLocation}/FnS".fn${fn}`, - kind: ts.ScriptElementKind.functionElement, + kind: ScriptElementKind.functionElement, kindModifiers: "export", triggerSpan }, @@ -205,14 +217,14 @@ fn5(); }; } - function renameFromDependencyTsWithDependencyChange(fn: number): Action { + function renameFromDependencyTsWithDependencyChange(fn: number): Action { const { expectedResponse: { info, locs }, ...rest } = renameFromDependencyTs(fn + 1); return { ...rest, expectedResponse: { info: { - ...info as ts.projectSystem.protocol.RenameInfoSuccess, + ...info as RenameInfoSuccess, displayName: `fn${fn}`, fullDisplayName: `"${dependecyLocation}/FnS".fn${fn}`, }, @@ -221,7 +233,7 @@ fn5(); }; } - function renameFromDependencyTsWithBothProjectsOpen(fn: number): Action { + function renameFromDependencyTsWithBothProjectsOpen(fn: number): Action { const { reqName, request, expectedResponse } = renameFromDependencyTs(fn); const { info, locs } = expectedResponse; return { @@ -243,7 +255,7 @@ fn5(); }; } - function renameFromDependencyTsWithBothProjectsOpenWithDependencyChange(fn: number): Action { + function renameFromDependencyTsWithBothProjectsOpenWithDependencyChange(fn: number): Action { const { reqName, request, expectedResponse, } = renameFromDependencyTsWithDependencyChange(fn); const { info, locs } = expectedResponse; return { @@ -272,21 +284,21 @@ fn5(); }); } - interface Action { + interface Action { reqName: string; request: Partial; expectedResponse: Response; } - function verifyAction(session: ts.projectSystem.TestSession, { reqName, request, expectedResponse }: Action) { + function verifyAction(session: TestSession, { reqName, request, expectedResponse }: Action) { const { response } = session.executeCommandSeq(request); assert.deepEqual(response, expectedResponse, `Failed Request: ${reqName}`); } function verifyDocumentPositionMapper( - session: ts.projectSystem.TestSession, - dependencyMap: ts.server.ScriptInfo | undefined, - documentPositionMapper: ts.server.ScriptInfo["documentPositionMapper"], + session: TestSession, + dependencyMap: ScriptInfo | undefined, + documentPositionMapper: ScriptInfo["documentPositionMapper"], equal: boolean, debugInfo?: string, ) { @@ -297,9 +309,9 @@ fn5(); } function verifyDocumentPositionMapperEqual( - session: ts.projectSystem.TestSession, - dependencyMap: ts.server.ScriptInfo | undefined, - documentPositionMapper: ts.server.ScriptInfo["documentPositionMapper"], + session: TestSession, + dependencyMap: ScriptInfo | undefined, + documentPositionMapper: ScriptInfo["documentPositionMapper"], debugInfo?: string, ) { verifyDocumentPositionMapper(session, dependencyMap, documentPositionMapper, /*equal*/ true, debugInfo); @@ -314,27 +326,27 @@ fn5(); } } - function verifyAllFnAction( - session: ts.projectSystem.TestSession, - host: ts.projectSystem.TestServerHost, + function verifyAllFnAction( + session: TestSession, + host: TestServerHost, action: (fn: number) => Action, expectedInfos: readonly string[], expectedWatchedFiles: readonly string[], - existingDependencyMap: ts.server.ScriptInfo | undefined, - existingDocumentPositionMapper: ts.server.ScriptInfo["documentPositionMapper"], + existingDependencyMap: ScriptInfo | undefined, + existingDocumentPositionMapper: ScriptInfo["documentPositionMapper"], existingMapEqual: boolean, existingDocumentPositionMapperEqual: boolean, skipMapPathInDtsInfo?: boolean ) { - let sourceMapPath: ts.server.ScriptInfo["sourceMapFilePath"] | undefined; - let dependencyMap: ts.server.ScriptInfo | undefined; - let documentPositionMapper: ts.server.ScriptInfo["documentPositionMapper"]; + let sourceMapPath: ScriptInfo["sourceMapFilePath"] | undefined; + let dependencyMap: ScriptInfo | undefined; + let documentPositionMapper: ScriptInfo["documentPositionMapper"]; for (let fn = 1; fn <= 5; fn++) { const fnAction = action(fn); verifyAction(session, fnAction); const debugInfo = `${fnAction.reqName}:: ${fn}`; - ts.projectSystem.checkScriptInfos(session.getProjectService(), expectedInfos, debugInfo); - ts.projectSystem.checkWatchedFiles(host, expectedWatchedFiles, debugInfo); + checkScriptInfos(session.getProjectService(), expectedInfos, debugInfo); + checkWatchedFiles(host, expectedWatchedFiles, debugInfo); const dtsInfo = session.getProjectService().getScriptInfoForPath(dtsPath); const dtsMapInfo = session.getProjectService().getScriptInfoForPath(dtsMapPath); @@ -365,36 +377,36 @@ fn5(); } function verifyScriptInfoCollectionWith( - session: ts.projectSystem.TestSession, - host: ts.projectSystem.TestServerHost, - openFiles: readonly ts.projectSystem.File[], + session: TestSession, + host: TestServerHost, + openFiles: readonly File[], expectedInfos: readonly string[], expectedWatchedFiles: readonly string[], ) { const { dependencyMap, documentPositionMapper } = getDocumentPositionMapper(session); // Collecting at this point retains dependency.d.ts and map - ts.projectSystem.closeFilesForSession([randomFile], session); - ts.projectSystem.openFilesForSession([randomFile], session); + closeFilesForSession([randomFile], session); + openFilesForSession([randomFile], session); - ts.projectSystem.checkScriptInfos(session.getProjectService(), expectedInfos); - ts.projectSystem.checkWatchedFiles(host, expectedWatchedFiles); + checkScriptInfos(session.getProjectService(), expectedInfos); + checkWatchedFiles(host, expectedWatchedFiles); // If map is not collected, document position mapper shouldnt change if (session.getProjectService().filenameToScriptInfo.has(dtsMapPath)) { verifyDocumentPositionMapperEqual(session, dependencyMap, documentPositionMapper); } // Closing open file, removes dependencies too - ts.projectSystem.closeFilesForSession([...openFiles, randomFile], session); - ts.projectSystem.openFilesForSession([randomFile], session); + closeFilesForSession([...openFiles, randomFile], session); + openFilesForSession([randomFile], session); verifyOnlyRandomInfos(session, host); } - type OnHostCreate = (host: ts.projectSystem.TestServerHost) => void; - type CreateSessionFn = (onHostCreate?: OnHostCreate) => { host: ts.projectSystem.TestServerHost; session: ts.projectSystem.TestSession; }; - function setupWith(createSession: CreateSessionFn, openFiles: readonly ts.projectSystem.File[], onHostCreate: OnHostCreate | undefined) { + type OnHostCreate = (host: TestServerHost) => void; + type CreateSessionFn = (onHostCreate?: OnHostCreate) => { host: TestServerHost; session: TestSession; }; + function setupWith(createSession: CreateSessionFn, openFiles: readonly File[], onHostCreate: OnHostCreate | undefined) { const result = createSession(onHostCreate); - ts.projectSystem.openFilesForSession(openFiles, result.session); + openFilesForSession(openFiles, result.session); return result; } @@ -411,25 +423,25 @@ fn5(); } function createSessionWithoutProjectReferences(onHostCreate?: OnHostCreate) { - const host = ts.projectSystem.createHostWithSolutionBuild(files, [mainConfig.path]); + const host = createHostWithSolutionBuild(files, [mainConfig.path]); // Erase project reference host.writeFile(mainConfig.path, JSON.stringify({ compilerOptions: { composite: true, declarationMap: true } })); onHostCreate?.(host); - const session = ts.projectSystem.createSession(host); + const session = createSession(host); return { host, session }; } function createSessionWithProjectReferences(onHostCreate?: OnHostCreate) { - const host = ts.projectSystem.createHostWithSolutionBuild(files, [mainConfig.path]); + const host = createHostWithSolutionBuild(files, [mainConfig.path]); onHostCreate?.(host); - const session = ts.projectSystem.createSession(host); + const session = createSession(host); return { host, session }; } function createSessionWithDisabledProjectReferences(onHostCreate?: OnHostCreate) { - const host = ts.projectSystem.createHostWithSolutionBuild(files, [mainConfig.path]); + const host = createHostWithSolutionBuild(files, [mainConfig.path]); // Erase project reference host.writeFile(mainConfig.path, JSON.stringify({ compilerOptions: { @@ -440,43 +452,43 @@ fn5(); references: [{ path: "../dependency" }] })); onHostCreate?.(host); - const session = ts.projectSystem.createSession(host); + const session = createSession(host); return { host, session }; } - function getDocumentPositionMapper(session: ts.projectSystem.TestSession) { + function getDocumentPositionMapper(session: TestSession) { const dependencyMap = session.getProjectService().filenameToScriptInfo.get(dtsMapPath); const documentPositionMapper = dependencyMap?.documentPositionMapper; return { dependencyMap, documentPositionMapper }; } - function checkMainProjectWithoutProjectReferences(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkProjectActualFiles(session.getProjectService().configuredProjects.get(mainConfig.path)!, [mainTs.path, ts.projectSystem.libFile.path, mainConfig.path, dtsPath]); + function checkMainProjectWithoutProjectReferences(session: TestSession) { + checkProjectActualFiles(session.getProjectService().configuredProjects.get(mainConfig.path)!, [mainTs.path, libFile.path, mainConfig.path, dtsPath]); } - function checkMainProjectWithoutProjectReferencesWithoutDts(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkProjectActualFiles(session.getProjectService().configuredProjects.get(mainConfig.path)!, [mainTs.path, ts.projectSystem.libFile.path, mainConfig.path]); + function checkMainProjectWithoutProjectReferencesWithoutDts(session: TestSession) { + checkProjectActualFiles(session.getProjectService().configuredProjects.get(mainConfig.path)!, [mainTs.path, libFile.path, mainConfig.path]); } - function checkMainProjectWithProjectReferences(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkProjectActualFiles(session.getProjectService().configuredProjects.get(mainConfig.path)!, [mainTs.path, ts.projectSystem.libFile.path, mainConfig.path, dependencyTs.path]); + function checkMainProjectWithProjectReferences(session: TestSession) { + checkProjectActualFiles(session.getProjectService().configuredProjects.get(mainConfig.path)!, [mainTs.path, libFile.path, mainConfig.path, dependencyTs.path]); } - function checkMainProjectWithDisabledProjectReferences(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkProjectActualFiles(session.getProjectService().configuredProjects.get(mainConfig.path)!, [mainTs.path, ts.projectSystem.libFile.path, mainConfig.path, dtsPath]); + function checkMainProjectWithDisabledProjectReferences(session: TestSession) { + checkProjectActualFiles(session.getProjectService().configuredProjects.get(mainConfig.path)!, [mainTs.path, libFile.path, mainConfig.path, dtsPath]); } - function checkMainProjectWithDisabledProjectReferencesWithoutDts(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkProjectActualFiles(session.getProjectService().configuredProjects.get(mainConfig.path)!, [mainTs.path, ts.projectSystem.libFile.path, mainConfig.path]); + function checkMainProjectWithDisabledProjectReferencesWithoutDts(session: TestSession) { + checkProjectActualFiles(session.getProjectService().configuredProjects.get(mainConfig.path)!, [mainTs.path, libFile.path, mainConfig.path]); } - function checkDependencyProjectWith(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkProjectActualFiles(session.getProjectService().configuredProjects.get(dependencyConfig.path)!, [dependencyTs.path, ts.projectSystem.libFile.path, dependencyConfig.path]); + function checkDependencyProjectWith(session: TestSession) { + checkProjectActualFiles(session.getProjectService().configuredProjects.get(dependencyConfig.path)!, [dependencyTs.path, libFile.path, dependencyConfig.path]); } - function makeChangeToMainTs(session: ts.projectSystem.TestSession) { - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + function makeChangeToMainTs(session: TestSession) { + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: mainTs.path, line: 14, @@ -488,9 +500,9 @@ fn5(); }); } - function makeChangeToDependencyTs(session: ts.projectSystem.TestSession) { - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + function makeChangeToDependencyTs(session: TestSession) { + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: dependencyTs.path, line: 6, @@ -510,8 +522,8 @@ fn5(); } function verifyScriptInfoCollection( - session: ts.projectSystem.TestSession, - host: ts.projectSystem.TestServerHost, + session: TestSession, + host: TestServerHost, expectedInfos: readonly string[], expectedWatchedFiles: readonly string[], ) { @@ -527,22 +539,22 @@ fn5(); return setupWithActionWith(setup, onHostCreate); } - function checkProjects(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); + function checkProjects(session: TestSession) { + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); checkMainProjectWithoutProjectReferences(session); } - function checkProjectsWithoutDts(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); + function checkProjectsWithoutDts(session: TestSession) { + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); checkMainProjectWithoutProjectReferencesWithoutDts(session); } function expectedScriptInfosWhenMapped() { - return [mainTs.path, randomFile.path, dependencyTs.path, ts.projectSystem.libFile.path, dtsPath, dtsMapLocation]; + return [mainTs.path, randomFile.path, dependencyTs.path, libFile.path, dtsPath, dtsMapLocation]; } function expectedWatchedFilesWhenMapped() { - return [dependencyTsPath, ts.projectSystem.libFile.path, dtsPath, dtsMapPath, mainConfig.path, randomConfig.path]; + return [dependencyTsPath, libFile.path, dtsPath, dtsMapPath, mainConfig.path, randomConfig.path]; } function expectedScriptInfosWhenNoMap() { @@ -887,17 +899,17 @@ fn5(); return setupWithActionWith(setup, onHostCreate); } - function checkProjects(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); + function checkProjects(session: TestSession) { + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); checkMainProjectWithProjectReferences(session); } function expectedScriptInfos() { - return [dependencyTs.path, ts.projectSystem.libFile.path, mainTs.path, randomFile.path]; + return [dependencyTs.path, libFile.path, mainTs.path, randomFile.path]; } function expectedWatchedFiles() { - return [dependencyTsPath, dependencyConfig.path, ts.projectSystem.libFile.path, mainConfig.path, randomConfig.path]; + return [dependencyTsPath, dependencyConfig.path, libFile.path, mainConfig.path, randomConfig.path]; } it("can go to definition correctly", () => { @@ -1261,9 +1273,9 @@ ${dependencyTs.content}`); }); it("when projects are not built", () => { - const host = ts.projectSystem.createServerHost(files); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([mainTs, randomFile], session); + const host = createServerHost(files); + const session = createSession(host); + openFilesForSession([mainTs, randomFile], session); verifyAllFnAction( session, host, @@ -1293,22 +1305,22 @@ ${dependencyTs.content}`); return setupWithActionWith(setup, onHostCreate); } - function checkProjects(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); + function checkProjects(session: TestSession) { + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); checkMainProjectWithDisabledProjectReferences(session); } - function checkProjectsWithoutDts(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); + function checkProjectsWithoutDts(session: TestSession) { + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); checkMainProjectWithDisabledProjectReferencesWithoutDts(session); } function expectedScriptInfosWhenMapped() { - return [mainTs.path, randomFile.path, dependencyTs.path, ts.projectSystem.libFile.path, dtsPath, dtsMapLocation]; + return [mainTs.path, randomFile.path, dependencyTs.path, libFile.path, dtsPath, dtsMapLocation]; } function expectedWatchedFilesWhenMapped() { - return [dependencyTsPath, ts.projectSystem.libFile.path, dtsPath, dtsMapPath, mainConfig.path, randomConfig.path, dependencyConfig.path]; + return [dependencyTsPath, libFile.path, dtsPath, dtsMapPath, mainConfig.path, randomConfig.path, dependencyConfig.path]; } function expectedScriptInfosWhenNoMap() { @@ -1654,25 +1666,25 @@ ${dependencyTs.content}`); } function verifyScriptInfoCollection( - session: ts.projectSystem.TestSession, - host: ts.projectSystem.TestServerHost, + session: TestSession, + host: TestServerHost, expectedInfos: readonly string[], expectedWatchedFiles: readonly string[], ) { return verifyScriptInfoCollectionWith(session, host, [dependencyTs], expectedInfos, expectedWatchedFiles); } - function checkProjects(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); + function checkProjects(session: TestSession) { + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 2 }); checkDependencyProjectWith(session); } function expectedScriptInfos() { - return [ts.projectSystem.libFile.path, dtsLocation, dtsMapLocation, dependencyTs.path, randomFile.path]; + return [libFile.path, dtsLocation, dtsMapLocation, dependencyTs.path, randomFile.path]; } function expectedWatchedFiles() { - return [ts.projectSystem.libFile.path, dtsPath, dtsMapPath, dependencyConfig.path, randomConfig.path]; + return [libFile.path, dtsPath, dtsMapPath, dependencyConfig.path, randomConfig.path]; } function expectedScriptInfosWhenNoMap() { @@ -2345,8 +2357,8 @@ ${dependencyTs.content}`); // change // Make change, without rebuild of solution - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: dependencyTs.path, line: 1, offset: 1, endLine: 1, endOffset: 1, insertString: `function fooBar() { } `} @@ -2374,8 +2386,8 @@ ${dependencyTs.content}`); // change // Make change, without rebuild of solution - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: dependencyTs.path, line: 1, offset: 1, endLine: 1, endOffset: 1, insertString: `function fooBar() { } `} @@ -2396,9 +2408,9 @@ ${dependencyTs.content}`); }); it("when projects are not built", () => { - const host = ts.projectSystem.createServerHost(files); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([dependencyTs, randomFile], session); + const host = createServerHost(files); + const session = createSession(host); + openFilesForSession([dependencyTs, randomFile], session); verifyAllFnAction( session, host, @@ -2752,8 +2764,8 @@ ${dependencyTs.content}`); } function verifyScriptInfoCollection( - session: ts.projectSystem.TestSession, - host: ts.projectSystem.TestServerHost, + session: TestSession, + host: TestServerHost, expectedInfos: readonly string[], expectedWatchedFiles: readonly string[], ) { @@ -2769,24 +2781,24 @@ ${dependencyTs.content}`); return setupWithActionWith(setup, onHostCreate); } - function checkProjects(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { configuredProjects: 3 }); + function checkProjects(session: TestSession) { + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 3 }); checkMainProjectWithoutProjectReferences(session); checkDependencyProjectWith(session); } - function checkProjectsWithoutDts(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { configuredProjects: 3 }); + function checkProjectsWithoutDts(session: TestSession) { + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 3 }); checkMainProjectWithoutProjectReferencesWithoutDts(session); checkDependencyProjectWith(session); } function expectedScriptInfosWhenMapped() { - return [mainTs.path, randomFile.path, dependencyTs.path, ts.projectSystem.libFile.path, dtsPath, dtsMapLocation]; + return [mainTs.path, randomFile.path, dependencyTs.path, libFile.path, dtsPath, dtsMapLocation]; } function expectedWatchedFilesWhenMapped() { - return [ts.projectSystem.libFile.path, dtsPath, dtsMapPath, mainConfig.path, randomConfig.path, dependencyConfig.path]; + return [libFile.path, dtsPath, dtsMapPath, mainConfig.path, randomConfig.path, dependencyConfig.path]; } function expectedScriptInfosWhenNoMap() { @@ -3292,18 +3304,18 @@ ${dependencyTs.content}`); return setupWithActionWith(setup, onHostCreate); } - function checkProjects(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { configuredProjects: 3 }); + function checkProjects(session: TestSession) { + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 3 }); checkMainProjectWithProjectReferences(session); checkDependencyProjectWith(session); } function expectedScriptInfosAfterGotoDef() { - return [dependencyTs.path, ts.projectSystem.libFile.path, mainTs.path, randomFile.path]; + return [dependencyTs.path, libFile.path, mainTs.path, randomFile.path]; } function expectedWatchedFilesAfterGotoDef() { - return [dependencyConfig.path, ts.projectSystem.libFile.path, mainConfig.path, randomConfig.path]; + return [dependencyConfig.path, libFile.path, mainConfig.path, randomConfig.path]; } function expectedScriptInfosAfterRenameWhenMapped() { @@ -3805,8 +3817,8 @@ ${dependencyTs.content}`); // change // Make change, without rebuild of solution - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: dependencyTs.path, line: 1, offset: 1, endLine: 1, endOffset: 1, insertString: `function fooBar() { } `} @@ -3845,8 +3857,8 @@ ${dependencyTs.content}`); // change // Make change, without rebuild of solution - session.executeCommandSeq({ - command: ts.projectSystem.protocol.CommandTypes.Change, + session.executeCommandSeq({ + command: CommandTypes.Change, arguments: { file: dependencyTs.path, line: 1, offset: 1, endLine: 1, endOffset: 1, insertString: `function fooBar() { } `} @@ -3878,9 +3890,9 @@ ${dependencyTs.content}`); }); it("when projects are not built", () => { - const host = ts.projectSystem.createServerHost(files); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([mainTs, dependencyTs, randomFile], session); + const host = createServerHost(files); + const session = createSession(host); + openFilesForSession([mainTs, dependencyTs, randomFile], session); verifyAllFnAction( session, host, @@ -3921,24 +3933,24 @@ ${dependencyTs.content}`); return setupWithActionWith(setup, onHostCreate); } - function checkProjects(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { configuredProjects: 3 }); + function checkProjects(session: TestSession) { + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 3 }); checkMainProjectWithDisabledProjectReferences(session); checkDependencyProjectWith(session); } - function checkProjectsWithoutDts(session: ts.projectSystem.TestSession) { - ts.projectSystem.checkNumberOfProjects(session.getProjectService(), { configuredProjects: 3 }); + function checkProjectsWithoutDts(session: TestSession) { + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 3 }); checkMainProjectWithDisabledProjectReferencesWithoutDts(session); checkDependencyProjectWith(session); } function expectedScriptInfosWhenMapped() { - return [mainTs.path, randomFile.path, dependencyTs.path, ts.projectSystem.libFile.path, dtsPath, dtsMapLocation]; + return [mainTs.path, randomFile.path, dependencyTs.path, libFile.path, dtsPath, dtsMapLocation]; } function expectedWatchedFilesWhenMapped() { - return [ts.projectSystem.libFile.path, dtsPath, dtsMapPath, mainConfig.path, randomConfig.path, dependencyConfig.path]; + return [libFile.path, dtsPath, dtsMapPath, mainConfig.path, randomConfig.path, dependencyConfig.path]; } function expectedScriptInfosWhenNoMap() { diff --git a/src/testRunner/unittests/tsserver/projects.ts b/src/testRunner/unittests/tsserver/projects.ts index 11b83adf6e023..abfd7f2499e25 100644 --- a/src/testRunner/unittests/tsserver/projects.ts +++ b/src/testRunner/unittests/tsserver/projects.ts @@ -1,59 +1,86 @@ +import { + noop, notImplemented, removeMinAndVersionNumbers, returnFalse, singleIterator, some, +} from "../../../compiler/core"; +import { Debug } from "../../../compiler/debug"; +import { combinePaths, getDirectoryPath, normalizePath } from "../../../compiler/path"; +import { Path, ScriptKind, ScriptTarget } from "../../../compiler/types"; +import { createTextSpan } from "../../../compiler/utilitiesPublic"; +import { + CloseRequest, CommandTypes, ConfigureRequest, ConfigureRequestArguments, GetApplicableRefactorsRequest, + GeterrRequest, OccurrencesRequest, OpenRequest, SemanticDiagnosticsSyncRequestArgs, +} from "../../../server/protocol"; +import { CommandNames } from "../../../server/session"; +import { ITypingsInstaller } from "../../../server/typingsCache"; +import { + asNormalizedPath, createInstallTypingsRequest, emptyArray, NormalizedPath, +} from "../../../server/utilitiesPublic"; +import { emptyOptions, ScriptElementKind } from "../../../services/types"; +import { getSnapshotText } from "../../../services/utilities"; import * as ts from "../../_namespaces/ts"; +import { projectSystem } from "../../_namespaces/ts"; +import { projectRoot } from "../tscWatch/helpers"; +import { + baselineTsserverLogs, checkNumberOfConfiguredProjects, checkNumberOfInferredProjects, checkNumberOfProjects, + checkProjectActualFiles, checkProjectRootFiles, checkWatchedFiles, closeFilesForSession, commonFile1, commonFile2, + configuredProjectAt, createLoggerWithInMemoryLogs, createProjectService, createServerHost, createSession, + customTypesMap, File, libFile, makeSessionRequest, openFilesForSession, toExternalFile, toExternalFiles, + verifyGetErrRequest, +} from "./helpers"; describe("unittests:: tsserver:: Projects", () => { it("handles the missing files - that were added to program because they were added with /// { - const file1: ts.projectSystem.File = { + const file1: File = { path: "/a/b/commonFile1.ts", content: `/// let x = y` }; - const host = ts.projectSystem.createServerHost([file1, ts.projectSystem.libFile]); - const session = ts.projectSystem.createSession(host, { logger: ts.projectSystem.createLoggerWithInMemoryLogs() }); - ts.projectSystem.openFilesForSession([file1], session); + const host = createServerHost([file1, libFile]); + const session = createSession(host, { logger: createLoggerWithInMemoryLogs() }); + openFilesForSession([file1], session); - const getErrRequest = ts.projectSystem.makeSessionRequest( - ts.server.CommandNames.SemanticDiagnosticsSync, + const getErrRequest = makeSessionRequest( + CommandNames.SemanticDiagnosticsSync, { file: file1.path } ); // Two errors: CommonFile2 not found and cannot find name y session.executeCommand(getErrRequest); - host.writeFile(ts.projectSystem.commonFile2.path, ts.projectSystem.commonFile2.content); + host.writeFile(commonFile2.path, commonFile2.content); host.runQueuedTimeoutCallbacks(); session.executeCommand(getErrRequest); - ts.projectSystem.baselineTsserverLogs("projects", "handles the missing files added with tripleslash ref", session); + baselineTsserverLogs("projects", "handles the missing files added with tripleslash ref", session); }); it("should create new inferred projects for files excluded from a configured project", () => { - const configFile: ts.projectSystem.File = { + const configFile: File = { path: "/a/b/tsconfig.json", content: `{ "compilerOptions": {}, - "files": ["${ts.projectSystem.commonFile1.path}", "${ts.projectSystem.commonFile2.path}"] + "files": ["${commonFile1.path}", "${commonFile2.path}"] }` }; - const files = [ts.projectSystem.commonFile1, ts.projectSystem.commonFile2, configFile]; - const host = ts.projectSystem.createServerHost(files); - const projectService = ts.projectSystem.createProjectService(host); - projectService.openClientFile(ts.projectSystem.commonFile1.path); + const files = [commonFile1, commonFile2, configFile]; + const host = createServerHost(files); + const projectService = createProjectService(host); + projectService.openClientFile(commonFile1.path); - const project = ts.projectSystem.configuredProjectAt(projectService, 0); - ts.projectSystem.checkProjectRootFiles(project, [ts.projectSystem.commonFile1.path, ts.projectSystem.commonFile2.path]); + const project = configuredProjectAt(projectService, 0); + checkProjectRootFiles(project, [commonFile1.path, commonFile2.path]); configFile.content = `{ "compilerOptions": {}, - "files": ["${ts.projectSystem.commonFile1.path}"] + "files": ["${commonFile1.path}"] }`; host.writeFile(configFile.path, configFile.content); - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); - ts.projectSystem.checkProjectRootFiles(project, [ts.projectSystem.commonFile1.path, ts.projectSystem.commonFile2.path]); + checkNumberOfConfiguredProjects(projectService, 1); + checkProjectRootFiles(project, [commonFile1.path, commonFile2.path]); host.checkTimeoutQueueLengthAndRun(2); // Update the configured project + refresh inferred projects - ts.projectSystem.checkNumberOfConfiguredProjects(projectService, 1); - ts.projectSystem.checkProjectRootFiles(project, [ts.projectSystem.commonFile1.path]); + checkNumberOfConfiguredProjects(projectService, 1); + checkProjectRootFiles(project, [commonFile1.path]); - projectService.openClientFile(ts.projectSystem.commonFile2.path); - ts.projectSystem.checkNumberOfInferredProjects(projectService, 1); + projectService.openClientFile(commonFile2.path); + checkNumberOfInferredProjects(projectService, 1); }); it("should disable features when the files are too large", () => { @@ -75,18 +102,18 @@ describe("unittests:: tsserver:: Projects", () => { const proj1name = "proj1", proj2name = "proj2", proj3name = "proj3"; - const host = ts.projectSystem.createServerHost([file1, file2, file3]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2, file3]); + const projectService = createProjectService(host); - projectService.openExternalProject({ rootFiles: ts.projectSystem.toExternalFiles([file1.path]), options: {}, projectFileName: proj1name }); + projectService.openExternalProject({ rootFiles: toExternalFiles([file1.path]), options: {}, projectFileName: proj1name }); const proj1 = projectService.findProject(proj1name)!; assert.isTrue(proj1.languageServiceEnabled); - projectService.openExternalProject({ rootFiles: ts.projectSystem.toExternalFiles([file2.path]), options: {}, projectFileName: proj2name }); + projectService.openExternalProject({ rootFiles: toExternalFiles([file2.path]), options: {}, projectFileName: proj2name }); const proj2 = projectService.findProject(proj2name)!; assert.isTrue(proj2.languageServiceEnabled); - projectService.openExternalProject({ rootFiles: ts.projectSystem.toExternalFiles([file3.path]), options: {}, projectFileName: proj3name }); + projectService.openExternalProject({ rootFiles: toExternalFiles([file3.path]), options: {}, projectFileName: proj3name }); const proj3 = projectService.findProject(proj3name)!; assert.isFalse(proj3.languageServiceEnabled); }); @@ -105,10 +132,10 @@ describe("unittests:: tsserver:: Projects", () => { const projName = "proj1"; - const host = ts.projectSystem.createServerHost([file1, file2]); - const projectService = ts.projectSystem.createProjectService(host, { useSingleInferredProject: true, eventHandler: ts.noop }); + const host = createServerHost([file1, file2]); + const projectService = createProjectService(host, { useSingleInferredProject: true, eventHandler: noop }); - projectService.openExternalProject({ rootFiles: ts.projectSystem.toExternalFiles([file1.path, file2.path]), options: {}, projectFileName: projName }); + projectService.openExternalProject({ rootFiles: toExternalFiles([file1.path, file2.path]), options: {}, projectFileName: projName }); const proj1 = projectService.findProject(projName)!; assert.isFalse(proj1.languageServiceEnabled); @@ -132,15 +159,15 @@ describe("unittests:: tsserver:: Projects", () => { }; const externalProjectName = "externalproject"; - const host = ts.projectSystem.createServerHost([file1, config1]); - const projectService = ts.projectSystem.createProjectService(host, { useSingleInferredProject: true, syntaxOnly: true }); + const host = createServerHost([file1, config1]); + const projectService = createProjectService(host, { useSingleInferredProject: true, syntaxOnly: true }); projectService.openExternalProject({ - rootFiles: ts.projectSystem.toExternalFiles([file1.path, config1.path]), + rootFiles: toExternalFiles([file1.path, config1.path]), options: {}, projectFileName: externalProjectName }); - ts.projectSystem.checkNumberOfProjects(projectService, { externalProjects: 1 }); + checkNumberOfProjects(projectService, { externalProjects: 1 }); const proj = projectService.externalProjects[0]; assert.isDefined(proj); @@ -162,11 +189,11 @@ describe("unittests:: tsserver:: Projects", () => { ) }; - const host = ts.projectSystem.createServerHost([file1, config1]); - const projectService = ts.projectSystem.createProjectService(host, { useSingleInferredProject: true, syntaxOnly: true }); + const host = createServerHost([file1, config1]); + const projectService = createProjectService(host, { useSingleInferredProject: true, syntaxOnly: true }); projectService.openClientFile(file1.path, file1.content); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); const proj = projectService.inferredProjects[0]; assert.isDefined(proj); @@ -188,11 +215,11 @@ describe("unittests:: tsserver:: Projects", () => { ) }; - const host = ts.projectSystem.createServerHost([file1, config1]); - const projectService = ts.projectSystem.createProjectService(host, { useSingleInferredProject: true, syntaxOnly: true }); - projectService.applyChangesInOpenFiles(ts.singleIterator({ fileName: file1.path, content: file1.content })); + const host = createServerHost([file1, config1]); + const projectService = createProjectService(host, { useSingleInferredProject: true, syntaxOnly: true }); + projectService.applyChangesInOpenFiles(singleIterator({ fileName: file1.path, content: file1.content })); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); const proj = projectService.inferredProjects[0]; assert.isDefined(proj); @@ -210,23 +237,23 @@ describe("unittests:: tsserver:: Projects", () => { content: "let x: number;" }; - const host = ts.projectSystem.createServerHost([f1, f2, ts.projectSystem.libFile]); - const service = ts.projectSystem.createProjectService(host); - service.openExternalProject({ projectFileName: "/a/b/project", rootFiles: ts.projectSystem.toExternalFiles([f1.path, f2.path]), options: {} }); + const host = createServerHost([f1, f2, libFile]); + const service = createProjectService(host); + service.openExternalProject({ projectFileName: "/a/b/project", rootFiles: toExternalFiles([f1.path, f2.path]), options: {} }); service.openClientFile(f1.path); service.openClientFile(f2.path, "let x: string"); service.checkNumberOfProjects({ externalProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(service.externalProjects[0], [f1.path, f2.path, ts.projectSystem.libFile.path]); + checkProjectActualFiles(service.externalProjects[0], [f1.path, f2.path, libFile.path]); - const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, ts.emptyOptions)!; + const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, emptyOptions)!; // should contain completions for string assert.isTrue(completions1.entries.some(e => e.name === "charAt"), "should contain 'charAt'"); assert.isFalse(completions1.entries.some(e => e.name === "toExponential"), "should not contain 'toExponential'"); service.closeClientFile(f2.path); - const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, ts.emptyOptions)!; + const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, emptyOptions)!; // should contain completions for string assert.isFalse(completions2.entries.some(e => e.name === "charAt"), "should not contain 'charAt'"); assert.isTrue(completions2.entries.some(e => e.name === "toExponential"), "should contain 'toExponential'"); @@ -242,21 +269,21 @@ describe("unittests:: tsserver:: Projects", () => { content: "" }; - const host = ts.projectSystem.createServerHost([f1, f2, ts.projectSystem.libFile]); - const service = ts.projectSystem.createProjectService(host); + const host = createServerHost([f1, f2, libFile]); + const service = createProjectService(host); service.openExternalProject({ projectFileName: "/a/b/project", rootFiles: [{ fileName: f1.path }, { fileName: f2.path, hasMixedContent: true }], options: {} }); service.openClientFile(f1.path); service.openClientFile(f2.path, "let somelongname: string"); service.checkNumberOfProjects({ externalProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(service.externalProjects[0], [f1.path, f2.path, ts.projectSystem.libFile.path]); + checkProjectActualFiles(service.externalProjects[0], [f1.path, f2.path, libFile.path]); - const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, ts.emptyOptions)!; + const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, emptyOptions)!; assert.isTrue(completions1.entries.some(e => e.name === "somelongname"), "should contain 'somelongname'"); service.closeClientFile(f2.path); - const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, ts.emptyOptions)!; + const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, emptyOptions)!; assert.isFalse(completions2.entries.some(e => e.name === "somelongname"), "should not contain 'somelongname'"); const sf2 = service.externalProjects[0].getLanguageService().getProgram()!.getSourceFile(f2.path)!; assert.equal(sf2.text, ""); @@ -275,26 +302,26 @@ describe("unittests:: tsserver:: Projects", () => { path: "/a/c/f3.ts", content: `export let y = 1;` }; - const host = ts.projectSystem.createServerHost([file1, file2, file3]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2, file3]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); const inferredProject0 = projectService.inferredProjects[0]; - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file1.path, file2.path]); + checkProjectActualFiles(projectService.inferredProjects[0], [file1.path, file2.path]); projectService.openClientFile(file3.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 2 }); + checkNumberOfProjects(projectService, { inferredProjects: 2 }); assert.strictEqual(projectService.inferredProjects[0], inferredProject0); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file1.path, file2.path]); + checkProjectActualFiles(projectService.inferredProjects[0], [file1.path, file2.path]); const inferredProject1 = projectService.inferredProjects[1]; - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [file3.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [file3.path]); host.writeFile(file2.path, `export * from "../c/f3"`); // now inferred project should inclule file3 host.checkTimeoutQueueLengthAndRun(2); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 2 }); + checkNumberOfProjects(projectService, { inferredProjects: 2 }); assert.strictEqual(projectService.inferredProjects[0], inferredProject0); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file1.path, file2.path, file3.path]); + checkProjectActualFiles(projectService.inferredProjects[0], [file1.path, file2.path, file3.path]); assert.strictEqual(projectService.inferredProjects[1], inferredProject1); assert.isTrue(inferredProject1.isOrphan()); }); @@ -312,25 +339,25 @@ describe("unittests:: tsserver:: Projects", () => { path: "/a/c/f3.ts", content: `export let y = 1;` }; - const host = ts.projectSystem.createServerHost([file1, file2, file3]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2, file3]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file1.path, file2.path, file3.path]); + checkProjectActualFiles(projectService.inferredProjects[0], [file1.path, file2.path, file3.path]); projectService.openClientFile(file3.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); host.deleteFile(file2.path); host.checkTimeoutQueueLengthAndRun(2); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 2 }); + checkNumberOfProjects(projectService, { inferredProjects: 2 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file1.path]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [file3.path]); + checkProjectActualFiles(projectService.inferredProjects[0], [file1.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [file3.path]); }); it("ignores files excluded by a custom safe type list", () => { @@ -342,10 +369,10 @@ describe("unittests:: tsserver:: Projects", () => { path: "/lib/duckquack-3.min.js", content: "whoa do @@ not parse me ok thanks!!!" }; - const host = ts.projectSystem.createServerHost([file1, office, ts.projectSystem.customTypesMap]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, office, customTypesMap]); + const projectService = createProjectService(host); try { - projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: ts.projectSystem.toExternalFiles([file1.path, office.path]) }); + projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path, office.path]) }); const proj = projectService.externalProjects[0]; assert.deepEqual(proj.getFileNames(/*excludeFilesFromExternalLibraries*/ true), [file1.path]); assert.deepEqual(proj.getTypeAcquisition().include, ["duck-types"]); @@ -368,27 +395,27 @@ describe("unittests:: tsserver:: Projects", () => { path: "/a/b/bliss.js", content: "export function is() { return true; }" }; - const host = ts.projectSystem.createServerHost([file1, ts.projectSystem.libFile, constructorFile, bliss, ts.projectSystem.customTypesMap]); + const host = createServerHost([file1, libFile, constructorFile, bliss, customTypesMap]); let request: string | undefined; const cachePath = "/a/data"; - const typingsInstaller: ts.server.ITypingsInstaller = { - isKnownTypesPackageName: ts.returnFalse, - installPackage: ts.notImplemented, + const typingsInstaller: ITypingsInstaller = { + isKnownTypesPackageName: returnFalse, + installPackage: notImplemented, enqueueInstallTypingsRequest: (proj, typeAcquisition, unresolvedImports) => { assert.isUndefined(request); - request = JSON.stringify(ts.server.createInstallTypingsRequest(proj, typeAcquisition, unresolvedImports || ts.server.emptyArray, cachePath)); + request = JSON.stringify(createInstallTypingsRequest(proj, typeAcquisition, unresolvedImports || emptyArray, cachePath)); }, - attach: ts.noop, - onProjectClosed: ts.noop, + attach: noop, + onProjectClosed: noop, globalTypingsCacheLocation: cachePath }; const projectName = "project"; - const projectService = ts.projectSystem.createProjectService(host, { typingsInstaller }); - projectService.openExternalProject({ projectFileName: projectName, options: {}, rootFiles: ts.projectSystem.toExternalFiles([file1.path, constructorFile.path, bliss.path]) }); + const projectService = createProjectService(host, { typingsInstaller }); + projectService.openExternalProject({ projectFileName: projectName, options: {}, rootFiles: toExternalFiles([file1.path, constructorFile.path, bliss.path]) }); assert.equal(request, JSON.stringify({ projectName, - fileNames: [ts.projectSystem.libFile.path, file1.path, constructorFile.path, bliss.path], + fileNames: [libFile.path, file1.path, constructorFile.path, bliss.path], compilerOptions: { allowNonTsExtensions: true, noEmitForJsFiles: true }, typeAcquisition: { include: ["blissfuljs"], exclude: [], enable: true }, unresolvedImports: ["s"], @@ -441,10 +468,10 @@ describe("unittests:: tsserver:: Projects", () => { content: "unspecified" }; const files = [file1, minFile, kendoFile1, kendoFile2, kendoFile3, officeFile1, officeFile2]; - const host = ts.projectSystem.createServerHost(files); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost(files); + const projectService = createProjectService(host); try { - projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: ts.projectSystem.toExternalFiles(files.map(f => f.path)) }); + projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles(files.map(f => f.path)) }); const proj = projectService.externalProjects[0]; assert.deepEqual(proj.getFileNames(/*excludeFilesFromExternalLibraries*/ true), [file1.path]); assert.deepEqual(proj.getTypeAcquisition().include, ["kendo-ui", "office"]); @@ -466,7 +493,7 @@ describe("unittests:: tsserver:: Projects", () => { ["jquery", "jquery"] ]; for (const t of testData) { - assert.equal(ts.removeMinAndVersionNumbers(t[0]), t[1], t[0]); + assert.equal(removeMinAndVersionNumbers(t[0]), t[1], t[0]); } }); @@ -483,10 +510,10 @@ describe("unittests:: tsserver:: Projects", () => { path: "/a/b/Bacon.js", content: "let y = 5" }; - const host = ts.projectSystem.createServerHost([file1, file2, file3, ts.projectSystem.customTypesMap]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2, file3, customTypesMap]); + const projectService = createProjectService(host); try { - projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: ts.projectSystem.toExternalFiles([file1.path, file2.path]), typeAcquisition: { enable: true } }); + projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path, file2.path]), typeAcquisition: { enable: true } }); const proj = projectService.externalProjects[0]; assert.deepEqual(proj.getFileNames(), [file2.path]); } @@ -510,52 +537,52 @@ describe("unittests:: tsserver:: Projects", () => { path: "/a/d/f3.ts", content: "export let y = 1;" }; - const host = ts.projectSystem.createServerHost([file1, file2, file3]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2, file3]); + const projectService = createProjectService(host); projectService.openClientFile(file2.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file2.path]); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkProjectActualFiles(projectService.inferredProjects[0], [file2.path]); let inferredProjects = projectService.inferredProjects.slice(); projectService.openClientFile(file3.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 2 }); + checkNumberOfProjects(projectService, { inferredProjects: 2 }); assert.strictEqual(projectService.inferredProjects[0], inferredProjects[0]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file2.path]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [file3.path]); + checkProjectActualFiles(projectService.inferredProjects[0], [file2.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [file3.path]); inferredProjects = projectService.inferredProjects.slice(); projectService.openClientFile(file1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); assert.notStrictEqual(projectService.inferredProjects[0], inferredProjects[0]); assert.notStrictEqual(projectService.inferredProjects[0], inferredProjects[1]); - ts.projectSystem.checkProjectRootFiles(projectService.inferredProjects[0], [file1.path]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file1.path, file2.path, file3.path]); + checkProjectRootFiles(projectService.inferredProjects[0], [file1.path]); + checkProjectActualFiles(projectService.inferredProjects[0], [file1.path, file2.path, file3.path]); inferredProjects = projectService.inferredProjects.slice(); projectService.closeClientFile(file1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 3 }); + checkNumberOfProjects(projectService, { inferredProjects: 3 }); assert.strictEqual(projectService.inferredProjects[0], inferredProjects[0]); assert.isTrue(projectService.inferredProjects[0].isOrphan()); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [file2.path]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[2], [file3.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [file2.path]); + checkProjectActualFiles(projectService.inferredProjects[2], [file3.path]); inferredProjects = projectService.inferredProjects.slice(); projectService.closeClientFile(file3.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 3 }); + checkNumberOfProjects(projectService, { inferredProjects: 3 }); assert.strictEqual(projectService.inferredProjects[0], inferredProjects[0]); assert.strictEqual(projectService.inferredProjects[1], inferredProjects[1]); assert.strictEqual(projectService.inferredProjects[2], inferredProjects[2]); assert.isTrue(projectService.inferredProjects[0].isOrphan()); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [file2.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [file2.path]); assert.isTrue(projectService.inferredProjects[2].isOrphan()); projectService.openClientFile(file3.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 2 }); + checkNumberOfProjects(projectService, { inferredProjects: 2 }); assert.strictEqual(projectService.inferredProjects[0], inferredProjects[2]); assert.strictEqual(projectService.inferredProjects[1], inferredProjects[1]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file3.path]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [file2.path]); + checkProjectActualFiles(projectService.inferredProjects[0], [file3.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [file2.path]); }); it("regression test for crash in acquireOrUpdateDocument", () => { @@ -571,13 +598,13 @@ describe("unittests:: tsserver:: Projects", () => { scriptKind: "JS" as "JS" }; - const host = ts.projectSystem.createServerHost([]); - const projectService = ts.projectSystem.createProjectService(host); - projectService.applyChangesInOpenFiles(ts.singleIterator(tsFile)); + const host = createServerHost([]); + const projectService = createProjectService(host); + projectService.applyChangesInOpenFiles(singleIterator(tsFile)); const projs = projectService.synchronizeProjectList([]); projectService.findProject(projs[0].info!.projectName)!.getLanguageService().getNavigationBarItems(tsFile.fileName); projectService.synchronizeProjectList([projs[0].info!]); - projectService.applyChangesInOpenFiles(ts.singleIterator(jsFile)); + projectService.applyChangesInOpenFiles(singleIterator(jsFile)); }); it("config file is deleted", () => { @@ -593,22 +620,22 @@ describe("unittests:: tsserver:: Projects", () => { path: "/a/b/tsconfig.json", content: JSON.stringify({ compilerOptions: {} }) }; - const host = ts.projectSystem.createServerHost([file1, file2, config]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2, config]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [file1.path, file2.path, config.path]); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkProjectActualFiles(configuredProjectAt(projectService, 0), [file1.path, file2.path, config.path]); projectService.openClientFile(file2.path); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [file1.path, file2.path, config.path]); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkProjectActualFiles(configuredProjectAt(projectService, 0), [file1.path, file2.path, config.path]); host.deleteFile(config.path); host.checkTimeoutQueueLengthAndRun(1); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 2 }); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [file1.path]); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[1], [file2.path]); + checkNumberOfProjects(projectService, { inferredProjects: 2 }); + checkProjectActualFiles(projectService.inferredProjects[0], [file1.path]); + checkProjectActualFiles(projectService.inferredProjects[1], [file2.path]); }); it("loading files with correct priority", () => { @@ -630,8 +657,8 @@ describe("unittests:: tsserver:: Projects", () => { compilerOptions: { allowJs: true } }) }; - const host = ts.projectSystem.createServerHost([f1, f2, f3, config]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([f1, f2, f3, config]); + const projectService = createProjectService(host); projectService.setHostConfiguration({ extraFileExtensions: [ { extension: ".js", isMixedContent: false }, @@ -640,21 +667,21 @@ describe("unittests:: tsserver:: Projects", () => { }); projectService.openClientFile(f1.path); projectService.checkNumberOfProjects({ configuredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [f1.path, config.path]); + checkProjectActualFiles(configuredProjectAt(projectService, 0), [f1.path, config.path]); // Since f2 refers to config file as the default project, it needs to be kept alive projectService.closeClientFile(f1.path); projectService.openClientFile(f2.path); projectService.checkNumberOfProjects({ inferredProjects: 1, configuredProjects: 1 }); assert.isDefined(projectService.configuredProjects.get(config.path)); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [f2.path]); + checkProjectActualFiles(projectService.inferredProjects[0], [f2.path]); // Should close configured project with next file open projectService.closeClientFile(f2.path); projectService.openClientFile(f3.path); projectService.checkNumberOfProjects({ inferredProjects: 1 }); assert.isUndefined(projectService.configuredProjects.get(config.path)); - ts.projectSystem.checkProjectActualFiles(projectService.inferredProjects[0], [f3.path]); + checkProjectActualFiles(projectService.inferredProjects[0], [f3.path]); }); it("tsconfig script block support", () => { @@ -670,41 +697,41 @@ describe("unittests:: tsserver:: Projects", () => { path: "/a/b/tsconfig.json", content: JSON.stringify({ compilerOptions: { allowJs: true } }) }; - const host = ts.projectSystem.createServerHost([file1, file2, config]); - const session = ts.projectSystem.createSession(host); - ts.projectSystem.openFilesForSession([file1], session); + const host = createServerHost([file1, file2, config]); + const session = createSession(host); + openFilesForSession([file1], session); const projectService = session.getProjectService(); // HTML file will not be included in any projects yet - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); - const configuredProj = ts.projectSystem.configuredProjectAt(projectService, 0); - ts.projectSystem.checkProjectActualFiles(configuredProj, [file1.path, config.path]); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + const configuredProj = configuredProjectAt(projectService, 0); + checkProjectActualFiles(configuredProj, [file1.path, config.path]); // Specify .html extension as mixed content - const extraFileExtensions = [{ extension: ".html", scriptKind: ts.ScriptKind.JS, isMixedContent: true }]; - const configureHostRequest = ts.projectSystem.makeSessionRequest(ts.projectSystem.CommandNames.Configure, { extraFileExtensions }); + const extraFileExtensions = [{ extension: ".html", scriptKind: ScriptKind.JS, isMixedContent: true }]; + const configureHostRequest = makeSessionRequest(projectSystem.CommandNames.Configure, { extraFileExtensions }); session.executeCommand(configureHostRequest); // The configured project should now be updated to include html file - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); - assert.strictEqual(ts.projectSystem.configuredProjectAt(projectService, 0), configuredProj, "Same configured project should be updated"); - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [file1.path, file2.path, config.path]); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + assert.strictEqual(configuredProjectAt(projectService, 0), configuredProj, "Same configured project should be updated"); + checkProjectActualFiles(configuredProjectAt(projectService, 0), [file1.path, file2.path, config.path]); // Open HTML file - projectService.applyChangesInOpenFiles(ts.singleIterator({ + projectService.applyChangesInOpenFiles(singleIterator({ fileName: file2.path, hasMixedContent: true, - scriptKind: ts.ScriptKind.JS, + scriptKind: ScriptKind.JS, content: `var hello = "hello";` })); // Now HTML file is included in the project - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [file1.path, file2.path, config.path]); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkProjectActualFiles(configuredProjectAt(projectService, 0), [file1.path, file2.path, config.path]); // Check identifiers defined in HTML content are available in .ts file - const project = ts.projectSystem.configuredProjectAt(projectService, 0); - let completions = project.getLanguageService().getCompletionsAtPosition(file1.path, 1, ts.emptyOptions); - assert(completions && ts.some(completions.entries, e => e.name === "hello"), `expected entry hello to be in completion list`); + const project = configuredProjectAt(projectService, 0); + let completions = project.getLanguageService().getCompletionsAtPosition(file1.path, 1, emptyOptions); + assert(completions && some(completions.entries, e => e.name === "hello"), `expected entry hello to be in completion list`); // Close HTML file projectService.applyChangesInOpenFiles( @@ -713,11 +740,11 @@ describe("unittests:: tsserver:: Projects", () => { /*closedFiles*/[file2.path]); // HTML file is still included in project - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); - ts.projectSystem.checkProjectActualFiles(ts.projectSystem.configuredProjectAt(projectService, 0), [file1.path, file2.path, config.path]); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkProjectActualFiles(configuredProjectAt(projectService, 0), [file1.path, file2.path, config.path]); // Check identifiers defined in HTML content are not available in .ts file - completions = project.getLanguageService().getCompletionsAtPosition(file1.path, 5, ts.emptyOptions); + completions = project.getLanguageService().getCompletionsAtPosition(file1.path, 5, emptyOptions); assert(completions && completions.entries[0].name !== "hello", `unexpected hello entry in completion list`); }); @@ -737,20 +764,20 @@ describe("unittests:: tsserver:: Projects", () => { content: JSON.stringify({ compilerOptions: { allowJs: true } }) }; - let host = ts.projectSystem.createServerHost([file1, file2, config1, ts.projectSystem.libFile], { executingFilePath: ts.combinePaths(ts.getDirectoryPath(ts.projectSystem.libFile.path), "tsc.js") }); - let session = ts.projectSystem.createSession(host); + let host = createServerHost([file1, file2, config1, libFile], { executingFilePath: combinePaths(getDirectoryPath(libFile.path), "tsc.js") }); + let session = createSession(host); // Specify .html extension as mixed content in a configure host request - const extraFileExtensions = [{ extension: ".html", scriptKind: ts.ScriptKind.JS, isMixedContent: true }]; - const configureHostRequest = ts.projectSystem.makeSessionRequest(ts.projectSystem.CommandNames.Configure, { extraFileExtensions }); + const extraFileExtensions = [{ extension: ".html", scriptKind: ScriptKind.JS, isMixedContent: true }]; + const configureHostRequest = makeSessionRequest(projectSystem.CommandNames.Configure, { extraFileExtensions }); session.executeCommand(configureHostRequest); - ts.projectSystem.openFilesForSession([file1], session); + openFilesForSession([file1], session); let projectService = session.getProjectService(); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); - let diagnostics = ts.projectSystem.configuredProjectAt(projectService, 0).getLanguageService().getCompilerOptionsDiagnostics(); + let diagnostics = configuredProjectAt(projectService, 0).getLanguageService().getCompilerOptionsDiagnostics(); assert.deepEqual(diagnostics, []); // #2. Ensure no errors when allowJs is false @@ -759,17 +786,17 @@ describe("unittests:: tsserver:: Projects", () => { content: JSON.stringify({ compilerOptions: { allowJs: false } }) }; - host = ts.projectSystem.createServerHost([file1, file2, config2, ts.projectSystem.libFile], { executingFilePath: ts.combinePaths(ts.getDirectoryPath(ts.projectSystem.libFile.path), "tsc.js") }); - session = ts.projectSystem.createSession(host); + host = createServerHost([file1, file2, config2, libFile], { executingFilePath: combinePaths(getDirectoryPath(libFile.path), "tsc.js") }); + session = createSession(host); session.executeCommand(configureHostRequest); - ts.projectSystem.openFilesForSession([file1], session); + openFilesForSession([file1], session); projectService = session.getProjectService(); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); - diagnostics = ts.projectSystem.configuredProjectAt(projectService, 0).getLanguageService().getCompilerOptionsDiagnostics(); + diagnostics = configuredProjectAt(projectService, 0).getLanguageService().getCompilerOptionsDiagnostics(); assert.deepEqual(diagnostics, []); // #3. Ensure no errors when compiler options aren't specified @@ -778,17 +805,17 @@ describe("unittests:: tsserver:: Projects", () => { content: JSON.stringify({}) }; - host = ts.projectSystem.createServerHost([file1, file2, config3, ts.projectSystem.libFile], { executingFilePath: ts.combinePaths(ts.getDirectoryPath(ts.projectSystem.libFile.path), "tsc.js") }); - session = ts.projectSystem.createSession(host); + host = createServerHost([file1, file2, config3, libFile], { executingFilePath: combinePaths(getDirectoryPath(libFile.path), "tsc.js") }); + session = createSession(host); session.executeCommand(configureHostRequest); - ts.projectSystem.openFilesForSession([file1], session); + openFilesForSession([file1], session); projectService = session.getProjectService(); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); - diagnostics = ts.projectSystem.configuredProjectAt(projectService, 0).getLanguageService().getCompilerOptionsDiagnostics(); + diagnostics = configuredProjectAt(projectService, 0).getLanguageService().getCompilerOptionsDiagnostics(); assert.deepEqual(diagnostics, []); // #4. Ensure no errors when files are explicitly specified in tsconfig @@ -797,17 +824,17 @@ describe("unittests:: tsserver:: Projects", () => { content: JSON.stringify({ compilerOptions: { allowJs: true }, files: [file1.path, file2.path] }) }; - host = ts.projectSystem.createServerHost([file1, file2, config4, ts.projectSystem.libFile], { executingFilePath: ts.combinePaths(ts.getDirectoryPath(ts.projectSystem.libFile.path), "tsc.js") }); - session = ts.projectSystem.createSession(host); + host = createServerHost([file1, file2, config4, libFile], { executingFilePath: combinePaths(getDirectoryPath(libFile.path), "tsc.js") }); + session = createSession(host); session.executeCommand(configureHostRequest); - ts.projectSystem.openFilesForSession([file1], session); + openFilesForSession([file1], session); projectService = session.getProjectService(); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); - diagnostics = ts.projectSystem.configuredProjectAt(projectService, 0).getLanguageService().getCompilerOptionsDiagnostics(); + diagnostics = configuredProjectAt(projectService, 0).getLanguageService().getCompilerOptionsDiagnostics(); assert.deepEqual(diagnostics, []); // #4. Ensure no errors when files are explicitly excluded in tsconfig @@ -816,17 +843,17 @@ describe("unittests:: tsserver:: Projects", () => { content: JSON.stringify({ compilerOptions: { allowJs: true }, exclude: [file2.path] }) }; - host = ts.projectSystem.createServerHost([file1, file2, config5, ts.projectSystem.libFile], { executingFilePath: ts.combinePaths(ts.getDirectoryPath(ts.projectSystem.libFile.path), "tsc.js") }); - session = ts.projectSystem.createSession(host); + host = createServerHost([file1, file2, config5, libFile], { executingFilePath: combinePaths(getDirectoryPath(libFile.path), "tsc.js") }); + session = createSession(host); session.executeCommand(configureHostRequest); - ts.projectSystem.openFilesForSession([file1], session); + openFilesForSession([file1], session); projectService = session.getProjectService(); - ts.projectSystem.checkNumberOfProjects(projectService, { configuredProjects: 1 }); + checkNumberOfProjects(projectService, { configuredProjects: 1 }); - diagnostics = ts.projectSystem.configuredProjectAt(projectService, 0).getLanguageService().getCompilerOptionsDiagnostics(); + diagnostics = configuredProjectAt(projectService, 0).getLanguageService().getCompilerOptionsDiagnostics(); assert.deepEqual(diagnostics, []); }); @@ -839,21 +866,21 @@ describe("unittests:: tsserver:: Projects", () => { path: "/a/b/f2.ts", content: "export let x = 1" }; - const host = ts.projectSystem.createServerHost([file1, file2]); - const projectService = ts.projectSystem.createProjectService(host); + const host = createServerHost([file1, file2]); + const projectService = createProjectService(host); projectService.openClientFile(file1.path); projectService.openClientFile(file2.path); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); projectService.applyChangesInOpenFiles( /*openFiles*/ undefined, - /*changedFiles*/ts.singleIterator({ fileName: file1.path, changes: ts.singleIterator({ span: ts.createTextSpan(0, file1.path.length), newText: "let y = 1" }) }), + /*changedFiles*/singleIterator({ fileName: file1.path, changes: singleIterator({ span: createTextSpan(0, file1.path.length), newText: "let y = 1" }) }), /*closedFiles*/ undefined); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 1 }); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); projectService.ensureInferredProjectsUpToDate_TestOnly(); - ts.projectSystem.checkNumberOfProjects(projectService, { inferredProjects: 2 }); + checkNumberOfProjects(projectService, { inferredProjects: 2 }); }); it("files with mixed content are handled correctly", () => { @@ -861,31 +888,31 @@ describe("unittests:: tsserver:: Projects", () => { path: "/a/b/f1.html", content: `