Skip to content

Commit

Permalink
Further refactoring to satisfy codebeat A-grade requirements
Browse files Browse the repository at this point in the history
  • Loading branch information
nktnet committed Oct 11, 2023
1 parent bc52c9b commit d2997f7
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 41 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"type": "git",
"url": "https://github.com/nktnet1/jewire"
},
"version": "0.0.3",
"version": "0.0.4",
"files": [
"dist"
],
Expand Down
22 changes: 15 additions & 7 deletions src/clone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,14 @@ const functionClone = <T extends (...args: any[]) => any>(fn: T, clone: CloneFn)
* @param target object instance to decorate methods around
*/
function decorateClassMethodClone(target: any) {
const decorateMethod = (obj: Record<string, any>, key: string | symbol) => {
function decorateClassMethodClone(target: any, clone: CloneFn) {
/**
* Ensure that the return values of all objects are cloned
*
* @param obj object whose method return values need to be cloned
* @param key name of the method whose return values will be cloned
*/
const decorateMethod = (obj: Record<string, any>, key: string | symbol): void => {
const descriptor = Reflect.getOwnPropertyDescriptor(obj, key);
/* istanbul ignore next */
if (!descriptor?.configurable) {
Expand All @@ -78,7 +84,7 @@ function decorateClassMethodClone(target: any) {
const { value } = descriptor;
if (typeof value === 'function' && value !== target) {
descriptor.value = function (...args: any[]) {
return entityClone(value.apply(this, args));
return entityClone(value.apply(this, args), clone);
};
Object.defineProperty(obj, key, descriptor);
}
Expand Down Expand Up @@ -107,13 +113,15 @@ function decorateClassMethodClone(target: any) {
* @throws {Error} - An unsupported data type is encountered
*/
/* istanbul ignore next */
const classClone: CloneFn = <T>(obj: T): T => {
const classClone = <T>(obj: T, objClone: CloneFn): T => {
if (obj === null || typeof obj !== 'object') {
return decorateClassMethodClone(obj as any);
return decorateClassMethodClone(obj as any, objClone);
}
const props = Object.getOwnPropertyDescriptors(obj);
for (const prop in props) {
props[prop].value = classClone(props[prop].value);
if (Object.prototype.hasOwnProperty.call(props, prop)) {
props[prop].value = classClone(props[prop].value, objClone);
}
}
return Object.create(
Object.getPrototypeOf(obj),
Expand All @@ -131,7 +139,7 @@ const classClone: CloneFn = <T>(obj: T): T => {
const functionOrClassClone = (functionOrClass: any, objClone: CloneFn) =>
isFunction(functionOrClass)
? functionClone(functionOrClass, objClone)
: classClone(functionOrClass);
: classClone(functionOrClass, objClone);

/**
* Clones an entity for use with Jest expect.toStrictEqual
Expand Down
51 changes: 30 additions & 21 deletions src/files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import fs from 'fs';
import path from 'path';
import { parse } from 'meriyah';
import { VALID_FILE_EXTENSIONS } from './config';
import { ASTProgram, HiddenExportInfo } from './types';
import { ASTProgram, HiddenExportInfo, Symbols } from './types';

/**
* Get the file path of the caller function.
Expand Down Expand Up @@ -51,6 +51,33 @@ export const findModuleFile = (modulePath: string, basePath: string): string =>
return filePath;
};

/**
* Retrieves all symbols from the given AST program
*
* @param ast Abstract Syntaxt Tree from parser
* @returns symbols consisting of variables, functions and classes
*/
const retrieveSymbolsFromAst = (ast: ASTProgram): Symbols => {
const variables: string[] = [];
const functions: string[] = [];
const classes: string[] = [];

ast.body.forEach((node) => {
if (node.type === 'FunctionDeclaration' && node.id !== null) {
functions.push(node.id.name);
} else if (node.type === 'VariableDeclaration') {
node.declarations.forEach((declaration) => {
if (declaration.id.type === 'Identifier') {
variables.push(declaration.id.name);
}
});
} else if (node.type === 'ClassDeclaration' && node.id !== null) {
classes.push(node.id.name);
}
});
return { variables, functions, classes };
};

/**
* Retrieves the name of all global variables/functions/classes, including
* those not exported in the file
Expand Down Expand Up @@ -82,24 +109,6 @@ Please double check the file:
for errors: ${error}`
);
}

const variables: string[] = [];
const functions: string[] = [];
const classes: string[] = [];

ast.body.forEach((node) => {
if (node.type === 'FunctionDeclaration' && node.id !== null) {
functions.push(node.id.name);
} else if (node.type === 'VariableDeclaration') {
node.declarations.forEach((declaration) => {
if (declaration.id.type === 'Identifier') {
variables.push(declaration.id.name);
}
});
} else if (node.type === 'ClassDeclaration' && node.id !== null) {
classes.push(node.id.name);
}
});

return { exports: { functions, variables, classes }, ast, code };
const symbols = retrieveSymbolsFromAst(ast);
return { symbols, ast, code };
};
8 changes: 4 additions & 4 deletions src/jewire.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ const jewire = (relativePath: string, options: Options = {}): Record<string, any
options.basePath ?? path.dirname(getCallerFilePath())
);
const hiddenExportInfo = getModuleHiddenExports(filePath);
const hiddenExports = Object.values(hiddenExportInfo.exports).flat();
const hiddenExports = Object.values(hiddenExportInfo.symbols).flat();
const rewireContext = rewire(filePath);
const entities: Record<string, any> = {};

for (const hE of hiddenExports) {
const entity = rewireContext.__get__(hE);
entities[hE] = entityClone(entity, options.objectClone);
for (const hiddenExport of hiddenExports) {
const entity = rewireContext.__get__(hiddenExport);
entities[hiddenExport] = entityClone(entity, options.objectClone);
}

if (options.callback) {
Expand Down
12 changes: 7 additions & 5 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import rewire from 'rewire';

export type { ASTProgram };

export interface Symbols {
functions: string[];
variables: string[];
classes: string[];
}

export interface HiddenExportInfo {
exports: {
functions: string[];
variables: string[];
classes: string[];
}
symbols: Symbols;
ast: ASTProgram;
code: string;
}
Expand Down
2 changes: 1 addition & 1 deletion tests/options/options.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ test('Using different objectClone', () => {
test('callback function upon success', () => {
jewire('../variables/variables', {
callback: (_, hE) => {
expect(hE.exports.variables).toStrictEqual([
expect(hE.symbols.variables).toStrictEqual([
'numberFive', 'array', 'shallowObject', 'arrayOfObjects', 'deeplyNestedObject',
]);
}
Expand Down

0 comments on commit d2997f7

Please sign in to comment.