Skip to content

Commit

Permalink
feat: add AssertClause and AssertEntry (#1224)
Browse files Browse the repository at this point in the history
  • Loading branch information
dsherret authored Nov 20, 2021
1 parent e93c96e commit bcf694f
Show file tree
Hide file tree
Showing 36 changed files with 1,086 additions and 473 deletions.
363 changes: 208 additions & 155 deletions deno/ts_morph.d.ts

Large diffs are not rendered by default.

281 changes: 210 additions & 71 deletions deno/ts_morph.js

Large diffs are not rendered by default.

363 changes: 208 additions & 155 deletions packages/ts-morph/lib/ts-morph.d.ts

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions packages/ts-morph/src/compiler/ast/aliases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ import { VariableDeclaration } from "./variable";

type WrappedToCompilerNodeType<T extends Node> = T["compilerNode"];

export type AssertionKey = Identifier | StringLiteral;
type _AssertionKeyTest = AssertTrue<IsExact<WrappedToCompilerNodeType<AssertionKey>, ts.AssertionKey>>;

export type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateIdentifier;
type _PropertyNameTest = AssertTrue<IsExact<WrappedToCompilerNodeType<PropertyName>, ts.PropertyName>>;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ts } from "@ts-morph/common";
import { Constructor } from "../../../../types";
import { AssertionKey } from "../../aliases";
import { NamedNodeBase, NamedNodeBaseExtensionType, NamedNodeSpecificBase } from "./NamedNodeBase";
import { ReferenceFindableNode } from "./ReferenceFindableNode";
import { RenameableNode } from "./RenameableNode";

export type AssertionKeyNamedNodeExtensionType = NamedNodeBaseExtensionType<ts.AssertionKey>;

export interface AssertionKeyNamedNode extends AssertionKeyNamedNodeSpecific, ReferenceFindableNode, RenameableNode {
}

export type AssertionKeyNamedNodeSpecific = NamedNodeSpecificBase<AssertionKey>;

export function AssertionKeyNamedNode<T extends Constructor<AssertionKeyNamedNodeExtensionType>>(Base: T): Constructor<AssertionKeyNamedNode> & T {
const base = ReferenceFindableNode(RenameableNode(Base));
return NamedNodeBase<ts.AssertionKey, typeof base>(base);
}
1 change: 1 addition & 0 deletions packages/ts-morph/src/compiler/ast/base/name/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./AssertionKeyNamedNode";
export * from "./BindingNamedNode";
export * from "./ModuleNamedNode";
export * from "./NameableNode";
Expand Down
105 changes: 33 additions & 72 deletions packages/ts-morph/src/compiler/ast/common/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2245,6 +2245,18 @@ export class Node<NodeType extends ts.Node = ts.Node> {
static readonly isArrowFunction: (node: compiler.Node | undefined) => node is compiler.ArrowFunction = Node.is(SyntaxKind.ArrowFunction);
/** Gets if the node is an AsExpression. */
static readonly isAsExpression: (node: compiler.Node | undefined) => node is compiler.AsExpression = Node.is(SyntaxKind.AsExpression);
/** Gets if the node is an AssertClause. */
static readonly isAssertClause: (node: compiler.Node | undefined) => node is compiler.AssertClause = Node.is(SyntaxKind.AssertClause);
/** Gets if the node is an AssertEntry. */
static readonly isAssertEntry: (node: compiler.Node | undefined) => node is compiler.AssertEntry = Node.is(SyntaxKind.AssertEntry);

/**
* Gets if the node is an AssertionKeyNamedNode.
* @param node - Node to check.
*/
static isAssertionKeyNamedNode<T extends compiler.Node>(node: T | undefined): node is compiler.AssertionKeyNamedNode & compiler.AssertionKeyNamedNodeExtensionType & T {
return node?.getKind() === SyntaxKind.AssertEntry;
}

/**
* Gets if the node is an AsyncableNode.
Expand Down Expand Up @@ -2987,14 +2999,8 @@ export class Node<NodeType extends ts.Node = ts.Node> {
}
}

/**
* Gets if the node is a JSDocAllType.
* @param node - Node to check.
*/
static isJSDocAllType(node: compiler.Node | undefined): node is compiler.JSDocAllType {
return node?.getKind() === SyntaxKind.JSDocAllType;
}

/** Gets if the node is a JSDocAllType. */
static readonly isJSDocAllType: (node: compiler.Node | undefined) => node is compiler.JSDocAllType = Node.is(SyntaxKind.JSDocAllType);
/** Gets if the node is a JSDocAugmentsTag. */
static readonly isJSDocAugmentsTag: (node: compiler.Node | undefined) => node is compiler.JSDocAugmentsTag = Node.is(SyntaxKind.JSDocAugmentsTag);
/** Gets if the node is a JSDocAuthorTag. */
Expand All @@ -3019,47 +3025,16 @@ export class Node<NodeType extends ts.Node = ts.Node> {
static readonly isJSDocLinkPlain: (node: compiler.Node | undefined) => node is compiler.JSDocLinkPlain = Node.is(SyntaxKind.JSDocLinkPlain);
/** Gets if the node is a JSDocMemberName. */
static readonly isJSDocMemberName: (node: compiler.Node | undefined) => node is compiler.JSDocMemberName = Node.is(SyntaxKind.JSDocMemberName);

/**
* Gets if the node is a JSDocNamepathType.
* @param node - Node to check.
*/
static isJSDocNamepathType(node: compiler.Node | undefined): node is compiler.JSDocNamepathType {
return node?.getKind() === SyntaxKind.JSDocNamepathType;
}

/**
* Gets if the node is a JSDocNameReference.
* @param node - Node to check.
*/
static isJSDocNameReference(node: compiler.Node | undefined): node is compiler.JSDocNameReference {
return node?.getKind() === SyntaxKind.JSDocNameReference;
}

/**
* Gets if the node is a JSDocNonNullableType.
* @param node - Node to check.
*/
static isJSDocNonNullableType(node: compiler.Node | undefined): node is compiler.JSDocNonNullableType {
return node?.getKind() === SyntaxKind.JSDocNonNullableType;
}

/**
* Gets if the node is a JSDocNullableType.
* @param node - Node to check.
*/
static isJSDocNullableType(node: compiler.Node | undefined): node is compiler.JSDocNullableType {
return node?.getKind() === SyntaxKind.JSDocNullableType;
}

/**
* Gets if the node is a JSDocOptionalType.
* @param node - Node to check.
*/
static isJSDocOptionalType(node: compiler.Node | undefined): node is compiler.JSDocOptionalType {
return node?.getKind() === SyntaxKind.JSDocOptionalType;
}

/** Gets if the node is a JSDocNamepathType. */
static readonly isJSDocNamepathType: (node: compiler.Node | undefined) => node is compiler.JSDocNamepathType = Node.is(SyntaxKind.JSDocNamepathType);
/** Gets if the node is a JSDocNameReference. */
static readonly isJSDocNameReference: (node: compiler.Node | undefined) => node is compiler.JSDocNameReference = Node.is(SyntaxKind.JSDocNameReference);
/** Gets if the node is a JSDocNonNullableType. */
static readonly isJSDocNonNullableType: (node: compiler.Node | undefined) => node is compiler.JSDocNonNullableType = Node.is(SyntaxKind.JSDocNonNullableType);
/** Gets if the node is a JSDocNullableType. */
static readonly isJSDocNullableType: (node: compiler.Node | undefined) => node is compiler.JSDocNullableType = Node.is(SyntaxKind.JSDocNullableType);
/** Gets if the node is a JSDocOptionalType. */
static readonly isJSDocOptionalType: (node: compiler.Node | undefined) => node is compiler.JSDocOptionalType = Node.is(SyntaxKind.JSDocOptionalType);
/** Gets if the node is a JSDocOverrideTag. */
static readonly isJSDocOverrideTag: (node: compiler.Node | undefined) => node is compiler.JSDocOverrideTag = Node.is(SyntaxKind.JSDocOverrideTag);
/** Gets if the node is a JSDocParameterTag. */
Expand Down Expand Up @@ -3178,13 +3153,8 @@ export class Node<NodeType extends ts.Node = ts.Node> {
}
}

/**
* Gets if the node is a JSDocTypeLiteral.
* @param node - Node to check.
*/
static isJSDocTypeLiteral(node: compiler.Node | undefined): node is compiler.JSDocTypeLiteral {
return node?.getKind() === SyntaxKind.JSDocTypeLiteral;
}
/** Gets if the node is a JSDocTypeLiteral. */
static readonly isJSDocTypeLiteral: (node: compiler.Node | undefined) => node is compiler.JSDocTypeLiteral = Node.is(SyntaxKind.JSDocTypeLiteral);

/**
* Gets if the node is a JSDocTypeParameteredTag.
Expand All @@ -3205,22 +3175,10 @@ export class Node<NodeType extends ts.Node = ts.Node> {
return node?.getKind() === SyntaxKind.JSDocTag;
}

/**
* Gets if the node is a JSDocUnknownType.
* @param node - Node to check.
*/
static isJSDocUnknownType(node: compiler.Node | undefined): node is compiler.JSDocUnknownType {
return node?.getKind() === SyntaxKind.JSDocUnknownType;
}

/**
* Gets if the node is a JSDocVariadicType.
* @param node - Node to check.
*/
static isJSDocVariadicType(node: compiler.Node | undefined): node is compiler.JSDocVariadicType {
return node?.getKind() === SyntaxKind.JSDocVariadicType;
}

/** Gets if the node is a JSDocUnknownType. */
static readonly isJSDocUnknownType: (node: compiler.Node | undefined) => node is compiler.JSDocUnknownType = Node.is(SyntaxKind.JSDocUnknownType);
/** Gets if the node is a JSDocVariadicType. */
static readonly isJSDocVariadicType: (node: compiler.Node | undefined) => node is compiler.JSDocVariadicType = Node.is(SyntaxKind.JSDocVariadicType);
/** Gets if the node is a JsxAttribute. */
static readonly isJsxAttribute: (node: compiler.Node | undefined) => node is compiler.JsxAttribute = Node.is(SyntaxKind.JsxAttribute);

Expand Down Expand Up @@ -3797,6 +3755,7 @@ export class Node<NodeType extends ts.Node = ts.Node> {
*/
static isReferenceFindableNode<T extends compiler.Node>(node: T | undefined): node is compiler.ReferenceFindableNode & compiler.ReferenceFindableNodeExtensionType & T {
switch (node?.getKind()) {
case SyntaxKind.AssertEntry:
case SyntaxKind.BindingElement:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
Expand Down Expand Up @@ -3841,6 +3800,7 @@ export class Node<NodeType extends ts.Node = ts.Node> {
*/
static isRenameableNode<T extends compiler.Node>(node: T | undefined): node is compiler.RenameableNode & compiler.RenameableNodeExtensionType & T {
switch (node?.getKind()) {
case SyntaxKind.AssertEntry:
case SyntaxKind.BindingElement:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
Expand Down Expand Up @@ -4516,6 +4476,7 @@ export class Node<NodeType extends ts.Node = ts.Node> {
/** @internal */
static _hasStructure(node: compiler.Node | undefined): node is compiler.Node & { getStructure(): Structure; } {
switch (node?.getKind()) {
case SyntaxKind.AssertEntry:
case SyntaxKind.CallSignature:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassStaticBlockDeclaration:
Expand Down
2 changes: 2 additions & 0 deletions packages/ts-morph/src/compiler/ast/kindToNodeMappings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export interface ImplementedKindToNodeMappings {
[SyntaxKind.ArrayType]: compiler.ArrayTypeNode;
[SyntaxKind.ArrowFunction]: compiler.ArrowFunction;
[SyntaxKind.AsExpression]: compiler.AsExpression;
[SyntaxKind.AssertClause]: compiler.AssertClause;
[SyntaxKind.AssertEntry]: compiler.AssertEntry;
[SyntaxKind.AwaitExpression]: compiler.AwaitExpression;
[SyntaxKind.BigIntLiteral]: compiler.BigIntLiteral;
[SyntaxKind.BindingElement]: compiler.BindingElement;
Expand Down
30 changes: 30 additions & 0 deletions packages/ts-morph/src/compiler/ast/module/AssertClause.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { ts } from "@ts-morph/common";
import { removeChildren } from "../../../manipulation";
import { AssertEntryStructure, OptionalKind } from "../../../structures";
import { Node } from "../common";

export const AssertClauseBase = Node;
export class AssertClause extends AssertClauseBase<ts.AssertClause> {
/** Sets the elements in the assert clause */
setElements(elements: ReadonlyArray<OptionalKind<AssertEntryStructure>>) {
this.replaceWithText(writer => {
const structurePrinter = this._context.structurePrinterFactory.forAssertEntry();
structurePrinter.printAssertClause(writer, elements);
});
return this;
}

/** Gets the elements of the assert clause. */
getElements() {
return this.compilerNode.elements.map(e => this._getNodeFromCompilerNode(e));
}

/** Removes the assert clause. */
remove() {
removeChildren({
children: [this],
removePrecedingNewLines: true,
removePrecedingSpaces: true,
});
}
}
35 changes: 35 additions & 0 deletions packages/ts-morph/src/compiler/ast/module/AssertEntry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { ts } from "@ts-morph/common";
import { AssertEntryStructure, AssertEntryStructureSpecificStructure, StructureKind } from "../../../structures";
import { AssertionKeyNamedNode } from "../base";
import { callBaseGetStructure } from "../callBaseGetStructure";
import { callBaseSet } from "../callBaseSet";
import { Node } from "../common";
import { StringLiteral } from "../literal";

export const AssertEntryBase = AssertionKeyNamedNode(Node);
export class AssertEntry extends AssertEntryBase<ts.AssertEntry> {
/** Gets the value of the assert entry. */
getValue(): StringLiteral {
return this._getNodeFromCompilerNode(this.compilerNode.value);
}

/** Sets the name and value. */
set(structure: Partial<AssertEntryStructure>) {
callBaseSet(AssertEntryBase.prototype, this, structure);

if (structure.value)
this.getValue().setLiteralValue(structure.value);

return this;
}

/**
* Gets the structure equivalent to this node.
*/
getStructure(): AssertEntryStructure {
return callBaseGetStructure<AssertEntryStructureSpecificStructure>(AssertEntryBase.prototype, this, {
kind: StructureKind.AssertEntry,
value: this.getValue().getLiteralValue(),
});
}
}
41 changes: 40 additions & 1 deletion packages/ts-morph/src/compiler/ast/module/ExportDeclaration.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { ArrayUtils, errors, nameof, StringUtils, SyntaxKind, ts } from "@ts-morph/common";
import { getNodesToReturn, insertIntoCommaSeparatedNodes, insertIntoParentTextRange, removeChildren, verifyAndGetIndex } from "../../../manipulation";
import { ExportDeclarationSpecificStructure, ExportDeclarationStructure, ExportSpecifierStructure, OptionalKind, StructureKind } from "../../../structures";
import {
AssertEntryStructure,
ExportDeclarationSpecificStructure,
ExportDeclarationStructure,
ExportSpecifierStructure,
OptionalKind,
StructureKind,
} from "../../../structures";
import { WriterFunction } from "../../../types";
import { ModuleUtils } from "../../../utils";
import { callBaseGetStructure } from "../callBaseGetStructure";
Expand Down Expand Up @@ -316,6 +323,33 @@ export class ExportDeclaration extends ExportDeclarationBase<ts.ExportDeclaratio
return this;
}

/** Sets the elements in an assert clause. */
setAssertElements(elements: ReadonlyArray<OptionalKind<AssertEntryStructure>> | undefined) {
let assertClause = this.getAssertClause();
if (assertClause) {
if (elements)
assertClause.setElements(elements);
else
assertClause.remove();
} else if (elements) {
const printer = this._context.structurePrinterFactory.forAssertEntry();
const writer = this._context.createWriter();
writer.space();
printer.printAssertClause(writer, elements);
insertIntoParentTextRange({
parent: this,
newText: writer.toString(),
insertPos: this.getSourceFile().getFullText()[this.getEnd() - 1] === ";" ? this.getEnd() - 1 : this.getEnd(),
});
}
return this;
}

/** Gets the assert clause or returns undefined if it doesn't exist. */
getAssertClause() {
return this._getNodeFromCompilerNodeIfExists(this.compilerNode.assertClause);
}

/**
* Sets the node from a structure.
* @param structure - Structure to set the node with.
Expand Down Expand Up @@ -344,6 +378,9 @@ export class ExportDeclaration extends ExportDeclarationBase<ts.ExportDeclaratio
if (structure.isTypeOnly != null)
this.setIsTypeOnly(structure.isTypeOnly);

if (structure.hasOwnProperty(nameof(structure, "assertElements")))
this.setAssertElements(structure.assertElements);

return this;
}

Expand All @@ -352,12 +389,14 @@ export class ExportDeclaration extends ExportDeclarationBase<ts.ExportDeclaratio
*/
getStructure(): ExportDeclarationStructure {
const moduleSpecifier = this.getModuleSpecifier();
const assertClause = this.getAssertClause();
return callBaseGetStructure<ExportDeclarationSpecificStructure>(ExportDeclarationBase.prototype, this, {
kind: StructureKind.ExportDeclaration,
isTypeOnly: this.isTypeOnly(),
moduleSpecifier: moduleSpecifier?.getLiteralText(),
namedExports: this.getNamedExports().map(node => node.getStructure()),
namespaceExport: this.getNamespaceExport()?.getName(),
assertElements: assertClause ? assertClause.getElements().map(e => e.getStructure()) : undefined,
});
}
}
Expand Down
Loading

0 comments on commit bcf694f

Please sign in to comment.