Skip to content

Commit

Permalink
fix: do not throw an error if decorator expr is wrapped in a paren expr
Browse files Browse the repository at this point in the history
Closes #1214
  • Loading branch information
dsherret committed Nov 13, 2021
1 parent be87373 commit c77db30
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 17 deletions.
6 changes: 3 additions & 3 deletions bvm.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"binaries": [
{
"path": "https://bvm.land/deno/1.15.3.json",
"checksum": "adb30172c0741a161ce6b53651e16f832c44e67bf1cabf55a9dd9780505b749a",
"version": "1.15.3"
"path": "https://bvm.land/deno/1.16.1.json",
"checksum": "0294b4e8d9426972cf015ebd3cc0d657eab9b20983790a92c27c96c265cb73d1",
"version": "1.16.1"
},
{
"path": "https://github.com/dprint/dprint/releases/download/0.18.1/bvm.json",
Expand Down
32 changes: 18 additions & 14 deletions packages/ts-morph/src/compiler/ast/decorator/Decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,24 @@ export class Decorator extends DecoratorBase<ts.Decorator> {
* Gets the name node of the decorator.
*/
getNameNode() {
if (this.isDecoratorFactory()) {
const callExpression = this.getCallExpression()!;
const callExpression = this.getCallExpression();
if (callExpression)
return getIdentifierFromName(callExpression.getExpression());
}

return getIdentifierFromName(this.getExpression());
else
return getIdentifierFromName(this.#getInnerExpression());

function getIdentifierFromName(expression: Expression) {
const identifier = getNameFromExpression(expression);
if (!Node.isIdentifier(identifier)) {
throw new errors.NotImplementedError(
`Expected the decorator expression '${identifier.getText()}' to be an identifier, `
+ `but it wasn't. Please report this as a bug.`,
`Expected the decorator expression '${identifier.getText()}' to be an identifier. `
+ `Please deal directly with 'getExpression()' on the decorator to handle more complex scenarios.`,
);
}
return identifier;
}

function getNameFromExpression(expression: Expression) {
function getNameFromExpression(expression: Expression): Node {
if (Node.isPropertyAccessExpression(expression))
return expression.getNameNode();
return expression;
Expand All @@ -61,7 +60,7 @@ export class Decorator extends DecoratorBase<ts.Decorator> {
* Gets if the decorator is a decorator factory.
*/
isDecoratorFactory() {
return this.compilerNode.expression.kind === SyntaxKind.CallExpression;
return Node.isCallExpression(this.#getInnerExpression());
}

/**
Expand All @@ -73,7 +72,7 @@ export class Decorator extends DecoratorBase<ts.Decorator> {
return this;

if (isDecoratorFactory) {
const expression = this.getExpression();
const expression = this.#getInnerExpression();
const expressionText = expression.getText();
insertIntoParentTextRange({
parent: this,
Expand Down Expand Up @@ -121,10 +120,8 @@ export class Decorator extends DecoratorBase<ts.Decorator> {
* Gets the call expression if a decorator factory.
*/
getCallExpression(): CallExpression | undefined {
if (!this.isDecoratorFactory())
return undefined;

return this.getExpression() as any as CallExpression;
const expression = this.#getInnerExpression();
return Node.isCallExpression(expression) ? expression : undefined;
}

/**
Expand Down Expand Up @@ -269,6 +266,13 @@ export class Decorator extends DecoratorBase<ts.Decorator> {
}
}

#getInnerExpression() {
let expr: Expression = this.getExpression();
while (Node.isParenthesizedExpression(expr))
expr = expr.getExpression();
return expr;
}

/**
* Sets the node from a structure.
* @param structure - Structure to set the node with.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ describe(nameof(Decorator), () => {
const { firstDecorator } = getFirstClassDecorator("@decorator('str', 23)\nclass Identifier {}");
expect(firstDecorator.isDecoratorFactory()).to.equal(true);
});

it("should be even when surrounded in parens", () => {
const { firstDecorator } = getFirstClassDecorator("@(decorator('str', 23))\nclass Identifier {}");
expect(firstDecorator.isDecoratorFactory()).to.equal(true);
});
});

describe(nameof<Decorator>(d => d.setIsDecoratorFactory), () => {
Expand Down Expand Up @@ -83,6 +88,10 @@ describe(nameof(Decorator), () => {
it("should get the name node for a decorator factory decorator with a namespace", () => {
doTest("@namespaceTest.decorator()\nclass Identifier {}", "decorator");
});

it("should get the name node for a decorator wrapped in a paren expr", () => {
doTest("@(decorator())\nclass Identifier {}", "decorator");
});
});

describe(nameof<Decorator>(d => d.getName), () => {
Expand Down

0 comments on commit c77db30

Please sign in to comment.