diff --git a/packages/ts-morph/src/compiler/ast/common/Node.ts b/packages/ts-morph/src/compiler/ast/common/Node.ts index ae7d703d7..f7e450c05 100644 --- a/packages/ts-morph/src/compiler/ast/common/Node.ts +++ b/packages/ts-morph/src/compiler/ast/common/Node.ts @@ -7,7 +7,7 @@ import { getNextMatchingPos, getNextNonWhitespacePos, getPreviousNonWhitespacePo replaceSourceFileTextForFormatting, replaceSourceFileTextStraight, hasNewLineInRange } from "../../../manipulation"; import { WriterFunction } from "../../../types"; import { getParentSyntaxList, getTextFromStringOrWriter, isStringKind, printNode, PrintNodeOptions, CharCodes } from "../../../utils"; -import { Structure } from "../../../structures"; +import { Structure, Structures } from "../../../structures"; import { FormatCodeSettings } from "../../tools"; import { Symbol } from "../../symbols"; import { Type } from "../../types"; @@ -2120,6 +2120,15 @@ export class Node { return (node as any).getBody?.() != null; } + /** + * Gets if the node has a structure. + * @param node - Node to check. + */ + static hasStructure(node: T): node is T & { getStructure(): Structures; } { + // this method is manually maintained + return typeof (node as any).getStructure === "function"; + } + /** Creates a type guard for syntax kinds. */ static is(kind: TKind): (node: compiler.Node | undefined) => node is KindToNodeMappings[TKind] { return (node: compiler.Node | undefined): node is KindToNodeMappings[TKind] => { diff --git a/packages/ts-morph/src/compiler/ast/statement/StatementedNode.ts b/packages/ts-morph/src/compiler/ast/statement/StatementedNode.ts index aca38fbdd..24bc2d093 100644 --- a/packages/ts-morph/src/compiler/ast/statement/StatementedNode.ts +++ b/packages/ts-morph/src/compiler/ast/statement/StatementedNode.ts @@ -784,7 +784,7 @@ export function StatementedNode boolean)): ModuleDeclaration { return errors.throwIfNullOrUndefined( this.getModule(nameOrFindFunction), - () => getNotFoundErrorMessageForNameOrFindFunction("namespace", nameOrFindFunction), + () => getNotFoundErrorMessageForNameOrFindFunction("module", nameOrFindFunction), ); } diff --git a/packages/ts-morph/src/tests/compiler/ast/common/nodeTypeGuardsTests.ts b/packages/ts-morph/src/tests/compiler/ast/common/nodeTypeGuardsTests.ts index f37aa3aa5..30fe0b619 100644 --- a/packages/ts-morph/src/tests/compiler/ast/common/nodeTypeGuardsTests.ts +++ b/packages/ts-morph/src/tests/compiler/ast/common/nodeTypeGuardsTests.ts @@ -1,6 +1,7 @@ import { expect } from "chai"; import { assert, IsExact } from "conditional-type-checks"; -import { ClassDeclaration, Node } from "../../../../compiler"; +import { ClassDeclaration, ExpressionStatement, Node } from "../../../../compiler"; +import { Structures } from "../../../../structures"; import { getInfoFromText } from "../../testHelpers"; describe(nameof(Node), () => { @@ -48,6 +49,22 @@ describe(nameof(Node), () => { }); }); + describe(nameof(Node.hasStructure), () => { + it("should have a structure when it does", () => { + const { firstChild } = getInfoFromText("class MyClass {}"); + expect(Node.hasName(firstChild)).to.be.true; + if (Node.hasStructure(firstChild)) { + assert>(true); + expect((firstChild.getStructure() as any).name).to.equal("MyClass"); + } + }); + + it("should not have a structure when it doesn't", () => { + const { firstChild } = getInfoFromText("func();"); + expect(Node.hasStructure(firstChild.getExpression().getChildren()[0])).to.be.false; + }); + }); + describe(nameof(Node.isNode), () => { const { firstChild, project } = getInfoFromText("class MyClass {}");