Skip to content

Commit

Permalink
Basic decorators after export keyword support.
Browse files Browse the repository at this point in the history
  • Loading branch information
dsherret committed Mar 18, 2023
1 parent c4a57f8 commit 94c0614
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
7 changes: 6 additions & 1 deletion packages/ts-morph/src/compiler/ast/base/DecoratableNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export function DecoratableNode<T extends Constructor<DecoratableNodeExtensionTy

insertIntoParentTextRange({
parent: decorators[0]?.getParentSyntaxListOrThrow() ?? this.getModifiers()[0]?.getParentSyntaxListOrThrow() ?? this,
insertPos: decorators[index - 1] == null ? this.getStart() : decorators[index - 1].getEnd(),
insertPos: index === 0 ? (decorators[0] ?? this).getStart() : decorators[index - 1].getEnd(),
newText: decoratorCode,
});

Expand Down Expand Up @@ -159,6 +159,11 @@ function getDecoratorFormattingKind(parent: DecoratableNode & Node, currentDecor
}

function areDecoratorsOnSameLine(parent: DecoratableNode & Node, currentDecorators: Node[]) {
if (currentDecorators.length === 1) {
const previousNode = currentDecorators[0].getPreviousSibling();
if (previousNode != null && previousNode.getStartLinePos() === currentDecorators[0].getStartLinePos())
return true;
}
if (currentDecorators.length <= 1)
return parent.getKind() === SyntaxKind.Parameter;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ describe("DecoratableNode", () => {
doTest("class MyClass {}", 0, [{ name: "dec" }], "@dec\nclass MyClass {}");
});

it("should insert when there is an export keyword before", () => {
doTest("export @dec2 class MyClass {}", 0, [{ name: "dec1" }], "export @dec1 @dec2 class MyClass {}");
});

it("should insert with arguments", () => {
doTest("class MyClass {}", 0, [
{ name: "dec", arguments: [] },
Expand Down Expand Up @@ -182,6 +186,10 @@ describe("DecoratableNode", () => {
it("should add when one exists", () => {
doTest("@dec\nclass MyClass {}", { name: "dec2" }, "@dec\n@dec2\nclass MyClass {}");
});

it("should add when one exists and the export keyword is first", () => {
doTest("export @dec class MyClass {}", { name: "dec2" }, "export @dec @dec2 class MyClass {}");
});
});

describe(nameof<DecoratableNode>("addDecorators"), () => {
Expand All @@ -208,6 +216,10 @@ describe("DecoratableNode", () => {
doTest("class Identifier {}", { decorators: [{ name: "dec1" }, { name: "dec2" }] }, "@dec1\n@dec2\nclass Identifier {}");
});

it("should modify when setting and has export keyword", () => {
doTest("export class Identifier {}", { decorators: [{ name: "dec1" }, { name: "dec2" }] }, "@dec1\n@dec2\nexport class Identifier {}");
});

it("should not modify anything if the structure doesn't change anything", () => {
doTest("class Identifier {}", {}, "class Identifier {}");
});
Expand All @@ -219,6 +231,11 @@ describe("DecoratableNode", () => {
it("should remove existing decorators when specifying a value", () => {
doTest("@old1 @old2 class Identifier {}", { decorators: [] }, "class Identifier {}");
});

it("should replace existing decorators when has export keyword", () => {
// todo: would be good to improve this in the future to maintain the position
doTest("export @old1 @old2 class Identifier {}", { decorators: [{ name: "newDec" }] }, "@newDec\nexport class Identifier {}");
});
});

describe(nameof<ClassDeclaration>("getStructure"), () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,10 @@ describe("Decorator", () => {
doTest("@decorator(2, 5, 3)\nclass T {}", 0, "class T {}");
});

it("should remove when it's after the export keyword", () => {
doTest("export @decorator(2, 5, 3) class T {}", 0, "export class T {}");
});

it("should remove when it's the first class decorator on the same line", () => {
doTest("@dec1 @dec2 @dec3\nclass T {}", 0, "@dec2 @dec3\nclass T {}");
});
Expand Down Expand Up @@ -464,6 +468,15 @@ describe("Decorator", () => {
};
doTest("@dec class T {}", structure, "@NewName<T>(1) class T {}");
});

it("should set when decorator is after export keyword", () => {
const structure: OptionalKindAndTrivia<MakeRequired<DecoratorStructure>> = {
name: "NewName",
arguments: ["1"],
typeArguments: ["T"],
};
doTest("export @dec class T {}", structure, "export @NewName<T>(1) class T {}");
});
});

describe(nameof<Decorator>("getStructure"), () => {
Expand All @@ -483,7 +496,7 @@ describe("Decorator", () => {
});

it("should get when has everything", () => {
doTest("@dec<T>(test) class T {}", {
doTest("export @dec<T>(test) class T {}", {
kind: StructureKind.Decorator,
name: "dec",
arguments: ["test"],
Expand Down

0 comments on commit 94c0614

Please sign in to comment.