From 6f444444570a3c3c7a639d832313882f487d5c5c Mon Sep 17 00:00:00 2001 From: Peter van Vliet Date: Thu, 26 Sep 2024 09:52:01 +0200 Subject: [PATCH] #296: refactored analysis tests --- packages/analysis/src/static/index.ts | 14 ++ .../models/ReflectionClass.fixture.ts | 28 --- .../models/ReflectionModule.fixture.ts | 36 ---- .../models/ReflectionScope.fixture.ts | 32 --- .../test/_fixtures/parser/ItemList.fixture.ts | 23 -- .../test/_fixtures/parser/Parser.fixture.ts | 204 ------------------ .../test/{ => dynamic}/Reflector.spec.ts | 70 +++--- .../fixtures/classes.fixture.ts} | 29 +-- .../dynamic/fixtures/functions.fixture.ts | 20 ++ .../analysis/test/dynamic/fixtures/index.ts | 5 + .../test/dynamic/fixtures/modules.fixture.ts | 16 ++ .../test/dynamic/fixtures/objects.fixture.ts | 10 + ...eflectionClass.spec.ts => ESClass.spec.ts} | 45 ++-- .../analysis/test/models/ESModule.spec.ts | 117 ++++++++++ ...eflectionScope.spec.ts => ESScope.spec.ts} | 111 +++++----- .../test/models/ReflectionModule.spec.ts | 121 ----------- .../test/models/fixtures/esClass.fixture.ts | 20 ++ .../test/models/fixtures/esModule.fixture.ts | 25 +++ .../test/models/fixtures/esScope.fixture.ts | 19 ++ .../analysis/test/models/fixtures/index.ts | 4 + .../analysis/test/parser/ItemList.spec.ts | 140 ------------ .../test/{parser => static}/Lexer.spec.ts | 13 +- .../test/{parser => static}/Parser.spec.ts | 188 ++++++++-------- .../test/static/fixtures/classes.fixture.ts | 53 +++++ .../fixtures/code.fixture.ts} | 4 +- .../static/fixtures/declarations.fixture.ts | 17 ++ .../test/static/fixtures/exports.fixture.ts | 15 ++ .../test/static/fixtures/functions.fixture.ts | 25 +++ .../test/static/fixtures/imports.fixture.ts | 13 ++ .../analysis/test/static/fixtures/index.ts | 9 + .../test/static/fixtures/modules.fixture.ts | 69 ++++++ .../test/static/fixtures/values.fixture.ts | 10 + 32 files changed, 664 insertions(+), 841 deletions(-) delete mode 100644 packages/analysis/test/_fixtures/models/ReflectionClass.fixture.ts delete mode 100644 packages/analysis/test/_fixtures/models/ReflectionModule.fixture.ts delete mode 100644 packages/analysis/test/_fixtures/models/ReflectionScope.fixture.ts delete mode 100644 packages/analysis/test/_fixtures/parser/ItemList.fixture.ts delete mode 100644 packages/analysis/test/_fixtures/parser/Parser.fixture.ts rename packages/analysis/test/{ => dynamic}/Reflector.spec.ts (77%) rename packages/analysis/test/{_fixtures/Reflector.fixture.ts => dynamic/fixtures/classes.fixture.ts} (63%) create mode 100644 packages/analysis/test/dynamic/fixtures/functions.fixture.ts create mode 100644 packages/analysis/test/dynamic/fixtures/index.ts create mode 100644 packages/analysis/test/dynamic/fixtures/modules.fixture.ts create mode 100644 packages/analysis/test/dynamic/fixtures/objects.fixture.ts rename packages/analysis/test/models/{ReflectionClass.spec.ts => ESClass.spec.ts} (57%) create mode 100644 packages/analysis/test/models/ESModule.spec.ts rename packages/analysis/test/models/{ReflectionScope.spec.ts => ESScope.spec.ts} (58%) delete mode 100644 packages/analysis/test/models/ReflectionModule.spec.ts create mode 100644 packages/analysis/test/models/fixtures/esClass.fixture.ts create mode 100644 packages/analysis/test/models/fixtures/esModule.fixture.ts create mode 100644 packages/analysis/test/models/fixtures/esScope.fixture.ts create mode 100644 packages/analysis/test/models/fixtures/index.ts delete mode 100644 packages/analysis/test/parser/ItemList.spec.ts rename packages/analysis/test/{parser => static}/Lexer.spec.ts (94%) rename packages/analysis/test/{parser => static}/Parser.spec.ts (82%) create mode 100644 packages/analysis/test/static/fixtures/classes.fixture.ts rename packages/analysis/test/{_fixtures/parser/Lexer.fixture.ts => static/fixtures/code.fixture.ts} (95%) create mode 100644 packages/analysis/test/static/fixtures/declarations.fixture.ts create mode 100644 packages/analysis/test/static/fixtures/exports.fixture.ts create mode 100644 packages/analysis/test/static/fixtures/functions.fixture.ts create mode 100644 packages/analysis/test/static/fixtures/imports.fixture.ts create mode 100644 packages/analysis/test/static/fixtures/index.ts create mode 100644 packages/analysis/test/static/fixtures/modules.fixture.ts create mode 100644 packages/analysis/test/static/fixtures/values.fixture.ts diff --git a/packages/analysis/src/static/index.ts b/packages/analysis/src/static/index.ts index 78b32d4c..957dc6a1 100644 --- a/packages/analysis/src/static/index.ts +++ b/packages/analysis/src/static/index.ts @@ -1,2 +1,16 @@ +export * from './definitions/Comment'; +export * from './definitions/Divider'; +export * from './definitions/Empty'; +export * from './definitions/Group'; +export * from './definitions/Keyword'; +export * from './definitions/List'; +export * from './definitions/Literal'; +export * from './definitions/Operator'; +export * from './definitions/Punctuation'; +export * from './definitions/Scope'; +export * from './definitions/TokenType'; +export * from './definitions/Whitespace'; + +export { default as Lexer } from './Lexer'; export { default as Parser } from './Parser'; diff --git a/packages/analysis/test/_fixtures/models/ReflectionClass.fixture.ts b/packages/analysis/test/_fixtures/models/ReflectionClass.fixture.ts deleted file mode 100644 index 465f74f2..00000000 --- a/packages/analysis/test/_fixtures/models/ReflectionClass.fixture.ts +++ /dev/null @@ -1,28 +0,0 @@ - -import ReflectionScope from '../../../src/models/ReflectionScope'; -import ReflectionField from '../../../src/models/ReflectionField'; -import ReflectionExpression from '../../../src/models/ReflectionExpression'; -import ReflectionFunction from '../../../src/models/ReflectionFunction'; -import ReflectionClass from '../../../src/models/ReflectionClass'; -import ReflectionGetter from '../../../src/models/ReflectionGetter'; -import ReflectionSetter from '../../../src/models/ReflectionSetter'; -import ReflectionDeclaration from '../../../src/models/ReflectionDeclaration'; - -const members = -[ - new ReflectionDeclaration('name', new ReflectionExpression('"Peter"'), false, true), - new ReflectionDeclaration('age', undefined, false, true), - new ReflectionDeclaration('length', undefined, false, false), - new ReflectionDeclaration('secret', undefined, false, true), - new ReflectionFunction('constructor', [new ReflectionField('age', undefined)], 'this.#age = age;'), - new ReflectionGetter('name', [], 'return this.#name;'), - new ReflectionGetter('age', [], 'return this.#age;'), - new ReflectionSetter('age', [new ReflectionField('age', undefined)], 'this.#age = age;'), - new ReflectionFunction('secretStuff', [], '', false, false, true), - new ReflectionFunction('toString', [], 'return `${this.#name} (${this.#age})`'), -]; - -const scope = new ReflectionScope(members); -const reflectionClass = new ReflectionClass('Person', undefined, scope); - -export { reflectionClass }; diff --git a/packages/analysis/test/_fixtures/models/ReflectionModule.fixture.ts b/packages/analysis/test/_fixtures/models/ReflectionModule.fixture.ts deleted file mode 100644 index de4515ca..00000000 --- a/packages/analysis/test/_fixtures/models/ReflectionModule.fixture.ts +++ /dev/null @@ -1,36 +0,0 @@ - -import ReflectionScope from '../../../src/models/ReflectionScope'; -import ReflectionModule from '../../../src/models/ReflectionModule'; -import ReflectionImport from '../../../src/models/ReflectionImport'; -import ReflectionAlias from '../../../src/models/ReflectionAlias'; -import ReflectionField from '../../../src/models/ReflectionField'; -import ReflectionExpression from '../../../src/models/ReflectionExpression'; -import ReflectionFunction from '../../../src/models/ReflectionFunction'; -import ReflectionClass from '../../../src/models/ReflectionClass'; -import ReflectionExport from '../../../src/models/ReflectionExport'; -import ReflectionGenerator from '../../../src/models/ReflectionGenerator'; -import ReflectionDeclaration from '../../../src/models/ReflectionDeclaration'; - -const members = -[ - new ReflectionImport([new ReflectionAlias('default', 'Person')], './Person.js'), - new ReflectionDeclaration('peter', new ReflectionExpression('new Person("Peter")')), - new ReflectionDeclaration('bas', new ReflectionExpression('new Person("Bas")')), - new ReflectionFunction('createJohn', [], 'return new Person("John")'), - new ReflectionFunction('sum', [new ReflectionField('a', undefined), new ReflectionField('b', undefined)], 'return a + b'), - new ReflectionGenerator('generateNumbers', [new ReflectionField('count', undefined)], 'for (let i = 0; i < count; i++) yield i;'), - new ReflectionGenerator('createJohn', [], 'yield new Person("John")'), - new ReflectionClass('Customer', 'Person', new ReflectionScope([])), - new ReflectionClass('Order', undefined, new ReflectionScope([])), - new ReflectionExport([ - new ReflectionAlias('sum', 'default'), - new ReflectionAlias('peter', 'peter'), - new ReflectionAlias('Customer', 'Customer'), - new ReflectionAlias('generateNumbers', 'generateNumbers') - ], undefined) -]; - -const scope = new ReflectionScope(members); -const reflectionModule = new ReflectionModule(scope); - -export { reflectionModule }; diff --git a/packages/analysis/test/_fixtures/models/ReflectionScope.fixture.ts b/packages/analysis/test/_fixtures/models/ReflectionScope.fixture.ts deleted file mode 100644 index 5394a076..00000000 --- a/packages/analysis/test/_fixtures/models/ReflectionScope.fixture.ts +++ /dev/null @@ -1,32 +0,0 @@ - -import ReflectionScope from '../../../src/models/ReflectionScope'; -import ReflectionField from '../../../src/models/ReflectionField'; -import ReflectionExpression from '../../../src/models/ReflectionExpression'; -import ReflectionFunction from '../../../src/models/ReflectionFunction'; -import ReflectionClass from '../../../src/models/ReflectionClass'; -import ReflectionGetter from '../../../src/models/ReflectionGetter'; -import ReflectionSetter from '../../../src/models/ReflectionSetter'; -import ReflectionImport from '../../../src/models/ReflectionImport'; -import ReflectionAlias from '../../../src/models/ReflectionAlias'; -import ReflectionExport from '../../../src/models/ReflectionExport'; -import ReflectionGenerator from '../../../src/models/ReflectionGenerator'; -import ReflectionDeclaration from '../../../src/models/ReflectionDeclaration'; - -const members = -[ - new ReflectionImport([new ReflectionAlias('default', 'Person')], './Person.js'), - new ReflectionDeclaration('name', new ReflectionExpression('"john"'), false, true), - new ReflectionDeclaration('age', new ReflectionExpression('42'), false, true), - new ReflectionFunction('createJohn', [], '{ return new Person("John") }'), - new ReflectionFunction('sum', [new ReflectionField('a', undefined), new ReflectionField('b', undefined)], 'return a + b'), - new ReflectionGetter('name', [], 'return this.#name;'), - new ReflectionGetter('age', [], 'return this.#age;'), - new ReflectionSetter('age', [new ReflectionField('age', undefined)], 'this.#age = age;'), - new ReflectionClass('Customer', 'Person', new ReflectionScope([])), - new ReflectionGenerator('createJohn', [], 'yield new Person("John")'), - new ReflectionExport([new ReflectionAlias('Customer', 'Customer'), new ReflectionAlias('sum', 'default')], undefined) -]; - -const reflectionScope = new ReflectionScope(members); - -export { reflectionScope }; diff --git a/packages/analysis/test/_fixtures/parser/ItemList.fixture.ts b/packages/analysis/test/_fixtures/parser/ItemList.fixture.ts deleted file mode 100644 index 2ac69dd8..00000000 --- a/packages/analysis/test/_fixtures/parser/ItemList.fixture.ts +++ /dev/null @@ -1,23 +0,0 @@ - -import ItemList from '../../../src/parser/ItemList'; - -const items: string[] = -[ - "a", - "b", - "c", - "d", - "e", - "f", - "g", - "h", - "i", - "j" -]; - -function createList(): ItemList -{ - return new ItemList(items); -} - -export { createList }; diff --git a/packages/analysis/test/_fixtures/parser/Parser.fixture.ts b/packages/analysis/test/_fixtures/parser/Parser.fixture.ts deleted file mode 100644 index 86a928ed..00000000 --- a/packages/analysis/test/_fixtures/parser/Parser.fixture.ts +++ /dev/null @@ -1,204 +0,0 @@ - -const VALUES = -{ - ARRAY: '[1, "foo", false, new Person("Peter", 42), { a: 1, b: 2 }]', - OBJECT: '{ key1: "value1", "key2": new Person().toString() }', - EXPRESSION:'new Number(Math.ceil(Math.random()) + 10).toString();', - EXPRESSION_GROUP: '(a + b) * c', - IF_ELSE: 'if (true) { return "value1"; } else { return "value2"; }', - TRY_CATCH_FINALLY: 'try { sum(1, 2); } catch (error) { console.error(error); } finally { console.log("finally"); }' -}; - -const IMPORTS = -{ - LOAD: "import 'module'", - IMPORT: "import { member } from 'module'", - IMPORT_AS: "import { member as alias } from 'module'", - IMPORT_ALL: "import * as name from 'module'", - IMPORT_DEFAULT: "import name from 'module'", - IMPORT_DEFAULT_MEMBER: "import name, { member } from 'module'", - IMPORT_DEFAULT_MEMBER_AS: "import name, { member as alias } from 'module'", - IMPORT_MULTIPLE_MEMBERS_AS: "import { name, member as alias } from 'module'", - IMPORT_DYNAMIC: "import('module')", -}; - -const EXPORTS = -{ - EXPORT: "export { member }", - EXPORT_AS: "export { member as alias }", - EXPORT_DEFAULT: "export default name", - EXPORT_MULTIPLE: "export { name, member }", - EXPORT_MULTIPLE_AS: "export { name, member as alias }", - EXPORT_CLASS_DECLARATION: "export class name {}", - EXPORT_FIELD_DECLARATION: "export const name = 'value'", - EXPORT_FUNCTION_DECLARATION: "export function name() {}", - EXPORT_ASYNC_FUNCTION_DECLARATION: "export async function name() {}", - REEXPORT_ALL: "export * from 'module'", - REEXPORT_MEMBER: "export { member } from 'module'", -}; - -const DECLARATIONS = -{ - EMPTY: "let name;", - CONST: "const name = 'const';", - LET: "let name = 'let';", - VAR: "var name = 'var';", - MULTIPLE: "let name1 = (1 + 2) * 3, name2, name3 = 'foo';", - EXPRESSION: `const number = new Number(Math.ceil(Math.random()) + 10).toString();`, - ARRAY: "const array = [ 'value1', 'value2' ];", - OBJECT: "const object = { key1: 'value1', key2: 'value2' };", - REGEX: "const regex = /regex/g;", - DESTRUCTURING_ARRAY: "const [value1, value2 = true] = array;", - DESTRUCTURING_OBJECT: "const {key1, key2 = false} = object;", - KEYWORD_AS_NAME: "const as = 'value';", - KEYWORD_AS_VALUE: "const alias = as;" -}; - -const FUNCTIONS = -{ - DECLARATION: "function name() {}", - ASYNC_DECLARATION: "async function name() {}", - EXPRESSION: "const name = function() {}", - ASYNC_EXPRESSION: "const name = async function() {}", - ARROW: "const name = () => {}", - ARROW_EXPRESSION: "const name = () => 'value';", - ARROW_ARGUMENT: 'const name = arg => arg;', - ASYNC_ARROW: "const name = async () => {}", - GENERATOR: "function* name() {}", - ASYNC_GENERATOR: "async function* name() {}", - EXPRESSION_GENERATOR: "const name = function*() {}", - ASYNC_EXPRESSION_GENERATOR: "const name = async function*() {}", - PARAMETERS: "function name(param1, param2) {}", - DEFAULT_PARAMETERS: "function name(param1 = 'value1', param2 = true) {}", - REST_PARAMETERS: "function name(...param1) {}", - DESTRUCTURING_PARAMETERS: "function name({ param1, param2 }, [ param3, param4 ]) {}", - DESTRUCTURING_DEFAULT_PARAMETERS: "function name({ param1 = 'value1', param2 = true }, [ param3 = 'value3', param4 = true ]) {}", - DESTRUCTURING_REST_PARAMETERS: "function name({ param1, param2 }, [ param3, ...param4 ]) {}", - SIMPLE_BODY: "function name() { return 'value'; }", - BLOCK_BODY: "function name() { if (true) { return 'value'; } }", - KEYWORD_AS_NAME: "function as() {}" -}; - -const CLASSES = -{ - DECLARATION: "class Name {}", - EXTENDS: "class Name extends Parent {}", - EXPRESSION: "const name = class {}", - MEMBERS: `class Name -{ - #field1 = 'value1'; - field2; - - static #field3 = "value3"; - static field4; - - constructor(field1, ...field2) - { - this.#field1 = field1; - this.field2 = field2; - } - - get #getter1() { return field1; } - - get getter2() { return field2; } - - static get #getter3() { return field3; } - - static get getter4() { return field4; } - - set #setter1(value) { this.#field1 = value; } - - set setter2(value) { this.#field2 = value; } - - static set #setter3(value) { this.#field3 = value; } - - static set setter4(value) { this.#field4 = value; } - - method1() { return this.#field1; } - - async method2() { return this.#field1; } - - static method3() { return this.#field1; } - - static async method4() { return this.#field1; } - - #method5() { return this.#field1; } - - *generator1() { yield 1; } - - async *generator2() { yield 1; } - - static async *generator3() { yield 1; } -}` -}; - -const MODULES = -{ - TERMINATED: -` -import { member } from 'module'; -import { member as alias } from 'module2'; - -const name = 'Peter' + ' van ' + 'Vliet'; - -export default function sum(a, b) { return a + b; } - -[1, 2, 3, 4, 5].sort((a, b) => a - b); - -try { sum(1, 2); } catch (error) { console.error(error); } - -export class Person -{ - #name; - #age; - - constructor(name, age) - { - this.#name = name; - this.#age = age; - } -} - -const peter = new Person(name, 42); - -async function async() { } -const a = async; -const b = async () => {}; - -const as = 12; -export { as as hi }; - -export { name, peter }; -`, - UNTERMINATED: -` - import { member } from 'module' - import { member as alias } from 'module2' - - const name = 'Peter' + ' van ' + 'Vliet' - - export default function sum(a, b) { return a + b } - - [1, 2, 3, 4, 5].sort((a, b) => a - b) - - try { sum(1, 2) } catch (error) { console.error(error) } - - export class Person - { - #name - #age - - constructor(name, age) - { - this.#name = name - this.#age = age - } - } - - const peter = new Person(name, 42) - - export { name, peter } -` -}; - -export { VALUES, IMPORTS, EXPORTS, DECLARATIONS, FUNCTIONS, CLASSES, MODULES }; diff --git a/packages/analysis/test/Reflector.spec.ts b/packages/analysis/test/dynamic/Reflector.spec.ts similarity index 77% rename from packages/analysis/test/Reflector.spec.ts rename to packages/analysis/test/dynamic/Reflector.spec.ts index e3009232..8bead38a 100644 --- a/packages/analysis/test/Reflector.spec.ts +++ b/packages/analysis/test/dynamic/Reflector.spec.ts @@ -1,17 +1,10 @@ import { describe, expect, it } from 'vitest'; -import ReflectionExpression from '../src/models/ReflectionExpression'; -import ReflectionField from '../src/models/ReflectionField'; -import Reflector from '../src/Reflector'; +import { ESExpression, ESField } from '../../src/models'; +import { Reflector } from '../../src/dynamic'; -import -{ - Person, CustomError, - johnDoe, janeDoe, plainError, customError, - optionalFunction, - testModule -} from './_fixtures/Reflector.fixture'; +import { CLASSES, FUNCTIONS, OBJECTS, MODULES } from './fixtures'; const reflector = new Reflector(); @@ -21,7 +14,7 @@ describe('Reflector', () => { it('should get all members from a module', () => { - const reflectionModule = reflector.fromModule(testModule, false); + const reflectionModule = reflector.fromModule(MODULES.MIXED, false); const members = reflectionModule.members; expect(members.length).toBe(3); @@ -36,7 +29,7 @@ describe('Reflector', () => const classes = reflectionModule.classes; expect(classes.length).toBe(1); - expect(classes[0].name).toBe('Person'); + expect(classes[0].name).toBe('Child'); }); }); @@ -44,8 +37,8 @@ describe('Reflector', () => { it('should get class reflection model without parent members from a class', () => { - const reflectionClass = reflector.fromClass(Person, false); - expect(reflectionClass.name).toBe('Person'); + const reflectionClass = reflector.fromClass(CLASSES.Child, false); + expect(reflectionClass.name).toBe('Child'); const members = reflectionClass.members; expect(members.length).toBe(9); @@ -74,8 +67,8 @@ describe('Reflector', () => it('should get class reflection model with parent members from a class', () => { - const reflectionClass = reflector.fromClass(Person, true); - expect(reflectionClass.name).toBe('Person'); + const reflectionClass = reflector.fromClass(CLASSES.Child, true); + expect(reflectionClass.name).toBe('Child'); const members = reflectionClass.members; expect(members.length).toBe(11); @@ -124,7 +117,7 @@ describe('Reflector', () => it('should get class reflection model from a class with function based parent class', () => { - const reflectionClass = reflector.fromClass(CustomError, true); + const reflectionClass = reflector.fromClass(CLASSES.CustomError, true); expect(reflectionClass.name).toBe('CustomError'); const members = reflectionClass.members; @@ -151,8 +144,8 @@ describe('Reflector', () => { it('should get class reflection model without parent members from an object', () => { - const reflectionClass = reflector.fromObject(johnDoe, false); - expect(reflectionClass.name).toBe('Person'); + const reflectionClass = reflector.fromObject(OBJECTS.CLASS, false); + expect(reflectionClass.name).toBe('Child'); const members = reflectionClass.members; expect(members.length).toBe(9); @@ -160,8 +153,8 @@ describe('Reflector', () => it('should get class reflection model with parent members from an object', () => { - const reflectionClass = reflector.fromObject(johnDoe, true); - expect(reflectionClass.name).toBe('Person'); + const reflectionClass = reflector.fromObject(OBJECTS.CLASS, true); + expect(reflectionClass.name).toBe('Child'); const members = reflectionClass.members; expect(members.length).toBe(11); @@ -169,7 +162,7 @@ describe('Reflector', () => it('should get class reflection model from a function based class object', () => { - const reflectionClass = reflector.fromObject(plainError, true); + const reflectionClass = reflector.fromObject(OBJECTS.ERROR, true); expect(reflectionClass.name).toBe('Error'); const members = reflectionClass.members; @@ -178,7 +171,7 @@ describe('Reflector', () => it('should get class reflection model from a a class object with function based parent class', () => { - const reflectionClass = reflector.fromObject(customError, true); + const reflectionClass = reflector.fromObject(OBJECTS.CUSTOM_ERROR, true); expect(reflectionClass.name).toBe('CustomError'); const members = reflectionClass.members; @@ -190,25 +183,25 @@ describe('Reflector', () => { it('should get function reflection model', () => { - const functionFunction = reflector.fromFunction(optionalFunction); + const functionFunction = reflector.fromFunction(FUNCTIONS.OPTIONAL_ARGS); expect(functionFunction.name).toBe('optionalFunction'); expect(functionFunction.body).toBe('{ return a + b + c ; }'); const parameters = functionFunction.parameters; expect(parameters.length).toBe(3); - const first = parameters[0] as ReflectionField; + const first = parameters[0] as ESField; expect(first.name).toBe('a'); expect(first.value).toBe(undefined); - const second = parameters[1] as ReflectionField; + const second = parameters[1] as ESField; expect(second.name).toBe('b'); - expect(second.value).toBeInstanceOf(ReflectionExpression); - expect(second.value?.definition).toBe('new Person ( 1 , "Jane" , "Doe" , 42 )'); + expect(second.value).toBeInstanceOf(ESExpression); + expect(second.value?.definition).toBe('new Child ( 1 , "Jane" , "Doe" , 42 )'); - const third = parameters[2] as ReflectionField; + const third = parameters[2] as ESField; expect(third.name).toBe('c'); - expect(third.value).toBeInstanceOf(ReflectionExpression); + expect(third.value).toBeInstanceOf(ESExpression); expect(third.value?.definition).toBe('0'); }); }); @@ -217,8 +210,9 @@ describe('Reflector', () => { it('should get an instance class of a class', () => { - const peter = reflector.createInstance(Person, [1, 'Peter', 'van Vliet', 24]) as Person; - expect(peter).toBeInstanceOf(Person); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const peter = reflector.createInstance(CLASSES.Child, [1, 'Peter', 'van Vliet', 24]) as any; + expect(peter).toBeInstanceOf(CLASSES.Child); expect(peter.id).toBe(1); expect(peter.fullName).toBe('Peter van Vliet'); expect(peter.age).toBe(24); @@ -229,13 +223,13 @@ describe('Reflector', () => { it('should detect a class object', () => { - const result = reflector.isClassObject(johnDoe); + const result = reflector.isClassObject(OBJECTS.CLASS); expect(result).toBe(true); }); it('should detect a non class object', () => { - const result = reflector.isClassObject(janeDoe); + const result = reflector.isClassObject(OBJECTS.PLAIN); expect(result).toBe(false); }); }); @@ -244,9 +238,9 @@ describe('Reflector', () => { it('should get the class of an object', () => { - const result = reflector.getClass(johnDoe); + const result = reflector.getClass(OBJECTS.CLASS); - expect(result.name).toBe('Person'); + expect(result.name).toBe('Child'); }); }); @@ -254,9 +248,9 @@ describe('Reflector', () => { it('should get the parent of a class', () => { - const result = reflector.getParentClass(Person); + const result = reflector.getParentClass(CLASSES.Child); - expect(result.name).toBe('Human'); + expect(result.name).toBe('Parent'); }); }); }); diff --git a/packages/analysis/test/_fixtures/Reflector.fixture.ts b/packages/analysis/test/dynamic/fixtures/classes.fixture.ts similarity index 63% rename from packages/analysis/test/_fixtures/Reflector.fixture.ts rename to packages/analysis/test/dynamic/fixtures/classes.fixture.ts index 1d421330..bb292336 100644 --- a/packages/analysis/test/_fixtures/Reflector.fixture.ts +++ b/packages/analysis/test/dynamic/fixtures/classes.fixture.ts @@ -1,5 +1,5 @@ -class Human +class Parent { id: number; @@ -14,7 +14,7 @@ class Human } } -class Person extends Human +class Child extends Parent { #firstName: string; // No getter and setter #lastName: string; // No getter and setter @@ -58,27 +58,4 @@ class CustomError extends Error get additional() { return this.#additional; } } -const johnDoe = new Person(1, 'John', 'Doe', 42); -const janeDoe = { id: 2, fullName: 'Jane Doe', age: 42 }; -const plainError = new Error('Plain error'); -const customError = new CustomError('Custom error', 'with extras'); - -function requiredFunction(a: string, b: Person, c: number): string -{ - return a + b + c; -} - -function optionalFunction(a: string, b = new Person(1, 'Jane', 'Doe', 42), c = 0): string -{ - return a + b + c; -} - -const testModule = { Person, johnDoe, requiredFunction }; - -export -{ - Person, CustomError, - johnDoe, janeDoe, plainError, customError, - optionalFunction, - testModule -}; +export const CLASSES = { Parent, Child, CustomError }; diff --git a/packages/analysis/test/dynamic/fixtures/functions.fixture.ts b/packages/analysis/test/dynamic/fixtures/functions.fixture.ts new file mode 100644 index 00000000..58b84ac1 --- /dev/null +++ b/packages/analysis/test/dynamic/fixtures/functions.fixture.ts @@ -0,0 +1,20 @@ + +import { CLASSES } from "./classes.fixture"; + +const Child = CLASSES.Child; + +function requiredFunction(a: string, b: typeof Child, c: number): string +{ + return a + b + c; +} + +function optionalFunction(a: string, b = new Child(1, 'Jane', 'Doe', 42), c = 0): string +{ + return a + b + c; +} + +export const FUNCTIONS = +{ + REQUIRED_ARGS: requiredFunction, + OPTIONAL_ARGS: optionalFunction +}; diff --git a/packages/analysis/test/dynamic/fixtures/index.ts b/packages/analysis/test/dynamic/fixtures/index.ts new file mode 100644 index 00000000..4b294449 --- /dev/null +++ b/packages/analysis/test/dynamic/fixtures/index.ts @@ -0,0 +1,5 @@ + +export * from './classes.fixture'; +export * from './objects.fixture'; +export * from './functions.fixture'; +export * from './modules.fixture'; diff --git a/packages/analysis/test/dynamic/fixtures/modules.fixture.ts b/packages/analysis/test/dynamic/fixtures/modules.fixture.ts new file mode 100644 index 00000000..0717fd5b --- /dev/null +++ b/packages/analysis/test/dynamic/fixtures/modules.fixture.ts @@ -0,0 +1,16 @@ + +import { CLASSES } from "./classes.fixture"; +import { OBJECTS } from "./objects.fixture"; +import { FUNCTIONS } from "./functions.fixture"; + +const mixedModule = +{ + Person: CLASSES.Child, + johnDoe: OBJECTS.CLASS, + requiredFunction: FUNCTIONS.REQUIRED_ARGS +}; + +export const MODULES = +{ + MIXED: mixedModule +}; diff --git a/packages/analysis/test/dynamic/fixtures/objects.fixture.ts b/packages/analysis/test/dynamic/fixtures/objects.fixture.ts new file mode 100644 index 00000000..672817bb --- /dev/null +++ b/packages/analysis/test/dynamic/fixtures/objects.fixture.ts @@ -0,0 +1,10 @@ + +import { CLASSES } from "./classes.fixture"; + +export const OBJECTS = +{ + PLAIN: { id: 2, fullName: 'Jane Doe', age: 42 }, + CLASS: new CLASSES.Child(1, 'John', 'Doe', 42), + ERROR: new Error('Plain error'), + CUSTOM_ERROR: new CLASSES.CustomError('Custom error', 'with extras') +}; diff --git a/packages/analysis/test/models/ReflectionClass.spec.ts b/packages/analysis/test/models/ESClass.spec.ts similarity index 57% rename from packages/analysis/test/models/ReflectionClass.spec.ts rename to packages/analysis/test/models/ESClass.spec.ts index e2252808..7fd0244b 100644 --- a/packages/analysis/test/models/ReflectionClass.spec.ts +++ b/packages/analysis/test/models/ESClass.spec.ts @@ -1,14 +1,11 @@ import { describe, expect, it } from 'vitest'; -import ReflectionDeclaration from '../../src/models/ReflectionDeclaration'; -import ReflectionFunction from '../../src/models/ReflectionFunction'; -import ReflectionGetter from '../../src/models/ReflectionGetter'; -import ReflectionSetter from '../../src/models/ReflectionSetter'; +import { ESDeclaration, ESFunction, ESGetter, ESSetter } from '../../src/models'; -import { reflectionClass } from '../_fixtures/models/ReflectionClass.fixture'; +import { esClass } from './fixtures'; -describe('models/ReflectionClass', () => +describe('models/ESClass', () => { // Scope tests are omitted @@ -16,17 +13,17 @@ describe('models/ReflectionClass', () => { it('should return all readable members', () => { - const readable = reflectionClass.readable; + const readable = esClass.readable; expect(readable.length).toBe(3); expect(readable[0].name).toBe('name'); - expect(readable[0]).toBeInstanceOf(ReflectionGetter); + expect(readable[0]).toBeInstanceOf(ESGetter); expect(readable[1].name).toBe('age'); - expect(readable[1]).toBeInstanceOf(ReflectionGetter); + expect(readable[1]).toBeInstanceOf(ESGetter); expect(readable[2].name).toBe('length'); - expect(readable[2]).toBeInstanceOf(ReflectionDeclaration); + expect(readable[2]).toBeInstanceOf(ESDeclaration); }); }); @@ -34,14 +31,14 @@ describe('models/ReflectionClass', () => { it('should return all writable members', () => { - const writable = reflectionClass.writable; + const writable = esClass.writable; expect(writable.length).toBe(2); expect(writable[0].name).toBe('age'); - expect(writable[0]).toBeInstanceOf(ReflectionSetter); + expect(writable[0]).toBeInstanceOf(ESSetter); expect(writable[1].name).toBe('length'); - expect(writable[1]).toBeInstanceOf(ReflectionDeclaration); + expect(writable[1]).toBeInstanceOf(ESDeclaration); }); }); @@ -49,14 +46,14 @@ describe('models/ReflectionClass', () => { it('should return all callable members', () => { - const callable = reflectionClass.callable; + const callable = esClass.callable; expect(callable.length).toBe(2); expect(callable[0].name).toBe('constructor'); - expect(callable[0]).toBeInstanceOf(ReflectionFunction); + expect(callable[0]).toBeInstanceOf(ESFunction); expect(callable[1].name).toBe('toString'); - expect(callable[1]).toBeInstanceOf(ReflectionFunction); + expect(callable[1]).toBeInstanceOf(ESFunction); }); }); @@ -64,21 +61,21 @@ describe('models/ReflectionClass', () => { it('should read a public field', () => { - const canRead = reflectionClass.canRead('length'); + const canRead = esClass.canRead('length'); expect(canRead).toBe(true); }); it('should read a private field with getter', () => { - const canRead = reflectionClass.canRead('name'); + const canRead = esClass.canRead('name'); expect(canRead).toBe(true); }); it('should not read a private field without a getter', () => { - const canRead = reflectionClass.canRead('secret'); + const canRead = esClass.canRead('secret'); expect(canRead).toBe(false); }); @@ -88,21 +85,21 @@ describe('models/ReflectionClass', () => { it('should write a public field', () => { - const canWrite = reflectionClass.canWrite('length'); + const canWrite = esClass.canWrite('length'); expect(canWrite).toBe(true); }); it('should write a private field with setter', () => { - const canWrite = reflectionClass.canWrite('age'); + const canWrite = esClass.canWrite('age'); expect(canWrite).toBe(true); }); it('should not wite a private field without a setter', () => { - const canWrite = reflectionClass.canWrite('secret'); + const canWrite = esClass.canWrite('secret'); expect(canWrite).toBe(false); }); @@ -112,14 +109,14 @@ describe('models/ReflectionClass', () => { it('should call a public function', () => { - const canCall = reflectionClass.canCall('toString'); + const canCall = esClass.canCall('toString'); expect(canCall).toBe(true); }); it('should not call a private function', () => { - const canCall = reflectionClass.canCall('secretStuff'); + const canCall = esClass.canCall('secretStuff'); expect(canCall).toBe(false); }); diff --git a/packages/analysis/test/models/ESModule.spec.ts b/packages/analysis/test/models/ESModule.spec.ts new file mode 100644 index 00000000..7d82ba18 --- /dev/null +++ b/packages/analysis/test/models/ESModule.spec.ts @@ -0,0 +1,117 @@ + +import { describe, expect, it } from 'vitest'; + +import { ESClass, ESDeclaration, ESFunction, ESGenerator, ESMember } from '../../src/models'; + +import { esModule } from './fixtures'; + +describe('models/ESModule', () => +{ + // Scope tests are omitted + + describe('.exportedDeclarations', () => + { + it('should filter exported declarations', () => + { + const declarations = esModule.exportedDeclarations; + expect(declarations.length).toBe(1); + + expect(declarations[0]).toBeInstanceOf(ESDeclaration); + expect(declarations[0].name).toBe('peter'); + }); + }); + + describe('.exportedFunctions', () => + { + it('should filter exported functions', () => + { + const functions = esModule.exportedFunctions; + expect(functions.length).toBe(1); + + expect(functions[0]).toBeInstanceOf(ESFunction); + expect(functions[0].name).toBe('sum'); + }); + }); + + describe('.exportedGenerators', () => + { + it('should filter exported generators', () => + { + const generators = esModule.exportedGenerators; + expect(generators.length).toBe(1); + + expect(generators[0]).toBeInstanceOf(ESGenerator); + expect(generators[0].name).toBe('generateNumbers'); + }); + }); + + describe('.exportedClasses', () => + { + it('should filter exported classes', () => + { + const classes = esModule.exportedClasses; + expect(classes.length).toBe(1); + + expect(classes[0]).toBeInstanceOf(ESClass); + expect(classes[0].name).toBe('Customer'); + }); + }); + + describe('.exported', () => + { + it('should return a map with exported members only', () => + { + const exported = esModule.exported; + expect(exported.size).toBe(4); + + const first = exported.get('default') as ESFunction; + expect(first).toBeInstanceOf(ESFunction); + expect(first.name).toBe('sum'); + + const second = exported.get('peter') as ESDeclaration; + expect(second).toBeInstanceOf(ESDeclaration); + expect(second.name).toBe('peter'); + + const third = exported.get('Customer') as ESClass; + expect(third).toBeInstanceOf(ESClass); + expect(third.name).toBe('Customer'); + + const fourth = exported.get('generateNumbers') as ESGenerator; + expect(fourth).toBeInstanceOf(ESGenerator); + expect(fourth.name).toBe('generateNumbers'); + }); + }); + + describe('.isExported(member)', () => + { + it('should indicate that a member is exported', () => + { + const member = esModule.getMember('sum') as ESMember; + const result = esModule.isExported(member); + expect(result).toBe(true); + }); + + it('should indicate that a member is not exported', () => + { + const member = esModule.getMember('createJohn') as ESMember; + const result = esModule.isExported(member); + expect(result).toBe(false); + }); + }); + + describe('.getExported(name)', () => + { + it('should get an exported member', () => + { + const member = esModule.getExported('default') as ESFunction; + expect(member).toBeInstanceOf(ESFunction); + expect(member.name).toBe('sum'); + }); + + it('should not get a non-exported member', () => + { + const member = esModule.getExported('createJohn'); + expect(member).toBe(undefined); + }); + }); +}); diff --git a/packages/analysis/test/models/ReflectionScope.spec.ts b/packages/analysis/test/models/ESScope.spec.ts similarity index 58% rename from packages/analysis/test/models/ReflectionScope.spec.ts rename to packages/analysis/test/models/ESScope.spec.ts index f6597c37..72b4a745 100644 --- a/packages/analysis/test/models/ReflectionScope.spec.ts +++ b/packages/analysis/test/models/ESScope.spec.ts @@ -1,27 +1,20 @@ import { describe, expect, it } from 'vitest'; -import ReflectionClass from '../../src/models/ReflectionClass'; -import ReflectionDeclaration from '../../src/models/ReflectionDeclaration'; -import ReflectionExport from '../../src/models/ReflectionExport'; -import ReflectionFunction from '../../src/models/ReflectionFunction'; -import ReflectionGenerator from '../../src/models/ReflectionGenerator'; -import ReflectionGetter from '../../src/models/ReflectionGetter'; -import ReflectionImport from '../../src/models/ReflectionImport'; -import ReflectionSetter from '../../src/models/ReflectionSetter'; - -import { reflectionScope } from '../_fixtures/models/ReflectionScope.fixture'; - -describe('models/ReflectionScope', () => +import { ESImport, ESDeclaration, ESFunction, ESGenerator, ESClass, ESExport, ESGetter, ESSetter } from '../../src/models'; + +import { esScope } from './fixtures'; + +describe('models/ESScope', () => { describe('.imports', () => { it('should filter import members', () => { - const imports = reflectionScope.imports; + const imports = esScope.imports; expect(imports.length).toBe(1); - expect(imports[0]).toBeInstanceOf(ReflectionImport); + expect(imports[0]).toBeInstanceOf(ESImport); expect(imports[0].members.length).toBe(1); }); }); @@ -30,10 +23,10 @@ describe('models/ReflectionScope', () => { it('should filter export members', () => { - const exports = reflectionScope.exports; + const exports = esScope.exports; expect(exports.length).toBe(1); - expect(exports[0]).toBeInstanceOf(ReflectionExport); + expect(exports[0]).toBeInstanceOf(ESExport); expect(exports[0].members.length).toBe(2); }); }); @@ -42,13 +35,13 @@ describe('models/ReflectionScope', () => { it('should filter field members', () => { - const declarations = reflectionScope.declarations; + const declarations = esScope.declarations; expect(declarations.length).toBe(2); - expect(declarations[0]).toBeInstanceOf(ReflectionDeclaration); + expect(declarations[0]).toBeInstanceOf(ESDeclaration); expect(declarations[0].name).toBe('name'); - expect(declarations[1]).toBeInstanceOf(ReflectionDeclaration); + expect(declarations[1]).toBeInstanceOf(ESDeclaration); expect(declarations[1].name).toBe('age'); }); }); @@ -57,13 +50,13 @@ describe('models/ReflectionScope', () => { it('should filter function members', () => { - const functions = reflectionScope.functions; + const functions = esScope.functions; expect(functions.length).toBe(2); - expect(functions[0]).toBeInstanceOf(ReflectionFunction); + expect(functions[0]).toBeInstanceOf(ESFunction); expect(functions[0].name).toBe('createJohn'); - expect(functions[1]).toBeInstanceOf(ReflectionFunction); + expect(functions[1]).toBeInstanceOf(ESFunction); expect(functions[1].name).toBe('sum'); }); }); @@ -72,13 +65,13 @@ describe('models/ReflectionScope', () => { it('should filter getter members', () => { - const getters = reflectionScope.getters; + const getters = esScope.getters; expect(getters.length).toBe(2); - expect(getters[0]).toBeInstanceOf(ReflectionGetter); + expect(getters[0]).toBeInstanceOf(ESGetter); expect(getters[0].name).toBe('name'); - expect(getters[1]).toBeInstanceOf(ReflectionGetter); + expect(getters[1]).toBeInstanceOf(ESGetter); expect(getters[1].name).toBe('age'); }); }); @@ -87,10 +80,10 @@ describe('models/ReflectionScope', () => { it('should filter setter members', () => { - const setters = reflectionScope.setters; + const setters = esScope.setters; expect(setters.length).toBe(1); - expect(setters[0]).toBeInstanceOf(ReflectionSetter); + expect(setters[0]).toBeInstanceOf(ESSetter); expect(setters[0].name).toBe('age'); }); }); @@ -99,10 +92,10 @@ describe('models/ReflectionScope', () => { it('should filter generator members', () => { - const generators = reflectionScope.generators; + const generators = esScope.generators; expect(generators.length).toBe(1); - expect(generators[0]).toBeInstanceOf(ReflectionGenerator); + expect(generators[0]).toBeInstanceOf(ESGenerator); expect(generators[0].name).toBe('createJohn'); }); }); @@ -111,10 +104,10 @@ describe('models/ReflectionScope', () => { it('should filter class members', () => { - const classes = reflectionScope.classes; + const classes = esScope.classes; expect(classes.length).toBe(1); - expect(classes[0]).toBeInstanceOf(ReflectionClass); + expect(classes[0]).toBeInstanceOf(ESClass); expect(classes[0].name).toBe('Customer'); }); }); @@ -123,8 +116,8 @@ describe('models/ReflectionScope', () => { it('should get a member by its name', () => { - const member = reflectionScope.getMember('sum'); - expect(member).toBeInstanceOf(ReflectionFunction); + const member = esScope.getMember('sum'); + expect(member).toBeInstanceOf(ESFunction); expect(member?.name).toBe('sum'); }); }); @@ -133,8 +126,8 @@ describe('models/ReflectionScope', () => { it('should get a field by its name', () => { - const member = reflectionScope.getDeclaration('name'); - expect(member).toBeInstanceOf(ReflectionDeclaration); + const member = esScope.getDeclaration('name'); + expect(member).toBeInstanceOf(ESDeclaration); expect(member?.name).toBe('name'); }); }); @@ -143,8 +136,8 @@ describe('models/ReflectionScope', () => { it('should get a function by its name', () => { - const member = reflectionScope.getFunction('createJohn'); - expect(member).toBeInstanceOf(ReflectionFunction); + const member = esScope.getFunction('createJohn'); + expect(member).toBeInstanceOf(ESFunction); expect(member?.name).toBe('createJohn'); }); }); @@ -153,8 +146,8 @@ describe('models/ReflectionScope', () => { it('should get a getter by its name', () => { - const member = reflectionScope.getGetter('name'); - expect(member).toBeInstanceOf(ReflectionGetter); + const member = esScope.getGetter('name'); + expect(member).toBeInstanceOf(ESGetter); expect(member?.name).toBe('name'); }); }); @@ -163,8 +156,8 @@ describe('models/ReflectionScope', () => { it('should get a setter by its name', () => { - const member = reflectionScope.getSetter('age'); - expect(member).toBeInstanceOf(ReflectionSetter); + const member = esScope.getSetter('age'); + expect(member).toBeInstanceOf(ESSetter); expect(member?.name).toBe('age'); }); }); @@ -173,8 +166,8 @@ describe('models/ReflectionScope', () => { it('should get a generator by its name', () => { - const member = reflectionScope.getGenerator('createJohn'); - expect(member).toBeInstanceOf(ReflectionGenerator); + const member = esScope.getGenerator('createJohn'); + expect(member).toBeInstanceOf(ESGenerator); expect(member?.name).toBe('createJohn'); }); }); @@ -183,8 +176,8 @@ describe('models/ReflectionScope', () => { it('should get a class by its name', () => { - const member = reflectionScope.getClass('Customer'); - expect(member).toBeInstanceOf(ReflectionClass); + const member = esScope.getClass('Customer'); + expect(member).toBeInstanceOf(ESClass); expect(member?.name).toBe('Customer'); }); }); @@ -193,13 +186,13 @@ describe('models/ReflectionScope', () => { it('should have an existing member', () => { - const result = reflectionScope.hasMember('sum'); + const result = esScope.hasMember('sum'); expect(result).toBe(true); }); it('should not have a non-existing member', () => { - const result = reflectionScope.hasMember('nonExisting'); + const result = esScope.hasMember('nonExisting'); expect(result).toBe(false); }); }); @@ -208,13 +201,13 @@ describe('models/ReflectionScope', () => { it('should have an existing field', () => { - const result = reflectionScope.hasDeclaration('age'); + const result = esScope.hasDeclaration('age'); expect(result).toBe(true); }); it('should not have a non-existing field', () => { - const result = reflectionScope.hasDeclaration('Customer'); + const result = esScope.hasDeclaration('Customer'); expect(result).toBe(false); }); }); @@ -223,13 +216,13 @@ describe('models/ReflectionScope', () => { it('should have an existing function', () => { - const result = reflectionScope.hasFunction('createJohn'); + const result = esScope.hasFunction('createJohn'); expect(result).toBe(true); }); it('should not have a non-existing function', () => { - const result = reflectionScope.hasFunction('name'); + const result = esScope.hasFunction('name'); expect(result).toBe(false); }); }); @@ -238,13 +231,13 @@ describe('models/ReflectionScope', () => { it('should have an existing getter', () => { - const result = reflectionScope.hasGetter('name'); + const result = esScope.hasGetter('name'); expect(result).toBe(true); }); it('should not have a non-existing getter', () => { - const result = reflectionScope.hasGetter('createJohn'); + const result = esScope.hasGetter('createJohn'); expect(result).toBe(false); }); }); @@ -253,13 +246,13 @@ describe('models/ReflectionScope', () => { it('should have an existing setter', () => { - const result = reflectionScope.hasSetter('age'); + const result = esScope.hasSetter('age'); expect(result).toBe(true); }); it('should not have a non-existing setter', () => { - const result = reflectionScope.hasSetter('name'); + const result = esScope.hasSetter('name'); expect(result).toBe(false); }); }); @@ -268,13 +261,13 @@ describe('models/ReflectionScope', () => { it('should have an existing generator', () => { - const result = reflectionScope.hasGenerator('createJohn'); + const result = esScope.hasGenerator('createJohn'); expect(result).toBe(true); }); it('should not have a non-existing generator', () => { - const result = reflectionScope.hasGenerator('sum'); + const result = esScope.hasGenerator('sum'); expect(result).toBe(false); }); }); @@ -283,13 +276,13 @@ describe('models/ReflectionScope', () => { it('should have an existing class', () => { - const result = reflectionScope.hasClass('Customer'); + const result = esScope.hasClass('Customer'); expect(result).toBe(true); }); it('should not have a non-existing class', () => { - const result = reflectionScope.hasClass('name'); + const result = esScope.hasClass('name'); expect(result).toBe(false); }); }); diff --git a/packages/analysis/test/models/ReflectionModule.spec.ts b/packages/analysis/test/models/ReflectionModule.spec.ts deleted file mode 100644 index de07ab85..00000000 --- a/packages/analysis/test/models/ReflectionModule.spec.ts +++ /dev/null @@ -1,121 +0,0 @@ - -import { describe, expect, it } from 'vitest'; - -import ReflectionClass from '../../src/models/ReflectionClass'; -import ReflectionDeclaration from '../../src/models/ReflectionDeclaration'; -import ReflectionFunction from '../../src/models/ReflectionFunction'; -import ReflectionGenerator from '../../src/models/ReflectionGenerator'; -import ReflectionMember from '../../src/models/ReflectionMember'; - -import { reflectionModule } from '../_fixtures/models/ReflectionModule.fixture'; - -describe('models/ReflectionModule', () => -{ - // Scope tests are omitted - - describe('.exportedDeclarations', () => - { - it('should filter exported declarations', () => - { - const declarations = reflectionModule.exportedDeclarations; - expect(declarations.length).toBe(1); - - expect(declarations[0]).toBeInstanceOf(ReflectionDeclaration); - expect(declarations[0].name).toBe('peter'); - }); - }); - - describe('.exportedFunctions', () => - { - it('should filter exported functions', () => - { - const functions = reflectionModule.exportedFunctions; - expect(functions.length).toBe(1); - - expect(functions[0]).toBeInstanceOf(ReflectionFunction); - expect(functions[0].name).toBe('sum'); - }); - }); - - describe('.exportedGenerators', () => - { - it('should filter exported generators', () => - { - const generators = reflectionModule.exportedGenerators; - expect(generators.length).toBe(1); - - expect(generators[0]).toBeInstanceOf(ReflectionGenerator); - expect(generators[0].name).toBe('generateNumbers'); - }); - }); - - describe('.exportedClasses', () => - { - it('should filter exported classes', () => - { - const classes = reflectionModule.exportedClasses; - expect(classes.length).toBe(1); - - expect(classes[0]).toBeInstanceOf(ReflectionClass); - expect(classes[0].name).toBe('Customer'); - }); - }); - - describe('.exported', () => - { - it('should return a map with exported members only', () => - { - const exported = reflectionModule.exported; - expect(exported.size).toBe(4); - - const first = exported.get('default') as ReflectionFunction; - expect(first).toBeInstanceOf(ReflectionFunction); - expect(first.name).toBe('sum'); - - const second = exported.get('peter') as ReflectionDeclaration; - expect(second).toBeInstanceOf(ReflectionDeclaration); - expect(second.name).toBe('peter'); - - const third = exported.get('Customer') as ReflectionClass; - expect(third).toBeInstanceOf(ReflectionClass); - expect(third.name).toBe('Customer'); - - const fourth = exported.get('generateNumbers') as ReflectionGenerator; - expect(fourth).toBeInstanceOf(ReflectionGenerator); - expect(fourth.name).toBe('generateNumbers'); - }); - }); - - describe('.isExported(member)', () => - { - it('should indicate that a member is exported', () => - { - const member = reflectionModule.getMember('sum') as ReflectionMember; - const result = reflectionModule.isExported(member); - expect(result).toBe(true); - }); - - it('should indicate that a member is not exported', () => - { - const member = reflectionModule.getMember('createJohn') as ReflectionMember; - const result = reflectionModule.isExported(member); - expect(result).toBe(false); - }); - }); - - describe('.getExported(name)', () => - { - it('should get an exported member', () => - { - const member = reflectionModule.getExported('default') as ReflectionFunction; - expect(member).toBeInstanceOf(ReflectionFunction); - expect(member.name).toBe('sum'); - }); - - it('should not get a non-exported member', () => - { - const member = reflectionModule.getExported('createJohn'); - expect(member).toBe(undefined); - }); - }); -}); diff --git a/packages/analysis/test/models/fixtures/esClass.fixture.ts b/packages/analysis/test/models/fixtures/esClass.fixture.ts new file mode 100644 index 00000000..cc3e7fdc --- /dev/null +++ b/packages/analysis/test/models/fixtures/esClass.fixture.ts @@ -0,0 +1,20 @@ + +import { ESClass, ESDeclaration, ESExpression, ESField, ESFunction, ESGetter, ESScope, ESSetter } from '../../../src/models'; + +const members = +[ + new ESDeclaration('name', new ESExpression('"Peter"'), false, true), + new ESDeclaration('age', undefined, false, true), + new ESDeclaration('length', undefined, false, false), + new ESDeclaration('secret', undefined, false, true), + new ESFunction('constructor', [new ESField('age', undefined)], 'this.#age = age;'), + new ESGetter('name', [], 'return this.#name;'), + new ESGetter('age', [], 'return this.#age;'), + new ESSetter('age', [new ESField('age', undefined)], 'this.#age = age;'), + new ESFunction('secretStuff', [], '', false, false, true), + new ESFunction('toString', [], 'return `${this.#name} (${this.#age})`'), +]; + +const scope = new ESScope(members); + +export const esClass = new ESClass('Person', undefined, scope); diff --git a/packages/analysis/test/models/fixtures/esModule.fixture.ts b/packages/analysis/test/models/fixtures/esModule.fixture.ts new file mode 100644 index 00000000..e0376cfa --- /dev/null +++ b/packages/analysis/test/models/fixtures/esModule.fixture.ts @@ -0,0 +1,25 @@ + +import { ESImport, ESAlias, ESDeclaration, ESExpression, ESFunction, ESField, ESGenerator, ESClass, ESScope, ESExport, ESModule } from '../../../src/models'; + +const members = +[ + new ESImport([new ESAlias('default', 'Person')], './Person.js'), + new ESDeclaration('peter', new ESExpression('new Person("Peter")')), + new ESDeclaration('bas', new ESExpression('new Person("Bas")')), + new ESFunction('createJohn', [], 'return new Person("John")'), + new ESFunction('sum', [new ESField('a', undefined), new ESField('b', undefined)], 'return a + b'), + new ESGenerator('generateNumbers', [new ESField('count', undefined)], 'for (let i = 0; i < count; i++) yield i;'), + new ESGenerator('createJohn', [], 'yield new Person("John")'), + new ESClass('Customer', 'Person', new ESScope([])), + new ESClass('Order', undefined, new ESScope([])), + new ESExport([ + new ESAlias('sum', 'default'), + new ESAlias('peter', 'peter'), + new ESAlias('Customer', 'Customer'), + new ESAlias('generateNumbers', 'generateNumbers') + ], undefined) +]; + +const scope = new ESScope(members); + +export const esModule = new ESModule(scope); diff --git a/packages/analysis/test/models/fixtures/esScope.fixture.ts b/packages/analysis/test/models/fixtures/esScope.fixture.ts new file mode 100644 index 00000000..ecb9bdec --- /dev/null +++ b/packages/analysis/test/models/fixtures/esScope.fixture.ts @@ -0,0 +1,19 @@ + +import { ESImport, ESAlias, ESDeclaration, ESExpression, ESFunction, ESField, ESGenerator, ESClass, ESScope, ESExport, ESGetter, ESSetter } from '../../../src/models'; + +const members = +[ + new ESImport([new ESAlias('default', 'Person')], './Person.js'), + new ESDeclaration('name', new ESExpression('"john"'), false, true), + new ESDeclaration('age', new ESExpression('42'), false, true), + new ESFunction('createJohn', [], '{ return new Person("John") }'), + new ESFunction('sum', [new ESField('a', undefined), new ESField('b', undefined)], 'return a + b'), + new ESGetter('name', [], 'return this.#name;'), + new ESGetter('age', [], 'return this.#age;'), + new ESSetter('age', [new ESField('age', undefined)], 'this.#age = age;'), + new ESClass('Customer', 'Person', new ESScope([])), + new ESGenerator('createJohn', [], 'yield new Person("John")'), + new ESExport([new ESAlias('Customer', 'Customer'), new ESAlias('sum', 'default')], undefined) +]; + +export const esScope = new ESScope(members); diff --git a/packages/analysis/test/models/fixtures/index.ts b/packages/analysis/test/models/fixtures/index.ts new file mode 100644 index 00000000..c87b52d8 --- /dev/null +++ b/packages/analysis/test/models/fixtures/index.ts @@ -0,0 +1,4 @@ + +export * from './esClass.fixture'; +export * from './esModule.fixture'; +export * from './esScope.fixture'; diff --git a/packages/analysis/test/parser/ItemList.spec.ts b/packages/analysis/test/parser/ItemList.spec.ts deleted file mode 100644 index d3462472..00000000 --- a/packages/analysis/test/parser/ItemList.spec.ts +++ /dev/null @@ -1,140 +0,0 @@ - -import { describe, expect, it } from 'vitest'; - -import { createList } from '../_fixtures/parser/ItemList.fixture'; - -describe('parser/ItemList', () => -{ - describe('.current', () => - { - it('should start at the first item', () => - { - const itemList = createList(); - - expect(itemList.current).toBe('a'); - }); - - it('should return the second item after a step', () => - { - const itemList = createList(); - itemList.step(); - - expect(itemList.current).toBe('b'); - }); - }); - - describe('.next', () => - { - it('should return the second item for a new list', () => - { - const itemList = createList(); - - expect(itemList.next).toBe('b'); - }); - - it('should return the third item after a step', () => - { - const itemList = createList(); - itemList.step(); - - expect(itemList.next).toBe('c'); - }); - }); - - describe('.previous', () => - { - it('should return undefined for a new list', () => - { - const itemList = createList(); - - expect(itemList.previous).toBe(undefined); - }); - - it('should return the first item after a step', () => - { - const itemList = createList(); - itemList.step(); - - expect(itemList.previous).toBe('a'); - }); - }); - - describe('.eol', () => - { - it('should be false for a new list', () => - { - const itemList = createList(); - - expect(itemList.eol).toBe(false); - }); - - it('should be true for at the end of the list', () => - { - const itemList = createList(); - itemList.step(10); - - expect(itemList.eol).toBe(true); - }); - }); - - describe('.notAtEnd()', () => - { - it('should be true for a new list', () => - { - const itemList = createList(); - const result = itemList.notAtEnd(); - - expect(result).toBe(true); - }); - - it('should be false for at the end of the list', () => - { - const itemList = createList(); - itemList.step(10); - - const result = itemList.notAtEnd(); - - expect(result).toBe(false); - }); - }); - - describe('.step(amount)', () => - { - it('should step one position without an argument', () => - { - const itemList = createList(); - itemList.step(); - - expect(itemList.position).toBe(1); - }); - - it('should step the given amount', () => - { - const itemList = createList(); - itemList.step(5); - - expect(itemList.position).toBe(5); - }); - }); - - describe('.stepBack(amount)', () => - { - it('should step back one position without an argument', () => - { - const itemList = createList(); - itemList.step(5); - itemList.stepBack(); - - expect(itemList.position).toBe(4); - }); - - it('should step back the given amount', () => - { - const itemList = createList(); - itemList.step(5); - itemList.stepBack(3); - - expect(itemList.position).toBe(2); - }); - }); -}); diff --git a/packages/analysis/test/parser/Lexer.spec.ts b/packages/analysis/test/static/Lexer.spec.ts similarity index 94% rename from packages/analysis/test/parser/Lexer.spec.ts rename to packages/analysis/test/static/Lexer.spec.ts index 54edd753..35e0df71 100644 --- a/packages/analysis/test/parser/Lexer.spec.ts +++ b/packages/analysis/test/static/Lexer.spec.ts @@ -1,16 +1,9 @@ import { describe, expect, it } from 'vitest'; -import { Divider } from '../../src/parser/definitions/Divider'; -import { Group } from '../../src/parser/definitions/Group'; -import { Keyword } from '../../src/parser/definitions/Keyword'; -import { List } from '../../src/parser/definitions/List'; -import { Operator } from '../../src/parser/definitions/Operator'; -import { Scope } from '../../src/parser/definitions/Scope'; -import { TokenType } from '../../src/parser/definitions/TokenType'; -import Lexer from '../../src/parser/Lexer'; - -import { CODE } from '../_fixtures/parser/Lexer.fixture'; +import { Divider, Group, Keyword, List, Operator, Scope, TokenType, Lexer } from '../../src/static'; + +import { CODE } from './fixtures'; const lexer = new Lexer(); diff --git a/packages/analysis/test/parser/Parser.spec.ts b/packages/analysis/test/static/Parser.spec.ts similarity index 82% rename from packages/analysis/test/parser/Parser.spec.ts rename to packages/analysis/test/static/Parser.spec.ts index 45c3d2c3..24330a08 100644 --- a/packages/analysis/test/parser/Parser.spec.ts +++ b/packages/analysis/test/static/Parser.spec.ts @@ -1,16 +1,10 @@ import { describe, expect, it } from 'vitest'; -import ReflectionArray from '../../src/models/ReflectionArray'; -import ReflectionDestructuredArray from '../../src/models/ReflectionDestructuredArray'; -import ReflectionDestructuredObject from '../../src/models/ReflectionDestructuredObject'; -import ReflectionExpression from '../../src/models/ReflectionExpression'; -import ReflectionField from '../../src/models/ReflectionField'; -import ReflectionGenerator from '../../src/models/ReflectionGenerator'; -import ReflectionObject from '../../src/models/ReflectionObject'; -import Parser from '../../src/parser/Parser'; +import { ESArray, ESObject, ESExpression, ESField, ESGenerator, ESDestructuredArray, ESDestructuredObject } from '../../src/models'; +import { Parser } from '../../src/static'; -import { VALUES, IMPORTS, EXPORTS, DECLARATIONS, FUNCTIONS, CLASSES, MODULES } from '../_fixtures/parser/Parser.fixture'; +import { VALUES, IMPORTS, EXPORTS, DECLARATIONS, FUNCTIONS, CLASSES, MODULES } from './fixtures'; const parser = new Parser(); @@ -21,42 +15,42 @@ describe('parser/Parser', () => it('should parse an array', () => { const value = parser.parseValue(VALUES.ARRAY); - expect(value).toBeInstanceOf(ReflectionArray); + expect(value).toBeInstanceOf(ESArray); expect(value.definition).toBe('[ 1 , "foo" , false , new Person ( "Peter" , 42 ) , { a : 1 , b : 2 } ]'); }); it('should parse an object', () => { const value = parser.parseValue(VALUES.OBJECT); - expect(value).toBeInstanceOf(ReflectionObject); + expect(value).toBeInstanceOf(ESObject); expect(value.definition).toBe('{ key1 : "value1" , "key2" : new Person ( ) .toString ( ) }'); }); it('should parse an expression', () => { const value = parser.parseValue(VALUES.EXPRESSION); - expect(value).toBeInstanceOf(ReflectionExpression); + expect(value).toBeInstanceOf(ESExpression); expect(value.definition).toBe('new Number ( Math.ceil ( Math.random ( ) ) + 10 ) .toString ( )'); }); it('should parse a grouped expression', () => { const value = parser.parseValue(VALUES.EXPRESSION_GROUP); - expect(value).toBeInstanceOf(ReflectionExpression); + expect(value).toBeInstanceOf(ESExpression); expect(value.definition).toBe('( a + b ) * c'); }); it('should parse an if...else expression', () => { const value = parser.parseValue(VALUES.IF_ELSE); - expect(value).toBeInstanceOf(ReflectionExpression); + expect(value).toBeInstanceOf(ESExpression); expect(value.definition).toBe('if ( true ) { return "value1" ; } else { return "value2" ; }'); }); it('should parse an try...catch...finally expression', () => { const value = parser.parseValue(VALUES.TRY_CATCH_FINALLY); - expect(value).toBeInstanceOf(ReflectionExpression); + expect(value).toBeInstanceOf(ESExpression); expect(value.definition).toBe('try { sum ( 1 , 2 ) ; } catch ( error ) { console.error ( error ) ; } finally { console.log ( "finally" ) ; }'); }); }); @@ -303,7 +297,7 @@ describe('parser/Parser', () => const declaration = parser.parseDeclaration(DECLARATIONS.CONST); expect(declaration.name).toBe('name'); - expect(declaration.value).toBeInstanceOf(ReflectionExpression); + expect(declaration.value).toBeInstanceOf(ESExpression); expect(declaration.value?.definition).toBe("'const'"); }); @@ -312,7 +306,7 @@ describe('parser/Parser', () => const declaration = parser.parseDeclaration(DECLARATIONS.LET); expect(declaration.name).toBe('name'); - expect(declaration.value).toBeInstanceOf(ReflectionExpression); + expect(declaration.value).toBeInstanceOf(ESExpression); expect(declaration.value?.definition).toBe("'let'"); }); @@ -321,7 +315,7 @@ describe('parser/Parser', () => const declaration = parser.parseDeclaration(DECLARATIONS.VAR); expect(declaration.name).toBe('name'); - expect(declaration.value).toBeInstanceOf(ReflectionExpression); + expect(declaration.value).toBeInstanceOf(ESExpression); expect(declaration.value?.definition).toBe("'var'"); }); @@ -330,7 +324,7 @@ describe('parser/Parser', () => const declaration = parser.parseDeclaration(DECLARATIONS.MULTIPLE); expect(declaration.name).toBe('name1'); - expect(declaration.value).toBeInstanceOf(ReflectionExpression); + expect(declaration.value).toBeInstanceOf(ESExpression); expect(declaration.value?.definition).toBe('( 1 + 2 ) * 3'); }); @@ -339,7 +333,7 @@ describe('parser/Parser', () => const declaration = parser.parseDeclaration(DECLARATIONS.EXPRESSION); expect(declaration.name).toBe('number'); - expect(declaration.value).toBeInstanceOf(ReflectionExpression); + expect(declaration.value).toBeInstanceOf(ESExpression); expect(declaration.value?.definition).toBe("new Number ( Math.ceil ( Math.random ( ) ) + 10 ) .toString ( )"); }); @@ -348,7 +342,7 @@ describe('parser/Parser', () => const declaration = parser.parseDeclaration(DECLARATIONS.ARRAY); expect(declaration.name).toBe('array'); - expect(declaration.value).toBeInstanceOf(ReflectionArray); + expect(declaration.value).toBeInstanceOf(ESArray); expect(declaration.value?.definition).toBe("[ 'value1' , 'value2' ]"); }); @@ -357,7 +351,7 @@ describe('parser/Parser', () => const declaration = parser.parseDeclaration(DECLARATIONS.OBJECT); expect(declaration.name).toBe('object'); - expect(declaration.value).toBeInstanceOf(ReflectionObject); + expect(declaration.value).toBeInstanceOf(ESObject); expect(declaration.value?.definition).toBe("{ key1 : 'value1' , key2 : 'value2' }"); }); @@ -366,7 +360,7 @@ describe('parser/Parser', () => const declaration = parser.parseDeclaration(DECLARATIONS.REGEX); expect(declaration.name).toBe('regex'); - expect(declaration.value).toBeInstanceOf(ReflectionExpression); + expect(declaration.value).toBeInstanceOf(ESExpression); expect(declaration.value?.definition).toBe("/regex/g"); }); @@ -375,21 +369,21 @@ describe('parser/Parser', () => const declaration = parser.parseDeclaration(DECLARATIONS.DESTRUCTURING_ARRAY); expect(declaration.name).toBe('[ value1 , value2 = true ]'); - expect(declaration.value).toBeInstanceOf(ReflectionExpression); - expect(declaration.identifier).toBeInstanceOf(ReflectionDestructuredArray); + expect(declaration.value).toBeInstanceOf(ESExpression); + expect(declaration.identifier).toBeInstanceOf(ESDestructuredArray); - const identifier = declaration.identifier as ReflectionDestructuredArray; + const identifier = declaration.identifier as ESDestructuredArray; expect(identifier.members.length).toBe(2); - const firstMember = identifier.members[0] as ReflectionField; - expect(firstMember).toBeInstanceOf(ReflectionField); + const firstMember = identifier.members[0] as ESField; + expect(firstMember).toBeInstanceOf(ESField); expect(firstMember.name).toBe('value1'); expect(firstMember.value).toBe(undefined); - const secondMember = identifier.members[1] as ReflectionField; - expect(secondMember).toBeInstanceOf(ReflectionField); + const secondMember = identifier.members[1] as ESField; + expect(secondMember).toBeInstanceOf(ESField); expect(secondMember.name).toBe('value2'); - expect(secondMember.value).toBeInstanceOf(ReflectionExpression); + expect(secondMember.value).toBeInstanceOf(ESExpression); expect(secondMember.value?.definition).toBe('true'); }); @@ -398,20 +392,20 @@ describe('parser/Parser', () => const declaration = parser.parseDeclaration(DECLARATIONS.DESTRUCTURING_OBJECT); expect(declaration.name).toBe('{ key1 , key2 = false }'); - expect(declaration.value).toBeInstanceOf(ReflectionExpression); - expect(declaration.identifier).toBeInstanceOf(ReflectionDestructuredObject); + expect(declaration.value).toBeInstanceOf(ESExpression); + expect(declaration.identifier).toBeInstanceOf(ESDestructuredObject); - const identifier = declaration.identifier as ReflectionDestructuredArray; + const identifier = declaration.identifier as ESDestructuredArray; expect(identifier.members.length).toBe(2); - const firstMember = identifier.members[0] as ReflectionField; - expect(firstMember).toBeInstanceOf(ReflectionField); + const firstMember = identifier.members[0] as ESField; + expect(firstMember).toBeInstanceOf(ESField); expect(firstMember.name).toBe('key1'); - const secondMember = identifier.members[1] as ReflectionField; - expect(secondMember).toBeInstanceOf(ReflectionField); + const secondMember = identifier.members[1] as ESField; + expect(secondMember).toBeInstanceOf(ESField); expect(secondMember.name).toBe('key2'); - expect(secondMember.value).toBeInstanceOf(ReflectionExpression); + expect(secondMember.value).toBeInstanceOf(ESExpression); expect(secondMember.value?.definition).toBe('false'); }); @@ -420,7 +414,7 @@ describe('parser/Parser', () => const declaration = parser.parseDeclaration(DECLARATIONS.KEYWORD_AS_NAME); expect(declaration.name).toBe('as'); - expect(declaration.value).toBeInstanceOf(ReflectionExpression); + expect(declaration.value).toBeInstanceOf(ESExpression); expect(declaration.value?.definition).toBe("'value'"); }); @@ -429,7 +423,7 @@ describe('parser/Parser', () => const declaration = parser.parseDeclaration(DECLARATIONS.KEYWORD_AS_VALUE); expect(declaration.name).toBe('alias'); - expect(declaration.value).toBeInstanceOf(ReflectionExpression); + expect(declaration.value).toBeInstanceOf(ESExpression); expect(declaration.value?.definition).toBe('as'); }); }); @@ -520,7 +514,7 @@ describe('parser/Parser', () => { const funktion = parser.parseFunction(FUNCTIONS.GENERATOR); - expect(funktion).toBeInstanceOf(ReflectionGenerator); + expect(funktion).toBeInstanceOf(ESGenerator); expect(funktion.name).toBe('name'); expect(funktion.isAsync).toBe(false); expect(funktion.parameters.length).toBe(0); @@ -531,7 +525,7 @@ describe('parser/Parser', () => { const funktion = parser.parseFunction(FUNCTIONS.ASYNC_GENERATOR); - expect(funktion).toBeInstanceOf(ReflectionGenerator); + expect(funktion).toBeInstanceOf(ESGenerator); expect(funktion.name).toBe('name'); expect(funktion.isAsync).toBe(true); expect(funktion.parameters.length).toBe(0); @@ -542,7 +536,7 @@ describe('parser/Parser', () => { const funktion = parser.parseFunction(FUNCTIONS.EXPRESSION_GENERATOR); - expect(funktion).toBeInstanceOf(ReflectionGenerator); + expect(funktion).toBeInstanceOf(ESGenerator); expect(funktion.name).toBe('name'); expect(funktion.isAsync).toBe(false); expect(funktion.parameters.length).toBe(0); @@ -553,7 +547,7 @@ describe('parser/Parser', () => { const funktion = parser.parseFunction(FUNCTIONS.ASYNC_EXPRESSION_GENERATOR); - expect(funktion).toBeInstanceOf(ReflectionGenerator); + expect(funktion).toBeInstanceOf(ESGenerator); expect(funktion.name).toBe('name'); expect(funktion.isAsync).toBe(true); expect(funktion.parameters.length).toBe(0); @@ -570,13 +564,13 @@ describe('parser/Parser', () => const parameters = funktion.parameters; expect(parameters.length).toBe(2); - const first = parameters[0] as ReflectionField; - expect(first).toBeInstanceOf(ReflectionField); + const first = parameters[0] as ESField; + expect(first).toBeInstanceOf(ESField); expect(first.name).toBe('param1'); expect(first.value).toBe(undefined); - const second = parameters[1] as ReflectionField; - expect(second).toBeInstanceOf(ReflectionField); + const second = parameters[1] as ESField; + expect(second).toBeInstanceOf(ESField); expect(second.name).toBe('param2'); expect(second.value).toBe(undefined); }); @@ -591,15 +585,15 @@ describe('parser/Parser', () => const parameters = funktion.parameters; expect(parameters.length).toBe(2); - const first = parameters[0] as ReflectionField; - expect(first).toBeInstanceOf(ReflectionField); + const first = parameters[0] as ESField; + expect(first).toBeInstanceOf(ESField); expect(first.name).toBe('param1'); - expect(first.value).toEqual(new ReflectionExpression("'value1'")); + expect(first.value).toEqual(new ESExpression("'value1'")); - const second = parameters[1] as ReflectionField; - expect(second).toBeInstanceOf(ReflectionField); + const second = parameters[1] as ESField; + expect(second).toBeInstanceOf(ESField); expect(second.name).toBe('param2'); - expect(second.value).toEqual(new ReflectionExpression("true")); + expect(second.value).toEqual(new ESExpression("true")); }); it('should parse a function with a rest parameter', () => @@ -612,8 +606,8 @@ describe('parser/Parser', () => const parameters = funktion.parameters; expect(parameters.length).toBe(1); - const first = parameters[0] as ReflectionField; - expect(first).toBeInstanceOf(ReflectionField); + const first = parameters[0] as ESField; + expect(first).toBeInstanceOf(ESField); expect(first.name).toBe('...param1'); expect(first.value).toEqual(undefined); }); @@ -628,31 +622,31 @@ describe('parser/Parser', () => const parameters = funktion.parameters; expect(parameters.length).toBe(2); - const firstParameter = parameters[0] as ReflectionDestructuredObject; - expect(firstParameter).toBeInstanceOf(ReflectionDestructuredObject); + const firstParameter = parameters[0] as ESDestructuredObject; + expect(firstParameter).toBeInstanceOf(ESDestructuredObject); expect(firstParameter.members.length).toBe(2); - const firstMember = firstParameter.members[0] as ReflectionField; - expect(firstMember).toBeInstanceOf(ReflectionField); + const firstMember = firstParameter.members[0] as ESField; + expect(firstMember).toBeInstanceOf(ESField); expect(firstMember.name).toBe('param1'); expect(firstMember.value).toBe(undefined); - const secondMember = firstParameter.members[1] as ReflectionField; - expect(secondMember).toBeInstanceOf(ReflectionField); + const secondMember = firstParameter.members[1] as ESField; + expect(secondMember).toBeInstanceOf(ESField); expect(secondMember.name).toBe('param2'); expect(secondMember.value).toBe(undefined); - const secondParameter = parameters[1] as ReflectionDestructuredArray; - expect(secondParameter).toBeInstanceOf(ReflectionDestructuredArray); + const secondParameter = parameters[1] as ESDestructuredArray; + expect(secondParameter).toBeInstanceOf(ESDestructuredArray); expect(secondParameter.members.length).toBe(2); - const thirdMember = secondParameter.members[0] as ReflectionField; - expect(thirdMember).toBeInstanceOf(ReflectionField); + const thirdMember = secondParameter.members[0] as ESField; + expect(thirdMember).toBeInstanceOf(ESField); expect(thirdMember.name).toBe('param3'); expect(thirdMember.value).toBe(undefined); - const fourthMember = secondParameter.members[1] as ReflectionField; - expect(fourthMember).toBeInstanceOf(ReflectionField); + const fourthMember = secondParameter.members[1] as ESField; + expect(fourthMember).toBeInstanceOf(ESField); expect(fourthMember.name).toBe('param4'); expect(fourthMember.value).toBe(undefined); }); @@ -667,33 +661,33 @@ describe('parser/Parser', () => const parameters = funktion.parameters; expect(parameters.length).toBe(2); - const firstParameter = parameters[0] as ReflectionDestructuredObject; - expect(firstParameter).toBeInstanceOf(ReflectionDestructuredObject); + const firstParameter = parameters[0] as ESDestructuredObject; + expect(firstParameter).toBeInstanceOf(ESDestructuredObject); expect(firstParameter.members.length).toBe(2); - const firstMember = firstParameter.members[0] as ReflectionField; - expect(firstMember).toBeInstanceOf(ReflectionField); + const firstMember = firstParameter.members[0] as ESField; + expect(firstMember).toBeInstanceOf(ESField); expect(firstMember.name).toBe('param1'); - expect(firstMember.value).toBeInstanceOf(ReflectionExpression); + expect(firstMember.value).toBeInstanceOf(ESExpression); - const secondMember = firstParameter.members[1] as ReflectionField; - expect(secondMember).toBeInstanceOf(ReflectionField); + const secondMember = firstParameter.members[1] as ESField; + expect(secondMember).toBeInstanceOf(ESField); expect(secondMember.name).toBe('param2'); - expect(secondMember.value).toBeInstanceOf(ReflectionExpression); + expect(secondMember.value).toBeInstanceOf(ESExpression); - const secondParameter = parameters[1] as ReflectionDestructuredArray; - expect(secondParameter).toBeInstanceOf(ReflectionDestructuredArray); + const secondParameter = parameters[1] as ESDestructuredArray; + expect(secondParameter).toBeInstanceOf(ESDestructuredArray); expect(secondParameter.members.length).toBe(2); - const thirdMember = secondParameter.members[0] as ReflectionField; - expect(thirdMember).toBeInstanceOf(ReflectionField); + const thirdMember = secondParameter.members[0] as ESField; + expect(thirdMember).toBeInstanceOf(ESField); expect(thirdMember.name).toBe('param3'); - expect(thirdMember.value).toBeInstanceOf(ReflectionExpression); + expect(thirdMember.value).toBeInstanceOf(ESExpression); - const fourthMember = secondParameter.members[1] as ReflectionField; - expect(fourthMember).toBeInstanceOf(ReflectionField); + const fourthMember = secondParameter.members[1] as ESField; + expect(fourthMember).toBeInstanceOf(ESField); expect(fourthMember.name).toBe('param4'); - expect(fourthMember.value).toBeInstanceOf(ReflectionExpression); + expect(fourthMember.value).toBeInstanceOf(ESExpression); }); it('should parse a function with destructuring rest parameters', () => @@ -706,31 +700,31 @@ describe('parser/Parser', () => const parameters = funktion.parameters; expect(parameters.length).toBe(2); - const firstParameter = parameters[0] as ReflectionDestructuredObject; - expect(firstParameter).toBeInstanceOf(ReflectionDestructuredObject); + const firstParameter = parameters[0] as ESDestructuredObject; + expect(firstParameter).toBeInstanceOf(ESDestructuredObject); expect(firstParameter.members.length).toBe(2); - const firstMember = firstParameter.members[0] as ReflectionField; - expect(firstMember).toBeInstanceOf(ReflectionField); + const firstMember = firstParameter.members[0] as ESField; + expect(firstMember).toBeInstanceOf(ESField); expect(firstMember.name).toBe('param1'); expect(firstMember.value).toBe(undefined); - const secondMember = firstParameter.members[1] as ReflectionField; - expect(secondMember).toBeInstanceOf(ReflectionField); + const secondMember = firstParameter.members[1] as ESField; + expect(secondMember).toBeInstanceOf(ESField); expect(secondMember.name).toBe('param2'); expect(secondMember.value).toBe(undefined); - const secondParameter = parameters[1] as ReflectionDestructuredArray; - expect(secondParameter).toBeInstanceOf(ReflectionDestructuredArray); + const secondParameter = parameters[1] as ESDestructuredArray; + expect(secondParameter).toBeInstanceOf(ESDestructuredArray); expect(secondParameter.members.length).toBe(2); - const thirdMember = secondParameter.members[0] as ReflectionField; - expect(thirdMember).toBeInstanceOf(ReflectionField); + const thirdMember = secondParameter.members[0] as ESField; + expect(thirdMember).toBeInstanceOf(ESField); expect(thirdMember.name).toBe('param3'); expect(thirdMember.value).toBe(undefined); - const fourthMember = secondParameter.members[1] as ReflectionField; - expect(fourthMember).toBeInstanceOf(ReflectionField); + const fourthMember = secondParameter.members[1] as ESField; + expect(fourthMember).toBeInstanceOf(ESField); expect(fourthMember.name).toBe('...param4'); expect(fourthMember.value).toBe(undefined); }); diff --git a/packages/analysis/test/static/fixtures/classes.fixture.ts b/packages/analysis/test/static/fixtures/classes.fixture.ts new file mode 100644 index 00000000..89cd3421 --- /dev/null +++ b/packages/analysis/test/static/fixtures/classes.fixture.ts @@ -0,0 +1,53 @@ + +export const CLASSES = +{ + DECLARATION: "class Name {}", + EXTENDS: "class Name extends Parent {}", + EXPRESSION: "const name = class {}", + MEMBERS: `class Name +{ + #field1 = 'value1'; + field2; + + static #field3 = "value3"; + static field4; + + constructor(field1, ...field2) + { + this.#field1 = field1; + this.field2 = field2; + } + + get #getter1() { return field1; } + + get getter2() { return field2; } + + static get #getter3() { return field3; } + + static get getter4() { return field4; } + + set #setter1(value) { this.#field1 = value; } + + set setter2(value) { this.#field2 = value; } + + static set #setter3(value) { this.#field3 = value; } + + static set setter4(value) { this.#field4 = value; } + + method1() { return this.#field1; } + + async method2() { return this.#field1; } + + static method3() { return this.#field1; } + + static async method4() { return this.#field1; } + + #method5() { return this.#field1; } + + *generator1() { yield 1; } + + async *generator2() { yield 1; } + + static async *generator3() { yield 1; } +}` +}; diff --git a/packages/analysis/test/_fixtures/parser/Lexer.fixture.ts b/packages/analysis/test/static/fixtures/code.fixture.ts similarity index 95% rename from packages/analysis/test/_fixtures/parser/Lexer.fixture.ts rename to packages/analysis/test/static/fixtures/code.fixture.ts index 86d14c13..7b83c6f1 100644 --- a/packages/analysis/test/_fixtures/parser/Lexer.fixture.ts +++ b/packages/analysis/test/static/fixtures/code.fixture.ts @@ -1,5 +1,5 @@ -const CODE = +export const CODE = { OPERATORS: `=====!=+=*!=`, LITERALS: '`foo\\`ter`"bar\\"becue"\'baz\'', @@ -15,5 +15,3 @@ const CODE = REGEX_ARGUMENT: `doSomething(/[\\"]['"]/g)`, MINIFIED: 'return`foo`;identifier1=identifier2' }; - -export { CODE }; diff --git a/packages/analysis/test/static/fixtures/declarations.fixture.ts b/packages/analysis/test/static/fixtures/declarations.fixture.ts new file mode 100644 index 00000000..d8833d65 --- /dev/null +++ b/packages/analysis/test/static/fixtures/declarations.fixture.ts @@ -0,0 +1,17 @@ + +export const DECLARATIONS = +{ + EMPTY: "let name;", + CONST: "const name = 'const';", + LET: "let name = 'let';", + VAR: "var name = 'var';", + MULTIPLE: "let name1 = (1 + 2) * 3, name2, name3 = 'foo';", + EXPRESSION: `const number = new Number(Math.ceil(Math.random()) + 10).toString();`, + ARRAY: "const array = [ 'value1', 'value2' ];", + OBJECT: "const object = { key1: 'value1', key2: 'value2' };", + REGEX: "const regex = /regex/g;", + DESTRUCTURING_ARRAY: "const [value1, value2 = true] = array;", + DESTRUCTURING_OBJECT: "const {key1, key2 = false} = object;", + KEYWORD_AS_NAME: "const as = 'value';", + KEYWORD_AS_VALUE: "const alias = as;" +}; diff --git a/packages/analysis/test/static/fixtures/exports.fixture.ts b/packages/analysis/test/static/fixtures/exports.fixture.ts new file mode 100644 index 00000000..ccd5de02 --- /dev/null +++ b/packages/analysis/test/static/fixtures/exports.fixture.ts @@ -0,0 +1,15 @@ + +export const EXPORTS = +{ + EXPORT: "export { member }", + EXPORT_AS: "export { member as alias }", + EXPORT_DEFAULT: "export default name", + EXPORT_MULTIPLE: "export { name, member }", + EXPORT_MULTIPLE_AS: "export { name, member as alias }", + EXPORT_CLASS_DECLARATION: "export class name {}", + EXPORT_FIELD_DECLARATION: "export const name = 'value'", + EXPORT_FUNCTION_DECLARATION: "export function name() {}", + EXPORT_ASYNC_FUNCTION_DECLARATION: "export async function name() {}", + REEXPORT_ALL: "export * from 'module'", + REEXPORT_MEMBER: "export { member } from 'module'", +}; diff --git a/packages/analysis/test/static/fixtures/functions.fixture.ts b/packages/analysis/test/static/fixtures/functions.fixture.ts new file mode 100644 index 00000000..6c6bf95f --- /dev/null +++ b/packages/analysis/test/static/fixtures/functions.fixture.ts @@ -0,0 +1,25 @@ + +export const FUNCTIONS = +{ + DECLARATION: "function name() {}", + ASYNC_DECLARATION: "async function name() {}", + EXPRESSION: "const name = function() {}", + ASYNC_EXPRESSION: "const name = async function() {}", + ARROW: "const name = () => {}", + ARROW_EXPRESSION: "const name = () => 'value';", + ARROW_ARGUMENT: 'const name = arg => arg;', + ASYNC_ARROW: "const name = async () => {}", + GENERATOR: "function* name() {}", + ASYNC_GENERATOR: "async function* name() {}", + EXPRESSION_GENERATOR: "const name = function*() {}", + ASYNC_EXPRESSION_GENERATOR: "const name = async function*() {}", + PARAMETERS: "function name(param1, param2) {}", + DEFAULT_PARAMETERS: "function name(param1 = 'value1', param2 = true) {}", + REST_PARAMETERS: "function name(...param1) {}", + DESTRUCTURING_PARAMETERS: "function name({ param1, param2 }, [ param3, param4 ]) {}", + DESTRUCTURING_DEFAULT_PARAMETERS: "function name({ param1 = 'value1', param2 = true }, [ param3 = 'value3', param4 = true ]) {}", + DESTRUCTURING_REST_PARAMETERS: "function name({ param1, param2 }, [ param3, ...param4 ]) {}", + SIMPLE_BODY: "function name() { return 'value'; }", + BLOCK_BODY: "function name() { if (true) { return 'value'; } }", + KEYWORD_AS_NAME: "function as() {}" +}; diff --git a/packages/analysis/test/static/fixtures/imports.fixture.ts b/packages/analysis/test/static/fixtures/imports.fixture.ts new file mode 100644 index 00000000..a78b3d85 --- /dev/null +++ b/packages/analysis/test/static/fixtures/imports.fixture.ts @@ -0,0 +1,13 @@ + +export const IMPORTS = +{ + LOAD: "import 'module'", + IMPORT: "import { member } from 'module'", + IMPORT_AS: "import { member as alias } from 'module'", + IMPORT_ALL: "import * as name from 'module'", + IMPORT_DEFAULT: "import name from 'module'", + IMPORT_DEFAULT_MEMBER: "import name, { member } from 'module'", + IMPORT_DEFAULT_MEMBER_AS: "import name, { member as alias } from 'module'", + IMPORT_MULTIPLE_MEMBERS_AS: "import { name, member as alias } from 'module'", + IMPORT_DYNAMIC: "import('module')", +}; diff --git a/packages/analysis/test/static/fixtures/index.ts b/packages/analysis/test/static/fixtures/index.ts new file mode 100644 index 00000000..c87031d7 --- /dev/null +++ b/packages/analysis/test/static/fixtures/index.ts @@ -0,0 +1,9 @@ + +export * from './classes.fixture'; +export * from './code.fixture'; +export * from './declarations.fixture'; +export * from './exports.fixture'; +export * from './functions.fixture'; +export * from './imports.fixture'; +export * from './modules.fixture'; +export * from './values.fixture'; diff --git a/packages/analysis/test/static/fixtures/modules.fixture.ts b/packages/analysis/test/static/fixtures/modules.fixture.ts new file mode 100644 index 00000000..743f33a7 --- /dev/null +++ b/packages/analysis/test/static/fixtures/modules.fixture.ts @@ -0,0 +1,69 @@ + +export const MODULES = +{ + TERMINATED: +` +import { member } from 'module'; +import { member as alias } from 'module2'; + +const name = 'Peter' + ' van ' + 'Vliet'; + +export default function sum(a, b) { return a + b; } + +[1, 2, 3, 4, 5].sort((a, b) => a - b); + +try { sum(1, 2); } catch (error) { console.error(error); } + +export class Person +{ + #name; + #age; + + constructor(name, age) + { + this.#name = name; + this.#age = age; + } +} + +const peter = new Person(name, 42); + +async function async() { } +const a = async; +const b = async () => {}; + +const as = 12; +export { as as hi }; + +export { name, peter }; +`, + UNTERMINATED: +` + import { member } from 'module' + import { member as alias } from 'module2' + + const name = 'Peter' + ' van ' + 'Vliet' + + export default function sum(a, b) { return a + b } + + [1, 2, 3, 4, 5].sort((a, b) => a - b) + + try { sum(1, 2) } catch (error) { console.error(error) } + + export class Person + { + #name + #age + + constructor(name, age) + { + this.#name = name + this.#age = age + } + } + + const peter = new Person(name, 42) + + export { name, peter } +` +}; diff --git a/packages/analysis/test/static/fixtures/values.fixture.ts b/packages/analysis/test/static/fixtures/values.fixture.ts new file mode 100644 index 00000000..af2c9d6e --- /dev/null +++ b/packages/analysis/test/static/fixtures/values.fixture.ts @@ -0,0 +1,10 @@ + +export const VALUES = +{ + ARRAY: '[1, "foo", false, new Person("Peter", 42), { a: 1, b: 2 }]', + OBJECT: '{ key1: "value1", "key2": new Person().toString() }', + EXPRESSION:'new Number(Math.ceil(Math.random()) + 10).toString();', + EXPRESSION_GROUP: '(a + b) * c', + IF_ELSE: 'if (true) { return "value1"; } else { return "value2"; }', + TRY_CATCH_FINALLY: 'try { sum(1, 2); } catch (error) { console.error(error); } finally { console.log("finally"); }' +};