From 0c09b68595b79d1c26f38f6045b663c871f61404 Mon Sep 17 00:00:00 2001
From: Kir_Antipov <kp.antipov@gmail.com>
Date: Fri, 3 Feb 2023 12:13:34 +0000
Subject: [PATCH] Made a class that represents TypeScript variable

---
 src/utils/typescript/typescript-variable.ts | 123 ++++++++++++++++++++
 1 file changed, 123 insertions(+)
 create mode 100644 src/utils/typescript/typescript-variable.ts

diff --git a/src/utils/typescript/typescript-variable.ts b/src/utils/typescript/typescript-variable.ts
new file mode 100644
index 0000000..762f72d
--- /dev/null
+++ b/src/utils/typescript/typescript-variable.ts
@@ -0,0 +1,123 @@
+import { TypeScriptNode } from "./typescript-node";
+import { AbstractTypeScriptNode } from "./abstract-typescript-node";
+import { getIndentation, getNewline, TypeScriptFormattingOptions } from "./typescript-formatting-options";
+import { isCommentableTypeScriptNode } from "./commentable-typescript-node";
+
+/**
+ * Represents the `const` keyword in TypeScript variable declaration.
+ */
+const CONST_DECLARATION = "const";
+
+/**
+ * Represents the `let` keyword in TypeScript variable declaration.
+ */
+const LET_DECLARATION = "let";
+
+/**
+ * Represents the `var` keyword in TypeScript variable declaration.
+ */
+const VAR_DECLARATION = "var";
+
+/**
+ * Represents a TypeScript variable declaration type.
+ */
+type TypeScriptVariableDeclaration = typeof CONST_DECLARATION | typeof LET_DECLARATION | typeof VAR_DECLARATION;
+
+/**
+ * Represents a TypeScript variable.
+ */
+export class TypeScriptVariable extends AbstractTypeScriptNode {
+    /**
+     * The name of the variable.
+     */
+    private readonly _name: string;
+
+    /**
+     * The value assigned to the TypeScript variable.
+     */
+    private readonly _value: TypeScriptNode;
+
+    /**
+     * The declaration type of the TypeScript variable (const, let, or var).
+     */
+    private readonly _declaration: TypeScriptVariableDeclaration;
+
+    /**
+     * Constructs a new {@link TypeScriptVariable} instance with the specified name, value, and declaration type.
+     *
+     * @param name - The name of the variable.
+     * @param value - The value assigned to the variable.
+     * @param declaration - The declaration type of the variable (const, let, or var). Defaults to `const`.
+     */
+    private constructor(name: string, value: TypeScriptNode, declaration?: TypeScriptVariableDeclaration) {
+        super();
+        this._name = name;
+        this._value = value;
+        this._declaration = declaration || CONST_DECLARATION;
+    }
+
+    /**
+     * Creates a new {@link TypeScriptVariable} instance with the specified name, value, and declaration type.
+     *
+     * @param name - The name of the variable.
+     * @param node - The value assigned to the variable.
+     * @param declaration - The declaration type of the variable (const, let, or var). Defaults to `const`.
+     *
+     * @returns A new {@link TypeScriptVariable} instance.
+     */
+    static create(name: string, node: TypeScriptNode, declaration?: TypeScriptVariableDeclaration): TypeScriptVariable {
+        return new TypeScriptVariable(name, node, declaration);
+    }
+
+    /**
+     * Gets the declaration type of the TypeScript variable (const, let, or var).
+     */
+    get declaration(): TypeScriptVariableDeclaration {
+        return this._declaration;
+    }
+
+    /**
+     * Gets the name of the TypeScript variable.
+     */
+    get name(): string {
+        return this._name;
+    }
+
+    /**
+     * Gets the value assigned to the TypeScript variable.
+     */
+    get value(): TypeScriptNode {
+        return this._value;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    formatComments(options?: TypeScriptFormattingOptions): string {
+        const newline = getNewline(options);
+        const node = this._value;
+
+        const thisComments = super.formatComments(options);
+        const nodeComments = isCommentableTypeScriptNode(node) ? node.formatComments(options) : "";
+        if (!thisComments) {
+            return nodeComments;
+        }
+        if (!nodeComments) {
+            return thisComments;
+        }
+        return `${thisComments}${newline}${nodeComments}`;
+    }
+
+    /**
+     * @inheritdoc
+     */
+    formatContent(options?: TypeScriptFormattingOptions): string {
+        const indent = getIndentation(options);
+
+        const value = this._value;
+        const formattedValue = (isCommentableTypeScriptNode(value) ? value.formatContent(options) : value.format(options)).trimStart();
+        const formattedExport = `${indent}${this._declaration} ${this._name} = ${formattedValue}${formattedValue.endsWith(";") ? "" : ";"}`;
+
+        return formattedExport;
+    }
+}