From f8e574f1d62986c8ad608dcf9fab7d94c780e034 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 4 Feb 2016 15:01:31 -0800 Subject: [PATCH 1/2] Added ArrayKind, moved createNode, changed JSDocParsing tests to use baselines. --- src/compiler/core.ts | 1 + src/compiler/factory.ts | 115 +- src/compiler/parser.ts | 118 +- src/compiler/types.ts | 19 +- src/compiler/utilities.ts | 62 +- src/compiler/visitor.ts | 221 +- src/services/breakpoints.ts | 36 +- src/services/services.ts | 6 +- ...ments.parsesCorrectly.leadingAsterisk.json | 37 + ...nts.parsesCorrectly.noLeadingAsterisk.json | 37 + ...Comments.parsesCorrectly.noReturnType.json | 27 + .../DocComments.parsesCorrectly.noType.json | 27 + ...cComments.parsesCorrectly.oneParamTag.json | 43 + ...DocComments.parsesCorrectly.paramTag1.json | 43 + ...arsesCorrectly.paramTagBracketedName1.json | 44 + ...arsesCorrectly.paramTagBracketedName2.json | 44 + ...parsesCorrectly.paramTagNameThenType1.json | 43 + ...parsesCorrectly.paramTagNameThenType2.json | 43 + ...ents.parsesCorrectly.paramWithoutType.json | 33 + ...ocComments.parsesCorrectly.returnTag1.json | 37 + ...ocComments.parsesCorrectly.returnTag2.json | 37 + ...cComments.parsesCorrectly.returnsTag1.json | 37 + ...cComments.parsesCorrectly.templateTag.json | 44 + ...Comments.parsesCorrectly.templateTag2.json | 55 + ...Comments.parsesCorrectly.templateTag3.json | 55 + ...Comments.parsesCorrectly.templateTag4.json | 55 + ...Comments.parsesCorrectly.templateTag5.json | 55 + ...Comments.parsesCorrectly.templateTag6.json | 55 + ...Comments.parsesCorrectly.twoParamTag2.json | 75 + ...parsesCorrectly.twoParamTagOnSameLine.json | 43 + .../DocComments.parsesCorrectly.typeTag.json | 37 + ...peExpressions.parsesCorrectly.allType.json | 5 + ...xpressions.parsesCorrectly.arrayType1.json | 16 + ...xpressions.parsesCorrectly.arrayType2.json | 21 + ...xpressions.parsesCorrectly.arrayType3.json | 26 + ...s.parsesCorrectly.functionReturnType1.json | 31 + ...essions.parsesCorrectly.functionType1.json | 11 + ...essions.parsesCorrectly.functionType2.json | 31 + ...eExpressions.parsesCorrectly.keyword1.json | 12 + ...eExpressions.parsesCorrectly.keyword2.json | 12 + ...eExpressions.parsesCorrectly.keyword3.json | 11 + ...eExpressions.parsesCorrectly.newType1.json | 27 + ...sions.parsesCorrectly.nonNullableType.json | 10 + ...ions.parsesCorrectly.nonNullableType2.json | 10 + ...ressions.parsesCorrectly.nullableType.json | 10 + ...essions.parsesCorrectly.nullableType2.json | 10 + ...ions.parsesCorrectly.optionalNullable.json | 10 + ...ressions.parsesCorrectly.optionalType.json | 10 + ...pressions.parsesCorrectly.recordType1.json | 11 + ...pressions.parsesCorrectly.recordType2.json | 22 + ...pressions.parsesCorrectly.recordType3.json | 27 + ...pressions.parsesCorrectly.recordType4.json | 33 + ...pressions.parsesCorrectly.recordType5.json | 38 + ...pressions.parsesCorrectly.recordType6.json | 38 + ...pressions.parsesCorrectly.recordType7.json | 43 + ...pressions.parsesCorrectly.recordType8.json | 23 + ...Expressions.parsesCorrectly.thisType1.json | 27 + ...sesCorrectly.topLevelNoParenUnionType.json | 21 + ...xpressions.parsesCorrectly.tupleType0.json | 11 + ...xpressions.parsesCorrectly.tupleType1.json | 16 + ...xpressions.parsesCorrectly.tupleType2.json | 21 + ...xpressions.parsesCorrectly.tupleType3.json | 26 + ...ssions.parsesCorrectly.typeReference1.json | 22 + ...ssions.parsesCorrectly.typeReference2.json | 27 + ...ssions.parsesCorrectly.typeReference3.json | 23 + ...Expressions.parsesCorrectly.unionType.json | 21 + ...pressions.parsesCorrectly.unknownType.json | 5 + ...ressions.parsesCorrectly.variadicType.json | 10 + tests/cases/unittests/jsDocParsing.ts | 2306 ++--------------- 69 files changed, 2225 insertions(+), 2393 deletions(-) create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.leadingAsterisk.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noLeadingAsterisk.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noReturnType.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noType.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.oneParamTag.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName1.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName2.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType1.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType2.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramWithoutType.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag1.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag2.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnsTag1.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag2.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag3.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag4.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag5.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag6.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTag2.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTagOnSameLine.json create mode 100644 tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typeTag.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.allType.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType1.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType2.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType3.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionReturnType1.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionType1.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionType2.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword1.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword2.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword3.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.newType1.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nonNullableType.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nonNullableType2.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nullableType.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nullableType2.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.optionalNullable.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.optionalType.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType1.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType2.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType3.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType4.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType5.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType6.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType7.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType8.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.thisType1.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.topLevelNoParenUnionType.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType0.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType1.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType2.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType3.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference1.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference2.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference3.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.unionType.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.unknownType.json create mode 100644 tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.variadicType.json diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 48abb6ae3e3..14d49604f67 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -866,6 +866,7 @@ namespace ts { this.end = end; this.flags = NodeFlags.None; this.parent = undefined; + this.original = undefined; } export let objectAllocator: ObjectAllocator = { diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 06eb4b98b9c..d838288ef25 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -1,53 +1,134 @@ -/// +/// /// -/* @internal */ + namespace ts { - export function createNodeArray(elements?: T[], location?: TextRange): NodeArray; - export function createNodeArray>(elements: TArray, location?: TextRange): TArray; - export function createNodeArray>(elements?: T[], location?: TextRange): TArray { - const array = (elements || []); - if (location) { - array.pos = location.pos; - array.end = location.end; - } - else if (array.pos === undefined || array.end === undefined) { - array.pos = -1; - array.end = -1; - } + let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; + let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; + export function createNode(kind: SyntaxKind, pos?: number, end?: number): Node { + if (kind === SyntaxKind.SourceFile) { + return new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, pos, end); + } + else { + return new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, pos, end); + } + } + + /* @internal */ + export function createNodeArray(elements?: T[], pos?: number, end?: number): NodeArray { + const array = >(elements || []); + array.pos = pos; + array.end = end; + array.arrayKind = ArrayKind.NodeArray; return array; } - export function createNodeArrayNode(elements?: (T | NodeArrayNode)[]): NodeArrayNode { - const array = >createNodeArray(elements); - array.kind = SyntaxKind.NodeArrayNode; + /* @internal */ + export function createModifiersArray(elements?: Modifier[], pos?: number, end?: number): ModifiersArray { + const array = (elements || []); + array.pos = pos; + array.end = end; + array.arrayKind = ArrayKind.ModifiersArray; + array.flags = 0; return array; } + /* @internal */ + export function createSynthesizedNode(kind: SyntaxKind, startsOnNewLine?: boolean): Node { + const node = createNode(kind, /*pos*/ -1, /*end*/ -1); + node.startsOnNewLine = startsOnNewLine; + return node; + } + + /* @internal */ + export function createSynthesizedNodeArray(elements?: T[]): NodeArray { + return createNodeArray(elements, /*pos*/ -1, /*end*/ -1); + } + + /* @internal */ + export function createSynthesizedModifiersArray(elements?: Modifier[]): ModifiersArray { + return createModifiersArray(elements, /*pos*/ -1, /*end*/ -1); + } + + /** + * Creates a shallow, memberwise clone of a node. The "kind", "pos", "end", "flags", and "parent" + * properties are excluded by default, and can be provided via the "location", "flags", and + * "parent" parameters. + * + * @param node The node to clone. + * @param location An optional TextRange to use to supply the new position. + * @param flags The NodeFlags to use for the cloned node. + * @param parent The parent for the new node. + * @param original An optional pointer to the original source tree node. + */ + /* @internal */ + export function cloneNode(node: T, location?: TextRange, flags?: NodeFlags, parent?: Node, original?: Node): T { + // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of + // the original node. We also need to exclude specific properties and only include own- + // properties (to skip members already defined on the shared prototype). + const clone = location !== undefined + ? createNode(node.kind, location.pos, location.end) + : createSynthesizedNode(node.kind); + + for (const key in node) { + if (clone.hasOwnProperty(key) || !node.hasOwnProperty(key)) { + continue; + } + + (clone)[key] = (node)[key]; + } + + if (flags !== undefined) { + clone.flags = flags; + } + + if (parent !== undefined) { + clone.parent = parent; + } + + if (original !== undefined) { + clone.original = original; + } + + return clone; + } + + /* @internal */ + export function createNodeArrayNode(elements: T[]): NodeArrayNode { + const node = >createSynthesizedNode(SyntaxKind.NodeArrayNode); + node.nodes = createNodeArray(elements); + return node; + } + + /* @internal */ export function createReturn(expression?: Expression): ReturnStatement { const node = createSynthesizedNode(SyntaxKind.ReturnStatement); node.expression = expression; return node; } + /* @internal */ export function createStatement(expression: Expression): ExpressionStatement { const node = createSynthesizedNode(SyntaxKind.ExpressionStatement); node.expression = expression; return node; } + /* @internal */ export function createVariableStatement(declarationList: VariableDeclarationList): VariableStatement { const node = createSynthesizedNode(SyntaxKind.VariableStatement); node.declarationList = declarationList; return node; } + /* @internal */ export function createVariableDeclarationList(declarations: VariableDeclaration[]): VariableDeclarationList { const node = createSynthesizedNode(SyntaxKind.VariableDeclarationList); node.declarations = createNodeArray(declarations); return node; } + /* @internal */ export function createBlock(statements: Statement[]): Block { const block = createSynthesizedNode(SyntaxKind.Block); block.statements = createNodeArray(statements); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index f866b86fca2..1d9f9fe2305 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1,21 +1,10 @@ /// /// +/// namespace ts { /* @internal */ export let parseTime = 0; - let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; - let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; - - export function createNode(kind: SyntaxKind, pos?: number, end?: number): Node { - if (kind === SyntaxKind.SourceFile) { - return new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, pos, end); - } - else { - return new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, pos, end); - } - } - function visitNode(cbNode: (node: Node) => T, node: Node): T { if (node) { return cbNode(node); @@ -875,7 +864,7 @@ namespace ts { /** Invokes the provided callback then unconditionally restores the parser to the state it * was in immediately prior to invoking the callback. The result of invoking the callback - * is returned from this function. + * is returned from this function. */ function lookAhead(callback: () => T): T { return speculationHelper(callback, /*isLookAhead*/ true); @@ -989,6 +978,29 @@ namespace ts { return new NodeConstructor(kind, pos, pos); } + function createNodeArray(elements?: T[], pos?: number): NodeArray { + const array = >(elements || []); + if (!(pos >= 0)) { + pos = getNodePos(); + } + array.pos = pos; + array.end = pos; + array.arrayKind = ArrayKind.NodeArray; + return array; + } + + function createModifiersArray(elements?: Modifier[], pos?: number): ModifiersArray { + const array = (elements || []); + if (!(pos >= 0)) { + pos = getNodePos(); + } + array.pos = pos; + array.end = pos; + array.arrayKind = ArrayKind.ModifiersArray; + array.flags = 0; + return array; + } + function finishNode(node: T, end?: number): T { node.end = end === undefined ? scanner.getStartPos() : end; @@ -1374,8 +1386,7 @@ namespace ts { function parseList(kind: ParsingContext, parseElement: () => T): NodeArray { const saveParsingContext = parsingContext; parsingContext |= 1 << kind; - const result = >[]; - result.pos = getNodePos(); + const result = createNodeArray(); while (!isListTerminator(kind)) { if (isListElement(kind, /*inErrorRecovery*/ false)) { @@ -1722,8 +1733,7 @@ namespace ts { function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimeter?: boolean): NodeArray { const saveParsingContext = parsingContext; parsingContext |= 1 << kind; - const result = >[]; - result.pos = getNodePos(); + const result = createNodeArray(); let commaStart = -1; // Meaning the previous token was not a comma while (true) { @@ -1778,12 +1788,8 @@ namespace ts { return result; } - function createMissingList(): NodeArray { - const pos = getNodePos(); - const result = >[]; - result.pos = pos; - result.end = pos; - return result; + function createMissingList(): NodeArray { + return createNodeArray(); } function parseBracketedList(kind: ParsingContext, parseElement: () => T, open: SyntaxKind, close: SyntaxKind): NodeArray { @@ -1848,8 +1854,7 @@ namespace ts { template.head = parseTemplateLiteralFragment(); Debug.assert(template.head.kind === SyntaxKind.TemplateHead, "Template head has wrong token kind"); - const templateSpans = >[]; - templateSpans.pos = getNodePos(); + const templateSpans = createNodeArray(); do { templateSpans.push(parseTemplateSpan()); @@ -2425,8 +2430,7 @@ namespace ts { function parseUnionOrIntersectionType(kind: SyntaxKind, parseConstituentType: () => TypeNode, operator: SyntaxKind): TypeNode { let type = parseConstituentType(); if (token === operator) { - const types = >[type]; - types.pos = type.pos; + const types = createNodeArray([type], type.pos); while (parseOptional(operator)) { types.push(parseConstituentType()); } @@ -2781,8 +2785,7 @@ namespace ts { parameter.name = identifier; finishNode(parameter); - node.parameters = >[parameter]; - node.parameters.pos = parameter.pos; + node.parameters = createNodeArray([parameter], parameter.pos); node.parameters.end = parameter.end; node.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, "=>"); @@ -3557,8 +3560,7 @@ namespace ts { } function parseJsxChildren(openingTagName: EntityName): NodeArray { - const result = >[]; - result.pos = scanner.getStartPos(); + const result = createNodeArray(); const saveParsingContext = parsingContext; parsingContext |= 1 << ParsingContext.JsxChildren; @@ -4922,14 +4924,15 @@ namespace ts { break; } - if (!decorators) { - decorators = >[]; - decorators.pos = decoratorStart; - } - const decorator = createNode(SyntaxKind.Decorator, decoratorStart); decorator.expression = doInDecoratorContext(parseLeftHandSideExpressionOrHigher); - decorators.push(finishNode(decorator)); + finishNode(decorator); + if (!decorators) { + decorators = createNodeArray([decorator], decoratorStart); + } + else { + decorators.push(decorator); + } } if (decorators) { decorators.end = getNodeEnd(); @@ -4953,7 +4956,7 @@ namespace ts { if (token === SyntaxKind.ConstKeyword && permitInvalidConstAsModifier) { // We need to ensure that any subsequent modifiers appear on the same line - // so that when 'const' is a standalone declaration, we don't issue an error. + // so that when 'const' is a standalone declaration, we don't issue an error. if (!tryParse(nextTokenIsOnSameLineAndCanFollowModifier)) { break; } @@ -4964,13 +4967,14 @@ namespace ts { } } - if (!modifiers) { - modifiers = []; - modifiers.pos = modifierStart; - } - flags |= modifierToFlag(modifierKind); - modifiers.push(finishNode(createNode(modifierKind, modifierStart))); + const modifier = finishNode(createNode(modifierKind, modifierStart)); + if (!modifiers) { + modifiers = createModifiersArray([modifier], modifierStart); + } + else { + modifiers.push(modifier); + } } if (modifiers) { modifiers.flags = flags; @@ -4980,17 +4984,14 @@ namespace ts { } function parseModifiersForArrowFunction(): ModifiersArray { - let flags = 0; let modifiers: ModifiersArray; if (token === SyntaxKind.AsyncKeyword) { const modifierStart = scanner.getStartPos(); const modifierKind = token; nextToken(); - modifiers = []; - modifiers.pos = modifierStart; - flags |= modifierToFlag(modifierKind); - modifiers.push(finishNode(createNode(modifierKind, modifierStart))); - modifiers.flags = flags; + const modifier = finishNode(createNode(modifierKind, modifierStart)); + modifiers = createModifiersArray([modifier], modifierStart); + modifiers.flags = modifierToFlag(modifierKind); modifiers.end = scanner.getStartPos(); } @@ -5216,7 +5217,7 @@ namespace ts { node.decorators = decorators; setModifiers(node, modifiers); if (token === SyntaxKind.GlobalKeyword) { - // parse 'global' as name of global scope augmentation + // parse 'global' as name of global scope augmentation node.name = parseIdentifier(); node.flags |= NodeFlags.GlobalAugmentation; } @@ -5848,10 +5849,8 @@ namespace ts { function parseJSDocTypeList(firstType: JSDocType) { Debug.assert(!!firstType); - const types = >[]; - types.pos = firstType.pos; + const types = createNodeArray([firstType], firstType.pos); - types.push(firstType); while (parseOptional(SyntaxKind.BarToken)) { types.push(parseJSDocType()); } @@ -6059,11 +6058,11 @@ namespace ts { function addTag(tag: JSDocTag): void { if (tag) { if (!tags) { - tags = >[]; - tags.pos = tag.pos; + tags = createNodeArray([tag], tag.pos); + } + else { + tags.push(tag); } - - tags.push(tag); tags.end = tag.end; } } @@ -6156,8 +6155,7 @@ namespace ts { } // Type parameter list looks like '@template T,U,V' - const typeParameters = >[]; - typeParameters.pos = scanner.getStartPos(); + const typeParameters = createNodeArray(); while (true) { const name = parseJSDocIdentifier(); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d2d436f545f..177934fc13b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -454,12 +454,27 @@ namespace ts { /* @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes) } - export interface NodeArray extends Array, TextRange { + export const enum ArrayKind { + NodeArray = 1, + ModifiersArray = 2, + } + + export interface NodeArray extends Array, TextRange { + arrayKind: ArrayKind; hasTrailingComma?: boolean; } + /** + * A NodeArrayNode is a transient node used during transformations to indicate that more than + * one node will substitute a single node in the source. When the source is a NodeArray (as + * part of a call to `visitNodes`), the nodes of a NodeArrayNode will be spread into the + * result array. When the source is a Node (as part of a call to `visitNode`), the NodeArrayNode + * must be converted into a compatible node via the `lift` callback. + */ + /* @internal */ // @kind(SyntaxKind.NodeArrayNode) - export interface NodeArrayNode extends Node, NodeArray> { + export interface NodeArrayNode extends Node { + nodes: NodeArray; } export interface ModifiersArray extends NodeArray { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 9fe32c89a69..a6df27bc3b9 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1647,47 +1647,6 @@ namespace ts { return isFunctionLike(n) || n.kind === SyntaxKind.ModuleDeclaration || n.kind === SyntaxKind.SourceFile; } - /** - * Creates a shallow, memberwise clone of a node. The "kind", "pos", "end", "flags", and "parent" - * properties are excluded by default, and can be provided via the "location", "flags", and - * "parent" parameters. - * @param node The node to clone. - * @param location An optional TextRange to use to supply the new position. - * @param flags The NodeFlags to use for the cloned node. - * @param parent The parent for the new node. - * @param original An optional pointer to the original node. - */ - export function cloneNode(node: T, location?: TextRange, flags?: NodeFlags, parent?: Node, original?: Node): T { - // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of - // the original node. We also need to exclude specific properties and only include own- - // properties (to skip members already defined on the shared prototype). - const clone = location !== undefined - ? createNode(node.kind, location.pos, location.end) - : createSynthesizedNode(node.kind); - - for (const key in node) { - if (key === "parent" || key === "flags" || clone.hasOwnProperty(key) || !node.hasOwnProperty(key)) { - continue; - } - - (clone)[key] = (node)[key]; - } - - if (flags !== undefined) { - clone.flags = flags; - } - - if (parent !== undefined) { - clone.parent = parent; - } - - if (original !== undefined) { - clone.original = original; - } - - return clone; - } - /** * Creates a deep clone of an EntityName, with new parent pointers. * @param node The EntityName to clone. @@ -1719,19 +1678,6 @@ namespace ts { return !(pos >= 0); } - export function createSynthesizedNode(kind: SyntaxKind, startsOnNewLine?: boolean): Node { - const node = createNode(kind, /* pos */ -1, /* end */ -1); - node.startsOnNewLine = startsOnNewLine; - return node; - } - - export function createSynthesizedNodeArray(): NodeArray { - const array = >[]; - array.pos = -1; - array.end = -1; - return array; - } - export function getOriginalNode(node: Node): Node { while (node.original !== undefined) { node = node.original; @@ -2728,12 +2674,12 @@ namespace ts { return false; } - export function isModifiersArray(nodes: NodeArray): nodes is ModifiersArray { - return !isNodeArrayNode(nodes) && typeof (nodes).flags === "number"; + export function isModifiersArray(array: NodeArray): array is ModifiersArray { + return array.arrayKind === ArrayKind.ModifiersArray; } - export function isNodeArrayNode(value: Node | NodeArray>): value is NodeArrayNode { - return (value).kind === SyntaxKind.NodeArrayNode; + export function isNodeArrayNode(node: Node): node is NodeArrayNode { + return node.kind === SyntaxKind.NodeArrayNode; } export function getLocalSymbolForExportDefault(symbol: Symbol) { diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 30717578eb8..a75e79565c5 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -1,5 +1,5 @@ /// -/// + /* @internal */ namespace ts { /** Additional context provided to `visitEachChild` */ @@ -15,9 +15,6 @@ namespace ts { * Describes an edge of a Node, used when traversing a syntax tree. */ interface NodeEdge { - /** Indicates that the edge is a NodeArray. */ - array?: boolean; - /** Indicates that the result is optional. */ optional?: boolean; @@ -25,7 +22,7 @@ namespace ts { test?: (node: Node) => node is Node; /** A callback used to lift a NodeArrayNode into a valid node. */ - lift?: (nodes: NodeArrayNode) => Node; + lift?: (nodes: NodeArray) => Node; }; /** @@ -55,8 +52,8 @@ namespace ts { expression: { test: isExpressionNode }, }, [SyntaxKind.Parameter]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, name: { test: isBindingPatternOrIdentifier }, type: { test: isTypeNodeNode, optional: true }, initializer: { test: isExpressionNode, optional: true }, @@ -65,52 +62,52 @@ namespace ts { expression: { test: isLeftHandSideExpression }, }, [SyntaxKind.PropertyDeclaration]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, name: { test: isPropertyName }, type: { test: isTypeNodeNode, optional: true }, initializer: { test: isExpressionNode, optional: true }, }, [SyntaxKind.MethodDeclaration]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, name: { test: isPropertyName }, - typeParameters: { test: isTypeParameter, array: true }, - parameters: { test: isParameter, array: true }, + typeParameters: { test: isTypeParameter }, + parameters: { test: isParameter }, type: { test: isTypeNodeNode, optional: true }, body: { test: isBlock, optional: true }, }, [SyntaxKind.Constructor]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, - typeParameters: { test: isTypeParameter, array: true }, - parameters: { test: isParameter, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, + typeParameters: { test: isTypeParameter }, + parameters: { test: isParameter }, type: { test: isTypeNodeNode, optional: true }, body: { test: isBlock, optional: true }, }, [SyntaxKind.GetAccessor]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, name: { test: isPropertyName }, - typeParameters: { test: isTypeParameter, array: true }, - parameters: { test: isParameter, array: true }, + typeParameters: { test: isTypeParameter }, + parameters: { test: isParameter }, type: { test: isTypeNodeNode, optional: true }, body: { test: isBlock, optional: true }, }, [SyntaxKind.SetAccessor]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, name: { test: isPropertyName }, - typeParameters: { test: isTypeParameter, array: true }, - parameters: { test: isParameter, array: true }, + typeParameters: { test: isTypeParameter }, + parameters: { test: isParameter }, type: { test: isTypeNodeNode, optional: true }, body: { test: isBlock, optional: true }, }, [SyntaxKind.ObjectBindingPattern]: { - elements: { test: isBindingElement, array: true }, + elements: { test: isBindingElement }, }, [SyntaxKind.ArrayBindingPattern]: { - elements: { test: isBindingElement, array: true }, + elements: { test: isBindingElement }, }, [SyntaxKind.BindingElement]: { propertyName: { test: isPropertyName, optional: true }, @@ -118,10 +115,10 @@ namespace ts { initializer: { test: isExpressionNode, optional: true }, }, [SyntaxKind.ArrayLiteralExpression]: { - elements: { test: isExpressionNode, array: true }, + elements: { test: isExpressionNode }, }, [SyntaxKind.ObjectLiteralExpression]: { - properties: { test: isObjectLiteralElement, array: true }, + properties: { test: isObjectLiteralElement }, }, [SyntaxKind.PropertyAccessExpression]: { expression: { test: isLeftHandSideExpression }, @@ -133,13 +130,13 @@ namespace ts { }, [SyntaxKind.CallExpression]: { expression: { test: isLeftHandSideExpression }, - typeArguments: { test: isTypeNodeNode, array: true }, - arguments: { test: isExpressionNode, array: true }, + typeArguments: { test: isTypeNodeNode }, + arguments: { test: isExpressionNode }, }, [SyntaxKind.NewExpression]: { expression: { test: isLeftHandSideExpression }, - typeArguments: { test: isTypeNodeNode, array: true }, - arguments: { test: isExpressionNode, array: true }, + typeArguments: { test: isTypeNodeNode }, + arguments: { test: isExpressionNode }, }, [SyntaxKind.TaggedTemplateExpression]: { tag: { test: isLeftHandSideExpression }, @@ -153,19 +150,19 @@ namespace ts { expression: { test: isExpressionNode }, }, [SyntaxKind.FunctionExpression]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, name: { test: isIdentifierNode, optional: true }, - typeParameters: { test: isTypeParameter, array: true }, - parameters: { test: isParameter, array: true }, + typeParameters: { test: isTypeParameter }, + parameters: { test: isParameter }, type: { test: isTypeNodeNode, optional: true }, body: { test: isBlock, optional: true }, }, [SyntaxKind.ArrowFunction]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, - typeParameters: { test: isTypeParameter, array: true }, - parameters: { test: isParameter, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, + typeParameters: { test: isTypeParameter }, + parameters: { test: isParameter }, type: { test: isTypeNodeNode, optional: true }, body: { test: isConciseBody, lift: liftToBlock }, }, @@ -198,7 +195,7 @@ namespace ts { }, [SyntaxKind.TemplateExpression]: { head: { test: isTemplateLiteralFragment }, - templateSpans: { test: isTemplateSpan, array: true }, + templateSpans: { test: isTemplateSpan }, }, [SyntaxKind.YieldExpression]: { expression: { test: isExpressionNode, optional: true }, @@ -207,16 +204,16 @@ namespace ts { expression: { test: isExpressionNode }, }, [SyntaxKind.ClassExpression]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, name: { test: isIdentifierNode, optional: true }, - typeParameters: { test: isTypeParameter, array: true }, - heritageClauses: { test: isHeritageClause, array: true }, - members: { test: isClassElement, array: true }, + typeParameters: { test: isTypeParameter }, + heritageClauses: { test: isHeritageClause }, + members: { test: isClassElement }, }, [SyntaxKind.ExpressionWithTypeArguments]: { expression: { test: isLeftHandSideExpression }, - typeArguments: { test: isTypeNodeNode, array: true }, + typeArguments: { test: isTypeNodeNode }, }, [SyntaxKind.AsExpression]: { expression: { test: isExpressionNode }, @@ -227,11 +224,11 @@ namespace ts { literal: { test: isTemplateLiteralFragment }, }, [SyntaxKind.Block]: { - statements: { test: isStatementNode, array: true }, + statements: { test: isStatementNode }, }, [SyntaxKind.VariableStatement]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, declarationList: { test: isVariableDeclarationList }, }, [SyntaxKind.ExpressionStatement]: { @@ -301,52 +298,52 @@ namespace ts { initializer: { test: isExpressionNode, optional: true }, }, [SyntaxKind.VariableDeclarationList]: { - declarations: { test: isVariableDeclaration, array: true }, + declarations: { test: isVariableDeclaration }, }, [SyntaxKind.FunctionDeclaration]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, name: { test: isIdentifierNode, optional: true }, - typeParameters: { test: isTypeParameter, array: true }, - parameters: { test: isParameter, array: true }, + typeParameters: { test: isTypeParameter }, + parameters: { test: isParameter }, type: { test: isTypeNodeNode, optional: true }, body: { test: isBlock, optional: true }, }, [SyntaxKind.ClassDeclaration]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, name: { test: isIdentifierNode, optional: true }, - typeParameters: { test: isTypeParameter, array: true }, - heritageClauses: { test: isHeritageClause, array: true }, - members: { test: isClassElement, array: true }, + typeParameters: { test: isTypeParameter }, + heritageClauses: { test: isHeritageClause }, + members: { test: isClassElement }, }, [SyntaxKind.EnumDeclaration]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, name: { test: isIdentifierNode }, - members: { test: isEnumMember, array: true }, + members: { test: isEnumMember }, }, [SyntaxKind.ModuleDeclaration]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, name: { test: isModuleName }, body: { test: isModuleBody }, }, [SyntaxKind.ModuleBlock]: { - statements: { test: isStatementNode, array: true }, + statements: { test: isStatementNode }, }, [SyntaxKind.CaseBlock]: { - clauses: { test: isCaseOrDefaultClause, array: true }, + clauses: { test: isCaseOrDefaultClause }, }, [SyntaxKind.ImportEqualsDeclaration]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, name: { test: isIdentifierNode }, moduleReference: { test: isModuleReference }, }, [SyntaxKind.ImportDeclaration]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, importClause: { test: isImportClause, optional: true }, moduleSpecifier: { test: isExpressionNode }, }, @@ -358,25 +355,25 @@ namespace ts { name: { test: isIdentifierNode }, }, [SyntaxKind.NamedImports]: { - elements: { test: isImportSpecifier, array: true }, + elements: { test: isImportSpecifier }, }, [SyntaxKind.ImportSpecifier]: { propertyName: { test: isIdentifierNode, optional: true }, name: { test: isIdentifierNode }, }, [SyntaxKind.ExportAssignment]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, expression: { test: isExpressionNode }, }, [SyntaxKind.ExportDeclaration]: { - decorators: { test: isDecorator, array: true }, - modifiers: { test: isModifier, array: true }, + decorators: { test: isDecorator }, + modifiers: { test: isModifier }, exportClause: { test: isNamedExports, optional: true }, moduleSpecifier: { test: isExpressionNode, optional: true }, }, [SyntaxKind.NamedExports]: { - elements: { test: isExportSpecifier, array: true }, + elements: { test: isExportSpecifier }, }, [SyntaxKind.ExportSpecifier]: { propertyName: { test: isIdentifierNode, optional: true }, @@ -387,16 +384,16 @@ namespace ts { }, [SyntaxKind.JsxElement]: { openingElement: { test: isJsxOpeningElement }, - children: { test: isJsxChild, array: true }, + children: { test: isJsxChild }, closingElement: { test: isJsxClosingElement }, }, [SyntaxKind.JsxSelfClosingElement]: { tagName: { test: isEntityName }, - attributes: { test: isJsxAttributeOrJsxSpreadAttribute, array: true }, + attributes: { test: isJsxAttributeOrJsxSpreadAttribute }, }, [SyntaxKind.JsxOpeningElement]: { tagName: { test: isEntityName }, - attributes: { test: isJsxAttributeOrJsxSpreadAttribute, array: true }, + attributes: { test: isJsxAttributeOrJsxSpreadAttribute }, }, [SyntaxKind.JsxClosingElement]: { tagName: { test: isEntityName }, @@ -413,13 +410,13 @@ namespace ts { }, [SyntaxKind.CaseClause]: { expression: { test: isExpressionNode }, - statements: { test: isStatementNode, array: true }, + statements: { test: isStatementNode }, }, [SyntaxKind.DefaultClause]: { - statements: { test: isStatementNode, array: true }, + statements: { test: isStatementNode }, }, [SyntaxKind.HeritageClause]: { - types: { test: isExpressionWithTypeArguments, array: true }, + types: { test: isExpressionWithTypeArguments }, }, [SyntaxKind.CatchClause]: { variableDeclaration: { test: isVariableDeclaration }, @@ -438,7 +435,7 @@ namespace ts { initializer: { test: isExpressionNode, optional: true }, }, [SyntaxKind.SourceFile]: { - statements: { test: isStatementNode, array: true }, + statements: { test: isStatementNode }, }, }; @@ -462,13 +459,9 @@ namespace ts { for (const propertyName in edgeTraversalPath) { const value = (>node)[propertyName]; if (value !== undefined) { - const edge = edgeTraversalPath[propertyName]; - if (edge.array) { - result = reduceLeft(>value, f, result); - } - else { - result = f(result, value); - } + result = isArray(value) + ? reduceLeft(>value, f, result) + : f(result, value); } } } @@ -485,7 +478,7 @@ namespace ts { * @param lift A callback to execute to lift a NodeArrayNode into a valid Node. * @param optional A value indicating whether the Node is optional. */ - export function visitNode(node: T, visitor: (node: Node) => Node, test?: (node: Node) => boolean, lift?: (node: NodeArrayNode) => T, optional?: boolean): T { + export function visitNode(node: T, visitor: (node: Node) => Node, test?: (node: Node) => boolean, lift?: (node: NodeArray) => T, optional?: boolean): T { if (node === undefined) { return undefined; } @@ -501,10 +494,7 @@ namespace ts { return undefined; } - if (test !== undefined) { - Debug.assert(test(visited), "Wrong node type after visit."); - } - + Debug.assert(test === undefined || test(visited), "Wrong node type after visit."); return visited; } @@ -520,7 +510,7 @@ namespace ts { return undefined; } - let updated: TArray; + let updated: NodeArray | ModifiersArray; for (let i = 0, len = nodes.length; i < len; i++) { const node = nodes[i]; if (node === undefined) { @@ -530,7 +520,9 @@ namespace ts { const visited = visitor(node); if (updated !== undefined || visited === undefined || visited !== node) { if (updated === undefined) { - updated = createNodeArray(nodes.slice(0, i), /*location*/ nodes); + updated = isModifiersArray(nodes) + ? createModifiersArray(nodes.slice(0, i), nodes.pos, nodes.end) + : createNodeArray(nodes.slice(0, i), nodes.pos, nodes.end); } if (visited === undefined) { @@ -541,22 +533,22 @@ namespace ts { spreadNodeArrayNode(visited, updated, test); } else if (visited !== undefined) { - Debug.assert(test(visited), "Wrong node type after visit."); + Debug.assert(test === undefined || test(visited), "Wrong node type after visit."); updated.push(visited); } } } - if (updated && isModifiersArray(nodes)) { + if (updated && isModifiersArray(updated)) { let flags: NodeFlags = 0; for (const node of updated) { flags |= modifierToFlag(node.kind); } - (>updated).flags = flags; + updated.flags = flags; } - return updated || nodes; + return updated || nodes; } /** @@ -592,8 +584,8 @@ namespace ts { updated[propertyName] = visited; } - if (visited && edge.array && isModifiersArray(>visited)) { - updated.flags |= (visited).flags; + if (visited && isArray(visited) && isModifiersArray(visited)) { + updated.flags |= visited.flags; } } } @@ -621,7 +613,7 @@ namespace ts { * @param visitor A callback used to visit the node. */ function visitEdge(edge: NodeEdge, value: Node | NodeArray, visitor: (node: Node) => Node) { - return edge.array + return isArray(value) ? visitNodes(>value, visitor, edge.test) : visitNode(value, visitor, edge.test, edge.lift, edge.optional); } @@ -634,18 +626,13 @@ namespace ts { * @param test The node test used to validate each node. */ function spreadNodeArrayNode(source: NodeArrayNode, dest: NodeArray, test: (node: Node) => boolean) { - for (const element of source) { + for (const element of source.nodes) { if (element === undefined) { continue; } - if (isNodeArrayNode(element)) { - spreadNodeArrayNode(element, dest, test); - } - else { - Debug.assert(test === undefined || test(element), "Wrong node type after visit."); - dest.push(element); - } + Debug.assert(test === undefined || test(element), "Wrong node type after visit."); + dest.push(element); } } @@ -724,7 +711,7 @@ namespace ts { * Merge generated declarations of a lexical environment into a NodeArray of Statement. */ function mergeStatements(statements: NodeArray, declarations: Statement[]) { - return createNodeArray(statements.concat(declarations), /*location*/ statements); + return createNodeArray(statements.concat(declarations), statements.pos, statements.end); } /** @@ -734,13 +721,13 @@ namespace ts { * @param node The visited Node. * @param options Options used to control lift behavior. */ - function liftNode(node: Node, lifter: (nodes: NodeArrayNode) => Node): Node { + function liftNode(node: Node, lifter: (nodes: NodeArray) => Node): Node { if (node === undefined) { return undefined; } else if (isNodeArrayNode(node)) { const lift = lifter || extractSingleNode; - return lift(node); + return lift(node.nodes); } else { return node; diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index 4cd361734e3..1c4d5957a02 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0. +// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0. // See LICENSE.txt in the project root for complete license information. /// @@ -19,8 +19,8 @@ namespace ts.BreakpointResolver { if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart(sourceFile)).line > lineOfPosition) { // Get previous token if the token is returned starts on new line // eg: let x =10; |--- cursor is here - // let y = 10; - // token at position will return let keyword on second line as the token but we would like to use + // let y = 10; + // token at position will return let keyword on second line as the token but we would like to use // token on same line if trailing trivia (comments or white spaces on same line) part of the last token on that line tokenAtLocation = findPrecedingToken(tokenAtLocation.pos, sourceFile); @@ -56,7 +56,7 @@ namespace ts.BreakpointResolver { return spanInNode(otherwiseOnNode); } - function spanInNodeArray(nodeArray: NodeArray) { + function spanInNodeArray(nodeArray: NodeArray) { return createTextSpanFromBounds(skipTrivia(sourceFile.text, nodeArray.pos), nodeArray.end); } @@ -259,13 +259,13 @@ namespace ts.BreakpointResolver { if (isArrayLiteralOrObjectLiteralDestructuringPattern(node)) { return spanInArrayLiteralOrObjectLiteralDestructuringPattern(node); } - + // Set breakpoint on identifier element of destructuring pattern - // a or ...c or d: x from + // a or ...c or d: x from // [a, b, ...c] or { a, b } or { d: x } from destructuring pattern if ((node.kind === SyntaxKind.Identifier || - node.kind == SyntaxKind.SpreadElementExpression || - node.kind === SyntaxKind.PropertyAssignment || + node.kind == SyntaxKind.SpreadElementExpression || + node.kind === SyntaxKind.PropertyAssignment || node.kind === SyntaxKind.ShorthandPropertyAssignment) && isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) { return textSpan(node); @@ -275,7 +275,7 @@ namespace ts.BreakpointResolver { const binaryExpression = node; // Set breakpoint in destructuring pattern if its destructuring assignment // [a, b, c] or {a, b, c} of - // [a, b, c] = expression or + // [a, b, c] = expression or // {a, b, c} = expression if (isArrayLiteralOrObjectLiteralDestructuringPattern(binaryExpression.left)) { return spanInArrayLiteralOrObjectLiteralDestructuringPattern( @@ -285,8 +285,8 @@ namespace ts.BreakpointResolver { if (binaryExpression.operatorToken.kind === SyntaxKind.EqualsToken && isArrayLiteralOrObjectLiteralDestructuringPattern(binaryExpression.parent)) { // Set breakpoint on assignment expression element of destructuring pattern - // a = expression of - // [a = expression, b, c] = someExpression or + // a = expression of + // [a = expression, b, c] = someExpression or // { a = expression, b, c } = someExpression return textSpan(node); } @@ -325,14 +325,14 @@ namespace ts.BreakpointResolver { break; } } - + // If this is name of property assignment, set breakpoint in the initializer if (node.parent.kind === SyntaxKind.PropertyAssignment && - (node.parent).name === node && + (node.parent).name === node && !isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.parent)) { return spanInNode((node.parent).initializer); } - + // Breakpoint in type assertion goes to its operand if (node.parent.kind === SyntaxKind.TypeAssertionExpression && (node.parent).type === node) { return spanInNextNode((node.parent).type); @@ -386,7 +386,7 @@ namespace ts.BreakpointResolver { if (variableDeclaration.parent.parent.kind === SyntaxKind.ForInStatement) { return spanInNode(variableDeclaration.parent.parent); } - + // If this is a destructuring pattern set breakpoint in binding pattern if (isBindingPattern(variableDeclaration.name)) { return spanInBindingPattern(variableDeclaration.name); @@ -403,7 +403,7 @@ namespace ts.BreakpointResolver { let declarations = variableDeclaration.parent.declarations; if (declarations && declarations[0] !== variableDeclaration) { // If we cant set breakpoint on this declaration, set it on previous one - // Because the variable declaration may be binding pattern and + // Because the variable declaration may be binding pattern and // we would like to set breakpoint in last binding element if thats the case, // use preceding token instead return spanInNode(findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent)); @@ -549,7 +549,7 @@ namespace ts.BreakpointResolver { return spanInNode(firstBindingElement); } - // Could be ArrayLiteral from destructuring assignment or + // Could be ArrayLiteral from destructuring assignment or // just nested element in another destructuring assignment // set breakpoint on assignment when parent is destructuring assignment // Otherwise set breakpoint for this element @@ -686,7 +686,7 @@ namespace ts.BreakpointResolver { function spanInColonToken(node: Node): TextSpan { // Is this : specifying return annotation of the function declaration if (isFunctionLike(node.parent) || - node.parent.kind === SyntaxKind.PropertyAssignment || + node.parent.kind === SyntaxKind.PropertyAssignment || node.parent.kind === SyntaxKind.Parameter) { return spanInPreviousNode(node); } diff --git a/src/services/services.ts b/src/services/services.ts index 85b2bfb58e8..373d0c3a8ff 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -186,6 +186,7 @@ namespace ts { public end: number; public flags: NodeFlags; public parent: Node; + public original: Node; private _children: Node[]; constructor(kind: SyntaxKind, pos: number, end: number) { @@ -194,6 +195,7 @@ namespace ts { this.end = end; this.flags = NodeFlags.None; this.parent = undefined; + this.original = undefined; } public getSourceFile(): SourceFile { @@ -1876,7 +1878,7 @@ namespace ts { options.isolatedModules = true; - // transpileModule does not write anything to disk so there is no need to verify that there are no conflicts between input and output paths. + // transpileModule does not write anything to disk so there is no need to verify that there are no conflicts between input and output paths. options.suppressOutputPathCheck = true; // Filename can be non-ts file. @@ -6102,7 +6104,7 @@ namespace ts { } } - // For export specifiers, it can be a local symbol, e.g. + // For export specifiers, it can be a local symbol, e.g. // import {a} from "mod"; // export {a as somethingElse} // We want the local target of the export (i.e. the import symbol) and not the final target (i.e. "mod".a) diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.leadingAsterisk.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.leadingAsterisk.json new file mode 100644 index 00000000000..fbc795c1cb8 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.leadingAsterisk.json @@ -0,0 +1,37 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 27, + "tags": { + "0": { + "kind": "JSDocTypeTag", + "pos": 8, + "end": 22, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 13, + "text": "type" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 14, + "end": 22, + "type": { + "kind": "NumberKeyword", + "pos": 15, + "end": 21 + } + } + }, + "length": 1, + "pos": 8, + "end": 22, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noLeadingAsterisk.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noLeadingAsterisk.json new file mode 100644 index 00000000000..fbc795c1cb8 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noLeadingAsterisk.json @@ -0,0 +1,37 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 27, + "tags": { + "0": { + "kind": "JSDocTypeTag", + "pos": 8, + "end": 22, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 13, + "text": "type" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 14, + "end": 22, + "type": { + "kind": "NumberKeyword", + "pos": 15, + "end": 21 + } + } + }, + "length": 1, + "pos": 8, + "end": 22, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noReturnType.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noReturnType.json new file mode 100644 index 00000000000..118fedcc381 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noReturnType.json @@ -0,0 +1,27 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 20, + "tags": { + "0": { + "kind": "JSDocReturnTag", + "pos": 8, + "end": 15, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 15, + "text": "return" + } + }, + "length": 1, + "pos": 8, + "end": 15, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noType.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noType.json new file mode 100644 index 00000000000..98453fb802e --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noType.json @@ -0,0 +1,27 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 18, + "tags": { + "0": { + "kind": "JSDocTypeTag", + "pos": 8, + "end": 13, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 13, + "text": "type" + } + }, + "length": 1, + "pos": 8, + "end": 13, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.oneParamTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.oneParamTag.json new file mode 100644 index 00000000000..d0c036bea74 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.oneParamTag.json @@ -0,0 +1,43 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 34, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 29, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 14, + "text": "param" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 15, + "end": 23, + "type": { + "kind": "NumberKeyword", + "pos": 16, + "end": 22 + } + }, + "postParameterName": { + "kind": "Identifier", + "pos": 24, + "end": 29, + "text": "name1" + } + }, + "length": 1, + "pos": 8, + "end": 29, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json new file mode 100644 index 00000000000..e05c296e10b --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTag1.json @@ -0,0 +1,43 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 59, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 29, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 14, + "text": "param" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 15, + "end": 23, + "type": { + "kind": "NumberKeyword", + "pos": 16, + "end": 22 + } + }, + "postParameterName": { + "kind": "Identifier", + "pos": 24, + "end": 29, + "text": "name1" + } + }, + "length": 1, + "pos": 8, + "end": 29, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName1.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName1.json new file mode 100644 index 00000000000..f731abb0a8e --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName1.json @@ -0,0 +1,44 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 61, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 31, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 14, + "text": "param" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 15, + "end": 23, + "type": { + "kind": "NumberKeyword", + "pos": 16, + "end": 22 + } + }, + "postParameterName": { + "kind": "Identifier", + "pos": 25, + "end": 30, + "text": "name1" + }, + "isBracketed": true + }, + "length": 1, + "pos": 8, + "end": 31, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName2.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName2.json new file mode 100644 index 00000000000..e230dfcd46c --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagBracketedName2.json @@ -0,0 +1,44 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 66, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 36, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 14, + "text": "param" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 15, + "end": 23, + "type": { + "kind": "NumberKeyword", + "pos": 16, + "end": 22 + } + }, + "postParameterName": { + "kind": "Identifier", + "pos": 26, + "end": 31, + "text": "name1" + }, + "isBracketed": true + }, + "length": 1, + "pos": 8, + "end": 36, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType1.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType1.json new file mode 100644 index 00000000000..44173787d27 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType1.json @@ -0,0 +1,43 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 34, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 29, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 14, + "text": "param" + }, + "preParameterName": { + "kind": "Identifier", + "pos": 15, + "end": 20, + "text": "name1" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 21, + "end": 29, + "type": { + "kind": "NumberKeyword", + "pos": 22, + "end": 28 + } + } + }, + "length": 1, + "pos": 8, + "end": 29, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType2.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType2.json new file mode 100644 index 00000000000..224eba3501e --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramTagNameThenType2.json @@ -0,0 +1,43 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 46, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 29, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 14, + "text": "param" + }, + "preParameterName": { + "kind": "Identifier", + "pos": 15, + "end": 20, + "text": "name1" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 21, + "end": 29, + "type": { + "kind": "NumberKeyword", + "pos": 22, + "end": 28 + } + } + }, + "length": 1, + "pos": 8, + "end": 29, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramWithoutType.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramWithoutType.json new file mode 100644 index 00000000000..0a78384e3e7 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.paramWithoutType.json @@ -0,0 +1,33 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 23, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 18, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 14, + "text": "param" + }, + "preParameterName": { + "kind": "Identifier", + "pos": 15, + "end": 18, + "text": "foo" + } + }, + "length": 1, + "pos": 8, + "end": 18, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag1.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag1.json new file mode 100644 index 00000000000..bac9b2a02ef --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag1.json @@ -0,0 +1,37 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 29, + "tags": { + "0": { + "kind": "JSDocReturnTag", + "pos": 8, + "end": 24, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 15, + "text": "return" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 16, + "end": 24, + "type": { + "kind": "NumberKeyword", + "pos": 17, + "end": 23 + } + } + }, + "length": 1, + "pos": 8, + "end": 24, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag2.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag2.json new file mode 100644 index 00000000000..6f7fb02b529 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag2.json @@ -0,0 +1,37 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 54, + "tags": { + "0": { + "kind": "JSDocReturnTag", + "pos": 8, + "end": 24, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 15, + "text": "return" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 16, + "end": 24, + "type": { + "kind": "NumberKeyword", + "pos": 17, + "end": 23 + } + } + }, + "length": 1, + "pos": 8, + "end": 24, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnsTag1.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnsTag1.json new file mode 100644 index 00000000000..d64b56b0a21 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnsTag1.json @@ -0,0 +1,37 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 30, + "tags": { + "0": { + "kind": "JSDocReturnTag", + "pos": 8, + "end": 25, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 16, + "text": "returns" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 17, + "end": 25, + "type": { + "kind": "NumberKeyword", + "pos": 18, + "end": 24 + } + } + }, + "length": 1, + "pos": 8, + "end": 25, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag.json new file mode 100644 index 00000000000..6be165c0c76 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag.json @@ -0,0 +1,44 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 24, + "tags": { + "0": { + "kind": "JSDocTemplateTag", + "pos": 8, + "end": 19, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 17, + "text": "template" + }, + "typeParameters": { + "0": { + "kind": "TypeParameter", + "pos": 18, + "end": 19, + "name": { + "kind": "Identifier", + "pos": 18, + "end": 19, + "text": "T" + } + }, + "length": 1, + "pos": 17, + "end": 19, + "arrayKind": 1 + } + }, + "length": 1, + "pos": 8, + "end": 19, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag2.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag2.json new file mode 100644 index 00000000000..85485b25143 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag2.json @@ -0,0 +1,55 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 26, + "tags": { + "0": { + "kind": "JSDocTemplateTag", + "pos": 8, + "end": 21, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 17, + "text": "template" + }, + "typeParameters": { + "0": { + "kind": "TypeParameter", + "pos": 18, + "end": 19, + "name": { + "kind": "Identifier", + "pos": 18, + "end": 19, + "text": "K" + } + }, + "1": { + "kind": "TypeParameter", + "pos": 20, + "end": 21, + "name": { + "kind": "Identifier", + "pos": 20, + "end": 21, + "text": "V" + } + }, + "length": 2, + "pos": 17, + "end": 21, + "arrayKind": 1 + } + }, + "length": 1, + "pos": 8, + "end": 21, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag3.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag3.json new file mode 100644 index 00000000000..e846f5daada --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag3.json @@ -0,0 +1,55 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 27, + "tags": { + "0": { + "kind": "JSDocTemplateTag", + "pos": 8, + "end": 22, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 17, + "text": "template" + }, + "typeParameters": { + "0": { + "kind": "TypeParameter", + "pos": 18, + "end": 19, + "name": { + "kind": "Identifier", + "pos": 18, + "end": 19, + "text": "K" + } + }, + "1": { + "kind": "TypeParameter", + "pos": 21, + "end": 22, + "name": { + "kind": "Identifier", + "pos": 21, + "end": 22, + "text": "V" + } + }, + "length": 2, + "pos": 17, + "end": 22, + "arrayKind": 1 + } + }, + "length": 1, + "pos": 8, + "end": 22, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag4.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag4.json new file mode 100644 index 00000000000..e846f5daada --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag4.json @@ -0,0 +1,55 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 27, + "tags": { + "0": { + "kind": "JSDocTemplateTag", + "pos": 8, + "end": 22, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 17, + "text": "template" + }, + "typeParameters": { + "0": { + "kind": "TypeParameter", + "pos": 18, + "end": 19, + "name": { + "kind": "Identifier", + "pos": 18, + "end": 19, + "text": "K" + } + }, + "1": { + "kind": "TypeParameter", + "pos": 21, + "end": 22, + "name": { + "kind": "Identifier", + "pos": 21, + "end": 22, + "text": "V" + } + }, + "length": 2, + "pos": 17, + "end": 22, + "arrayKind": 1 + } + }, + "length": 1, + "pos": 8, + "end": 22, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag5.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag5.json new file mode 100644 index 00000000000..245ed626980 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag5.json @@ -0,0 +1,55 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 28, + "tags": { + "0": { + "kind": "JSDocTemplateTag", + "pos": 8, + "end": 23, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 17, + "text": "template" + }, + "typeParameters": { + "0": { + "kind": "TypeParameter", + "pos": 18, + "end": 19, + "name": { + "kind": "Identifier", + "pos": 18, + "end": 19, + "text": "K" + } + }, + "1": { + "kind": "TypeParameter", + "pos": 22, + "end": 23, + "name": { + "kind": "Identifier", + "pos": 22, + "end": 23, + "text": "V" + } + }, + "length": 2, + "pos": 17, + "end": 23, + "arrayKind": 1 + } + }, + "length": 1, + "pos": 8, + "end": 23, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag6.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag6.json new file mode 100644 index 00000000000..323770c644e --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag6.json @@ -0,0 +1,55 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 60, + "tags": { + "0": { + "kind": "JSDocTemplateTag", + "pos": 8, + "end": 23, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 17, + "text": "template" + }, + "typeParameters": { + "0": { + "kind": "TypeParameter", + "pos": 18, + "end": 19, + "name": { + "kind": "Identifier", + "pos": 18, + "end": 19, + "text": "K" + } + }, + "1": { + "kind": "TypeParameter", + "pos": 22, + "end": 23, + "name": { + "kind": "Identifier", + "pos": 22, + "end": 23, + "text": "V" + } + }, + "length": 2, + "pos": 17, + "end": 23, + "arrayKind": 1 + } + }, + "length": 1, + "pos": 8, + "end": 23, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTag2.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTag2.json new file mode 100644 index 00000000000..95c96531bdf --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTag2.json @@ -0,0 +1,75 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 60, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 29, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 14, + "text": "param" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 15, + "end": 23, + "type": { + "kind": "NumberKeyword", + "pos": 16, + "end": 22 + } + }, + "postParameterName": { + "kind": "Identifier", + "pos": 24, + "end": 29, + "text": "name1" + } + }, + "1": { + "kind": "JSDocParameterTag", + "pos": 34, + "end": 55, + "atToken": { + "kind": "AtToken", + "pos": 34, + "end": 35 + }, + "tagName": { + "kind": "Identifier", + "pos": 35, + "end": 40, + "text": "param" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 41, + "end": 49, + "type": { + "kind": "NumberKeyword", + "pos": 42, + "end": 48 + } + }, + "postParameterName": { + "kind": "Identifier", + "pos": 50, + "end": 55, + "text": "name2" + } + }, + "length": 2, + "pos": 8, + "end": 55, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTagOnSameLine.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTagOnSameLine.json new file mode 100644 index 00000000000..93b84f00324 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.twoParamTagOnSameLine.json @@ -0,0 +1,43 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 56, + "tags": { + "0": { + "kind": "JSDocParameterTag", + "pos": 8, + "end": 29, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 14, + "text": "param" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 15, + "end": 23, + "type": { + "kind": "NumberKeyword", + "pos": 16, + "end": 22 + } + }, + "postParameterName": { + "kind": "Identifier", + "pos": 24, + "end": 29, + "text": "name1" + } + }, + "length": 1, + "pos": 8, + "end": 29, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typeTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typeTag.json new file mode 100644 index 00000000000..fbc795c1cb8 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typeTag.json @@ -0,0 +1,37 @@ +{ + "kind": "JSDocComment", + "pos": 0, + "end": 27, + "tags": { + "0": { + "kind": "JSDocTypeTag", + "pos": 8, + "end": 22, + "atToken": { + "kind": "AtToken", + "pos": 8, + "end": 9 + }, + "tagName": { + "kind": "Identifier", + "pos": 9, + "end": 13, + "text": "type" + }, + "typeExpression": { + "kind": "JSDocTypeExpression", + "pos": 14, + "end": 22, + "type": { + "kind": "NumberKeyword", + "pos": 15, + "end": 21 + } + } + }, + "length": 1, + "pos": 8, + "end": 22, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.allType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.allType.json new file mode 100644 index 00000000000..68081a1b9e4 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.allType.json @@ -0,0 +1,5 @@ +{ + "kind": "JSDocAllType", + "pos": 1, + "end": 2 +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType1.json new file mode 100644 index 00000000000..cd9255d392c --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType1.json @@ -0,0 +1,16 @@ +{ + "kind": "JSDocArrayType", + "pos": 1, + "end": 4, + "elementType": { + "kind": "JSDocTypeReference", + "pos": 1, + "end": 2, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 2, + "text": "a" + } + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType2.json new file mode 100644 index 00000000000..1fe6d184599 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType2.json @@ -0,0 +1,21 @@ +{ + "kind": "JSDocArrayType", + "pos": 1, + "end": 6, + "elementType": { + "kind": "JSDocArrayType", + "pos": 1, + "end": 4, + "elementType": { + "kind": "JSDocTypeReference", + "pos": 1, + "end": 2, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 2, + "text": "a" + } + } + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType3.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType3.json new file mode 100644 index 00000000000..2fe27c67a1b --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.arrayType3.json @@ -0,0 +1,26 @@ +{ + "kind": "JSDocOptionalType", + "pos": 1, + "end": 7, + "type": { + "kind": "JSDocArrayType", + "pos": 1, + "end": 6, + "elementType": { + "kind": "JSDocArrayType", + "pos": 1, + "end": 4, + "elementType": { + "kind": "JSDocTypeReference", + "pos": 1, + "end": 2, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 2, + "text": "a" + } + } + } + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionReturnType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionReturnType1.json new file mode 100644 index 00000000000..e02b9ab7dd9 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionReturnType1.json @@ -0,0 +1,31 @@ +{ + "kind": "JSDocFunctionType", + "pos": 1, + "end": 26, + "parameters": { + "0": { + "kind": "Parameter", + "pos": 10, + "end": 16, + "type": { + "kind": "StringKeyword", + "pos": 10, + "end": 16 + } + }, + "1": { + "kind": "Parameter", + "pos": 17, + "end": 25, + "type": { + "kind": "BooleanKeyword", + "pos": 17, + "end": 25 + } + }, + "length": 2, + "pos": 10, + "end": 25, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionType1.json new file mode 100644 index 00000000000..94fe0ec2978 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionType1.json @@ -0,0 +1,11 @@ +{ + "kind": "JSDocFunctionType", + "pos": 1, + "end": 11, + "parameters": { + "length": 0, + "pos": 10, + "end": 10, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionType2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionType2.json new file mode 100644 index 00000000000..e02b9ab7dd9 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.functionType2.json @@ -0,0 +1,31 @@ +{ + "kind": "JSDocFunctionType", + "pos": 1, + "end": 26, + "parameters": { + "0": { + "kind": "Parameter", + "pos": 10, + "end": 16, + "type": { + "kind": "StringKeyword", + "pos": 10, + "end": 16 + } + }, + "1": { + "kind": "Parameter", + "pos": 17, + "end": 25, + "type": { + "kind": "BooleanKeyword", + "pos": 17, + "end": 25 + } + }, + "length": 2, + "pos": 10, + "end": 25, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword1.json new file mode 100644 index 00000000000..80b1378b291 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword1.json @@ -0,0 +1,12 @@ +{ + "kind": "JSDocTypeReference", + "pos": 1, + "end": 4, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 4, + "originalKeywordKind": "VarKeyword", + "text": "var" + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword2.json new file mode 100644 index 00000000000..91972325847 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword2.json @@ -0,0 +1,12 @@ +{ + "kind": "JSDocTypeReference", + "pos": 1, + "end": 5, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 5, + "originalKeywordKind": "NullKeyword", + "text": "null" + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword3.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword3.json new file mode 100644 index 00000000000..f7624064826 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword3.json @@ -0,0 +1,11 @@ +{ + "kind": "JSDocTypeReference", + "pos": 1, + "end": 10, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 10, + "text": "undefined" + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.newType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.newType1.json new file mode 100644 index 00000000000..194037970c5 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.newType1.json @@ -0,0 +1,27 @@ +{ + "kind": "JSDocConstructorType", + "pos": 1, + "end": 8, + "type": { + "kind": "JSDocTypeReference", + "pos": 5, + "end": 8, + "name": { + "kind": "FirstNode", + "pos": 5, + "end": 8, + "left": { + "kind": "Identifier", + "pos": 5, + "end": 6, + "text": "a" + }, + "right": { + "kind": "Identifier", + "pos": 7, + "end": 8, + "text": "b" + } + } + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nonNullableType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nonNullableType.json new file mode 100644 index 00000000000..e089754a0de --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nonNullableType.json @@ -0,0 +1,10 @@ +{ + "kind": "JSDocNonNullableType", + "pos": 1, + "end": 8, + "type": { + "kind": "NumberKeyword", + "pos": 2, + "end": 8 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nonNullableType2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nonNullableType2.json new file mode 100644 index 00000000000..377b19d0f70 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nonNullableType2.json @@ -0,0 +1,10 @@ +{ + "kind": "JSDocNonNullableType", + "pos": 1, + "end": 8, + "type": { + "kind": "NumberKeyword", + "pos": 1, + "end": 7 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nullableType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nullableType.json new file mode 100644 index 00000000000..9c4457fba12 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nullableType.json @@ -0,0 +1,10 @@ +{ + "kind": "JSDocNullableType", + "pos": 1, + "end": 8, + "type": { + "kind": "NumberKeyword", + "pos": 2, + "end": 8 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nullableType2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nullableType2.json new file mode 100644 index 00000000000..03aea7be8c5 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.nullableType2.json @@ -0,0 +1,10 @@ +{ + "kind": "JSDocNullableType", + "pos": 1, + "end": 8, + "type": { + "kind": "NumberKeyword", + "pos": 1, + "end": 7 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.optionalNullable.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.optionalNullable.json new file mode 100644 index 00000000000..f4940c28475 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.optionalNullable.json @@ -0,0 +1,10 @@ +{ + "kind": "JSDocOptionalType", + "pos": 1, + "end": 3, + "type": { + "kind": "JSDocUnknownType", + "pos": 1, + "end": 2 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.optionalType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.optionalType.json new file mode 100644 index 00000000000..6069107cc6e --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.optionalType.json @@ -0,0 +1,10 @@ +{ + "kind": "JSDocOptionalType", + "pos": 1, + "end": 8, + "type": { + "kind": "NumberKeyword", + "pos": 1, + "end": 7 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType1.json new file mode 100644 index 00000000000..929f0046cff --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType1.json @@ -0,0 +1,11 @@ +{ + "kind": "JSDocRecordType", + "pos": 1, + "end": 3, + "members": { + "length": 0, + "pos": 2, + "end": 2, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType2.json new file mode 100644 index 00000000000..8e6eb1fa11a --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType2.json @@ -0,0 +1,22 @@ +{ + "kind": "JSDocRecordType", + "pos": 1, + "end": 6, + "members": { + "0": { + "kind": "JSDocRecordMember", + "pos": 2, + "end": 5, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 5, + "text": "foo" + } + }, + "length": 1, + "pos": 2, + "end": 5, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType3.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType3.json new file mode 100644 index 00000000000..ce5dedcaf56 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType3.json @@ -0,0 +1,27 @@ +{ + "kind": "JSDocRecordType", + "pos": 1, + "end": 14, + "members": { + "0": { + "kind": "JSDocRecordMember", + "pos": 2, + "end": 13, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 5, + "text": "foo" + }, + "type": { + "kind": "NumberKeyword", + "pos": 6, + "end": 13 + } + }, + "length": 1, + "pos": 2, + "end": 13, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType4.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType4.json new file mode 100644 index 00000000000..1192b2a3a3c --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType4.json @@ -0,0 +1,33 @@ +{ + "kind": "JSDocRecordType", + "pos": 1, + "end": 11, + "members": { + "0": { + "kind": "JSDocRecordMember", + "pos": 2, + "end": 5, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 5, + "text": "foo" + } + }, + "1": { + "kind": "JSDocRecordMember", + "pos": 6, + "end": 10, + "name": { + "kind": "Identifier", + "pos": 6, + "end": 10, + "text": "bar" + } + }, + "length": 2, + "pos": 2, + "end": 10, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType5.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType5.json new file mode 100644 index 00000000000..b31585c8e37 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType5.json @@ -0,0 +1,38 @@ +{ + "kind": "JSDocRecordType", + "pos": 1, + "end": 19, + "members": { + "0": { + "kind": "JSDocRecordMember", + "pos": 2, + "end": 13, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 5, + "text": "foo" + }, + "type": { + "kind": "NumberKeyword", + "pos": 6, + "end": 13 + } + }, + "1": { + "kind": "JSDocRecordMember", + "pos": 14, + "end": 18, + "name": { + "kind": "Identifier", + "pos": 14, + "end": 18, + "text": "bar" + } + }, + "length": 2, + "pos": 2, + "end": 18, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType6.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType6.json new file mode 100644 index 00000000000..81ee5b53451 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType6.json @@ -0,0 +1,38 @@ +{ + "kind": "JSDocRecordType", + "pos": 1, + "end": 19, + "members": { + "0": { + "kind": "JSDocRecordMember", + "pos": 2, + "end": 5, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 5, + "text": "foo" + } + }, + "1": { + "kind": "JSDocRecordMember", + "pos": 6, + "end": 18, + "name": { + "kind": "Identifier", + "pos": 6, + "end": 10, + "text": "bar" + }, + "type": { + "kind": "NumberKeyword", + "pos": 11, + "end": 18 + } + }, + "length": 2, + "pos": 2, + "end": 18, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType7.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType7.json new file mode 100644 index 00000000000..595798b1a83 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType7.json @@ -0,0 +1,43 @@ +{ + "kind": "JSDocRecordType", + "pos": 1, + "end": 27, + "members": { + "0": { + "kind": "JSDocRecordMember", + "pos": 2, + "end": 13, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 5, + "text": "foo" + }, + "type": { + "kind": "NumberKeyword", + "pos": 6, + "end": 13 + } + }, + "1": { + "kind": "JSDocRecordMember", + "pos": 14, + "end": 26, + "name": { + "kind": "Identifier", + "pos": 14, + "end": 18, + "text": "bar" + }, + "type": { + "kind": "NumberKeyword", + "pos": 19, + "end": 26 + } + }, + "length": 2, + "pos": 2, + "end": 26, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType8.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType8.json new file mode 100644 index 00000000000..b4d00c873ce --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType8.json @@ -0,0 +1,23 @@ +{ + "kind": "JSDocRecordType", + "pos": 1, + "end": 11, + "members": { + "0": { + "kind": "JSDocRecordMember", + "pos": 2, + "end": 10, + "name": { + "kind": "Identifier", + "pos": 2, + "end": 10, + "originalKeywordKind": "FunctionKeyword", + "text": "function" + } + }, + "length": 1, + "pos": 2, + "end": 10, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.thisType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.thisType1.json new file mode 100644 index 00000000000..f0b8038b586 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.thisType1.json @@ -0,0 +1,27 @@ +{ + "kind": "JSDocThisType", + "pos": 1, + "end": 9, + "type": { + "kind": "JSDocTypeReference", + "pos": 6, + "end": 9, + "name": { + "kind": "FirstNode", + "pos": 6, + "end": 9, + "left": { + "kind": "Identifier", + "pos": 6, + "end": 7, + "text": "a" + }, + "right": { + "kind": "Identifier", + "pos": 8, + "end": 9, + "text": "b" + } + } + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.topLevelNoParenUnionType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.topLevelNoParenUnionType.json new file mode 100644 index 00000000000..dd1b017da00 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.topLevelNoParenUnionType.json @@ -0,0 +1,21 @@ +{ + "kind": "JSDocUnionType", + "pos": 1, + "end": 14, + "types": { + "0": { + "kind": "NumberKeyword", + "pos": 1, + "end": 7 + }, + "1": { + "kind": "StringKeyword", + "pos": 8, + "end": 14 + }, + "length": 2, + "pos": 1, + "end": 14, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType0.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType0.json new file mode 100644 index 00000000000..dbb6f35ab00 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType0.json @@ -0,0 +1,11 @@ +{ + "kind": "JSDocTupleType", + "pos": 1, + "end": 3, + "types": { + "length": 0, + "pos": 2, + "end": 2, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType1.json new file mode 100644 index 00000000000..1ab9530626d --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType1.json @@ -0,0 +1,16 @@ +{ + "kind": "JSDocTupleType", + "pos": 1, + "end": 9, + "types": { + "0": { + "kind": "NumberKeyword", + "pos": 2, + "end": 8 + }, + "length": 1, + "pos": 2, + "end": 8, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType2.json new file mode 100644 index 00000000000..aaea91528d7 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType2.json @@ -0,0 +1,21 @@ +{ + "kind": "JSDocTupleType", + "pos": 1, + "end": 16, + "types": { + "0": { + "kind": "NumberKeyword", + "pos": 2, + "end": 8 + }, + "1": { + "kind": "StringKeyword", + "pos": 9, + "end": 15 + }, + "length": 2, + "pos": 2, + "end": 15, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType3.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType3.json new file mode 100644 index 00000000000..a685de86622 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.tupleType3.json @@ -0,0 +1,26 @@ +{ + "kind": "JSDocTupleType", + "pos": 1, + "end": 24, + "types": { + "0": { + "kind": "NumberKeyword", + "pos": 2, + "end": 8 + }, + "1": { + "kind": "StringKeyword", + "pos": 9, + "end": 15 + }, + "2": { + "kind": "BooleanKeyword", + "pos": 16, + "end": 23 + }, + "length": 3, + "pos": 2, + "end": 23, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference1.json new file mode 100644 index 00000000000..970c6fe1b13 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference1.json @@ -0,0 +1,22 @@ +{ + "kind": "JSDocTypeReference", + "pos": 1, + "end": 11, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 2, + "text": "a" + }, + "typeArguments": { + "0": { + "kind": "NumberKeyword", + "pos": 4, + "end": 10 + }, + "length": 1, + "pos": 4, + "end": 10, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference2.json new file mode 100644 index 00000000000..913ba27897d --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference2.json @@ -0,0 +1,27 @@ +{ + "kind": "JSDocTypeReference", + "pos": 1, + "end": 18, + "name": { + "kind": "Identifier", + "pos": 1, + "end": 2, + "text": "a" + }, + "typeArguments": { + "0": { + "kind": "NumberKeyword", + "pos": 4, + "end": 10 + }, + "1": { + "kind": "StringKeyword", + "pos": 11, + "end": 17 + }, + "length": 2, + "pos": 4, + "end": 17, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference3.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference3.json new file mode 100644 index 00000000000..683c17e582e --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference3.json @@ -0,0 +1,23 @@ +{ + "kind": "JSDocTypeReference", + "pos": 1, + "end": 11, + "name": { + "kind": "FirstNode", + "pos": 1, + "end": 11, + "left": { + "kind": "Identifier", + "pos": 1, + "end": 2, + "text": "a" + }, + "right": { + "kind": "Identifier", + "pos": 3, + "end": 11, + "originalKeywordKind": "FunctionKeyword", + "text": "function" + } + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.unionType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.unionType.json new file mode 100644 index 00000000000..aae1d6bc169 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.unionType.json @@ -0,0 +1,21 @@ +{ + "kind": "JSDocUnionType", + "pos": 1, + "end": 16, + "types": { + "0": { + "kind": "NumberKeyword", + "pos": 2, + "end": 8 + }, + "1": { + "kind": "StringKeyword", + "pos": 9, + "end": 15 + }, + "length": 2, + "pos": 2, + "end": 15, + "arrayKind": 1 + } +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.unknownType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.unknownType.json new file mode 100644 index 00000000000..0fb7af7ef23 --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.unknownType.json @@ -0,0 +1,5 @@ +{ + "kind": "JSDocUnknownType", + "pos": 1, + "end": 2 +} \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.variadicType.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.variadicType.json new file mode 100644 index 00000000000..2cf6079533c --- /dev/null +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.variadicType.json @@ -0,0 +1,10 @@ +{ + "kind": "JSDocVariadicType", + "pos": 1, + "end": 10, + "type": { + "kind": "NumberKeyword", + "pos": 4, + "end": 10 + } +} \ No newline at end of file diff --git a/tests/cases/unittests/jsDocParsing.ts b/tests/cases/unittests/jsDocParsing.ts index 9988383b467..b742ef783df 100644 --- a/tests/cases/unittests/jsDocParsing.ts +++ b/tests/cases/unittests/jsDocParsing.ts @@ -6,2213 +6,281 @@ module ts { describe("JSDocParsing", () => { describe("TypeExpressions", () => { - function parsesCorrectly(content: string, expected: string) { - let typeAndDiagnostics = ts.parseJSDocTypeExpressionForTests(content); - assert.isTrue(typeAndDiagnostics && typeAndDiagnostics.diagnostics.length === 0); + function parsesCorrectly(name: string, content: string) { + it(name, () => { + let typeAndDiagnostics = ts.parseJSDocTypeExpressionForTests(content); + assert.isTrue(typeAndDiagnostics && typeAndDiagnostics.diagnostics.length === 0); - let result = Utils.sourceFileToJSON(typeAndDiagnostics.jsDocTypeExpression.type); - assert.equal(result, expected); + Harness.Baseline.runBaseline("parseCorrectly", "JSDocParsing/TypeExpressions.parsesCorrectly." + name + ".json", + () => Utils.sourceFileToJSON(typeAndDiagnostics.jsDocTypeExpression.type)); + }); } - function parsesIncorrectly(content: string) { - let type = ts.parseJSDocTypeExpressionForTests(content); - assert.isTrue(!type || type.diagnostics.length > 0); + function parsesIncorrectly(name: string, content: string) { + it(name, () => { + let type = ts.parseJSDocTypeExpressionForTests(content); + assert.isTrue(!type || type.diagnostics.length > 0); + }); } describe("parseCorrectly", () => { - it("unknownType", () => { - parsesCorrectly("{?}", - `{ - "kind": "JSDocUnknownType", - "pos": 1, - "end": 2 -}`); - }); - - it("allType", () => { - parsesCorrectly("{*}", - `{ - "kind": "JSDocAllType", - "pos": 1, - "end": 2 -}`); - }); - - it("nullableType", () => { - parsesCorrectly("{?number}", - `{ - "kind": "JSDocNullableType", - "pos": 1, - "end": 8, - "type": { - "kind": "NumberKeyword", - "pos": 2, - "end": 8 - } -}`) - }); - - it("nullableType2", () => { - parsesCorrectly("{number?}", - `{ - "kind": "JSDocNullableType", - "pos": 1, - "end": 8, - "type": { - "kind": "NumberKeyword", - "pos": 1, - "end": 7 - } -}`) - }); - - it("nonNullableType", () => { - parsesCorrectly("{!number}", - `{ - "kind": "JSDocNonNullableType", - "pos": 1, - "end": 8, - "type": { - "kind": "NumberKeyword", - "pos": 2, - "end": 8 - } -}`) - }); - - it("nonNullableType2", () => { - parsesCorrectly("{number!}", - `{ - "kind": "JSDocNonNullableType", - "pos": 1, - "end": 8, - "type": { - "kind": "NumberKeyword", - "pos": 1, - "end": 7 - } -}`) - }); - - it("recordType1", () => { - parsesCorrectly("{{}}", - `{ - "kind": "JSDocRecordType", - "pos": 1, - "end": 3, - "members": { - "length": 0, - "pos": 2, - "end": 2 - } -}`) - }); - - it("recordType2", () => { - parsesCorrectly("{{foo}}", - `{ - "kind": "JSDocRecordType", - "pos": 1, - "end": 6, - "members": { - "0": { - "kind": "JSDocRecordMember", - "pos": 2, - "end": 5, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 5, - "text": "foo" - } - }, - "length": 1, - "pos": 2, - "end": 5 - } -}`) - }); - - it("recordType3", () => { - parsesCorrectly("{{foo: number}}", - `{ - "kind": "JSDocRecordType", - "pos": 1, - "end": 14, - "members": { - "0": { - "kind": "JSDocRecordMember", - "pos": 2, - "end": 13, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 5, - "text": "foo" - }, - "type": { - "kind": "NumberKeyword", - "pos": 6, - "end": 13 - } - }, - "length": 1, - "pos": 2, - "end": 13 - } -}`) - }); - - it("recordType4", () => { - parsesCorrectly("{{foo, bar}}", - `{ - "kind": "JSDocRecordType", - "pos": 1, - "end": 11, - "members": { - "0": { - "kind": "JSDocRecordMember", - "pos": 2, - "end": 5, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 5, - "text": "foo" - } - }, - "1": { - "kind": "JSDocRecordMember", - "pos": 6, - "end": 10, - "name": { - "kind": "Identifier", - "pos": 6, - "end": 10, - "text": "bar" - } - }, - "length": 2, - "pos": 2, - "end": 10 - } -}`) - }); - - it("recordType5", () => { - parsesCorrectly("{{foo: number, bar}}", - `{ - "kind": "JSDocRecordType", - "pos": 1, - "end": 19, - "members": { - "0": { - "kind": "JSDocRecordMember", - "pos": 2, - "end": 13, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 5, - "text": "foo" - }, - "type": { - "kind": "NumberKeyword", - "pos": 6, - "end": 13 - } - }, - "1": { - "kind": "JSDocRecordMember", - "pos": 14, - "end": 18, - "name": { - "kind": "Identifier", - "pos": 14, - "end": 18, - "text": "bar" - } - }, - "length": 2, - "pos": 2, - "end": 18 - } -}`) - }); - - it("recordType6", () => { - parsesCorrectly("{{foo, bar: number}}", - `{ - "kind": "JSDocRecordType", - "pos": 1, - "end": 19, - "members": { - "0": { - "kind": "JSDocRecordMember", - "pos": 2, - "end": 5, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 5, - "text": "foo" - } - }, - "1": { - "kind": "JSDocRecordMember", - "pos": 6, - "end": 18, - "name": { - "kind": "Identifier", - "pos": 6, - "end": 10, - "text": "bar" - }, - "type": { - "kind": "NumberKeyword", - "pos": 11, - "end": 18 - } - }, - "length": 2, - "pos": 2, - "end": 18 - } -}`) - }); - - it("recordType7", () => { - parsesCorrectly("{{foo: number, bar: number}}", - `{ - "kind": "JSDocRecordType", - "pos": 1, - "end": 27, - "members": { - "0": { - "kind": "JSDocRecordMember", - "pos": 2, - "end": 13, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 5, - "text": "foo" - }, - "type": { - "kind": "NumberKeyword", - "pos": 6, - "end": 13 - } - }, - "1": { - "kind": "JSDocRecordMember", - "pos": 14, - "end": 26, - "name": { - "kind": "Identifier", - "pos": 14, - "end": 18, - "text": "bar" - }, - "type": { - "kind": "NumberKeyword", - "pos": 19, - "end": 26 - } - }, - "length": 2, - "pos": 2, - "end": 26 - } -}`) - }); - - it("recordType8", () => { - parsesCorrectly("{{function}}", - `{ - "kind": "JSDocRecordType", - "pos": 1, - "end": 11, - "members": { - "0": { - "kind": "JSDocRecordMember", - "pos": 2, - "end": 10, - "name": { - "kind": "Identifier", - "pos": 2, - "end": 10, - "originalKeywordKind": "FunctionKeyword", - "text": "function" - } - }, - "length": 1, - "pos": 2, - "end": 10 - } -}`) - }); - - it("unionType", () => { - parsesCorrectly("{(number|string)}", - `{ - "kind": "JSDocUnionType", - "pos": 1, - "end": 16, - "types": { - "0": { - "kind": "NumberKeyword", - "pos": 2, - "end": 8 - }, - "1": { - "kind": "StringKeyword", - "pos": 9, - "end": 15 - }, - "length": 2, - "pos": 2, - "end": 15 - } -}`); - }); - - it("topLevelNoParenUnionType", () => { - parsesCorrectly("{number|string}", - `{ - "kind": "JSDocUnionType", - "pos": 1, - "end": 14, - "types": { - "0": { - "kind": "NumberKeyword", - "pos": 1, - "end": 7 - }, - "1": { - "kind": "StringKeyword", - "pos": 8, - "end": 14 - }, - "length": 2, - "pos": 1, - "end": 14 - } -}`); - }); - - it("functionType1", () => { - parsesCorrectly("{function()}", - `{ - "kind": "JSDocFunctionType", - "pos": 1, - "end": 11, - "parameters": { - "length": 0, - "pos": 10, - "end": 10 - } -}`); - }); - - it("functionType2", () => { - parsesCorrectly("{function(string, boolean)}", - `{ - "kind": "JSDocFunctionType", - "pos": 1, - "end": 26, - "parameters": { - "0": { - "kind": "Parameter", - "pos": 10, - "end": 16, - "type": { - "kind": "StringKeyword", - "pos": 10, - "end": 16 - } - }, - "1": { - "kind": "Parameter", - "pos": 17, - "end": 25, - "type": { - "kind": "BooleanKeyword", - "pos": 17, - "end": 25 - } - }, - "length": 2, - "pos": 10, - "end": 25 - } -}`); - }); - - it("functionReturnType1", () => { - parsesCorrectly("{function(string, boolean)}", - `{ - "kind": "JSDocFunctionType", - "pos": 1, - "end": 26, - "parameters": { - "0": { - "kind": "Parameter", - "pos": 10, - "end": 16, - "type": { - "kind": "StringKeyword", - "pos": 10, - "end": 16 - } - }, - "1": { - "kind": "Parameter", - "pos": 17, - "end": 25, - "type": { - "kind": "BooleanKeyword", - "pos": 17, - "end": 25 - } - }, - "length": 2, - "pos": 10, - "end": 25 - } -}`); - }); - - it("thisType1", () => { - parsesCorrectly("{this:a.b}", - `{ - "kind": "JSDocThisType", - "pos": 1, - "end": 9, - "type": { - "kind": "JSDocTypeReference", - "pos": 6, - "end": 9, - "name": { - "kind": "FirstNode", - "pos": 6, - "end": 9, - "left": { - "kind": "Identifier", - "pos": 6, - "end": 7, - "text": "a" - }, - "right": { - "kind": "Identifier", - "pos": 8, - "end": 9, - "text": "b" - } - } - } -}`); - }); - - it("newType1", () => { - parsesCorrectly("{new:a.b}", - `{ - "kind": "JSDocConstructorType", - "pos": 1, - "end": 8, - "type": { - "kind": "JSDocTypeReference", - "pos": 5, - "end": 8, - "name": { - "kind": "FirstNode", - "pos": 5, - "end": 8, - "left": { - "kind": "Identifier", - "pos": 5, - "end": 6, - "text": "a" - }, - "right": { - "kind": "Identifier", - "pos": 7, - "end": 8, - "text": "b" - } - } - } -}`); - }); - - it("variadicType", () => { - parsesCorrectly("{...number}", - `{ - "kind": "JSDocVariadicType", - "pos": 1, - "end": 10, - "type": { - "kind": "NumberKeyword", - "pos": 4, - "end": 10 - } -}`); - }); - - it("optionalType", () => { - parsesCorrectly("{number=}", - `{ - "kind": "JSDocOptionalType", - "pos": 1, - "end": 8, - "type": { - "kind": "NumberKeyword", - "pos": 1, - "end": 7 - } -}`); - }); - - it("optionalNullable", () => { - parsesCorrectly("{?=}", - `{ - "kind": "JSDocOptionalType", - "pos": 1, - "end": 3, - "type": { - "kind": "JSDocUnknownType", - "pos": 1, - "end": 2 - } -}`); - }); - - it("typeReference1", () => { - parsesCorrectly("{a.}", - `{ - "kind": "JSDocTypeReference", - "pos": 1, - "end": 11, - "name": { - "kind": "Identifier", - "pos": 1, - "end": 2, - "text": "a" - }, - "typeArguments": { - "0": { - "kind": "NumberKeyword", - "pos": 4, - "end": 10 - }, - "length": 1, - "pos": 4, - "end": 10 - } -}`); - }); - - it("typeReference2", () => { - parsesCorrectly("{a.}", - `{ - "kind": "JSDocTypeReference", - "pos": 1, - "end": 18, - "name": { - "kind": "Identifier", - "pos": 1, - "end": 2, - "text": "a" - }, - "typeArguments": { - "0": { - "kind": "NumberKeyword", - "pos": 4, - "end": 10 - }, - "1": { - "kind": "StringKeyword", - "pos": 11, - "end": 17 - }, - "length": 2, - "pos": 4, - "end": 17 - } -}`); - }); - - it("typeReference3", () => { - parsesCorrectly("{a.function}", - `{ - "kind": "JSDocTypeReference", - "pos": 1, - "end": 11, - "name": { - "kind": "FirstNode", - "pos": 1, - "end": 11, - "left": { - "kind": "Identifier", - "pos": 1, - "end": 2, - "text": "a" - }, - "right": { - "kind": "Identifier", - "pos": 3, - "end": 11, - "originalKeywordKind": "FunctionKeyword", - "text": "function" - } - } -}`); - }); - - it("arrayType1", () => { - parsesCorrectly( - "{a[]}", - `{ - "kind": "JSDocArrayType", - "pos": 1, - "end": 4, - "elementType": { - "kind": "JSDocTypeReference", - "pos": 1, - "end": 2, - "name": { - "kind": "Identifier", - "pos": 1, - "end": 2, - "text": "a" - } - } -}`); - }); - - it("arrayType2", () => { - parsesCorrectly( - "{a[][]}", - `{ - "kind": "JSDocArrayType", - "pos": 1, - "end": 6, - "elementType": { - "kind": "JSDocArrayType", - "pos": 1, - "end": 4, - "elementType": { - "kind": "JSDocTypeReference", - "pos": 1, - "end": 2, - "name": { - "kind": "Identifier", - "pos": 1, - "end": 2, - "text": "a" - } - } - } -}`); - }); - - it("arrayType3", () => { - parsesCorrectly( - "{a[][]=}", - `{ - "kind": "JSDocOptionalType", - "pos": 1, - "end": 7, - "type": { - "kind": "JSDocArrayType", - "pos": 1, - "end": 6, - "elementType": { - "kind": "JSDocArrayType", - "pos": 1, - "end": 4, - "elementType": { - "kind": "JSDocTypeReference", - "pos": 1, - "end": 2, - "name": { - "kind": "Identifier", - "pos": 1, - "end": 2, - "text": "a" - } - } - } - } -}`); - }); - - it("keyword1", () => { - parsesCorrectly( - "{var}", - `{ - "kind": "JSDocTypeReference", - "pos": 1, - "end": 4, - "name": { - "kind": "Identifier", - "pos": 1, - "end": 4, - "originalKeywordKind": "VarKeyword", - "text": "var" - } -}`); - }); - - it("keyword2", () => { - parsesCorrectly( - "{null}", - `{ - "kind": "JSDocTypeReference", - "pos": 1, - "end": 5, - "name": { - "kind": "Identifier", - "pos": 1, - "end": 5, - "originalKeywordKind": "NullKeyword", - "text": "null" - } -}`); - }); - - it("keyword3", () => { - parsesCorrectly( - "{undefined}", - `{ - "kind": "JSDocTypeReference", - "pos": 1, - "end": 10, - "name": { - "kind": "Identifier", - "pos": 1, - "end": 10, - "text": "undefined" - } -}`); - }); - - it("tupleType0", () => { - parsesCorrectly( - "{[]}", - `{ - "kind": "JSDocTupleType", - "pos": 1, - "end": 3, - "types": { - "length": 0, - "pos": 2, - "end": 2 - } -}`); - }); - - it("tupleType1", () => { - parsesCorrectly( - "{[number]}", - `{ - "kind": "JSDocTupleType", - "pos": 1, - "end": 9, - "types": { - "0": { - "kind": "NumberKeyword", - "pos": 2, - "end": 8 - }, - "length": 1, - "pos": 2, - "end": 8 - } -}`); - }); - - it("tupleType2", () => { - parsesCorrectly( - "{[number,string]}", - `{ - "kind": "JSDocTupleType", - "pos": 1, - "end": 16, - "types": { - "0": { - "kind": "NumberKeyword", - "pos": 2, - "end": 8 - }, - "1": { - "kind": "StringKeyword", - "pos": 9, - "end": 15 - }, - "length": 2, - "pos": 2, - "end": 15 - } -}`); - }); - - it("tupleType3", () => { - parsesCorrectly( - "{[number,string,boolean]}", - `{ - "kind": "JSDocTupleType", - "pos": 1, - "end": 24, - "types": { - "0": { - "kind": "NumberKeyword", - "pos": 2, - "end": 8 - }, - "1": { - "kind": "StringKeyword", - "pos": 9, - "end": 15 - }, - "2": { - "kind": "BooleanKeyword", - "pos": 16, - "end": 23 - }, - "length": 3, - "pos": 2, - "end": 23 - } -}`); - }); + parsesCorrectly("unknownType", "{?}"); + parsesCorrectly("allType", "{*}"); + parsesCorrectly("nullableType", "{?number}"); + parsesCorrectly("nullableType2", "{number?}"); + parsesCorrectly("nonNullableType", "{!number}"); + parsesCorrectly("nonNullableType2", "{number!}"); + parsesCorrectly("recordType1", "{{}}"); + parsesCorrectly("recordType2", "{{foo}}"); + parsesCorrectly("recordType3", "{{foo: number}}"); + parsesCorrectly("recordType4", "{{foo, bar}}"); + parsesCorrectly("recordType5", "{{foo: number, bar}}"); + parsesCorrectly("recordType6", "{{foo, bar: number}}"); + parsesCorrectly("recordType7", "{{foo: number, bar: number}}"); + parsesCorrectly("recordType8", "{{function}}"); + parsesCorrectly("unionType", "{(number|string)}"); + parsesCorrectly("topLevelNoParenUnionType", "{number|string}"); + parsesCorrectly("functionType1", "{function()}"); + parsesCorrectly("functionType2", "{function(string, boolean)}"); + parsesCorrectly("functionReturnType1", "{function(string, boolean)}"); + parsesCorrectly("thisType1", "{this:a.b}"); + parsesCorrectly("newType1", "{new:a.b}"); + parsesCorrectly("variadicType", "{...number}"); + parsesCorrectly("optionalType", "{number=}"); + parsesCorrectly("optionalNullable", "{?=}"); + parsesCorrectly("typeReference1", "{a.}"); + parsesCorrectly("typeReference2", "{a.}"); + parsesCorrectly("typeReference3", "{a.function}"); + parsesCorrectly("arrayType1", "{a[]}"); + parsesCorrectly("arrayType2", "{a[][]}"); + parsesCorrectly("arrayType3", "{a[][]=}"); + parsesCorrectly("keyword1", "{var}"); + parsesCorrectly("keyword2", "{null}"); + parsesCorrectly("keyword3", "{undefined}"); + parsesCorrectly("tupleType0", "{[]}"); + parsesCorrectly("tupleType1", "{[number]}"); + parsesCorrectly("tupleType2", "{[number,string]}"); + parsesCorrectly("tupleType3", "{[number,string,boolean]}"); }); describe("parsesIncorrectly", () => { - it("emptyType", () => { - parsesIncorrectly("{}"); - }); - - it("trailingCommaInRecordType", () => { - parsesIncorrectly("{{a,}}"); - }); - - it("unionTypeWithTrailingBar", () => { - parsesIncorrectly("{(a|)}"); - }); - - it("unionTypeWithoutTypes", () => { - parsesIncorrectly("{()}"); - }); - - it("nullableTypeWithoutType", () => { - parsesIncorrectly("{!}"); - }); - - it("functionTypeWithTrailingComma", () => { - parsesIncorrectly("{function(a,)}"); - }); - - it("thisWithoutType", () => { - parsesIncorrectly("{this:}"); - }); - - it("newWithoutType", () => { - parsesIncorrectly("{new:}"); - }); - - it("variadicWithoutType", () => { - parsesIncorrectly("{...}"); - }); - - it("optionalWithoutType", () => { - parsesIncorrectly("{=}"); - }); - - it("allWithType", () => { - parsesIncorrectly("{*foo}"); - }); - - it("typeArgumentsNotFollowingDot", () => { - parsesIncorrectly("{a<>}"); - }); - - it("emptyTypeArguments", () => { - parsesIncorrectly("{a.<>}"); - }); - - it("typeArgumentsWithTrailingComma", () => { - parsesIncorrectly("{a.}"); - }); - - it("tsFunctionType", () => { - parsesIncorrectly("{() => string}"); - }); - - it("tsConstructoType", () => { - parsesIncorrectly("{new () => string}"); - }); - - it("typeOfType", () => { - parsesIncorrectly("{typeof M}"); - }); - - it("namedParameter", () => { - parsesIncorrectly("{function(a: number)}"); - }); - - it("callSignatureInRecordType", () => { - parsesIncorrectly("{{(): number}}"); - }); - - it("methodInRecordType", () => { - parsesIncorrectly("{{foo(): number}}"); - }); - - it("tupleTypeWithComma", () => { - parsesIncorrectly( "{[,]}"); - }); - - it("tupleTypeWithTrailingComma", () => { - parsesIncorrectly("{[number,]}"); - }); - - it("tupleTypeWithLeadingComma", () => { - parsesIncorrectly("{[,number]}"); - }); + parsesIncorrectly("emptyType", "{}"); + parsesIncorrectly("trailingCommaInRecordType", "{{a,}}"); + parsesIncorrectly("unionTypeWithTrailingBar", "{(a|)}"); + parsesIncorrectly("unionTypeWithoutTypes", "{()}"); + parsesIncorrectly("nullableTypeWithoutType", "{!}"); + parsesIncorrectly("functionTypeWithTrailingComma", "{function(a,)}"); + parsesIncorrectly("thisWithoutType", "{this:}"); + parsesIncorrectly("newWithoutType", "{new:}"); + parsesIncorrectly("variadicWithoutType", "{...}"); + parsesIncorrectly("optionalWithoutType", "{=}"); + parsesIncorrectly("allWithType", "{*foo}"); + parsesIncorrectly("typeArgumentsNotFollowingDot", "{a<>}"); + parsesIncorrectly("emptyTypeArguments", "{a.<>}"); + parsesIncorrectly("typeArgumentsWithTrailingComma", "{a.}"); + parsesIncorrectly("tsFunctionType", "{() => string}"); + parsesIncorrectly("tsConstructoType", "{new () => string}"); + parsesIncorrectly("typeOfType", "{typeof M}"); + parsesIncorrectly("namedParameter", "{function(a: number)}"); + parsesIncorrectly("callSignatureInRecordType", "{{(): number}}"); + parsesIncorrectly("methodInRecordType", "{{foo(): number}}"); + parsesIncorrectly("tupleTypeWithComma", "{[,]}"); + parsesIncorrectly("tupleTypeWithTrailingComma", "{[number,]}"); + parsesIncorrectly("tupleTypeWithLeadingComma", "{[,number]}"); }); }); describe("DocComments", () => { - function parsesCorrectly(content: string, expected: string) { - let comment = parseIsolatedJSDocComment(content); - if (!comment) { - Debug.fail('Comment failed to parse entirely'); - } - if (comment.diagnostics.length > 0) { - Debug.fail('Comment has at least one diagnostic: ' + comment.diagnostics[0].messageText); - } + function parsesCorrectly(name: string, content: string) { + it(name, () => { + let comment = parseIsolatedJSDocComment(content); + if (!comment) { + Debug.fail('Comment failed to parse entirely'); + } + if (comment.diagnostics.length > 0) { + Debug.fail('Comment has at least one diagnostic: ' + comment.diagnostics[0].messageText); + } - let result = JSON.stringify(comment.jsDocComment, (k, v) => { - return v && v.pos !== undefined - ? JSON.parse(Utils.sourceFileToJSON(v)) - : v; - }, 4); - - if (result !== expected) { - // Turn on a human-readable diff - if (typeof require !== 'undefined') { - require('chai').config.showDiff = true; - chai.expect(JSON.parse(result)).equal(JSON.parse(expected)); - } - else { - assert.equal(result, expected); - } - } + Harness.Baseline.runBaseline("parseCorrectly", "JSDocParsing/DocComments.parsesCorrectly." + name + ".json", + () => JSON.stringify(comment.jsDocComment, + (k, v) => v && v.pos !== undefined ? JSON.parse(Utils.sourceFileToJSON(v)) : v, 4)); + }); } - function parsesIncorrectly(content: string) { - let type = parseIsolatedJSDocComment(content); - assert.isTrue(!type || type.diagnostics.length > 0); + function parsesIncorrectly(name: string, content: string) { + it(name, () => { + let type = parseIsolatedJSDocComment(content); + assert.isTrue(!type || type.diagnostics.length > 0); + }); } describe("parsesIncorrectly", () => { - it("emptyComment", () => { - parsesIncorrectly("/***/"); - }); - - it("threeAsterisks", () => { - parsesIncorrectly("/*** */"); - }); - - it("asteriskAfterPreamble", () => { - parsesIncorrectly("/** * @type {number} */"); - }); - - it("multipleTypes", () => { - parsesIncorrectly( -`/** - * @type {number} + parsesIncorrectly("emptyComment", "/***/"); + parsesIncorrectly("threeAsterisks", "/*** */"); + parsesIncorrectly("asteriskAfterPreamble", "/** * @type {number} */"); + parsesIncorrectly("multipleTypes", + `/** + * @type {number} * @type {string} */`); - }); - - it("multipleReturnTypes", () => { - parsesIncorrectly( -`/** + parsesIncorrectly("multipleReturnTypes", + `/** * @return {number} * @return {string} */`); - }); - - it("noTypeParameters", () => { - parsesIncorrectly( -`/** + parsesIncorrectly("noTypeParameters", + `/** * @template */`); - }); - - it("trailingTypeParameterComma", () => { - parsesIncorrectly( -`/** + parsesIncorrectly("trailingTypeParameterComma", + `/** * @template T, */`); - }); - - it("paramWithoutName", () => { - parsesIncorrectly( -`/** + parsesIncorrectly("paramWithoutName", + `/** * @param {number} */`); - }); - - it("paramWithoutTypeOrName", () => { - parsesIncorrectly( -`/** - * @param + parsesIncorrectly("paramWithoutTypeOrName", + `/** + * @param */`); - }); }); describe("parsesCorrectly", () => { - it("noLeadingAsterisk", () => { - parsesCorrectly( + parsesCorrectly("noLeadingAsterisk", `/** @type {number} - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 27, - "tags": { - "0": { - "kind": "JSDocTypeTag", - "pos": 8, - "end": 22, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 13, - "text": "type" - }, - "typeExpression": { - "kind": "JSDocTypeExpression", - "pos": 14, - "end": 22, - "type": { - "kind": "NumberKeyword", - "pos": 15, - "end": 21 - } - } - }, - "length": 1, - "pos": 8, - "end": 22 - } -}`); - }); + */`); - it("noType", () => { - parsesCorrectly( - `/** + + parsesCorrectly("noType", +`/** * @type - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 18, - "tags": { - "0": { - "kind": "JSDocTypeTag", - "pos": 8, - "end": 13, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 13, - "text": "type" - } - }, - "length": 1, - "pos": 8, - "end": 13 - } -}`); - }); + */`); - it("noReturnType", () => { - parsesCorrectly( - `/** + + parsesCorrectly("noReturnType", +`/** * @return - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 20, - "tags": { - "0": { - "kind": "JSDocReturnTag", - "pos": 8, - "end": 15, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 15, - "text": "return" - } - }, - "length": 1, - "pos": 8, - "end": 15 - } -}`); - }); + */`); - it("leadingAsterisk", () => { - parsesCorrectly( + parsesCorrectly("leadingAsterisk", `/** * @type {number} - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 27, - "tags": { - "0": { - "kind": "JSDocTypeTag", - "pos": 8, - "end": 22, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 13, - "text": "type" - }, - "typeExpression": { - "kind": "JSDocTypeExpression", - "pos": 14, - "end": 22, - "type": { - "kind": "NumberKeyword", - "pos": 15, - "end": 21 - } - } - }, - "length": 1, - "pos": 8, - "end": 22 - } -}`); - }); + */`); - it("typeTag", () => { - parsesCorrectly( + + parsesCorrectly("typeTag", `/** * @type {number} - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 27, - "tags": { - "0": { - "kind": "JSDocTypeTag", - "pos": 8, - "end": 22, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 13, - "text": "type" - }, - "typeExpression": { - "kind": "JSDocTypeExpression", - "pos": 14, - "end": 22, - "type": { - "kind": "NumberKeyword", - "pos": 15, - "end": 21 - } - } - }, - "length": 1, - "pos": 8, - "end": 22 - } -}`); - }); + */`); - it("returnTag1", () => { - parsesCorrectly( + + parsesCorrectly("returnTag1", `/** * @return {number} - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 29, - "tags": { - "0": { - "kind": "JSDocReturnTag", - "pos": 8, - "end": 24, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 15, - "text": "return" - }, - "typeExpression": { - "kind": "JSDocTypeExpression", - "pos": 16, - "end": 24, - "type": { - "kind": "NumberKeyword", - "pos": 17, - "end": 23 - } - } - }, - "length": 1, - "pos": 8, - "end": 24 - } -}`); - }); + */`); - it("returnTag2", () => { - parsesCorrectly( - `/** + + parsesCorrectly("returnTag2", +`/** * @return {number} Description text follows - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 54, - "tags": { - "0": { - "kind": "JSDocReturnTag", - "pos": 8, - "end": 24, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 15, - "text": "return" - }, - "typeExpression": { - "kind": "JSDocTypeExpression", - "pos": 16, - "end": 24, - "type": { - "kind": "NumberKeyword", - "pos": 17, - "end": 23 - } - } - }, - "length": 1, - "pos": 8, - "end": 24 - } -}`); - }); + */`); - it("returnsTag1", () => { - parsesCorrectly( - `/** + + parsesCorrectly("returnsTag1", +`/** * @returns {number} - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 30, - "tags": { - "0": { - "kind": "JSDocReturnTag", - "pos": 8, - "end": 25, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 16, - "text": "returns" - }, - "typeExpression": { - "kind": "JSDocTypeExpression", - "pos": 17, - "end": 25, - "type": { - "kind": "NumberKeyword", - "pos": 18, - "end": 24 - } - } - }, - "length": 1, - "pos": 8, - "end": 25 - } -}`); - }); + */`); - it("oneParamTag", () => { - parsesCorrectly( + + parsesCorrectly("oneParamTag", `/** * @param {number} name1 - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 34, - "tags": { - "0": { - "kind": "JSDocParameterTag", - "pos": 8, - "end": 29, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 14, - "text": "param" - }, - "typeExpression": { - "kind": "JSDocTypeExpression", - "pos": 15, - "end": 23, - "type": { - "kind": "NumberKeyword", - "pos": 16, - "end": 22 - } - }, - "postParameterName": { - "kind": "Identifier", - "pos": 24, - "end": 29, - "text": "name1" - } - }, - "length": 1, - "pos": 8, - "end": 29 - } -}`); - }); + */`); - it("twoParamTag2", () => { - parsesCorrectly( + + parsesCorrectly("twoParamTag2", `/** * @param {number} name1 * @param {number} name2 - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 60, - "tags": { - "0": { - "kind": "JSDocParameterTag", - "pos": 8, - "end": 29, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 14, - "text": "param" - }, - "typeExpression": { - "kind": "JSDocTypeExpression", - "pos": 15, - "end": 23, - "type": { - "kind": "NumberKeyword", - "pos": 16, - "end": 22 - } - }, - "postParameterName": { - "kind": "Identifier", - "pos": 24, - "end": 29, - "text": "name1" - } - }, - "1": { - "kind": "JSDocParameterTag", - "pos": 34, - "end": 55, - "atToken": { - "kind": "AtToken", - "pos": 34, - "end": 35 - }, - "tagName": { - "kind": "Identifier", - "pos": 35, - "end": 40, - "text": "param" - }, - "typeExpression": { - "kind": "JSDocTypeExpression", - "pos": 41, - "end": 49, - "type": { - "kind": "NumberKeyword", - "pos": 42, - "end": 48 - } - }, - "postParameterName": { - "kind": "Identifier", - "pos": 50, - "end": 55, - "text": "name2" - } - }, - "length": 2, - "pos": 8, - "end": 55 - } -}`); - }); + */`); - it("paramTag1", () => { - parsesCorrectly( - `/** + + parsesCorrectly("paramTag1", +`/** * @param {number} name1 Description text follows - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 59, - "tags": { - "0": { - "kind": "JSDocParameterTag", - "pos": 8, - "end": 29, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 14, - "text": "param" - }, - "typeExpression": { - "kind": "JSDocTypeExpression", - "pos": 15, - "end": 23, - "type": { - "kind": "NumberKeyword", - "pos": 16, - "end": 22 - } - }, - "postParameterName": { - "kind": "Identifier", - "pos": 24, - "end": 29, - "text": "name1" - } - }, - "length": 1, - "pos": 8, - "end": 29 - } -}`); - }); + */`); - it("paramTagBracketedName1", () => { - parsesCorrectly( - `/** + + parsesCorrectly("paramTagBracketedName1", +`/** * @param {number} [name1] Description text follows - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 61, - "tags": { - "0": { - "kind": "JSDocParameterTag", - "pos": 8, - "end": 31, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 14, - "text": "param" - }, - "typeExpression": { - "kind": "JSDocTypeExpression", - "pos": 15, - "end": 23, - "type": { - "kind": "NumberKeyword", - "pos": 16, - "end": 22 - } - }, - "postParameterName": { - "kind": "Identifier", - "pos": 25, - "end": 30, - "text": "name1" - }, - "isBracketed": true - }, - "length": 1, - "pos": 8, - "end": 31 - } -}`); - }); + */`); - it("paramTagBracketedName2", () => { - parsesCorrectly( - `/** + + parsesCorrectly("paramTagBracketedName2", +`/** * @param {number} [ name1 = 1] Description text follows - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 66, - "tags": { - "0": { - "kind": "JSDocParameterTag", - "pos": 8, - "end": 36, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 14, - "text": "param" - }, - "typeExpression": { - "kind": "JSDocTypeExpression", - "pos": 15, - "end": 23, - "type": { - "kind": "NumberKeyword", - "pos": 16, - "end": 22 - } - }, - "postParameterName": { - "kind": "Identifier", - "pos": 26, - "end": 31, - "text": "name1" - }, - "isBracketed": true - }, - "length": 1, - "pos": 8, - "end": 36 - } -}`); - }); + */`); - it("twoParamTagOnSameLine", () => { - parsesCorrectly( + + parsesCorrectly("twoParamTagOnSameLine", `/** * @param {number} name1 @param {number} name2 - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 56, - "tags": { - "0": { - "kind": "JSDocParameterTag", - "pos": 8, - "end": 29, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 14, - "text": "param" - }, - "typeExpression": { - "kind": "JSDocTypeExpression", - "pos": 15, - "end": 23, - "type": { - "kind": "NumberKeyword", - "pos": 16, - "end": 22 - } - }, - "postParameterName": { - "kind": "Identifier", - "pos": 24, - "end": 29, - "text": "name1" - } - }, - "length": 1, - "pos": 8, - "end": 29 - } -}`); - }); + */`); - it("paramTagNameThenType1", () => { - parsesCorrectly( - `/** + + parsesCorrectly("paramTagNameThenType1", +`/** * @param name1 {number} - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 34, - "tags": { - "0": { - "kind": "JSDocParameterTag", - "pos": 8, - "end": 29, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 14, - "text": "param" - }, - "preParameterName": { - "kind": "Identifier", - "pos": 15, - "end": 20, - "text": "name1" - }, - "typeExpression": { - "kind": "JSDocTypeExpression", - "pos": 21, - "end": 29, - "type": { - "kind": "NumberKeyword", - "pos": 22, - "end": 28 - } - } - }, - "length": 1, - "pos": 8, - "end": 29 - } -}`); - }); + */`); - it("paramTagNameThenType2", () => { - parsesCorrectly( - `/** + + parsesCorrectly("paramTagNameThenType2", +`/** * @param name1 {number} Description - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 46, - "tags": { - "0": { - "kind": "JSDocParameterTag", - "pos": 8, - "end": 29, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 14, - "text": "param" - }, - "preParameterName": { - "kind": "Identifier", - "pos": 15, - "end": 20, - "text": "name1" - }, - "typeExpression": { - "kind": "JSDocTypeExpression", - "pos": 21, - "end": 29, - "type": { - "kind": "NumberKeyword", - "pos": 22, - "end": 28 - } - } - }, - "length": 1, - "pos": 8, - "end": 29 - } -}`); - }); + */`); - it("templateTag", () => { - parsesCorrectly( + + parsesCorrectly("templateTag", `/** * @template T - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 24, - "tags": { - "0": { - "kind": "JSDocTemplateTag", - "pos": 8, - "end": 19, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 17, - "text": "template" - }, - "typeParameters": { - "0": { - "kind": "TypeParameter", - "pos": 18, - "end": 19, - "name": { - "kind": "Identifier", - "pos": 18, - "end": 19, - "text": "T" - } - }, - "length": 1, - "pos": 17, - "end": 19 - } - }, - "length": 1, - "pos": 8, - "end": 19 - } -}`); - }); + */`); - it("templateTag2", () => { - parsesCorrectly( - `/** + + parsesCorrectly("templateTag2", +`/** * @template K,V - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 26, - "tags": { - "0": { - "kind": "JSDocTemplateTag", - "pos": 8, - "end": 21, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 17, - "text": "template" - }, - "typeParameters": { - "0": { - "kind": "TypeParameter", - "pos": 18, - "end": 19, - "name": { - "kind": "Identifier", - "pos": 18, - "end": 19, - "text": "K" - } - }, - "1": { - "kind": "TypeParameter", - "pos": 20, - "end": 21, - "name": { - "kind": "Identifier", - "pos": 20, - "end": 21, - "text": "V" - } - }, - "length": 2, - "pos": 17, - "end": 21 - } - }, - "length": 1, - "pos": 8, - "end": 21 - } -}`); - }); + */`); - it("templateTag3", () => { - parsesCorrectly( - `/** + + parsesCorrectly("templateTag3", +`/** * @template K ,V - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 27, - "tags": { - "0": { - "kind": "JSDocTemplateTag", - "pos": 8, - "end": 22, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 17, - "text": "template" - }, - "typeParameters": { - "0": { - "kind": "TypeParameter", - "pos": 18, - "end": 19, - "name": { - "kind": "Identifier", - "pos": 18, - "end": 19, - "text": "K" - } - }, - "1": { - "kind": "TypeParameter", - "pos": 21, - "end": 22, - "name": { - "kind": "Identifier", - "pos": 21, - "end": 22, - "text": "V" - } - }, - "length": 2, - "pos": 17, - "end": 22 - } - }, - "length": 1, - "pos": 8, - "end": 22 - } -}`); - }); + */`); - it("templateTag4", () => { - parsesCorrectly( - `/** + + parsesCorrectly("templateTag4", +`/** * @template K, V - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 27, - "tags": { - "0": { - "kind": "JSDocTemplateTag", - "pos": 8, - "end": 22, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 17, - "text": "template" - }, - "typeParameters": { - "0": { - "kind": "TypeParameter", - "pos": 18, - "end": 19, - "name": { - "kind": "Identifier", - "pos": 18, - "end": 19, - "text": "K" - } - }, - "1": { - "kind": "TypeParameter", - "pos": 21, - "end": 22, - "name": { - "kind": "Identifier", - "pos": 21, - "end": 22, - "text": "V" - } - }, - "length": 2, - "pos": 17, - "end": 22 - } - }, - "length": 1, - "pos": 8, - "end": 22 - } -}`); - }); + */`); - it("templateTag5", () => { - parsesCorrectly( - `/** + + parsesCorrectly("templateTag5", +`/** * @template K , V - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 28, - "tags": { - "0": { - "kind": "JSDocTemplateTag", - "pos": 8, - "end": 23, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 17, - "text": "template" - }, - "typeParameters": { - "0": { - "kind": "TypeParameter", - "pos": 18, - "end": 19, - "name": { - "kind": "Identifier", - "pos": 18, - "end": 19, - "text": "K" - } - }, - "1": { - "kind": "TypeParameter", - "pos": 22, - "end": 23, - "name": { - "kind": "Identifier", - "pos": 22, - "end": 23, - "text": "V" - } - }, - "length": 2, - "pos": 17, - "end": 23 - } - }, - "length": 1, - "pos": 8, - "end": 23 - } -}`); - }); + */`); - it("templateTag6", () => { - parsesCorrectly( - `/** + parsesCorrectly("templateTag6", +`/** * @template K , V Description of type parameters. - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 60, - "tags": { - "0": { - "kind": "JSDocTemplateTag", - "pos": 8, - "end": 23, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 17, - "text": "template" - }, - "typeParameters": { - "0": { - "kind": "TypeParameter", - "pos": 18, - "end": 19, - "name": { - "kind": "Identifier", - "pos": 18, - "end": 19, - "text": "K" - } - }, - "1": { - "kind": "TypeParameter", - "pos": 22, - "end": 23, - "name": { - "kind": "Identifier", - "pos": 22, - "end": 23, - "text": "V" - } - }, - "length": 2, - "pos": 17, - "end": 23 - } - }, - "length": 1, - "pos": 8, - "end": 23 - } -}`); - }); + */`); - it("paramWithoutType", () => { - parsesCorrectly( - `/** + parsesCorrectly("paramWithoutType", +`/** * @param foo - */`, - `{ - "kind": "JSDocComment", - "pos": 0, - "end": 23, - "tags": { - "0": { - "kind": "JSDocParameterTag", - "pos": 8, - "end": 18, - "atToken": { - "kind": "AtToken", - "pos": 8, - "end": 9 - }, - "tagName": { - "kind": "Identifier", - "pos": 9, - "end": 14, - "text": "param" - }, - "preParameterName": { - "kind": "Identifier", - "pos": 15, - "end": 18, - "text": "foo" - } - }, - "length": 1, - "pos": 8, - "end": 18 - } -}`); - }); + */`); }); }); }); From 8bf176ac3dcc5edb8d3e1a4d219c681f22c02377 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 4 Feb 2016 16:41:58 -0800 Subject: [PATCH 2/2] Cleanup and reorganization of node tests --- src/compiler/binder.ts | 2 +- src/compiler/checker.ts | 10 +- src/compiler/emitter.ts | 6 +- src/compiler/factory.ts | 1 + src/compiler/program.ts | 2 +- src/compiler/scanner.ts | 2 +- src/compiler/types.ts | 32 +- src/compiler/utilities.ts | 872 ++++++++++++----------- src/compiler/visitor.ts | 810 ++++++++++----------- src/harness/typeWriter.ts | 2 +- src/services/breakpoints.ts | 2 +- src/services/formatting/rules.ts | 10 +- src/services/formatting/smartIndenter.ts | 4 +- src/services/services.ts | 4 +- 14 files changed, 919 insertions(+), 840 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 0e169ca7aca..f377fb674d2 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1696,7 +1696,7 @@ namespace ts { case Reachability.Unreachable: const reportError = // report error on all statements except empty ones - (isStatement(node) && node.kind !== SyntaxKind.EmptyStatement) || + (isStatementButNotDeclaration(node) && node.kind !== SyntaxKind.EmptyStatement) || // report error on class declarations node.kind === SyntaxKind.ClassDeclaration || // report error on instantiated modules or const-enums only modules if preserveConstEnums is set diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0628e7fd522..3cb9031fd99 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4934,7 +4934,7 @@ namespace ts { case SyntaxKind.JSDocRecordType: return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); // This function assumes that an identifier or qualified name is a type expression - // Callers should first ensure this by calling isTypeNode + // Callers should first ensure this by calling isPartOfTypeNode case SyntaxKind.Identifier: case SyntaxKind.QualifiedName: const symbol = getSymbolAtLocation(node); @@ -15385,7 +15385,7 @@ namespace ts { (entityName.parent.kind === SyntaxKind.JsxClosingElement)) { return getJsxElementTagSymbol(entityName.parent); } - else if (isExpression(entityName)) { + else if (isPartOfExpression(entityName)) { if (nodeIsMissing(entityName)) { // Missing entity name. return undefined; @@ -15468,7 +15468,7 @@ namespace ts { case SyntaxKind.ThisKeyword: case SyntaxKind.SuperKeyword: - const type = isExpression(node) ? checkExpression(node) : getTypeFromTypeNode(node); + const type = isPartOfExpression(node) ? checkExpression(node) : getTypeFromTypeNode(node); return type.symbol; case SyntaxKind.ThisType: @@ -15529,11 +15529,11 @@ namespace ts { return unknownType; } - if (isTypeNode(node)) { + if (isPartOfTypeNode(node)) { return getTypeFromTypeNode(node); } - if (isExpression(node)) { + if (isPartOfExpression(node)) { return getTypeOfExpression(node); } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index e86d86603b4..f0e32bdf96c 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1020,7 +1020,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge return; } - const emitOuterParens = isExpression(node.parent) + const emitOuterParens = isPartOfExpression(node.parent) && templateNeedsParens(node, node.parent); if (emitOuterParens) { @@ -5788,7 +5788,7 @@ const _super = (function (geti, seti) { /** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */ function emitSerializedTypeReferenceNode(node: TypeReferenceNode) { let location: Node = node.parent; - while (isDeclaration(location) || isTypeNode(location)) { + while (isDeclaration(location) || isPartOfTypeNode(location)) { location = location.parent; } @@ -7156,7 +7156,7 @@ const _super = (function (geti, seti) { } // text should be quoted string - // for deduplication purposes in key remove leading and trailing quotes so 'a' and "a" will be considered the same + // for deduplication purposes in key remove leading and trailing quotes so 'a' and "a" will be considered the same const key = text.substr(1, text.length - 2); if (hasProperty(groupIndices, key)) { diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index d838288ef25..c28162d8723 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -134,4 +134,5 @@ namespace ts { block.statements = createNodeArray(statements); return block; } + } \ No newline at end of file diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 9852b2354e2..4a3d0cbc164 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1719,7 +1719,7 @@ namespace ts { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators")); } - if (options.reactNamespace && !isIdentifier(options.reactNamespace, languageVersion)) { + if (options.reactNamespace && !isIdentifierText(options.reactNamespace, languageVersion)) { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Invalid_value_for_reactNamespace_0_is_not_a_valid_identifier, options.reactNamespace)); } diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 4470d7f623c..68c8f5bc794 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -696,7 +696,7 @@ namespace ts { } /* @internal */ - export function isIdentifier(name: string, languageVersion: ScriptTarget): boolean { + export function isIdentifierText(name: string, languageVersion: ScriptTarget): boolean { if (!isIdentifierStart(name.charCodeAt(0), languageVersion)) { return false; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 177934fc13b..e123d08e81c 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -553,10 +553,12 @@ namespace ts { // @kind(SyntaxKind.ConstructSignature) export interface ConstructSignatureDeclaration extends SignatureDeclaration, TypeElement { } + export type BindingName = Identifier | ObjectBindingPattern | ArrayBindingPattern; + // @kind(SyntaxKind.VariableDeclaration) export interface VariableDeclaration extends Declaration { parent?: VariableDeclarationList; - name: Identifier | BindingPattern; // Declared variable name + name: BindingName; // Declared variable name type?: TypeNode; // Optional type annotation initializer?: Expression; // Optional initializer } @@ -569,7 +571,7 @@ namespace ts { // @kind(SyntaxKind.Parameter) export interface ParameterDeclaration extends Declaration { dotDotDotToken?: Node; // Present on rest parameter - name: Identifier | BindingPattern; // Declared parameter name + name: BindingName; // Declared parameter name questionToken?: Node; // Present on optional parameter type?: TypeNode; // Optional type annotation initializer?: Expression; // Optional initializer @@ -579,7 +581,7 @@ namespace ts { export interface BindingElement extends Declaration { propertyName?: PropertyName; // Binding property name (in object binding pattern) dotDotDotToken?: Node; // Present on rest binding element - name: Identifier | BindingPattern; // Declared binding element name + name: BindingName; // Declared binding element name initializer?: Expression; // Optional initializer } @@ -946,6 +948,8 @@ namespace ts { _templateLiteralFragmentBrand: any; } + export type Template = TemplateExpression | LiteralExpression; + // @kind(SyntaxKind.TemplateExpression) export interface TemplateExpression extends PrimaryExpression { head: TemplateLiteralFragment; @@ -1017,7 +1021,7 @@ namespace ts { // @kind(SyntaxKind.TaggedTemplateExpression) export interface TaggedTemplateExpression extends MemberExpression { tag: LeftHandSideExpression; - template: LiteralExpression | TemplateExpression; + template: Template; } export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator; @@ -1049,7 +1053,7 @@ namespace ts { export interface JsxOpeningElement extends Expression { _openingElementBrand?: any; tagName: EntityName; - attributes: NodeArray; + attributes: NodeArray; } /// A JSX expression of the form @@ -1061,6 +1065,8 @@ namespace ts { /// Either the opening tag in a ... pair, or the lone in a self-closing form export type JsxOpeningLikeElement = JsxSelfClosingElement | JsxOpeningElement; + export type JsxAttributeLike = JsxAttribute | JsxSpreadAttribute; + // @kind(SyntaxKind.JsxAttribute) export interface JsxAttribute extends Node { name: Identifier; @@ -1143,22 +1149,24 @@ namespace ts { expression: Expression; } + export type ForInitializer = VariableDeclarationList | Expression; + // @kind(SyntaxKind.ForStatement) export interface ForStatement extends IterationStatement { - initializer?: VariableDeclarationList | Expression; + initializer?: ForInitializer; condition?: Expression; incrementor?: Expression; } // @kind(SyntaxKind.ForInStatement) export interface ForInStatement extends IterationStatement { - initializer: VariableDeclarationList | Expression; + initializer: ForInitializer; expression: Expression; } // @kind(SyntaxKind.ForOfStatement) export interface ForOfStatement extends IterationStatement { - initializer: VariableDeclarationList | Expression; + initializer: ForInitializer; expression: Expression; } @@ -1297,9 +1305,11 @@ namespace ts { export type ModuleBody = ModuleBlock | ModuleDeclaration; + export type ModuleName = Identifier | StringLiteral; + // @kind(SyntaxKind.ModuleDeclaration) export interface ModuleDeclaration extends DeclarationStatement { - name: Identifier | LiteralExpression; + name: ModuleName; body: ModuleBlock | ModuleDeclaration; } @@ -1334,6 +1344,8 @@ namespace ts { moduleSpecifier: Expression; } + export type NamedImportBindings = NamespaceImport | NamedImports; + // In case of: // import d from "mod" => name = d, namedBinding = undefined // import * as ns from "mod" => name = undefined, namedBinding: NamespaceImport = { name: ns } @@ -1343,7 +1355,7 @@ namespace ts { // @kind(SyntaxKind.ImportClause) export interface ImportClause extends Declaration { name?: Identifier; // Default binding - namedBindings?: NamespaceImport | NamedImports; + namedBindings?: NamedImportBindings; } // @kind(SyntaxKind.NamespaceImport) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index a6df27bc3b9..9cc5ffcf30f 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -498,7 +498,7 @@ namespace ts { export let fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*/; export let fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*/; - export function isTypeNode(node: Node): boolean { + export function isPartOfTypeNode(node: Node): boolean { if (SyntaxKind.FirstTypeNode <= node.kind && node.kind <= SyntaxKind.LastTypeNode) { return true; } @@ -527,7 +527,7 @@ namespace ts { } // At this point, node is either a qualified name or an identifier Debug.assert(node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName || node.kind === SyntaxKind.PropertyAccessExpression, - "'node' was expected to be a qualified name, identifier or property access in 'isTypeNode'."); + "'node' was expected to be a qualified name, identifier or property access in 'isPartOfTypeNode'."); case SyntaxKind.QualifiedName: case SyntaxKind.PropertyAccessExpression: case SyntaxKind.ThisKeyword: @@ -535,11 +535,11 @@ namespace ts { if (parent.kind === SyntaxKind.TypeQuery) { return false; } - // Do not recursively call isTypeNode on the parent. In the example: + // Do not recursively call isPartOfTypeNode on the parent. In the example: // // let a: A.B.C; // - // Calling isTypeNode would consider the qualified name A.B a type node. Only C or + // Calling isPartOfTypeNode would consider the qualified name A.B a type node. Only C or // A.B.C is a type node. if (SyntaxKind.FirstTypeNode <= parent.kind && parent.kind <= SyntaxKind.LastTypeNode) { return true; @@ -643,7 +643,7 @@ namespace ts { return; } } - else if (!isTypeNode(node)) { + else if (!isPartOfTypeNode(node)) { // This is the general case, which should include mostly expressions and statements. // Also includes NodeArrays. forEachChild(node, traverse); @@ -652,6 +652,7 @@ namespace ts { } } + export function isVariableLike(node: Node): node is VariableLikeDeclaration { if (node) { switch (node.kind) { @@ -938,15 +939,7 @@ namespace ts { && nodeCanBeDecorated(node); } - export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression { - return node.kind === SyntaxKind.PropertyAccessExpression; - } - - export function isElementAccessExpression(node: Node): node is ElementAccessExpression { - return node.kind === SyntaxKind.ElementAccessExpression; - } - - export function isExpression(node: Node): boolean { + export function isPartOfExpression(node: Node): boolean { switch (node.kind) { case SyntaxKind.SuperKeyword: case SyntaxKind.NullKeyword: @@ -1040,7 +1033,7 @@ namespace ts { case SyntaxKind.ExpressionWithTypeArguments: return (parent).expression === node && isExpressionWithTypeArgumentsInClassExtendsClause(parent); default: - if (isExpression(parent)) { + if (isPartOfExpression(parent)) { return true; } } @@ -1295,10 +1288,6 @@ namespace ts { return SyntaxKind.FirstTemplateToken <= kind && kind <= SyntaxKind.LastTemplateToken; } - export function isBindingPattern(node: Node): node is BindingPattern { - return !!node && (node.kind === SyntaxKind.ArrayBindingPattern || node.kind === SyntaxKind.ObjectBindingPattern); - } - export function isNodeDescendentOf(node: Node, ancestor: Node): boolean { while (node) { if (node === ancestor) return true; @@ -1317,83 +1306,6 @@ namespace ts { return false; } - export function isDeclaration(node: Node): boolean { - switch (node.kind) { - case SyntaxKind.ArrowFunction: - case SyntaxKind.BindingElement: - case SyntaxKind.ClassDeclaration: - case SyntaxKind.ClassExpression: - case SyntaxKind.Constructor: - case SyntaxKind.EnumDeclaration: - case SyntaxKind.EnumMember: - case SyntaxKind.ExportSpecifier: - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.FunctionExpression: - case SyntaxKind.GetAccessor: - case SyntaxKind.ImportClause: - case SyntaxKind.ImportEqualsDeclaration: - case SyntaxKind.ImportSpecifier: - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.MethodSignature: - case SyntaxKind.ModuleDeclaration: - case SyntaxKind.NamespaceImport: - case SyntaxKind.Parameter: - case SyntaxKind.PropertyAssignment: - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.PropertySignature: - case SyntaxKind.SetAccessor: - case SyntaxKind.ShorthandPropertyAssignment: - case SyntaxKind.TypeAliasDeclaration: - case SyntaxKind.TypeParameter: - case SyntaxKind.VariableDeclaration: - return true; - } - return false; - } - - export function isStatement(n: Node): boolean { - switch (n.kind) { - case SyntaxKind.BreakStatement: - case SyntaxKind.ContinueStatement: - case SyntaxKind.DebuggerStatement: - case SyntaxKind.DoStatement: - case SyntaxKind.ExpressionStatement: - case SyntaxKind.EmptyStatement: - case SyntaxKind.ForInStatement: - case SyntaxKind.ForOfStatement: - case SyntaxKind.ForStatement: - case SyntaxKind.IfStatement: - case SyntaxKind.LabeledStatement: - case SyntaxKind.ReturnStatement: - case SyntaxKind.SwitchStatement: - case SyntaxKind.ThrowStatement: - case SyntaxKind.TryStatement: - case SyntaxKind.VariableStatement: - case SyntaxKind.WhileStatement: - case SyntaxKind.WithStatement: - case SyntaxKind.ExportAssignment: - return true; - default: - return false; - } - } - - export function isClassElement(n: Node): n is ClassElement { - switch (n.kind) { - case SyntaxKind.Constructor: - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - case SyntaxKind.MethodSignature: - case SyntaxKind.IndexSignature: - return true; - default: - return false; - } - } - // True if the given identifier, string literal, or number literal is the name of a declaration node export function isDeclarationName(name: Node): name is Identifier | StringLiteral | LiteralExpression { if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) { @@ -1663,10 +1575,6 @@ namespace ts { return clone; } - export function isQualifiedName(node: Node): node is QualifiedName { - return node.kind === SyntaxKind.QualifiedName; - } - export function nodeIsSynthesized(node: TextRange): boolean { return positionIsSynthesized(node.pos) || positionIsSynthesized(node.end); @@ -2332,65 +2240,6 @@ namespace ts { return 0; } - export function isLiteralExpression(node: Node): node is LiteralExpression { - return isLiteralKind(node.kind); - } - - export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression { - if (node) { - switch (node.kind) { - case SyntaxKind.PropertyAccessExpression: - case SyntaxKind.ElementAccessExpression: - case SyntaxKind.NewExpression: - case SyntaxKind.CallExpression: - case SyntaxKind.JsxElement: - case SyntaxKind.JsxSelfClosingElement: - case SyntaxKind.TaggedTemplateExpression: - case SyntaxKind.ArrayLiteralExpression: - case SyntaxKind.ParenthesizedExpression: - case SyntaxKind.ObjectLiteralExpression: - case SyntaxKind.ClassExpression: - case SyntaxKind.FunctionExpression: - case SyntaxKind.Identifier: - case SyntaxKind.RegularExpressionLiteral: - case SyntaxKind.NumericLiteral: - case SyntaxKind.StringLiteral: - case SyntaxKind.NoSubstitutionTemplateLiteral: - case SyntaxKind.TemplateExpression: - case SyntaxKind.FalseKeyword: - case SyntaxKind.NullKeyword: - case SyntaxKind.ThisKeyword: - case SyntaxKind.TrueKeyword: - case SyntaxKind.SuperKeyword: - return true; - } - } - - return false; - } - - export function isEntityName(node: Node): node is EntityName { - const kind = node.kind; - return kind === SyntaxKind.QualifiedName - || kind === SyntaxKind.Identifier; - } - - export function isIdentifierNode(node: Node): node is Identifier { - return node.kind === SyntaxKind.Identifier; - } - - export function isComputedPropertyName(node: Node): node is ComputedPropertyName { - return node.kind === SyntaxKind.ComputedPropertyName; - } - - export function isBinaryExpression(node: Node): node is BinaryExpression { - return node.kind === SyntaxKind.BinaryExpression; - } - - export function isShortHandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment { - return node.kind === SyntaxKind.ShorthandPropertyAssignment; - } - export function isAssignmentOperator(token: SyntaxKind): boolean { return token >= SyntaxKind.FirstAssignment && token <= SyntaxKind.LastAssignment; } @@ -2401,245 +2250,6 @@ namespace ts { isClassLike(node.parent.parent); } - export function isExpressionNode(node: Node): node is Expression { - const kind = node.kind; - return isUnaryExpression(node) - || kind === SyntaxKind.ConditionalExpression - || kind === SyntaxKind.YieldExpression - || kind === SyntaxKind.ArrowFunction - || kind === SyntaxKind.BinaryExpression - || kind === SyntaxKind.SpreadElementExpression - || kind === SyntaxKind.AsExpression - || kind === SyntaxKind.OmittedExpression; - } - - export function isDecorator(node: Node): node is Decorator { - return node.kind === SyntaxKind.Decorator; - } - - export function isModifier(node: Node): node is Modifier { - return isModifierKind(node.kind); - } - - /** - * Node test that determines whether a node is a valid type node. - * This differs from the existing `isTypeNode` function which - * determines whether a node is *part* of a TypeNode. - */ - export function isTypeNodeNode(node: Node): node is TypeNode { - const kind = node.kind; - return kind === SyntaxKind.AnyKeyword - || kind === SyntaxKind.NumberKeyword - || kind === SyntaxKind.BooleanKeyword - || kind === SyntaxKind.StringKeyword - || kind === SyntaxKind.SymbolKeyword - || kind === SyntaxKind.VoidKeyword - || kind === SyntaxKind.FunctionType - || kind === SyntaxKind.ConstructorType - || kind === SyntaxKind.TypeReference - || kind === SyntaxKind.TypePredicate - || kind === SyntaxKind.TypeQuery - || kind === SyntaxKind.TypeLiteral - || kind === SyntaxKind.ArrayType - || kind === SyntaxKind.TupleType - || kind === SyntaxKind.UnionType - || kind === SyntaxKind.IntersectionType - || kind === SyntaxKind.ParenthesizedType - || kind === SyntaxKind.StringLiteralType - || kind === SyntaxKind.ExpressionWithTypeArguments - || kind === SyntaxKind.ThisType; - } - - export function isStatementNode(node: Node): node is Statement { - return isStatement(node) - || isDeclarationStatement(node); - } - - export function isDeclarationStatement(node: Node): node is DeclarationStatement { - const kind = node.kind; - return kind === SyntaxKind.FunctionDeclaration - || kind === SyntaxKind.MissingDeclaration - || kind === SyntaxKind.ClassDeclaration - || kind === SyntaxKind.InterfaceDeclaration - || kind === SyntaxKind.TypeAliasDeclaration - || kind === SyntaxKind.EnumDeclaration - || kind === SyntaxKind.ModuleDeclaration - || kind === SyntaxKind.ImportEqualsDeclaration - || kind === SyntaxKind.ExportDeclaration - || kind === SyntaxKind.ExportAssignment; - } - - export function isPropertyName(node: Node): node is PropertyName { - const kind = node.kind; - return kind === SyntaxKind.Identifier - || kind === SyntaxKind.StringLiteral - || kind === SyntaxKind.NumericLiteral - || kind === SyntaxKind.ComputedPropertyName; - } - - export function isConciseBody(node: Node): node is Expression | Block { - return isBlock(node) - || isExpressionNode(node); - } - - export function isTypeParameter(node: Node): node is TypeParameterDeclaration { - return node.kind === SyntaxKind.TypeParameter; - } - - export function isParameter(node: Node): node is ParameterDeclaration { - return node.kind === SyntaxKind.Parameter; - } - - export function isBindingElement(node: Node): node is BindingElement { - return node.kind === SyntaxKind.BindingElement; - } - - export function isObjectLiteralElement(node: Node): node is ObjectLiteralElement { - const kind = node.kind; - return kind === SyntaxKind.PropertyAssignment - || kind === SyntaxKind.ShorthandPropertyAssignment - || kind === SyntaxKind.MethodDeclaration - || kind === SyntaxKind.GetAccessor - || kind === SyntaxKind.SetAccessor - || kind === SyntaxKind.MissingDeclaration; - } - - export function isTemplate(node: Node): node is LiteralExpression | TemplateExpression { - const kind = node.kind; - return kind === SyntaxKind.TemplateExpression - || kind === SyntaxKind.NoSubstitutionTemplateLiteral; - } - - export function isUnaryExpression(node: Node): node is UnaryExpression { - const kind = node.kind; - return isLeftHandSideExpression(node) - || kind === SyntaxKind.PrefixUnaryExpression - || kind === SyntaxKind.PostfixUnaryExpression - || kind === SyntaxKind.DeleteExpression - || kind === SyntaxKind.TypeOfExpression - || kind === SyntaxKind.VoidExpression - || kind === SyntaxKind.AwaitExpression - || kind === SyntaxKind.TypeAssertionExpression; - } - - export function isTemplateLiteralFragment(node: Node): node is TemplateLiteralFragment { - const kind = node.kind; - return kind === SyntaxKind.TemplateHead - || kind === SyntaxKind.TemplateMiddle - || kind === SyntaxKind.TemplateTail; - } - - export function isTemplateSpan(node: Node): node is TemplateSpan { - return node.kind === SyntaxKind.TemplateSpan; - } - - export function isHeritageClause(node: Node): node is HeritageClause { - return node.kind === SyntaxKind.HeritageClause; - } - - export function isVariableDeclarationList(node: Node): node is VariableDeclarationList { - return node.kind === SyntaxKind.VariableDeclarationList; - } - - export function isExpressionOrVariableDeclarationList(node: Node): node is Expression | VariableDeclarationList { - return isVariableDeclarationList(node) - || isExpressionNode(node); - } - - export function isCaseBlock(node: Node): node is CaseBlock { - return node.kind === SyntaxKind.CaseBlock; - } - - export function isBlock(node: Node): node is Block { - return node.kind === SyntaxKind.Block; - } - - export function isCatchClause(node: Node): node is CatchClause { - return node.kind === SyntaxKind.CatchClause; - } - - export function isVariableDeclaration(node: Node): node is VariableDeclaration { - return node.kind === SyntaxKind.VariableDeclaration; - } - - export function isEnumMember(node: Node): node is EnumMember { - return node.kind === SyntaxKind.EnumMember; - } - - export function isModuleName(node: Node): node is Identifier | LiteralExpression { - return node.kind === SyntaxKind.Identifier - || node.kind === SyntaxKind.StringLiteral; - } - - export function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause { - return node.kind === SyntaxKind.CaseClause - || node.kind === SyntaxKind.DefaultClause; - } - - export function isModuleReference(node: Node): node is EntityName | ExternalModuleReference { - return node.kind === SyntaxKind.ExternalModuleReference - || isEntityName(node); - } - - export function isImportClause(node: Node): node is ImportClause { - return node.kind === SyntaxKind.ImportClause; - } - - export function isNamedImportsOrNamespaceImport(node: Node): node is NamedImports | NamespaceImport { - const kind = node.kind; - return kind === SyntaxKind.NamedImports - || kind === SyntaxKind.NamespaceImport; - } - - export function isImportSpecifier(node: Node): node is ImportSpecifier { - return node.kind === SyntaxKind.ImportSpecifier; - } - - export function isNamedExports(node: Node): node is NamedExports { - return node.kind === SyntaxKind.NamedExports; - } - - export function isExportSpecifier(node: Node): node is ExportSpecifier { - return node.kind === SyntaxKind.ExportSpecifier; - } - - export function isJsxOpeningElement(node: Node): node is JsxOpeningElement { - return node.kind === SyntaxKind.JsxOpeningElement; - } - - export function isJsxClosingElement(node: Node): node is JsxClosingElement { - return node.kind === SyntaxKind.JsxClosingElement; - } - - export function isJsxChild(node: Node): node is JsxChild { - const kind = node.kind; - return kind === SyntaxKind.JsxElement - || kind === SyntaxKind.JsxExpression - || kind === SyntaxKind.JsxSelfClosingElement - || kind === SyntaxKind.JsxText; - } - - export function isJsxAttributeOrJsxSpreadAttribute(node: Node): node is JsxAttribute | JsxSpreadAttribute { - const kind = node.kind; - return kind === SyntaxKind.JsxAttribute - || kind === SyntaxKind.JsxSpreadAttribute; - } - - export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments { - return node.kind === SyntaxKind.ExpressionWithTypeArguments; - } - - export function isModuleBody(node: Node): node is ModuleBody { - const kind = node.kind; - return kind === SyntaxKind.ModuleBlock - || kind === SyntaxKind.ModuleDeclaration; - } - - export function isBindingPatternOrIdentifier(node: Node): node is (BindingPattern | Identifier) { - return isBindingPattern(node) - || isIdentifierNode(node); - } - // Returns false if this heritage clause element's expression contains something unsupported // (i.e. not a name or dotted name). export function isSupportedExpressionWithTypeArguments(node: ExpressionWithTypeArguments): boolean { @@ -2674,14 +2284,6 @@ namespace ts { return false; } - export function isModifiersArray(array: NodeArray): array is ModifiersArray { - return array.arrayKind === ArrayKind.ModifiersArray; - } - - export function isNodeArrayNode(node: Node): node is NodeArrayNode { - return node.kind === SyntaxKind.NodeArrayNode; - } - export function getLocalSymbolForExportDefault(symbol: Symbol) { return symbol && symbol.valueDeclaration && (symbol.valueDeclaration.flags & NodeFlags.Default) ? symbol.valueDeclaration.localSymbol : undefined; } @@ -2835,6 +2437,464 @@ namespace ts { } return carriageReturnLineFeed; } + + // Node tests + // + // All node tests in the following list should *not* reference parent pointers so that + // they may be used with transformations. + + export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression { + return node.kind === SyntaxKind.PropertyAccessExpression; + } + + export function isElementAccessExpression(node: Node): node is ElementAccessExpression { + return node.kind === SyntaxKind.ElementAccessExpression; + } + + function isBindingPatternKind(kind: SyntaxKind) { + return kind === SyntaxKind.ArrayBindingPattern + || kind === SyntaxKind.ObjectBindingPattern; + } + + export function isBindingPattern(node: Node): node is BindingPattern { + return node && isBindingPatternKind(node.kind); + } + + export function isClassElement(node: Node): node is ClassElement { + const kind = node.kind; + return kind === SyntaxKind.Constructor + || kind === SyntaxKind.PropertyDeclaration + || kind === SyntaxKind.MethodDeclaration + || kind === SyntaxKind.GetAccessor + || kind === SyntaxKind.SetAccessor + || kind === SyntaxKind.MethodSignature + || kind === SyntaxKind.IndexSignature; + } + + export function isQualifiedName(node: Node): node is QualifiedName { + return node.kind === SyntaxKind.QualifiedName; + } + + export function isLiteralExpression(node: Node): node is LiteralExpression { + return isLiteralKind(node.kind); + } + + function isEntityNameKind(kind: SyntaxKind) { + return kind === SyntaxKind.QualifiedName + || kind === SyntaxKind.Identifier; + } + + export function isEntityName(node: Node): node is EntityName { + return isEntityNameKind(node.kind); + } + + export function isIdentifier(node: Node): node is Identifier { + return node.kind === SyntaxKind.Identifier; + } + + export function isComputedPropertyName(node: Node): node is ComputedPropertyName { + return node.kind === SyntaxKind.ComputedPropertyName; + } + + export function isBinaryExpression(node: Node): node is BinaryExpression { + return node.kind === SyntaxKind.BinaryExpression; + } + + export function isShortHandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment { + return node.kind === SyntaxKind.ShorthandPropertyAssignment; + } + + function isLeftHandSideExpressionKind(kind: SyntaxKind) { + return kind === SyntaxKind.PropertyAccessExpression + || kind === SyntaxKind.ElementAccessExpression + || kind === SyntaxKind.NewExpression + || kind === SyntaxKind.CallExpression + || kind === SyntaxKind.JsxElement + || kind === SyntaxKind.JsxSelfClosingElement + || kind === SyntaxKind.TaggedTemplateExpression + || kind === SyntaxKind.ArrayLiteralExpression + || kind === SyntaxKind.ParenthesizedExpression + || kind === SyntaxKind.ObjectLiteralExpression + || kind === SyntaxKind.ClassExpression + || kind === SyntaxKind.FunctionExpression + || kind === SyntaxKind.Identifier + || kind === SyntaxKind.RegularExpressionLiteral + || kind === SyntaxKind.NumericLiteral + || kind === SyntaxKind.StringLiteral + || kind === SyntaxKind.NoSubstitutionTemplateLiteral + || kind === SyntaxKind.TemplateExpression + || kind === SyntaxKind.FalseKeyword + || kind === SyntaxKind.NullKeyword + || kind === SyntaxKind.ThisKeyword + || kind === SyntaxKind.TrueKeyword + || kind === SyntaxKind.SuperKeyword; + } + + export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression { + return isLeftHandSideExpressionKind(node.kind); + } + + function isUnaryExpressionKind(kind: SyntaxKind): boolean { + return kind === SyntaxKind.PrefixUnaryExpression + || kind === SyntaxKind.PostfixUnaryExpression + || kind === SyntaxKind.DeleteExpression + || kind === SyntaxKind.TypeOfExpression + || kind === SyntaxKind.VoidExpression + || kind === SyntaxKind.AwaitExpression + || kind === SyntaxKind.TypeAssertionExpression + || isLeftHandSideExpressionKind(kind); + } + + export function isUnaryExpression(node: Node): node is UnaryExpression { + return isUnaryExpressionKind(node.kind); + } + + function isExpressionKind(kind: SyntaxKind): boolean { + return kind === SyntaxKind.ConditionalExpression + || kind === SyntaxKind.YieldExpression + || kind === SyntaxKind.ArrowFunction + || kind === SyntaxKind.BinaryExpression + || kind === SyntaxKind.SpreadElementExpression + || kind === SyntaxKind.AsExpression + || kind === SyntaxKind.OmittedExpression + || isUnaryExpressionKind(kind); + } + + export function isExpression(node: Node): node is Expression { + return isExpressionKind(node.kind); + } + + export function isDecorator(node: Node): node is Decorator { + return node.kind === SyntaxKind.Decorator; + } + + export function isModifier(node: Node): node is Modifier { + return isModifierKind(node.kind); + } + + function isTypeNodeKind(kind: SyntaxKind) { + return (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode) + || kind === SyntaxKind.AnyKeyword + || kind === SyntaxKind.NumberKeyword + || kind === SyntaxKind.BooleanKeyword + || kind === SyntaxKind.StringKeyword + || kind === SyntaxKind.SymbolKeyword + || kind === SyntaxKind.VoidKeyword + || kind === SyntaxKind.ExpressionWithTypeArguments; + } + + /** + * Node test that determines whether a node is a valid type node. + * This differs from the `isPartOfTypeNode` function which determines whether a node is *part* + * of a TypeNode. + */ + export function isTypeNode(node: Node): node is TypeNode { + return isTypeNodeKind(node.kind); + } + + function isDeclarationKind(kind: SyntaxKind) { + return kind === SyntaxKind.ArrowFunction + || kind === SyntaxKind.BindingElement + || kind === SyntaxKind.ClassDeclaration + || kind === SyntaxKind.ClassExpression + || kind === SyntaxKind.Constructor + || kind === SyntaxKind.EnumDeclaration + || kind === SyntaxKind.EnumMember + || kind === SyntaxKind.ExportSpecifier + || kind === SyntaxKind.FunctionDeclaration + || kind === SyntaxKind.FunctionExpression + || kind === SyntaxKind.GetAccessor + || kind === SyntaxKind.ImportClause + || kind === SyntaxKind.ImportEqualsDeclaration + || kind === SyntaxKind.ImportSpecifier + || kind === SyntaxKind.InterfaceDeclaration + || kind === SyntaxKind.MethodDeclaration + || kind === SyntaxKind.MethodSignature + || kind === SyntaxKind.ModuleDeclaration + || kind === SyntaxKind.NamespaceImport + || kind === SyntaxKind.Parameter + || kind === SyntaxKind.PropertyAssignment + || kind === SyntaxKind.PropertyDeclaration + || kind === SyntaxKind.PropertySignature + || kind === SyntaxKind.SetAccessor + || kind === SyntaxKind.ShorthandPropertyAssignment + || kind === SyntaxKind.TypeAliasDeclaration + || kind === SyntaxKind.TypeParameter + || kind === SyntaxKind.VariableDeclaration; + } + + export function isDeclaration(node: Node): node is Declaration { + return isDeclarationKind(node.kind); + } + + function isDeclarationStatementKind(kind: SyntaxKind) { + return kind === SyntaxKind.FunctionDeclaration + || kind === SyntaxKind.MissingDeclaration + || kind === SyntaxKind.ClassDeclaration + || kind === SyntaxKind.InterfaceDeclaration + || kind === SyntaxKind.TypeAliasDeclaration + || kind === SyntaxKind.EnumDeclaration + || kind === SyntaxKind.ModuleDeclaration + || kind === SyntaxKind.ImportEqualsDeclaration + || kind === SyntaxKind.ExportDeclaration + || kind === SyntaxKind.ExportAssignment; + } + + export function isDeclarationStatement(node: Node): node is DeclarationStatement { + return isDeclarationStatementKind(node.kind); + } + + function isStatementKindButNotDeclarationKind(kind: SyntaxKind) { + return kind === SyntaxKind.BreakStatement + || kind === SyntaxKind.ContinueStatement + || kind === SyntaxKind.DebuggerStatement + || kind === SyntaxKind.DoStatement + || kind === SyntaxKind.ExpressionStatement + || kind === SyntaxKind.EmptyStatement + || kind === SyntaxKind.ForInStatement + || kind === SyntaxKind.ForOfStatement + || kind === SyntaxKind.ForStatement + || kind === SyntaxKind.IfStatement + || kind === SyntaxKind.LabeledStatement + || kind === SyntaxKind.ReturnStatement + || kind === SyntaxKind.SwitchStatement + || kind === SyntaxKind.ThrowStatement + || kind === SyntaxKind.TryStatement + || kind === SyntaxKind.VariableStatement + || kind === SyntaxKind.WhileStatement + || kind === SyntaxKind.WithStatement; + } + + /** + * Determines whether the node is a statement that is not also a declaration + */ + export function isStatementButNotDeclaration(node: Node): node is Statement { + return isStatementKindButNotDeclarationKind(node.kind); + } + + function isStatementKind(kind: SyntaxKind) { + return isStatementKindButNotDeclarationKind(kind) + || isDeclarationStatementKind(kind); + } + + export function isStatement(node: Node): node is Statement { + return isStatementKind(node.kind); + } + + function isPropertyNameKind(kind: SyntaxKind) { + return kind === SyntaxKind.Identifier + || kind === SyntaxKind.StringLiteral + || kind === SyntaxKind.NumericLiteral + || kind === SyntaxKind.ComputedPropertyName; + } + + export function isPropertyName(node: Node): node is PropertyName { + return isPropertyNameKind(node.kind); + } + + function isConciseBodyKind(kind: SyntaxKind) { + return kind === SyntaxKind.Block + || isExpressionKind(kind); + } + + export function isConciseBody(node: Node): node is ConciseBody { + return isConciseBodyKind(node.kind); + } + + export function isTypeParameter(node: Node): node is TypeParameterDeclaration { + return node.kind === SyntaxKind.TypeParameter; + } + + export function isParameter(node: Node): node is ParameterDeclaration { + return node.kind === SyntaxKind.Parameter; + } + + export function isBindingElement(node: Node): node is BindingElement { + return node.kind === SyntaxKind.BindingElement; + } + + function isObjectLiteralElementKind(kind: SyntaxKind) { + return kind === SyntaxKind.PropertyAssignment + || kind === SyntaxKind.ShorthandPropertyAssignment + || kind === SyntaxKind.MethodDeclaration + || kind === SyntaxKind.GetAccessor + || kind === SyntaxKind.SetAccessor + || kind === SyntaxKind.MissingDeclaration; + } + + export function isObjectLiteralElement(node: Node): node is ObjectLiteralElement { + return isObjectLiteralElementKind(node.kind); + } + + function isTemplateKind(kind: SyntaxKind) { + return kind === SyntaxKind.TemplateExpression + || kind === SyntaxKind.NoSubstitutionTemplateLiteral; + } + + export function isTemplate(node: Node): node is Template { + return isTemplateKind(node.kind); + } + + function isTemplateLiteralFragmentKind(kind: SyntaxKind) { + return kind === SyntaxKind.TemplateHead + || kind === SyntaxKind.TemplateMiddle + || kind === SyntaxKind.TemplateTail; + } + + export function isTemplateLiteralFragment(node: Node): node is TemplateLiteralFragment { + return isTemplateLiteralFragmentKind(node.kind); + } + + export function isTemplateSpan(node: Node): node is TemplateSpan { + return node.kind === SyntaxKind.TemplateSpan; + } + + export function isHeritageClause(node: Node): node is HeritageClause { + return node.kind === SyntaxKind.HeritageClause; + } + + export function isVariableDeclarationList(node: Node): node is VariableDeclarationList { + return node.kind === SyntaxKind.VariableDeclarationList; + } + + function isForInitializerKind(kind: SyntaxKind) { + return kind === SyntaxKind.VariableDeclarationList + || isExpressionKind(kind); + } + + export function isForInitializer(node: Node): node is ForInitializer { + return isForInitializerKind(node.kind); + } + + export function isCaseBlock(node: Node): node is CaseBlock { + return node.kind === SyntaxKind.CaseBlock; + } + + export function isBlock(node: Node): node is Block { + return node.kind === SyntaxKind.Block; + } + + export function isCatchClause(node: Node): node is CatchClause { + return node.kind === SyntaxKind.CatchClause; + } + + export function isVariableDeclaration(node: Node): node is VariableDeclaration { + return node.kind === SyntaxKind.VariableDeclaration; + } + + export function isEnumMember(node: Node): node is EnumMember { + return node.kind === SyntaxKind.EnumMember; + } + + function isModuleNameKind(kind: SyntaxKind) { + return kind === SyntaxKind.Identifier + || kind === SyntaxKind.StringLiteral; + } + + export function isModuleName(node: Node): node is ModuleName { + return isModuleNameKind(node.kind); + } + + function isCaseOrDefaultClauseKind(kind: SyntaxKind) { + return kind === SyntaxKind.CaseClause + || kind === SyntaxKind.DefaultClause; + } + + export function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause { + return isCaseOrDefaultClauseKind(node.kind); + } + + function isModuleReferenceKind(kind: SyntaxKind) { + return kind === SyntaxKind.ExternalModuleReference + || isEntityNameKind(kind); + } + + export function isModuleReference(node: Node): node is ModuleReference { + return isModuleReferenceKind(node.kind); + } + + export function isImportClause(node: Node): node is ImportClause { + return node.kind === SyntaxKind.ImportClause; + } + + function isNamedImportBindingsKind(kind: SyntaxKind) { + return kind === SyntaxKind.NamedImports + || kind === SyntaxKind.NamespaceImport; + } + + export function isNamedImportBindings(node: Node): node is NamedImportBindings { + return isNamedImportBindingsKind(node.kind); + } + + export function isImportSpecifier(node: Node): node is ImportSpecifier { + return node.kind === SyntaxKind.ImportSpecifier; + } + + export function isNamedExports(node: Node): node is NamedExports { + return node.kind === SyntaxKind.NamedExports; + } + + export function isExportSpecifier(node: Node): node is ExportSpecifier { + return node.kind === SyntaxKind.ExportSpecifier; + } + + export function isJsxOpeningElement(node: Node): node is JsxOpeningElement { + return node.kind === SyntaxKind.JsxOpeningElement; + } + + export function isJsxClosingElement(node: Node): node is JsxClosingElement { + return node.kind === SyntaxKind.JsxClosingElement; + } + + function isJsxChildKind(kind: SyntaxKind) { + return kind === SyntaxKind.JsxElement + || kind === SyntaxKind.JsxExpression + || kind === SyntaxKind.JsxSelfClosingElement + || kind === SyntaxKind.JsxText; + } + + export function isJsxChild(node: Node): node is JsxChild { + return isJsxChildKind(node.kind); + } + + function isJsxAttributeLikeKind(kind: SyntaxKind) { + return kind === SyntaxKind.JsxAttribute + || kind === SyntaxKind.JsxSpreadAttribute; + } + + export function isJsxAttributeLike(node: Node): node is JsxAttributeLike { + return isJsxAttributeLikeKind(node.kind); + } + + export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments { + return node.kind === SyntaxKind.ExpressionWithTypeArguments; + } + + function isModuleBodyKind(kind: SyntaxKind) { + return kind === SyntaxKind.ModuleBlock + || kind === SyntaxKind.ModuleDeclaration; + } + + export function isModuleBody(node: Node): node is ModuleBody { + return isModuleBodyKind(node.kind); + } + + function isBindingNameKind(kind: SyntaxKind) { + return kind === SyntaxKind.Identifier + || isBindingPatternKind(kind); + } + + export function isBindingName(node: Node): node is BindingName { + return isBindingNameKind(node.kind); + } + + export function isNodeArrayNode(node: Node): node is NodeArrayNode { + return node.kind === SyntaxKind.NodeArrayNode; + } + + export function isModifiersArray(array: NodeArray): array is ModifiersArray { + return array.arrayKind === ArrayKind.ModifiersArray; + } } namespace ts { diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index a75e79565c5..12829a540e5 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -15,6 +15,9 @@ namespace ts { * Describes an edge of a Node, used when traversing a syntax tree. */ interface NodeEdge { + /** The property name for the edge. */ + name: string; + /** Indicates that the result is optional. */ optional?: boolean; @@ -28,7 +31,7 @@ namespace ts { /** * Describes the shape of a Node. */ - type NodeTraversalPath = Map; + type NodeTraversalPath = NodeEdge[]; /** * This map contains information about the shape of each Node in "types.ts" pertaining to how @@ -44,399 +47,399 @@ namespace ts { * significantly impacted. */ const nodeEdgeTraversalMap: Map = { - [SyntaxKind.QualifiedName]: { - left: { test: isEntityName }, - right: { test: isIdentifierNode }, - }, - [SyntaxKind.ComputedPropertyName]: { - expression: { test: isExpressionNode }, - }, - [SyntaxKind.Parameter]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - name: { test: isBindingPatternOrIdentifier }, - type: { test: isTypeNodeNode, optional: true }, - initializer: { test: isExpressionNode, optional: true }, - }, - [SyntaxKind.Decorator]: { - expression: { test: isLeftHandSideExpression }, - }, - [SyntaxKind.PropertyDeclaration]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - name: { test: isPropertyName }, - type: { test: isTypeNodeNode, optional: true }, - initializer: { test: isExpressionNode, optional: true }, - }, - [SyntaxKind.MethodDeclaration]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - name: { test: isPropertyName }, - typeParameters: { test: isTypeParameter }, - parameters: { test: isParameter }, - type: { test: isTypeNodeNode, optional: true }, - body: { test: isBlock, optional: true }, - }, - [SyntaxKind.Constructor]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - typeParameters: { test: isTypeParameter }, - parameters: { test: isParameter }, - type: { test: isTypeNodeNode, optional: true }, - body: { test: isBlock, optional: true }, - }, - [SyntaxKind.GetAccessor]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - name: { test: isPropertyName }, - typeParameters: { test: isTypeParameter }, - parameters: { test: isParameter }, - type: { test: isTypeNodeNode, optional: true }, - body: { test: isBlock, optional: true }, - }, - [SyntaxKind.SetAccessor]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - name: { test: isPropertyName }, - typeParameters: { test: isTypeParameter }, - parameters: { test: isParameter }, - type: { test: isTypeNodeNode, optional: true }, - body: { test: isBlock, optional: true }, - }, - [SyntaxKind.ObjectBindingPattern]: { - elements: { test: isBindingElement }, - }, - [SyntaxKind.ArrayBindingPattern]: { - elements: { test: isBindingElement }, - }, - [SyntaxKind.BindingElement]: { - propertyName: { test: isPropertyName, optional: true }, - name: { test: isBindingPatternOrIdentifier }, - initializer: { test: isExpressionNode, optional: true }, - }, - [SyntaxKind.ArrayLiteralExpression]: { - elements: { test: isExpressionNode }, - }, - [SyntaxKind.ObjectLiteralExpression]: { - properties: { test: isObjectLiteralElement }, - }, - [SyntaxKind.PropertyAccessExpression]: { - expression: { test: isLeftHandSideExpression }, - name: { test: isIdentifierNode }, - }, - [SyntaxKind.ElementAccessExpression]: { - expression: { test: isLeftHandSideExpression }, - argumentExpression: { test: isExpressionNode }, - }, - [SyntaxKind.CallExpression]: { - expression: { test: isLeftHandSideExpression }, - typeArguments: { test: isTypeNodeNode }, - arguments: { test: isExpressionNode }, - }, - [SyntaxKind.NewExpression]: { - expression: { test: isLeftHandSideExpression }, - typeArguments: { test: isTypeNodeNode }, - arguments: { test: isExpressionNode }, - }, - [SyntaxKind.TaggedTemplateExpression]: { - tag: { test: isLeftHandSideExpression }, - template: { test: isTemplate }, - }, - [SyntaxKind.TypeAssertionExpression]: { - type: { test: isTypeNodeNode }, - expression: { test: isUnaryExpression }, - }, - [SyntaxKind.ParenthesizedExpression]: { - expression: { test: isExpressionNode }, - }, - [SyntaxKind.FunctionExpression]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - name: { test: isIdentifierNode, optional: true }, - typeParameters: { test: isTypeParameter }, - parameters: { test: isParameter }, - type: { test: isTypeNodeNode, optional: true }, - body: { test: isBlock, optional: true }, - }, - [SyntaxKind.ArrowFunction]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - typeParameters: { test: isTypeParameter }, - parameters: { test: isParameter }, - type: { test: isTypeNodeNode, optional: true }, - body: { test: isConciseBody, lift: liftToBlock }, - }, - [SyntaxKind.DeleteExpression]: { - expression: { test: isUnaryExpression }, - }, - [SyntaxKind.TypeOfExpression]: { - expression: { test: isUnaryExpression }, - }, - [SyntaxKind.VoidExpression]: { - expression: { test: isUnaryExpression }, - }, - [SyntaxKind.AwaitExpression]: { - expression: { test: isUnaryExpression }, - }, - [SyntaxKind.PrefixUnaryExpression]: { - operand: { test: isUnaryExpression }, - }, - [SyntaxKind.PostfixUnaryExpression]: { - operand: { test: isLeftHandSideExpression }, - }, - [SyntaxKind.BinaryExpression]: { - left: { test: isExpressionNode }, - right: { test: isExpressionNode }, - }, - [SyntaxKind.ConditionalExpression]: { - condition: { test: isExpressionNode }, - whenTrue: { test: isExpressionNode }, - whenFalse: { test: isExpressionNode }, - }, - [SyntaxKind.TemplateExpression]: { - head: { test: isTemplateLiteralFragment }, - templateSpans: { test: isTemplateSpan }, - }, - [SyntaxKind.YieldExpression]: { - expression: { test: isExpressionNode, optional: true }, - }, - [SyntaxKind.SpreadElementExpression]: { - expression: { test: isExpressionNode }, - }, - [SyntaxKind.ClassExpression]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - name: { test: isIdentifierNode, optional: true }, - typeParameters: { test: isTypeParameter }, - heritageClauses: { test: isHeritageClause }, - members: { test: isClassElement }, - }, - [SyntaxKind.ExpressionWithTypeArguments]: { - expression: { test: isLeftHandSideExpression }, - typeArguments: { test: isTypeNodeNode }, - }, - [SyntaxKind.AsExpression]: { - expression: { test: isExpressionNode }, - type: { test: isTypeNodeNode }, - }, - [SyntaxKind.TemplateSpan]: { - expression: { test: isExpressionNode }, - literal: { test: isTemplateLiteralFragment }, - }, - [SyntaxKind.Block]: { - statements: { test: isStatementNode }, - }, - [SyntaxKind.VariableStatement]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - declarationList: { test: isVariableDeclarationList }, - }, - [SyntaxKind.ExpressionStatement]: { - expression: { test: isExpressionNode }, - }, - [SyntaxKind.IfStatement]: { - expression: { test: isExpressionNode }, - thenStatement: { test: isStatementNode, lift: liftToBlock }, - elseStatement: { test: isStatementNode, lift: liftToBlock, optional: true}, - }, - [SyntaxKind.DoStatement]: { - statement: { test: isStatementNode, lift: liftToBlock }, - expression: { test: isExpressionNode }, - }, - [SyntaxKind.WhileStatement]: { - expression: { test: isExpressionNode }, - statement: { test: isStatementNode, lift: liftToBlock }, - }, - [SyntaxKind.ForStatement]: { - initializer: { test: isExpressionOrVariableDeclarationList, optional: true }, - condition: { test: isExpressionNode, optional: true }, - incrementor: { test: isExpressionNode, optional: true }, - statement: { test: isStatementNode, lift: liftToBlock }, - }, - [SyntaxKind.ForInStatement]: { - initializer: { test: isExpressionOrVariableDeclarationList }, - expression: { test: isExpressionNode }, - statement: { test: isStatementNode, lift: liftToBlock }, - }, - [SyntaxKind.ForOfStatement]: { - initializer: { test: isExpressionOrVariableDeclarationList }, - expression: { test: isExpressionNode }, - statement: { test: isStatementNode, lift: liftToBlock }, - }, - [SyntaxKind.ContinueStatement]: { - label: { test: isIdentifierNode, optional: true }, - }, - [SyntaxKind.BreakStatement]: { - label: { test: isIdentifierNode, optional: true }, - }, - [SyntaxKind.ReturnStatement]: { - expression: { test: isExpressionNode, optional: true }, - }, - [SyntaxKind.WithStatement]: { - expression: { test: isExpressionNode }, - statement: { test: isStatementNode, lift: liftToBlock }, - }, - [SyntaxKind.SwitchStatement]: { - expression: { test: isExpressionNode }, - caseBlock: { test: isCaseBlock }, - }, - [SyntaxKind.LabeledStatement]: { - label: { test: isIdentifierNode }, - statement: { test: isStatementNode, lift: liftToBlock }, - }, - [SyntaxKind.ThrowStatement]: { - expression: { test: isExpressionNode }, - }, - [SyntaxKind.TryStatement]: { - tryBlock: { test: isBlock }, - catchClause: { test: isCatchClause, optional: true }, - finallyBlock: { test: isBlock, optional: true }, - }, - [SyntaxKind.VariableDeclaration]: { - name: { test: isBindingPatternOrIdentifier }, - type: { test: isTypeNodeNode, optional: true }, - initializer: { test: isExpressionNode, optional: true }, - }, - [SyntaxKind.VariableDeclarationList]: { - declarations: { test: isVariableDeclaration }, - }, - [SyntaxKind.FunctionDeclaration]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - name: { test: isIdentifierNode, optional: true }, - typeParameters: { test: isTypeParameter }, - parameters: { test: isParameter }, - type: { test: isTypeNodeNode, optional: true }, - body: { test: isBlock, optional: true }, - }, - [SyntaxKind.ClassDeclaration]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - name: { test: isIdentifierNode, optional: true }, - typeParameters: { test: isTypeParameter }, - heritageClauses: { test: isHeritageClause }, - members: { test: isClassElement }, - }, - [SyntaxKind.EnumDeclaration]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - name: { test: isIdentifierNode }, - members: { test: isEnumMember }, - }, - [SyntaxKind.ModuleDeclaration]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - name: { test: isModuleName }, - body: { test: isModuleBody }, - }, - [SyntaxKind.ModuleBlock]: { - statements: { test: isStatementNode }, - }, - [SyntaxKind.CaseBlock]: { - clauses: { test: isCaseOrDefaultClause }, - }, - [SyntaxKind.ImportEqualsDeclaration]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - name: { test: isIdentifierNode }, - moduleReference: { test: isModuleReference }, - }, - [SyntaxKind.ImportDeclaration]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - importClause: { test: isImportClause, optional: true }, - moduleSpecifier: { test: isExpressionNode }, - }, - [SyntaxKind.ImportClause]: { - name: { test: isIdentifierNode, optional: true }, - namedBindings: { test: isNamedImportsOrNamespaceImport, optional: true }, - }, - [SyntaxKind.NamespaceImport]: { - name: { test: isIdentifierNode }, - }, - [SyntaxKind.NamedImports]: { - elements: { test: isImportSpecifier }, - }, - [SyntaxKind.ImportSpecifier]: { - propertyName: { test: isIdentifierNode, optional: true }, - name: { test: isIdentifierNode }, - }, - [SyntaxKind.ExportAssignment]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - expression: { test: isExpressionNode }, - }, - [SyntaxKind.ExportDeclaration]: { - decorators: { test: isDecorator }, - modifiers: { test: isModifier }, - exportClause: { test: isNamedExports, optional: true }, - moduleSpecifier: { test: isExpressionNode, optional: true }, - }, - [SyntaxKind.NamedExports]: { - elements: { test: isExportSpecifier }, - }, - [SyntaxKind.ExportSpecifier]: { - propertyName: { test: isIdentifierNode, optional: true }, - name: { test: isIdentifierNode }, - }, - [SyntaxKind.ExternalModuleReference]: { - expression: { test: isExpressionNode, optional: true }, - }, - [SyntaxKind.JsxElement]: { - openingElement: { test: isJsxOpeningElement }, - children: { test: isJsxChild }, - closingElement: { test: isJsxClosingElement }, - }, - [SyntaxKind.JsxSelfClosingElement]: { - tagName: { test: isEntityName }, - attributes: { test: isJsxAttributeOrJsxSpreadAttribute }, - }, - [SyntaxKind.JsxOpeningElement]: { - tagName: { test: isEntityName }, - attributes: { test: isJsxAttributeOrJsxSpreadAttribute }, - }, - [SyntaxKind.JsxClosingElement]: { - tagName: { test: isEntityName }, - }, - [SyntaxKind.JsxAttribute]: { - name: { test: isIdentifierNode }, - initializer: { test: isExpressionNode, optional: true }, - }, - [SyntaxKind.JsxSpreadAttribute]: { - expression: { test: isExpressionNode }, - }, - [SyntaxKind.JsxExpression]: { - expression: { test: isExpressionNode, optional: true }, - }, - [SyntaxKind.CaseClause]: { - expression: { test: isExpressionNode }, - statements: { test: isStatementNode }, - }, - [SyntaxKind.DefaultClause]: { - statements: { test: isStatementNode }, - }, - [SyntaxKind.HeritageClause]: { - types: { test: isExpressionWithTypeArguments }, - }, - [SyntaxKind.CatchClause]: { - variableDeclaration: { test: isVariableDeclaration }, - block: { test: isBlock }, - }, - [SyntaxKind.PropertyAssignment]: { - name: { test: isPropertyName }, - initializer: { test: isExpressionNode }, - }, - [SyntaxKind.ShorthandPropertyAssignment]: { - name: { test: isIdentifierNode }, - objectAssignmentInitializer: { test: isExpressionNode, optional: true }, - }, - [SyntaxKind.EnumMember]: { - name: { test: isPropertyName }, - initializer: { test: isExpressionNode, optional: true }, - }, - [SyntaxKind.SourceFile]: { - statements: { test: isStatementNode }, - }, + [SyntaxKind.QualifiedName]: [ + { name: "left", test: isEntityName }, + { name: "right", test: isIdentifier }, + ], + [SyntaxKind.ComputedPropertyName]: [ + { name: "expression", test: isExpression }, + ], + [SyntaxKind.Parameter]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "name", test: isBindingName }, + { name: "type", test: isTypeNode, optional: true }, + { name: "initializer", test: isExpression, optional: true }, + ], + [SyntaxKind.Decorator]: [ + { name: "expression", test: isLeftHandSideExpression }, + ], + [SyntaxKind.PropertyDeclaration]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "name", test: isPropertyName }, + { name: "type", test: isTypeNode, optional: true }, + { name: "initializer", test: isExpression, optional: true }, + ], + [SyntaxKind.MethodDeclaration]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "name", test: isPropertyName }, + { name: "typeParameters", test: isTypeParameter }, + { name: "parameters", test: isParameter }, + { name: "type", test: isTypeNode, optional: true }, + { name: "body", test: isBlock, optional: true }, + ], + [SyntaxKind.Constructor]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "typeParameters", test: isTypeParameter }, + { name: "parameters", test: isParameter }, + { name: "type", test: isTypeNode, optional: true }, + { name: "body", test: isBlock, optional: true }, + ], + [SyntaxKind.GetAccessor]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "name", test: isPropertyName }, + { name: "typeParameters", test: isTypeParameter }, + { name: "parameters", test: isParameter }, + { name: "type", test: isTypeNode, optional: true }, + { name: "body", test: isBlock, optional: true }, + ], + [SyntaxKind.SetAccessor]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "name", test: isPropertyName }, + { name: "typeParameters", test: isTypeParameter }, + { name: "parameters", test: isParameter }, + { name: "type", test: isTypeNode, optional: true }, + { name: "body", test: isBlock, optional: true }, + ], + [SyntaxKind.ObjectBindingPattern]: [ + { name: "elements", test: isBindingElement }, + ], + [SyntaxKind.ArrayBindingPattern]: [ + { name: "elements", test: isBindingElement }, + ], + [SyntaxKind.BindingElement]: [ + { name: "propertyName", test: isPropertyName, optional: true }, + { name: "name", test: isBindingName }, + { name: "initializer", test: isExpression, optional: true }, + ], + [SyntaxKind.ArrayLiteralExpression]: [ + { name: "elements", test: isExpression }, + ], + [SyntaxKind.ObjectLiteralExpression]: [ + { name: "properties", test: isObjectLiteralElement }, + ], + [SyntaxKind.PropertyAccessExpression]: [ + { name: "expression", test: isLeftHandSideExpression }, + { name: "name", test: isIdentifier }, + ], + [SyntaxKind.ElementAccessExpression]: [ + { name: "expression", test: isLeftHandSideExpression }, + { name: "argumentExpression", test: isExpression }, + ], + [SyntaxKind.CallExpression]: [ + { name: "expression", test: isLeftHandSideExpression }, + { name: "typeArguments", test: isTypeNode }, + { name: "arguments", test: isExpression }, + ], + [SyntaxKind.NewExpression]: [ + { name: "expression", test: isLeftHandSideExpression }, + { name: "typeArguments", test: isTypeNode }, + { name: "arguments", test: isExpression }, + ], + [SyntaxKind.TaggedTemplateExpression]: [ + { name: "tag", test: isLeftHandSideExpression }, + { name: "template", test: isTemplate }, + ], + [SyntaxKind.TypeAssertionExpression]: [ + { name: "type", test: isTypeNode }, + { name: "expression", test: isUnaryExpression }, + ], + [SyntaxKind.ParenthesizedExpression]: [ + { name: "expression", test: isExpression }, + ], + [SyntaxKind.FunctionExpression]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "name", test: isIdentifier, optional: true }, + { name: "typeParameters", test: isTypeParameter }, + { name: "parameters", test: isParameter }, + { name: "type", test: isTypeNode, optional: true }, + { name: "body", test: isBlock, optional: true }, + ], + [SyntaxKind.ArrowFunction]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "typeParameters", test: isTypeParameter }, + { name: "parameters", test: isParameter }, + { name: "type", test: isTypeNode, optional: true }, + { name: "body", test: isConciseBody, lift: liftToBlock }, + ], + [SyntaxKind.DeleteExpression]: [ + { name: "expression", test: isUnaryExpression }, + ], + [SyntaxKind.TypeOfExpression]: [ + { name: "expression", test: isUnaryExpression }, + ], + [SyntaxKind.VoidExpression]: [ + { name: "expression", test: isUnaryExpression }, + ], + [SyntaxKind.AwaitExpression]: [ + { name: "expression", test: isUnaryExpression }, + ], + [SyntaxKind.PrefixUnaryExpression]: [ + { name: "operand", test: isUnaryExpression }, + ], + [SyntaxKind.PostfixUnaryExpression]: [ + { name: "operand", test: isLeftHandSideExpression }, + ], + [SyntaxKind.BinaryExpression]: [ + { name: "left", test: isExpression }, + { name: "right", test: isExpression }, + ], + [SyntaxKind.ConditionalExpression]: [ + { name: "condition", test: isExpression }, + { name: "whenTrue", test: isExpression }, + { name: "whenFalse", test: isExpression }, + ], + [SyntaxKind.TemplateExpression]: [ + { name: "head", test: isTemplateLiteralFragment }, + { name: "templateSpans", test: isTemplateSpan }, + ], + [SyntaxKind.YieldExpression]: [ + { name: "expression", test: isExpression, optional: true }, + ], + [SyntaxKind.SpreadElementExpression]: [ + { name: "expression", test: isExpression }, + ], + [SyntaxKind.ClassExpression]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "name", test: isIdentifier, optional: true }, + { name: "typeParameters", test: isTypeParameter }, + { name: "heritageClauses", test: isHeritageClause }, + { name: "members", test: isClassElement }, + ], + [SyntaxKind.ExpressionWithTypeArguments]: [ + { name: "expression", test: isLeftHandSideExpression }, + { name: "typeArguments", test: isTypeNode }, + ], + [SyntaxKind.AsExpression]: [ + { name: "expression", test: isExpression }, + { name: "type", test: isTypeNode }, + ], + [SyntaxKind.TemplateSpan]: [ + { name: "expression", test: isExpression }, + { name: "literal", test: isTemplateLiteralFragment }, + ], + [SyntaxKind.Block]: [ + { name: "statements", test: isStatement }, + ], + [SyntaxKind.VariableStatement]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "declarationList", test: isVariableDeclarationList }, + ], + [SyntaxKind.ExpressionStatement]: [ + { name: "expression", test: isExpression }, + ], + [SyntaxKind.IfStatement]: [ + { name: "expression", test: isExpression }, + { name: "thenStatement", test: isStatement, lift: liftToBlock }, + { name: "elseStatement", test: isStatement, lift: liftToBlock, optional: true }, + ], + [SyntaxKind.DoStatement]: [ + { name: "statement", test: isStatement, lift: liftToBlock }, + { name: "expression", test: isExpression }, + ], + [SyntaxKind.WhileStatement]: [ + { name: "expression", test: isExpression }, + { name: "statement", test: isStatement, lift: liftToBlock }, + ], + [SyntaxKind.ForStatement]: [ + { name: "initializer", test: isForInitializer, optional: true }, + { name: "condition", test: isExpression, optional: true }, + { name: "incrementor", test: isExpression, optional: true }, + { name: "statement", test: isStatement, lift: liftToBlock }, + ], + [SyntaxKind.ForInStatement]: [ + { name: "initializer", test: isForInitializer }, + { name: "expression", test: isExpression }, + { name: "statement", test: isStatement, lift: liftToBlock }, + ], + [SyntaxKind.ForOfStatement]: [ + { name: "initializer", test: isForInitializer }, + { name: "expression", test: isExpression }, + { name: "statement", test: isStatement, lift: liftToBlock }, + ], + [SyntaxKind.ContinueStatement]: [ + { name: "label", test: isIdentifier, optional: true }, + ], + [SyntaxKind.BreakStatement]: [ + { name: "label", test: isIdentifier, optional: true }, + ], + [SyntaxKind.ReturnStatement]: [ + { name: "expression", test: isExpression, optional: true }, + ], + [SyntaxKind.WithStatement]: [ + { name: "expression", test: isExpression }, + { name: "statement", test: isStatement, lift: liftToBlock }, + ], + [SyntaxKind.SwitchStatement]: [ + { name: "expression", test: isExpression }, + { name: "caseBlock", test: isCaseBlock }, + ], + [SyntaxKind.LabeledStatement]: [ + { name: "label", test: isIdentifier }, + { name: "statement", test: isStatement, lift: liftToBlock }, + ], + [SyntaxKind.ThrowStatement]: [ + { name: "expression", test: isExpression }, + ], + [SyntaxKind.TryStatement]: [ + { name: "tryBlock", test: isBlock }, + { name: "catchClause", test: isCatchClause, optional: true }, + { name: "finallyBlock", test: isBlock, optional: true }, + ], + [SyntaxKind.VariableDeclaration]: [ + { name: "name", test: isBindingName }, + { name: "type", test: isTypeNode, optional: true }, + { name: "initializer", test: isExpression, optional: true }, + ], + [SyntaxKind.VariableDeclarationList]: [ + { name: "declarations", test: isVariableDeclaration }, + ], + [SyntaxKind.FunctionDeclaration]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "name", test: isIdentifier, optional: true }, + { name: "typeParameters", test: isTypeParameter }, + { name: "parameters", test: isParameter }, + { name: "type", test: isTypeNode, optional: true }, + { name: "body", test: isBlock, optional: true }, + ], + [SyntaxKind.ClassDeclaration]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "name", test: isIdentifier, optional: true }, + { name: "typeParameters", test: isTypeParameter }, + { name: "heritageClauses", test: isHeritageClause }, + { name: "members", test: isClassElement }, + ], + [SyntaxKind.EnumDeclaration]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "name", test: isIdentifier }, + { name: "members", test: isEnumMember }, + ], + [SyntaxKind.ModuleDeclaration]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "name", test: isModuleName }, + { name: "body", test: isModuleBody }, + ], + [SyntaxKind.ModuleBlock]: [ + { name: "statements", test: isStatement }, + ], + [SyntaxKind.CaseBlock]: [ + { name: "clauses", test: isCaseOrDefaultClause }, + ], + [SyntaxKind.ImportEqualsDeclaration]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "name", test: isIdentifier }, + { name: "moduleReference", test: isModuleReference }, + ], + [SyntaxKind.ImportDeclaration]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "importClause", test: isImportClause, optional: true }, + { name: "moduleSpecifier", test: isExpression }, + ], + [SyntaxKind.ImportClause]: [ + { name: "name", test: isIdentifier, optional: true }, + { name: "namedBindings", test: isNamedImportBindings, optional: true }, + ], + [SyntaxKind.NamespaceImport]: [ + { name: "name", test: isIdentifier }, + ], + [SyntaxKind.NamedImports]: [ + { name: "elements", test: isImportSpecifier }, + ], + [SyntaxKind.ImportSpecifier]: [ + { name: "propertyName", test: isIdentifier, optional: true }, + { name: "name", test: isIdentifier }, + ], + [SyntaxKind.ExportAssignment]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "expression", test: isExpression }, + ], + [SyntaxKind.ExportDeclaration]: [ + { name: "decorators", test: isDecorator }, + { name: "modifiers", test: isModifier }, + { name: "exportClause", test: isNamedExports, optional: true }, + { name: "moduleSpecifier", test: isExpression, optional: true }, + ], + [SyntaxKind.NamedExports]: [ + { name: "elements", test: isExportSpecifier }, + ], + [SyntaxKind.ExportSpecifier]: [ + { name: "propertyName", test: isIdentifier, optional: true }, + { name: "name", test: isIdentifier }, + ], + [SyntaxKind.ExternalModuleReference]: [ + { name: "expression", test: isExpression, optional: true }, + ], + [SyntaxKind.JsxElement]: [ + { name: "openingElement", test: isJsxOpeningElement }, + { name: "children", test: isJsxChild }, + { name: "closingElement", test: isJsxClosingElement }, + ], + [SyntaxKind.JsxSelfClosingElement]: [ + { name: "tagName", test: isEntityName }, + { name: "attributes", test: isJsxAttributeLike }, + ], + [SyntaxKind.JsxOpeningElement]: [ + { name: "tagName", test: isEntityName }, + { name: "attributes", test: isJsxAttributeLike }, + ], + [SyntaxKind.JsxClosingElement]: [ + { name: "tagName", test: isEntityName }, + ], + [SyntaxKind.JsxAttribute]: [ + { name: "name", test: isIdentifier }, + { name: "initializer", test: isExpression, optional: true }, + ], + [SyntaxKind.JsxSpreadAttribute]: [ + { name: "expression", test: isExpression }, + ], + [SyntaxKind.JsxExpression]: [ + { name: "expression", test: isExpression, optional: true }, + ], + [SyntaxKind.CaseClause]: [ + { name: "expression", test: isExpression }, + { name: "statements", test: isStatement }, + ], + [SyntaxKind.DefaultClause]: [ + { name: "statements", test: isStatement }, + ], + [SyntaxKind.HeritageClause]: [ + { name: "types", test: isExpressionWithTypeArguments }, + ], + [SyntaxKind.CatchClause]: [ + { name: "variableDeclaration", test: isVariableDeclaration }, + { name: "block", test: isBlock }, + ], + [SyntaxKind.PropertyAssignment]: [ + { name: "name", test: isPropertyName }, + { name: "initializer", test: isExpression }, + ], + [SyntaxKind.ShorthandPropertyAssignment]: [ + { name: "name", test: isIdentifier }, + { name: "objectAssignmentInitializer", test: isExpression, optional: true }, + ], + [SyntaxKind.EnumMember]: [ + { name: "name", test: isPropertyName }, + { name: "initializer", test: isExpression, optional: true }, + ], + [SyntaxKind.SourceFile]: [ + { name: "statements", test: isStatement }, + ], }; /** @@ -456,8 +459,8 @@ namespace ts { let result = initial; const edgeTraversalPath = nodeEdgeTraversalMap[node.kind]; if (edgeTraversalPath) { - for (const propertyName in edgeTraversalPath) { - const value = (>node)[propertyName]; + for (const edge of edgeTraversalPath) { + const value = (>node)[edge.name]; if (value !== undefined) { result = isArray(value) ? reduceLeft(>value, f, result) @@ -568,24 +571,24 @@ namespace ts { environment.startLexicalEnvironment(); } + let modifiers: NodeFlags; let updated: T & Map; const edgeTraversalPath = nodeEdgeTraversalMap[node.kind]; if (edgeTraversalPath) { - for (const propertyName in edgeTraversalPath) { - const value = (>node)[propertyName]; + for (const edge of edgeTraversalPath) { + const value = (>node)[edge.name]; if (value !== undefined) { - const edge = edgeTraversalPath[propertyName]; const visited = visitEdge(edge, value, visitor); if (updated !== undefined || visited !== value) { if (updated === undefined) { updated = cloneNode(node, /*location*/ undefined, node.flags & ~NodeFlags.Modifier, /*parent*/ undefined, /*original*/ node); } - updated[propertyName] = visited; + updated[edge.name] = visited; } if (visited && isArray(visited) && isModifiersArray(visited)) { - updated.flags |= visited.flags; + modifiers = visited.flags; } } } @@ -594,6 +597,9 @@ namespace ts { if (updated === undefined) { updated = node; } + else if (modifiers) { + updated.flags |= modifiers; + } if (isNewLexicalEnvironment) { const declarations = environment.endLexicalEnvironment(); @@ -740,7 +746,7 @@ namespace ts { * @param nodes The NodeArray. */ function liftToBlock(nodes: NodeArray) { - Debug.assert(trueForAll(nodes, isStatementNode), "Cannot lift nodes to a Block."); + Debug.assert(trueForAll(nodes, isStatement), "Cannot lift nodes to a Block."); return createBlock(>nodes); } diff --git a/src/harness/typeWriter.ts b/src/harness/typeWriter.ts index e332dab648e..145e81f30a8 100644 --- a/src/harness/typeWriter.ts +++ b/src/harness/typeWriter.ts @@ -29,7 +29,7 @@ class TypeWriterWalker { } private visitNode(node: ts.Node): void { - if (ts.isExpression(node) || node.kind === ts.SyntaxKind.Identifier) { + if (ts.isPartOfExpression(node) || node.kind === ts.SyntaxKind.Identifier) { this.logTypeAndSymbol(node); } diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index 1c4d5957a02..6f20093c7da 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -296,7 +296,7 @@ namespace ts.BreakpointResolver { } } - if (isExpression(node)) { + if (isPartOfExpression(node)) { switch (node.parent.kind) { case SyntaxKind.DoStatement: // Set span as if on while keyword diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 2df78df01dc..4bc0ad70ad3 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -313,7 +313,7 @@ namespace ts.formatting { this.SpaceAfterVoidOperator = new Rule(RuleDescriptor.create3(SyntaxKind.VoidKeyword, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsVoidOpContext), RuleAction.Space)); this.NoSpaceBetweenReturnAndSemicolon = new Rule(RuleDescriptor.create1(SyntaxKind.ReturnKeyword, SyntaxKind.SemicolonToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); - + // Add a space between statements. All keywords except (do,else,case) has open/close parens after them. // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any] this.SpaceBetweenStatements = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.DoKeyword, SyntaxKind.ElseKeyword, SyntaxKind.CaseKeyword]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotForContext), RuleAction.Space)); @@ -554,17 +554,17 @@ namespace ts.formatting { static IsSameLineTokenOrBeforeMultilineBlockContext(context: FormattingContext): boolean { //// This check is mainly used inside SpaceBeforeOpenBraceInControl and SpaceBeforeOpenBraceInFunction. //// - //// Ex: + //// Ex: //// if (1) { .... //// * ) and { are on the same line so apply the rule. Here we don't care whether it's same or multi block context //// - //// Ex: + //// Ex: //// if (1) //// { ... } //// * ) and { are on differnet lines. We only need to format if the block is multiline context. So in this case we don't format. //// //// Ex: - //// if (1) + //// if (1) //// { ... //// } //// * ) and { are on differnet lines. We only need to format if the block is multiline context. So in this case we format. @@ -735,7 +735,7 @@ namespace ts.formatting { } static NodeIsInDecoratorContext(node: Node): boolean { - while (isExpression(node)) { + while (isPartOfExpression(node)) { node = node.parent; } return node.kind === SyntaxKind.Decorator; diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 8e0fef884e7..248d81cb072 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -467,7 +467,7 @@ namespace ts.formatting { } return false; } - + /* @internal */ export function nodeWillIndentChild(parent: TextRangeWithKind, child: TextRangeWithKind, indentByDefault: boolean) { let childKind = child ? child.kind : SyntaxKind.Unknown; @@ -497,7 +497,7 @@ namespace ts.formatting { Function returns true when the parent node should indent the given child by an explicit rule */ export function shouldIndentChildNode(parent: TextRangeWithKind, child?: TextRangeWithKind): boolean { - return nodeContentIsAlwaysIndented(parent.kind) || nodeWillIndentChild(parent, child, false); + return nodeContentIsAlwaysIndented(parent.kind) || nodeWillIndentChild(parent, child, false); } } } diff --git a/src/services/services.ts b/src/services/services.ts index 373d0c3a8ff..24e20ed070a 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2986,7 +2986,7 @@ namespace ts { // e.g "b a" is valid quoted name but when we strip off the quotes, it is invalid. // We, thus, need to check if whatever was inside the quotes is actually a valid identifier name. if (performCharacterChecks) { - if (!isIdentifier(name, target)) { + if (!isIdentifierText(name, target)) { return undefined; } } @@ -6342,7 +6342,7 @@ namespace ts { return node.parent.kind === SyntaxKind.TypeReference || (node.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isExpressionWithTypeArgumentsInClassExtendsClause(node.parent)) || - (node.kind === SyntaxKind.ThisKeyword && !isExpression(node)) || + (node.kind === SyntaxKind.ThisKeyword && !isPartOfExpression(node)) || node.kind === SyntaxKind.ThisType; }