diff --git a/src/compat/deprecations.ts b/src/compat/deprecations.ts index 940f290e679..30472b93aa2 100644 --- a/src/compat/deprecations.ts +++ b/src/compat/deprecations.ts @@ -1933,13 +1933,12 @@ namespace ts { * NOTE: It is unsafe to change any properties of a `Node` that relate to its AST children, as those changes won't be * captured with respect to transformations. * - * @deprecated Use `factory.cloneNode` instead and set `pos`, `end`, and `parent` as needed. + * @deprecated Use `factory.cloneNode` instead and use `setCommentRange` or `setSourceMapRange` and avoid setting `parent`. */ export function getMutableClone(node: T): T { const clone = factory.cloneNode(node); - clone.pos = node.pos; - clone.end = node.end; - clone.parent = node.parent; + setTextRange(clone, node); + setParent(clone, node.parent); return clone; } diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index f688ab4673d..58071d2bc80 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -17,7 +17,8 @@ namespace ts { export function getModuleInstanceState(node: ModuleDeclaration, visited?: Map): 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 - setParentPointers(node, node.body); + setParent(node.body, node); + setParentRecursive(node.body, /*incremental*/ false); } return node.body ? getModuleInstanceStateCached(node.body, visited) : ModuleInstanceState.Instantiated; } @@ -114,7 +115,8 @@ namespace ts { for (const statement of statements) { if (nodeHasName(statement, name)) { if (!statement.parent) { - setParentPointers(p, statement); + setParent(statement, p); + setParentRecursive(statement, /*incremental*/ false); } const state = getModuleInstanceStateCached(statement, visited); if (found === undefined || state > found) { @@ -467,7 +469,7 @@ namespace ts { 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 (isNamedDeclaration(node)) { - node.name.parent = node; + setParent(node.name, node); } // Report errors every position with duplicate declaration @@ -1484,9 +1486,10 @@ namespace ts { } function bindJSDocTypeAlias(node: JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag) { - node.tagName.parent = node; + setParent(node.tagName, node); if (node.kind !== SyntaxKind.JSDocEnumTag && node.fullName) { - setParentPointers(node, node.fullName); + setParent(node.fullName, node); + setParentRecursive(node.fullName, /*incremental*/ false); } } @@ -2174,7 +2177,7 @@ namespace ts { if (!node) { return; } - node.parent = parent; + setParent(node, parent); const saveInStrictMode = inStrictMode; // Even though in the AST the jsdoc @typedef node belongs to the current node, @@ -2233,7 +2236,8 @@ namespace ts { } else { for (const j of node.jsDoc!) { - setParentPointers(node, j); + setParent(j, node); + setParentRecursive(j, /*incremental*/ false); } } } @@ -2726,8 +2730,8 @@ namespace ts { /** For `x.prototype = { p, ... }`, declare members p,... if `x` is function/class/{}, or not declared. */ function bindPrototypeAssignment(node: BindableStaticPropertyAssignmentExpression) { - node.left.parent = node; - node.right.parent = node; + setParent(node.left, node); + setParent(node.right, node); bindPropertyAssignment(node.left.expression, node.left, /*isPrototypeProperty*/ false, /*containerIsClass*/ true); } @@ -2751,9 +2755,9 @@ namespace ts { const constructorFunction = classPrototype.expression; // Fix up parent pointers since we're going to use these nodes before we bind into them - lhs.parent = parent; - constructorFunction.parent = classPrototype; - classPrototype.parent = lhs; + setParent(constructorFunction, classPrototype); + setParent(classPrototype, lhs); + setParent(lhs, parent); bindPropertyAssignment(constructorFunction, lhs, /*isPrototypeProperty*/ true, /*containerIsClass*/ true); } @@ -2772,8 +2776,8 @@ namespace ts { return; } // Fix up parent pointers since we're going to use these nodes before we bind into them - node.left.parent = node; - node.right.parent = node; + 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; @@ -2797,7 +2801,7 @@ namespace ts { * Also works for expression statements preceded by JSDoc, like / ** @type number * / x.y; */ function bindStaticPropertyAssignment(node: BindableStaticAccessExpression) { - node.expression.parent = node; + setParent(node.expression, node); bindPropertyAssignment(node.expression, node, /*isPrototypeProperty*/ false, /*containerIsClass*/ false); } @@ -2979,7 +2983,7 @@ namespace ts { const symbolExport = symbol.exports!.get(prototypeSymbol.escapedName); if (symbolExport) { if (node.name) { - node.name.parent = node; + setParent(node.name, node); } file.bindDiagnostics.push(createDiagnosticForNode(symbolExport.declarations[0], Diagnostics.Duplicate_identifier_0, symbolName(prototypeSymbol))); } @@ -3241,13 +3245,4 @@ namespace ts { } return container.symbol && container.symbol.exports && container.symbol.exports.get(name); } - - /** - * "Binds" JSDoc nodes in TypeScript code. - * Since we will never create symbols for JSDoc, we just set parent pointers instead. - */ - function setParentPointers(parent: Node, child: Node): void { - child.parent = parent; - forEachChild(child, grandchild => setParentPointers(child, grandchild)); - } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4450d7b15a1..ce2d09f9d0e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5616,7 +5616,7 @@ namespace ts { // Add a namespace // Create namespace as non-synthetic so it is usable as an enclosing declaration let fakespace = parseNodeFactory.createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, factory.createIdentifier(localName), factory.createModuleBlock([]), NodeFlags.Namespace); - fakespace.parent = enclosingDeclaration as SourceFile | NamespaceDeclaration; + setParent(fakespace, enclosingDeclaration as SourceFile | NamespaceDeclaration); fakespace.locals = createSymbolTable(props); fakespace.symbol = props[0].parent!; @@ -6775,8 +6775,8 @@ namespace ts { if (propName) { const literal = setTextRange(parseNodeFactory.createStringLiteral(propName), node); const result = setTextRange(parseNodeFactory.createElementAccess(parentAccess, literal), node); - literal.parent = result; - result.parent = node; + setParent(literal, result); + setParent(result, node); result.flowNode = parentAccess.flowNode; return result; } @@ -20313,9 +20313,10 @@ namespace ts { const unionTypes = (funcTypeNode.type).types; if (unionTypes && unionTypes[unionTypes.length - 1].kind === SyntaxKind.UndefinedKeyword) { // TODO(rbuckton): Does this need to be parented? - const parenedFuncType = setParent(setTextRange(factory.cloneNode(funcTypeNode), funcTypeNode), funcTypeNode.parent); // Highlight to the end of the second to last constituent of the union - parenedFuncType.end = unionTypes[unionTypes.length - 2].end; + const parenedFuncType = setParent( + setTextRangePosEnd(factory.cloneNode(funcTypeNode), funcTypeNode.pos, unionTypes[unionTypes.length - 2].end), + funcTypeNode.parent); addRelatedInfo(diag, createDiagnosticForNode(parenedFuncType, Diagnostics.Did_you_mean_to_parenthesize_this_function_type)); } } @@ -22371,7 +22372,7 @@ namespace ts { (getArrayLiteralTupleTypeIfApplicable(childrenTypes, childrenContextualType, /*hasRestElement*/ false) || createArrayType(getUnionType(childrenTypes))); // Fake up a property declaration for the children childrenPropSymbol.valueDeclaration = factory.createPropertySignature(/*modifiers*/ undefined, unescapeLeadingUnderscores(jsxChildrenPropertyName), /*questionToken*/ undefined, /*type*/ undefined); - childrenPropSymbol.valueDeclaration.parent = attributes; + setParent(childrenPropSymbol.valueDeclaration, attributes); childrenPropSymbol.valueDeclaration.symbol = childrenPropSymbol; const childPropMap = createSymbolTable(); childPropMap.set(jsxChildrenPropertyName, childrenPropSymbol); @@ -23985,7 +23986,7 @@ namespace ts { function createSyntheticExpression(parent: Node, type: Type, isSpread?: boolean) { const result = parseNodeFactory.createSyntheticExpression(type, isSpread); setTextRange(result, parent); - result.parent = parent; + setParent(result, parent); return result; } @@ -24181,11 +24182,12 @@ namespace ts { spanArray = factory.createNodeArray(args.slice(max)); } - spanArray.pos = first(spanArray).pos; - spanArray.end = last(spanArray).end; - if (spanArray.end === spanArray.pos) { - spanArray.end++; + const pos = first(spanArray).pos; + let end = last(spanArray).end; + if (end === pos) { + end++; } + setTextRangePosEnd(spanArray, pos, end); const diagnostic = createDiagnosticForNodeArray( getSourceFileOfNode(node), spanArray, error, paramRange, argCount); return related ? addRelatedInfo(diagnostic, related) : diagnostic; @@ -32044,8 +32046,8 @@ namespace ts { function isPropertyInitializedInConstructor(propName: Identifier, propType: Type, constructor: ConstructorDeclaration) { const reference = factory.createPropertyAccess(factory.createThis(), propName); - reference.expression.parent = reference; - reference.parent = constructor; + setParent(reference.expression, reference); + setParent(reference, constructor); reference.flowNode = constructor.returnFlowNode; const flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType)); return !(getFalsyFlags(flowType) & TypeFlags.Undefined); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 0a221f220ca..c4f908b42a8 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -681,7 +681,7 @@ namespace ts { const statements = prologueInfo?.directives.map(directive => { const literal = setTextRange(factory.createStringLiteral(directive.expression.text), directive.expression); const statement = setTextRange(factory.createExpressionStatement(literal), directive); - literal.parent = statement; + setParent(literal, statement); return statement; }); const eofToken = factory.createToken(SyntaxKind.EndOfFileToken); @@ -692,14 +692,10 @@ namespace ts { !host.useCaseSensitiveFileNames() ); sourceFile.text = prologueInfo?.text ?? ""; - sourceFile.pos = 0; - sourceFile.end = prologueInfo?.text.length ?? 0; - for (const statement of sourceFile.statements) { - statement.parent = sourceFile; - } - eofToken.pos = sourceFile.end; - eofToken.end = sourceFile.end; - eofToken.parent = sourceFile; + setTextRangePosWidth(sourceFile, 0, prologueInfo?.text.length ?? 0); + setEachParent(sourceFile.statements, sourceFile); + setTextRangePosWidth(eofToken, sourceFile.end, 0); + setParent(eofToken, sourceFile); return sourceFile; }); } diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index 6e4743448e6..1d67d380d2c 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -525,8 +525,7 @@ namespace ts { // 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); - array.pos = -1; - array.end = -1; + setTextRangePosEnd(array, -1, -1); if (hasTrailingComma) { array.hasTrailingComma = hasTrailingComma; } @@ -3942,8 +3941,8 @@ namespace ts { } // @api - function createJSDocTemplateTag(tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[]): JSDocTemplateTag { - const node = createBaseJSDocTag(SyntaxKind.JSDocTemplateTag, tagName || createIdentifier("template"), /*comment*/ undefined); + function createJSDocTemplateTag(tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment?: string): JSDocTemplateTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocTemplateTag, tagName || createIdentifier("template"), comment); setChild(node, node.constraint = constraint); setChildren(node, node.typeParameters = createNodeArray(typeParameters)); return finishJSDoc(node); @@ -3973,8 +3972,8 @@ namespace ts { } // @api - function createJSDocThisTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression): JSDocThisTag { - const node = createBaseJSDocTag(SyntaxKind.JSDocThisTag, tagName || createIdentifier("this"), /*comment*/ undefined); + function createJSDocThisTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string): JSDocThisTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocThisTag, tagName || createIdentifier("this"), comment); setChild(node, node.typeExpression = typeExpression); return finishJSDoc(node); } @@ -4006,8 +4005,8 @@ namespace ts { } // @api - function createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"]): JSDocAugmentsTag { - const node = createBaseJSDocTag(SyntaxKind.JSDocAugmentsTag, tagName || createIdentifier("augments"), /*comment*/ undefined); + function createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment?: string): JSDocAugmentsTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocAugmentsTag, tagName || createIdentifier("augments"), comment); setChild(node, node.class = className); return finishJSDoc(node); } @@ -4022,21 +4021,21 @@ namespace ts { } // @api - function createJSDocClassTag(tagName: Identifier | undefined): JSDocClassTag { - const node = createBaseJSDocTag(SyntaxKind.JSDocClassTag, tagName || createIdentifier("class"), /*comment*/ undefined); + function createJSDocClassTag(tagName: Identifier | undefined, comment?: string): JSDocClassTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocClassTag, tagName || createIdentifier("class"), comment); return finishJSDoc(node); } // @api - function createJSDocEnumTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression): JSDocEnumTag { - const node = createBaseJSDocTag(SyntaxKind.JSDocEnumTag, tagName || createIdentifier("enum"), /*comment*/ undefined); + function createJSDocEnumTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string): JSDocEnumTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocEnumTag, tagName || createIdentifier("enum"), comment); setChild(node, node.typeExpression = typeExpression); return finishJSDoc(node); } // @api - function createJSDocUnknownTag(tagName: Identifier): JSDocUnknownTag { - const node = createBaseJSDocTag(SyntaxKind.JSDocTag, tagName, /*comment*/ undefined); + function createJSDocUnknownTag(tagName: Identifier, comment?: string): JSDocUnknownTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocTag, tagName, comment); return finishJSDoc(node); } @@ -5803,8 +5802,7 @@ namespace ts { if (!texts) { const textNode = factory.createUnparsedTextLike(/*data*/ undefined, /*internal*/ false); - textNode.pos = 0; - textNode.end = typeof length === "function" ? length() : length; + setTextRangePosWidth(textNode, 0, typeof length === "function" ? length() : length); texts = [textNode]; } diff --git a/src/compiler/factory/utilities.ts b/src/compiler/factory/utilities.ts index f0acbf8b22e..3d3d3cc52ba 100644 --- a/src/compiler/factory/utilities.ts +++ b/src/compiler/factory/utilities.ts @@ -30,7 +30,7 @@ namespace ts { 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 - react.parent = getParseTreeNode(parent)!; + setParent(react, getParseTreeNode(parent)); return react; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 92b71adb1e7..a301ad1d7c3 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -620,22 +620,18 @@ namespace ts { const factory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules | NodeFactoryFlags.NoNodeConverters, baseNodeFactory, { onSetChild(parent, child) { if (setParentNodes) { - child.parent = parent; + setParent(child, parent); } }, onSetChildren(parent, children) { if (setParentNodes) { - for (const child of children) { - child.parent = parent; - } + setEachParent(children, parent); } }, onFinishNode(node) { if (setParentNodes) { if (hasJSDocNodes(node)) { - for (const jsDoc of node.jsDoc!) { - jsDoc.parent = node; - } + setEachParent(node.jsDoc, node); } } }, @@ -965,39 +961,14 @@ namespace ts { // 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. - - let parent: Node = rootNode; - forEachChild(rootNode, visitNode); - return; - - function visitNode(n: Node): void { - // walk down setting parents that differ from the parent we think it should be. This - // allows us to quickly bail out of setting parents for subtrees during incremental - // parsing - if (n.parent !== parent) { - n.parent = parent; - - const saveParent = parent; - parent = n; - forEachChild(n, visitNode); - if (hasJSDocNodes(n)) { - for (const jsDoc of n.jsDoc!) { - jsDoc.parent = n; - parent = jsDoc; - forEachChild(jsDoc, visitNode); - } - } - parent = saveParent; - } - } + setParentRecursive(rootNode, /*incremental*/ true); } function createSourceFile(fileName: string, languageVersion: ScriptTarget, scriptKind: ScriptKind, isDeclarationFile: boolean, statements: readonly Statement[], endOfFileToken: EndOfFileToken, flags: NodeFlags): 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 const sourceFile = factory.createSourceFile(statements, endOfFileToken, flags); - sourceFile.pos = 0; - sourceFile.end = sourceText.length; + setTextRangePosWidth(sourceFile, 0, sourceText.length); sourceFile.text = sourceText; sourceFile.bindDiagnostics = []; sourceFile.bindSuggestionDiagnostics = undefined; @@ -1399,15 +1370,12 @@ namespace ts { function createNodeArray(elements: T[], pos: number, end?: number): NodeArray { const array = factory.createNodeArray(elements, /*hasTrailingComma*/ undefined); - array.pos = pos; - array.end = end === undefined ? scanner.getStartPos() : end; + setTextRangePosEnd(array, pos, end ?? scanner.getStartPos()); return array; } function finishNode(node: T, pos: number, end?: number): T { - node.pos = pos; - node.end = end === undefined ? scanner.getStartPos() : end; - + setTextRangePosEnd(node, pos, end ?? scanner.getStartPos()); if (contextFlags) { (node as Mutable).flags |= contextFlags; } @@ -3036,8 +3004,7 @@ namespace ts { const type = parseType(); if (!(contextFlags & NodeFlags.JSDoc) && isJSDocNullableType(type) && type.pos === type.type.pos) { const node = factory.createOptionalTypeNode(type.type); - node.pos = type.pos; - node.end = type.end; + setTextRange(node, type); (node as Mutable).flags = type.flags; return node; } @@ -4479,7 +4446,7 @@ namespace ts { if (invalidElement) { parseErrorAtCurrentToken(Diagnostics.JSX_expressions_must_have_one_parent_element); const operatorToken = createMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false); - operatorToken.pos = operatorToken.end = invalidElement.pos; + setTextRangePosWidth(operatorToken, invalidElement.pos, 0); return finishNode(factory.createBinary(result, operatorToken as Token, invalidElement), pos); } } @@ -5723,7 +5690,7 @@ namespace ts { // 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(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected); - missing.pos = pos; + setTextRangePos(missing, pos); missing.decorators = decorators; missing.modifiers = modifiers; return missing; @@ -6736,9 +6703,7 @@ namespace ts { const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode; const comment = doInsideOfContext(NodeFlags.JSDoc, () => parseJSDocCommentWorker(start, length)); - if (comment) { - comment.parent = parent; - } + setParent(comment, parent); if (contextFlags & NodeFlags.JavaScriptFile) { if (!jsDocDiagnostics) { @@ -6947,21 +6912,21 @@ namespace ts { let tag: JSDocTag | undefined; switch (tagName.escapedText) { case "author": - tag = parseAuthorTag(start, tagName, margin); + tag = parseAuthorTag(start, tagName, margin, indentText); break; case "augments": case "extends": - tag = parseAugmentsTag(start, tagName); + tag = parseAugmentsTag(start, tagName, margin, indentText); break; case "class": case "constructor": - tag = parseClassTag(start, tagName); + tag = parseClassTag(start, tagName, margin, indentText); break; case "this": - tag = parseThisTag(start, tagName); + tag = parseThisTag(start, tagName, margin, indentText); break; case "enum": - tag = parseEnumTag(start, tagName); + tag = parseEnumTag(start, tagName, margin, indentText); break; case "arg": case "argument": @@ -6969,35 +6934,35 @@ namespace ts { return parseParameterOrPropertyTag(start, tagName, PropertyLikeParse.Parameter, margin); case "return": case "returns": - tag = parseReturnTag(start, tagName); + tag = parseReturnTag(start, tagName, margin, indentText); break; case "template": - tag = parseTemplateTag(start, tagName); + tag = parseTemplateTag(start, tagName, margin, indentText); break; case "type": - tag = parseTypeTag(start, tagName); + tag = parseTypeTag(start, tagName, margin, indentText); break; case "typedef": - tag = parseTypedefTag(start, tagName, margin); + tag = parseTypedefTag(start, tagName, margin, indentText); break; case "callback": - tag = parseCallbackTag(start, tagName, margin); + tag = parseCallbackTag(start, tagName, margin, indentText); break; default: - tag = parseUnknownTag(start, tagName); + tag = parseUnknownTag(start, tagName, margin, indentText); break; } - - if (!tag.comment) { - // some tags, like typedef and callback, have already parsed their comments earlier - if (!indentText) { - margin += tag.end - tag.pos; - } - tag.comment = parseTagComments(margin, indentText.slice(margin)); - } return tag; } + function parseTrailingTagComments(pos: number, end: number, margin: number, indentText: string) { + // some tags, like typedef and callback, have already parsed their comments earlier + if (!indentText) { + margin += end - pos; + } + return parseTagComments(margin, indentText.slice(margin)); + } + function parseTagComments(indent: number, initialMargin?: string): string | undefined { const comments: string[] = []; let state = JSDocState.BeginningOfLine; @@ -7091,8 +7056,9 @@ namespace ts { return comments.length === 0 ? undefined : comments.join(""); } - function parseUnknownTag(start: number, tagName: Identifier) { - return finishNode(factory.createJSDocUnknownTag(tagName), start); + function parseUnknownTag(start: number, tagName: Identifier, indent: number, indentText: string) { + const end = getNodePos(); + return finishNode(factory.createJSDocUnknownTag(tagName, parseTrailingTagComments(start, end, indent, indentText)), start, end); } function addTag(tag: JSDocTag | undefined): void { @@ -7191,28 +7157,32 @@ namespace ts { } } - function parseReturnTag(start: number, tagName: Identifier): JSDocReturnTag { + 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), start); + const end = getNodePos(); + return finishNode(factory.createJSDocReturnTag(tagName, typeExpression, parseTrailingTagComments(start, end, indent, indentText)), start, end); } - function parseTypeTag(start: number, tagName: Identifier): JSDocTypeTag { + 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); - return finishNode(factory.createJSDocTypeTag(tagName, typeExpression), start); + const end = getNodePos(); + const comments = indent !== undefined && indentText !== undefined ? parseTrailingTagComments(start, end, indent, indentText) : undefined; + return finishNode(factory.createJSDocTypeTag(tagName, typeExpression, comments), start, end); } - function parseAuthorTag(start: number, tagName: Identifier, indent: number): JSDocAuthorTag { + function parseAuthorTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocAuthorTag { const authorInfoWithEmail = tryParse(() => tryParseAuthorNameAndEmail()); if (!authorInfoWithEmail) { - return finishNode(factory.createJSDocAuthorTag(tagName), start); + const end = getNodePos(); + return finishNode(factory.createJSDocAuthorTag(tagName, parseTrailingTagComments(start, end, indent, indentText)), start, end); } let comments = authorInfoWithEmail; @@ -7268,9 +7238,10 @@ namespace ts { } } - function parseAugmentsTag(start: number, tagName: Identifier): JSDocAugmentsTag { + function parseAugmentsTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocAugmentsTag { const className = parseExpressionWithTypeArgumentsForAugments(); - return finishNode(factory.createJSDocAugmentsTag(tagName, className), start); + const end = getNodePos(); + return finishNode(factory.createJSDocAugmentsTag(tagName, className, parseTrailingTagComments(start, end, margin, indentText)), start, end); } function parseExpressionWithTypeArgumentsForAugments(): ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression } { @@ -7296,29 +7267,32 @@ namespace ts { return node; } - function parseClassTag(start: number, tagName: Identifier): JSDocClassTag { - return finishNode(factory.createJSDocClassTag(tagName), start); + function parseClassTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocClassTag { + const end = getNodePos(); + return finishNode(factory.createJSDocClassTag(tagName, parseTrailingTagComments(start, end, margin, indentText)), start, end); } - function parseThisTag(start: number, tagName: Identifier): JSDocThisTag { + function parseThisTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocThisTag { const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); skipWhitespace(); - return finishNode(factory.createJSDocThisTag(tagName, typeExpression), start); + const end = getNodePos(); + return finishNode(factory.createJSDocThisTag(tagName, typeExpression, parseTrailingTagComments(start, end, margin, indentText)), start, end); } - function parseEnumTag(start: number, tagName: Identifier): JSDocEnumTag { + function parseEnumTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocEnumTag { const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); skipWhitespace(); - return finishNode(factory.createJSDocEnumTag(tagName, typeExpression), start); + const end = getNodePos(); + return finishNode(factory.createJSDocEnumTag(tagName, typeExpression, parseTrailingTagComments(start, end, margin, indentText)), start, end); } - function parseTypedefTag(start: number, tagName: Identifier, indent: number): JSDocTypedefTag { + function parseTypedefTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocTypedefTag { let typeExpression: JSDocTypeExpression | JSDocTypeLiteral | undefined = tryParseTypeExpression(); skipWhitespaceOrAsterisk(); const fullName = parseJSDocTypeNameWithNamespace(); skipWhitespace(); - const comment = parseTagComments(indent); + let comment = parseTagComments(indent); let end: number | undefined; if (!typeExpression || isObjectOrObjectArrayTypeReference(typeExpression.type)) { @@ -7350,10 +7324,17 @@ namespace ts { } } - const typedefTag = factory.createJSDocTypedefTag(tagName, typeExpression, fullName, comment); - // Only include the characters between the name end and the next token if a comment was actually parsed out - otherwise it's just whitespace - return finishNode(typedefTag, start, end || typedefTag.comment !== undefined ? scanner.getStartPos() : (typedefTag.fullName || typedefTag.typeExpression || typedefTag.tagName).end); + end = end || comment !== undefined ? + getNodePos() : + (fullName ?? typeExpression ?? tagName).end; + + if (!comment) { + comment = parseTrailingTagComments(start, end, indent, indentText); + } + + const typedefTag = factory.createJSDocTypedefTag(tagName, typeExpression, fullName, comment); + return finishNode(typedefTag, start, end); } function parseJSDocTypeNameWithNamespace(nested?: boolean) { @@ -7391,10 +7372,10 @@ namespace ts { return createNodeArray(parameters || [], pos); } - function parseCallbackTag(start: number, tagName: Identifier, indent: number): JSDocCallbackTag { + function parseCallbackTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocCallbackTag { const fullName = parseJSDocTypeNameWithNamespace(); skipWhitespace(); - const comment = parseTagComments(indent); + let comment = parseTagComments(indent); const parameters = parseCallbackTagParameters(indent); const returnTag = tryParse(() => { if (parseOptionalJsdoc(SyntaxKind.AtToken)) { @@ -7405,7 +7386,11 @@ namespace ts { } }); const typeExpression = finishNode(factory.createJSDocSignature(/*typeParameters*/ undefined, parameters, returnTag), start); - return finishNode(factory.createJSDocCallbackTag(tagName, typeExpression, fullName, comment), start); + const end = getNodePos(); + if (!comment) { + comment = parseTrailingTagComments(start, end, indent, indentText); + } + return finishNode(factory.createJSDocCallbackTag(tagName, typeExpression, fullName, comment), start, end); } function escapedTextsEqual(a: EntityName, b: EntityName): boolean { @@ -7507,7 +7492,7 @@ namespace ts { return createNodeArray(typeParameters, pos); } - function parseTemplateTag(start: number, tagName: Identifier): 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 @@ -7521,7 +7506,8 @@ namespace ts { // TODO: Consider only parsing a single type parameter if there is a constraint. const constraint = token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined; const typeParameters = parseTemplateTagTypeParameters(); - return finishNode(factory.createJSDocTemplateTag(tagName, constraint, typeParameters), start); + const end = getNodePos(); + return finishNode(factory.createJSDocTemplateTag(tagName, constraint, typeParameters, parseTrailingTagComments(start, end, indent, indentText)), start, end); } function parseOptionalJsdoc(t: JSDocSyntaxKind): boolean { @@ -7671,8 +7657,7 @@ namespace ts { node._children = undefined; } - node.pos += delta; - node.end += delta; + setTextRangePosEnd(node, node.pos + delta, node.end + delta); if (aggressiveChecks && shouldCheckNode(node)) { Debug.assert(text === newText.substring(node.pos, node.end)); @@ -7689,8 +7674,7 @@ namespace ts { function visitArray(array: IncrementalNodeArray) { array._children = undefined; - array.pos += delta; - array.end += delta; + setTextRangePosEnd(array, array.pos + delta, array.end + delta); for (const node of array) { visitNode(node); @@ -7745,7 +7729,7 @@ namespace ts { // // The element will keep its position if possible. Or Move backward to the new-end // if it's in the 'Y' range. - element.pos = Math.min(element.pos, changeRangeNewEnd); + const pos = Math.min(element.pos, changeRangeNewEnd); // If the 'end' is after the change range, then we always adjust it by the delta // amount. However, if the end is in the change range, then how we adjust it @@ -7767,21 +7751,20 @@ namespace ts { // However any element that ended after that will have their pos adjusted to be // at the end of the new range. i.e. any node that ended in the 'Y' range will // be adjusted to have their end at the end of the 'Z' range. - if (element.end >= changeRangeOldEnd) { + const end = element.end >= changeRangeOldEnd ? // Element ends after the change range. Always adjust the end pos. - element.end += delta; - } - else { + element.end + delta : // Element ends in the change range. The element will keep its position if // possible. Or Move backward to the new-end if it's in the 'Y' range. - element.end = Math.min(element.end, changeRangeNewEnd); + Math.min(element.end, changeRangeNewEnd); + + Debug.assert(pos <= end); + if (element.parent) { + Debug.assert(pos >= element.parent.pos); + Debug.assert(end <= element.parent.end); } - Debug.assert(element.pos <= element.end); - if (element.parent) { - Debug.assert(element.pos >= element.parent.pos); - Debug.assert(element.end <= element.parent.end); - } + setTextRangePosEnd(element, pos, end); } function checkNodePositions(node: Node, aggressiveChecks: boolean) { @@ -8011,8 +7994,8 @@ namespace ts { } } - interface IncrementalElement extends TextRange { - parent: Node; + interface IncrementalElement extends ReadonlyTextRange { + readonly parent: Node; intersectsChange: boolean; length?: number; _children: Node[] | undefined; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index dff9d4aa1d7..22b6beeb9c8 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2073,8 +2073,8 @@ namespace ts { const externalHelpersModuleReference = factory.createStringLiteral(externalHelpersModuleNameText); const importDecl = factory.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*importClause*/ undefined, externalHelpersModuleReference); addEmitFlags(importDecl, EmitFlags.NeverApplyImportHelper); - externalHelpersModuleReference.parent = importDecl; - importDecl.parent = file; + setParent(externalHelpersModuleReference, importDecl); + setParent(importDecl, file); imports = [externalHelpersModuleReference]; } diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 13cfc21db51..7c3fe77395c 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -1126,7 +1126,7 @@ namespace ts { const props = resolver.getPropertiesOfContainerFunction(input); // Use parseNodeFactory so it is usable as an enclosing declaration const fakespace = parseNodeFactory.createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, clean.name || factory.createIdentifier("_default"), factory.createModuleBlock([]), NodeFlags.Namespace); - fakespace.parent = enclosingDeclaration as SourceFile | NamespaceDeclaration; + setParent(fakespace, enclosingDeclaration as SourceFile | NamespaceDeclaration); fakespace.locals = createSymbolTable(props); fakespace.symbol = props[0].parent!; const declarations = mapDefined(props, p => { diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 72e3466ef9f..37f6f5aaa0e 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -789,11 +789,11 @@ namespace ts { // "inner" and "outer" below are added purely to preserve source map locations from // the old emitter const inner = factory.createPartiallyEmittedExpression(classFunction); - inner.end = node.end; + setTextRangeEnd(inner, node.end); setEmitFlags(inner, EmitFlags.NoComments); const outer = factory.createPartiallyEmittedExpression(inner); - outer.end = skipTrivia(currentText, node.pos); + setTextRangeEnd(outer, skipTrivia(currentText, node.pos)); setEmitFlags(outer, EmitFlags.NoComments); const result = factory.createParen( @@ -829,11 +829,11 @@ namespace ts { // The following partially-emitted expression exists purely to align our sourcemap // emit with the original emitter. const outer = factory.createPartiallyEmittedExpression(localName); - outer.end = closingBraceLocation.end; + setTextRangeEnd(outer, closingBraceLocation.end); setEmitFlags(outer, EmitFlags.NoComments); const statement = factory.createReturn(outer); - statement.pos = closingBraceLocation.pos; + setTextRangePos(statement, closingBraceLocation.pos); setEmitFlags(statement, EmitFlags.NoComments | EmitFlags.NoTokenSourceMaps); statements.push(statement); @@ -2364,7 +2364,7 @@ namespace ts { statements.push(factory.createExpressionStatement(visitBinaryExpression(assignment, /*needsDestructuringValue*/ false))); } else { - assignment.end = initializer.end; + setTextRangeEnd(assignment, initializer.end); statements.push(setTextRange(factory.createExpressionStatement(visitNode(assignment, visitor, isExpression)), moveRangeEnd(initializer, -1))); } } @@ -4077,8 +4077,7 @@ namespace ts { // "abc" + (1 << 2) + "" const expression = reduceLeft(expressions, factory.createAdd)!; if (nodeIsSynthesized(expression)) { - expression.pos = node.pos; - expression.end = node.end; + setTextRange(expression, node); } return expression; diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index c2e6025739f..d2bb2f41079 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -650,11 +650,11 @@ namespace ts { // The following partially-emitted expression exists purely to align our sourcemap // emit with the original emitter. const outer = factory.createPartiallyEmittedExpression(localName); - outer.end = closingBraceLocation.end; + setTextRangeEnd(outer, closingBraceLocation.end); setEmitFlags(outer, EmitFlags.NoComments); const statement = factory.createReturn(outer); - statement.pos = closingBraceLocation.pos; + setTextRangePos(statement, closingBraceLocation.pos); setEmitFlags(statement, EmitFlags.NoComments | EmitFlags.NoTokenSourceMaps); statements.push(statement); @@ -1739,7 +1739,7 @@ namespace ts { // a source tree node for the purposes of the checker. const name = setParent(setTextRange(parseNodeFactory.cloneNode(node), node), node.parent); name.original = undefined; - name.parent = getParseTreeNode(currentLexicalScope)!; // ensure the parent is set to a parse tree node. + setParent(name, getParseTreeNode(currentLexicalScope)); // ensure the parent is set to a parse tree node. return name; case SyntaxKind.QualifiedName: diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3816aed3b9d..2acfed01bc3 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -8,6 +8,11 @@ namespace ts { end: number; } + export interface ReadonlyTextRange { + readonly pos: number; + readonly end: number; + } + // token > SyntaxKind.Identifier => token is a keyword // Also, If you add a new SyntaxKind be sure to keep the `Markers` section at the bottom in sync export const enum SyntaxKind { @@ -796,7 +801,7 @@ namespace ts { ReportsMask = ReportsUnmeasurable | ReportsUnreliable } - export interface Node extends TextRange { + export interface Node extends ReadonlyTextRange { readonly kind: SyntaxKind; readonly flags: NodeFlags; /* @internal */ modifierFlagsCache: ModifierFlags; @@ -804,7 +809,7 @@ namespace ts { readonly decorators?: NodeArray; // Array of decorators (in document order) readonly modifiers?: ModifiersArray; // Array of modifiers /* @internal */ id?: number; // Unique id (used to look up NodeLinks) - parent: Node; // Parent node (initialized by binding) + readonly parent: Node; // Parent node (initialized by binding) /* @internal */ original?: Node; // The original node if this is an updated node. /* @internal */ symbol: Symbol; // Symbol declared by node (initialized by binding) /* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding) @@ -927,7 +932,7 @@ namespace ts { /* @internal */ export type MutableNodeArray = NodeArray & T[]; - export interface NodeArray extends ReadonlyArray, TextRange { + export interface NodeArray extends ReadonlyArray, ReadonlyTextRange { hasTrailingComma?: boolean; /* @internal */ transformFlags: TransformFlags; // Flags for transforms, possibly undefined } @@ -1119,8 +1124,8 @@ namespace ts { } export interface ComputedPropertyName extends Node { - parent: Declaration; readonly kind: SyntaxKind.ComputedPropertyName; + readonly parent: Declaration; readonly expression: Expression; } @@ -1258,8 +1263,8 @@ namespace ts { ; export interface PropertyAssignment extends ObjectLiteralElement, JSDocContainer { - parent: ObjectLiteralExpression; readonly kind: SyntaxKind.PropertyAssignment; + readonly parent: ObjectLiteralExpression; readonly name: PropertyName; readonly questionToken?: QuestionToken; // Present for use with reporting a grammar error readonly exclamationToken?: ExclamationToken; // Present for use with reporting a grammar error @@ -1267,8 +1272,8 @@ namespace ts { } export interface ShorthandPropertyAssignment extends ObjectLiteralElement, JSDocContainer { - parent: ObjectLiteralExpression; readonly kind: SyntaxKind.ShorthandPropertyAssignment; + readonly parent: ObjectLiteralExpression; readonly name: Identifier; readonly questionToken?: QuestionToken; readonly exclamationToken?: ExclamationToken; @@ -1279,8 +1284,8 @@ namespace ts { } export interface SpreadAssignment extends ObjectLiteralElement, JSDocContainer { - parent: ObjectLiteralExpression; readonly kind: SyntaxKind.SpreadAssignment; + readonly parent: ObjectLiteralExpression; readonly expression: Expression; } @@ -1302,14 +1307,14 @@ namespace ts { } export interface ObjectBindingPattern extends Node { - parent: VariableDeclaration | ParameterDeclaration | BindingElement; readonly kind: SyntaxKind.ObjectBindingPattern; + readonly parent: VariableDeclaration | ParameterDeclaration | BindingElement; readonly elements: NodeArray; } export interface ArrayBindingPattern extends Node { - parent: VariableDeclaration | ParameterDeclaration | BindingElement; readonly kind: SyntaxKind.ArrayBindingPattern; + readonly parent: VariableDeclaration | ParameterDeclaration | BindingElement; readonly elements: NodeArray; } @@ -1353,8 +1358,8 @@ namespace ts { } export interface MethodSignature extends SignatureDeclarationBase, TypeElement { - parent: ObjectTypeDeclaration; readonly kind: SyntaxKind.MethodSignature; + readonly parent: ObjectTypeDeclaration; readonly name: PropertyName; } @@ -1368,16 +1373,16 @@ namespace ts { // at later stages of the compiler pipeline. In that case, you can either check the parent kind // of the method, or use helpers like isObjectLiteralMethodDeclaration export interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { - parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly kind: SyntaxKind.MethodDeclaration; + readonly parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly name: PropertyName; readonly body?: FunctionBody; /* @internal*/ exclamationToken?: ExclamationToken; // Present for use with reporting a grammar error } export interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer { - parent: ClassLikeDeclaration; readonly kind: SyntaxKind.Constructor; + readonly parent: ClassLikeDeclaration; readonly body?: FunctionBody; /* @internal */ returnFlowNode?: FlowNode; /* @internal */ typeParameters?: NodeArray; // Present for use with reporting a grammar error @@ -1386,15 +1391,15 @@ namespace ts { /** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */ export interface SemicolonClassElement extends ClassElement { - parent: ClassLikeDeclaration; readonly kind: SyntaxKind.SemicolonClassElement; + readonly parent: ClassLikeDeclaration; } // See the comment on MethodDeclaration for the intuition behind GetAccessorDeclaration being a // ClassElement and an ObjectLiteralElement. export interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { - parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly kind: SyntaxKind.GetAccessor; + readonly parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly name: PropertyName; readonly body?: FunctionBody; /* @internal */ typeParameters?: NodeArray; // Present for use with reporting a grammar error @@ -1403,8 +1408,8 @@ namespace ts { // See the comment on MethodDeclaration for the intuition behind SetAccessorDeclaration being a // ClassElement and an ObjectLiteralElement. export interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { - parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly kind: SyntaxKind.SetAccessor; + readonly parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly name: PropertyName; readonly body?: FunctionBody; /* @internal */ typeParameters?: NodeArray; // Present for use with reporting a grammar error @@ -1414,8 +1419,8 @@ namespace ts { export type AccessorDeclaration = GetAccessorDeclaration | SetAccessorDeclaration; export interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement { - parent: ObjectTypeDeclaration; readonly kind: SyntaxKind.IndexSignature; + readonly parent: ObjectTypeDeclaration; readonly type: TypeNode; } @@ -2030,17 +2035,17 @@ namespace ts { export interface TemplateHead extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateHead; - parent: TemplateExpression; + readonly parent: TemplateExpression; } export interface TemplateMiddle extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateMiddle; - parent: TemplateSpan; + readonly parent: TemplateSpan; } export interface TemplateTail extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateTail; - parent: TemplateSpan; + readonly parent: TemplateSpan; } export type PseudoLiteralToken = @@ -2068,8 +2073,8 @@ namespace ts { // Each of these corresponds to a substitution expression and a template literal, in that order. // The template literal must have kind TemplateMiddleLiteral or TemplateTailLiteral. export interface TemplateSpan extends Node { - parent: TemplateExpression; readonly kind: SyntaxKind.TemplateSpan; + readonly parent: TemplateExpression; readonly expression: Expression; readonly literal: TemplateMiddle | TemplateTail; } @@ -2087,8 +2092,8 @@ namespace ts { } export interface SpreadElement extends Expression { - parent: ArrayLiteralExpression | CallExpression | NewExpression; readonly kind: SyntaxKind.SpreadElement; + readonly parent: ArrayLiteralExpression | CallExpression | NewExpression; readonly expression: Expression; } @@ -2257,8 +2262,8 @@ namespace ts { } export interface ExpressionWithTypeArguments extends NodeWithTypeArguments { - parent: HeritageClause | JSDocAugmentsTag; readonly kind: SyntaxKind.ExpressionWithTypeArguments; + readonly parent: HeritageClause | JSDocAugmentsTag; readonly expression: LeftHandSideExpression; } @@ -2351,14 +2356,14 @@ namespace ts { } export interface JsxAttributes extends ObjectLiteralExpressionBase { - parent: JsxOpeningLikeElement; readonly kind: SyntaxKind.JsxAttributes; + readonly parent: JsxOpeningLikeElement; } /// The opening element of a ... JsxElement export interface JsxOpeningElement extends Expression { - parent: JsxElement; readonly kind: SyntaxKind.JsxOpeningElement; + readonly parent: JsxElement; readonly tagName: JsxTagNameExpression; readonly typeArguments?: NodeArray; readonly attributes: JsxAttributes; @@ -2382,46 +2387,46 @@ namespace ts { /// The opening element of a <>... JsxFragment export interface JsxOpeningFragment extends Expression { - parent: JsxFragment; readonly kind: SyntaxKind.JsxOpeningFragment; + readonly parent: JsxFragment; } /// The closing element of a <>... JsxFragment export interface JsxClosingFragment extends Expression { - parent: JsxFragment; readonly kind: SyntaxKind.JsxClosingFragment; + readonly parent: JsxFragment; } export interface JsxAttribute extends ObjectLiteralElement { - parent: JsxAttributes; readonly kind: SyntaxKind.JsxAttribute; + readonly parent: JsxAttributes; readonly name: Identifier; /// JSX attribute initializers are optional; is sugar for readonly initializer?: StringLiteral | JsxExpression; } export interface JsxSpreadAttribute extends ObjectLiteralElement { - parent: JsxAttributes; readonly kind: SyntaxKind.JsxSpreadAttribute; + readonly parent: JsxAttributes; readonly expression: Expression; } export interface JsxClosingElement extends Node { - parent: JsxElement; readonly kind: SyntaxKind.JsxClosingElement; + readonly parent: JsxElement; readonly tagName: JsxTagNameExpression; } export interface JsxExpression extends Expression { - parent: JsxElement | JsxAttributeLike; readonly kind: SyntaxKind.JsxExpression; + readonly parent: JsxElement | JsxAttributeLike; readonly dotDotDotToken?: Token; readonly expression?: Expression; } export interface JsxText extends LiteralLikeNode { - parent: JsxElement; readonly kind: SyntaxKind.JsxText; + readonly parent: JsxElement; readonly containsOnlyTriviaWhiteSpaces: boolean; } @@ -2599,26 +2604,26 @@ namespace ts { readonly kind: SyntaxKind.SwitchStatement; readonly expression: Expression; readonly caseBlock: CaseBlock; - possiblyExhaustive?: boolean; + possiblyExhaustive?: boolean; // initialized by binding } export interface CaseBlock extends Node { - parent: SwitchStatement; readonly kind: SyntaxKind.CaseBlock; + readonly parent: SwitchStatement; readonly clauses: NodeArray; } export interface CaseClause extends Node { - parent: CaseBlock; readonly kind: SyntaxKind.CaseClause; + readonly parent: CaseBlock; readonly expression: Expression; readonly statements: NodeArray; /* @internal */ fallthroughFlowNode?: FlowNode; } export interface DefaultClause extends Node { - parent: CaseBlock; readonly kind: SyntaxKind.DefaultClause; + readonly parent: CaseBlock; readonly statements: NodeArray; /* @internal */ fallthroughFlowNode?: FlowNode; } @@ -2647,8 +2652,8 @@ namespace ts { } export interface CatchClause extends Node { - parent: TryStatement; readonly kind: SyntaxKind.CatchClause; + readonly parent: TryStatement; readonly variableDeclaration?: VariableDeclaration; readonly block: Block; } @@ -2717,8 +2722,8 @@ namespace ts { } export interface HeritageClause extends Node { - parent: InterfaceDeclaration | ClassLikeDeclaration; readonly kind: SyntaxKind.HeritageClause; + readonly parent: InterfaceDeclaration | ClassLikeDeclaration; readonly token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword; readonly types: NodeArray; } @@ -2731,8 +2736,8 @@ namespace ts { } export interface EnumMember extends NamedDeclaration, JSDocContainer { - parent: EnumDeclaration; readonly kind: SyntaxKind.EnumMember; + readonly parent: EnumDeclaration; // This does include ComputedPropertyName, but the parser will give an error // if it parses a ComputedPropertyName in an EnumMember readonly name: PropertyName; @@ -2761,8 +2766,8 @@ namespace ts { } export interface ModuleDeclaration extends DeclarationStatement, JSDocContainer { - parent: ModuleBody | SourceFile; readonly kind: SyntaxKind.ModuleDeclaration; + readonly parent: ModuleBody | SourceFile; readonly name: ModuleName; readonly body?: ModuleBody | JSDocNamespaceDeclaration; } @@ -2788,8 +2793,8 @@ namespace ts { } export interface ModuleBlock extends Node, Statement { - parent: ModuleDeclaration; readonly kind: SyntaxKind.ModuleBlock; + readonly parent: ModuleDeclaration; readonly statements: NodeArray; } @@ -2804,8 +2809,8 @@ namespace ts { * - import x = M.x; */ export interface ImportEqualsDeclaration extends DeclarationStatement, JSDocContainer { - parent: SourceFile | ModuleBlock; readonly kind: SyntaxKind.ImportEqualsDeclaration; + readonly parent: SourceFile | ModuleBlock; readonly name: Identifier; // 'EntityName' for an internal module reference, 'ExternalModuleReference' for an external @@ -2814,8 +2819,8 @@ namespace ts { } export interface ExternalModuleReference extends Node { - parent: ImportEqualsDeclaration; readonly kind: SyntaxKind.ExternalModuleReference; + readonly parent: ImportEqualsDeclaration; readonly expression: Expression; } @@ -2824,8 +2829,8 @@ namespace ts { // In rest of the cases, module specifier is string literal corresponding to module // ImportClause information is shown at its declaration below. export interface ImportDeclaration extends Statement, JSDocContainer { - parent: SourceFile | ModuleBlock; readonly kind: SyntaxKind.ImportDeclaration; + readonly parent: SourceFile | ModuleBlock; readonly importClause?: ImportClause; /** If this is not a StringLiteral it will be a grammar error. */ readonly moduleSpecifier: Expression; @@ -2843,15 +2848,15 @@ namespace ts { // import { a, b as x } from "mod" => name = undefined, namedBinding: NamedImports = { elements: [{ name: a }, { name: x, propertyName: b}]} // import d, { a, b as x } from "mod" => name = d, namedBinding: NamedImports = { elements: [{ name: a }, { name: x, propertyName: b}]} export interface ImportClause extends NamedDeclaration { - parent: ImportDeclaration; readonly kind: SyntaxKind.ImportClause; + readonly parent: ImportDeclaration; readonly name?: Identifier; // Default binding readonly namedBindings?: NamedImportBindings; } export interface NamespaceImport extends NamedDeclaration { - parent: ImportClause; readonly kind: SyntaxKind.NamespaceImport; + readonly parent: ImportClause; readonly name: Identifier; } @@ -2863,8 +2868,8 @@ namespace ts { } export interface ExportDeclaration extends DeclarationStatement, JSDocContainer { - parent: SourceFile | ModuleBlock; readonly kind: SyntaxKind.ExportDeclaration; + readonly parent: SourceFile | ModuleBlock; /** Will not be assigned in the case of `export * from "foo";` */ readonly exportClause?: NamedExports; /** If this is not a StringLiteral it will be a grammar error. */ @@ -2872,29 +2877,29 @@ namespace ts { } export interface NamedImports extends Node { - parent: ImportClause; readonly kind: SyntaxKind.NamedImports; + readonly parent: ImportClause; readonly elements: NodeArray; } export interface NamedExports extends Node { - parent: ExportDeclaration; readonly kind: SyntaxKind.NamedExports; + readonly parent: ExportDeclaration; readonly elements: NodeArray; } export type NamedImportsOrExports = NamedImports | NamedExports; export interface ImportSpecifier extends NamedDeclaration { - parent: NamedImports; readonly kind: SyntaxKind.ImportSpecifier; + readonly parent: NamedImports; readonly propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent) readonly name: Identifier; // Declared name } export interface ExportSpecifier extends NamedDeclaration { - parent: NamedExports; readonly kind: SyntaxKind.ExportSpecifier; + readonly parent: NamedExports; readonly propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent) readonly name: Identifier; // Declared name } @@ -2909,8 +2914,8 @@ namespace ts { * Unless `isExportEquals` is set, this node was parsed as an `export default`. */ export interface ExportAssignment extends DeclarationStatement, JSDocContainer { - parent: SourceFile; readonly kind: SyntaxKind.ExportAssignment; + readonly parent: SourceFile; readonly isExportEquals?: boolean; readonly expression: Expression; } @@ -2991,16 +2996,16 @@ namespace ts { ; export interface JSDoc extends Node { - parent: HasJSDoc; readonly kind: SyntaxKind.JSDocComment; + readonly parent: HasJSDoc; readonly tags?: NodeArray; - comment?: string; + readonly comment?: string; } export interface JSDocTag extends Node { - parent: JSDoc | JSDocTypeLiteral; + readonly parent: JSDoc | JSDocTypeLiteral; readonly tagName: Identifier; - comment?: string; + readonly comment?: string; } export interface JSDocUnknownTag extends JSDocTag { @@ -3025,8 +3030,8 @@ namespace ts { } export interface JSDocEnumTag extends JSDocTag, Declaration { - parent: JSDoc; readonly kind: SyntaxKind.JSDocEnumTag; + readonly parent: JSDoc; readonly typeExpression?: JSDocTypeExpression; } @@ -3052,16 +3057,16 @@ namespace ts { } export interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { - parent: JSDoc; readonly kind: SyntaxKind.JSDocTypedefTag; + readonly parent: JSDoc; readonly fullName?: JSDocNamespaceDeclaration | Identifier; readonly name?: Identifier; readonly typeExpression?: JSDocTypeExpression | JSDocTypeLiteral; } export interface JSDocCallbackTag extends JSDocTag, NamedDeclaration { - parent: JSDoc; readonly kind: SyntaxKind.JSDocCallbackTag; + readonly parent: JSDoc; readonly fullName?: JSDocNamespaceDeclaration | Identifier; readonly name?: Identifier; readonly typeExpression: JSDocSignature; @@ -3075,7 +3080,7 @@ namespace ts { } export interface JSDocPropertyLikeTag extends JSDocTag, Declaration { - parent: JSDoc; + readonly parent: JSDoc; readonly name: EntityName; readonly typeExpression?: JSDocTypeExpression; /** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */ @@ -3404,32 +3409,32 @@ namespace ts { ; export interface UnparsedSection extends Node { - parent: UnparsedSource; readonly kind: SyntaxKind; + readonly parent: UnparsedSource; readonly data?: string; } export interface UnparsedPrologue extends UnparsedSection { - parent: UnparsedSource; readonly kind: SyntaxKind.UnparsedPrologue; + readonly parent: UnparsedSource; readonly data: string; } export interface UnparsedPrepend extends UnparsedSection { - parent: UnparsedSource; readonly kind: SyntaxKind.UnparsedPrepend; + readonly parent: UnparsedSource; readonly data: string; readonly texts: readonly UnparsedTextLike[]; } export interface UnparsedTextLike extends UnparsedSection { - parent: UnparsedSource; readonly kind: SyntaxKind.UnparsedText | SyntaxKind.UnparsedInternalText; + readonly parent: UnparsedSource; } export interface UnparsedSyntheticReference extends UnparsedSection { - parent: UnparsedSource; readonly kind: SyntaxKind.UnparsedSyntheticReference; + readonly parent: UnparsedSource; /*@internal*/ readonly section: BundleFileHasNoDefaultLib | BundleFileReference; } @@ -6634,19 +6639,19 @@ namespace ts { /* @internal */ createJSDocTypeExpression(type: TypeNode): JSDocTypeExpression; /* @internal */ createJSDocTypeLiteral(jsDocPropertyTags?: readonly JSDocPropertyLikeTag[], isArrayType?: boolean): JSDocTypeLiteral; /* @internal */ createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature; - /* @internal */ createJSDocTemplateTag(tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[]): JSDocTemplateTag; + /* @internal */ createJSDocTemplateTag(tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment?: string): JSDocTemplateTag; /* @internal */ createJSDocTypedefTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression | JSDocTypeLiteral, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string): JSDocTypedefTag; /* @internal */ createJSDocTypeTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string): JSDocTypeTag; /* @internal */ createJSDocReturnTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string): JSDocReturnTag; - /* @internal */ createJSDocThisTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression): JSDocThisTag; + /* @internal */ createJSDocThisTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string): JSDocThisTag; /* @internal */ createJSDocAuthorTag(tagName: Identifier | undefined, comment?: string): JSDocAuthorTag; - /* @internal */ createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"]): JSDocAugmentsTag; - /* @internal */ createJSDocClassTag(tagName: Identifier | undefined): JSDocClassTag; + /* @internal */ createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment?: string): JSDocAugmentsTag; + /* @internal */ createJSDocClassTag(tagName: Identifier | undefined, comment?: string): JSDocClassTag; /* @internal */ createJSDocCallbackTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string): JSDocCallbackTag; - /* @internal */ createJSDocEnumTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression): JSDocEnumTag; + /* @internal */ createJSDocEnumTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string): JSDocEnumTag; /* @internal */ createJSDocParameterTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string): JSDocParameterTag; /* @internal */ createJSDocPropertyTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string): JSDocPropertyTag; - /* @internal */ createJSDocUnknownTag(tagName: Identifier): JSDocUnknownTag; + /* @internal */ createJSDocUnknownTag(tagName: Identifier, comment?: string): JSDocUnknownTag; /* @internal */ createJSDocComment(comment?: string | undefined, tags?: NodeArray | undefined): JSDoc; // diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index e6f9dbd6f07..f3a244b36a3 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -5938,35 +5938,109 @@ namespace ts { } namespace ts { - export function setTextRange(range: T, location: TextRange | undefined): T { + export function setTextRange(range: T, location: ReadonlyTextRange | undefined): T { return location ? setTextRangePosEnd(range, location.pos, location.end) : range; } /* @internal */ - export function setTextRangePosEnd(range: T, pos: number, end: number) { + export function setTextRangePos(range: T, pos: number) { range.pos = pos; + return range; + } + + /* @internal */ + export function setTextRangeEnd(range: T, end: number) { range.end = end; return range; } /* @internal */ - export function setParent(child: T, parent: T["parent"]): T { - if (!child.parent) { - child.parent = parent; + export function setTextRangePosEnd(range: T, pos: number, end: number) { + return setTextRangeEnd(setTextRangePos(range, pos), end); + } + + /* @internal */ + export function setTextRangePosWidth(range: T, pos: number, width: number) { + return setTextRangePosEnd(range, pos, pos + width); + } + + /** + * Sets the `parent` property of a `Node`. + */ + /* @internal */ + export function setParent(child: T, parent: T["parent"] | undefined): T; + /* @internal */ + export function setParent(child: T | undefined, parent: T["parent"] | undefined): T | undefined; + export function setParent(child: T | undefined, parent: T["parent"] | undefined): T | undefined { + if (child && parent) { + (child as Mutable).parent = parent; } return child; } + /** + * Sets the `parent` property of each `Node` in an array of nodes, if is not already set. + */ /* @internal */ - export function setEachParent(children: T, parent: NonNullable[number]["parent"]): T { + export function setEachParent(children: T, parent: T[number]["parent"]): T; + /* @internal */ + export function setEachParent(children: T | undefined, parent: T[number]["parent"]): T | undefined; + export function setEachParent(children: T | undefined, parent: T[number]["parent"]): T | undefined { if (children) { - for (const child of children!) { + for (const child of children) { setParent(child, parent); } } return children; } + /** + * Sets the `parent` property of each `Node` recursively. + * @param rootNode The root node from which to start the recursion. + * @param incremental When `true`, only recursively descends through nodes whose `parent` pointers are incorrect. + * This allows us to quickly bail out of setting `parent` for subtrees during incremental parsing. + */ + /* @internal */ + export function setParentRecursive(rootNode: T, incremental: boolean): T; + /* @internal */ + export function setParentRecursive(rootNode: T | undefined, incremental: boolean): T | undefined; + export function setParentRecursive(rootNode: T | undefined, incremental: boolean): T | undefined { + if (!rootNode) return rootNode; + + let parent: Node = rootNode; + forEachChild(rootNode, isJSDocNode(rootNode) ? visitNodeWithoutJSDoc : visitNodeWithJSDoc); + return rootNode; + + function visitNodeWithJSDoc(child: Node) { + visitNode(child, visitChildrenWithJSDoc); + } + + function visitNodeWithoutJSDoc(child: Node) { + visitNode(child, visitChildrenWithoutJSDoc); + } + + function visitChildrenWithJSDoc(node: Node) { + forEachChild(node, visitNodeWithJSDoc); + if (hasJSDocNodes(node)) { + forEach(node.jsDoc, visitNodeWithoutJSDoc); + } + } + + function visitChildrenWithoutJSDoc(node: Node) { + forEachChild(node, visitNodeWithoutJSDoc); + } + + function visitNode(n: Node, visitChildren: (node: Node) => void) { + if (!incremental || n.parent !== parent) { + setParent(n, parent); + const saveParent = parent; + parent = n; + visitChildren(n); + parent = saveParent; + } + } + } + export function isConstTypeReference(node: Node) { return isTypeReferenceNode(node) && isIdentifier(node.typeName) && node.typeName.escapedText === "const" && !node.typeArguments; diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 396ce5c9281..3d5dd43af93 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -131,8 +131,7 @@ namespace ts { if (updated) { // TODO(rbuckton): Remove dependency on `ts.factory` in favor of a provided factory. const updatedArray = factory.createNodeArray(updated, hasTrailingComma); - updatedArray.pos = pos; - updatedArray.end = end; + setTextRangePosEnd(updatedArray, pos, end); return updatedArray; } diff --git a/src/services/classifier.ts b/src/services/classifier.ts index 69d1dcdf8e6..3b248979d3f 100644 --- a/src/services/classifier.ts +++ b/src/services/classifier.ts @@ -682,7 +682,7 @@ namespace ts { const docCommentAndDiagnostics = parseIsolatedJSDocComment(sourceFile.text, start, width); if (docCommentAndDiagnostics && docCommentAndDiagnostics.jsDoc) { // TODO: This should be predicated on `token["kind"]` being compatible with `HasJSDoc["kind"]` - docCommentAndDiagnostics.jsDoc.parent = token as HasJSDoc; + setParent(docCommentAndDiagnostics.jsDoc, token as HasJSDoc); classifyJSDocComment(docCommentAndDiagnostics.jsDoc); return; } diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 7a9a7fabae7..eeb88f6cd16 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -897,8 +897,7 @@ namespace ts.textChanges { const visited = visitEachChild(node, assignPositionsToNode, nullTransformationContext, assignPositionsToNodeArray, assignPositionsToNode)!; // TODO: GH#18217 // create proxy node for non synthesized nodes const newNode = nodeIsSynthesized(visited) ? visited : Object.create(visited) as Node; - newNode.pos = getPos(node); - newNode.end = getEnd(node); + setTextRangePosEnd(newNode, getPos(node), getEnd(node)); return newNode; } @@ -909,8 +908,7 @@ namespace ts.textChanges { } // clone nodearray if necessary const nodeArray = visited === nodes ? factory.createNodeArray(visited.slice(0)) : visited; - nodeArray.pos = getPos(nodes); - nodeArray.end = getEnd(nodes); + setTextRangePosEnd(nodeArray, getPos(nodes), getEnd(nodes)); return nodeArray; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 00346fa6659..c1259a7d6c9 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1797,7 +1797,7 @@ namespace ts { // PERF: As an optimization, rather than calling getSynthesizedClone, we'll update // the new node created by visitEachChild with the extra changes getSynthesizedClone // would have made. - visited.parent = undefined!; + (visited as Mutable).parent = undefined!; return visited; function wrapper(node: T) { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 8c12a77a05d..24a620f9b48 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -72,6 +72,10 @@ declare namespace ts { pos: number; end: number; } + export interface ReadonlyTextRange { + readonly pos: number; + readonly end: number; + } export enum SyntaxKind { Unknown = 0, EndOfFileToken = 1, @@ -500,12 +504,12 @@ declare namespace ts { IntrinsicIndexedElement = 2, IntrinsicElement = 3 } - export interface Node extends TextRange { + export interface Node extends ReadonlyTextRange { readonly kind: SyntaxKind; readonly flags: NodeFlags; readonly decorators?: NodeArray; readonly modifiers?: ModifiersArray; - parent: Node; + readonly parent: Node; } export interface JSDocContainer { } @@ -513,7 +517,7 @@ declare namespace ts { export type HasType = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertySignature | PropertyDeclaration | TypePredicateNode | ParenthesizedTypeNode | TypeOperatorNode | MappedTypeNode | AssertionExpression | TypeAliasDeclaration | JSDocTypeExpression | JSDocNonNullableType | JSDocNullableType | JSDocOptionalType | JSDocVariadicType; export type HasInitializer = HasExpressionInitializer | ForStatement | ForInStatement | ForOfStatement | JsxAttribute; export type HasExpressionInitializer = VariableDeclaration | ParameterDeclaration | BindingElement | PropertySignature | PropertyDeclaration | PropertyAssignment | EnumMember; - export interface NodeArray extends ReadonlyArray, TextRange { + export interface NodeArray extends ReadonlyArray, ReadonlyTextRange { hasTrailingComma?: boolean; } export interface Token extends Node { @@ -592,8 +596,8 @@ declare namespace ts { readonly name?: Identifier | StringLiteral | NumericLiteral; } export interface ComputedPropertyName extends Node { - parent: Declaration; readonly kind: SyntaxKind.ComputedPropertyName; + readonly parent: Declaration; readonly expression: Expression; } export interface Decorator extends Node { @@ -678,16 +682,16 @@ declare namespace ts { /** Unlike ObjectLiteralElement, excludes JSXAttribute and JSXSpreadAttribute. */ export type ObjectLiteralElementLike = PropertyAssignment | ShorthandPropertyAssignment | SpreadAssignment | MethodDeclaration | AccessorDeclaration; export interface PropertyAssignment extends ObjectLiteralElement, JSDocContainer { - parent: ObjectLiteralExpression; readonly kind: SyntaxKind.PropertyAssignment; + readonly parent: ObjectLiteralExpression; readonly name: PropertyName; readonly questionToken?: QuestionToken; readonly exclamationToken?: ExclamationToken; readonly initializer: Expression; } export interface ShorthandPropertyAssignment extends ObjectLiteralElement, JSDocContainer { - parent: ObjectLiteralExpression; readonly kind: SyntaxKind.ShorthandPropertyAssignment; + readonly parent: ObjectLiteralExpression; readonly name: Identifier; readonly questionToken?: QuestionToken; readonly exclamationToken?: ExclamationToken; @@ -695,8 +699,8 @@ declare namespace ts { readonly objectAssignmentInitializer?: Expression; } export interface SpreadAssignment extends ObjectLiteralElement, JSDocContainer { - parent: ObjectLiteralExpression; readonly kind: SyntaxKind.SpreadAssignment; + readonly parent: ObjectLiteralExpression; readonly expression: Expression; } export type VariableLikeDeclaration = VariableDeclaration | ParameterDeclaration | BindingElement | PropertyDeclaration | PropertyAssignment | PropertySignature | JsxAttribute | ShorthandPropertyAssignment | EnumMember | JSDocPropertyTag | JSDocParameterTag; @@ -704,13 +708,13 @@ declare namespace ts { readonly name: PropertyName; } export interface ObjectBindingPattern extends Node { - parent: VariableDeclaration | ParameterDeclaration | BindingElement; readonly kind: SyntaxKind.ObjectBindingPattern; + readonly parent: VariableDeclaration | ParameterDeclaration | BindingElement; readonly elements: NodeArray; } export interface ArrayBindingPattern extends Node { - parent: VariableDeclaration | ParameterDeclaration | BindingElement; readonly kind: SyntaxKind.ArrayBindingPattern; + readonly parent: VariableDeclaration | ParameterDeclaration | BindingElement; readonly elements: NodeArray; } export type BindingPattern = ObjectBindingPattern | ArrayBindingPattern; @@ -739,42 +743,42 @@ declare namespace ts { readonly body?: FunctionBody; } export interface MethodSignature extends SignatureDeclarationBase, TypeElement { - parent: ObjectTypeDeclaration; readonly kind: SyntaxKind.MethodSignature; + readonly parent: ObjectTypeDeclaration; readonly name: PropertyName; } export interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { - parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly kind: SyntaxKind.MethodDeclaration; + readonly parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly name: PropertyName; readonly body?: FunctionBody; } export interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer { - parent: ClassLikeDeclaration; readonly kind: SyntaxKind.Constructor; + readonly parent: ClassLikeDeclaration; readonly body?: FunctionBody; } /** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */ export interface SemicolonClassElement extends ClassElement { - parent: ClassLikeDeclaration; readonly kind: SyntaxKind.SemicolonClassElement; + readonly parent: ClassLikeDeclaration; } export interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { - parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly kind: SyntaxKind.GetAccessor; + readonly parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly name: PropertyName; readonly body?: FunctionBody; } export interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { - parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly kind: SyntaxKind.SetAccessor; + readonly parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly name: PropertyName; readonly body?: FunctionBody; } export type AccessorDeclaration = GetAccessorDeclaration | SetAccessorDeclaration; export interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement { - parent: ObjectTypeDeclaration; readonly kind: SyntaxKind.IndexSignature; + readonly parent: ObjectTypeDeclaration; readonly type: TypeNode; } export interface TypeNode extends Node { @@ -1078,15 +1082,15 @@ declare namespace ts { export type LiteralToken = NumericLiteral | BigIntLiteral | StringLiteral | JsxText | RegularExpressionLiteral | NoSubstitutionTemplateLiteral; export interface TemplateHead extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateHead; - parent: TemplateExpression; + readonly parent: TemplateExpression; } export interface TemplateMiddle extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateMiddle; - parent: TemplateSpan; + readonly parent: TemplateSpan; } export interface TemplateTail extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateTail; - parent: TemplateSpan; + readonly parent: TemplateSpan; } export type PseudoLiteralToken = TemplateHead | TemplateMiddle | TemplateTail; export type TemplateLiteralToken = NoSubstitutionTemplateLiteral | PseudoLiteralToken; @@ -1097,8 +1101,8 @@ declare namespace ts { } export type TemplateLiteral = TemplateExpression | NoSubstitutionTemplateLiteral; export interface TemplateSpan extends Node { - parent: TemplateExpression; readonly kind: SyntaxKind.TemplateSpan; + readonly parent: TemplateExpression; readonly expression: Expression; readonly literal: TemplateMiddle | TemplateTail; } @@ -1111,8 +1115,8 @@ declare namespace ts { readonly elements: NodeArray; } export interface SpreadElement extends Expression { - parent: ArrayLiteralExpression | CallExpression | NewExpression; readonly kind: SyntaxKind.SpreadElement; + readonly parent: ArrayLiteralExpression | CallExpression | NewExpression; readonly expression: Expression; } /** @@ -1177,8 +1181,8 @@ declare namespace ts { readonly expression: ImportExpression; } export interface ExpressionWithTypeArguments extends NodeWithTypeArguments { - parent: HeritageClause | JSDocAugmentsTag; readonly kind: SyntaxKind.ExpressionWithTypeArguments; + readonly parent: HeritageClause | JSDocAugmentsTag; readonly expression: LeftHandSideExpression; } export interface NewExpression extends PrimaryExpression, Declaration { @@ -1227,12 +1231,12 @@ declare namespace ts { readonly expression: JsxTagNameExpression; } export interface JsxAttributes extends ObjectLiteralExpressionBase { - parent: JsxOpeningLikeElement; readonly kind: SyntaxKind.JsxAttributes; + readonly parent: JsxOpeningLikeElement; } export interface JsxOpeningElement extends Expression { - parent: JsxElement; readonly kind: SyntaxKind.JsxOpeningElement; + readonly parent: JsxElement; readonly tagName: JsxTagNameExpression; readonly typeArguments?: NodeArray; readonly attributes: JsxAttributes; @@ -1250,38 +1254,38 @@ declare namespace ts { readonly closingFragment: JsxClosingFragment; } export interface JsxOpeningFragment extends Expression { - parent: JsxFragment; readonly kind: SyntaxKind.JsxOpeningFragment; + readonly parent: JsxFragment; } export interface JsxClosingFragment extends Expression { - parent: JsxFragment; readonly kind: SyntaxKind.JsxClosingFragment; + readonly parent: JsxFragment; } export interface JsxAttribute extends ObjectLiteralElement { - parent: JsxAttributes; readonly kind: SyntaxKind.JsxAttribute; + readonly parent: JsxAttributes; readonly name: Identifier; readonly initializer?: StringLiteral | JsxExpression; } export interface JsxSpreadAttribute extends ObjectLiteralElement { - parent: JsxAttributes; readonly kind: SyntaxKind.JsxSpreadAttribute; + readonly parent: JsxAttributes; readonly expression: Expression; } export interface JsxClosingElement extends Node { - parent: JsxElement; readonly kind: SyntaxKind.JsxClosingElement; + readonly parent: JsxElement; readonly tagName: JsxTagNameExpression; } export interface JsxExpression extends Expression { - parent: JsxElement | JsxAttributeLike; readonly kind: SyntaxKind.JsxExpression; + readonly parent: JsxElement | JsxAttributeLike; readonly dotDotDotToken?: Token; readonly expression?: Expression; } export interface JsxText extends LiteralLikeNode { - parent: JsxElement; readonly kind: SyntaxKind.JsxText; + readonly parent: JsxElement; readonly containsOnlyTriviaWhiteSpaces: boolean; } export type JsxChild = JsxText | JsxExpression | JsxElement | JsxSelfClosingElement | JsxFragment; @@ -1382,19 +1386,19 @@ declare namespace ts { possiblyExhaustive?: boolean; } export interface CaseBlock extends Node { - parent: SwitchStatement; readonly kind: SyntaxKind.CaseBlock; + readonly parent: SwitchStatement; readonly clauses: NodeArray; } export interface CaseClause extends Node { - parent: CaseBlock; readonly kind: SyntaxKind.CaseClause; + readonly parent: CaseBlock; readonly expression: Expression; readonly statements: NodeArray; } export interface DefaultClause extends Node { - parent: CaseBlock; readonly kind: SyntaxKind.DefaultClause; + readonly parent: CaseBlock; readonly statements: NodeArray; } export type CaseOrDefaultClause = CaseClause | DefaultClause; @@ -1414,8 +1418,8 @@ declare namespace ts { readonly finallyBlock?: Block; } export interface CatchClause extends Node { - parent: TryStatement; readonly kind: SyntaxKind.CatchClause; + readonly parent: TryStatement; readonly variableDeclaration?: VariableDeclaration; readonly block: Block; } @@ -1455,8 +1459,8 @@ declare namespace ts { readonly members: NodeArray; } export interface HeritageClause extends Node { - parent: InterfaceDeclaration | ClassLikeDeclaration; readonly kind: SyntaxKind.HeritageClause; + readonly parent: InterfaceDeclaration | ClassLikeDeclaration; readonly token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword; readonly types: NodeArray; } @@ -1467,8 +1471,8 @@ declare namespace ts { readonly type: TypeNode; } export interface EnumMember extends NamedDeclaration, JSDocContainer { - parent: EnumDeclaration; readonly kind: SyntaxKind.EnumMember; + readonly parent: EnumDeclaration; readonly name: PropertyName; readonly initializer?: Expression; } @@ -1480,8 +1484,8 @@ declare namespace ts { export type ModuleName = Identifier | StringLiteral; export type ModuleBody = NamespaceBody | JSDocNamespaceBody; export interface ModuleDeclaration extends DeclarationStatement, JSDocContainer { - parent: ModuleBody | SourceFile; readonly kind: SyntaxKind.ModuleDeclaration; + readonly parent: ModuleBody | SourceFile; readonly name: ModuleName; readonly body?: ModuleBody | JSDocNamespaceDeclaration; } @@ -1496,8 +1500,8 @@ declare namespace ts { readonly body?: JSDocNamespaceBody; } export interface ModuleBlock extends Node, Statement { - parent: ModuleDeclaration; readonly kind: SyntaxKind.ModuleBlock; + readonly parent: ModuleDeclaration; readonly statements: NodeArray; } export type ModuleReference = EntityName | ExternalModuleReference; @@ -1507,33 +1511,33 @@ declare namespace ts { * - import x = M.x; */ export interface ImportEqualsDeclaration extends DeclarationStatement, JSDocContainer { - parent: SourceFile | ModuleBlock; readonly kind: SyntaxKind.ImportEqualsDeclaration; + readonly parent: SourceFile | ModuleBlock; readonly name: Identifier; readonly moduleReference: ModuleReference; } export interface ExternalModuleReference extends Node { - parent: ImportEqualsDeclaration; readonly kind: SyntaxKind.ExternalModuleReference; + readonly parent: ImportEqualsDeclaration; readonly expression: Expression; } export interface ImportDeclaration extends Statement, JSDocContainer { - parent: SourceFile | ModuleBlock; readonly kind: SyntaxKind.ImportDeclaration; + readonly parent: SourceFile | ModuleBlock; readonly importClause?: ImportClause; /** If this is not a StringLiteral it will be a grammar error. */ readonly moduleSpecifier: Expression; } export type NamedImportBindings = NamespaceImport | NamedImports; export interface ImportClause extends NamedDeclaration { - parent: ImportDeclaration; readonly kind: SyntaxKind.ImportClause; + readonly parent: ImportDeclaration; readonly name?: Identifier; readonly namedBindings?: NamedImportBindings; } export interface NamespaceImport extends NamedDeclaration { - parent: ImportClause; readonly kind: SyntaxKind.NamespaceImport; + readonly parent: ImportClause; readonly name: Identifier; } export interface NamespaceExportDeclaration extends DeclarationStatement, JSDocContainer { @@ -1541,33 +1545,33 @@ declare namespace ts { readonly name: Identifier; } export interface ExportDeclaration extends DeclarationStatement, JSDocContainer { - parent: SourceFile | ModuleBlock; readonly kind: SyntaxKind.ExportDeclaration; + readonly parent: SourceFile | ModuleBlock; /** Will not be assigned in the case of `export * from "foo";` */ readonly exportClause?: NamedExports; /** If this is not a StringLiteral it will be a grammar error. */ readonly moduleSpecifier?: Expression; } export interface NamedImports extends Node { - parent: ImportClause; readonly kind: SyntaxKind.NamedImports; + readonly parent: ImportClause; readonly elements: NodeArray; } export interface NamedExports extends Node { - parent: ExportDeclaration; readonly kind: SyntaxKind.NamedExports; + readonly parent: ExportDeclaration; readonly elements: NodeArray; } export type NamedImportsOrExports = NamedImports | NamedExports; export interface ImportSpecifier extends NamedDeclaration { - parent: NamedImports; readonly kind: SyntaxKind.ImportSpecifier; + readonly parent: NamedImports; readonly propertyName?: Identifier; readonly name: Identifier; } export interface ExportSpecifier extends NamedDeclaration { - parent: NamedExports; readonly kind: SyntaxKind.ExportSpecifier; + readonly parent: NamedExports; readonly propertyName?: Identifier; readonly name: Identifier; } @@ -1577,8 +1581,8 @@ declare namespace ts { * Unless `isExportEquals` is set, this node was parsed as an `export default`. */ export interface ExportAssignment extends DeclarationStatement, JSDocContainer { - parent: SourceFile; readonly kind: SyntaxKind.ExportAssignment; + readonly parent: SourceFile; readonly isExportEquals?: boolean; readonly expression: Expression; } @@ -1636,15 +1640,15 @@ declare namespace ts { } export type JSDocTypeReferencingNode = JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType; export interface JSDoc extends Node { - parent: HasJSDoc; readonly kind: SyntaxKind.JSDocComment; + readonly parent: HasJSDoc; readonly tags?: NodeArray; - comment?: string; + readonly comment?: string; } export interface JSDocTag extends Node { - parent: JSDoc | JSDocTypeLiteral; + readonly parent: JSDoc | JSDocTypeLiteral; readonly tagName: Identifier; - comment?: string; + readonly comment?: string; } export interface JSDocUnknownTag extends JSDocTag { readonly kind: SyntaxKind.JSDocTag; @@ -1666,8 +1670,8 @@ declare namespace ts { readonly kind: SyntaxKind.JSDocClassTag; } export interface JSDocEnumTag extends JSDocTag, Declaration { - parent: JSDoc; readonly kind: SyntaxKind.JSDocEnumTag; + readonly parent: JSDoc; readonly typeExpression?: JSDocTypeExpression; } export interface JSDocThisTag extends JSDocTag { @@ -1688,15 +1692,15 @@ declare namespace ts { readonly typeExpression: JSDocTypeExpression; } export interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { - parent: JSDoc; readonly kind: SyntaxKind.JSDocTypedefTag; + readonly parent: JSDoc; readonly fullName?: JSDocNamespaceDeclaration | Identifier; readonly name?: Identifier; readonly typeExpression?: JSDocTypeExpression | JSDocTypeLiteral; } export interface JSDocCallbackTag extends JSDocTag, NamedDeclaration { - parent: JSDoc; readonly kind: SyntaxKind.JSDocCallbackTag; + readonly parent: JSDoc; readonly fullName?: JSDocNamespaceDeclaration | Identifier; readonly name?: Identifier; readonly typeExpression: JSDocSignature; @@ -1708,7 +1712,7 @@ declare namespace ts { readonly type: JSDocReturnTag | undefined; } export interface JSDocPropertyLikeTag extends JSDocTag, Declaration { - parent: JSDoc; + readonly parent: JSDoc; readonly name: EntityName; readonly typeExpression?: JSDocTypeExpression; /** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */ @@ -1855,28 +1859,28 @@ declare namespace ts { export type UnparsedSourceText = UnparsedPrepend | UnparsedTextLike; export type UnparsedNode = UnparsedPrologue | UnparsedSourceText | UnparsedSyntheticReference; export interface UnparsedSection extends Node { - parent: UnparsedSource; readonly kind: SyntaxKind; + readonly parent: UnparsedSource; readonly data?: string; } export interface UnparsedPrologue extends UnparsedSection { - parent: UnparsedSource; readonly kind: SyntaxKind.UnparsedPrologue; + readonly parent: UnparsedSource; readonly data: string; } export interface UnparsedPrepend extends UnparsedSection { - parent: UnparsedSource; readonly kind: SyntaxKind.UnparsedPrepend; + readonly parent: UnparsedSource; readonly data: string; readonly texts: readonly UnparsedTextLike[]; } export interface UnparsedTextLike extends UnparsedSection { - parent: UnparsedSource; readonly kind: SyntaxKind.UnparsedText | SyntaxKind.UnparsedInternalText; + readonly parent: UnparsedSource; } export interface UnparsedSyntheticReference extends UnparsedSection { - parent: UnparsedSource; readonly kind: SyntaxKind.UnparsedSyntheticReference; + readonly parent: UnparsedSource; } export interface JsonSourceFile extends SourceFile { readonly statements: NodeArray; @@ -3891,7 +3895,7 @@ declare namespace ts { function getEffectiveConstraintOfTypeParameter(node: TypeParameterDeclaration): TypeNode | undefined; } declare namespace ts { - function setTextRange(range: T, location: TextRange | undefined): T; + function setTextRange(range: T, location: ReadonlyTextRange | undefined): T; function isConstTypeReference(node: Node): boolean; function skipPartiallyEmittedExpressions(node: Expression): Expression; function skipPartiallyEmittedExpressions(node: Node): Node; @@ -10316,7 +10320,7 @@ declare namespace ts { /** * @deprecated Use `factory.createJSDocThisTag` or the factory supplied by your transformation context instead. */ - createJSDocThisTag: (tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression | undefined) => JSDocThisTag, + createJSDocThisTag: (tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression | undefined, comment?: string | undefined) => JSDocThisTag, /** * @deprecated Use `factory.createJSDocComment` or the factory supplied by your transformation context instead. */ @@ -10729,7 +10733,7 @@ declare namespace ts { * NOTE: It is unsafe to change any properties of a `Node` that relate to its AST children, as those changes won't be * captured with respect to transformations. * - * @deprecated Use `factory.cloneNode` instead and set `pos`, `end`, and `parent` as needed. + * @deprecated Use `factory.cloneNode` instead and use `setCommentRange` or `setSourceMapRange` and avoid setting `parent`. */ function getMutableClone(node: T): T; /** diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 7b69bbdb735..46c1f7ecf55 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -72,6 +72,10 @@ declare namespace ts { pos: number; end: number; } + export interface ReadonlyTextRange { + readonly pos: number; + readonly end: number; + } export enum SyntaxKind { Unknown = 0, EndOfFileToken = 1, @@ -500,12 +504,12 @@ declare namespace ts { IntrinsicIndexedElement = 2, IntrinsicElement = 3 } - export interface Node extends TextRange { + export interface Node extends ReadonlyTextRange { readonly kind: SyntaxKind; readonly flags: NodeFlags; readonly decorators?: NodeArray; readonly modifiers?: ModifiersArray; - parent: Node; + readonly parent: Node; } export interface JSDocContainer { } @@ -513,7 +517,7 @@ declare namespace ts { export type HasType = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertySignature | PropertyDeclaration | TypePredicateNode | ParenthesizedTypeNode | TypeOperatorNode | MappedTypeNode | AssertionExpression | TypeAliasDeclaration | JSDocTypeExpression | JSDocNonNullableType | JSDocNullableType | JSDocOptionalType | JSDocVariadicType; export type HasInitializer = HasExpressionInitializer | ForStatement | ForInStatement | ForOfStatement | JsxAttribute; export type HasExpressionInitializer = VariableDeclaration | ParameterDeclaration | BindingElement | PropertySignature | PropertyDeclaration | PropertyAssignment | EnumMember; - export interface NodeArray extends ReadonlyArray, TextRange { + export interface NodeArray extends ReadonlyArray, ReadonlyTextRange { hasTrailingComma?: boolean; } export interface Token extends Node { @@ -592,8 +596,8 @@ declare namespace ts { readonly name?: Identifier | StringLiteral | NumericLiteral; } export interface ComputedPropertyName extends Node { - parent: Declaration; readonly kind: SyntaxKind.ComputedPropertyName; + readonly parent: Declaration; readonly expression: Expression; } export interface Decorator extends Node { @@ -678,16 +682,16 @@ declare namespace ts { /** Unlike ObjectLiteralElement, excludes JSXAttribute and JSXSpreadAttribute. */ export type ObjectLiteralElementLike = PropertyAssignment | ShorthandPropertyAssignment | SpreadAssignment | MethodDeclaration | AccessorDeclaration; export interface PropertyAssignment extends ObjectLiteralElement, JSDocContainer { - parent: ObjectLiteralExpression; readonly kind: SyntaxKind.PropertyAssignment; + readonly parent: ObjectLiteralExpression; readonly name: PropertyName; readonly questionToken?: QuestionToken; readonly exclamationToken?: ExclamationToken; readonly initializer: Expression; } export interface ShorthandPropertyAssignment extends ObjectLiteralElement, JSDocContainer { - parent: ObjectLiteralExpression; readonly kind: SyntaxKind.ShorthandPropertyAssignment; + readonly parent: ObjectLiteralExpression; readonly name: Identifier; readonly questionToken?: QuestionToken; readonly exclamationToken?: ExclamationToken; @@ -695,8 +699,8 @@ declare namespace ts { readonly objectAssignmentInitializer?: Expression; } export interface SpreadAssignment extends ObjectLiteralElement, JSDocContainer { - parent: ObjectLiteralExpression; readonly kind: SyntaxKind.SpreadAssignment; + readonly parent: ObjectLiteralExpression; readonly expression: Expression; } export type VariableLikeDeclaration = VariableDeclaration | ParameterDeclaration | BindingElement | PropertyDeclaration | PropertyAssignment | PropertySignature | JsxAttribute | ShorthandPropertyAssignment | EnumMember | JSDocPropertyTag | JSDocParameterTag; @@ -704,13 +708,13 @@ declare namespace ts { readonly name: PropertyName; } export interface ObjectBindingPattern extends Node { - parent: VariableDeclaration | ParameterDeclaration | BindingElement; readonly kind: SyntaxKind.ObjectBindingPattern; + readonly parent: VariableDeclaration | ParameterDeclaration | BindingElement; readonly elements: NodeArray; } export interface ArrayBindingPattern extends Node { - parent: VariableDeclaration | ParameterDeclaration | BindingElement; readonly kind: SyntaxKind.ArrayBindingPattern; + readonly parent: VariableDeclaration | ParameterDeclaration | BindingElement; readonly elements: NodeArray; } export type BindingPattern = ObjectBindingPattern | ArrayBindingPattern; @@ -739,42 +743,42 @@ declare namespace ts { readonly body?: FunctionBody; } export interface MethodSignature extends SignatureDeclarationBase, TypeElement { - parent: ObjectTypeDeclaration; readonly kind: SyntaxKind.MethodSignature; + readonly parent: ObjectTypeDeclaration; readonly name: PropertyName; } export interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { - parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly kind: SyntaxKind.MethodDeclaration; + readonly parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly name: PropertyName; readonly body?: FunctionBody; } export interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer { - parent: ClassLikeDeclaration; readonly kind: SyntaxKind.Constructor; + readonly parent: ClassLikeDeclaration; readonly body?: FunctionBody; } /** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */ export interface SemicolonClassElement extends ClassElement { - parent: ClassLikeDeclaration; readonly kind: SyntaxKind.SemicolonClassElement; + readonly parent: ClassLikeDeclaration; } export interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { - parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly kind: SyntaxKind.GetAccessor; + readonly parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly name: PropertyName; readonly body?: FunctionBody; } export interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { - parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly kind: SyntaxKind.SetAccessor; + readonly parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly name: PropertyName; readonly body?: FunctionBody; } export type AccessorDeclaration = GetAccessorDeclaration | SetAccessorDeclaration; export interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement { - parent: ObjectTypeDeclaration; readonly kind: SyntaxKind.IndexSignature; + readonly parent: ObjectTypeDeclaration; readonly type: TypeNode; } export interface TypeNode extends Node { @@ -1078,15 +1082,15 @@ declare namespace ts { export type LiteralToken = NumericLiteral | BigIntLiteral | StringLiteral | JsxText | RegularExpressionLiteral | NoSubstitutionTemplateLiteral; export interface TemplateHead extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateHead; - parent: TemplateExpression; + readonly parent: TemplateExpression; } export interface TemplateMiddle extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateMiddle; - parent: TemplateSpan; + readonly parent: TemplateSpan; } export interface TemplateTail extends TemplateLiteralLikeNode { readonly kind: SyntaxKind.TemplateTail; - parent: TemplateSpan; + readonly parent: TemplateSpan; } export type PseudoLiteralToken = TemplateHead | TemplateMiddle | TemplateTail; export type TemplateLiteralToken = NoSubstitutionTemplateLiteral | PseudoLiteralToken; @@ -1097,8 +1101,8 @@ declare namespace ts { } export type TemplateLiteral = TemplateExpression | NoSubstitutionTemplateLiteral; export interface TemplateSpan extends Node { - parent: TemplateExpression; readonly kind: SyntaxKind.TemplateSpan; + readonly parent: TemplateExpression; readonly expression: Expression; readonly literal: TemplateMiddle | TemplateTail; } @@ -1111,8 +1115,8 @@ declare namespace ts { readonly elements: NodeArray; } export interface SpreadElement extends Expression { - parent: ArrayLiteralExpression | CallExpression | NewExpression; readonly kind: SyntaxKind.SpreadElement; + readonly parent: ArrayLiteralExpression | CallExpression | NewExpression; readonly expression: Expression; } /** @@ -1177,8 +1181,8 @@ declare namespace ts { readonly expression: ImportExpression; } export interface ExpressionWithTypeArguments extends NodeWithTypeArguments { - parent: HeritageClause | JSDocAugmentsTag; readonly kind: SyntaxKind.ExpressionWithTypeArguments; + readonly parent: HeritageClause | JSDocAugmentsTag; readonly expression: LeftHandSideExpression; } export interface NewExpression extends PrimaryExpression, Declaration { @@ -1227,12 +1231,12 @@ declare namespace ts { readonly expression: JsxTagNameExpression; } export interface JsxAttributes extends ObjectLiteralExpressionBase { - parent: JsxOpeningLikeElement; readonly kind: SyntaxKind.JsxAttributes; + readonly parent: JsxOpeningLikeElement; } export interface JsxOpeningElement extends Expression { - parent: JsxElement; readonly kind: SyntaxKind.JsxOpeningElement; + readonly parent: JsxElement; readonly tagName: JsxTagNameExpression; readonly typeArguments?: NodeArray; readonly attributes: JsxAttributes; @@ -1250,38 +1254,38 @@ declare namespace ts { readonly closingFragment: JsxClosingFragment; } export interface JsxOpeningFragment extends Expression { - parent: JsxFragment; readonly kind: SyntaxKind.JsxOpeningFragment; + readonly parent: JsxFragment; } export interface JsxClosingFragment extends Expression { - parent: JsxFragment; readonly kind: SyntaxKind.JsxClosingFragment; + readonly parent: JsxFragment; } export interface JsxAttribute extends ObjectLiteralElement { - parent: JsxAttributes; readonly kind: SyntaxKind.JsxAttribute; + readonly parent: JsxAttributes; readonly name: Identifier; readonly initializer?: StringLiteral | JsxExpression; } export interface JsxSpreadAttribute extends ObjectLiteralElement { - parent: JsxAttributes; readonly kind: SyntaxKind.JsxSpreadAttribute; + readonly parent: JsxAttributes; readonly expression: Expression; } export interface JsxClosingElement extends Node { - parent: JsxElement; readonly kind: SyntaxKind.JsxClosingElement; + readonly parent: JsxElement; readonly tagName: JsxTagNameExpression; } export interface JsxExpression extends Expression { - parent: JsxElement | JsxAttributeLike; readonly kind: SyntaxKind.JsxExpression; + readonly parent: JsxElement | JsxAttributeLike; readonly dotDotDotToken?: Token; readonly expression?: Expression; } export interface JsxText extends LiteralLikeNode { - parent: JsxElement; readonly kind: SyntaxKind.JsxText; + readonly parent: JsxElement; readonly containsOnlyTriviaWhiteSpaces: boolean; } export type JsxChild = JsxText | JsxExpression | JsxElement | JsxSelfClosingElement | JsxFragment; @@ -1382,19 +1386,19 @@ declare namespace ts { possiblyExhaustive?: boolean; } export interface CaseBlock extends Node { - parent: SwitchStatement; readonly kind: SyntaxKind.CaseBlock; + readonly parent: SwitchStatement; readonly clauses: NodeArray; } export interface CaseClause extends Node { - parent: CaseBlock; readonly kind: SyntaxKind.CaseClause; + readonly parent: CaseBlock; readonly expression: Expression; readonly statements: NodeArray; } export interface DefaultClause extends Node { - parent: CaseBlock; readonly kind: SyntaxKind.DefaultClause; + readonly parent: CaseBlock; readonly statements: NodeArray; } export type CaseOrDefaultClause = CaseClause | DefaultClause; @@ -1414,8 +1418,8 @@ declare namespace ts { readonly finallyBlock?: Block; } export interface CatchClause extends Node { - parent: TryStatement; readonly kind: SyntaxKind.CatchClause; + readonly parent: TryStatement; readonly variableDeclaration?: VariableDeclaration; readonly block: Block; } @@ -1455,8 +1459,8 @@ declare namespace ts { readonly members: NodeArray; } export interface HeritageClause extends Node { - parent: InterfaceDeclaration | ClassLikeDeclaration; readonly kind: SyntaxKind.HeritageClause; + readonly parent: InterfaceDeclaration | ClassLikeDeclaration; readonly token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword; readonly types: NodeArray; } @@ -1467,8 +1471,8 @@ declare namespace ts { readonly type: TypeNode; } export interface EnumMember extends NamedDeclaration, JSDocContainer { - parent: EnumDeclaration; readonly kind: SyntaxKind.EnumMember; + readonly parent: EnumDeclaration; readonly name: PropertyName; readonly initializer?: Expression; } @@ -1480,8 +1484,8 @@ declare namespace ts { export type ModuleName = Identifier | StringLiteral; export type ModuleBody = NamespaceBody | JSDocNamespaceBody; export interface ModuleDeclaration extends DeclarationStatement, JSDocContainer { - parent: ModuleBody | SourceFile; readonly kind: SyntaxKind.ModuleDeclaration; + readonly parent: ModuleBody | SourceFile; readonly name: ModuleName; readonly body?: ModuleBody | JSDocNamespaceDeclaration; } @@ -1496,8 +1500,8 @@ declare namespace ts { readonly body?: JSDocNamespaceBody; } export interface ModuleBlock extends Node, Statement { - parent: ModuleDeclaration; readonly kind: SyntaxKind.ModuleBlock; + readonly parent: ModuleDeclaration; readonly statements: NodeArray; } export type ModuleReference = EntityName | ExternalModuleReference; @@ -1507,33 +1511,33 @@ declare namespace ts { * - import x = M.x; */ export interface ImportEqualsDeclaration extends DeclarationStatement, JSDocContainer { - parent: SourceFile | ModuleBlock; readonly kind: SyntaxKind.ImportEqualsDeclaration; + readonly parent: SourceFile | ModuleBlock; readonly name: Identifier; readonly moduleReference: ModuleReference; } export interface ExternalModuleReference extends Node { - parent: ImportEqualsDeclaration; readonly kind: SyntaxKind.ExternalModuleReference; + readonly parent: ImportEqualsDeclaration; readonly expression: Expression; } export interface ImportDeclaration extends Statement, JSDocContainer { - parent: SourceFile | ModuleBlock; readonly kind: SyntaxKind.ImportDeclaration; + readonly parent: SourceFile | ModuleBlock; readonly importClause?: ImportClause; /** If this is not a StringLiteral it will be a grammar error. */ readonly moduleSpecifier: Expression; } export type NamedImportBindings = NamespaceImport | NamedImports; export interface ImportClause extends NamedDeclaration { - parent: ImportDeclaration; readonly kind: SyntaxKind.ImportClause; + readonly parent: ImportDeclaration; readonly name?: Identifier; readonly namedBindings?: NamedImportBindings; } export interface NamespaceImport extends NamedDeclaration { - parent: ImportClause; readonly kind: SyntaxKind.NamespaceImport; + readonly parent: ImportClause; readonly name: Identifier; } export interface NamespaceExportDeclaration extends DeclarationStatement, JSDocContainer { @@ -1541,33 +1545,33 @@ declare namespace ts { readonly name: Identifier; } export interface ExportDeclaration extends DeclarationStatement, JSDocContainer { - parent: SourceFile | ModuleBlock; readonly kind: SyntaxKind.ExportDeclaration; + readonly parent: SourceFile | ModuleBlock; /** Will not be assigned in the case of `export * from "foo";` */ readonly exportClause?: NamedExports; /** If this is not a StringLiteral it will be a grammar error. */ readonly moduleSpecifier?: Expression; } export interface NamedImports extends Node { - parent: ImportClause; readonly kind: SyntaxKind.NamedImports; + readonly parent: ImportClause; readonly elements: NodeArray; } export interface NamedExports extends Node { - parent: ExportDeclaration; readonly kind: SyntaxKind.NamedExports; + readonly parent: ExportDeclaration; readonly elements: NodeArray; } export type NamedImportsOrExports = NamedImports | NamedExports; export interface ImportSpecifier extends NamedDeclaration { - parent: NamedImports; readonly kind: SyntaxKind.ImportSpecifier; + readonly parent: NamedImports; readonly propertyName?: Identifier; readonly name: Identifier; } export interface ExportSpecifier extends NamedDeclaration { - parent: NamedExports; readonly kind: SyntaxKind.ExportSpecifier; + readonly parent: NamedExports; readonly propertyName?: Identifier; readonly name: Identifier; } @@ -1577,8 +1581,8 @@ declare namespace ts { * Unless `isExportEquals` is set, this node was parsed as an `export default`. */ export interface ExportAssignment extends DeclarationStatement, JSDocContainer { - parent: SourceFile; readonly kind: SyntaxKind.ExportAssignment; + readonly parent: SourceFile; readonly isExportEquals?: boolean; readonly expression: Expression; } @@ -1636,15 +1640,15 @@ declare namespace ts { } export type JSDocTypeReferencingNode = JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType; export interface JSDoc extends Node { - parent: HasJSDoc; readonly kind: SyntaxKind.JSDocComment; + readonly parent: HasJSDoc; readonly tags?: NodeArray; - comment?: string; + readonly comment?: string; } export interface JSDocTag extends Node { - parent: JSDoc | JSDocTypeLiteral; + readonly parent: JSDoc | JSDocTypeLiteral; readonly tagName: Identifier; - comment?: string; + readonly comment?: string; } export interface JSDocUnknownTag extends JSDocTag { readonly kind: SyntaxKind.JSDocTag; @@ -1666,8 +1670,8 @@ declare namespace ts { readonly kind: SyntaxKind.JSDocClassTag; } export interface JSDocEnumTag extends JSDocTag, Declaration { - parent: JSDoc; readonly kind: SyntaxKind.JSDocEnumTag; + readonly parent: JSDoc; readonly typeExpression?: JSDocTypeExpression; } export interface JSDocThisTag extends JSDocTag { @@ -1688,15 +1692,15 @@ declare namespace ts { readonly typeExpression: JSDocTypeExpression; } export interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { - parent: JSDoc; readonly kind: SyntaxKind.JSDocTypedefTag; + readonly parent: JSDoc; readonly fullName?: JSDocNamespaceDeclaration | Identifier; readonly name?: Identifier; readonly typeExpression?: JSDocTypeExpression | JSDocTypeLiteral; } export interface JSDocCallbackTag extends JSDocTag, NamedDeclaration { - parent: JSDoc; readonly kind: SyntaxKind.JSDocCallbackTag; + readonly parent: JSDoc; readonly fullName?: JSDocNamespaceDeclaration | Identifier; readonly name?: Identifier; readonly typeExpression: JSDocSignature; @@ -1708,7 +1712,7 @@ declare namespace ts { readonly type: JSDocReturnTag | undefined; } export interface JSDocPropertyLikeTag extends JSDocTag, Declaration { - parent: JSDoc; + readonly parent: JSDoc; readonly name: EntityName; readonly typeExpression?: JSDocTypeExpression; /** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */ @@ -1855,28 +1859,28 @@ declare namespace ts { export type UnparsedSourceText = UnparsedPrepend | UnparsedTextLike; export type UnparsedNode = UnparsedPrologue | UnparsedSourceText | UnparsedSyntheticReference; export interface UnparsedSection extends Node { - parent: UnparsedSource; readonly kind: SyntaxKind; + readonly parent: UnparsedSource; readonly data?: string; } export interface UnparsedPrologue extends UnparsedSection { - parent: UnparsedSource; readonly kind: SyntaxKind.UnparsedPrologue; + readonly parent: UnparsedSource; readonly data: string; } export interface UnparsedPrepend extends UnparsedSection { - parent: UnparsedSource; readonly kind: SyntaxKind.UnparsedPrepend; + readonly parent: UnparsedSource; readonly data: string; readonly texts: readonly UnparsedTextLike[]; } export interface UnparsedTextLike extends UnparsedSection { - parent: UnparsedSource; readonly kind: SyntaxKind.UnparsedText | SyntaxKind.UnparsedInternalText; + readonly parent: UnparsedSource; } export interface UnparsedSyntheticReference extends UnparsedSection { - parent: UnparsedSource; readonly kind: SyntaxKind.UnparsedSyntheticReference; + readonly parent: UnparsedSource; } export interface JsonSourceFile extends SourceFile { readonly statements: NodeArray; @@ -3891,7 +3895,7 @@ declare namespace ts { function getEffectiveConstraintOfTypeParameter(node: TypeParameterDeclaration): TypeNode | undefined; } declare namespace ts { - function setTextRange(range: T, location: TextRange | undefined): T; + function setTextRange(range: T, location: ReadonlyTextRange | undefined): T; function isConstTypeReference(node: Node): boolean; function skipPartiallyEmittedExpressions(node: Expression): Expression; function skipPartiallyEmittedExpressions(node: Node): Node; @@ -6859,7 +6863,7 @@ declare namespace ts { /** * @deprecated Use `factory.createJSDocThisTag` or the factory supplied by your transformation context instead. */ - createJSDocThisTag: (tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression | undefined) => JSDocThisTag, + createJSDocThisTag: (tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression | undefined, comment?: string | undefined) => JSDocThisTag, /** * @deprecated Use `factory.createJSDocComment` or the factory supplied by your transformation context instead. */ @@ -7272,7 +7276,7 @@ declare namespace ts { * NOTE: It is unsafe to change any properties of a `Node` that relate to its AST children, as those changes won't be * captured with respect to transformations. * - * @deprecated Use `factory.cloneNode` instead and set `pos`, `end`, and `parent` as needed. + * @deprecated Use `factory.cloneNode` instead and use `setCommentRange` or `setSourceMapRange` and avoid setting `parent`. */ function getMutableClone(node: T): T; /**