From d00ce8f9849902fedea31ab0ff93c7171cf4eebb Mon Sep 17 00:00:00 2001
From: Kir_Antipov <kp.antipov@gmail.com>
Date: Wed, 1 Feb 2023 14:48:31 +0000
Subject: [PATCH] Implemented base class for TypeScript nodes

---
 .../typescript/abstract-typescript-node.ts    | 91 +++++++++++++++++++
 1 file changed, 91 insertions(+)
 create mode 100644 src/utils/typescript/abstract-typescript-node.ts

diff --git a/src/utils/typescript/abstract-typescript-node.ts b/src/utils/typescript/abstract-typescript-node.ts
new file mode 100644
index 0000000..d7c370a
--- /dev/null
+++ b/src/utils/typescript/abstract-typescript-node.ts
@@ -0,0 +1,91 @@
+import { TypeScriptComment } from "./typescript-comment";
+import { CommentableTypeScriptNode } from "./commentable-typescript-node";
+import { getNewline, TypeScriptFormattingOptions } from "./typescript-formatting-options";
+
+/**
+ * Provides basic functionality for formatting TypeScript nodes with comments.
+ */
+export abstract class AbstractTypeScriptNode implements CommentableTypeScriptNode {
+    /**
+     * An array of `TypeScriptComment` instances representing the comments associated with this node.
+     */
+    private _comments?: TypeScriptComment[];
+
+    /**
+     * Returns an iterable of comments associated with this node.
+     */
+    comments(): Iterable<TypeScriptComment> {
+        return this._comments || [];
+    }
+
+    /**
+     * @inheritdoc
+     */
+    addComment(comment: TypeScriptComment): TypeScriptComment;
+
+    /**
+     * @inheritdoc
+     */
+    addComment(comment: string): TypeScriptComment;
+
+    /**
+     * @inheritdoc
+     */
+    addComment(comment: string | TypeScriptComment): TypeScriptComment {
+        const commentNode = typeof comment === "string" ? TypeScriptComment.parse(comment) : comment;
+        this._comments ??= [];
+        this._comments.push(commentNode);
+        return commentNode;
+    }
+
+    /**
+     * Adds a TSDoc comment to this node.
+     *
+     * @param comment - The TSDoc comment to add to this node.
+     *
+     * @returns A new instance of {@link TypeScriptComment} representing the added TSDoc comment.
+     */
+    addTSDoc(comment: string): TypeScriptComment {
+        return this.addComment(TypeScriptComment.createTSDoc(comment));
+    }
+
+    /**
+     * @inheritdoc
+     */
+    deleteComment(comment: TypeScriptComment): boolean {
+        const i = this._comments?.indexOf(comment) ?? -1;
+        if (i === -1) {
+            return false;
+        }
+
+        this._comments.splice(i, 1);
+        return true;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    formatComments(options?: TypeScriptFormattingOptions): string {
+        const newline = getNewline(options);
+        const formattedComments = this._comments?.map(x => x.format(options)).join(newline) || "";
+        return formattedComments;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    abstract formatContent(options?: TypeScriptFormattingOptions): string;
+
+    /**
+     * @inheritdoc
+     */
+    format(options?: TypeScriptFormattingOptions): string {
+        const newline = getNewline(options);
+
+        const formattedComments = this.formatComments(options);
+        const formattedContent = this.formatContent(options);
+        const formattedNode = `${formattedComments}${formattedComments ? newline : ""}${formattedContent}`;
+
+        return formattedNode;
+    }
+}