Skip to content

Commit

Permalink
feat: add helper properties on TemplateLiteralTypeNode.
Browse files Browse the repository at this point in the history
Closes #1266
  • Loading branch information
dsherret committed May 6, 2022
1 parent 79ab80f commit 1a8de49
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 6 deletions.
21 changes: 20 additions & 1 deletion deno/ts_morph.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3393,6 +3393,13 @@ export declare class Node<NodeType extends ts.Node = ts.Node> {
* @param kind - Syntax kind.
*/
asKindOrThrow<TKind extends SyntaxKind>(kind: TKind): KindToNodeMappings[TKind];
/**
* Returns if the node is the specified kind.
*
* This is a type guard.
* @param kind - Syntax kind.
*/
isKind<TKind extends SyntaxKind>(kind: TKind): this is KindToNodeMappings[TKind];
/**
* Gets the node as the specified kind if it is equal to that kind, otherwise returns undefined.
* @param kind - Syntax kind.
Expand Down Expand Up @@ -6946,7 +6953,7 @@ export declare class TemplateExpression extends TemplateExpressionBase<ts.Templa
* @param value - Value to set.
* @returns The new node if the kind changed; the current node otherwise.
*/
setLiteralValue(value: string): TemplateLiteral;
setLiteralValue(value: string): Node<ts.Node>;
/** @inheritdoc **/
getParent(): NodeParentType<ts.TemplateExpression>;
/** @inheritdoc **/
Expand Down Expand Up @@ -8881,6 +8888,18 @@ export declare class ParenthesizedTypeNode extends TypeNode<ts.ParenthesizedType
}

export declare class TemplateLiteralTypeNode extends TypeNode<ts.TemplateLiteralTypeNode> {
/** Gets the template head. */
getHead(): TemplateHead;
/** Gets the template spans. */
getTemplateSpans(): TypeNode<ts.TypeNode>[];
/**
* Sets the literal value.
*
* Note: This could possibly replace the node if you remove all the tagged templates.
* @param value - Value to set.
* @returns The new node if the kind changed; the current node otherwise.
*/
setLiteralValue(value: string): Node<ts.Node>;
/** @inheritdoc **/
getParent(): NodeParentType<ts.TemplateLiteralTypeNode>;
/** @inheritdoc **/
Expand Down
23 changes: 22 additions & 1 deletion deno/ts_morph.js
Original file line number Diff line number Diff line change
Expand Up @@ -3112,8 +3112,11 @@ class Node {
asKindOrThrow(kind) {
return errors.throwIfNullOrUndefined(this.asKind(kind), () => `Expected the node to be of kind ${getSyntaxKindName(kind)}, but it was ${getSyntaxKindName(this.getKind())}.`);
}
isKind(kind) {
return this.getKind() === kind;
}
asKind(kind) {
if (this.getKind() === kind) {
if (this.isKind(kind)) {
return this;
}
else {
Expand Down Expand Up @@ -15244,6 +15247,24 @@ class ParenthesizedTypeNode extends TypeNode {
}

class TemplateLiteralTypeNode extends TypeNode {
getHead() {
return this._getNodeFromCompilerNode(this.compilerNode.head);
}
getTemplateSpans() {
return this.compilerNode.templateSpans.map(s => this._getNodeFromCompilerNode(s));
}
setLiteralValue(value) {
var _a;
const childIndex = this.getChildIndex();
const parent = (_a = this.getParentSyntaxList()) !== null && _a !== void 0 ? _a : this.getParentOrThrow();
replaceNodeText({
sourceFile: this._sourceFile,
start: this.getStart() + 1,
replacingLength: this.getWidth() - 2,
newText: value,
});
return parent.getChildAtIndex(childIndex);
}
}

class ThisTypeNode extends TypeNode {
Expand Down
21 changes: 20 additions & 1 deletion packages/ts-morph/lib/ts-morph.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3393,6 +3393,13 @@ export declare class Node<NodeType extends ts.Node = ts.Node> {
* @param kind - Syntax kind.
*/
asKindOrThrow<TKind extends SyntaxKind>(kind: TKind): KindToNodeMappings[TKind];
/**
* Returns if the node is the specified kind.
*
* This is a type guard.
* @param kind - Syntax kind.
*/
isKind<TKind extends SyntaxKind>(kind: TKind): this is KindToNodeMappings[TKind];
/**
* Gets the node as the specified kind if it is equal to that kind, otherwise returns undefined.
* @param kind - Syntax kind.
Expand Down Expand Up @@ -6946,7 +6953,7 @@ export declare class TemplateExpression extends TemplateExpressionBase<ts.Templa
* @param value - Value to set.
* @returns The new node if the kind changed; the current node otherwise.
*/
setLiteralValue(value: string): TemplateLiteral;
setLiteralValue(value: string): Node<ts.Node>;
/** @inheritdoc **/
getParent(): NodeParentType<ts.TemplateExpression>;
/** @inheritdoc **/
Expand Down Expand Up @@ -8881,6 +8888,18 @@ export declare class ParenthesizedTypeNode extends TypeNode<ts.ParenthesizedType
}

export declare class TemplateLiteralTypeNode extends TypeNode<ts.TemplateLiteralTypeNode> {
/** Gets the template head. */
getHead(): TemplateHead;
/** Gets the template spans. */
getTemplateSpans(): TypeNode<ts.TypeNode>[];
/**
* Sets the literal value.
*
* Note: This could possibly replace the node if you remove all the tagged templates.
* @param value - Value to set.
* @returns The new node if the kind changed; the current node otherwise.
*/
setLiteralValue(value: string): Node<ts.Node>;
/** @inheritdoc **/
getParent(): NodeParentType<ts.TemplateLiteralTypeNode>;
/** @inheritdoc **/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ts } from "@ts-morph/common";
import { replaceNodeText } from "../../../../manipulation";
import { TemplateLiteral } from "../../aliases";
import { PrimaryExpression } from "../../expression";
import { TemplateHead } from "./TemplateHead";

Expand Down Expand Up @@ -37,6 +36,6 @@ export class TemplateExpression extends TemplateExpressionBase<ts.TemplateExpres
newText: value,
});

return parent.getChildAtIndex(childIndex) as TemplateLiteral;
return parent.getChildAtIndex(childIndex);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,40 @@
import { ts } from "@ts-morph/common";
import { replaceNodeText } from "../../../manipulation";
import { TemplateHead } from "../literal";
import { TypeNode } from "./TypeNode";

export class TemplateLiteralTypeNode extends TypeNode<ts.TemplateLiteralTypeNode> {
// todo: helper methods
/**
* Gets the template head.
*/
getHead(): TemplateHead {
return this._getNodeFromCompilerNode(this.compilerNode.head);
}

/**
* Gets the template spans.
*/
getTemplateSpans() {
return this.compilerNode.templateSpans.map(s => this._getNodeFromCompilerNode(s));
}

/**
* Sets the literal value.
*
* Note: This could possibly replace the node if you remove all the tagged templates.
* @param value - Value to set.
* @returns The new node if the kind changed; the current node otherwise.
*/
setLiteralValue(value: string) {
const childIndex = this.getChildIndex();
const parent = this.getParentSyntaxList() ?? this.getParentOrThrow();
replaceNodeText({
sourceFile: this._sourceFile,
start: this.getStart() + 1,
replacingLength: this.getWidth() - 2,
newText: value,
});

return parent.getChildAtIndex(childIndex);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { nameof, SyntaxKind } from "@ts-morph/common";
import { expect } from "chai";
import { TemplateExpression, TemplateLiteralTypeNode } from "../../../../compiler";
import { getInfoFromTextWithDescendant } from "../../testHelpers";

function getTypeNode(text: string) {
return getInfoFromTextWithDescendant<TemplateLiteralTypeNode>(text, SyntaxKind.TemplateLiteralType).descendant;
}

describe("TemplateLiteralTypeNode", () => {
describe(nameof<TemplateLiteralTypeNode>("getHead"), () => {
function doTest(text: string, expectedText: string) {
const expression = getTypeNode(text);
expect(expression.getHead().getText()).to.equal(expectedText);
}

it("should get the correct template head", () => {
doTest("type Test = `foo${test}`", "`foo${");
});
});

describe(nameof<TemplateLiteralTypeNode>("getTemplateSpans"), () => {
function doTest(text: string, expectedText: string) {
const expression = getTypeNode(text);
expect(expression.getTemplateSpans()[0].getText()).to.equal(expectedText);
}

it("should get the correct template spans", () => {
doTest("type Test = `foo${test}`", "test}`");
});
});

describe(nameof<TemplateLiteralTypeNode>("setLiteralValue"), () => {
function doTest(text: string, newText: string, expectedText: string) {
const expression = getTypeNode(text);
const sourceFile = expression._sourceFile;
expect(expression.setLiteralValue(newText).wasForgotten()).to.be.false;
expect(sourceFile.getText()).to.equal(expectedText);
}

it("should set the value", () => {
doTest("type Test = `foo${test}`", "testing${this}out", "type Test = `testing${this}out`");
});

it("should set the value to not have any tagged templates", () => {
doTest("type Test = `foo${test}`", "testing", "type Test = `testing`");
});
});
});

0 comments on commit 1a8de49

Please sign in to comment.