diff --git a/generator/generators/googleCloud/generator.js b/generator/generators/googleCloud/generator.js index ea5d502a..84a364b2 100644 --- a/generator/generators/googleCloud/generator.js +++ b/generator/generators/googleCloud/generator.js @@ -204,7 +204,7 @@ function extractClassBasedSDKData(methods, sdkFiles) { params: parameters, returnType: returnType, returnTypeName: null, - client: classAst.name.text, // Class name + client: classAst.name.text, }; if (returnType === 'TypeReference') { method_1.returnTypeName = diff --git a/generator/generators/linode/generator.js b/generator/generators/linode/generator.js index 16932040..90f2271b 100644 --- a/generator/generators/linode/generator.js +++ b/generator/generators/linode/generator.js @@ -140,9 +140,19 @@ var __generator = } }; exports.__esModule = true; -exports.generateLinodeClass = exports.extractSDKData = void 0; +exports.generateLinodeClass = exports.getFunctions = exports.extractSDKData = void 0; +var fs = require('fs'); var typescript_1 = require('typescript'); var parser_1 = require('../../parsers/linode/parser'); +var transformer_1 = require('../../transformers/linode/transformer'); +var helper_1 = require('../lib/helper'); +var dummyFile = process.cwd() + '/dummyClasses/linode.js'; +var dummyAst = typescript_1.createSourceFile( + dummyFile, + fs.readFileSync(dummyFile).toString(), + typescript_1.ScriptTarget.Latest, + true +); function extractSDKData(sdkAst, serviceClass) { var methods = []; var functions = []; @@ -170,11 +180,12 @@ function extractSDKData(sdkAst, serviceClass) { }; // common type if (param.type.typeName) { - parameter.typeName = param.type.typeName.excapedText; + parameter.typeName = param.type.typeName.text; } parameters_1.push(parameter); } }); + // console.log(parameters); methods.push({ functionName: name_1.toString(), SDKFunctionName: methodName, @@ -182,81 +193,179 @@ function extractSDKData(sdkAst, serviceClass) { }); } }); - var classData = { - className: '', - functions: methods, - serviceName: null, - }; - return classData; + return methods; } exports.extractSDKData = extractSDKData; -function generateLinodeClass(serviceClass, serviceName) { +function getFunctions(sdkFiles, serviceClass) { return __awaiter(this, void 0, void 0, function() { - var methods, files, sdkFiles; + var functionsArray; var _this = this; return __generator(this, function(_a) { - methods = []; - if (serviceClass == null) return [2 /*return*/]; - Object.keys(serviceClass).map(function(key, index) { - methods.push({ - pkgName: serviceClass[key].split(' ')[0], - fileName: serviceClass[key].split(' ')[1], - functionName: key, - SDKFunctionName: serviceClass[key].split(' ')[2], - params: [], - returnType: null, - client: null, - }); - }); - files = Array.from( - new Set( - methods.map(function(method) { - return method.fileName; - }) - ) - ); - sdkFiles = files.map(function(file) { - return { - fileName: file, - pkgName: methods[0].pkgName, - ast: null, - client: null, - sdkFunctionNames: methods - .filter(function(method) { - return method.fileName === file; - }) - .map(function(method) { - return method.SDKFunctionName; - }), - }; - }); - sdkFiles.map(function(file) { - return __awaiter(_this, void 0, void 0, function() { - var _this = this; - return __generator(this, function(_a) { - parser_1.getAST(file).then(function(result) { + switch (_a.label) { + case 0: + functionsArray = []; + return [ + 4 /*yield*/, + sdkFiles.map(function(file) { return __awaiter(_this, void 0, void 0, function() { - var sdkAst, classData; + var _this = this; return __generator(this, function(_a) { - sdkAst = result; - try { - classData = extractSDKData( - sdkAst, - serviceClass - ); - classData.serviceName = serviceName; - } catch (e) { - console.error(e); - } + parser_1 + .getAST(file) + .then(function(result) { + return __awaiter( + _this, + void 0, + void 0, + function() { + var sdkAst, functions; + return __generator( + this, + function(_a) { + sdkAst = result; + try { + functions = extractSDKData( + sdkAst, + serviceClass + ); + functions.map( + function( + method, + index + ) { + functionsArray.push( + method + ); + } + ); + } catch (e) { + console.error( + e + ); + } + return [ + 2 /*return*/, + ]; + } + ); + } + ); + }); return [2 /*return*/]; }); }); + }), + ]; + case 1: + _a.sent(); + return [2 /*return*/, functionsArray]; + } + }); + }); +} +exports.getFunctions = getFunctions; +function generateLinodeClass(serviceClass, serviceName) { + return __awaiter(this, void 0, void 0, function() { + var methods_1, + files, + sdkFiles, + functionsArray, + classData, + output, + filePath, + dir, + e_1; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 3, , 4]); + methods_1 = []; + if (serviceClass == null) return [2 /*return*/]; + Object.keys(serviceClass).map(function(key, index) { + methods_1.push({ + pkgName: serviceClass[key].split(' ')[0], + fileName: serviceClass[key].split(' ')[1], + functionName: key, + SDKFunctionName: serviceClass[key].split(' ')[2], + params: [], + returnType: null, + client: null, }); - return [2 /*return*/]; }); - }); - }); - return [2 /*return*/]; + files = Array.from( + new Set( + methods_1.map(function(method) { + return method.fileName; + }) + ) + ); + sdkFiles = files.map(function(file) { + return { + fileName: file, + pkgName: methods_1[0].pkgName, + ast: null, + client: null, + sdkFunctionNames: methods_1 + .filter(function(method) { + return method.fileName === file; + }) + .map(function(method) { + return method.SDKFunctionName; + }), + }; + }); + return [4 /*yield*/, getFunctions(sdkFiles, serviceClass)]; + case 1: + functionsArray = _a.sent(); + classData = { + className: serviceName + 'LinodeClass', + functions: functionsArray, + serviceName: serviceName, + }; + return [ + 4 /*yield*/, + transformer_1.transform(dummyAst, classData), + ]; + case 2: + output = _a.sent(); + filePath = void 0; + dir = helper_1.getDir(serviceName); + if ( + !fs.existsSync( + process.cwd() + '/generatedClasses/Linode/' + dir + ) + ) { + fs.mkdirSync( + process.cwd() + '/generatedClasses/Linode/' + dir + ); + } + if (/^[A-Z]*$/.test(serviceName)) { + filePath = + process.cwd() + + '/generatedClasses/Linode/' + + dir + + '/linode-' + + serviceName + + '.js'; + } else { + filePath = + process.cwd() + + '/generatedClasses/Linode/' + + dir + + '/linode-' + + serviceName.charAt(0).toLowerCase() + + serviceName.slice(1) + + '.js'; + } + helper_1.printFile(filePath, output); + return [3 /*break*/, 4]; + case 3: + e_1 = _a.sent(); + console.error(e_1); + return [3 /*break*/, 4]; + case 4: + return [2 /*return*/]; + } }); }); } diff --git a/generator/generators/linode/generator.ts b/generator/generators/linode/generator.ts index 5a50e74c..b6d95a43 100644 --- a/generator/generators/linode/generator.ts +++ b/generator/generators/linode/generator.ts @@ -1,7 +1,8 @@ import * as fs from 'fs'; -import { createSourceFile, ScriptTarget,SyntaxKind } from 'typescript'; +import { createSourceFile, ScriptTarget, SyntaxKind } from 'typescript'; import { getAST } from '../../parsers/linode/parser'; +import { transform } from '../../transformers/linode/transformer'; import { getDir, printFile } from '../lib/helper'; interface SDKClassData { @@ -78,6 +79,8 @@ export function extractSDKData(sdkAst, serviceClass) { parameters.push(parameter); } }); + // console.log(parameters); + methods.push({ functionName: name.toString(), SDKFunctionName: methodName, @@ -152,7 +155,33 @@ export async function generateLinodeClass(serviceClass, serviceName) { functions: functionsArray, serviceName: serviceName, }; + const output = await transform(dummyAst, classData); + let filePath; + const dir = getDir(serviceName); + + if (!fs.existsSync(process.cwd() + '/generatedClasses/Linode/' + dir)) { + fs.mkdirSync(process.cwd() + '/generatedClasses/Linode/' + dir); + } + if (/^[A-Z]*$/.test(serviceName)) { + filePath = + process.cwd() + + '/generatedClasses/Linode/' + + dir + + '/linode-' + + serviceName + + '.js'; + } else { + filePath = + process.cwd() + + '/generatedClasses/Linode/' + + dir + + '/linode-' + + serviceName.charAt(0).toLowerCase() + + serviceName.slice(1) + + '.js'; + } + printFile(filePath, output); } catch (e) { console.error(e); } -} \ No newline at end of file +} diff --git a/generator/parsers/linode/parser.js b/generator/parsers/linode/parser.js index 7958cca4..e98e1784 100644 --- a/generator/parsers/linode/parser.js +++ b/generator/parsers/linode/parser.js @@ -171,10 +171,6 @@ function getAST(sdkFileInfo) { return [ 4 /*yield*/, ast.forEachChild(function(child) { - // fs.writeFile('test.txt', SyntaxKind[child.kind], null); - // console.log(SyntaxKind[child.kind]); - // console.log('Linode', SyntaxKind[child.kind]); - // console.log("child",child); if ( typescript_1.SyntaxKind[child.kind] === 'FirstStatement' @@ -185,16 +181,11 @@ function getAST(sdkFileInfo) { cloned_1.push( tmp_1.declarationList.declarations[0] ); - // console.log( - // 'name', - // tmp.declarationList.declarations[0].type.parameters[0] - // ); } }), ]; case 1: _a.sent(); - // console.log('cloned', cloned); if (!cloned_1) { reject(new Error('Function not found!')); } else { diff --git a/generator/transformers/linode/transformer.js b/generator/transformers/linode/transformer.js new file mode 100644 index 00000000..8f76a586 --- /dev/null +++ b/generator/transformers/linode/transformer.js @@ -0,0 +1,450 @@ +'use strict'; +var __awaiter = + (this && this.__awaiter) || + function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P + ? value + : new P(function(resolve) { + resolve(value); + }); + } + return new (P || (P = Promise))(function(resolve, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator['throw'](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done + ? resolve(result.value) + : adopt(result.value).then(fulfilled, rejected); + } + step( + (generator = generator.apply(thisArg, _arguments || [])).next() + ); + }); + }; +var __generator = + (this && this.__generator) || + function(thisArg, body) { + var _ = { + label: 0, + sent: function() { + if (t[0] & 1) throw t[1]; + return t[1]; + }, + trys: [], + ops: [], + }, + f, + y, + t, + g; + return ( + (g = { next: verb(0), throw: verb(1), return: verb(2) }), + typeof Symbol === 'function' && + (g[Symbol.iterator] = function() { + return this; + }), + g + ); + function verb(n) { + return function(v) { + return step([n, v]); + }; + } + function step(op) { + if (f) throw new TypeError('Generator is already executing.'); + while (_) + try { + if ( + ((f = 1), + y && + (t = + op[0] & 2 + ? y['return'] + : op[0] + ? y['throw'] || + ((t = y['return']) && t.call(y), 0) + : y.next) && + !(t = t.call(y, op[1])).done) + ) + return t; + if (((y = 0), t)) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: + case 1: + t = op; + break; + case 4: + _.label++; + return { value: op[1], done: false }; + case 5: + _.label++; + y = op[1]; + op = [0]; + continue; + case 7: + op = _.ops.pop(); + _.trys.pop(); + continue; + default: + if ( + !((t = _.trys), + (t = t.length > 0 && t[t.length - 1])) && + (op[0] === 6 || op[0] === 2) + ) { + _ = 0; + continue; + } + if ( + op[0] === 3 && + (!t || (op[1] > t[0] && op[1] < t[3])) + ) { + _.label = op[1]; + break; + } + if (op[0] === 6 && _.label < t[1]) { + _.label = t[1]; + t = op; + break; + } + if (t && _.label < t[2]) { + _.label = t[2]; + _.ops.push(op); + break; + } + if (t[2]) _.ops.pop(); + _.trys.pop(); + continue; + } + op = body.call(thisArg, _); + } catch (e) { + op = [6, e]; + y = 0; + } finally { + f = t = 0; + } + if (op[0] & 5) throw op[1]; + return { value: op[0] ? op[1] : void 0, done: true }; + } + }; +exports.__esModule = true; +exports.transform = void 0; +var lodash_1 = require('lodash'); +var ts = require('typescript'); +var dummyIdentifiers = ['ClassName', 'SDKFunctionName']; +var printer = ts.createPrinter({ + newLine: ts.NewLineKind.LineFeed, + removeComments: false, +}); +function addMultiLineComment(node, comment) { + ts.addSyntheticLeadingComment( + node, + ts.SyntaxKind.MultiLineCommentTrivia, + comment, + true + ); +} +function runTransformation(sourceCode, transformMethod) { + return new Promise(function(resolve, reject) { + try { + var result = ts.transform(sourceCode, [transformMethod]); + var transformedNodes = result.transformed[0]; + var output = printer.printNode( + ts.EmitHint.SourceFile, + transformedNodes, + sourceCode + ); + resolve(output); + } catch (error) { + reject(error); + } + }); +} +function toSourceFile(sourceCode) { + return ts.createSourceFile( + 'dummyClass.js', + sourceCode, + ts.ScriptTarget.Latest, + true + ); +} +function transform(code, classData) { + return __awaiter(this, void 0, void 0, function() { + var addFunctions, + addIdentifiers, + addComments, + node, + result_1, + result_2, + result_3; + return __generator(this, function(_a) { + switch (_a.label) { + case 0: + addFunctions = function(context) { + return function(rootNode) { + function visit(node) { + if (ts.isClassDeclaration(node)) { + var functions_1 = []; + classData.functions.map(function(method) { + var clonedNode = Object.assign( + {}, + node.members[1] + ); + clonedNode.name = ts.createIdentifier( + method.functionName + ); + functions_1.push(clonedNode); + }); + var updatedClass = ts.updateClassDeclaration( + node, + node.decorators, + node.modifiers, + node.name, + node.typeParameters, + node.heritageClauses, + ts.createNodeArray( + [node.members[0]].concat( + functions_1 + ) + ) + ); + return updatedClass; + } + return ts.visitEachChild(node, visit, context); + } + return ts.visitNode(rootNode, visit); + }; + }; + addIdentifiers = function(context) { + return function(rootNode) { + var count = 0; + function visit(node) { + if (ts.isMethodDeclaration(node)) { + var parameters = classData.functions[ + count + ].params.map(function(param) { + var paramNode = ts.createParameter( + undefined, + undefined, + undefined, + param.name + ); + if (param.optional) { + paramNode.initializer = ts.createIdentifier( + 'undefined' + ); + } + return paramNode; + }); + node.parameters = parameters; + } + if ( + ts.isIdentifier(node) && + dummyIdentifiers.includes(node.text) + ) { + var updatedIdentifier = void 0; + switch (node.text) { + case 'ClassName': + updatedIdentifier = ts.updateIdentifier( + ts.createIdentifier( + 'Linode_' + + classData.serviceName + ) + ); + break; + case 'SDKFunctionName': + updatedIdentifier = ts.updateIdentifier( + ts.createIdentifier( + classData.functions[count] + .SDKFunctionName + ) + ); + count++; + } + return updatedIdentifier; + } + if (ts.isCallExpression(node)) { + node.expression.forEachChild(function( + childNode + ) { + if ( + ts.isIdentifier(childNode) && + childNode.text === 'SDKFunctionName' + ) { + console.log( + classData.functions[count] + .params + ); + var args = classData.functions[ + count + ].params.map(function(param) { + return ts.createIdentifier( + param.name + ); + }); + node.arguments = args.concat( + node.arguments + ); + } + }); + } + return ts.visitEachChild(node, visit, context); + } + return ts.visitNode(rootNode, visit); + }; + }; + addComments = function(context) { + return function(rootNode) { + var count = 0; + function visit(node) { + if (ts.isClassDeclaration(node)) { + addMultiLineComment( + node, + 'This is an auto generated class, please do not change.' + ); + var comment = + '*\n\t* Class to create a ' + + classData.className + + ' object\n\t* @category Linode \n\t'; + addMultiLineComment(node, comment); + } + if (ts.isMethodDeclaration(node)) { + var parameters = classData.functions[ + count + ].params.map(function(param) { + var statment; + if (param.optional) { + if (param.type == 'TypeReference') + statment = + '* @param {' + + param.typeName + + '} ' + + param.name + + ' - Data required for ' + + classData.functions[count] + .SDKFunctionName; + else + statment = + '* @param {' + + param.type + + '} ' + + param.name + + ' - Data required for ' + + classData.functions[count] + .SDKFunctionName; + } else { + if (param.type == 'TypeReference') + statment = + '* @param {' + + param.typeName + + '} ' + + param.name + + ' - Data required for ' + + classData.functions[count] + .SDKFunctionName; + else + statment = + '* @param {' + + param.type + + '} ' + + param.name + + ' - Data required for ' + + classData.functions[count] + .SDKFunctionName; + } + return statment; + }); + console.log('parameters', parameters); + var comment = void 0; + if (parameters.length > 0) { + var paramStatments_1 = ''; + parameters.map(function(param) { + paramStatments_1 = paramStatments_1.concat( + paramStatments_1 === '' + ? '' + param + : '\n' + param + ); + }); + comment = + '*\n\t* Trigers the ' + + classData.functions[count] + .SDKFunctionName + + ' function of ' + + classData.className + + '\n\t' + + paramStatments_1 + + '\n\t* @returns {Promise<' + + classData.functions[count] + .SDKFunctionName + + 'Response>}\n\t'; + } else { + comment = + '*\n\t* Trigers the ' + + classData.functions[count] + .SDKFunctionName + + ' function of ' + + classData.className + + '\n\t* @returns {Promise<' + + classData.functions[count] + .SDKFunctionName + + 'Response>}\n\t'; + } + addMultiLineComment(node, comment); + count++; + } + return ts.visitEachChild(node, visit, context); + } + return ts.visitNode(rootNode, visit); + }; + }; + node = code.statements.find(function(stm) { + return ts.isClassDeclaration(stm); + }); + if (!classData.className || !classData.functions) { + throw new Error('Input is invalid'); + } + if ( + !node || + !node.members.some(function(member) { + return ts.isMethodDeclaration(member); + }) + ) { + throw new Error('Code is invalid'); + } + code = lodash_1.cloneDeep(code); + return [4 /*yield*/, runTransformation(code, addFunctions)]; + case 1: + result_1 = _a.sent(); + return [ + 4 /*yield*/, + runTransformation( + toSourceFile(result_1), + addIdentifiers + ), + ]; + case 2: + result_2 = _a.sent(); + return [ + 4 /*yield*/, + runTransformation(toSourceFile(result_2), addComments), + ]; + case 3: + result_3 = _a.sent(); + return [2 /*return*/, result_3]; + } + }); + }); +} +exports.transform = transform; diff --git a/generator/transformers/linode/transformer.ts b/generator/transformers/linode/transformer.ts new file mode 100644 index 00000000..3630b0ba --- /dev/null +++ b/generator/transformers/linode/transformer.ts @@ -0,0 +1,246 @@ +import { cloneDeep } from 'lodash'; +import * as ts from 'typescript'; + +const dummyIdentifiers = ['ClassName', 'SDKFunctionName']; + +const printer: ts.Printer = ts.createPrinter({ + newLine: ts.NewLineKind.LineFeed, + removeComments: false, +}); + +function addMultiLineComment(node, comment: string) { + ts.addSyntheticLeadingComment( + node, + ts.SyntaxKind.MultiLineCommentTrivia, + comment, + true + ); +} + +function runTransformation(sourceCode, transformMethod): Promise { + return new Promise((resolve, reject) => { + try { + const result = ts.transform(sourceCode, [transformMethod]); + const transformedNodes = result.transformed[0]; + const output = printer.printNode( + ts.EmitHint.SourceFile, + transformedNodes, + sourceCode + ); + resolve(output); + } catch (error) { + reject(error); + } + }); +} + +function toSourceFile(sourceCode: string): ts.SourceFile { + return ts.createSourceFile( + 'dummyClass.js', + sourceCode, + ts.ScriptTarget.Latest, + true + ); +} + +export async function transform( + code: ts.SourceFile, + classData: any +): Promise { + const addFunctions = ( + context: ts.TransformationContext + ) => (rootNode: T) => { + function visit(node: ts.Node): ts.Node { + if (ts.isClassDeclaration(node)) { + const functions: any = []; + classData.functions.map(method => { + const clonedNode = Object.assign({}, node.members[1]); + clonedNode.name = ts.createIdentifier(method.functionName); + functions.push(clonedNode); + }); + + const updatedClass = ts.updateClassDeclaration( + node, + node.decorators, + node.modifiers, + node.name, + node.typeParameters, + node.heritageClauses, + ts.createNodeArray([node.members[0]].concat(functions)) + ); + return updatedClass; + } + return ts.visitEachChild(node, visit, context); + } + return ts.visitNode(rootNode, visit); + }; + + // const addIdentifiers = ( + // context: ts.TransformationContext + // ) => (rootNode: T) => { + // let count = 0; + // }; + + const addIdentifiers = ( + context: ts.TransformationContext + ) => (rootNode: T) => { + let count = 0; + function visit(node: ts.Node): ts.Node { + if (ts.isMethodDeclaration(node)) { + const parameters = classData.functions[count].params.map( + param => { + const paramNode = ts.createParameter( + undefined, + undefined, + undefined, + param.name + ); + + if (param.optional) { + paramNode.initializer = ts.createIdentifier( + 'undefined' + ); + } + + return paramNode; + } + ); + + node.parameters = parameters; + } + + if (ts.isIdentifier(node) && dummyIdentifiers.includes(node.text)) { + let updatedIdentifier; + + switch (node.text) { + case 'ClassName': + updatedIdentifier = ts.updateIdentifier( + ts.createIdentifier( + 'Linode_' + classData.serviceName + ) + ); + break; + case 'SDKFunctionName': + updatedIdentifier = ts.updateIdentifier( + ts.createIdentifier( + classData.functions[count].SDKFunctionName + ) + ); + count++; + } + + return updatedIdentifier; + } + + if (ts.isCallExpression(node)) { + node.expression.forEachChild(childNode => { + if ( + ts.isIdentifier(childNode) && + childNode.text === 'SDKFunctionName' + ) { + console.log(classData.functions[count].params); + + const args = classData.functions[count].params.map( + param => ts.createIdentifier(param.name) + ); + node.arguments = args.concat(node.arguments); + } + }); + } + + return ts.visitEachChild(node, visit, context); + } + return ts.visitNode(rootNode, visit); + }; + + const addComments = ( + context: ts.TransformationContext + ) => (rootNode: T) => { + let count = 0; + function visit(node: ts.Node): ts.Node { + if (ts.isClassDeclaration(node)) { + addMultiLineComment( + node, + 'This is an auto generated class, please do not change.' + ); + const comment = `* + * Class to create a ${classData.className} object + * @category Linode + `; + addMultiLineComment(node, comment); + } + + if (ts.isMethodDeclaration(node)) { + const parameters = classData.functions[count].params.map( + param => { + let statment; + + if (param.optional) { + if (param.type == 'TypeReference') + statment = `* @param {${param.typeName}} ${param.name} - Data required for ${classData.functions[count].SDKFunctionName}`; + else + statment = `* @param {${param.type}} ${param.name} - Data required for ${classData.functions[count].SDKFunctionName}`; + } else { + if (param.type == 'TypeReference') + statment = `* @param {${param.typeName}} ${param.name} - Data required for ${classData.functions[count].SDKFunctionName}`; + else + statment = `* @param {${param.type}} ${param.name} - Data required for ${classData.functions[count].SDKFunctionName}`; + } + return statment; + } + ); + console.log('parameters', parameters); + + let comment; + if (parameters.length > 0) { + let paramStatments: string = ''; + parameters.map(param => { + paramStatments = paramStatments.concat( + paramStatments === '' ? `${param}` : `\n${param}` + ); + }); + + comment = `* + * Trigers the ${classData.functions[count].SDKFunctionName} function of ${classData.className} + ${paramStatments} + * @returns {Promise<${classData.functions[count].SDKFunctionName}Response>} + `; + } else { + comment = `* + * Trigers the ${classData.functions[count].SDKFunctionName} function of ${classData.className} + * @returns {Promise<${classData.functions[count].SDKFunctionName}Response>} + `; + } + + addMultiLineComment(node, comment); + count++; + } + + return ts.visitEachChild(node, visit, context); + } + return ts.visitNode(rootNode, visit); + }; + + const node: any = code.statements.find(stm => ts.isClassDeclaration(stm)); + + if (!classData.className || !classData.functions) { + throw new Error('Input is invalid'); + } + + if (!node || !node.members.some(member => ts.isMethodDeclaration(member))) { + throw new Error('Code is invalid'); + } + + code = cloneDeep(code); + + const result_1 = await runTransformation(code, addFunctions); + const result_2 = await runTransformation( + toSourceFile(result_1), + addIdentifiers + ); + const result_3 = await runTransformation( + toSourceFile(result_2), + addComments + ); + return result_3; +}