From 16a2d2bd77b37ec418aa203d7b96cf1b09852049 Mon Sep 17 00:00:00 2001 From: Dimitri Stallenberg Date: Wed, 20 Sep 2023 00:10:51 +0200 Subject: [PATCH 01/11] style: enable eslint linting rules --- .eslintrc.json | 70 +- .../analysis-javascript/lib/RootContext.ts | 22 +- .../lib/cfg/ControlFlowGraphFactory.ts | 5 +- .../lib/cfg/ControlFlowGraphVisitor.ts | 2 +- .../lib/constant/ConstantPoolFactory.ts | 3 +- .../lib/constant/ConstantVisitor.ts | 1 + .../lib/dependency/DependencyFactory.ts | 3 +- .../analysis-javascript/lib/target/Target.ts | 1 + .../lib/target/TargetFactory.ts | 3 +- .../lib/target/TargetVisitor.ts | 97 +-- .../target/export/ExportDefaultDeclaration.ts | 9 +- .../lib/target/export/ExportFactory.ts | 5 +- .../target/export/ExportNamedDeclaration.ts | 7 +- .../lib/target/export/ExpressionStatement.ts | 6 +- .../lib/type/discovery/TypeExtractor.ts | 8 +- .../type/discovery/element/ElementVisitor.ts | 1 + .../type/discovery/object/ObjectVisitor.ts | 1 + .../lib/type/discovery/relation/Relation.ts | 10 - .../discovery/relation/RelationVisitor.ts | 3 +- .../resolving/InferenceTypeModelFactory.ts | 666 +++++++++--------- .../lib/type/resolving/TypeModel.ts | 209 +++--- .../lib/type/resolving/TypeModelFactory.ts | 1 + .../lib/type/resolving/TypePool.ts | 4 +- .../test/cfg/ControlFlowGraphVisitor.test.ts | 2 +- .../test/target/TargetFactory.test.ts | 2 +- .../test/target/TargetVisitor.test.ts | 10 +- .../test/type/ElementVisitor.test.ts | 3 +- .../type/InferenceTypeModelFactory.test.ts | 5 +- .../test/type/RelationVisitor.test.ts | 1 - .../lib/AbstractSyntaxTreeVisitor.ts | 6 +- .../lib/globalVariables.ts | 1 + .../lib/datastructures/InstrumentationData.ts | 70 +- .../lib/datastructures/MetaData.ts | 20 +- .../lib/criterion/BranchDistance.ts | 19 +- .../lib/criterion/BranchDistanceVisitor.ts | 15 +- .../lib/search/JavaScriptExecutionResult.ts | 2 +- .../lib/search/JavaScriptSubject.ts | 8 +- .../lib/search/crossover/TreeCrossover.ts | 10 +- .../lib/testbuilding/ContextBuilder.ts | 12 +- .../lib/testbuilding/JavaScriptDecoder.ts | 9 +- .../testbuilding/JavaScriptSuiteBuilder.ts | 2 +- .../lib/testcase/JavaScriptTestCase.ts | 6 +- .../lib/testcase/StatementPool.ts | 9 +- .../ExecutionInformationIntegrator.ts | 3 +- .../testcase/execution/JavaScriptRunner.ts | 129 ++-- .../testcase/execution/SilentMochaReporter.ts | 1 + .../lib/testcase/execution/TestExecutor.ts | 21 +- .../sampling/JavaScriptRandomSampler.ts | 25 +- .../sampling/JavaScriptTestCaseSampler.ts | 36 +- .../testcase/sampling/generators/Generator.ts | 3 +- .../generators/action/CallGenerator.ts | 3 +- .../action/ConstantObjectGenerator.ts | 6 +- .../action/ConstructorCallGenerator.ts | 8 +- .../action/FunctionCallGenerator.ts | 8 +- .../generators/action/GetterGenerator.ts | 8 +- .../generators/action/MethodCallGenerator.ts | 10 +- .../action/ObjectFunctionCallGenerator.ts | 10 +- .../generators/action/SetterGenerator.ts | 10 +- .../lib/testcase/statements/Statement.ts | 2 +- .../statements/action/ActionStatement.ts | 2 +- .../statements/action/ClassActionStatement.ts | 4 +- .../statements/action/ConstantObject.ts | 4 +- .../statements/action/ConstructorCall.ts | 6 +- .../statements/action/FunctionCall.ts | 4 +- .../lib/testcase/statements/action/Getter.ts | 4 +- .../testcase/statements/action/MethodCall.ts | 6 +- .../statements/action/ObjectFunctionCall.ts | 4 +- .../lib/testcase/statements/action/Setter.ts | 8 +- .../statements/complex/ArrayStatement.ts | 4 +- .../complex/ArrowFunctionStatement.ts | 4 +- .../statements/complex/ObjectStatement.ts | 4 +- .../statements/primitive/BoolStatement.ts | 4 +- .../statements/primitive/IntegerStatement.ts | 6 +- .../statements/primitive/NullStatement.ts | 5 +- .../statements/primitive/NumericStatement.ts | 6 +- .../primitive/PrimitiveStatement.ts | 5 +- .../statements/primitive/StringStatement.ts | 4 +- .../primitive/UndefinedStatement.ts | 7 +- .../BranchDistanceBinaryDoubleEqual.test.ts | 1 + ...BranchDistanceBinaryDoubleNotEqual.test.ts | 1 + .../BranchDistanceBinaryGreater.test.ts | 1 + ...BranchDistanceBinaryGreaterOrEqual.test.ts | 1 + .../BranchDistanceBinarySmaller.test.ts | 1 + ...BranchDistanceBinarySmallerOrEqual.test.ts | 1 + .../BranchDistanceBinaryTrippleEqual.test.ts | 1 + ...ranchDistanceBinaryTrippleNotEqual.test.ts | 1 + .../criterion/BranchDistanceLogicalOr.test.ts | 1 + .../BranchDistanceStringFunctions.test.ts | 1 + .../criterion/BranchDistanceUnaryNot.test.ts | 1 + .../criterion/BranchDistanceVisitor.test.ts | 1 + .../RandomBranchDistanceTests.test.ts | 1 + .../lib/StateStorage.ts | 2 +- tools/javascript/lib/JavaScriptLauncher.ts | 113 +-- tools/javascript/lib/JavaScriptModule.ts | 14 +- tools/javascript/lib/commands/test.ts | 4 +- .../plugins/sampler/RandomSamplerPlugin.ts | 3 +- 96 files changed, 985 insertions(+), 887 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 91d1fe1f7..04d86d23c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -7,20 +7,20 @@ "extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended", - // "plugin:@typescript-eslint/recommended-requiring-type-checking", // TODO later too much work currently + "plugin:@typescript-eslint/recommended-requiring-type-checking", "plugin:unicorn/recommended", - // "plugin:import/recommended", // TODO gives weird errors + "plugin:import/recommended", "plugin:import/typescript", "plugin:promise/recommended", - "prettier"//, - // "plugin:sonarjs/recommended" // TODO later too much work currently + "prettier", + "plugin:sonarjs/recommended" ], - // "parser": "@typescript-eslint/parser", + "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 2021, - "sourceType": "module"//, - // "project": "./tsconfig.json", - // "tsconfigRootDir": "." + "sourceType": "module", + "project": "./tsconfig.json", + "tsconfigRootDir": "." }, "settings": { "import/resolver": { @@ -34,24 +34,24 @@ "unused-imports" ], "rules": { - // "import/first": "error", - // "import/newline-after-import": "error", - // "import/no-duplicates": "error", - // "import/order": ["error", - // { - // "alphabetize": { - // "order": "asc", - // "caseInsensitive": true - // }, - // "newlines-between": "always" - // } - // ], - // "sort-imports": ["error", - // { - // "ignoreDeclarationSort": true, - // "ignoreCase": true - // } - // ], + "import/first": "error", + "import/newline-after-import": "error", + "import/no-duplicates": "error", + "import/order": ["error", + { + "alphabetize": { + "order": "asc", + "caseInsensitive": true + }, + "newlines-between": "always" + } + ], + "sort-imports": ["error", + { + "ignoreDeclarationSort": true, + "ignoreCase": true + } + ], "notice/notice": [ "error", { @@ -60,16 +60,16 @@ } ], "unicorn/filename-case": "off", + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": "off", + "unused-imports/no-unused-imports": "error", + "unused-imports/no-unused-vars": [ + "error", + { "vars": "all", "varsIgnorePattern": "^_", "args": "after-used", "argsIgnorePattern": "^_" } + ], "unicorn/prefer-ternary": "warn", - - // "no-unused-vars": "off", - // "@typescript-eslint/no-unused-vars": "off", - // "unused-imports/no-unused-imports": "error", - // "unused-imports/no-unused-vars": [ - // "error", - // { "vars": "all", "varsIgnorePattern": "^_", "args": "after-used", "argsIgnorePattern": "^_" } - // ], + "unicorn/expiring-todo-comments": "off", "no-fallthrough": "off", - "unicorn/expiring-todo-comments": "off" + "sonarjs/cognitive-complexity": "warn" } } diff --git a/libraries/analysis-javascript/lib/RootContext.ts b/libraries/analysis-javascript/lib/RootContext.ts index 986b1daca..289c0971d 100644 --- a/libraries/analysis-javascript/lib/RootContext.ts +++ b/libraries/analysis-javascript/lib/RootContext.ts @@ -20,27 +20,27 @@ import { existsSync, lstatSync } from "node:fs"; import * as t from "@babel/types"; import { RootContext as CoreRootContext } from "@syntest/analysis"; +import { getLogger, Logger } from "@syntest/logging"; +import TypedEmitter from "typed-emitter"; import { AbstractSyntaxTreeFactory } from "./ast/AbstractSyntaxTreeFactory"; import { ControlFlowGraphFactory } from "./cfg/ControlFlowGraphFactory"; +import { ConstantPool } from "./constant/ConstantPool"; +import { ConstantPoolFactory } from "./constant/ConstantPoolFactory"; +import { ConstantPoolManager } from "./constant/ConstantPoolManager"; import { DependencyFactory } from "./dependency/DependencyFactory"; +import { Events } from "./Events"; import { Export } from "./target/export/Export"; -import { TargetFactory } from "./target/TargetFactory"; -import { TypeModelFactory } from "./type/resolving/TypeModelFactory"; -import { readFile } from "./utils/fileSystem"; import { ExportFactory } from "./target/export/ExportFactory"; -import { TypeExtractor } from "./type/discovery/TypeExtractor"; -import { TypeModel } from "./type/resolving/TypeModel"; +import { TargetFactory } from "./target/TargetFactory"; import { Element } from "./type/discovery/element/Element"; import { DiscoveredObjectType } from "./type/discovery/object/DiscoveredType"; import { Relation } from "./type/discovery/relation/Relation"; +import { TypeExtractor } from "./type/discovery/TypeExtractor"; +import { TypeModel } from "./type/resolving/TypeModel"; +import { TypeModelFactory } from "./type/resolving/TypeModelFactory"; import { TypePool } from "./type/resolving/TypePool"; -import TypedEmitter from "typed-emitter"; -import { Events } from "./Events"; -import { ConstantPoolManager } from "./constant/ConstantPoolManager"; -import { Logger, getLogger } from "@syntest/logging"; -import { ConstantPoolFactory } from "./constant/ConstantPoolFactory"; -import { ConstantPool } from "./constant/ConstantPool"; +import { readFile } from "./utils/fileSystem"; export class RootContext extends CoreRootContext { protected static LOGGER: Logger; diff --git a/libraries/analysis-javascript/lib/cfg/ControlFlowGraphFactory.ts b/libraries/analysis-javascript/lib/cfg/ControlFlowGraphFactory.ts index 45ecf902a..37c0d0479 100644 --- a/libraries/analysis-javascript/lib/cfg/ControlFlowGraphFactory.ts +++ b/libraries/analysis-javascript/lib/cfg/ControlFlowGraphFactory.ts @@ -18,11 +18,12 @@ import { traverse } from "@babel/core"; import * as t from "@babel/types"; import { ControlFlowGraphFactory as CoreControlFlowGraphFactory } from "@syntest/analysis"; -import { ControlFlowProgram, contractControlFlowProgram } from "@syntest/cfg"; +import { contractControlFlowProgram, ControlFlowProgram } from "@syntest/cfg"; -import { ControlFlowGraphVisitor } from "./ControlFlowGraphVisitor"; import { Factory } from "../Factory"; +import { ControlFlowGraphVisitor } from "./ControlFlowGraphVisitor"; + export class ControlFlowGraphFactory extends Factory implements CoreControlFlowGraphFactory diff --git a/libraries/analysis-javascript/lib/cfg/ControlFlowGraphVisitor.ts b/libraries/analysis-javascript/lib/cfg/ControlFlowGraphVisitor.ts index 7be04cdff..296acc9a9 100644 --- a/libraries/analysis-javascript/lib/cfg/ControlFlowGraphVisitor.ts +++ b/libraries/analysis-javascript/lib/cfg/ControlFlowGraphVisitor.ts @@ -28,7 +28,7 @@ import { Node, NodeType, } from "@syntest/cfg"; -import { Logger, getLogger } from "@syntest/logging"; +import { getLogger, Logger } from "@syntest/logging"; export class ControlFlowGraphVisitor extends AbstractSyntaxTreeVisitor { protected static override LOGGER: Logger; diff --git a/libraries/analysis-javascript/lib/constant/ConstantPoolFactory.ts b/libraries/analysis-javascript/lib/constant/ConstantPoolFactory.ts index 98ef3deda..2b04c4703 100644 --- a/libraries/analysis-javascript/lib/constant/ConstantPoolFactory.ts +++ b/libraries/analysis-javascript/lib/constant/ConstantPoolFactory.ts @@ -19,8 +19,9 @@ import { traverse } from "@babel/core"; import * as t from "@babel/types"; import { Factory } from "../Factory"; -import { ConstantVisitor } from "./ConstantVisitor"; + import { ConstantPool } from "./ConstantPool"; +import { ConstantVisitor } from "./ConstantVisitor"; export class ConstantPoolFactory extends Factory { /** diff --git a/libraries/analysis-javascript/lib/constant/ConstantVisitor.ts b/libraries/analysis-javascript/lib/constant/ConstantVisitor.ts index b32eea608..3bbbcfda0 100644 --- a/libraries/analysis-javascript/lib/constant/ConstantVisitor.ts +++ b/libraries/analysis-javascript/lib/constant/ConstantVisitor.ts @@ -18,6 +18,7 @@ import { NodePath } from "@babel/core"; import * as t from "@babel/types"; import { AbstractSyntaxTreeVisitor } from "@syntest/ast-visitor-javascript"; + import { ConstantPool } from "./ConstantPool"; export class ConstantVisitor extends AbstractSyntaxTreeVisitor { diff --git a/libraries/analysis-javascript/lib/dependency/DependencyFactory.ts b/libraries/analysis-javascript/lib/dependency/DependencyFactory.ts index 319b1c25a..1a9244573 100644 --- a/libraries/analysis-javascript/lib/dependency/DependencyFactory.ts +++ b/libraries/analysis-javascript/lib/dependency/DependencyFactory.ts @@ -20,9 +20,10 @@ import { traverse } from "@babel/core"; import * as t from "@babel/types"; import { DependencyFactory as CoreDependencyFactory } from "@syntest/analysis"; -import { DependencyVisitor } from "./DependencyVisitor"; import { Factory } from "../Factory"; +import { DependencyVisitor } from "./DependencyVisitor"; + /** * Dependency generator for targets. * diff --git a/libraries/analysis-javascript/lib/target/Target.ts b/libraries/analysis-javascript/lib/target/Target.ts index 177560f75..e8eb5bcf9 100644 --- a/libraries/analysis-javascript/lib/target/Target.ts +++ b/libraries/analysis-javascript/lib/target/Target.ts @@ -49,6 +49,7 @@ export type Exportable = { // eslint-disable-next-line @typescript-eslint/no-explicit-any export function isExported(target: any): target is Exportable { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access return "exported" in target && target.exported === true; } diff --git a/libraries/analysis-javascript/lib/target/TargetFactory.ts b/libraries/analysis-javascript/lib/target/TargetFactory.ts index 278312b25..c9fa9f2fc 100644 --- a/libraries/analysis-javascript/lib/target/TargetFactory.ts +++ b/libraries/analysis-javascript/lib/target/TargetFactory.ts @@ -22,10 +22,11 @@ import { traverse } from "@babel/core"; import * as t from "@babel/types"; import { TargetFactory as CoreTargetFactory } from "@syntest/analysis"; +import { Factory } from "../Factory"; + import { ExportVisitor } from "./export/ExportVisitor"; import { Target } from "./Target"; import { TargetVisitor } from "./TargetVisitor"; -import { Factory } from "../Factory"; /** * TargetFactory for Javascript. diff --git a/libraries/analysis-javascript/lib/target/TargetVisitor.ts b/libraries/analysis-javascript/lib/target/TargetVisitor.ts index eb1d27275..af3ef9c96 100644 --- a/libraries/analysis-javascript/lib/target/TargetVisitor.ts +++ b/libraries/analysis-javascript/lib/target/TargetVisitor.ts @@ -20,7 +20,11 @@ import { NodePath } from "@babel/core"; import * as t from "@babel/types"; import { TargetType } from "@syntest/analysis"; import { AbstractSyntaxTreeVisitor } from "@syntest/ast-visitor-javascript"; +import { getLogger, Logger } from "@syntest/logging"; + +import { unsupportedSyntax } from "../utils/diagnostics"; +import { Export } from "./export/Export"; import { Callable, ClassTarget, @@ -32,9 +36,6 @@ import { ObjectTarget, SubTarget, } from "./Target"; -import { Export } from "./export/Export"; -import { unsupportedSyntax } from "../utils/diagnostics"; -import { getLogger, Logger } from "@syntest/logging"; const COMPUTED_FLAG = ":computed:"; export class TargetVisitor extends AbstractSyntaxTreeVisitor { @@ -91,33 +92,6 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { // we always use x as the target name instead of A const parentNode = path.parentPath.node; switch (parentNode.type) { - case "ClassProperty": { - // e.g. class A { ? = class {} } - // e.g. class A { ? = function () {} } - // e.g. class A { ? = () => {} } - - if (parentNode.key.type === "Identifier") { - // e.g. class A { x = class {} } - // e.g. class A { x = function () {} } - // e.g. class A { x = () => {} } - return parentNode.key.name; - } else if (parentNode.key.type.includes("Literal")) { - // e.g. class A { "x" = class {} } - // e.g. class A { "x" = function () {} } - // e.g. class A { "x" = () => {} } - return "value" in parentNode.key - ? parentNode.key.value.toString() - : "null"; - } else { - // e.g. const {x} = class {} - // e.g. const {x} = function {} - // e.g. const {x} = () => {} - // Should not be possible - throw new Error( - unsupportedSyntax(path.node.type, this._getNodeId(path)) - ); - } - } case "VariableDeclarator": { // e.g. const ?? = class {} // e.g. const ?? = function {} @@ -208,16 +182,28 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { ); } } + case "ClassProperty": + // e.g. class A { ? = class {} } + // e.g. class A { ? = function () {} } + // e.g. class A { ? = () => {} } case "ObjectProperty": { // e.g. {?: class {}} // e.g. {?: function {}} // e.g. {?: () => {}} if (parentNode.key.type === "Identifier") { + // e.g. class A { x = class {} } + // e.g. class A { x = function () {} } + // e.g. class A { x = () => {} } + // e.g. {y: class {}} // e.g. {y: function {}} // e.g. {y: () => {}} return parentNode.key.name; } else if (parentNode.key.type.includes("Literal")) { + // e.g. class A { "x" = class {} } + // e.g. class A { "x" = function () {} } + // e.g. class A { "x" = () => {} } + // e.g. {1: class {}} // e.g. {1: function {}} // e.g. {1: () => {}} @@ -225,6 +211,10 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { ? parentNode.key.value.toString() : "null"; } else { + // e.g. const {x} = class {} + // e.g. const {x} = function {} + // e.g. const {x} = () => {} + // e.g. {?: class {}} // e.g. {?: function {}} // e.g. {?: () => {}} @@ -348,33 +338,12 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { // call(() => {}) const targetName = this._getTargetNameOfExpression(path); - if (path.parentPath.isVariableDeclarator()) { - const id = this._getNodeId(path); - const export_ = this._getExport(id); + // TODO is there a difference if the parent is a variable declarator? - this._extractFromFunction( - path, - id, - id, - targetName, - export_, - false, - false - ); - } else { - const id = this._getNodeId(path); - const export_ = this._getExport(id); + const id = this._getNodeId(path); + const export_ = this._getExport(id); - this._extractFromFunction( - path, - id, - id, - targetName, - export_, - false, - false - ); - } + this._extractFromFunction(path, id, id, targetName, export_, false, false); path.skip(); }; @@ -455,15 +424,13 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { if (object.isIdentifier()) { // x.? = ? // x['?'] = ? - if (object.node.name === "exports") { - // exports.? = ? - isObject = false; - id = this._getBindingId(right); - } else if ( - object.node.name === "module" && - property.isIdentifier() && - property.node.name === "exports" + if ( + object.node.name === "exports" || + (object.node.name === "module" && + property.isIdentifier() && + property.node.name === "exports") ) { + // exports.? = ? // module.exports = ? isObject = false; id = this._getBindingId(right); @@ -704,7 +671,7 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { key.isNumericLiteral() || key.isBigIntLiteral() ) { - targetName = `${key.node.value}`; + targetName = String(key.node.value); } if (value.isFunction()) { @@ -791,7 +758,7 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { key.isNumericLiteral() || key.isBigIntLiteral() ) { - targetName = `${key.node.value}`; + targetName = String(key.node.value); } if (value.isFunction()) { diff --git a/libraries/analysis-javascript/lib/target/export/ExportDefaultDeclaration.ts b/libraries/analysis-javascript/lib/target/export/ExportDefaultDeclaration.ts index 90d986d5e..eb60ecd03 100644 --- a/libraries/analysis-javascript/lib/target/export/ExportDefaultDeclaration.ts +++ b/libraries/analysis-javascript/lib/target/export/ExportDefaultDeclaration.ts @@ -36,10 +36,13 @@ export function extractExportsFromExportDefaultDeclaration( // export default x name = declaration.node.name; id = visitor._getBindingId(declaration); - } else if (declaration.isLiteral()) { + } else if (declaration.isLiteral() || declaration.isCallExpression()) { // export default 1 // export default "abc" // export default true + + // export default x() + name = "default"; id = visitor._getNodeId(declaration); } else if (declaration.isNewExpression()) { @@ -60,10 +63,6 @@ export function extractExportsFromExportDefaultDeclaration( // export default class {} name = declaration.node.id ? declaration.node.id.name : "default"; id = visitor._getNodeId(declaration); - } else if (declaration.isCallExpression()) { - // export default x() - name = "default"; - id = visitor._getNodeId(declaration); } else if (declaration.isObjectExpression()) { // export default {} const exports: Export[] = []; diff --git a/libraries/analysis-javascript/lib/target/export/ExportFactory.ts b/libraries/analysis-javascript/lib/target/export/ExportFactory.ts index 2103a4729..8f6fcd995 100644 --- a/libraries/analysis-javascript/lib/target/export/ExportFactory.ts +++ b/libraries/analysis-javascript/lib/target/export/ExportFactory.ts @@ -19,10 +19,11 @@ import { traverse } from "@babel/core"; import * as t from "@babel/types"; -import { ExportVisitor } from "./ExportVisitor"; -import { Export } from "./Export"; import { Factory } from "../../Factory"; +import { Export } from "./Export"; +import { ExportVisitor } from "./ExportVisitor"; + /** * ExportFactory for Javascript. * diff --git a/libraries/analysis-javascript/lib/target/export/ExportNamedDeclaration.ts b/libraries/analysis-javascript/lib/target/export/ExportNamedDeclaration.ts index 0373e17de..faa00285a 100644 --- a/libraries/analysis-javascript/lib/target/export/ExportNamedDeclaration.ts +++ b/libraries/analysis-javascript/lib/target/export/ExportNamedDeclaration.ts @@ -44,6 +44,7 @@ function extractFromObjectPattern( ); } + const notIdentifier = "Property key is not an identifier"; for (const property of path.get("properties")) { if (property.isRestElement()) { // unsupported @@ -57,7 +58,7 @@ function extractFromObjectPattern( if (!key.isIdentifier()) { // unsupported // not possible i think - throw new Error("Property key is not an identifier"); + throw new Error(notIdentifier); } const propertyName = key.node.name; @@ -74,7 +75,7 @@ function extractFromObjectPattern( if (_property.node.key.type !== "Identifier") { // unsupported // not possible i think - throw new Error("Property key is not an identifier"); + throw new Error(notIdentifier); } // so we want to find the property that has the same name as the property in the object pattern @@ -103,7 +104,7 @@ function extractFromObjectPattern( if (!key.isIdentifier()) { // unsupported // should never happen - throw new Error("Property key is not an identifier"); + throw new Error(notIdentifier); } if (match.isObjectProperty()) { diff --git a/libraries/analysis-javascript/lib/target/export/ExpressionStatement.ts b/libraries/analysis-javascript/lib/target/export/ExpressionStatement.ts index a19c55ea1..0b6782880 100644 --- a/libraries/analysis-javascript/lib/target/export/ExpressionStatement.ts +++ b/libraries/analysis-javascript/lib/target/export/ExpressionStatement.ts @@ -18,10 +18,10 @@ import { NodePath } from "@babel/core"; import * as t from "@babel/types"; +import { getLogger } from "@syntest/logging"; import { Export } from "./Export"; import { ExportVisitor } from "./ExportVisitor"; -import { getLogger } from "@syntest/logging"; type PartialExport = PartialDefaultExport | PartialNonDefaultExport; @@ -142,7 +142,7 @@ function _extractObjectProperties( // e.g. exports = { "a": ? } // e.g. exports = { 1: ? } // e.g. exports = { true: ? } - keyName = `${key.node.value}`; + keyName = String(key.node.value); } else if (key.isIdentifier()) { // e.g. exports = { a: ? } keyName = key.node.name; @@ -314,7 +314,7 @@ function _getNameOfProperty( property.isBigIntLiteral() ) { // module.exports['x'] = ? - return `${property.node.value}`; + return String(property.node.value); } else { // module.exports[a] = ? getLogger("ExportVisitor").warn( diff --git a/libraries/analysis-javascript/lib/type/discovery/TypeExtractor.ts b/libraries/analysis-javascript/lib/type/discovery/TypeExtractor.ts index 8cb86742c..905bbf57b 100644 --- a/libraries/analysis-javascript/lib/type/discovery/TypeExtractor.ts +++ b/libraries/analysis-javascript/lib/type/discovery/TypeExtractor.ts @@ -15,13 +15,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ObjectVisitor } from "./object/ObjectVisitor"; import traverse from "@babel/traverse"; -import { ElementVisitor } from "./element/ElementVisitor"; -import { RelationVisitor } from "./relation/RelationVisitor"; import * as t from "@babel/types"; + import { Factory } from "../../Factory"; +import { ElementVisitor } from "./element/ElementVisitor"; +import { ObjectVisitor } from "./object/ObjectVisitor"; +import { RelationVisitor } from "./relation/RelationVisitor"; + export class TypeExtractor extends Factory { extractElements(filepath: string, ast: t.Node) { const elementVisitor = new ElementVisitor(filepath, this.syntaxForgiving); diff --git a/libraries/analysis-javascript/lib/type/discovery/element/ElementVisitor.ts b/libraries/analysis-javascript/lib/type/discovery/element/ElementVisitor.ts index 2371a4459..88cd1805a 100644 --- a/libraries/analysis-javascript/lib/type/discovery/element/ElementVisitor.ts +++ b/libraries/analysis-javascript/lib/type/discovery/element/ElementVisitor.ts @@ -21,6 +21,7 @@ import { AbstractSyntaxTreeVisitor, MemberSeparator, } from "@syntest/ast-visitor-javascript"; + import { Element, ElementType } from "../element/Element"; export class ElementVisitor extends AbstractSyntaxTreeVisitor { diff --git a/libraries/analysis-javascript/lib/type/discovery/object/ObjectVisitor.ts b/libraries/analysis-javascript/lib/type/discovery/object/ObjectVisitor.ts index ff63a6e12..be8c043d4 100644 --- a/libraries/analysis-javascript/lib/type/discovery/object/ObjectVisitor.ts +++ b/libraries/analysis-javascript/lib/type/discovery/object/ObjectVisitor.ts @@ -18,6 +18,7 @@ import { NodePath } from "@babel/core"; import * as t from "@babel/types"; import { AbstractSyntaxTreeVisitor } from "@syntest/ast-visitor-javascript"; + import { DiscoveredObjectKind, DiscoveredType } from "./DiscoveredType"; export class ObjectVisitor extends AbstractSyntaxTreeVisitor { diff --git a/libraries/analysis-javascript/lib/type/discovery/relation/Relation.ts b/libraries/analysis-javascript/lib/type/discovery/relation/Relation.ts index 637ac4c97..57c245a23 100644 --- a/libraries/analysis-javascript/lib/type/discovery/relation/Relation.ts +++ b/libraries/analysis-javascript/lib/type/discovery/relation/Relation.ts @@ -26,16 +26,6 @@ export interface Relation { computed?: boolean; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function isRelation(object: any): object is Relation { - return ( - object !== undefined && - object.id !== undefined && - object.type !== undefined && - object.involved !== undefined - ); -} - export function getRelationName(type: RelationType): string { return Object.entries(RelationType).find(([, value]) => value === type)[0]; } diff --git a/libraries/analysis-javascript/lib/type/discovery/relation/RelationVisitor.ts b/libraries/analysis-javascript/lib/type/discovery/relation/RelationVisitor.ts index 98d6dc7ae..7edeaf8a5 100644 --- a/libraries/analysis-javascript/lib/type/discovery/relation/RelationVisitor.ts +++ b/libraries/analysis-javascript/lib/type/discovery/relation/RelationVisitor.ts @@ -18,7 +18,8 @@ import { NodePath } from "@babel/core"; import * as t from "@babel/types"; import { AbstractSyntaxTreeVisitor } from "@syntest/ast-visitor-javascript"; -import { Relation, RelationType, getRelationType } from "../relation/Relation"; + +import { getRelationType, Relation, RelationType } from "../relation/Relation"; export class RelationVisitor extends AbstractSyntaxTreeVisitor { private _relationMap: Map; diff --git a/libraries/analysis-javascript/lib/type/resolving/InferenceTypeModelFactory.ts b/libraries/analysis-javascript/lib/type/resolving/InferenceTypeModelFactory.ts index ebe138857..8632e6297 100644 --- a/libraries/analysis-javascript/lib/type/resolving/InferenceTypeModelFactory.ts +++ b/libraries/analysis-javascript/lib/type/resolving/InferenceTypeModelFactory.ts @@ -16,16 +16,16 @@ * limitations under the License. */ +import { Element, ElementType } from "../discovery/element/Element"; import { + getRelationName, Relation, RelationType, - getRelationName, } from "../discovery/relation/Relation"; -import { elementTypeToTypingType, TypeEnum } from "./TypeEnum"; -import { TypeModelFactory } from "./TypeModelFactory"; -import { Element, ElementType } from "../discovery/element/Element"; +import { elementTypeToTypingType, TypeEnum } from "./TypeEnum"; import { TypeModel } from "./TypeModel"; +import { TypeModelFactory } from "./TypeModelFactory"; export class InferenceTypeModelFactory extends TypeModelFactory { private _typeModel: TypeModel; @@ -211,52 +211,14 @@ export class InferenceTypeModelFactory extends TypeModelFactory { return id; }); + // eslint-disable-next-line sonarjs/max-switch-cases switch (relationType) { case RelationType.Return: { - const functionId = involved[0]; - const argumentId = involved[1]; - - if (argumentId !== undefined) { - this._typeModel.addStrongRelation(relationId, argumentId); - this._typeModel.addReturnType(functionId, argumentId); - } - + this._return(relation, involved); break; } case RelationType.Call: { - // TODO currently not possible because of the way the relations are created - const [functionId, ...arguments_] = involved; - - // const [functionId] = involved; - - this._typeModel.addTypeScore(functionId, TypeEnum.FUNCTION); - - const type = this._typeModel.getObjectDescription(functionId); - - // relation result is equal to return type of functionId - for (const returnValueId of type.return) { - if (relationId === returnValueId) { - // recursive function call so we do not add a relation - continue; - } - this._typeModel.addStrongRelation(relationId, returnValueId); - } - - // couple function arguments with function parameters - if (type && type.parameters.size > 0) { - const smallest = Math.min(arguments_.length, type.parameters.size); - - for (let index = 0; index < smallest; index++) { - const argumentId = arguments_[index]; - const parameterId = type.parameters.get(index); - if (argumentId === parameterId) { - // recursive function call so we do not add a relation - continue; - } - this._typeModel.addStrongRelation(parameterId, argumentId); - } - } - + this._call(relation, involved); break; } case RelationType.PrivateName: { @@ -264,76 +226,17 @@ export class InferenceTypeModelFactory extends TypeModelFactory { break; } case RelationType.ObjectProperty: { - const [propertyId, valueId] = involved; - - const propertyElement = elementMap.get(propertyId); - - if (propertyElement) { - const propertyName = - "name" in propertyElement - ? propertyElement.name - : propertyElement.value; - - this._typeModel.addPropertyType(relationId, propertyName, propertyId); - } else { - // TODO what if the property is not an element (spread element for example) - } - - // connect property to value - if (valueId !== undefined && valueId !== propertyId) { - this._typeModel.addStrongRelation(propertyId, valueId); - } - + this._objectProperty(elementMap, relation, involved); break; } case RelationType.ObjectMethod: { - const [functionId, ...parameters] = involved; - - // TODO what if the property is not an element - const propertyElement = elementMap.get(functionId); - const propertyName = - "name" in propertyElement - ? propertyElement.name - : propertyElement.value; - - this._typeModel.addPropertyType(relationId, propertyName, functionId); - this.addFunctionParameters( - elementMap, - relationMap, - functionId, - parameters - ); - + this._objectMethod(elementMap, relationMap, relation, involved); break; } case RelationType.ClassProperty: case RelationType.StaticClassProperty: { - if (involved.length < 2) { - throw new Error( - `Class property relation should have at least 2 elements, but has ${involved.length}` - ); - } - - const classId = involved[0]; - const propertyId = involved[1]; - const valueId = involved[2]; - - // TODO what if the property is not an element - const propertyElement = elementMap.get(propertyId); - const propertyName = - "name" in propertyElement - ? propertyElement.name - : propertyElement.value; - - // make object for the class - this._typeModel.addPropertyType(classId, propertyName, propertyId); - - // connect property to value - if (valueId !== undefined) { - this._typeModel.addStrongRelation(propertyId, valueId); - } - + this._classProperty(elementMap, involved); break; } case RelationType.ClassMethod: @@ -343,47 +246,12 @@ export class InferenceTypeModelFactory extends TypeModelFactory { case RelationType.ClassConstructor: case RelationType.ClassGetter: case RelationType.ClassSetter: { - if (involved.length < 2) { - throw new Error( - `Class method relation should have at least 2 elements, but has ${involved.length}` - ); - } - - const [, functionId, ...parameters] = involved; - // const [classId, functionId, ...parameters] = involved; - - // TODO the following does not work because the element refers to the identifier of the method - // BUT we do not record the ids as such we actually record the id of the entire function - // // TODO what if the function id is not an element - // const propertyElement = this.getElement(functionId); - // const propertyName = - // "name" in propertyElement - // ? propertyElement.name - // : propertyElement.value; - - // this._typeModel.addProperty(classId, propertyName, functionId); - - // TODO maybe not for setter / getter - // make function for the method - this.addFunctionParameters( - elementMap, - relationMap, - functionId, - parameters - ); - + this._classMethod(elementMap, relationMap, involved); break; } case RelationType.ArrayPattern: { - const elements = involved; - - this._typeModel.addTypeScore(relationId, TypeEnum.ARRAY); - // create array type - for (const id of elements) { - this._typeModel.addElementType(relationId, id); - } - + this._arrayPattern(relation, involved); break; } case RelationType.ObjectPattern: { @@ -412,63 +280,19 @@ export class InferenceTypeModelFactory extends TypeModelFactory { break; } case RelationType.For: { - const conditionId = involved[0]; - - if (conditionId === undefined) { - // weird - break; - } - // add boolean type to condition - this._typeModel.addTypeScore(conditionId, TypeEnum.BOOLEAN); - + this._for(involved); break; } case RelationType.ForIn: { - const declarator = involved[0]; - const arrayOrObject = involved[1]; - - this._typeModel.addTypeScore(arrayOrObject, TypeEnum.ARRAY); - this._typeModel.addTypeScore(arrayOrObject, TypeEnum.OBJECT); - - const typeOfArray = this._typeModel.getObjectDescription(arrayOrObject); - - for (const id of typeOfArray.elements.values()) { - // connect declarator to array element - this._typeModel.addWeakRelation(declarator, id); - } - - const typeOfObject = - this._typeModel.getObjectDescription(arrayOrObject); - - for (const id of typeOfObject.properties.values()) { - // connect declarator to object property - this._typeModel.addWeakRelation(declarator, id); - } - + this._forIn(involved); break; } case RelationType.ForOf: { - const declarator = involved[0]; - const array = involved[1]; - - this._typeModel.addTypeScore(array, TypeEnum.ARRAY); - - const typeOfArray = this._typeModel.getObjectDescription(array); - - for (const id of typeOfArray.elements.values()) { - // connect declarator to array element - this._typeModel.addWeakRelation(declarator, id); - } - + this._forOf(involved); break; } case RelationType.Switch: { - const [discriminant, ...cases] = involved; - - for (const case_ of cases) { - this._typeModel.addWeakRelation(discriminant, case_); - } - + this._switch(involved); break; } @@ -489,6 +313,8 @@ export class InferenceTypeModelFactory extends TypeModelFactory { const elements = involved; // create array type + this._typeModel.addTypeScore(relationId, TypeEnum.ARRAY); + for (const id of elements) { this._typeModel.addElementType(relationId, id); } @@ -555,67 +381,14 @@ export class InferenceTypeModelFactory extends TypeModelFactory { // Left-hand-side Expressions case RelationType.PropertyAccessor: case RelationType.OptionalPropertyAccessor: { - const [objectId, propertyId] = involved; - const [, originalProperty] = originalInvolved; - - const propertyElement = elementMap.get(originalProperty); - - if (propertyElement === undefined) { - // e.g. object[b ? 1 : 0] - // the property is not an element - this._typeModel.addTypeScore(objectId, TypeEnum.STRING); - this._typeModel.addTypeScore(objectId, TypeEnum.ARRAY); - this._typeModel.addTypeScore(objectId, TypeEnum.OBJECT, 2); - } else - switch (propertyElement.type) { - case ElementType.NumericalLiteral: { - // e.g. object[0] - // add array type to object - this._typeModel.addElementType(objectId, relationId); - - break; - } - case ElementType.StringLiteral: { - // e.g. object["abc"] - // add array type to object - this._typeModel.addPropertyType( - objectId, - propertyElement.value, - propertyId - ); - - break; - } - case ElementType.Identifier: { - if (relation.computed) { - // e.g. object[abc] - // not allowed dynamic stuff happening - // or we can check wether abc is a number - - // add the defaults - this._typeModel.addTypeScore(objectId, TypeEnum.STRING); - this._typeModel.addTypeScore(objectId, TypeEnum.ARRAY); - this._typeModel.addTypeScore(objectId, TypeEnum.OBJECT, 2); - } else { - // e.g. object.abc - this._typeModel.addPropertyType( - objectId, - propertyElement.name, - propertyId - ); - } - - break; - } - // No default - } - - // we don't have to connect the relationid to the propertyId since they are equal already - this._typeModel.addStrongRelation(relationId, propertyId); - // this._typeModel.setEqual(relationId, propertyId) + this._propertyAccessor( + elementMap, + relation, + involved, + originalInvolved + ); break; } - case RelationType.New: { const class_ = involved[0]; // TODO maybe this is not neccessary since the class is already connected to the relation @@ -869,27 +642,7 @@ export class InferenceTypeModelFactory extends TypeModelFactory { } case RelationType.Assignment: { - // should always have two involved - if (involved.length !== 2) { - throw new Error( - `Assignment relation should have two involved, but has ${involved.length}. ${relation.id}` - ); - } - const [leftId, rightId] = involved; - - if (leftId !== rightId) { - this._typeModel.addStrongRelation(leftId, rightId); - } - // undefined should be the actual result - // this._typeModel.addPrimitiveTypeScore(relationId, { - // type: TypeEnum.UNDEFINED, - // }); - - // this._typeModel.setEqual(leftId, relationId); - // this._typeModel.addStrongRelation(relationId, leftId); - - this._typeModel.addTypeScore(relationId, TypeEnum.UNDEFINED); - + this._assignment(relation, involved); break; } case RelationType.MultiplicationAssignment: // must be numeric @@ -903,61 +656,18 @@ export class InferenceTypeModelFactory extends TypeModelFactory { case RelationType.BitwiseAndAssignment: // must be numeric case RelationType.BitwiseXorAssignment: // must be numeric case RelationType.BitwiseOrAssignment: { - if (involved.length !== 2) { - throw new Error( - `Assignment relation should have two involved, but has ${involved.length}` - ); - } - const [leftId, rightId] = involved; - - // if they are equal we dont add a relation - if (leftId !== rightId) { - this._typeModel.addStrongRelation(leftId, rightId); - } - // likely numeric - this._typeModel.addTypeScore(leftId, TypeEnum.NUMERIC); - this._typeModel.addTypeScore(rightId, TypeEnum.NUMERIC); - - this._typeModel.addTypeScore(relationId, TypeEnum.UNDEFINED); - + this._specialAssignment(relation, involved); break; } case RelationType.AdditionAssignment: { - if (involved.length !== 2) { - throw new Error( - `Assignment relation should have two involved, but has ${involved.length}` - ); - } - const [leftId, rightId] = involved; - - this._typeModel.addWeakRelation(leftId, rightId); - // likely numeric or string - this._typeModel.addTypeScore(leftId, TypeEnum.NUMERIC); - this._typeModel.addTypeScore(leftId, TypeEnum.STRING); - this._typeModel.addTypeScore(rightId, TypeEnum.NUMERIC); - this._typeModel.addTypeScore(rightId, TypeEnum.STRING); - - this._typeModel.addTypeScore(relationId, TypeEnum.UNDEFINED); - + this._additionAssignment(relation, involved); break; } case RelationType.LogicalAndAssignment: // could be multiple things case RelationType.LogicalOrAssignment: // could be multiple things case RelationType.LogicalNullishAssignment: { - if (involved.length !== 2) { - throw new Error( - `Assignment relation should have two involved, but has ${involved.length}` - ); - } - const [leftId, rightId] = involved; - - this._typeModel.addWeakRelation(leftId, rightId); - // likely boolean - this._typeModel.addTypeScore(leftId, TypeEnum.BOOLEAN); - this._typeModel.addTypeScore(rightId, TypeEnum.BOOLEAN); - this._typeModel.addTypeScore(relationId, TypeEnum.UNDEFINED); - + this._logicalAssignment(relation, involved); break; } @@ -986,6 +696,326 @@ export class InferenceTypeModelFactory extends TypeModelFactory { } } + private _return(relation: Relation, involved: string[]) { + const [functionId, argumentId] = involved; + + if (argumentId !== undefined) { + this._typeModel.addStrongRelation(relation.id, argumentId); + this._typeModel.addReturnType(functionId, argumentId); + } + } + + private _call(relation: Relation, involved: string[]) { + const [functionId, ...arguments_] = involved; + + // const [functionId] = involved; + + this._typeModel.addTypeScore(functionId, TypeEnum.FUNCTION); + + const type = this._typeModel.getObjectDescription(functionId); + + // relation result is equal to return type of functionId + for (const returnValueId of type.return) { + if (relation.id === returnValueId) { + // recursive function call so we do not add a relation + continue; + } + this._typeModel.addStrongRelation(relation.id, returnValueId); + } + + // couple function arguments with function parameters + if (type && type.parameters.size > 0) { + const smallest = Math.min(arguments_.length, type.parameters.size); + + for (let index = 0; index < smallest; index++) { + const argumentId = arguments_[index]; + const parameterId = type.parameters.get(index); + if (argumentId === parameterId) { + // recursive function call so we do not add a relation + continue; + } + this._typeModel.addStrongRelation(parameterId, argumentId); + } + } + } + + private _objectProperty( + elementMap: Map, + relation: Relation, + involved: string[] + ) { + const [propertyId, valueId] = involved; + + const propertyElement = elementMap.get(propertyId); + + if (propertyElement) { + const propertyName = + "name" in propertyElement + ? propertyElement.name + : propertyElement.value; + + this._typeModel.addPropertyType(relation.id, propertyName, propertyId); + } else { + // TODO what if the property is not an element (spread element for example) + } + + // connect property to value + if (valueId !== undefined && valueId !== propertyId) { + this._typeModel.addStrongRelation(propertyId, valueId); + } + } + + private _objectMethod( + elementMap: Map, + relationMap: Map, + relation: Relation, + involved: string[] + ) { + const [functionId, ...parameters] = involved; + + // TODO what if the property is not an element + const propertyElement = elementMap.get(functionId); + const propertyName = + "name" in propertyElement ? propertyElement.name : propertyElement.value; + + this._typeModel.addPropertyType(relation.id, propertyName, functionId); + this.addFunctionParameters(elementMap, relationMap, functionId, parameters); + } + + private _classProperty(elementMap: Map, involved: string[]) { + if (involved.length < 2) { + throw new Error( + `Class property relation should have at least 2 elements, but has ${involved.length}` + ); + } + + const [classId, propertyId, valueId] = involved; + + // TODO what if the property is not an element + const propertyElement = elementMap.get(propertyId); + const propertyName = + "name" in propertyElement ? propertyElement.name : propertyElement.value; + + // make object for the class + this._typeModel.addPropertyType(classId, propertyName, propertyId); + + // connect property to value + if (valueId !== undefined) { + this._typeModel.addStrongRelation(propertyId, valueId); + } + } + + private _classMethod( + elementMap: Map, + relationMap: Map, + involved: string[] + ) { + if (involved.length < 2) { + throw new Error( + `Class method relation should have at least 2 elements, but has ${involved.length}` + ); + } + + const [, functionId, ...parameters] = involved; + // const [classId, functionId, ...parameters] = involved; + + // TODO the following does not work because the element refers to the identifier of the method + // BUT we do not record the ids as such we actually record the id of the entire function + // // TODO what if the function id is not an element + // const propertyElement = this.getElement(functionId); + // const propertyName = + // "name" in propertyElement + // ? propertyElement.name + // : propertyElement.value; + + // this._typeModel.addProperty(classId, propertyName, functionId); + + // TODO maybe not for setter / getter + // make function for the method + this.addFunctionParameters(elementMap, relationMap, functionId, parameters); + } + + private _arrayPattern(relation: Relation, involved: string[]) { + const elements = involved; + + this._typeModel.addTypeScore(relation.id, TypeEnum.ARRAY); + // create array type + for (const id of elements) { + this._typeModel.addElementType(relation.id, id); + } + } + + private _for(involved: string[]) { + const conditionId = involved[0]; + + if (conditionId !== undefined) { + // add boolean type to condition + this._typeModel.addTypeScore(conditionId, TypeEnum.BOOLEAN); + } + } + + private _forIn(involved: string[]) { + const [declarator, arrayOrObject] = involved; + + this._typeModel.addTypeScore(arrayOrObject, TypeEnum.ARRAY); + this._typeModel.addTypeScore(arrayOrObject, TypeEnum.OBJECT); + + const objectDescription = + this._typeModel.getObjectDescription(arrayOrObject); + + for (const id of objectDescription.elements.values()) { + // connect declarator to array element + this._typeModel.addWeakRelation(declarator, id); + } + + for (const id of objectDescription.properties.values()) { + // connect declarator to object property + this._typeModel.addWeakRelation(declarator, id); + } + } + + private _forOf(involved: string[]) { + const [declarator, array] = involved; + + this._typeModel.addTypeScore(array, TypeEnum.ARRAY); + + const typeOfArray = this._typeModel.getObjectDescription(array); + + for (const id of typeOfArray.elements.values()) { + // connect declarator to array element + this._typeModel.addWeakRelation(declarator, id); + } + } + + private _switch(involved: string[]) { + const [discriminant, ...cases] = involved; + + for (const case_ of cases) { + this._typeModel.addWeakRelation(discriminant, case_); + } + } + + private _propertyAccessor( + elementMap: Map, + relation: Relation, + involved: string[], + originalInvolved: string[] + ) { + const [objectId, propertyId] = involved; + const [, originalProperty] = originalInvolved; + + const propertyElement = elementMap.get(originalProperty); + + if (propertyElement === undefined) { + // e.g. object[b ? 1 : 0] + // the property is not an element + this._typeModel.addTypeScore(objectId, TypeEnum.STRING); + this._typeModel.addTypeScore(objectId, TypeEnum.ARRAY); + this._typeModel.addTypeScore(objectId, TypeEnum.OBJECT, 2); + } else + switch (propertyElement.type) { + case ElementType.NumericalLiteral: { + // e.g. object[0] + // add array type to object + this._typeModel.addElementType(objectId, relation.id); + + break; + } + case ElementType.StringLiteral: { + // e.g. object["abc"] + // add array type to object + this._typeModel.addPropertyType( + objectId, + propertyElement.value, + propertyId + ); + + break; + } + case ElementType.Identifier: { + if (relation.computed) { + // e.g. object[abc] + // not allowed dynamic stuff happening + // or we can check wether abc is a number + + // add the defaults + this._typeModel.addTypeScore(objectId, TypeEnum.STRING); + this._typeModel.addTypeScore(objectId, TypeEnum.ARRAY); + this._typeModel.addTypeScore(objectId, TypeEnum.OBJECT, 2); + } else { + // e.g. object.abc + this._typeModel.addPropertyType( + objectId, + propertyElement.name, + propertyId + ); + } + + break; + } + // No default + } + + // we don't have to connect the relationid to the propertyId since they are equal already + this._typeModel.addStrongRelation(relation.id, propertyId); + // this._typeModel.setEqual(relation.id, propertyId) + } + + private _assignment(relation: Relation, involved: string[]) { + // should always have two involved + if (involved.length !== 2) { + throw new Error( + `Assignment relation should have two involved, but has ${involved.length}. ${relation.id}` + ); + } + const [leftId, rightId] = involved; + + if (leftId !== rightId) { + this._typeModel.addStrongRelation(leftId, rightId); + } + // undefined should be the actual result + // this._typeModel.addPrimitiveTypeScore(relationId, { + // type: TypeEnum.UNDEFINED, + // }); + + // this._typeModel.setEqual(leftId, relationId); + // this._typeModel.addStrongRelation(relationId, leftId); + + this._typeModel.addTypeScore(relation.id, TypeEnum.UNDEFINED); + } + private _specialAssignment(relation: Relation, involved: string[]) { + this._assignment(relation, involved); + const [leftId, rightId] = involved; + + // likely numeric + this._typeModel.addTypeScore(leftId, TypeEnum.NUMERIC); + this._typeModel.addTypeScore(rightId, TypeEnum.NUMERIC); + } + + private _additionAssignment(relation: Relation, involved: string[]) { + this._specialAssignment(relation, involved); + const [leftId, rightId] = involved; + + // likely string + this._typeModel.addTypeScore(leftId, TypeEnum.STRING); + this._typeModel.addTypeScore(rightId, TypeEnum.STRING); + } + + private _logicalAssignment(relation: Relation, involved: string[]) { + if (involved.length !== 2) { + throw new Error( + `Assignment relation should have two involved, but has ${involved.length}` + ); + } + const [leftId, rightId] = involved; + + this._typeModel.addWeakRelation(leftId, rightId); + // likely boolean + this._typeModel.addTypeScore(leftId, TypeEnum.BOOLEAN); + this._typeModel.addTypeScore(rightId, TypeEnum.BOOLEAN); + this._typeModel.addTypeScore(relation.id, TypeEnum.UNDEFINED); + } + private addFunctionParameters( elementMap: Map, relationMap: Map, diff --git a/libraries/analysis-javascript/lib/type/resolving/TypeModel.ts b/libraries/analysis-javascript/lib/type/resolving/TypeModel.ts index 22cfb7e41..70367584c 100644 --- a/libraries/analysis-javascript/lib/type/resolving/TypeModel.ts +++ b/libraries/analysis-javascript/lib/type/resolving/TypeModel.ts @@ -17,10 +17,11 @@ */ import { prng } from "@syntest/prng"; + import { - ObjectType, arrayProperties, functionProperties, + ObjectType, stringProperties, } from "./Type"; import { TypeEnum } from "./TypeEnum"; @@ -383,7 +384,7 @@ export class TypeModel { const matchingTypes = probabilities; - let best: string = matchingTypes.keys().next().value; + let best: string = [...matchingTypes.keys()][0]; for (const [type, probability] of matchingTypes.entries()) { if (probability > matchingTypes.get(best)) { @@ -398,7 +399,7 @@ export class TypeModel { incorporateExecutionScore: boolean, filepath: string ): Map> { - const map = new Map(); + const map = new Map>(); for (const id of this._elements) { if (!id.startsWith(filepath)) { continue; @@ -427,7 +428,7 @@ export class TypeModel { // this._scoreHasChangedMap.set(element, false); - const probabilityMap = new Map(); + let probabilityMap = new Map(); if (id === "anon") { return probabilityMap; @@ -480,108 +481,156 @@ export class TypeModel { } for (const relation of usableRelations) { - const score = relationMap.get(relation); - if (!relationPairsVisited.has(id)) { - relationPairsVisited.set(id, new Set()); - } - if (!relationPairsVisited.has(relation)) { - relationPairsVisited.set(relation, new Set()); - } + probabilityMap = this.incorporateRelation( + id, + probabilityMap, + relation, + relationMap, + relationPairsVisited, + totalScore, + incorporateExecutionScore + ); + } - relationPairsVisited.get(id).add(relation); - relationPairsVisited.get(relation).add(id); + // incorporate execution scores + probabilityMap = this.incorporateExecutionScores( + id, + probabilityMap, + incorporateExecutionScore + ); - const probabilityOfRelation = score / totalScore; + return this.normalizeProbabilities(probabilityMap); + } - const probabilityMapOfRelation = this.calculateProbabilitiesForElement( - incorporateExecutionScore, - relation, - relationPairsVisited - ); + incorporateRelation( + id: string, + probabilityMap: Map, + relation: string, + relationMap: Map, + relationPairsVisited: Map>, + totalScore: number, + incorporateExecutionScore: boolean + ): Map { + const score = relationMap.get(relation); - for (const [type, probability] of probabilityMapOfRelation.entries()) { - let finalType = type; - - if (!type.includes("<>")) { - // maybe should check for includes (or the inverse by checking for primitive types) - // this will only add only the final relation id - // the other method will add all relation id from the element to the final relation - finalType = `${relation}<>${type}`; - } - - if (finalType.includes("<>") && finalType.split("<>")[0] === id) { - // skip this is a self loop - continue; - } - - if (!probabilityMap.has(finalType)) { - probabilityMap.set(finalType, 0); - } - - probabilityMap.set( - finalType, - probabilityMap.get(finalType) + probability * probabilityOfRelation - ); - } + if (!relationPairsVisited.has(id)) { + relationPairsVisited.set(id, new Set()); + } + if (!relationPairsVisited.has(relation)) { + relationPairsVisited.set(relation, new Set()); } - // incorporate execution scores - const executionScoreMap = this._typeExecutionScoreMap.get(id); + relationPairsVisited.get(id).add(relation); + relationPairsVisited.get(relation).add(id); - if (incorporateExecutionScore && executionScoreMap.size > 1) { - let minValue = 0; - for (const score of executionScoreMap.values()) { - minValue = Math.min(minValue, score); - } + const probabilityOfRelation = score / totalScore; - let totalScore = 0; - for (const type of probabilityMap.keys()) { - let score = executionScoreMap.get(type) ?? 0; - score -= minValue; - score += 1; - totalScore += score; - } + const probabilityMapOfRelation = this.calculateProbabilitiesForElement( + incorporateExecutionScore, + relation, + relationPairsVisited + ); - if (totalScore < 0) { - throw new Error("Total score should be positive"); + for (const [type, probability] of probabilityMapOfRelation.entries()) { + let finalType = type; + + if (!type.includes("<>")) { + // maybe should check for includes (or the inverse by checking for primitive types) + // this will only add only the final relation id + // the other method will add all relation id from the element to the final relation + finalType = `${relation}<>${type}`; } - if (totalScore === 0) { - throw new Error("Total score should be positive"); + if (finalType.includes("<>") && finalType.split("<>")[0] === id) { + // skip this is a self loop + continue; } - if (Number.isNaN(totalScore)) { - throw new TypeError("Total score should be positive"); + if (!probabilityMap.has(finalType)) { + probabilityMap.set(finalType, 0); } - // incorporate execution score - for (const type of probabilityMap.keys()) { - let score = executionScoreMap.has(type) - ? executionScoreMap.get(type) - : 0; - score -= minValue; - score += 1; + probabilityMap.set( + finalType, + probabilityMap.get(finalType) + probability * probabilityOfRelation + ); + } - const executionScoreDiscount = score / totalScore; - const probability = probabilityMap.get(type); - const newProbability = executionScoreDiscount * probability; + return probabilityMap; + } - probabilityMap.set(type, newProbability); - } + incorporateExecutionScores( + id: string, + probabilityMap: Map, + incorporateExecutionScore: boolean + ): Map { + const executionScoreMap = this._typeExecutionScoreMap.get(id); + + if (!incorporateExecutionScore || executionScoreMap.size <= 1) { + return probabilityMap; + } + + const combinedProbabilityMap = new Map(); + + let minValue = 0; + for (const score of executionScoreMap.values()) { + minValue = Math.min(minValue, score); + } + + let totalScore = 0; + for (const type of probabilityMap.keys()) { + let score = executionScoreMap.get(type) ?? 0; + score -= minValue; + score += 1; + totalScore += score; + } + + if (totalScore < 0) { + throw new Error("Total score should be positive but is negative"); + } + + if (totalScore === 0) { + throw new Error("Total score should be positive but is zero"); + } + + if (Number.isNaN(totalScore)) { + throw new TypeError("Total score should be positive but is NaN"); + } + + // incorporate execution score + for (const type of probabilityMap.keys()) { + let score = executionScoreMap.has(type) ? executionScoreMap.get(type) : 0; + score -= minValue; + score += 1; + + const executionScoreDiscount = score / totalScore; + const probability = probabilityMap.get(type); + const newProbability = executionScoreDiscount * probability; + + combinedProbabilityMap.set(type, newProbability); } + return combinedProbabilityMap; + } + + normalizeProbabilities( + probabilityMap: Map + ): Map { // normalize to 1 let totalProbability = 0; for (const probability of probabilityMap.values()) { totalProbability += probability; } - if (totalProbability !== 0 && totalProbability !== 1) { - for (const [type, probability] of probabilityMap.entries()) { - probabilityMap.set(type, probability / totalProbability); - } + if (totalProbability === 0 || totalProbability === 1) { + return probabilityMap; } - return probabilityMap; + const normalizedProbabilityMap = new Map(); + for (const [type, probability] of probabilityMap.entries()) { + normalizedProbabilityMap.set(type, probability / totalProbability); + } + + return normalizedProbabilityMap; } } diff --git a/libraries/analysis-javascript/lib/type/resolving/TypeModelFactory.ts b/libraries/analysis-javascript/lib/type/resolving/TypeModelFactory.ts index 209a41739..6c6a6aeb1 100644 --- a/libraries/analysis-javascript/lib/type/resolving/TypeModelFactory.ts +++ b/libraries/analysis-javascript/lib/type/resolving/TypeModelFactory.ts @@ -18,6 +18,7 @@ import { Element } from "../discovery/element/Element"; import { Relation } from "../discovery/relation/Relation"; + import { TypeModel } from "./TypeModel"; /** diff --git a/libraries/analysis-javascript/lib/type/resolving/TypePool.ts b/libraries/analysis-javascript/lib/type/resolving/TypePool.ts index f63616d29..07a809dc1 100644 --- a/libraries/analysis-javascript/lib/type/resolving/TypePool.ts +++ b/libraries/analysis-javascript/lib/type/resolving/TypePool.ts @@ -17,9 +17,11 @@ */ import { prng } from "@syntest/prng"; + +import { Export } from "../../target/export/Export"; import { DiscoveredObjectType } from "../discovery/object/DiscoveredType"; + import { ObjectType } from "./Type"; -import { Export } from "../../target/export/Export"; // TODO we could cache some of this stuff (unless we do dynamic adding of properties at some point) export class TypePool { diff --git a/libraries/analysis-javascript/test/cfg/ControlFlowGraphVisitor.test.ts b/libraries/analysis-javascript/test/cfg/ControlFlowGraphVisitor.test.ts index a0ead2eea..b3fa2ddd4 100644 --- a/libraries/analysis-javascript/test/cfg/ControlFlowGraphVisitor.test.ts +++ b/libraries/analysis-javascript/test/cfg/ControlFlowGraphVisitor.test.ts @@ -16,11 +16,11 @@ * limitations under the License. */ import { traverse } from "@babel/core"; +import { contractControlFlowProgram, EdgeType } from "@syntest/cfg"; import * as chai from "chai"; import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory"; import { ControlFlowGraphVisitor } from "../../lib/cfg/ControlFlowGraphVisitor"; -import { EdgeType, contractControlFlowProgram } from "@syntest/cfg"; const expect = chai.expect; diff --git a/libraries/analysis-javascript/test/target/TargetFactory.test.ts b/libraries/analysis-javascript/test/target/TargetFactory.test.ts index ee1194aaa..5718d3643 100644 --- a/libraries/analysis-javascript/test/target/TargetFactory.test.ts +++ b/libraries/analysis-javascript/test/target/TargetFactory.test.ts @@ -16,8 +16,8 @@ * limitations under the License. */ import { expect } from "chai"; -import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory"; +import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory"; import { TargetFactory } from "../../lib/target/TargetFactory"; describe("TargetFactory", () => { diff --git a/libraries/analysis-javascript/test/target/TargetVisitor.test.ts b/libraries/analysis-javascript/test/target/TargetVisitor.test.ts index aee65d96e..dcde99eb3 100644 --- a/libraries/analysis-javascript/test/target/TargetVisitor.test.ts +++ b/libraries/analysis-javascript/test/target/TargetVisitor.test.ts @@ -16,20 +16,20 @@ * limitations under the License. */ import { traverse } from "@babel/core"; +import { TargetType } from "@syntest/analysis"; import * as chai from "chai"; import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory"; import { ExportVisitor } from "../../lib/target/export/ExportVisitor"; -import { TargetVisitor } from "../../lib/target/TargetVisitor"; import { - FunctionTarget, - SubTarget, ClassTarget, + FunctionTarget, MethodTarget, - ObjectTarget, ObjectFunctionTarget, + ObjectTarget, + SubTarget, } from "../../lib/target/Target"; -import { TargetType } from "@syntest/analysis"; +import { TargetVisitor } from "../../lib/target/TargetVisitor"; const expect = chai.expect; diff --git a/libraries/analysis-javascript/test/type/ElementVisitor.test.ts b/libraries/analysis-javascript/test/type/ElementVisitor.test.ts index b5d99b97c..3a4573bff 100644 --- a/libraries/analysis-javascript/test/type/ElementVisitor.test.ts +++ b/libraries/analysis-javascript/test/type/ElementVisitor.test.ts @@ -19,9 +19,8 @@ import { traverse } from "@babel/core"; import * as chai from "chai"; import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory"; - -import { ElementVisitor } from "../../lib/type/discovery/element/ElementVisitor"; import { Identifier } from "../../lib/type/discovery/element/Element"; +import { ElementVisitor } from "../../lib/type/discovery/element/ElementVisitor"; const expect = chai.expect; diff --git a/libraries/analysis-javascript/test/type/InferenceTypeModelFactory.test.ts b/libraries/analysis-javascript/test/type/InferenceTypeModelFactory.test.ts index a4d7e52de..aa99debec 100644 --- a/libraries/analysis-javascript/test/type/InferenceTypeModelFactory.test.ts +++ b/libraries/analysis-javascript/test/type/InferenceTypeModelFactory.test.ts @@ -16,11 +16,12 @@ * limitations under the License. */ import traverse from "@babel/traverse"; + import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory"; import { ElementVisitor } from "../../lib/type/discovery/element/ElementVisitor"; -import { InferenceTypeModelFactory } from "../../lib/type/resolving/InferenceTypeModelFactory"; -import { RelationVisitor } from "../../lib/type/discovery/relation/RelationVisitor"; import { RelationType } from "../../lib/type/discovery/relation/Relation"; +import { RelationVisitor } from "../../lib/type/discovery/relation/RelationVisitor"; +import { InferenceTypeModelFactory } from "../../lib/type/resolving/InferenceTypeModelFactory"; function helper(source: string) { const generator = new AbstractSyntaxTreeFactory(); diff --git a/libraries/analysis-javascript/test/type/RelationVisitor.test.ts b/libraries/analysis-javascript/test/type/RelationVisitor.test.ts index 6974ef0f7..84dd1fdaf 100644 --- a/libraries/analysis-javascript/test/type/RelationVisitor.test.ts +++ b/libraries/analysis-javascript/test/type/RelationVisitor.test.ts @@ -19,7 +19,6 @@ import { traverse } from "@babel/core"; import * as chai from "chai"; import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory"; - import { RelationVisitor } from "../../lib/type/discovery/relation/RelationVisitor"; const expect = chai.expect; diff --git a/libraries/ast-visitor-javascript/lib/AbstractSyntaxTreeVisitor.ts b/libraries/ast-visitor-javascript/lib/AbstractSyntaxTreeVisitor.ts index 5a80e3b78..72e8c51f1 100644 --- a/libraries/ast-visitor-javascript/lib/AbstractSyntaxTreeVisitor.ts +++ b/libraries/ast-visitor-javascript/lib/AbstractSyntaxTreeVisitor.ts @@ -18,10 +18,10 @@ import { NodePath } from "@babel/core"; import { Scope as BabelScope, TraverseOptions } from "@babel/traverse"; import * as t from "@babel/types"; - import { getLogger, Logger } from "@syntest/logging"; -import { reservedKeywords } from "./reservedKeywords"; + import { globalVariables } from "./globalVariables"; +import { reservedKeywords } from "./reservedKeywords"; export const MemberSeparator = " <-> "; @@ -122,7 +122,7 @@ export class AbstractSyntaxTreeVisitor implements TraverseOptions { return ( this._getBindingId(path.parentPath.get("object")) + MemberSeparator + - (path.isIdentifier() ? path.node.name : path.node.value) + (path.isIdentifier() ? path.node.name : `${path.node.value}`) // this._getNodeId(path) // bad ); } diff --git a/libraries/ast-visitor-javascript/lib/globalVariables.ts b/libraries/ast-visitor-javascript/lib/globalVariables.ts index 2ff521766..f689f900a 100644 --- a/libraries/ast-visitor-javascript/lib/globalVariables.ts +++ b/libraries/ast-visitor-javascript/lib/globalVariables.ts @@ -18,5 +18,6 @@ import * as globals from "globals"; export const globalVariables = new Set( + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument Object.values(globals).flatMap((value) => Object.keys(value)) ); diff --git a/libraries/instrumentation-javascript/lib/datastructures/InstrumentationData.ts b/libraries/instrumentation-javascript/lib/datastructures/InstrumentationData.ts index 8470fa441..eb1210816 100644 --- a/libraries/instrumentation-javascript/lib/datastructures/InstrumentationData.ts +++ b/libraries/instrumentation-javascript/lib/datastructures/InstrumentationData.ts @@ -29,37 +29,45 @@ export type Location = { }; }; +export type StatementMap = { + [id: string]: Location; +}; + +export type BranchMap = { + [id: string]: { + line: number; + type: string; + loc: Location; + locations: [Location, Location]; + }; +}; + +export type FunctionMap = { + [id: string]: { + name: string; + line: number; + decl: Location; + loc: Location; + }; +}; + export type InstrumentationData = { - [path: string]: { - hash: string; - statementMap: { - [id: string]: Location; - }; - branchMap: { - [id: string]: { - line: number; - type: string; - loc: Location; - locations: [Location, Location]; - }; - }; - fnMap: { - [id: string]: { - name: string; - line: number; - decl: Location; - loc: Location; - }; - }; - s: { - [id: string]: number; - }; - f: { - [id: string]: number; - }; - b: { - // 0 is true, 1 is false - [id: string]: [number, number]; - }; + hash: string; + statementMap: StatementMap; + branchMap: BranchMap; + fnMap: FunctionMap; + s: { + [id: string]: number; + }; + f: { + [id: string]: number; }; + b: { + // 0 is true, 1 is false + [id: string]: [number, number]; + }; +}; + +export type InstrumentationDataMap = { + [path: string]: InstrumentationData; }; diff --git a/libraries/instrumentation-javascript/lib/datastructures/MetaData.ts b/libraries/instrumentation-javascript/lib/datastructures/MetaData.ts index 2614889dc..e67488e3b 100644 --- a/libraries/instrumentation-javascript/lib/datastructures/MetaData.ts +++ b/libraries/instrumentation-javascript/lib/datastructures/MetaData.ts @@ -16,16 +16,18 @@ * limitations under the License. */ export type MetaData = { - [path: string]: { - hash: string; - meta: { - [id: string]: { - condition_ast: string; - condition: string; - variables: { - [id: string]: unknown; - }; + hash: string; + meta: { + [id: string]: { + condition_ast: string; + condition: string; + variables: { + [id: string]: unknown; }; }; }; }; + +export type MetaDataMap = { + [path: string]: MetaData; +}; diff --git a/libraries/search-javascript/lib/criterion/BranchDistance.ts b/libraries/search-javascript/lib/criterion/BranchDistance.ts index acb1cfc68..fd75f3016 100644 --- a/libraries/search-javascript/lib/criterion/BranchDistance.ts +++ b/libraries/search-javascript/lib/criterion/BranchDistance.ts @@ -16,14 +16,15 @@ * limitations under the License. */ +import { transformSync, traverse } from "@babel/core"; +import { defaultBabelOptions } from "@syntest/analysis-javascript"; +import { getLogger, Logger } from "@syntest/logging"; import { BranchDistance as CoreBranchDistance, shouldNeverHappen, } from "@syntest/search"; + import { BranchDistanceVisitor } from "./BranchDistanceVisitor"; -import { transformSync, traverse } from "@babel/core"; -import { defaultBabelOptions } from "@syntest/analysis-javascript"; -import { Logger, getLogger } from "@syntest/logging"; export class BranchDistance extends CoreBranchDistance { protected static LOGGER: Logger; @@ -60,10 +61,12 @@ export class BranchDistance extends CoreBranchDistance { if (distance > 1 || distance < 0) { const variables_ = Object.entries(variables) - .map(([key, value]) => `${key}=${value}`) + .map(([key, value]) => `${key}=${String(value)}`) .join(", "); throw new Error( - `Invalid distance: ${distance} for ${condition} -> ${trueOrFalse}. Variables: ${variables_}` + `Invalid distance: ${distance} for ${condition} -> ${String( + trueOrFalse + )}. Variables: ${variables_}` ); } @@ -79,10 +82,12 @@ export class BranchDistance extends CoreBranchDistance { if (distance === 0) { // in general it should not be zero if used correctly so we give a warning const variables_ = Object.entries(variables) - .map(([key, value]) => `${key}=${value}`) + .map(([key, value]) => `${key}=${String(value)}`) .join(", "); BranchDistance.LOGGER.warn( - `Calculated distance for condition '${condition}' -> ${trueOrFalse}, is zero. Variables: ${variables_}` + `Calculated distance for condition '${condition}' -> ${String( + trueOrFalse + )}, is zero. Variables: ${variables_}` ); } return distance; diff --git a/libraries/search-javascript/lib/criterion/BranchDistanceVisitor.ts b/libraries/search-javascript/lib/criterion/BranchDistanceVisitor.ts index fcaab7927..c9f8c9b18 100644 --- a/libraries/search-javascript/lib/criterion/BranchDistanceVisitor.ts +++ b/libraries/search-javascript/lib/criterion/BranchDistanceVisitor.ts @@ -15,13 +15,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/no-unsafe-argument */ +/* eslint-disable @typescript-eslint/restrict-plus-operands */ import { NodePath } from "@babel/core"; import * as t from "@babel/types"; import { AbstractSyntaxTreeVisitor } from "@syntest/ast-visitor-javascript"; -import { Logger, getLogger } from "@syntest/logging"; +import { getLogger, Logger } from "@syntest/logging"; import { shouldNeverHappen } from "@syntest/search"; +const invalidOperator = "Invalid operator!"; export class BranchDistanceVisitor extends AbstractSyntaxTreeVisitor { protected static override LOGGER: Logger; @@ -377,7 +382,7 @@ export class BranchDistanceVisitor extends AbstractSyntaxTreeVisitor { } default: { // should be unreachable - throw new Error("Invalid operator!"); + throw new Error(invalidOperator); } } } @@ -472,7 +477,7 @@ export class BranchDistanceVisitor extends AbstractSyntaxTreeVisitor { } default: { // should be unreachable - throw new Error("Invalid operator!"); + throw new Error(invalidOperator); } } @@ -710,7 +715,7 @@ export class BranchDistanceVisitor extends AbstractSyntaxTreeVisitor { } default: { // should be unreachable - throw new Error("Invalid operator!"); + throw new Error(invalidOperator); } } @@ -822,7 +827,7 @@ export class BranchDistanceVisitor extends AbstractSyntaxTreeVisitor { } default: { // should be unreachable - throw new Error("Invalid operator!"); + throw new Error(invalidOperator); } } diff --git a/libraries/search-javascript/lib/search/JavaScriptExecutionResult.ts b/libraries/search-javascript/lib/search/JavaScriptExecutionResult.ts index 4d9b58ef4..0e229ba3c 100644 --- a/libraries/search-javascript/lib/search/JavaScriptExecutionResult.ts +++ b/libraries/search-javascript/lib/search/JavaScriptExecutionResult.ts @@ -16,7 +16,7 @@ * limitations under the License. */ -import { Trace, ExecutionResult } from "@syntest/search"; +import { ExecutionResult, Trace } from "@syntest/search"; export enum JavaScriptExecutionStatus { PASSED, diff --git a/libraries/search-javascript/lib/search/JavaScriptSubject.ts b/libraries/search-javascript/lib/search/JavaScriptSubject.ts index 4744aa7ab..db303fb24 100644 --- a/libraries/search-javascript/lib/search/JavaScriptSubject.ts +++ b/libraries/search-javascript/lib/search/JavaScriptSubject.ts @@ -15,20 +15,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { RootContext, SubTarget, Target } from "@syntest/analysis-javascript"; import { TargetType } from "@syntest/analysis"; +import { RootContext, SubTarget, Target } from "@syntest/analysis-javascript"; import { ControlFlowGraph, Edge, EdgeType } from "@syntest/cfg"; import { + ApproachLevel, + BranchObjectiveFunction, FunctionObjectiveFunction, ObjectiveFunction, SearchSubject, - ApproachLevel, shouldNeverHappen, - BranchObjectiveFunction, } from "@syntest/search"; -import { JavaScriptTestCase } from "../testcase/JavaScriptTestCase"; import { BranchDistance } from "../criterion/BranchDistance"; +import { JavaScriptTestCase } from "../testcase/JavaScriptTestCase"; export class JavaScriptSubject extends SearchSubject { protected syntaxForgiving: boolean; diff --git a/libraries/search-javascript/lib/search/crossover/TreeCrossover.ts b/libraries/search-javascript/lib/search/crossover/TreeCrossover.ts index ac760efbe..e953d7710 100644 --- a/libraries/search-javascript/lib/search/crossover/TreeCrossover.ts +++ b/libraries/search-javascript/lib/search/crossover/TreeCrossover.ts @@ -16,14 +16,14 @@ * limitations under the License. */ -import { Crossover } from "@syntest/search"; import { prng } from "@syntest/prng"; +import { Crossover } from "@syntest/search"; import { JavaScriptTestCase } from "../../testcase/JavaScriptTestCase"; -import { Statement } from "../../testcase/statements/Statement"; import { ActionStatement } from "../../testcase/statements/action/ActionStatement"; -import { ConstructorCall } from "../../testcase/statements/action/ConstructorCall"; import { ConstantObject } from "../../testcase/statements/action/ConstantObject"; +import { ConstructorCall } from "../../testcase/statements/action/ConstructorCall"; +import { Statement } from "../../testcase/statements/Statement"; type SwapStatement = { parent: Statement; @@ -50,11 +50,13 @@ type MatchingPair = { export class TreeCrossover extends Crossover { public crossOver(parents: JavaScriptTestCase[]): JavaScriptTestCase[] { if (parents.length !== 2) { - throw new Error("Expected exactly 2 parents, got: " + parents.length); + throw new Error(`Expected exactly 2 parents, got: ${parents.length}`); } + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion const rootA: ActionStatement[] = (parents[0].copy()) .roots; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion const rootB: ActionStatement[] = (parents[1].copy()) .roots; diff --git a/libraries/search-javascript/lib/testbuilding/ContextBuilder.ts b/libraries/search-javascript/lib/testbuilding/ContextBuilder.ts index 63c4f7e3e..88652e472 100644 --- a/libraries/search-javascript/lib/testbuilding/ContextBuilder.ts +++ b/libraries/search-javascript/lib/testbuilding/ContextBuilder.ts @@ -16,15 +16,19 @@ * limitations under the License. */ -import { Statement } from "../testcase/statements/Statement"; import * as path from "node:path"; + import { Export } from "@syntest/analysis-javascript"; +import { + globalVariables, + reservedKeywords, +} from "@syntest/ast-visitor-javascript"; +import { getLogger, Logger } from "@syntest/logging"; + import { ClassActionStatement } from "../testcase/statements/action/ClassActionStatement"; import { FunctionCall } from "../testcase/statements/action/FunctionCall"; import { ObjectFunctionCall } from "../testcase/statements/action/ObjectFunctionCall"; -import { reservedKeywords } from "@syntest/ast-visitor-javascript"; -import { globalVariables } from "@syntest/ast-visitor-javascript"; -import { Logger, getLogger } from "@syntest/logging"; +import { Statement } from "../testcase/statements/Statement"; type Import = RegularImport | RenamedImport; diff --git a/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts b/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts index 1cc462bac..5f17f43c7 100644 --- a/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts +++ b/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts @@ -19,13 +19,14 @@ import { Decoder } from "@syntest/search"; import { JavaScriptTestCase } from "../testcase/JavaScriptTestCase"; -import { Decoding } from "../testcase/statements/Statement"; import { ActionStatement } from "../testcase/statements/action/ActionStatement"; -import { ContextBuilder } from "./ContextBuilder"; -import { FunctionCall } from "../testcase/statements/action/FunctionCall"; import { ClassActionStatement } from "../testcase/statements/action/ClassActionStatement"; -import { assertionFunction } from "./assertionFunctionTemplate"; +import { FunctionCall } from "../testcase/statements/action/FunctionCall"; import { ObjectFunctionCall } from "../testcase/statements/action/ObjectFunctionCall"; +import { Decoding } from "../testcase/statements/Statement"; + +import { assertionFunction } from "./assertionFunctionTemplate"; +import { ContextBuilder } from "./ContextBuilder"; export class JavaScriptDecoder implements Decoder { private targetRootDirectory: string; diff --git a/libraries/search-javascript/lib/testbuilding/JavaScriptSuiteBuilder.ts b/libraries/search-javascript/lib/testbuilding/JavaScriptSuiteBuilder.ts index cbb1178e9..a5477b324 100644 --- a/libraries/search-javascript/lib/testbuilding/JavaScriptSuiteBuilder.ts +++ b/libraries/search-javascript/lib/testbuilding/JavaScriptSuiteBuilder.ts @@ -16,12 +16,12 @@ * limitations under the License. */ import { Archive } from "@syntest/search"; +import { StorageManager } from "@syntest/storage"; import { JavaScriptRunner } from "../testcase/execution/JavaScriptRunner"; import { JavaScriptTestCase } from "../testcase/JavaScriptTestCase"; import { JavaScriptDecoder } from "./JavaScriptDecoder"; -import { StorageManager } from "@syntest/storage"; export class JavaScriptSuiteBuilder { private storageManager: StorageManager; diff --git a/libraries/search-javascript/lib/testcase/JavaScriptTestCase.ts b/libraries/search-javascript/lib/testcase/JavaScriptTestCase.ts index d877f1bee..d3847d39f 100644 --- a/libraries/search-javascript/lib/testcase/JavaScriptTestCase.ts +++ b/libraries/search-javascript/lib/testcase/JavaScriptTestCase.ts @@ -16,14 +16,14 @@ * limitations under the License. */ +import { getLogger, Logger } from "@syntest/logging"; import { prng } from "@syntest/prng"; import { Decoder, Encoding } from "@syntest/search"; -import { getLogger, Logger } from "@syntest/logging"; +import { AssertionDataTestCase } from "./execution/AssertionData"; import { JavaScriptTestCaseSampler } from "./sampling/JavaScriptTestCaseSampler"; -import { ActionStatement } from "./statements/action/ActionStatement"; import { StatementPool } from "./StatementPool"; -import { AssertionDataTestCase } from "./execution/AssertionData"; +import { ActionStatement } from "./statements/action/ActionStatement"; /** * JavaScriptTestCase class diff --git a/libraries/search-javascript/lib/testcase/StatementPool.ts b/libraries/search-javascript/lib/testcase/StatementPool.ts index 609eb0bea..423bad572 100644 --- a/libraries/search-javascript/lib/testcase/StatementPool.ts +++ b/libraries/search-javascript/lib/testcase/StatementPool.ts @@ -15,14 +15,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ActionStatement } from "./statements/action/ActionStatement"; -import { Statement } from "./statements/Statement"; import { prng } from "@syntest/prng"; -import { ConstructorCall } from "./statements/action/ConstructorCall"; + +import { ActionStatement } from "./statements/action/ActionStatement"; +import { ClassActionStatement } from "./statements/action/ClassActionStatement"; import { ConstantObject } from "./statements/action/ConstantObject"; +import { ConstructorCall } from "./statements/action/ConstructorCall"; import { FunctionCall } from "./statements/action/FunctionCall"; -import { ClassActionStatement } from "./statements/action/ClassActionStatement"; import { ObjectFunctionCall } from "./statements/action/ObjectFunctionCall"; +import { Statement } from "./statements/Statement"; export class StatementPool { // type -> statement array diff --git a/libraries/search-javascript/lib/testcase/execution/ExecutionInformationIntegrator.ts b/libraries/search-javascript/lib/testcase/execution/ExecutionInformationIntegrator.ts index c26f73fa0..9af9b8bb7 100644 --- a/libraries/search-javascript/lib/testcase/execution/ExecutionInformationIntegrator.ts +++ b/libraries/search-javascript/lib/testcase/execution/ExecutionInformationIntegrator.ts @@ -16,11 +16,12 @@ * limitations under the License. */ +import { TypeModel } from "@syntest/analysis-javascript"; import Mocha = require("mocha"); import { JavaScriptTestCase } from "../JavaScriptTestCase"; import { Statement } from "../statements/Statement"; -import { TypeModel } from "@syntest/analysis-javascript"; + import { Test } from "./TestExecutor"; export class ExecutionInformationIntegrator { diff --git a/libraries/search-javascript/lib/testcase/execution/JavaScriptRunner.ts b/libraries/search-javascript/lib/testcase/execution/JavaScriptRunner.ts index b2c5b0f17..f577e8533 100644 --- a/libraries/search-javascript/lib/testcase/execution/JavaScriptRunner.ts +++ b/libraries/search-javascript/lib/testcase/execution/JavaScriptRunner.ts @@ -16,10 +16,18 @@ * limitations under the License. */ +import { ChildProcess, fork } from "node:child_process"; import * as path from "node:path"; -import { Trace, EncodingRunner, ExecutionResult } from "@syntest/search"; +import { + InstrumentationData, + InstrumentationDataMap, + MetaData, + MetaDataMap, +} from "@syntest/instrumentation-javascript"; import { getLogger, Logger } from "@syntest/logging"; +import { EncodingRunner, ExecutionResult, Trace } from "@syntest/search"; +import { StorageManager } from "@syntest/storage"; import { JavaScriptExecutionResult, @@ -30,13 +38,7 @@ import { JavaScriptDecoder } from "../../testbuilding/JavaScriptDecoder"; import { JavaScriptTestCase } from "../JavaScriptTestCase"; import { ExecutionInformationIntegrator } from "./ExecutionInformationIntegrator"; -import { StorageManager } from "@syntest/storage"; import { DoneMessage, Message } from "./TestExecutor"; -import { ChildProcess, fork } from "node:child_process"; -import { - InstrumentationData, - MetaData, -} from "@syntest/instrumentation-javascript"; export class JavaScriptRunner implements EncodingRunner { protected static LOGGER: Logger; @@ -186,7 +188,7 @@ export class JavaScriptRunner implements EncodingRunner { undefined ); } else { - JavaScriptRunner.LOGGER.error(error); + JavaScriptRunner.LOGGER.error(String(error)); throw error; } } @@ -201,8 +203,8 @@ export class JavaScriptRunner implements EncodingRunner { } private _extractTraces( - instrumentationData: InstrumentationData, - metaData: MetaData + instrumentationData: InstrumentationDataMap, + metaData: MetaDataMap ): Trace[] { const traces: Trace[] = []; @@ -237,82 +239,59 @@ export class JavaScriptRunner implements EncodingRunner { }); } - for (const branchKey of Object.keys(instrumentationData[key].branchMap)) { - const branch = instrumentationData[key].branchMap[branchKey]; - const hits = instrumentationData[key].b[branchKey]; - let meta; + traces.push( + ...this._extractBranchTraces( + key, + instrumentationData[key], + metaData !== undefined && key in metaData ? metaData[key] : undefined + ) + ); + } + + return traces; + } - if (metaData !== undefined && key in metaData) { - const metaPath = metaData[key]; - const metaMeta = metaPath.meta; - meta = metaMeta[branchKey.toString()]; - } + private _extractBranchTraces( + key: string, + instrumentationData: InstrumentationData, + metaData: MetaData + ): Trace[] { + const traces: Trace[] = []; + for (const branchKey of Object.keys(instrumentationData.branchMap)) { + const branch = instrumentationData.branchMap[branchKey]; + const hits = instrumentationData.b[branchKey]; + let meta; + + if (metaData !== undefined) { + const metaMeta = metaData.meta; + meta = metaMeta[branchKey.toString()]; + } + for (const [index, location] of branch.locations.entries()) { traces.push({ - id: branch.locations[0].id, + id: location.id, path: key, type: "branch", - location: branch.locations[0], + location: branch.locations[index], - hits: hits[0], + hits: hits[index], condition: meta?.condition, variables: meta?.variables, }); + } - if (branch.locations.length > 2) { - // switch case - for (const [index, location] of branch.locations.entries()) { - if (index === 0) { - continue; - } - traces.push({ - id: location.id, - path: key, - type: "branch", - location: branch.locations[index], - - hits: hits[index], - - condition: meta?.condition, - variables: meta?.variables, - }); - } - } else if (branch.locations.length === 2) { - // normal branch - // or small switch - traces.push({ - id: branch.locations[1].id, - path: key, - type: "branch", - location: branch.locations[1], - - hits: hits[1], - - condition: meta?.condition, - variables: meta?.variables, - }); - } else if ( - branch.locations.length === 1 && - branch.type === "default-arg" - ) { - // this is the default-arg branch it only has one location - traces.push({ - id: branch.locations[0].id, - path: key, - type: "branch", - location: branch.locations[0], - - hits: hits[0] ? 0 : 1, - - condition: meta?.condition, - variables: meta?.variables, - }); - } else { - throw new Error( - `Invalid number of locations for branch type: ${branch.type}` - ); - } + if ( + !( + branch.locations.length > 2 || // more than 2 means switch + branch.locations.length === 2 || // equal to 2 means if statement (or small switch) + (branch.locations.length === 1 && branch.type === "default-arg") + ) // equal to 1 means default arg + ) { + // otherwise something is wrong + throw new Error( + `Invalid number of locations for branch type: ${branch.type}` + ); } } diff --git a/libraries/search-javascript/lib/testcase/execution/SilentMochaReporter.ts b/libraries/search-javascript/lib/testcase/execution/SilentMochaReporter.ts index 9ef5590df..3d37b3221 100644 --- a/libraries/search-javascript/lib/testcase/execution/SilentMochaReporter.ts +++ b/libraries/search-javascript/lib/testcase/execution/SilentMochaReporter.ts @@ -71,6 +71,7 @@ export class SilentMochaReporter { // eslint-disable-next-line unicorn/prefer-spread .concat(error); } else { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment test.err = error; } this.failures.push(test); diff --git a/libraries/search-javascript/lib/testcase/execution/TestExecutor.ts b/libraries/search-javascript/lib/testcase/execution/TestExecutor.ts index 6a57781ae..e482aa932 100644 --- a/libraries/search-javascript/lib/testcase/execution/TestExecutor.ts +++ b/libraries/search-javascript/lib/testcase/execution/TestExecutor.ts @@ -16,15 +16,17 @@ * limitations under the License. */ +import { + InstrumentationDataMap, + MetaDataMap, +} from "@syntest/instrumentation-javascript"; import { Runner } from "mocha"; import Mocha = require("mocha"); + import { JavaScriptExecutionStatus } from "../../search/JavaScriptExecutionResult"; -import { - InstrumentationData, - MetaData, -} from "@syntest/instrumentation-javascript"; -import { SilentMochaReporter } from "./SilentMochaReporter"; + import { AssertionData } from "./AssertionData"; +import { SilentMochaReporter } from "./SilentMochaReporter"; export type Message = RunMessage | DoneMessage; @@ -39,8 +41,8 @@ export type DoneMessage = { message: "done"; suites: Suite[]; stats: Mocha.Stats; - instrumentationData: InstrumentationData; - metaData: MetaData; + instrumentationData: InstrumentationDataMap; + metaData: MetaDataMap; assertionData?: AssertionData; error?: string; }; @@ -62,6 +64,7 @@ process.on("unhandledRejection", (reason) => { throw reason; }); +// eslint-disable-next-line @typescript-eslint/no-misused-promises process.on("message", async (data: Message) => { if (typeof data !== "object") { throw new TypeError("Invalid data received from child process"); @@ -136,8 +139,8 @@ async function runMocha(silent: boolean, paths: string[], timeout: number) { }); type GlobalType = { - __coverage__: InstrumentationData; - __meta__: MetaData; + __coverage__: InstrumentationDataMap; + __meta__: MetaDataMap; __assertion__: AssertionData; }; diff --git a/libraries/search-javascript/lib/testcase/sampling/JavaScriptRandomSampler.ts b/libraries/search-javascript/lib/testcase/sampling/JavaScriptRandomSampler.ts index 55ec25391..d0c6f921d 100644 --- a/libraries/search-javascript/lib/testcase/sampling/JavaScriptRandomSampler.ts +++ b/libraries/search-javascript/lib/testcase/sampling/JavaScriptRandomSampler.ts @@ -16,10 +16,11 @@ * limitations under the License. */ +import { TargetType } from "@syntest/analysis"; import { ClassTarget, - DiscoveredObjectKind, ConstantPoolManager, + DiscoveredObjectKind, FunctionTarget, isExported, MethodTarget, @@ -30,29 +31,27 @@ import { prng } from "@syntest/prng"; import { JavaScriptSubject } from "../../search/JavaScriptSubject"; import { JavaScriptTestCase } from "../JavaScriptTestCase"; +import { StatementPool } from "../StatementPool"; +import { ActionStatement } from "../statements/action/ActionStatement"; +import { ConstantObject } from "../statements/action/ConstantObject"; +import { ConstructorCall } from "../statements/action/ConstructorCall"; +import { FunctionCall } from "../statements/action/FunctionCall"; import { Getter } from "../statements/action/Getter"; import { MethodCall } from "../statements/action/MethodCall"; +import { ObjectFunctionCall } from "../statements/action/ObjectFunctionCall"; import { Setter } from "../statements/action/Setter"; import { ArrayStatement } from "../statements/complex/ArrayStatement"; import { ArrowFunctionStatement } from "../statements/complex/ArrowFunctionStatement"; import { ObjectStatement } from "../statements/complex/ObjectStatement"; import { BoolStatement } from "../statements/primitive/BoolStatement"; +import { IntegerStatement } from "../statements/primitive/IntegerStatement"; import { NullStatement } from "../statements/primitive/NullStatement"; import { NumericStatement } from "../statements/primitive/NumericStatement"; import { StringStatement } from "../statements/primitive/StringStatement"; import { UndefinedStatement } from "../statements/primitive/UndefinedStatement"; -import { ConstructorCall } from "../statements/action/ConstructorCall"; -import { FunctionCall } from "../statements/action/FunctionCall"; -import { ConstantObject } from "../statements/action/ConstantObject"; import { Statement } from "../statements/Statement"; import { JavaScriptTestCaseSampler } from "./JavaScriptTestCaseSampler"; -import { TargetType } from "@syntest/analysis"; -import { ObjectFunctionCall } from "../statements/action/ObjectFunctionCall"; -import { ObjectType } from "@syntest/analysis-javascript"; -import { IntegerStatement } from "../statements/primitive/IntegerStatement"; -import { ActionStatement } from "../statements/action/ActionStatement"; -import { StatementPool } from "../StatementPool"; export class JavaScriptRandomSampler extends JavaScriptTestCaseSampler { constructor( @@ -487,9 +486,9 @@ export class JavaScriptRandomSampler extends JavaScriptTestCaseSampler { objectTypeId: string, property: string ): Statement { - const objectType = ( - this.rootContext.getTypeModel().getObjectDescription(objectTypeId) - ); + const objectType = this.rootContext + .getTypeModel() + .getObjectDescription(objectTypeId); const value = objectType.properties.get(property); if (!value) { diff --git a/libraries/search-javascript/lib/testcase/sampling/JavaScriptTestCaseSampler.ts b/libraries/search-javascript/lib/testcase/sampling/JavaScriptTestCaseSampler.ts index ec91674df..3082386ee 100644 --- a/libraries/search-javascript/lib/testcase/sampling/JavaScriptTestCaseSampler.ts +++ b/libraries/search-javascript/lib/testcase/sampling/JavaScriptTestCaseSampler.ts @@ -16,38 +16,38 @@ * limitations under the License. */ +import { ConstantPoolManager, RootContext } from "@syntest/analysis-javascript"; import { EncodingSampler } from "@syntest/search"; import { JavaScriptSubject } from "../../search/JavaScriptSubject"; import { JavaScriptTestCase } from "../JavaScriptTestCase"; +import { StatementPool } from "../StatementPool"; +import { ActionStatement } from "../statements/action/ActionStatement"; +import { ConstantObject } from "../statements/action/ConstantObject"; +import { ConstructorCall } from "../statements/action/ConstructorCall"; +import { FunctionCall } from "../statements/action/FunctionCall"; import { Getter } from "../statements/action/Getter"; import { MethodCall } from "../statements/action/MethodCall"; +import { ObjectFunctionCall } from "../statements/action/ObjectFunctionCall"; import { Setter } from "../statements/action/Setter"; +import { ArrayStatement } from "../statements/complex/ArrayStatement"; +import { ArrowFunctionStatement } from "../statements/complex/ArrowFunctionStatement"; +import { ObjectStatement } from "../statements/complex/ObjectStatement"; import { BoolStatement } from "../statements/primitive/BoolStatement"; +import { IntegerStatement } from "../statements/primitive/IntegerStatement"; +import { NullStatement } from "../statements/primitive/NullStatement"; import { NumericStatement } from "../statements/primitive/NumericStatement"; import { StringStatement } from "../statements/primitive/StringStatement"; -import { ConstructorCall } from "../statements/action/ConstructorCall"; -import { Statement } from "../statements/Statement"; -import { ConstantObject } from "../statements/action/ConstantObject"; -import { ObjectFunctionCall } from "../statements/action/ObjectFunctionCall"; -import { NullStatement } from "../statements/primitive/NullStatement"; import { UndefinedStatement } from "../statements/primitive/UndefinedStatement"; -import { ArrowFunctionStatement } from "../statements/complex/ArrowFunctionStatement"; -import { ArrayStatement } from "../statements/complex/ArrayStatement"; -import { ObjectStatement } from "../statements/complex/ObjectStatement"; -import { IntegerStatement } from "../statements/primitive/IntegerStatement"; -import { FunctionCall } from "../statements/action/FunctionCall"; -import { FunctionCallGenerator } from "./generators/action/FunctionCallGenerator"; -import { RootContext } from "@syntest/analysis-javascript"; -import { StatementPool } from "../StatementPool"; -import { ActionStatement } from "../statements/action/ActionStatement"; +import { Statement } from "../statements/Statement"; + +import { ConstantObjectGenerator } from "./generators/action/ConstantObjectGenerator"; import { ConstructorCallGenerator } from "./generators/action/ConstructorCallGenerator"; -import { MethodCallGenerator } from "./generators/action/MethodCallGenerator"; +import { FunctionCallGenerator } from "./generators/action/FunctionCallGenerator"; import { GetterGenerator } from "./generators/action/GetterGenerator"; -import { SetterGenerator } from "./generators/action/SetterGenerator"; -import { ConstantObjectGenerator } from "./generators/action/ConstantObjectGenerator"; +import { MethodCallGenerator } from "./generators/action/MethodCallGenerator"; import { ObjectFunctionCallGenerator } from "./generators/action/ObjectFunctionCallGenerator"; -import { ConstantPoolManager } from "@syntest/analysis-javascript"; +import { SetterGenerator } from "./generators/action/SetterGenerator"; /** * JavaScriptRandomSampler class diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/Generator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/Generator.ts index 22c086de2..6b97c629e 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/Generator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/Generator.ts @@ -16,9 +16,10 @@ * limitations under the License. */ import { RootContext } from "@syntest/analysis-javascript"; + +import { StatementPool } from "../../StatementPool"; import { Statement } from "../../statements/Statement"; import { JavaScriptTestCaseSampler } from "../JavaScriptTestCaseSampler"; -import { StatementPool } from "../../StatementPool"; export abstract class Generator { protected _sampler: JavaScriptTestCaseSampler; diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/action/CallGenerator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/action/CallGenerator.ts index bd810d916..cd0bc8235 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/action/CallGenerator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/action/CallGenerator.ts @@ -16,8 +16,9 @@ * limitations under the License. */ import { ObjectType } from "@syntest/analysis-javascript"; -import { Statement } from "../../../statements/Statement"; import { prng } from "@syntest/prng"; + +import { Statement } from "../../../statements/Statement"; import { Generator } from "../Generator"; export abstract class CallGenerator extends Generator { diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/action/ConstantObjectGenerator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/action/ConstantObjectGenerator.ts index a80bc14c6..0d0a7d691 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/action/ConstantObjectGenerator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/action/ConstantObjectGenerator.ts @@ -16,9 +16,11 @@ * limitations under the License. */ import { prng } from "@syntest/prng"; -import { CallGenerator } from "./CallGenerator"; -import { ConstantObject } from "../../../statements/action/ConstantObject"; + import { StatementPool } from "../../../StatementPool"; +import { ConstantObject } from "../../../statements/action/ConstantObject"; + +import { CallGenerator } from "./CallGenerator"; export class ConstantObjectGenerator extends CallGenerator { override generate( diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/action/ConstructorCallGenerator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/action/ConstructorCallGenerator.ts index 022c909fa..d8174f7f2 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/action/ConstructorCallGenerator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/action/ConstructorCallGenerator.ts @@ -15,11 +15,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Statement } from "../../../statements/Statement"; import { prng } from "@syntest/prng"; -import { CallGenerator } from "./CallGenerator"; -import { ConstructorCall } from "../../../statements/action/ConstructorCall"; + import { StatementPool } from "../../../StatementPool"; +import { ConstructorCall } from "../../../statements/action/ConstructorCall"; +import { Statement } from "../../../statements/Statement"; + +import { CallGenerator } from "./CallGenerator"; export class ConstructorCallGenerator extends CallGenerator { override generate( diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/action/FunctionCallGenerator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/action/FunctionCallGenerator.ts index a66d6496c..405a94913 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/action/FunctionCallGenerator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/action/FunctionCallGenerator.ts @@ -15,11 +15,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Statement } from "../../../statements/Statement"; import { prng } from "@syntest/prng"; + +import { StatementPool } from "../../../StatementPool"; import { FunctionCall } from "../../../statements/action/FunctionCall"; +import { Statement } from "../../../statements/Statement"; + import { CallGenerator } from "./CallGenerator"; -import { StatementPool } from "../../../StatementPool"; export class FunctionCallGenerator extends CallGenerator { override generate( @@ -28,7 +30,7 @@ export class FunctionCallGenerator extends CallGenerator { typeIdentifier: string, exportIdentifier: string, name: string, - statementPool: StatementPool + _statementPool: StatementPool ): FunctionCall { const type_ = this.rootContext .getTypeModel() diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/action/GetterGenerator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/action/GetterGenerator.ts index 64cff15cd..b86c529c7 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/action/GetterGenerator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/action/GetterGenerator.ts @@ -16,9 +16,11 @@ * limitations under the License. */ import { prng } from "@syntest/prng"; -import { CallGenerator } from "./CallGenerator"; -import { Getter } from "../../../statements/action/Getter"; + import { StatementPool } from "../../../StatementPool"; +import { Getter } from "../../../statements/action/Getter"; + +import { CallGenerator } from "./CallGenerator"; export class GetterGenerator extends CallGenerator { override generate( @@ -27,7 +29,7 @@ export class GetterGenerator extends CallGenerator { typeIdentifier: string, exportIdentifier: string, name: string, - statementPool: StatementPool + _statementPool: StatementPool ): Getter { const constructor_ = this.sampler.sampleConstructorCall( depth + 1, diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/action/MethodCallGenerator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/action/MethodCallGenerator.ts index 4ebd86e66..15403e612 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/action/MethodCallGenerator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/action/MethodCallGenerator.ts @@ -15,11 +15,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Statement } from "../../../statements/Statement"; import { prng } from "@syntest/prng"; -import { CallGenerator } from "./CallGenerator"; -import { MethodCall } from "../../../statements/action/MethodCall"; + import { StatementPool } from "../../../StatementPool"; +import { MethodCall } from "../../../statements/action/MethodCall"; +import { Statement } from "../../../statements/Statement"; + +import { CallGenerator } from "./CallGenerator"; export class MethodCallGenerator extends CallGenerator { override generate( @@ -28,7 +30,7 @@ export class MethodCallGenerator extends CallGenerator { typeIdentifier: string, exportIdentifier: string, name: string, - statementPool: StatementPool + _statementPool: StatementPool ): MethodCall { const type_ = this.rootContext .getTypeModel() diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/action/ObjectFunctionCallGenerator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/action/ObjectFunctionCallGenerator.ts index ec3ecef32..d92680ab4 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/action/ObjectFunctionCallGenerator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/action/ObjectFunctionCallGenerator.ts @@ -15,11 +15,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Statement } from "../../../statements/Statement"; import { prng } from "@syntest/prng"; -import { CallGenerator } from "./CallGenerator"; -import { ObjectFunctionCall } from "../../../statements/action/ObjectFunctionCall"; + import { StatementPool } from "../../../StatementPool"; +import { ObjectFunctionCall } from "../../../statements/action/ObjectFunctionCall"; +import { Statement } from "../../../statements/Statement"; + +import { CallGenerator } from "./CallGenerator"; export class ObjectFunctionCallGenerator extends CallGenerator { override generate( @@ -28,7 +30,7 @@ export class ObjectFunctionCallGenerator extends CallGenerator { override generate( @@ -28,7 +30,7 @@ export class SetterGenerator extends CallGenerator { typeIdentifier: string, exportIdentifier: string, name: string, - statementPool: StatementPool + _statementPool: StatementPool ): Setter { const type_ = this.rootContext .getTypeModel() diff --git a/libraries/search-javascript/lib/testcase/statements/Statement.ts b/libraries/search-javascript/lib/testcase/statements/Statement.ts index 57fbf9fb4..f01740c10 100644 --- a/libraries/search-javascript/lib/testcase/statements/Statement.ts +++ b/libraries/search-javascript/lib/testcase/statements/Statement.ts @@ -16,9 +16,9 @@ * limitations under the License. */ +import { TypeEnum } from "@syntest/analysis-javascript"; import { Encoding, EncodingSampler } from "@syntest/search"; -import { TypeEnum } from "@syntest/analysis-javascript"; import { ContextBuilder } from "../../testbuilding/ContextBuilder"; /** diff --git a/libraries/search-javascript/lib/testcase/statements/action/ActionStatement.ts b/libraries/search-javascript/lib/testcase/statements/action/ActionStatement.ts index bea9f6823..8656acf13 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/ActionStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/ActionStatement.ts @@ -16,10 +16,10 @@ * limitations under the License. */ +import { Export, TypeEnum } from "@syntest/analysis-javascript"; import { Encoding, EncodingSampler, shouldNeverHappen } from "@syntest/search"; import { Statement } from "../Statement"; -import { Export, TypeEnum } from "@syntest/analysis-javascript"; /** * ActionStatement diff --git a/libraries/search-javascript/lib/testcase/statements/action/ClassActionStatement.ts b/libraries/search-javascript/lib/testcase/statements/action/ClassActionStatement.ts index da6ef0ff3..aa6f9e791 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/ClassActionStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/ClassActionStatement.ts @@ -15,11 +15,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { TypeEnum } from "@syntest/analysis-javascript"; import { shouldNeverHappen } from "@syntest/search"; + import { Statement } from "../Statement"; + import { ActionStatement } from "./ActionStatement"; import { ConstructorCall } from "./ConstructorCall"; -import { TypeEnum } from "@syntest/analysis-javascript"; export abstract class ClassActionStatement extends ActionStatement { private _constructor: ConstructorCall; diff --git a/libraries/search-javascript/lib/testcase/statements/action/ConstantObject.ts b/libraries/search-javascript/lib/testcase/statements/action/ConstantObject.ts index 306c9deec..5106b19da 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/ConstantObject.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/ConstantObject.ts @@ -16,14 +16,14 @@ * limitations under the License. */ +import { Export, TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; import { Decoding } from "../Statement"; -import { Export, TypeEnum } from "@syntest/analysis-javascript"; import { ActionStatement } from "./ActionStatement"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/action/ConstructorCall.ts b/libraries/search-javascript/lib/testcase/statements/action/ConstructorCall.ts index 0d5656b88..dca7a7cc3 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/ConstructorCall.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/ConstructorCall.ts @@ -16,15 +16,15 @@ * limitations under the License. */ +import { Export, TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { MethodCall } from "./MethodCall"; import { Decoding, Statement } from "../Statement"; -import { Export, TypeEnum } from "@syntest/analysis-javascript"; import { ActionStatement } from "./ActionStatement"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; +import { MethodCall } from "./MethodCall"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/action/FunctionCall.ts b/libraries/search-javascript/lib/testcase/statements/action/FunctionCall.ts index a53abee9b..0907d551f 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/FunctionCall.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/FunctionCall.ts @@ -16,14 +16,14 @@ * limitations under the License. */ +import { Export, TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; import { Decoding, Statement } from "../Statement"; -import { Export, TypeEnum } from "@syntest/analysis-javascript"; import { ActionStatement } from "./ActionStatement"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/action/Getter.ts b/libraries/search-javascript/lib/testcase/statements/action/Getter.ts index ffefe078a..f49387978 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/Getter.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/Getter.ts @@ -16,15 +16,15 @@ * limitations under the License. */ +import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; import { Decoding } from "../Statement"; import { ClassActionStatement } from "./ClassActionStatement"; import { ConstructorCall } from "./ConstructorCall"; -import { TypeEnum } from "@syntest/analysis-javascript"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/action/MethodCall.ts b/libraries/search-javascript/lib/testcase/statements/action/MethodCall.ts index 95b0edfdc..bb74f624a 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/MethodCall.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/MethodCall.ts @@ -16,15 +16,15 @@ * limitations under the License. */ +import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; import { Decoding, Statement } from "../Statement"; -import { ConstructorCall } from "./ConstructorCall"; import { ClassActionStatement } from "./ClassActionStatement"; -import { TypeEnum } from "@syntest/analysis-javascript"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; +import { ConstructorCall } from "./ConstructorCall"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/action/ObjectFunctionCall.ts b/libraries/search-javascript/lib/testcase/statements/action/ObjectFunctionCall.ts index 6c3aaabc0..c356b9d2e 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/ObjectFunctionCall.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/ObjectFunctionCall.ts @@ -16,16 +16,16 @@ * limitations under the License. */ +import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; import { shouldNeverHappen } from "@syntest/search"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; import { Decoding, Statement } from "../Statement"; import { ActionStatement } from "./ActionStatement"; import { ConstantObject } from "./ConstantObject"; -import { TypeEnum } from "@syntest/analysis-javascript"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/action/Setter.ts b/libraries/search-javascript/lib/testcase/statements/action/Setter.ts index 54fc824e5..60e44ee65 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/Setter.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/Setter.ts @@ -16,17 +16,17 @@ * limitations under the License. */ +import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; import { Decoding, Statement } from "../Statement"; -import { Getter } from "./Getter"; -import { MethodCall } from "./MethodCall"; import { ClassActionStatement } from "./ClassActionStatement"; import { ConstructorCall } from "./ConstructorCall"; -import { TypeEnum } from "@syntest/analysis-javascript"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; +import { Getter } from "./Getter"; +import { MethodCall } from "./MethodCall"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/complex/ArrayStatement.ts b/libraries/search-javascript/lib/testcase/statements/complex/ArrayStatement.ts index aeaa84ad0..ddc216554 100644 --- a/libraries/search-javascript/lib/testcase/statements/complex/ArrayStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/complex/ArrayStatement.ts @@ -16,13 +16,13 @@ * limitations under the License. */ +import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; import { shouldNeverHappen } from "@syntest/search"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; import { Decoding, Statement } from "../Statement"; -import { TypeEnum } from "@syntest/analysis-javascript"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/complex/ArrowFunctionStatement.ts b/libraries/search-javascript/lib/testcase/statements/complex/ArrowFunctionStatement.ts index 49496e131..84a1d3717 100644 --- a/libraries/search-javascript/lib/testcase/statements/complex/ArrowFunctionStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/complex/ArrowFunctionStatement.ts @@ -16,13 +16,13 @@ * limitations under the License. */ +import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; import { shouldNeverHappen } from "@syntest/search"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; import { Decoding, Statement } from "../Statement"; -import { TypeEnum } from "@syntest/analysis-javascript"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/complex/ObjectStatement.ts b/libraries/search-javascript/lib/testcase/statements/complex/ObjectStatement.ts index dfc2c2ab2..fafdb6733 100644 --- a/libraries/search-javascript/lib/testcase/statements/complex/ObjectStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/complex/ObjectStatement.ts @@ -16,13 +16,13 @@ * limitations under the License. */ +import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; import { shouldNeverHappen } from "@syntest/search"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; import { Decoding, Statement } from "../Statement"; -import { TypeEnum } from "@syntest/analysis-javascript"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/primitive/BoolStatement.ts b/libraries/search-javascript/lib/testcase/statements/primitive/BoolStatement.ts index 1e882b975..1208b81fd 100644 --- a/libraries/search-javascript/lib/testcase/statements/primitive/BoolStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/primitive/BoolStatement.ts @@ -16,13 +16,13 @@ * limitations under the License. */ +import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; +import { Statement } from "../Statement"; import { PrimitiveStatement } from "./PrimitiveStatement"; -import { Statement } from "../Statement"; -import { TypeEnum } from "@syntest/analysis-javascript"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/primitive/IntegerStatement.ts b/libraries/search-javascript/lib/testcase/statements/primitive/IntegerStatement.ts index 054a58ee3..da6047b2e 100644 --- a/libraries/search-javascript/lib/testcase/statements/primitive/IntegerStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/primitive/IntegerStatement.ts @@ -16,14 +16,14 @@ * limitations under the License. */ +import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; - -import { PrimitiveStatement } from "./PrimitiveStatement"; import { Statement } from "../Statement"; + import { NumericStatement } from "./NumericStatement"; -import { TypeEnum } from "@syntest/analysis-javascript"; +import { PrimitiveStatement } from "./PrimitiveStatement"; /** * Generic number class diff --git a/libraries/search-javascript/lib/testcase/statements/primitive/NullStatement.ts b/libraries/search-javascript/lib/testcase/statements/primitive/NullStatement.ts index 713f26777..bb3937b4d 100644 --- a/libraries/search-javascript/lib/testcase/statements/primitive/NullStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/primitive/NullStatement.ts @@ -16,12 +16,13 @@ * limitations under the License. */ +import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; -import { PrimitiveStatement } from "./PrimitiveStatement"; import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; import { Statement } from "../Statement"; -import { TypeEnum } from "@syntest/analysis-javascript"; + +import { PrimitiveStatement } from "./PrimitiveStatement"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/primitive/NumericStatement.ts b/libraries/search-javascript/lib/testcase/statements/primitive/NumericStatement.ts index 7d6d296f2..fcbaf00f0 100644 --- a/libraries/search-javascript/lib/testcase/statements/primitive/NumericStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/primitive/NumericStatement.ts @@ -16,14 +16,14 @@ * limitations under the License. */ +import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; - -import { PrimitiveStatement } from "./PrimitiveStatement"; import { Statement } from "../Statement"; + import { IntegerStatement } from "./IntegerStatement"; -import { TypeEnum } from "@syntest/analysis-javascript"; +import { PrimitiveStatement } from "./PrimitiveStatement"; /** * Generic number class diff --git a/libraries/search-javascript/lib/testcase/statements/primitive/PrimitiveStatement.ts b/libraries/search-javascript/lib/testcase/statements/primitive/PrimitiveStatement.ts index c8f57679f..5e996ffbb 100644 --- a/libraries/search-javascript/lib/testcase/statements/primitive/PrimitiveStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/primitive/PrimitiveStatement.ts @@ -17,9 +17,10 @@ */ import { TypeEnum } from "@syntest/analysis-javascript"; + +import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; import { Decoding, Statement } from "../Statement"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; /** * @author Dimitri Stallenberg @@ -57,7 +58,7 @@ export abstract class PrimitiveStatement extends Statement { return []; } - setChild(index: number, newChild: Statement): void { + setChild(_index: number, _newChild: Statement): void { throw new Error("Primitive statements don't have children"); } diff --git a/libraries/search-javascript/lib/testcase/statements/primitive/StringStatement.ts b/libraries/search-javascript/lib/testcase/statements/primitive/StringStatement.ts index 77950dc0f..19d301225 100644 --- a/libraries/search-javascript/lib/testcase/statements/primitive/StringStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/primitive/StringStatement.ts @@ -16,14 +16,14 @@ * limitations under the License. */ +import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; import { Decoding, Statement } from "../Statement"; import { PrimitiveStatement } from "./PrimitiveStatement"; -import { TypeEnum } from "@syntest/analysis-javascript"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/primitive/UndefinedStatement.ts b/libraries/search-javascript/lib/testcase/statements/primitive/UndefinedStatement.ts index 4fef6d801..6b59d139f 100644 --- a/libraries/search-javascript/lib/testcase/statements/primitive/UndefinedStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/primitive/UndefinedStatement.ts @@ -16,12 +16,13 @@ * limitations under the License. */ +import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; -import { PrimitiveStatement } from "./PrimitiveStatement"; -import { Statement } from "../Statement"; import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { TypeEnum } from "@syntest/analysis-javascript"; +import { Statement } from "../Statement"; + +import { PrimitiveStatement } from "./PrimitiveStatement"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/test/criterion/BranchDistanceBinaryDoubleEqual.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceBinaryDoubleEqual.test.ts index ea6105f6c..d9450a65a 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceBinaryDoubleEqual.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceBinaryDoubleEqual.test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ import { expect } from "chai"; + import { BranchDistance } from "../../lib/criterion/BranchDistance"; describe("BranchDistance a == b test", () => { diff --git a/libraries/search-javascript/test/criterion/BranchDistanceBinaryDoubleNotEqual.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceBinaryDoubleNotEqual.test.ts index e0e4a224d..af962097e 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceBinaryDoubleNotEqual.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceBinaryDoubleNotEqual.test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ import { expect } from "chai"; + import { BranchDistance } from "../../lib/criterion/BranchDistance"; describe("BranchDistance a != b test", () => { diff --git a/libraries/search-javascript/test/criterion/BranchDistanceBinaryGreater.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceBinaryGreater.test.ts index dfe2a37d5..f8adc6a2d 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceBinaryGreater.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceBinaryGreater.test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ import { expect } from "chai"; + import { BranchDistance } from "../../lib/criterion/BranchDistance"; describe("BranchDistance a > b test", () => { diff --git a/libraries/search-javascript/test/criterion/BranchDistanceBinaryGreaterOrEqual.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceBinaryGreaterOrEqual.test.ts index 82eca5b35..8690ac939 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceBinaryGreaterOrEqual.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceBinaryGreaterOrEqual.test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ import { expect } from "chai"; + import { BranchDistance } from "../../lib/criterion/BranchDistance"; describe("BranchDistance a >= b test", () => { diff --git a/libraries/search-javascript/test/criterion/BranchDistanceBinarySmaller.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceBinarySmaller.test.ts index a133df40f..82b030529 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceBinarySmaller.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceBinarySmaller.test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ import { expect } from "chai"; + import { BranchDistance } from "../../lib/criterion/BranchDistance"; describe("BranchDistance a < b test", () => { diff --git a/libraries/search-javascript/test/criterion/BranchDistanceBinarySmallerOrEqual.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceBinarySmallerOrEqual.test.ts index 9be5f0e7d..f36bf4603 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceBinarySmallerOrEqual.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceBinarySmallerOrEqual.test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ import { expect } from "chai"; + import { BranchDistance } from "../../lib/criterion/BranchDistance"; describe("BranchDistance a <= b test", () => { diff --git a/libraries/search-javascript/test/criterion/BranchDistanceBinaryTrippleEqual.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceBinaryTrippleEqual.test.ts index cf48bf153..3f2353e80 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceBinaryTrippleEqual.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceBinaryTrippleEqual.test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ import { expect } from "chai"; + import { BranchDistance } from "../../lib/criterion/BranchDistance"; describe("BranchDistance a === b test", () => { diff --git a/libraries/search-javascript/test/criterion/BranchDistanceBinaryTrippleNotEqual.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceBinaryTrippleNotEqual.test.ts index 7f9bef8e6..f57b42c14 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceBinaryTrippleNotEqual.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceBinaryTrippleNotEqual.test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ import { expect } from "chai"; + import { BranchDistance } from "../../lib/criterion/BranchDistance"; describe("BranchDistance a !== b test", () => { diff --git a/libraries/search-javascript/test/criterion/BranchDistanceLogicalOr.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceLogicalOr.test.ts index 3f68cc5d1..f6fe6245c 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceLogicalOr.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceLogicalOr.test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ import { expect } from "chai"; + import { BranchDistance } from "../../lib/criterion/BranchDistance"; describe("BranchDistance a || b test", () => { diff --git a/libraries/search-javascript/test/criterion/BranchDistanceStringFunctions.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceStringFunctions.test.ts index 3beb949fc..28e45a70a 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceStringFunctions.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceStringFunctions.test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ import { expect } from "chai"; + import { BranchDistance } from "../../lib/criterion/BranchDistance"; describe("BranchDistance string functions", () => { diff --git a/libraries/search-javascript/test/criterion/BranchDistanceUnaryNot.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceUnaryNot.test.ts index ca2d5b0dc..01c0dd875 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceUnaryNot.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceUnaryNot.test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ import { expect } from "chai"; + import { BranchDistance } from "../../lib/criterion/BranchDistance"; describe("BranchDistance !a test", () => { diff --git a/libraries/search-javascript/test/criterion/BranchDistanceVisitor.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceVisitor.test.ts index 2a8a6eead..924c27060 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceVisitor.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceVisitor.test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ import { expect } from "chai"; + import { BranchDistanceVisitor } from "../../lib/criterion/BranchDistanceVisitor"; describe("BranchDistance string functions", () => { diff --git a/libraries/search-javascript/test/criterion/RandomBranchDistanceTests.test.ts b/libraries/search-javascript/test/criterion/RandomBranchDistanceTests.test.ts index 060ac5c60..f919cef05 100644 --- a/libraries/search-javascript/test/criterion/RandomBranchDistanceTests.test.ts +++ b/libraries/search-javascript/test/criterion/RandomBranchDistanceTests.test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ import { expect } from "chai"; + import { BranchDistance } from "../../lib/criterion/BranchDistance"; describe("Random Tests", () => { diff --git a/plugins/plugin-javascript-event-listener-state-storage/lib/StateStorage.ts b/plugins/plugin-javascript-event-listener-state-storage/lib/StateStorage.ts index 39d549369..60b52513f 100644 --- a/plugins/plugin-javascript-event-listener-state-storage/lib/StateStorage.ts +++ b/plugins/plugin-javascript-event-listener-state-storage/lib/StateStorage.ts @@ -17,8 +17,8 @@ */ import * as path from "node:path"; -import { StorageManager } from "@syntest/storage"; import { RootContext, TypeModel } from "@syntest/analysis-javascript"; +import { StorageManager } from "@syntest/storage"; export class StateStorage { private storageManager: StorageManager; diff --git a/tools/javascript/lib/JavaScriptLauncher.ts b/tools/javascript/lib/JavaScriptLauncher.ts index 667f49e6c..7b9fa1621 100644 --- a/tools/javascript/lib/JavaScriptLauncher.ts +++ b/tools/javascript/lib/JavaScriptLauncher.ts @@ -18,50 +18,43 @@ import * as path from "node:path"; -import { TestCommandOptions } from "./commands/test"; import { - TypeModelFactory, - InferenceTypeModelFactory, - Target, AbstractSyntaxTreeFactory, - TargetFactory, - RootContext, + ConstantPoolFactory, ControlFlowGraphFactory, - ExportFactory, DependencyFactory, - TypeExtractor, + ExportFactory, + InferenceTypeModelFactory, isExported, + RootContext, + Target, + TargetFactory, + TypeExtractor, + TypeModelFactory, } from "@syntest/analysis-javascript"; import { ArgumentsObject, + CrossoverPlugin, + FileSelector, Launcher, ObjectiveManagerPlugin, - CrossoverPlugin, - SearchAlgorithmPlugin, - TargetSelector, PluginType, - SecondaryObjectivePlugin, ProcreationPlugin, - TerminationTriggerPlugin, PropertyName, - FileSelector, + SearchAlgorithmPlugin, + SecondaryObjectivePlugin, + TargetSelector, + TerminationTriggerPlugin, } from "@syntest/base-language"; import { - UserInterface, - TableObject, ItemizationItem, + TableObject, + UserInterface, } from "@syntest/cli-graphics"; +import { Instrumenter } from "@syntest/instrumentation-javascript"; +import { getLogger, Logger } from "@syntest/logging"; +import { MetricManager } from "@syntest/metric"; import { ModuleManager } from "@syntest/module"; -import { - JavaScriptTestCase, - JavaScriptDecoder, - JavaScriptRunner, - JavaScriptSuiteBuilder, - JavaScriptSubject, - JavaScriptRandomSampler, - JavaScriptTestCaseSampler, - ExecutionInformationIntegrator, -} from "@syntest/search-javascript"; import { Archive, BudgetManager, @@ -73,11 +66,19 @@ import { TerminationManager, TotalTimeBudget, } from "@syntest/search"; -import { Instrumenter } from "@syntest/instrumentation-javascript"; -import { getLogger, Logger } from "@syntest/logging"; -import { MetricManager } from "@syntest/metric"; +import { + ExecutionInformationIntegrator, + JavaScriptDecoder, + JavaScriptRandomSampler, + JavaScriptRunner, + JavaScriptSubject, + JavaScriptSuiteBuilder, + JavaScriptTestCase, + JavaScriptTestCaseSampler, +} from "@syntest/search-javascript"; import { StorageManager } from "@syntest/storage"; -import { ConstantPoolFactory } from "@syntest/analysis-javascript"; + +import { TestCommandOptions } from "./commands/test"; export type JavaScriptArguments = ArgumentsObject & TestCommandOptions; export class JavaScriptLauncher extends Launcher { @@ -88,8 +89,6 @@ export class JavaScriptLauncher extends Launcher { private rootContext: RootContext; private archive: Archive; - private dependencyMap: Map; - private coveredInPath = new Map>(); private decoder: JavaScriptDecoder; @@ -112,6 +111,7 @@ export class JavaScriptLauncher extends Launcher { JavaScriptLauncher.LOGGER = getLogger("JavaScriptLauncher"); } + // eslint-disable-next-line @typescript-eslint/require-await async initialize(): Promise { JavaScriptLauncher.LOGGER.info("Initialization started"); const start = Date.now(); @@ -282,12 +282,18 @@ export class JavaScriptLauncher extends Launcher { ["Search Algorithm", this.arguments_.searchAlgorithm], ["Population Size", `${this.arguments_.populationSize}`], ["Objective Manager", `${this.arguments_.objectiveManager}`], - ["Secondary Objectives", `${this.arguments_.secondaryObjectives}`], + [ + "Secondary Objectives", + `[${this.arguments_.secondaryObjectives.join(", ")}]`, + ], ["Procreation Operator", `${this.arguments_.procreation}`], ["Crossover Operator", `${this.arguments_.crossover}`], ["Sampling Operator", `${this.arguments_.sampler}`], - ["Termination Triggers", `${this.arguments_.terminationTriggers}`], - ["Test Minimization Enabled", `${this.arguments_.testMinimization}`], + [ + "Termination Triggers", + `[${this.arguments_.terminationTriggers.join(", ")}]`, + ], + ["Test Minimization Enabled", String(this.arguments_.testMinimization)], ["Seed", `${this.arguments_.randomSeed.toString()}`], ], @@ -324,10 +330,13 @@ export class JavaScriptLauncher extends Launcher { // sampling ["Max Depth", `${this.arguments_.maxDepth}`], ["Max Action Statements", `${this.arguments_.maxActionStatements}`], - ["Explore Illegal Values", `${this.arguments_.exploreIllegalValues}`], + [ + "Explore Illegal Values", + String(this.arguments_.exploreIllegalValues), + ], [ "Use Constant Pool Values", - `${(this.arguments_).constantPool}`, + String((this.arguments_).constantPool), ], [ "Use Constant Pool Probability", @@ -335,7 +344,7 @@ export class JavaScriptLauncher extends Launcher { ], [ "Use Type Pool Values", - `${(this.arguments_).typePool}`, + String((this.arguments_).typePool), ], [ "Use Type Pool Probability", @@ -343,7 +352,7 @@ export class JavaScriptLauncher extends Launcher { ], [ "Use Statement Pool Values", - `${(this.arguments_).statementPool}`, + String((this.arguments_).statementPool), ], [ "Use Statement Pool Probability", @@ -363,10 +372,10 @@ export class JavaScriptLauncher extends Launcher { ], [ "Incorporate Execution Information", - `${ + String( (this.arguments_) .incorporateExecutionInformation - }`, + ), ], [ "Random Type Probability", @@ -444,16 +453,11 @@ export class JavaScriptLauncher extends Launcher { JavaScriptLauncher.LOGGER.info("Processing started"); const start = Date.now(); this.archive = new Archive(); - this.dependencyMap = new Map(); for (const target of this.targets) { JavaScriptLauncher.LOGGER.info(`Processing ${target.name}`); const archive = await this.testTarget(this.rootContext, target); - - const dependencies = this.rootContext.getDependencies(target.path); this.archive.merge(archive); - - this.dependencyMap.set(target.name, dependencies); } JavaScriptLauncher.LOGGER.info("Processing done"); const timeInMs = (Date.now() - start) / 1000; @@ -557,9 +561,9 @@ export class JavaScriptLauncher extends Launcher { table.rows.push([ `${path.basename(target.path)}: ${target.name}`, - summary["statement"] + " / " + Object.keys(data.s).length, - summary["branch"] + " / " + Object.keys(data.b).length * 2, - summary["function"] + " / " + Object.keys(data.f).length, + `${summary["statement"]} / ${Object.keys(data.s).length}`, + `${summary["branch"]} / ${Object.keys(data.b).length * 2}`, + `${summary["function"]} / ${Object.keys(data.f).length}`, target.path, ]); } @@ -609,9 +613,9 @@ export class JavaScriptLauncher extends Launcher { if (totalFunctions === 0) overall["function"] = 1; table.footers.push( - overall["statement"] * 100 + " %", - overall["branch"] * 100 + " %", - overall["function"] * 100 + " %", + `${overall["statement"] * 100} %`, + `${overall["branch"] * 100} %`, + `${overall["function"] * 100} %`, "" ); @@ -667,10 +671,6 @@ export class JavaScriptLauncher extends Launcher { return new Archive(); } - const dependencies = rootContext.getDependencies(target.path); - const dependencyMap = new Map(); - dependencyMap.set(target.name, dependencies); - const constantPoolManager = rootContext.getConstantPoolManager(target.path); const sampler = new JavaScriptRandomSampler( @@ -829,6 +829,7 @@ export class JavaScriptLauncher extends Launcher { return archive; } + // eslint-disable-next-line @typescript-eslint/require-await async exit(): Promise { JavaScriptLauncher.LOGGER.info("Exiting"); if (this.runner && this.runner.process) { diff --git a/tools/javascript/lib/JavaScriptModule.ts b/tools/javascript/lib/JavaScriptModule.ts index 3e37c9c32..6bbe0f207 100644 --- a/tools/javascript/lib/JavaScriptModule.ts +++ b/tools/javascript/lib/JavaScriptModule.ts @@ -16,23 +16,23 @@ * limitations under the License. */ -import { Module, ModuleManager, Tool } from "@syntest/module"; -import yargs = require("yargs"); - -import { getTestCommand } from "./commands/test"; import { Configuration, TestingToolModule } from "@syntest/base-language"; import { UserInterface } from "@syntest/cli-graphics"; import { MetricManager } from "@syntest/metric"; +import { Module, ModuleManager, Tool } from "@syntest/module"; import { StorageManager } from "@syntest/storage"; -import { RandomSamplerPlugin } from "./plugins/sampler/RandomSamplerPlugin"; +import yargs = require("yargs"); + +import { getTestCommand } from "./commands/test"; import { TreeCrossoverPlugin } from "./plugins/crossover/TreeCrossoverPlugin"; +import { RandomSamplerPlugin } from "./plugins/sampler/RandomSamplerPlugin"; export default class JavaScriptModule extends TestingToolModule { constructor() { super( - // eslint-disable-next-line @typescript-eslint/no-var-requires, unicorn/prefer-module + // eslint-disable-next-line @typescript-eslint/no-var-requires, unicorn/prefer-module, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access require("../../package.json").name, - // eslint-disable-next-line @typescript-eslint/no-var-requires, unicorn/prefer-module + // eslint-disable-next-line @typescript-eslint/no-var-requires, unicorn/prefer-module, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access require("../../package.json").version ); } diff --git a/tools/javascript/lib/commands/test.ts b/tools/javascript/lib/commands/test.ts index 098b963b5..65da41f32 100644 --- a/tools/javascript/lib/commands/test.ts +++ b/tools/javascript/lib/commands/test.ts @@ -16,12 +16,12 @@ * limitations under the License. */ import { UserInterface } from "@syntest/cli-graphics"; +import { MetricManager } from "@syntest/metric"; import { Command, ModuleManager } from "@syntest/module"; +import { StorageManager } from "@syntest/storage"; import Yargs = require("yargs"); import { JavaScriptArguments, JavaScriptLauncher } from "../JavaScriptLauncher"; -import { MetricManager } from "@syntest/metric"; -import { StorageManager } from "@syntest/storage"; export function getTestCommand( tool: string, diff --git a/tools/javascript/lib/plugins/sampler/RandomSamplerPlugin.ts b/tools/javascript/lib/plugins/sampler/RandomSamplerPlugin.ts index 7f0a078ff..d65808052 100644 --- a/tools/javascript/lib/plugins/sampler/RandomSamplerPlugin.ts +++ b/tools/javascript/lib/plugins/sampler/RandomSamplerPlugin.ts @@ -16,13 +16,14 @@ * limitations under the License. */ import { SamplerOptions, SamplerPlugin } from "@syntest/base-language"; +import { EncodingSampler } from "@syntest/search"; import { JavaScriptRandomSampler, JavaScriptSubject, JavaScriptTestCase, } from "@syntest/search-javascript"; + import { JavaScriptArguments } from "../../JavaScriptLauncher"; -import { EncodingSampler } from "@syntest/search"; /** * Plugin for RandomSampler From fc8ba17870a475ec2a619026631279d9df272051 Mon Sep 17 00:00:00 2001 From: Dimitri Stallenberg Date: Wed, 20 Sep 2023 00:19:14 +0200 Subject: [PATCH 02/11] fix: remove circular dependency in constructor call --- .../testcase/statements/action/ConstructorCall.ts | 12 +----------- .../lib/testcase/statements/action/MethodCall.ts | 2 +- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/libraries/search-javascript/lib/testcase/statements/action/ConstructorCall.ts b/libraries/search-javascript/lib/testcase/statements/action/ConstructorCall.ts index dca7a7cc3..f4e8db67b 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/ConstructorCall.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/ConstructorCall.ts @@ -24,10 +24,9 @@ import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSamp import { Decoding, Statement } from "../Statement"; import { ActionStatement } from "./ActionStatement"; -import { MethodCall } from "./MethodCall"; /** - * @author Dimitri Stallenberg + * ConstructorCall */ export class ConstructorCall extends ActionStatement { private _classIdentifier: string; @@ -41,7 +40,6 @@ export class ConstructorCall extends ActionStatement { * @param type the return identifierDescription of the constructor * @param uniqueId optional argument * @param args the arguments of the constructor - * @param calls the child calls on the object */ constructor( variableIdentifier: string, @@ -62,14 +60,6 @@ export class ConstructorCall extends ActionStatement { export_ ); this._classIdentifier = classIdentifier; - - for (const argument of arguments_) { - if (argument instanceof MethodCall) { - throw new TypeError( - "Constructor args cannot be of identifierDescription MethodCall" - ); - } - } } mutate(sampler: JavaScriptTestCaseSampler, depth: number): ConstructorCall { diff --git a/libraries/search-javascript/lib/testcase/statements/action/MethodCall.ts b/libraries/search-javascript/lib/testcase/statements/action/MethodCall.ts index bb74f624a..90d0904a6 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/MethodCall.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/MethodCall.ts @@ -27,7 +27,7 @@ import { ClassActionStatement } from "./ClassActionStatement"; import { ConstructorCall } from "./ConstructorCall"; /** - * @author Dimitri Stallenberg + * MethodCall */ export class MethodCall extends ClassActionStatement { /** From 9f069ad0c194ae4311e926c067a3358f35f7549a Mon Sep 17 00:00:00 2001 From: Dimitri Stallenberg Date: Wed, 20 Sep 2023 12:22:38 +0200 Subject: [PATCH 03/11] feat: implement test splitting --- .../lib/testbuilding/JavaScriptDecoder.ts | 5 +- .../testbuilding/JavaScriptSuiteBuilder.ts | 51 +---- .../lib/testcase/JavaScriptTestCase.ts | 2 +- .../testcase/execution/JavaScriptRunner.ts | 14 +- tools/javascript/lib/JavaScriptLauncher.ts | 30 +-- .../javascript/lib/workflows/testSplitting.ts | 214 ++++++++++++++++++ 6 files changed, 250 insertions(+), 66 deletions(-) create mode 100644 tools/javascript/lib/workflows/testSplitting.ts diff --git a/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts b/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts index 5f17f43c7..28160cb74 100644 --- a/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts +++ b/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts @@ -37,7 +37,6 @@ export class JavaScriptDecoder implements Decoder { decode( testCases: JavaScriptTestCase | JavaScriptTestCase[], - targetName: string, gatherAssertionData = false, sourceDirectory = "../instrumented" ): string { @@ -128,10 +127,10 @@ export class JavaScriptDecoder implements Decoder { "// Imports", ...imports, gatherAssertionData ? assertionFunction : "", - `describe('${targetName}', function() {`, + `describe('TODO proper test naming', function() {`, ...beforeEachLines, ...tests.flatMap((testLines: string[], index) => [ - `\tit("Test ${index + 1} for '${targetName}'", async () => {`, + `\tit("Test ${index + 1}", async () => {`, ...testLines.map((line) => `\t\t${line}`), index === tests.length - 1 ? "\t})" : "\t})\n", ]), diff --git a/libraries/search-javascript/lib/testbuilding/JavaScriptSuiteBuilder.ts b/libraries/search-javascript/lib/testbuilding/JavaScriptSuiteBuilder.ts index a5477b324..ecc97ffa7 100644 --- a/libraries/search-javascript/lib/testbuilding/JavaScriptSuiteBuilder.ts +++ b/libraries/search-javascript/lib/testbuilding/JavaScriptSuiteBuilder.ts @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Archive } from "@syntest/search"; +import { Target } from "@syntest/analysis"; import { StorageManager } from "@syntest/storage"; import { JavaScriptRunner } from "../testcase/execution/JavaScriptRunner"; @@ -39,7 +39,7 @@ export class JavaScriptSuiteBuilder { } async runSuite( - archive: Map, + archive: Map, sourceDirectory: string, testDirectory: string, gatherAssertionData: boolean, @@ -51,35 +51,33 @@ export class JavaScriptSuiteBuilder { // write the test cases with logs to know what to assert let totalAmount = 0; if (compact) { - for (const key of archive.keys()) { - totalAmount += archive.get(key).length; + for (const target of archive.keys()) { + totalAmount += archive.get(target).length; const decodedTest = this.decoder.decode( - archive.get(key), - `${key}`, + archive.get(target), gatherAssertionData, sourceDirectory ); const testPath = this.storageManager.store( [testDirectory], - `test-${key}.spec.js`, + `test-${target.name}.spec.js`, decodedTest, !final ); paths.push(testPath); } } else { - for (const key of archive.keys()) { - totalAmount += archive.get(key).length; - for (const testCase of archive.get(key)) { + for (const target of archive.keys()) { + totalAmount += archive.get(target).length; + for (const testCase of archive.get(target)) { const decodedTest = this.decoder.decode( testCase, - "", gatherAssertionData, sourceDirectory ); const testPath = this.storageManager.store( [testDirectory], - `test${key}${testCase.id}.spec.js`, + `test${target.name}${testCase.id}.spec.js`, decodedTest, !final ); @@ -114,33 +112,4 @@ export class JavaScriptSuiteBuilder { return { stats, instrumentationData }; } - - reduceArchive( - archive: Archive - ): Map { - const reducedArchive = new Map(); - - for (const objective of archive.getObjectives()) { - const targetName = objective - .getSubject() - .name.split("/") - .pop() - .split(".")[0]; - - if (!reducedArchive.has(targetName)) { - reducedArchive.set(targetName, []); - } - - if ( - reducedArchive.get(targetName).includes(archive.getEncoding(objective)) - ) { - // skip duplicate individuals (i.e. individuals which cover multiple objectives - continue; - } - - reducedArchive.get(targetName).push(archive.getEncoding(objective)); - } - - return reducedArchive; - } } diff --git a/libraries/search-javascript/lib/testcase/JavaScriptTestCase.ts b/libraries/search-javascript/lib/testcase/JavaScriptTestCase.ts index d3847d39f..f423be009 100644 --- a/libraries/search-javascript/lib/testcase/JavaScriptTestCase.ts +++ b/libraries/search-javascript/lib/testcase/JavaScriptTestCase.ts @@ -93,7 +93,7 @@ export class JavaScriptTestCase extends Encoding { } hashCode(decoder: Decoder): number { - const string = decoder.decode(this, `${this.id}`); + const string = decoder.decode(this); let hash = 0; for (let index = 0; index < string.length; index++) { const character = string.codePointAt(index); diff --git a/libraries/search-javascript/lib/testcase/execution/JavaScriptRunner.ts b/libraries/search-javascript/lib/testcase/execution/JavaScriptRunner.ts index f577e8533..ba41d8b10 100644 --- a/libraries/search-javascript/lib/testcase/execution/JavaScriptRunner.ts +++ b/libraries/search-javascript/lib/testcase/execution/JavaScriptRunner.ts @@ -33,7 +33,6 @@ import { JavaScriptExecutionResult, JavaScriptExecutionStatus, } from "../../search/JavaScriptExecutionResult"; -import { JavaScriptSubject } from "../../search/JavaScriptSubject"; import { JavaScriptDecoder } from "../../testbuilding/JavaScriptDecoder"; import { JavaScriptTestCase } from "../JavaScriptTestCase"; @@ -135,13 +134,16 @@ export class JavaScriptRunner implements EncodingRunner { }); } - async execute( - subject: JavaScriptSubject, - testCase: JavaScriptTestCase - ): Promise { + async executeMultiple(testCases: JavaScriptTestCase[]): Promise { + for (const testCase of testCases) { + testCase.setExecutionResult(await this.execute(testCase)); + } + } + + async execute(testCase: JavaScriptTestCase): Promise { JavaScriptRunner.LOGGER.silly("Executing test case"); - const decodedTestCase = this.decoder.decode(testCase, subject.name, false); + const decodedTestCase = this.decoder.decode(testCase, false); const testPath = this.storageManager.store( [this.tempTestDirectory], diff --git a/tools/javascript/lib/JavaScriptLauncher.ts b/tools/javascript/lib/JavaScriptLauncher.ts index 7b9fa1621..28cdecae7 100644 --- a/tools/javascript/lib/JavaScriptLauncher.ts +++ b/tools/javascript/lib/JavaScriptLauncher.ts @@ -79,6 +79,7 @@ import { import { StorageManager } from "@syntest/storage"; import { TestCommandOptions } from "./commands/test"; +import { testSplitting } from "./workflows/testSplitting"; export type JavaScriptArguments = ArgumentsObject & TestCommandOptions; export class JavaScriptLauncher extends Launcher { @@ -87,7 +88,7 @@ export class JavaScriptLauncher extends Launcher { private targets: Target[]; private rootContext: RootContext; - private archive: Archive; + private archives: Map>; private coveredInPath = new Map>(); @@ -109,6 +110,7 @@ export class JavaScriptLauncher extends Launcher { userInterface ); JavaScriptLauncher.LOGGER = getLogger("JavaScriptLauncher"); + this.archives = new Map(); } // eslint-disable-next-line @typescript-eslint/require-await @@ -452,12 +454,11 @@ export class JavaScriptLauncher extends Launcher { async process(): Promise { JavaScriptLauncher.LOGGER.info("Processing started"); const start = Date.now(); - this.archive = new Archive(); for (const target of this.targets) { JavaScriptLauncher.LOGGER.info(`Processing ${target.name}`); const archive = await this.testTarget(this.rootContext, target); - this.archive.merge(archive); + this.archives.set(target, archive); } JavaScriptLauncher.LOGGER.info("Processing done"); const timeInMs = (Date.now() - start) / 1000; @@ -467,6 +468,11 @@ export class JavaScriptLauncher extends Launcher { async postprocess(): Promise { JavaScriptLauncher.LOGGER.info("Postprocessing started"); const start = Date.now(); + JavaScriptLauncher.LOGGER.info("Minimization started"); + const finalEncodings = await testSplitting(this.runner, this.archives); + JavaScriptLauncher.LOGGER.info("Minimization done"); + let timeInMs = (Date.now() - start) / 1000; + // this.metricManager.recordProperty(PropertyName., `${timeInMs}`); // TODO new metric const suiteBuilder = new JavaScriptSuiteBuilder( this.storageManager, @@ -474,15 +480,9 @@ export class JavaScriptLauncher extends Launcher { this.runner ); - const reducedArchive = suiteBuilder.reduceArchive(this.archive); - - if (this.archive.size === 0) { - throw new Error("Zero tests were created"); - } - // TODO fix hardcoded paths await suiteBuilder.runSuite( - reducedArchive, + finalEncodings, "../instrumented", this.arguments_.testDirectory, true, @@ -495,7 +495,7 @@ export class JavaScriptLauncher extends Launcher { ]); const { stats, instrumentationData } = await suiteBuilder.runSuite( - reducedArchive, + finalEncodings, "../instrumented", this.arguments_.testDirectory, false, @@ -596,11 +596,11 @@ export class JavaScriptLauncher extends Launcher { // other results this.metricManager.recordProperty( PropertyName.ARCHIVE_SIZE, - `${this.archive.size}` + `${this.archives.size}` ); this.metricManager.recordProperty( PropertyName.MINIMIZED_ARCHIVE_SIZE, - `${this.archive.size}` + `${this.archives.size}` ); overall["statement"] /= totalStatements; @@ -630,7 +630,7 @@ export class JavaScriptLauncher extends Launcher { // create final suite await suiteBuilder.runSuite( - reducedArchive, + finalEncodings, originalSourceDirectory, this.arguments_.testDirectory, false, @@ -638,7 +638,7 @@ export class JavaScriptLauncher extends Launcher { true ); JavaScriptLauncher.LOGGER.info("Postprocessing done"); - const timeInMs = (Date.now() - start) / 1000; + timeInMs = (Date.now() - start) / 1000; this.metricManager.recordProperty( PropertyName.POSTPROCESS_TIME, `${timeInMs}` diff --git a/tools/javascript/lib/workflows/testSplitting.ts b/tools/javascript/lib/workflows/testSplitting.ts new file mode 100644 index 000000000..47d18d4e4 --- /dev/null +++ b/tools/javascript/lib/workflows/testSplitting.ts @@ -0,0 +1,214 @@ +/* + * Copyright 2020-2023 Delft University of Technology and SynTest contributors + * + * This file is part of SynTest Framework - SynTest JavaScript. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Target } from "@syntest/analysis-javascript"; +import { Archive } from "@syntest/search"; +import { + ActionStatement, + JavaScriptExecutionResult, + JavaScriptRunner, + JavaScriptTestCase, +} from "@syntest/search-javascript"; + +export async function testSplitting( + runner: JavaScriptRunner, + archives: Map> +) { + const finalEncodings = new Map(); + let total = 0; + + for (const [target, archive] of archives.entries()) { + let encodings = archive.getEncodings(); + // TODO this can be done multiple times since the splitting function only splits an encoding in two parts + // so an encoding of length 4 could be split into two encodings of length 2 and those 2 can be split into 4 encodings of length 1 + // eslint-disable-next-line no-constant-condition + while (true) { + const splitEncodings = await _testSplitting(runner, encodings); + if (encodings.length === splitEncodings.length) { + // nothing changed + break; + } + encodings = splitEncodings; + + console.log("split found, repeating"); + } + finalEncodings.set(target, encodings); + total += finalEncodings.size; + } + + if (total === 0) { + throw new Error("Zero tests were created"); + } + + return finalEncodings; +} + +async function _testSplitting( + runner: JavaScriptRunner, + originalEncodings: JavaScriptTestCase[] +) { + const finalEncodings: JavaScriptTestCase[] = []; + + for (const encoding of originalEncodings) { + // maximum of 2^(|roots| - 1) - 1 pairs + const childEncodingPairs = _splitEncoding(encoding); + // TODO in the interest of saving time we could pick random child encodings + // TODO or we could execute them in order of balance and then simply stop when we have one that works + + const possiblePairs: JavaScriptTestCase[][] = []; + for (const pair of childEncodingPairs) { + // evaluate + await runner.executeMultiple(pair); + // are they equal? + if ( + _equalResults( + encoding.getExecutionResult(), + pair.map( + (child) => child.getExecutionResult() + ) + ) + ) { + possiblePairs.push(pair); + } + } + + if (possiblePairs.length === 0) { + // no possible pairs so we use the original one + finalEncodings.push(encoding); + continue; + } + + // prefer more balanced splits (i.e. 2-2 over 1-3) + let bestBalance = Number.MAX_VALUE; + let bestPair: JavaScriptTestCase[] = possiblePairs[0]; + for (const pair of possiblePairs) { + const [encodingA, encodingB] = pair; + const balance = Math.abs(encodingA.getLength() - encodingB.getLength()); + + if (balance < bestBalance) { + bestBalance = balance; + bestPair = pair; + } + } + + console.log( + `split found: ${encoding.getLength()} -> ${bestPair[0].getLength()} + ${bestPair[1].getLength()}` + ); + finalEncodings.push(...bestPair); + } + + return finalEncodings; +} + +/** + * This function splits the encoding into two encodings in every unique possible way + * More than two splits are not considered (would require calling the function again) + * + * 1-23, 2-13, 3-12 + * 001, 010, 011 + * 110, 101, 100 + * 1-234, 2-134, 3-124, 4-123, 12-34, 13-24, 14-23 + * 1110, 1101, 1011, 1000, 1100, 1010, 1001 + * 0001, 0010, 0100, 0111, 0011, 0101, 0110 + * So if an encoding exists of 4 roots the splits are: 1-234, 2-134, 3-124, 4-123, 12-34, 13-24, 14-23 + * @param encoding + * @returns + */ +function _splitEncoding(encoding: JavaScriptTestCase): JavaScriptTestCase[][] { + const roots = encoding.roots; + + const childEncodings: JavaScriptTestCase[][] = []; + + // only consider in order combinations + for ( + let orderedCombination = 1; + orderedCombination < Math.pow(2, roots.length - 1); + orderedCombination++ + ) { + const childRoots: ActionStatement[] = []; + const oppositeChildRoots: ActionStatement[] = []; + + const binary = [ + ...orderedCombination.toString(2).padStart(roots.length, "0"), + ]; + binary.reverse(); + for (const [index, root] of roots.entries()) { + if (binary[index] === "0") { + childRoots.push(root); + } else { + oppositeChildRoots.push(root); + } + } + childEncodings.push([ + new JavaScriptTestCase(childRoots), + new JavaScriptTestCase(oppositeChildRoots), + ]); + } + + return childEncodings; +} + +function _equalResults( + originalResult: JavaScriptExecutionResult, + splitResults: JavaScriptExecutionResult[] +): boolean { + // compare errors + if (originalResult.hasError()) { + let notEqual = true; + for (const result of splitResults) { + if ( + result.hasError() && + _equalErrors(originalResult.getError(), result.getError()) + ) { + notEqual = false; + } + } + if (notEqual) { + return false; + } + } + + // compare traces + const traceMap = new Map(); + for (const trace of originalResult.getTraces()) { + if (trace.hits > 0) { + traceMap.set(trace.id, false); + } + } + for (const result of splitResults) { + for (const trace of result.getTraces()) { + if (trace.hits > 0) { + if (!traceMap.has(trace.id)) { + // ?? we covered a new trace?? + continue; + } + traceMap.set(trace.id, true); + } + } + } + + return [...traceMap.values()].some(Boolean); +} + +function _equalErrors(errorA: Error, errorB: Error) { + return ( + errorA.name === errorB.name && + errorA.message === errorB.message && + errorA.stack === errorB.stack + ); +} From e3c762e6899151f6468f72bed8e2bea6ac4d2cd8 Mon Sep 17 00:00:00 2001 From: Dimitri Stallenberg Date: Wed, 20 Sep 2023 15:58:17 +0200 Subject: [PATCH 04/11] feat: finalize test de-duplication --- .../lib/search/JavaScriptExecutionResult.ts | 25 +- .../lib/testbuilding/JavaScriptDecoder.ts | 10 +- tools/javascript/lib/JavaScriptLauncher.ts | 96 +++++++- .../javascript/lib/workflows/DeDuplicator.ts | 90 +++++++ tools/javascript/lib/workflows/MetaComment.ts | 101 ++++++++ .../javascript/lib/workflows/TestSplitter.ts | 227 ++++++++++++++++++ .../javascript/lib/workflows/testSplitting.ts | 214 ----------------- 7 files changed, 538 insertions(+), 225 deletions(-) create mode 100644 tools/javascript/lib/workflows/DeDuplicator.ts create mode 100644 tools/javascript/lib/workflows/MetaComment.ts create mode 100644 tools/javascript/lib/workflows/TestSplitter.ts delete mode 100644 tools/javascript/lib/workflows/testSplitting.ts diff --git a/libraries/search-javascript/lib/search/JavaScriptExecutionResult.ts b/libraries/search-javascript/lib/search/JavaScriptExecutionResult.ts index 0e229ba3c..910aded36 100644 --- a/libraries/search-javascript/lib/search/JavaScriptExecutionResult.ts +++ b/libraries/search-javascript/lib/search/JavaScriptExecutionResult.ts @@ -15,6 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import * as crypto from "node:crypto"; import { ExecutionResult, Trace } from "@syntest/search"; @@ -28,8 +29,6 @@ export enum JavaScriptExecutionStatus { /** * JavaScript specific implementation of the execution results. - * - * @author Mitchell Olsthoorn */ export class JavaScriptExecutionResult implements ExecutionResult { /** @@ -87,10 +86,14 @@ export class JavaScriptExecutionResult implements ExecutionResult { return false; } + if (id.startsWith("error:::")) { + return this.hasError() && this.getErrorIdentifier() === id; + } + const trace = this._traces.find((trace) => trace.id === id); if (!trace) { - if (id.startsWith("placeholder")) { + if (id.startsWith("placeholder:::")) { // TODO maybe this already fixed? // TODO stupit hack because the placeholder nodes we add in the cfg are not being registred by the instrumentation // should fix @@ -136,6 +139,22 @@ export class JavaScriptExecutionResult implements ExecutionResult { return this._error; } + public getErrorIdentifier(): string { + let stack = this.getError().stack; + + stack = stack + ? stack + .split("\n") + // only use location lines + .filter((line) => line.startsWith(" at")) + // only use locations within the source code (i.e. not from the generated tests) + .filter((line) => line.includes("/instrumented/")) // stupid hack should be done better somehow, suffices for now + .join("\n") + : this.getError().message; + + return "error:::" + crypto.createHash("md5").update(stack).digest("hex"); + } + /** * @inheritDoc */ diff --git a/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts b/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts index 28160cb74..7e1c5a30e 100644 --- a/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts +++ b/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts @@ -245,10 +245,18 @@ export class JavaScriptDecoder implements Decoder { } if (errorDecoding) { + let value = testCase.assertionData.error.error.message; + + value = value.replaceAll(/\\/g, "\\\\"); + value = value.replaceAll(/\n/g, "\\n"); + value = value.replaceAll(/\r/g, "\\r"); + value = value.replaceAll(/\t/g, "\\t"); + value = value.replaceAll(/"/g, '\\"'); + assertions.push( `await expect((async () => {`, `\t${errorDecoding.decoded.split(" = ")[1]}`, - `})()).to.be.rejectedWith(\`${testCase.assertionData.error.error.message}\`)` + `})()).to.be.rejectedWith("${value}")` ); } diff --git a/tools/javascript/lib/JavaScriptLauncher.ts b/tools/javascript/lib/JavaScriptLauncher.ts index 28cdecae7..7688d7d0a 100644 --- a/tools/javascript/lib/JavaScriptLauncher.ts +++ b/tools/javascript/lib/JavaScriptLauncher.ts @@ -62,6 +62,7 @@ import { EncodingSampler, EvaluationBudget, IterationBudget, + ObjectiveFunction, SearchTimeBudget, TerminationManager, TotalTimeBudget, @@ -79,7 +80,9 @@ import { import { StorageManager } from "@syntest/storage"; import { TestCommandOptions } from "./commands/test"; -import { testSplitting } from "./workflows/testSplitting"; +import { DeDuplicator } from "./workflows/DeDuplicator"; +import { addMetaComments } from "./workflows/MetaComment"; +import { TestSplitting } from "./workflows/TestSplitter"; export type JavaScriptArguments = ArgumentsObject & TestCommandOptions; export class JavaScriptLauncher extends Launcher { @@ -468,11 +471,89 @@ export class JavaScriptLauncher extends Launcher { async postprocess(): Promise { JavaScriptLauncher.LOGGER.info("Postprocessing started"); const start = Date.now(); - JavaScriptLauncher.LOGGER.info("Minimization started"); - const finalEncodings = await testSplitting(this.runner, this.archives); - JavaScriptLauncher.LOGGER.info("Minimization done"); - let timeInMs = (Date.now() - start) / 1000; - // this.metricManager.recordProperty(PropertyName., `${timeInMs}`); // TODO new metric + const testSplitter = new TestSplitting(this.runner); + const objectives = new Map[]>( + [...this.archives.entries()].map(([target, archive]) => [ + target, + archive.getObjectives(), + ]) + ); + let finalEncodings = new Map( + [...this.archives.entries()].map(([target, archive]) => [ + target, + archive.getEncodings(), + ]) + ); + + if (this.arguments_.testSplitting) { + const start = Date.now(); + const before = [...finalEncodings.values()] + .map((x) => x.length) + .reduce((p, c) => p + c); + JavaScriptLauncher.LOGGER.info("Splitting started"); + finalEncodings = await testSplitter.testSplitting(finalEncodings); + + const timeInMs = (Date.now() - start) / 1000; + const after = [...finalEncodings.values()] + .map((x) => x.length) + .reduce((p, c) => p + c); + + JavaScriptLauncher.LOGGER.info( + `Splitting done took: ${timeInMs}, went from ${before} to ${after} test cases` + ); + // this.metricManager.recordProperty(PropertyName., `${timeInMs}`); // TODO new metric + } + if (this.arguments_.testMinimization) { + const start = Date.now(); + JavaScriptLauncher.LOGGER.info("Minimization started"); + const timeInMs = (Date.now() - start) / 1000; + JavaScriptLauncher.LOGGER.info(`Minimization done, took: ${timeInMs}`); + // this.metricManager.recordProperty(PropertyName., `${timeInMs}`); // TODO new metric + } + + const secondaryObjectives = new Set( + this.arguments_.secondaryObjectives.map((secondaryObjective) => { + return (>( + this.moduleManager.getPlugin( + PluginType.SecondaryObjective, + secondaryObjective + ) + )).createSecondaryObjective(); + }) + ); + + const startDeduplication = Date.now(); + const before = [...finalEncodings.values()] + .map((x) => x.length) + .reduce((p, c) => p + c); + JavaScriptLauncher.LOGGER.info("De-Duplication started"); + + const deDuplicator = new DeDuplicator(); + const newArchives = deDuplicator.deDuplicate( + secondaryObjectives, + objectives, + finalEncodings + ); + + const timeInMsDeDuplication = (Date.now() - startDeduplication) / 1000; + const after = [...newArchives.values()] + .map((x) => x.size) + .reduce((p, c) => p + c); + + JavaScriptLauncher.LOGGER.info( + `De-Duplication done took: ${timeInMsDeDuplication}, went from ${before} to ${after} test cases` + ); + + if (this.arguments_.metaComments) { + addMetaComments(newArchives); + } + + finalEncodings = new Map( + [...newArchives.entries()].map(([target, archive]) => [ + target, + archive.getEncodings(), + ]) + ); const suiteBuilder = new JavaScriptSuiteBuilder( this.storageManager, @@ -638,7 +719,7 @@ export class JavaScriptLauncher extends Launcher { true ); JavaScriptLauncher.LOGGER.info("Postprocessing done"); - timeInMs = (Date.now() - start) / 1000; + const timeInMs = (Date.now() - start) / 1000; this.metricManager.recordProperty( PropertyName.POSTPROCESS_TIME, `${timeInMs}` @@ -713,6 +794,7 @@ export class JavaScriptLauncher extends Launcher { )).createObjectiveManager({ runner: this.runner, secondaryObjectives: secondaryObjectives, + exceptionObjectivesEnabled: this.arguments_.exceptionObjectives, }); const crossover = (>( diff --git a/tools/javascript/lib/workflows/DeDuplicator.ts b/tools/javascript/lib/workflows/DeDuplicator.ts new file mode 100644 index 000000000..f03b591cb --- /dev/null +++ b/tools/javascript/lib/workflows/DeDuplicator.ts @@ -0,0 +1,90 @@ +/* + * Copyright 2020-2023 Delft University of Technology and SynTest contributors + * + * This file is part of SynTest Framework - SynTest JavaScript. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Target } from "@syntest/analysis-javascript"; +import { getLogger, Logger } from "@syntest/logging"; +import { + Archive, + ObjectiveFunction, + SecondaryObjectiveComparator, +} from "@syntest/search"; +import { JavaScriptTestCase } from "@syntest/search-javascript"; + +export class DeDuplicator { + protected static LOGGER: Logger; + constructor() { + DeDuplicator.LOGGER = getLogger("DeDuplicator"); + } + + deDuplicate( + secondaryObjectives: Set>, + objectivesMap: Map[]>, + encodingsMap: Map + ): Map> { + const archives = new Map>(); + for (const [target, encodings] of encodingsMap.entries()) { + const objectives = objectivesMap.get(target); + + const archive = new Archive(); + archives.set(target, archive); + + for (const encoding of encodings) { + const executionResult = encoding.getExecutionResult(); + + if (!executionResult) { + throw new Error("Invalid encoding without executionResult"); + } + + for (const objective of objectives) { + if (executionResult.coversId(objective.getIdentifier())) { + if (!archive.hasObjective(objective)) { + DeDuplicator.LOGGER.debug("Adding new encoding to archive"); + archive.update(objective, encoding, false); + continue; + } + + // If the objective is already in the archive we use secondary objectives + const currentEncoding = archive.getEncoding(objective); + + // Look at secondary objectives when two solutions are found + for (const secondaryObjective of secondaryObjectives) { + const comparison = secondaryObjective.compare( + encoding, + currentEncoding + ); + + // If one of the two encodings is better, don't evaluate the next objectives + if (comparison != 0) { + // Override the encoding if the current one is better + if (comparison > 0) { + DeDuplicator.LOGGER.debug( + "Overwriting archive with better encoding" + ); + + archive.update(objective, encoding, false); + } + break; + } + } + } + } + } + } + + return archives; + } +} diff --git a/tools/javascript/lib/workflows/MetaComment.ts b/tools/javascript/lib/workflows/MetaComment.ts new file mode 100644 index 000000000..81ab7f622 --- /dev/null +++ b/tools/javascript/lib/workflows/MetaComment.ts @@ -0,0 +1,101 @@ +/* + * Copyright 2020-2023 Delft University of Technology and SynTest contributors + * + * This file is part of SynTest Framework - SynTest JavaScript. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Target } from "@syntest/analysis-javascript"; +import { Archive, ExceptionObjectiveFunction } from "@syntest/search"; +import { JavaScriptTestCase } from "@syntest/search-javascript"; + +export function addMetaComments( + archives: Map> +) { + for (const [, archive] of archives) { + const encodings = archive.getEncodings(); + for (const encoding of encodings) { + const uses = archive.getUses(encoding); + for (const use of uses) { + if (use instanceof ExceptionObjectiveFunction) { + encoding.addMetaComment(`Selected for:`); + for (const line of use.error.stack.split("\n")) { + encoding.addMetaComment(`\t${line}`); + } + encoding.addMetaComment(""); + } else { + encoding.addMetaComment( + `Selected for objective: ${use.getIdentifier()}` + ); + } + } + + const executionResult = encoding.getExecutionResult(); + if (executionResult) { + for (const objective of archive.getObjectives()) { + if (executionResult.coversId(objective.getIdentifier())) { + encoding.addMetaComment( + `Covers objective: ${objective.getIdentifier()}` + ); + } + } + } + } + } +} + +// export function addMetaComments( +// objectivesMap: Map[]>, +// encodingsMap: Map +// ) { +// for (const [target, encodings] of encodingsMap.entries()) { +// const objectives = objectivesMap.get(target) +// const coveredBy = new Map, Set>(objectives.map((objective) => [objective, new Set()])) +// for (const encoding of encodings) { +// const executionResult = encoding.getExecutionResult(); + +// if (!executionResult) { +// throw new Error("Invalid encoding without executionResult") +// } + +// for (const objective of objectives) { +// if (executionResult.coversId(objective.getIdentifier())) { +// encoding.addMetaComment( +// `Covers objective: ${objective.getIdentifier()}` +// ); + +// coveredBy.get(objective).add(encoding) +// } +// } +// } + +// for (const [objective, encodings] of coveredBy.entries()) { +// if (encodings.size !== 1) { +// continue +// } +// const encoding = [...encodings][0] +// if (objective instanceof ExceptionObjectiveFunction) { +// encoding.addMetaComment(`Selected for:`); +// for (const line of objective.error.stack.split("\n")) { +// encoding.addMetaComment(`\t${line}`); +// } +// encoding.addMetaComment(""); +// } else { +// encoding.addMetaComment( +// `Selected for objective: ${objective.getIdentifier()}` +// ); +// } +// } +// } +// } diff --git a/tools/javascript/lib/workflows/TestSplitter.ts b/tools/javascript/lib/workflows/TestSplitter.ts new file mode 100644 index 000000000..734797b98 --- /dev/null +++ b/tools/javascript/lib/workflows/TestSplitter.ts @@ -0,0 +1,227 @@ +/* + * Copyright 2020-2023 Delft University of Technology and SynTest contributors + * + * This file is part of SynTest Framework - SynTest JavaScript. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Target } from "@syntest/analysis-javascript"; +import { getLogger, Logger } from "@syntest/logging"; +import { + ActionStatement, + JavaScriptExecutionResult, + JavaScriptRunner, + JavaScriptTestCase, +} from "@syntest/search-javascript"; + +export class TestSplitting { + protected static LOGGER: Logger; + protected runner: JavaScriptRunner; + + constructor(runner: JavaScriptRunner) { + TestSplitting.LOGGER = getLogger("TestSplitting"); + this.runner = runner; + } + + public async testSplitting(encodingMap: Map) { + const finalEncodings = new Map(); + let total = 0; + + // eslint-disable-next-line prefer-const + for (let [target, encodings] of encodingMap.entries()) { + // TODO this can be done multiple times since the splitting function only splits an encoding in two parts + // so an encoding of length 4 could be split into two encodings of length 2 and those 2 can be split into 4 encodings of length 1 + let round = 0; + // eslint-disable-next-line no-constant-condition + while (true) { + const splitEncodings = await this._testSplitting(encodings); + if (encodings.length === splitEncodings.length) { + // nothing changed + break; + } + encodings = splitEncodings; + + round += 1; + + TestSplitting.LOGGER.info(`Split found, repeating. Round ${round}`); + } + finalEncodings.set(target, encodings); + total += finalEncodings.size; + } + + if (total === 0) { + throw new Error("Zero tests were created"); + } + + return finalEncodings; + } + + private async _testSplitting(originalEncodings: JavaScriptTestCase[]) { + const finalEncodings: JavaScriptTestCase[] = []; + + for (const encoding of originalEncodings) { + const executionResult = encoding.getExecutionResult(); + + if (!executionResult) { + throw new Error("Invalid encoding without executionResult"); + } + + // maximum of 2^(|roots| - 1) - 1 pairs + const childEncodingPairs = this._splitEncoding(encoding); + // TODO in the interest of saving time we could pick random child encodings + // TODO or we could execute them in order of balance and then simply stop when we have one that works + + const possiblePairs: JavaScriptTestCase[][] = []; + for (const pair of childEncodingPairs) { + // evaluate + await this.runner.executeMultiple(pair); + // are they equal? + if ( + this._equalResults( + executionResult, + pair.map( + (child) => child.getExecutionResult() + ) + ) + ) { + possiblePairs.push(pair); + } + } + + if (possiblePairs.length === 0) { + // no possible pairs so we use the original one + finalEncodings.push(encoding); + continue; + } + + // prefer more balanced splits (i.e. 2-2 over 1-3) + let bestBalance = Number.MAX_VALUE; + let bestPair: JavaScriptTestCase[] = possiblePairs[0]; + for (const pair of possiblePairs) { + const [encodingA, encodingB] = pair; + const balance = Math.abs(encodingA.getLength() - encodingB.getLength()); + + if (balance < bestBalance) { + bestBalance = balance; + bestPair = pair; + } + } + + TestSplitting.LOGGER.debug( + `Split found: ${encoding.getLength()} -> ${bestPair[0].getLength()} + ${bestPair[1].getLength()}` + ); + finalEncodings.push(...bestPair); + } + + return finalEncodings; + } + + /** + * This function splits the encoding into two encodings in every unique possible way + * More than two splits are not considered (would require calling the function again) + * + * 1-23, 2-13, 3-12 + * 001, 010, 011 + * 110, 101, 100 + * 1-234, 2-134, 3-124, 4-123, 12-34, 13-24, 14-23 + * 1110, 1101, 1011, 1000, 1100, 1010, 1001 + * 0001, 0010, 0100, 0111, 0011, 0101, 0110 + * So if an encoding exists of 4 roots the splits are: 1-234, 2-134, 3-124, 4-123, 12-34, 13-24, 14-23 + * @param encoding + * @returns + */ + private _splitEncoding(encoding: JavaScriptTestCase): JavaScriptTestCase[][] { + const roots = encoding.roots; + + const childEncodings: JavaScriptTestCase[][] = []; + + // only consider in order combinations + for ( + let orderedCombination = 1; + orderedCombination < Math.pow(2, roots.length - 1); + orderedCombination++ + ) { + const childRoots: ActionStatement[] = []; + const oppositeChildRoots: ActionStatement[] = []; + + const binary = [ + ...orderedCombination.toString(2).padStart(roots.length, "0"), + ]; + binary.reverse(); + for (const [index, root] of roots.entries()) { + if (binary[index] === "0") { + childRoots.push(root); + } else { + oppositeChildRoots.push(root); + } + } + childEncodings.push([ + new JavaScriptTestCase(childRoots), + new JavaScriptTestCase(oppositeChildRoots), + ]); + } + + return childEncodings; + } + + private _equalResults( + originalResult: JavaScriptExecutionResult, + splitResults: JavaScriptExecutionResult[] + ): boolean { + // compare errors + if (originalResult.hasError()) { + let notEqual = true; + for (const result of splitResults) { + if ( + result.hasError() && + this._equalErrors(originalResult.getError(), result.getError()) + ) { + notEqual = false; + } + } + if (notEqual) { + return false; + } + } + + // compare traces + const traceMap = new Map(); + for (const trace of originalResult.getTraces()) { + if (trace.hits > 0) { + traceMap.set(trace.id, false); + } + } + for (const result of splitResults) { + for (const trace of result.getTraces()) { + if (trace.hits > 0) { + if (!traceMap.has(trace.id)) { + // ?? we covered a new trace?? + continue; + } + traceMap.set(trace.id, true); + } + } + } + + return [...traceMap.values()].some(Boolean); + } + + private _equalErrors(errorA: Error, errorB: Error) { + return ( + errorA.name === errorB.name && + errorA.message === errorB.message && + errorA.stack === errorB.stack + ); + } +} diff --git a/tools/javascript/lib/workflows/testSplitting.ts b/tools/javascript/lib/workflows/testSplitting.ts deleted file mode 100644 index 47d18d4e4..000000000 --- a/tools/javascript/lib/workflows/testSplitting.ts +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright 2020-2023 Delft University of Technology and SynTest contributors - * - * This file is part of SynTest Framework - SynTest JavaScript. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Target } from "@syntest/analysis-javascript"; -import { Archive } from "@syntest/search"; -import { - ActionStatement, - JavaScriptExecutionResult, - JavaScriptRunner, - JavaScriptTestCase, -} from "@syntest/search-javascript"; - -export async function testSplitting( - runner: JavaScriptRunner, - archives: Map> -) { - const finalEncodings = new Map(); - let total = 0; - - for (const [target, archive] of archives.entries()) { - let encodings = archive.getEncodings(); - // TODO this can be done multiple times since the splitting function only splits an encoding in two parts - // so an encoding of length 4 could be split into two encodings of length 2 and those 2 can be split into 4 encodings of length 1 - // eslint-disable-next-line no-constant-condition - while (true) { - const splitEncodings = await _testSplitting(runner, encodings); - if (encodings.length === splitEncodings.length) { - // nothing changed - break; - } - encodings = splitEncodings; - - console.log("split found, repeating"); - } - finalEncodings.set(target, encodings); - total += finalEncodings.size; - } - - if (total === 0) { - throw new Error("Zero tests were created"); - } - - return finalEncodings; -} - -async function _testSplitting( - runner: JavaScriptRunner, - originalEncodings: JavaScriptTestCase[] -) { - const finalEncodings: JavaScriptTestCase[] = []; - - for (const encoding of originalEncodings) { - // maximum of 2^(|roots| - 1) - 1 pairs - const childEncodingPairs = _splitEncoding(encoding); - // TODO in the interest of saving time we could pick random child encodings - // TODO or we could execute them in order of balance and then simply stop when we have one that works - - const possiblePairs: JavaScriptTestCase[][] = []; - for (const pair of childEncodingPairs) { - // evaluate - await runner.executeMultiple(pair); - // are they equal? - if ( - _equalResults( - encoding.getExecutionResult(), - pair.map( - (child) => child.getExecutionResult() - ) - ) - ) { - possiblePairs.push(pair); - } - } - - if (possiblePairs.length === 0) { - // no possible pairs so we use the original one - finalEncodings.push(encoding); - continue; - } - - // prefer more balanced splits (i.e. 2-2 over 1-3) - let bestBalance = Number.MAX_VALUE; - let bestPair: JavaScriptTestCase[] = possiblePairs[0]; - for (const pair of possiblePairs) { - const [encodingA, encodingB] = pair; - const balance = Math.abs(encodingA.getLength() - encodingB.getLength()); - - if (balance < bestBalance) { - bestBalance = balance; - bestPair = pair; - } - } - - console.log( - `split found: ${encoding.getLength()} -> ${bestPair[0].getLength()} + ${bestPair[1].getLength()}` - ); - finalEncodings.push(...bestPair); - } - - return finalEncodings; -} - -/** - * This function splits the encoding into two encodings in every unique possible way - * More than two splits are not considered (would require calling the function again) - * - * 1-23, 2-13, 3-12 - * 001, 010, 011 - * 110, 101, 100 - * 1-234, 2-134, 3-124, 4-123, 12-34, 13-24, 14-23 - * 1110, 1101, 1011, 1000, 1100, 1010, 1001 - * 0001, 0010, 0100, 0111, 0011, 0101, 0110 - * So if an encoding exists of 4 roots the splits are: 1-234, 2-134, 3-124, 4-123, 12-34, 13-24, 14-23 - * @param encoding - * @returns - */ -function _splitEncoding(encoding: JavaScriptTestCase): JavaScriptTestCase[][] { - const roots = encoding.roots; - - const childEncodings: JavaScriptTestCase[][] = []; - - // only consider in order combinations - for ( - let orderedCombination = 1; - orderedCombination < Math.pow(2, roots.length - 1); - orderedCombination++ - ) { - const childRoots: ActionStatement[] = []; - const oppositeChildRoots: ActionStatement[] = []; - - const binary = [ - ...orderedCombination.toString(2).padStart(roots.length, "0"), - ]; - binary.reverse(); - for (const [index, root] of roots.entries()) { - if (binary[index] === "0") { - childRoots.push(root); - } else { - oppositeChildRoots.push(root); - } - } - childEncodings.push([ - new JavaScriptTestCase(childRoots), - new JavaScriptTestCase(oppositeChildRoots), - ]); - } - - return childEncodings; -} - -function _equalResults( - originalResult: JavaScriptExecutionResult, - splitResults: JavaScriptExecutionResult[] -): boolean { - // compare errors - if (originalResult.hasError()) { - let notEqual = true; - for (const result of splitResults) { - if ( - result.hasError() && - _equalErrors(originalResult.getError(), result.getError()) - ) { - notEqual = false; - } - } - if (notEqual) { - return false; - } - } - - // compare traces - const traceMap = new Map(); - for (const trace of originalResult.getTraces()) { - if (trace.hits > 0) { - traceMap.set(trace.id, false); - } - } - for (const result of splitResults) { - for (const trace of result.getTraces()) { - if (trace.hits > 0) { - if (!traceMap.has(trace.id)) { - // ?? we covered a new trace?? - continue; - } - traceMap.set(trace.id, true); - } - } - } - - return [...traceMap.values()].some(Boolean); -} - -function _equalErrors(errorA: Error, errorB: Error) { - return ( - errorA.name === errorB.name && - errorA.message === errorB.message && - errorA.stack === errorB.stack - ); -} From 3f733c4e86a3e866258a3ec7d967a77042cd4d6f Mon Sep 17 00:00:00 2001 From: Dimitri Stallenberg Date: Wed, 20 Sep 2023 17:28:10 +0200 Subject: [PATCH 05/11] fix: update secondary objective stuff --- tools/javascript/lib/JavaScriptLauncher.ts | 12 ++++++------ tools/javascript/lib/workflows/DeDuplicator.ts | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/javascript/lib/JavaScriptLauncher.ts b/tools/javascript/lib/JavaScriptLauncher.ts index 7688d7d0a..cf3a1dd84 100644 --- a/tools/javascript/lib/JavaScriptLauncher.ts +++ b/tools/javascript/lib/JavaScriptLauncher.ts @@ -511,15 +511,15 @@ export class JavaScriptLauncher extends Launcher { // this.metricManager.recordProperty(PropertyName., `${timeInMs}`); // TODO new metric } - const secondaryObjectives = new Set( - this.arguments_.secondaryObjectives.map((secondaryObjective) => { + const secondaryObjectives = this.arguments_.secondaryObjectives.map( + (secondaryObjective) => { return (>( this.moduleManager.getPlugin( PluginType.SecondaryObjective, secondaryObjective ) )).createSecondaryObjective(); - }) + } ); const startDeduplication = Date.now(); @@ -775,15 +775,15 @@ export class JavaScriptLauncher extends Launcher { ); sampler.rootContext = rootContext; - const secondaryObjectives = new Set( - this.arguments_.secondaryObjectives.map((secondaryObjective) => { + const secondaryObjectives = this.arguments_.secondaryObjectives.map( + (secondaryObjective) => { return (>( this.moduleManager.getPlugin( PluginType.SecondaryObjective, secondaryObjective ) )).createSecondaryObjective(); - }) + } ); const objectiveManager = (>( diff --git a/tools/javascript/lib/workflows/DeDuplicator.ts b/tools/javascript/lib/workflows/DeDuplicator.ts index f03b591cb..94514f14d 100644 --- a/tools/javascript/lib/workflows/DeDuplicator.ts +++ b/tools/javascript/lib/workflows/DeDuplicator.ts @@ -31,7 +31,7 @@ export class DeDuplicator { } deDuplicate( - secondaryObjectives: Set>, + secondaryObjectives: SecondaryObjectiveComparator[], objectivesMap: Map[]>, encodingsMap: Map ): Map> { From f66d35f7fba6bc76ebbd91b158ae34722e94c8fc Mon Sep 17 00:00:00 2001 From: Dimitri Stallenberg Date: Wed, 20 Sep 2023 18:35:59 +0200 Subject: [PATCH 06/11] fix: reset instrumentation data --- .../lib/testcase/execution/TestExecutor.ts | 44 +++++++++++++++---- tools/javascript/lib/JavaScriptLauncher.ts | 8 ++-- .../javascript/lib/workflows/TestSplitter.ts | 32 +++++++------- 3 files changed, 56 insertions(+), 28 deletions(-) diff --git a/libraries/search-javascript/lib/testcase/execution/TestExecutor.ts b/libraries/search-javascript/lib/testcase/execution/TestExecutor.ts index e482aa932..c5b9eedcb 100644 --- a/libraries/search-javascript/lib/testcase/execution/TestExecutor.ts +++ b/libraries/search-javascript/lib/testcase/execution/TestExecutor.ts @@ -20,6 +20,7 @@ import { InstrumentationDataMap, MetaDataMap, } from "@syntest/instrumentation-javascript"; +import cloneDeep = require("lodash.clonedeep"); import { Runner } from "mocha"; import Mocha = require("mocha"); @@ -138,22 +139,47 @@ async function runMocha(silent: boolean, paths: string[], timeout: number) { }; }); - type GlobalType = { - __coverage__: InstrumentationDataMap; - __meta__: MetaDataMap; - __assertion__: AssertionData; - }; - // Retrieve execution traces const result: DoneMessage = { message: "done", suites: suites, stats: runner.stats, - instrumentationData: ((global)).__coverage__, - metaData: ((global)).__meta__, - assertionData: ((global)).__assertion__, + instrumentationData: cloneDeep( + ((global)).__coverage__ + ), + metaData: cloneDeep(((global)).__meta__), + assertionData: cloneDeep(((global)).__assertion__), }; + resetInstrumentationData(); + ((global)).__meta__ = undefined; + ((global)).__assertion__ = undefined; process.send(result); mocha.dispose(); } + +function resetInstrumentationData() { + const coverage = ((global)).__coverage__; + + if (coverage === undefined) { + return; + } + + for (const key of Object.keys(coverage)) { + for (const statementKey of Object.keys(coverage[key].s)) { + coverage[key].s[statementKey] = 0; + } + for (const functionKey of Object.keys(coverage[key].f)) { + coverage[key].f[functionKey] = 0; + } + for (const branchKey of Object.keys(coverage[key].b)) { + coverage[key].b[branchKey] = [0, 0]; + } + } +} + +type GlobalType = { + __coverage__: InstrumentationDataMap; + __meta__: MetaDataMap; + __assertion__: AssertionData; +}; diff --git a/tools/javascript/lib/JavaScriptLauncher.ts b/tools/javascript/lib/JavaScriptLauncher.ts index cf3a1dd84..2c7b343a7 100644 --- a/tools/javascript/lib/JavaScriptLauncher.ts +++ b/tools/javascript/lib/JavaScriptLauncher.ts @@ -549,10 +549,10 @@ export class JavaScriptLauncher extends Launcher { } finalEncodings = new Map( - [...newArchives.entries()].map(([target, archive]) => [ - target, - archive.getEncodings(), - ]) + [...newArchives.entries()].map(([target, archive]) => { + console.log("archive size", archive.size); + return [target, archive.getEncodings()]; + }) ); const suiteBuilder = new JavaScriptSuiteBuilder( diff --git a/tools/javascript/lib/workflows/TestSplitter.ts b/tools/javascript/lib/workflows/TestSplitter.ts index 734797b98..04b3c6b6d 100644 --- a/tools/javascript/lib/workflows/TestSplitter.ts +++ b/tools/javascript/lib/workflows/TestSplitter.ts @@ -105,23 +105,25 @@ export class TestSplitting { continue; } - // prefer more balanced splits (i.e. 2-2 over 1-3) - let bestBalance = Number.MAX_VALUE; - let bestPair: JavaScriptTestCase[] = possiblePairs[0]; - for (const pair of possiblePairs) { - const [encodingA, encodingB] = pair; - const balance = Math.abs(encodingA.getLength() - encodingB.getLength()); + // // prefer more balanced splits (i.e. 2-2 over 1-3) + // let bestBalance = Number.MAX_VALUE; + // let bestPair: JavaScriptTestCase[] = possiblePairs[0]; + // for (const pair of possiblePairs) { + // const [encodingA, encodingB] = pair; + // const balance = Math.abs(encodingA.getLength() - encodingB.getLength()); + + // if (balance < bestBalance) { + // bestBalance = balance; + // bestPair = pair; + // } + // } - if (balance < bestBalance) { - bestBalance = balance; - bestPair = pair; - } + for (const pair of possiblePairs) { + TestSplitting.LOGGER.debug( + `Split found: ${encoding.getLength()} -> ${pair[0].getLength()} + ${pair[1].getLength()}` + ); } - - TestSplitting.LOGGER.debug( - `Split found: ${encoding.getLength()} -> ${bestPair[0].getLength()} + ${bestPair[1].getLength()}` - ); - finalEncodings.push(...bestPair); + finalEncodings.push(...possiblePairs.flat()); } return finalEncodings; From a6adfeb18e4cbaaf1e4bcb3d9cd5171ae0079a92 Mon Sep 17 00:00:00 2001 From: Dimitri Stallenberg Date: Wed, 20 Sep 2023 18:39:54 +0200 Subject: [PATCH 07/11] fix: add commented code --- tools/javascript/lib/workflows/TestSplitter.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/javascript/lib/workflows/TestSplitter.ts b/tools/javascript/lib/workflows/TestSplitter.ts index 04b3c6b6d..f4d806e44 100644 --- a/tools/javascript/lib/workflows/TestSplitter.ts +++ b/tools/javascript/lib/workflows/TestSplitter.ts @@ -118,6 +118,12 @@ export class TestSplitting { // } // } + // TestSplitting.LOGGER.debug( + // `Split found: ${encoding.getLength()} -> ${bestPair[0].getLength()} + ${bestPair[1].getLength()}` + // ); + + // finalEncodings.push(...bestPair)); + for (const pair of possiblePairs) { TestSplitting.LOGGER.debug( `Split found: ${encoding.getLength()} -> ${pair[0].getLength()} + ${pair[1].getLength()}` From d06f3000802cd8a7f1dff06ef7f991e62441dbc3 Mon Sep 17 00:00:00 2001 From: Dimitri Stallenberg Date: Thu, 21 Sep 2023 11:51:59 +0200 Subject: [PATCH 08/11] chore: remove commented code --- tools/javascript/lib/workflows/MetaComment.ts | 45 ------------------- 1 file changed, 45 deletions(-) diff --git a/tools/javascript/lib/workflows/MetaComment.ts b/tools/javascript/lib/workflows/MetaComment.ts index 81ab7f622..5f979d1c0 100644 --- a/tools/javascript/lib/workflows/MetaComment.ts +++ b/tools/javascript/lib/workflows/MetaComment.ts @@ -54,48 +54,3 @@ export function addMetaComments( } } } - -// export function addMetaComments( -// objectivesMap: Map[]>, -// encodingsMap: Map -// ) { -// for (const [target, encodings] of encodingsMap.entries()) { -// const objectives = objectivesMap.get(target) -// const coveredBy = new Map, Set>(objectives.map((objective) => [objective, new Set()])) -// for (const encoding of encodings) { -// const executionResult = encoding.getExecutionResult(); - -// if (!executionResult) { -// throw new Error("Invalid encoding without executionResult") -// } - -// for (const objective of objectives) { -// if (executionResult.coversId(objective.getIdentifier())) { -// encoding.addMetaComment( -// `Covers objective: ${objective.getIdentifier()}` -// ); - -// coveredBy.get(objective).add(encoding) -// } -// } -// } - -// for (const [objective, encodings] of coveredBy.entries()) { -// if (encodings.size !== 1) { -// continue -// } -// const encoding = [...encodings][0] -// if (objective instanceof ExceptionObjectiveFunction) { -// encoding.addMetaComment(`Selected for:`); -// for (const line of objective.error.stack.split("\n")) { -// encoding.addMetaComment(`\t${line}`); -// } -// encoding.addMetaComment(""); -// } else { -// encoding.addMetaComment( -// `Selected for objective: ${objective.getIdentifier()}` -// ); -// } -// } -// } -// } From cbc0993415a1cb521e6f8f10084eee1c78906aa4 Mon Sep 17 00:00:00 2001 From: Dimitri Stallenberg Date: Thu, 21 Sep 2023 13:01:19 +0200 Subject: [PATCH 09/11] chore: change describe name to SynTest Test Suite --- .../search-javascript/lib/testbuilding/JavaScriptDecoder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts b/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts index 7e1c5a30e..5760320b9 100644 --- a/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts +++ b/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts @@ -127,7 +127,7 @@ export class JavaScriptDecoder implements Decoder { "// Imports", ...imports, gatherAssertionData ? assertionFunction : "", - `describe('TODO proper test naming', function() {`, + `describe('SynTest Test Suite', function() {`, ...beforeEachLines, ...tests.flatMap((testLines: string[], index) => [ `\tit("Test ${index + 1}", async () => {`, From 42c538499d2580fa83f1978c407617a2a6da3f8d Mon Sep 17 00:00:00 2001 From: Dimitri Stallenberg Date: Thu, 21 Sep 2023 13:36:25 +0200 Subject: [PATCH 10/11] fix: update packages --- libraries/analysis-javascript/package.json | 2 +- libraries/search-javascript/package.json | 2 +- package-lock.json | 22 +++++++++++----------- tools/javascript/package.json | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/libraries/analysis-javascript/package.json b/libraries/analysis-javascript/package.json index 70a3fe615..81552ae61 100644 --- a/libraries/analysis-javascript/package.json +++ b/libraries/analysis-javascript/package.json @@ -53,7 +53,7 @@ "@syntest/cfg": "^0.4.0", "@syntest/logging": "^0.1.1", "@syntest/prng": "^0.1.1", - "@syntest/search": "^0.4.0" + "@syntest/search": "^0.5.0-beta.3" }, "engines": { "node": ">=10.24.0" diff --git a/libraries/search-javascript/package.json b/libraries/search-javascript/package.json index 3f43d8951..8e5e1a00c 100644 --- a/libraries/search-javascript/package.json +++ b/libraries/search-javascript/package.json @@ -57,7 +57,7 @@ "@syntest/instrumentation-javascript": "*", "@syntest/logging": "^0.1.1", "@syntest/prng": "^0.1.1", - "@syntest/search": "^0.4.0", + "@syntest/search": "^0.5.0-beta.3", "@syntest/storage": "^0.2.0", "chai": "4.3.7", "chai-as-promised": "7.1.1", diff --git a/package-lock.json b/package-lock.json index 54c256227..6b76cea8d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -67,7 +67,7 @@ "@syntest/cfg": "^0.4.0", "@syntest/logging": "^0.1.1", "@syntest/prng": "^0.1.1", - "@syntest/search": "^0.4.0" + "@syntest/search": "^0.5.0-beta.3" }, "devDependencies": { "@babel/types": "^7.21.5" @@ -241,7 +241,7 @@ "@syntest/instrumentation-javascript": "*", "@syntest/logging": "^0.1.1", "@syntest/prng": "^0.1.1", - "@syntest/search": "^0.4.0", + "@syntest/search": "^0.5.0-beta.3", "@syntest/storage": "^0.2.0", "chai": "4.3.7", "chai-as-promised": "7.1.1", @@ -4894,16 +4894,16 @@ "link": true }, "node_modules/@syntest/base-language": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@syntest/base-language/-/base-language-0.2.1.tgz", - "integrity": "sha512-rVYaqhOCTDdzAnLWdZRmgXuEwJLdY8HdSI0/ssPEhsN9Otd6YRJ0gcQslTJ3/shdZsPTM74de4UZVk3q1SyOmw==", + "version": "0.3.0-beta.3", + "resolved": "https://registry.npmjs.org/@syntest/base-language/-/base-language-0.3.0-beta.3.tgz", + "integrity": "sha512-Peq5vEk+DjpnYrJAWeGtaVE9DsUZ5fTQxEfwd6y0WQkAE5Pzrk0dnEuVNTM1X2P5Qn2ua/UcvPC+LpAG2m3GiQ==", "dependencies": { "@syntest/analysis": "^0.2.0", "@syntest/cli-graphics": "^0.2.0", "@syntest/logging": "^0.1.1", "@syntest/metric": "^0.1.1", "@syntest/module": "^0.1.1", - "@syntest/search": "^0.4.1", + "@syntest/search": "^0.5.0-beta.3", "@syntest/storage": "^0.2.0", "globby": "11.0.4", "yargs": "^17.7.1" @@ -5040,9 +5040,9 @@ } }, "node_modules/@syntest/search": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@syntest/search/-/search-0.4.1.tgz", - "integrity": "sha512-JTnzsQ3Pk611Dg/AvJvcTz0b+LoK5dxPFc4gpISkttzXDG4vrKOpOsflDdZ5WU5N2Jew6BnOq+tQh5VAMG8CkQ==", + "version": "0.5.0-beta.3", + "resolved": "https://registry.npmjs.org/@syntest/search/-/search-0.5.0-beta.3.tgz", + "integrity": "sha512-zjcI8CRXbQcg81OXw1Ye8wo1xrC0ivFRiw8+Mt7bLAYJaIKHd3x2DIq3jWZiw/f7s9m5aS8hKgiJpBvkRjXOmQ==", "dependencies": { "@syntest/analysis": "^0.2.0", "@syntest/cfg": "^0.4.0", @@ -15794,13 +15794,13 @@ "license": "Apache-2.0", "dependencies": { "@syntest/analysis-javascript": "*", - "@syntest/base-language": "^0.2.0", + "@syntest/base-language": "^0.3.0-beta.3", "@syntest/cli-graphics": "^0.2.0", "@syntest/instrumentation-javascript": "*", "@syntest/logging": "^0.1.0", "@syntest/metric": "^0.1.0", "@syntest/module": "^0.1.0", - "@syntest/search": "^0.4.0", + "@syntest/search": "^0.5.0-beta.3", "@syntest/search-javascript": "*", "@syntest/storage": "*", "yargs": "^17.7.2" diff --git a/tools/javascript/package.json b/tools/javascript/package.json index a2a365890..d32c9941f 100644 --- a/tools/javascript/package.json +++ b/tools/javascript/package.json @@ -47,13 +47,13 @@ }, "dependencies": { "@syntest/analysis-javascript": "*", - "@syntest/base-language": "^0.2.0", + "@syntest/base-language": "^0.3.0-beta.3", "@syntest/cli-graphics": "^0.2.0", "@syntest/instrumentation-javascript": "*", "@syntest/logging": "^0.1.0", "@syntest/metric": "^0.1.0", "@syntest/module": "^0.1.0", - "@syntest/search": "^0.4.0", + "@syntest/search": "^0.5.0-beta.3", "@syntest/search-javascript": "*", "@syntest/storage": "*", "yargs": "^17.7.2" From d37d222fbf7e3fc938d701ac8014fdba991b7146 Mon Sep 17 00:00:00 2001 From: Dimitri Stallenberg Date: Wed, 27 Sep 2023 10:43:18 +0200 Subject: [PATCH 11/11] feat: esnext syntax --- .eslintignore | 1 - .eslintrc.json | 11 +- .husky/commit-msg | 2 +- commitlint.config.json | 3 + libraries/analysis-javascript/index.ts | 70 ++++---- libraries/analysis-javascript/lib/Events.ts | 2 +- .../analysis-javascript/lib/RootContext.ts | 36 ++--- .../lib/ast/AbstractSyntaxTreeFactory.ts | 2 +- .../lib/cfg/ControlFlowGraphFactory.ts | 4 +- .../lib/constant/ConstantPoolFactory.ts | 6 +- .../lib/constant/ConstantPoolManager.ts | 2 +- .../lib/constant/ConstantVisitor.ts | 2 +- .../lib/dependency/DependencyFactory.ts | 4 +- .../analysis-javascript/lib/target/Target.ts | 2 +- .../lib/target/TargetFactory.ts | 8 +- .../lib/target/TargetVisitor.ts | 153 ++++++++++++------ .../target/export/ExportDefaultDeclaration.ts | 119 +++++++++----- .../lib/target/export/ExportFactory.ts | 6 +- .../target/export/ExportNamedDeclaration.ts | 4 +- .../lib/target/export/ExportVisitor.ts | 8 +- .../lib/target/export/ExpressionStatement.ts | 4 +- .../lib/type/discovery/TypeExtractor.ts | 12 +- .../type/discovery/element/ElementVisitor.ts | 8 +- .../type/discovery/object/ObjectVisitor.ts | 74 +++++---- .../discovery/relation/RelationVisitor.ts | 6 +- .../resolving/InferenceTypeModelFactory.ts | 10 +- .../lib/type/resolving/TypeEnum.ts | 2 +- .../lib/type/resolving/TypeModel.ts | 4 +- .../lib/type/resolving/TypeModelFactory.ts | 6 +- .../lib/type/resolving/TypePool.ts | 6 +- .../lib/utils/diagnostics.ts | 4 + libraries/analysis-javascript/package.json | 1 + .../test/AbstractSyntaxTreeGenerator.test.ts | 2 +- .../test/AbstractSyntaxTreeVisitor.test.ts | 2 +- .../test/cfg/ControlFlowGraphVisitor.test.ts | 4 +- .../cfg/ForControlFlowGraphVisitor.test.ts | 4 +- .../TernaryControlFlowGraphVisitor.test.ts | 4 +- .../test/dependency/DependencyVisitor.test.ts | 4 +- .../test/target/TargetFactory.test.ts | 4 +- .../test/target/TargetVisitor.test.ts | 8 +- .../test/target/export/ExportVisitor.test.ts | 4 +- .../test/type/ElementVisitor.test.ts | 6 +- .../type/InferenceTypeModelFactory.test.ts | 10 +- .../test/type/RelationVisitor.test.ts | 4 +- libraries/ast-visitor-javascript/index.ts | 6 +- .../lib/AbstractSyntaxTreeVisitor.ts | 10 +- .../lib/globalVariables.ts | 2 +- libraries/ast-visitor-javascript/package.json | 1 + .../test/example.test.ts | 2 +- libraries/instrumentation-javascript/index.ts | 12 +- .../lib/datastructures}/AssertionData.ts | 0 .../lib/datastructures/InstrumentationData.ts | 4 +- .../lib/instrumentation/Global.ts | 13 +- .../lib/instrumentation/Instrumenter.ts | 2 +- .../lib/instrumentation/VisitState.ts | 18 +-- .../lib/instrumentation/Visitor.ts | 5 +- .../lib/instrumentation/source-coverage.ts | 32 ++-- .../instrumentation-javascript/package.json | 4 +- .../test/example.test.ts | 2 +- libraries/search-javascript/index.ts | 58 +++---- .../lib/criterion/BranchDistance.ts | 2 +- .../lib/search/JavaScriptSubject.ts | 4 +- .../lib/search/crossover/TreeCrossover.ts | 10 +- .../lib/testbuilding/ContextBuilder.ts | 103 +++++++----- .../lib/testbuilding/JavaScriptDecoder.ts | 20 ++- .../testbuilding/JavaScriptSuiteBuilder.ts | 7 +- .../lib/testcase/JavaScriptTestCase.ts | 8 +- .../lib/testcase/StatementPool.ts | 14 +- .../ExecutionInformationIntegrator.ts | 8 +- .../testcase/execution/JavaScriptRunner.ts | 21 +-- .../testcase/execution/SilentMochaReporter.ts | 2 +- .../lib/testcase/execution/TestExecutor.ts | 50 ++++-- .../sampling/JavaScriptRandomSampler.ts | 46 +++--- .../sampling/JavaScriptTestCaseSampler.ts | 58 +++---- .../testcase/sampling/generators/Generator.ts | 6 +- .../generators/action/CallGenerator.ts | 4 +- .../action/ConstantObjectGenerator.ts | 6 +- .../action/ConstructorCallGenerator.ts | 8 +- .../action/FunctionCallGenerator.ts | 8 +- .../generators/action/GetterGenerator.ts | 6 +- .../generators/action/MethodCallGenerator.ts | 8 +- .../action/ObjectFunctionCallGenerator.ts | 8 +- .../generators/action/SetterGenerator.ts | 8 +- .../lib/testcase/statements/Statement.ts | 2 +- .../statements/action/ActionStatement.ts | 2 +- .../statements/action/ClassActionStatement.ts | 6 +- .../statements/action/ConstantObject.ts | 8 +- .../statements/action/ConstructorCall.ts | 8 +- .../statements/action/FunctionCall.ts | 8 +- .../lib/testcase/statements/action/Getter.ts | 10 +- .../testcase/statements/action/MethodCall.ts | 10 +- .../statements/action/ObjectFunctionCall.ts | 10 +- .../lib/testcase/statements/action/Setter.ts | 14 +- .../statements/complex/ArrayStatement.ts | 6 +- .../complex/ArrowFunctionStatement.ts | 6 +- .../statements/complex/ObjectStatement.ts | 6 +- .../statements/primitive/BoolStatement.ts | 6 +- .../statements/primitive/IntegerStatement.ts | 8 +- .../statements/primitive/NullStatement.ts | 6 +- .../statements/primitive/NumericStatement.ts | 8 +- .../primitive/PrimitiveStatement.ts | 6 +- .../statements/primitive/StringStatement.ts | 8 +- .../primitive/UndefinedStatement.ts | 6 +- libraries/search-javascript/package.json | 2 + .../BranchDistanceBinaryDoubleEqual.test.ts | 2 +- ...BranchDistanceBinaryDoubleNotEqual.test.ts | 2 +- .../BranchDistanceBinaryGreater.test.ts | 2 +- ...BranchDistanceBinaryGreaterOrEqual.test.ts | 2 +- .../BranchDistanceBinarySmaller.test.ts | 2 +- ...BranchDistanceBinarySmallerOrEqual.test.ts | 2 +- .../BranchDistanceBinaryTrippleEqual.test.ts | 2 +- ...ranchDistanceBinaryTrippleNotEqual.test.ts | 2 +- .../criterion/BranchDistanceLogicalOr.test.ts | 2 +- .../BranchDistanceStringFunctions.test.ts | 2 +- .../criterion/BranchDistanceUnaryNot.test.ts | 2 +- .../criterion/BranchDistanceVisitor.test.ts | 2 +- .../RandomBranchDistanceTests.test.ts | 2 +- package-lock.json | 62 ++++++- package.json | 7 +- .../index.ts | 2 +- .../lib/StateStorageEventListenerPlugin.ts | 9 +- .../lib/StateStorageModule.ts | 11 +- .../package.json | 1 + .../test/simulation.test.ts | 2 +- .../tsconfig.json | 2 +- tools/javascript/index.ts | 2 +- tools/javascript/lib/JavaScriptLauncher.ts | 25 ++- tools/javascript/lib/JavaScriptModule.ts | 17 +- tools/javascript/lib/commands/test.ts | 11 +- .../plugins/sampler/RandomSamplerPlugin.ts | 2 +- tools/javascript/package.json | 1 + tools/javascript/test/example.test.ts | 2 +- tools/javascript/tsconfig.json | 2 +- tsconfig-base.json | 15 +- tsconfig.json | 5 +- 135 files changed, 928 insertions(+), 646 deletions(-) create mode 100644 commitlint.config.json rename libraries/{search-javascript/lib/testcase/execution => instrumentation-javascript/lib/datastructures}/AssertionData.ts (100%) rename commitlint.config.js => libraries/instrumentation-javascript/lib/instrumentation/Global.ts (66%) diff --git a/.eslintignore b/.eslintignore index f34af8576..3c82b948c 100755 --- a/.eslintignore +++ b/.eslintignore @@ -11,7 +11,6 @@ syntest/ LICENSE* Dockerfile NOTICE -commitlint.config.js link.sh **/coverage diff --git a/.eslintrc.json b/.eslintrc.json index 04d86d23c..f3bb4f0e7 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -32,6 +32,7 @@ "@typescript-eslint", "notice", "unused-imports" + ], "rules": { "import/first": "error", @@ -70,6 +71,14 @@ "unicorn/prefer-ternary": "warn", "unicorn/expiring-todo-comments": "off", "no-fallthrough": "off", - "sonarjs/cognitive-complexity": "warn" + "sonarjs/cognitive-complexity": "warn", + "import/extensions": [ + "error", + { + "ts": "never", + "js": "always", + "json": "always" + } + ] } } diff --git a/.husky/commit-msg b/.husky/commit-msg index 4002db717..f052c0b81 100755 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -1,4 +1,4 @@ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" -npx --no -- commitlint --edit +npx --no -- commitlint --edit --config ./commitlint.config.json diff --git a/commitlint.config.json b/commitlint.config.json new file mode 100644 index 000000000..c30e5a970 --- /dev/null +++ b/commitlint.config.json @@ -0,0 +1,3 @@ +{ + "extends": ["@commitlint/config-conventional"] +} diff --git a/libraries/analysis-javascript/index.ts b/libraries/analysis-javascript/index.ts index 6194b63fe..827d89d0d 100644 --- a/libraries/analysis-javascript/index.ts +++ b/libraries/analysis-javascript/index.ts @@ -15,50 +15,50 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export * from "./lib/ast/AbstractSyntaxTreeFactory"; -export * from "./lib/ast/defaultBabelConfig"; +export * from "./lib/ast/AbstractSyntaxTreeFactory.js"; +export * from "./lib/ast/defaultBabelConfig.js"; -export * from "./lib/cfg/ControlFlowGraphFactory"; -export * from "./lib/cfg/ControlFlowGraphVisitor"; +export * from "./lib/cfg/ControlFlowGraphFactory.js"; +export * from "./lib/cfg/ControlFlowGraphVisitor.js"; -export * from "./lib/constant/ConstantPool"; -export * from "./lib/constant/ConstantPoolFactory"; -export * from "./lib/constant/ConstantPoolManager"; -export * from "./lib/constant/ConstantVisitor"; +export * from "./lib/constant/ConstantPool.js"; +export * from "./lib/constant/ConstantPoolFactory.js"; +export * from "./lib/constant/ConstantPoolManager.js"; +export * from "./lib/constant/ConstantVisitor.js"; -export * from "./lib/dependency/DependencyFactory"; -export * from "./lib/dependency/DependencyVisitor"; +export * from "./lib/dependency/DependencyFactory.js"; +export * from "./lib/dependency/DependencyVisitor.js"; -export * from "./lib/target/export/Export"; -export * from "./lib/target/export/ExportDefaultDeclaration"; -export * from "./lib/target/export/ExportFactory"; -export * from "./lib/target/export/ExportNamedDeclaration"; -export * from "./lib/target/export/ExportVisitor"; -export * from "./lib/target/export/ExpressionStatement"; +export * from "./lib/target/export/Export.js"; +export * from "./lib/target/export/ExportDefaultDeclaration.js"; +export * from "./lib/target/export/ExportFactory.js"; +export * from "./lib/target/export/ExportNamedDeclaration.js"; +export * from "./lib/target/export/ExportVisitor.js"; +export * from "./lib/target/export/ExpressionStatement.js"; -export * from "./lib/target/Target"; -export * from "./lib/target/TargetFactory"; -export * from "./lib/target/TargetVisitor"; -export * from "./lib/target/VisibilityType"; +export * from "./lib/target/Target.js"; +export * from "./lib/target/TargetFactory.js"; +export * from "./lib/target/TargetVisitor.js"; +export * from "./lib/target/VisibilityType.js"; -export * from "./lib/type/discovery/element/Element"; -export * from "./lib/type/discovery/element/ElementVisitor"; +export * from "./lib/type/discovery/element/Element.js"; +export * from "./lib/type/discovery/element/ElementVisitor.js"; -export * from "./lib/type/discovery/object/DiscoveredType"; -export * from "./lib/type/discovery/object/ObjectVisitor"; +export * from "./lib/type/discovery/object/DiscoveredType.js"; +export * from "./lib/type/discovery/object/ObjectVisitor.js"; -export * from "./lib/type/discovery/relation/Relation"; -export * from "./lib/type/discovery/relation/RelationVisitor"; +export * from "./lib/type/discovery/relation/Relation.js"; +export * from "./lib/type/discovery/relation/RelationVisitor.js"; -export * from "./lib/type/discovery/TypeExtractor"; +export * from "./lib/type/discovery/TypeExtractor.js"; -export * from "./lib/type/resolving/Type"; -export * from "./lib/type/resolving/TypeEnum"; -export * from "./lib/type/resolving/TypeModel"; -export * from "./lib/type/resolving/TypeModelFactory"; -export * from "./lib/type/resolving/InferenceTypeModelFactory"; +export * from "./lib/type/resolving/Type.js"; +export * from "./lib/type/resolving/TypeEnum.js"; +export * from "./lib/type/resolving/TypeModel.js"; +export * from "./lib/type/resolving/TypeModelFactory.js"; +export * from "./lib/type/resolving/InferenceTypeModelFactory.js"; -export * from "./lib/utils/fileSystem"; +export * from "./lib/utils/fileSystem.js"; -export * from "./lib/Events"; -export * from "./lib/RootContext"; +export * from "./lib/Events.js"; +export * from "./lib/RootContext.js"; diff --git a/libraries/analysis-javascript/lib/Events.ts b/libraries/analysis-javascript/lib/Events.ts index 28001fc05..526469ae6 100644 --- a/libraries/analysis-javascript/lib/Events.ts +++ b/libraries/analysis-javascript/lib/Events.ts @@ -16,7 +16,7 @@ * limitations under the License. */ -import { RootContext } from "./RootContext"; +import { RootContext } from "./RootContext.js"; export type Events = { exportExtractionStart: (rootContext: RootContext, filepath: string) => void; diff --git a/libraries/analysis-javascript/lib/RootContext.ts b/libraries/analysis-javascript/lib/RootContext.ts index 289c0971d..820d159d2 100644 --- a/libraries/analysis-javascript/lib/RootContext.ts +++ b/libraries/analysis-javascript/lib/RootContext.ts @@ -23,24 +23,24 @@ import { RootContext as CoreRootContext } from "@syntest/analysis"; import { getLogger, Logger } from "@syntest/logging"; import TypedEmitter from "typed-emitter"; -import { AbstractSyntaxTreeFactory } from "./ast/AbstractSyntaxTreeFactory"; -import { ControlFlowGraphFactory } from "./cfg/ControlFlowGraphFactory"; -import { ConstantPool } from "./constant/ConstantPool"; -import { ConstantPoolFactory } from "./constant/ConstantPoolFactory"; -import { ConstantPoolManager } from "./constant/ConstantPoolManager"; -import { DependencyFactory } from "./dependency/DependencyFactory"; -import { Events } from "./Events"; -import { Export } from "./target/export/Export"; -import { ExportFactory } from "./target/export/ExportFactory"; -import { TargetFactory } from "./target/TargetFactory"; -import { Element } from "./type/discovery/element/Element"; -import { DiscoveredObjectType } from "./type/discovery/object/DiscoveredType"; -import { Relation } from "./type/discovery/relation/Relation"; -import { TypeExtractor } from "./type/discovery/TypeExtractor"; -import { TypeModel } from "./type/resolving/TypeModel"; -import { TypeModelFactory } from "./type/resolving/TypeModelFactory"; -import { TypePool } from "./type/resolving/TypePool"; -import { readFile } from "./utils/fileSystem"; +import { AbstractSyntaxTreeFactory } from "./ast/AbstractSyntaxTreeFactory.js"; +import { ControlFlowGraphFactory } from "./cfg/ControlFlowGraphFactory.js"; +import { ConstantPool } from "./constant/ConstantPool.js"; +import { ConstantPoolFactory } from "./constant/ConstantPoolFactory.js"; +import { ConstantPoolManager } from "./constant/ConstantPoolManager.js"; +import { DependencyFactory } from "./dependency/DependencyFactory.js"; +import { Events } from "./Events.js"; +import { Export } from "./target/export/Export.js"; +import { ExportFactory } from "./target/export/ExportFactory.js"; +import { TargetFactory } from "./target/TargetFactory.js"; +import { Element } from "./type/discovery/element/Element.js"; +import { DiscoveredObjectType } from "./type/discovery/object/DiscoveredType.js"; +import { Relation } from "./type/discovery/relation/Relation.js"; +import { TypeExtractor } from "./type/discovery/TypeExtractor.js"; +import { TypeModel } from "./type/resolving/TypeModel.js"; +import { TypeModelFactory } from "./type/resolving/TypeModelFactory.js"; +import { TypePool } from "./type/resolving/TypePool.js"; +import { readFile } from "./utils/fileSystem.js"; export class RootContext extends CoreRootContext { protected static LOGGER: Logger; diff --git a/libraries/analysis-javascript/lib/ast/AbstractSyntaxTreeFactory.ts b/libraries/analysis-javascript/lib/ast/AbstractSyntaxTreeFactory.ts index 650300809..ccd5356c1 100644 --- a/libraries/analysis-javascript/lib/ast/AbstractSyntaxTreeFactory.ts +++ b/libraries/analysis-javascript/lib/ast/AbstractSyntaxTreeFactory.ts @@ -20,7 +20,7 @@ import { transformSync } from "@babel/core"; import * as t from "@babel/types"; import { AbstractSyntaxTreeFactory as CoreAbstractSyntaxTreeFactory } from "@syntest/analysis"; -import { defaultBabelOptions } from "./defaultBabelConfig"; +import { defaultBabelOptions } from "./defaultBabelConfig.js"; export class AbstractSyntaxTreeFactory implements CoreAbstractSyntaxTreeFactory diff --git a/libraries/analysis-javascript/lib/cfg/ControlFlowGraphFactory.ts b/libraries/analysis-javascript/lib/cfg/ControlFlowGraphFactory.ts index 37c0d0479..7ab354f7a 100644 --- a/libraries/analysis-javascript/lib/cfg/ControlFlowGraphFactory.ts +++ b/libraries/analysis-javascript/lib/cfg/ControlFlowGraphFactory.ts @@ -20,9 +20,9 @@ import * as t from "@babel/types"; import { ControlFlowGraphFactory as CoreControlFlowGraphFactory } from "@syntest/analysis"; import { contractControlFlowProgram, ControlFlowProgram } from "@syntest/cfg"; -import { Factory } from "../Factory"; +import { Factory } from "../Factory.js"; -import { ControlFlowGraphVisitor } from "./ControlFlowGraphVisitor"; +import { ControlFlowGraphVisitor } from "./ControlFlowGraphVisitor.js"; export class ControlFlowGraphFactory extends Factory diff --git a/libraries/analysis-javascript/lib/constant/ConstantPoolFactory.ts b/libraries/analysis-javascript/lib/constant/ConstantPoolFactory.ts index 2b04c4703..a67324644 100644 --- a/libraries/analysis-javascript/lib/constant/ConstantPoolFactory.ts +++ b/libraries/analysis-javascript/lib/constant/ConstantPoolFactory.ts @@ -18,10 +18,10 @@ import { traverse } from "@babel/core"; import * as t from "@babel/types"; -import { Factory } from "../Factory"; +import { Factory } from "../Factory.js"; -import { ConstantPool } from "./ConstantPool"; -import { ConstantVisitor } from "./ConstantVisitor"; +import { ConstantPool } from "./ConstantPool.js"; +import { ConstantVisitor } from "./ConstantVisitor.js"; export class ConstantPoolFactory extends Factory { /** diff --git a/libraries/analysis-javascript/lib/constant/ConstantPoolManager.ts b/libraries/analysis-javascript/lib/constant/ConstantPoolManager.ts index 3693c7cca..cd63dcc4a 100644 --- a/libraries/analysis-javascript/lib/constant/ConstantPoolManager.ts +++ b/libraries/analysis-javascript/lib/constant/ConstantPoolManager.ts @@ -16,7 +16,7 @@ * limitations under the License. */ -import { ConstantPool } from "./ConstantPool"; +import { ConstantPool } from "./ConstantPool.js"; export class ConstantPoolManager { protected _targetConstantPool: ConstantPool; diff --git a/libraries/analysis-javascript/lib/constant/ConstantVisitor.ts b/libraries/analysis-javascript/lib/constant/ConstantVisitor.ts index 3bbbcfda0..ae60e1157 100644 --- a/libraries/analysis-javascript/lib/constant/ConstantVisitor.ts +++ b/libraries/analysis-javascript/lib/constant/ConstantVisitor.ts @@ -19,7 +19,7 @@ import { NodePath } from "@babel/core"; import * as t from "@babel/types"; import { AbstractSyntaxTreeVisitor } from "@syntest/ast-visitor-javascript"; -import { ConstantPool } from "./ConstantPool"; +import { ConstantPool } from "./ConstantPool.js"; export class ConstantVisitor extends AbstractSyntaxTreeVisitor { protected _constantPool: ConstantPool; diff --git a/libraries/analysis-javascript/lib/dependency/DependencyFactory.ts b/libraries/analysis-javascript/lib/dependency/DependencyFactory.ts index 1a9244573..905877fb7 100644 --- a/libraries/analysis-javascript/lib/dependency/DependencyFactory.ts +++ b/libraries/analysis-javascript/lib/dependency/DependencyFactory.ts @@ -20,9 +20,9 @@ import { traverse } from "@babel/core"; import * as t from "@babel/types"; import { DependencyFactory as CoreDependencyFactory } from "@syntest/analysis"; -import { Factory } from "../Factory"; +import { Factory } from "../Factory.js"; -import { DependencyVisitor } from "./DependencyVisitor"; +import { DependencyVisitor } from "./DependencyVisitor.js"; /** * Dependency generator for targets. diff --git a/libraries/analysis-javascript/lib/target/Target.ts b/libraries/analysis-javascript/lib/target/Target.ts index e8eb5bcf9..14e58e220 100644 --- a/libraries/analysis-javascript/lib/target/Target.ts +++ b/libraries/analysis-javascript/lib/target/Target.ts @@ -21,7 +21,7 @@ import { TargetType, } from "@syntest/analysis"; -import { VisibilityType } from "./VisibilityType"; +import { VisibilityType } from "./VisibilityType.js"; export interface Target extends CoreTarget { path: string; diff --git a/libraries/analysis-javascript/lib/target/TargetFactory.ts b/libraries/analysis-javascript/lib/target/TargetFactory.ts index c9fa9f2fc..73ab326a6 100644 --- a/libraries/analysis-javascript/lib/target/TargetFactory.ts +++ b/libraries/analysis-javascript/lib/target/TargetFactory.ts @@ -22,11 +22,11 @@ import { traverse } from "@babel/core"; import * as t from "@babel/types"; import { TargetFactory as CoreTargetFactory } from "@syntest/analysis"; -import { Factory } from "../Factory"; +import { Factory } from "../Factory.js"; -import { ExportVisitor } from "./export/ExportVisitor"; -import { Target } from "./Target"; -import { TargetVisitor } from "./TargetVisitor"; +import { ExportVisitor } from "./export/ExportVisitor.js"; +import { Target } from "./Target.js"; +import { TargetVisitor } from "./TargetVisitor.js"; /** * TargetFactory for Javascript. diff --git a/libraries/analysis-javascript/lib/target/TargetVisitor.ts b/libraries/analysis-javascript/lib/target/TargetVisitor.ts index af3ef9c96..14d93ce95 100644 --- a/libraries/analysis-javascript/lib/target/TargetVisitor.ts +++ b/libraries/analysis-javascript/lib/target/TargetVisitor.ts @@ -22,9 +22,9 @@ import { TargetType } from "@syntest/analysis"; import { AbstractSyntaxTreeVisitor } from "@syntest/ast-visitor-javascript"; import { getLogger, Logger } from "@syntest/logging"; -import { unsupportedSyntax } from "../utils/diagnostics"; +import { computedProperty, unsupportedSyntax } from "../utils/diagnostics.js"; -import { Export } from "./export/Export"; +import { Export } from "./export/Export.js"; import { Callable, ClassTarget, @@ -35,12 +35,20 @@ import { ObjectFunctionTarget, ObjectTarget, SubTarget, -} from "./Target"; +} from "./Target.js"; -const COMPUTED_FLAG = ":computed:"; export class TargetVisitor extends AbstractSyntaxTreeVisitor { protected static override LOGGER: Logger; + private _logOrFail(message: string): undefined { + if (this.syntaxForgiving) { + TargetVisitor.LOGGER.warn(message); + return undefined; + } else { + throw new Error(message); + } + } + private _exports: Export[]; private _subTargets: SubTarget[]; @@ -70,7 +78,9 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { // e.g. class {} // e.g. function () {} // Should not be possible - throw new Error("unknown class declaration"); + return this._logOrFail( + unsupportedSyntax(path.type, this._getNodeId(path)) + ); } } else { // e.g. class x {} @@ -85,7 +95,9 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { * @param path * @returns */ - private _getTargetNameOfExpression(path: NodePath): string { + private _getTargetNameOfExpression( + path: NodePath + ): string | undefined { // e.g. const x = class A {} // e.g. const x = function A {} // e.g. const x = () => {} @@ -106,7 +118,7 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { // e.g. const {x} = function {} // e.g. const {x} = () => {} // Should not be possible - throw new Error( + return this._logOrFail( unsupportedSyntax(path.node.type, this._getNodeId(path)) ); } @@ -138,13 +150,9 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { // e.g. x[y] = class {} // e.g. x[y] = function {} // e.g. x[y] = () => {} - // TODO unsupported cannot get the name unless executing - TargetVisitor.LOGGER.warn( - `This tool does not support computed property assignments. Found one at ${this._getNodeId( - path - )}` + return this._logOrFail( + computedProperty(path.node.type, this._getNodeId(path)) ); - return COMPUTED_FLAG; } } else if (assigned.property.type === "Identifier") { // e.g. x.y = class {} @@ -168,7 +176,7 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { // e.g. x.? = function {} // e.g. x.? = () => {} // Should not be possible - throw new Error( + return this._logOrFail( unsupportedSyntax(path.node.type, this._getNodeId(path)) ); } @@ -177,7 +185,7 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { // e.g. {x} = function {} // e.g. {x} = () => {} // Should not be possible - throw new Error( + return this._logOrFail( unsupportedSyntax(path.node.type, this._getNodeId(path)) ); } @@ -219,7 +227,7 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { // e.g. {?: function {}} // e.g. {?: () => {}} // Should not be possible - throw new Error( + return this._logOrFail( unsupportedSyntax(path.node.type, this._getNodeId(path)) ); } @@ -256,15 +264,18 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { // e.g. c || () => {} return this._getTargetNameOfExpression(path.parentPath); } + case "ExportDefaultDeclaration": { + // e.g. export default class {} + // e.g. export default function () {} + // e.g. export default () => {} + return "default"; + } default: { // e.g. class {} // e.g. function () {} // e.g. () => {} - // Should not be possible - throw new Error( - `Unknown parent expression ${parentNode.type} for ${ - path.node.type - } in ${this._getNodeId(path)}` + return this._logOrFail( + unsupportedSyntax(parentNode.type, this._getNodeId(path)) ); } } @@ -309,12 +320,16 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { // only thing left where these can be found is: // call(function () {}) const targetName = this._getTargetNameOfExpression(path); + path.skip(); + + if (!targetName) { + return; + } + const id = this._getNodeId(path); const export_ = this._getExport(id); this._extractFromFunction(path, id, id, targetName, export_, false, false); - - path.skip(); }; public ClassExpression: (path: NodePath) => void = ( @@ -323,12 +338,16 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { // only thing left where these can be found is: // call(class {}) const targetName = this._getTargetNameOfExpression(path); + path.skip(); + + if (!targetName) { + return; + } + const id = this._getNodeId(path); const export_ = this._getExport(id); this._extractFromClass(path, id, id, targetName, export_); - - path.skip(); }; public ArrowFunctionExpression: ( @@ -337,15 +356,17 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { // only thing left where these can be found is: // call(() => {}) const targetName = this._getTargetNameOfExpression(path); + path.skip(); + if (!targetName) { + return; + } // TODO is there a difference if the parent is a variable declarator? const id = this._getNodeId(path); const export_ = this._getExport(id); this._extractFromFunction(path, id, id, targetName, export_, false, false); - - path.skip(); }; public VariableDeclarator: (path: NodePath) => void = ( @@ -399,6 +420,10 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { } const targetName = this._getTargetNameOfExpression(right); + + if (!targetName) { + return; + } let isObject = false; let isMethod = false; let objectId: string; @@ -408,11 +433,10 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { const object = left.get("object"); const property = left.get("property"); - if (left.get("property").isIdentifier() && left.node.computed) { - TargetVisitor.LOGGER.warn( - "We do not support dynamic computed properties: x[a] = ?" - ); + if (property.isIdentifier() && left.node.computed) { path.skip(); + + this._logOrFail(computedProperty(left.type, this._getNodeId(path))); return; } else if (!left.get("property").isIdentifier() && !left.node.computed) { // we also dont support a.f() = ? @@ -637,25 +661,50 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { // loop over object properties for (const property of path.get("properties")) { if (property.isObjectMethod()) { - if (property.node.key.type !== "Identifier") { + if (property.node.computed) { // e.g. class A { ?() {} } // unsupported - // not possible i think - throw new Error("unknown class method key"); + this._logOrFail( + computedProperty(property.type, this._getNodeId(property)) + ); + continue; } - const targetName = property.node.key.name; + const key = property.get("key"); + if (key.isIdentifier()) { + const targetName = key.node.name; - const id = this._getNodeId(property); - this._extractFromFunction( - property, - id, - id, - targetName, - undefined, - true, - false, - objectId - ); + const id = this._getNodeId(property); + this._extractFromFunction( + property, + id, + id, + targetName, + undefined, + true, + false, + objectId + ); + } else if (key.isLiteral()) { + const targetName = "value" in key ? String(key.value) : "null"; + + const id = this._getNodeId(property); + this._extractFromFunction( + property, + id, + id, + targetName, + undefined, + true, + false, + objectId + ); + } else { + // not possible i think + this._logOrFail( + unsupportedSyntax(property.node.type, this._getNodeId(property)) + ); + continue; + } } else if (property.isObjectProperty()) { const key = property.get("key"); const value = property.get("value"); @@ -726,7 +775,13 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { // e.g. class A { ?() {} } // unsupported // not possible i think - throw new Error("unknown class method key"); + this._logOrFail( + unsupportedSyntax( + classBodyAttribute.node.type, + this._getNodeId(classBodyAttribute) + ) + ); + continue; } const targetName = classBodyAttribute.node.key.name; @@ -781,8 +836,8 @@ export class TargetVisitor extends AbstractSyntaxTreeVisitor { } } } else { - TargetVisitor.LOGGER.warn( - `Unsupported class body attribute: ${classBodyAttribute.node.type}` + return this._logOrFail( + unsupportedSyntax(body.node.type, this._getNodeId(classBodyAttribute)) ); } } diff --git a/libraries/analysis-javascript/lib/target/export/ExportDefaultDeclaration.ts b/libraries/analysis-javascript/lib/target/export/ExportDefaultDeclaration.ts index eb60ecd03..e6028efce 100644 --- a/libraries/analysis-javascript/lib/target/export/ExportDefaultDeclaration.ts +++ b/libraries/analysis-javascript/lib/target/export/ExportDefaultDeclaration.ts @@ -18,33 +18,59 @@ import { NodePath } from "@babel/core"; import * as t from "@babel/types"; +import { getLogger } from "@syntest/logging"; -import { Export } from "./Export"; -import { ExportVisitor } from "./ExportVisitor"; +import { Export } from "./Export.js"; +import { ExportVisitor } from "./ExportVisitor.js"; export function extractExportsFromExportDefaultDeclaration( visitor: ExportVisitor, filePath: string, path: NodePath ): Export[] { - let name: string; - let id: string; - const declaration = path.get("declaration"); + return extractExportFromDeclaration(visitor, filePath, declaration); +} + +function extractExportFromDeclaration( + visitor: ExportVisitor, + filePath: string, + declaration: NodePath< + | t.TSDeclareFunction + | t.FunctionDeclaration + | t.ClassDeclaration + | t.Expression + > +): Export[] { if (declaration.isIdentifier()) { // export default x - name = declaration.node.name; - id = visitor._getBindingId(declaration); + return [ + { + id: visitor._getBindingId(declaration), + filePath, + name: declaration.node.name, + renamedTo: declaration.node.name, + default: true, + module: false, + }, + ]; } else if (declaration.isLiteral() || declaration.isCallExpression()) { // export default 1 // export default "abc" // export default true // export default x() - - name = "default"; - id = visitor._getNodeId(declaration); + return [ + { + id: visitor._getNodeId(declaration), + filePath, + name: "default", + renamedTo: "default", + default: true, + module: false, + }, + ]; } else if (declaration.isNewExpression()) { // export default new Class() @@ -52,17 +78,34 @@ export function extractExportsFromExportDefaultDeclaration( // unsupported throw new Error("Unsupported export default declaration"); } - name = declaration.node.callee.name; - // idk if this is correct - id = visitor._getNodeId(declaration); + return [ + { + // idk if this is correct + id: visitor._getNodeId(declaration), + filePath, + name: declaration.node.callee.name, + renamedTo: declaration.node.callee.name, + default: true, + module: false, + }, + ]; } else if ( declaration.isFunctionDeclaration() || declaration.isClassDeclaration() ) { // export default function () {} // export default class {} - name = declaration.node.id ? declaration.node.id.name : "default"; - id = visitor._getNodeId(declaration); + const name = declaration.node.id ? declaration.node.id.name : "default"; + return [ + { + id: visitor._getNodeId(declaration), + filePath, + name: name, + renamedTo: name, + default: true, + module: false, + }, + ]; } else if (declaration.isObjectExpression()) { // export default {} const exports: Export[] = []; @@ -85,26 +128,30 @@ export function extractExportsFromExportDefaultDeclaration( } return exports; - } else { - // we could also put anon here, but that would be a bit weird - // name = "anonymous" - // unsupported - // examples which we don't support: - // export default [] - // etc. - throw new Error( - `Unsupported export default declaration at ${visitor._getNodeId(path)}` - ); + } else if (declaration.isLogicalExpression()) { + return [ + ...extractExportFromDeclaration( + visitor, + filePath, + declaration.get("left") + ), + ...extractExportFromDeclaration( + visitor, + filePath, + declaration.get("right") + ), + ]; } - - return [ - { - id: id, - filePath, - name: name, - renamedTo: name, - default: true, - module: false, - }, - ]; + // we could also put anon here, but that would be a bit weird + // name = "anonymous" + // unsupported + // examples which we don't support: + // export default [] + // etc. + getLogger("ExportDefaultDeclaration").warn( + `Unsupported export default declaration at ${visitor._getNodeId( + declaration + )}` + ); + return []; } diff --git a/libraries/analysis-javascript/lib/target/export/ExportFactory.ts b/libraries/analysis-javascript/lib/target/export/ExportFactory.ts index 8f6fcd995..b763479da 100644 --- a/libraries/analysis-javascript/lib/target/export/ExportFactory.ts +++ b/libraries/analysis-javascript/lib/target/export/ExportFactory.ts @@ -19,10 +19,10 @@ import { traverse } from "@babel/core"; import * as t from "@babel/types"; -import { Factory } from "../../Factory"; +import { Factory } from "../../Factory.js"; -import { Export } from "./Export"; -import { ExportVisitor } from "./ExportVisitor"; +import { Export } from "./Export.js"; +import { ExportVisitor } from "./ExportVisitor.js"; /** * ExportFactory for Javascript. diff --git a/libraries/analysis-javascript/lib/target/export/ExportNamedDeclaration.ts b/libraries/analysis-javascript/lib/target/export/ExportNamedDeclaration.ts index faa00285a..cef62cebd 100644 --- a/libraries/analysis-javascript/lib/target/export/ExportNamedDeclaration.ts +++ b/libraries/analysis-javascript/lib/target/export/ExportNamedDeclaration.ts @@ -18,8 +18,8 @@ import { NodePath } from "@babel/core"; import * as t from "@babel/types"; -import { Export } from "./Export"; -import { ExportVisitor } from "./ExportVisitor"; +import { Export } from "./Export.js"; +import { ExportVisitor } from "./ExportVisitor.js"; function extractFromObjectPattern( visitor: ExportVisitor, diff --git a/libraries/analysis-javascript/lib/target/export/ExportVisitor.ts b/libraries/analysis-javascript/lib/target/export/ExportVisitor.ts index c54b54eb3..7ea53602d 100644 --- a/libraries/analysis-javascript/lib/target/export/ExportVisitor.ts +++ b/libraries/analysis-javascript/lib/target/export/ExportVisitor.ts @@ -20,10 +20,10 @@ import { NodePath } from "@babel/core"; import * as t from "@babel/types"; import { AbstractSyntaxTreeVisitor } from "@syntest/ast-visitor-javascript"; -import { Export } from "./Export"; -import { extractExportsFromExportDefaultDeclaration } from "./ExportDefaultDeclaration"; -import { extractExportsFromExportNamedDeclaration } from "./ExportNamedDeclaration"; -import { extractExportsFromAssignmentExpression } from "./ExpressionStatement"; +import { Export } from "./Export.js"; +import { extractExportsFromExportDefaultDeclaration } from "./ExportDefaultDeclaration.js"; +import { extractExportsFromExportNamedDeclaration } from "./ExportNamedDeclaration.js"; +import { extractExportsFromAssignmentExpression } from "./ExpressionStatement.js"; export class ExportVisitor extends AbstractSyntaxTreeVisitor { private _exports: Export[]; diff --git a/libraries/analysis-javascript/lib/target/export/ExpressionStatement.ts b/libraries/analysis-javascript/lib/target/export/ExpressionStatement.ts index 0b6782880..12fe281ab 100644 --- a/libraries/analysis-javascript/lib/target/export/ExpressionStatement.ts +++ b/libraries/analysis-javascript/lib/target/export/ExpressionStatement.ts @@ -20,8 +20,8 @@ import { NodePath } from "@babel/core"; import * as t from "@babel/types"; import { getLogger } from "@syntest/logging"; -import { Export } from "./Export"; -import { ExportVisitor } from "./ExportVisitor"; +import { Export } from "./Export.js"; +import { ExportVisitor } from "./ExportVisitor.js"; type PartialExport = PartialDefaultExport | PartialNonDefaultExport; diff --git a/libraries/analysis-javascript/lib/type/discovery/TypeExtractor.ts b/libraries/analysis-javascript/lib/type/discovery/TypeExtractor.ts index 905bbf57b..485b51fec 100644 --- a/libraries/analysis-javascript/lib/type/discovery/TypeExtractor.ts +++ b/libraries/analysis-javascript/lib/type/discovery/TypeExtractor.ts @@ -15,14 +15,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import traverse from "@babel/traverse"; +import _traverse from "@babel/traverse"; import * as t from "@babel/types"; -import { Factory } from "../../Factory"; +import { Factory } from "../../Factory.js"; -import { ElementVisitor } from "./element/ElementVisitor"; -import { ObjectVisitor } from "./object/ObjectVisitor"; -import { RelationVisitor } from "./relation/RelationVisitor"; +import { ElementVisitor } from "./element/ElementVisitor.js"; +import { ObjectVisitor } from "./object/ObjectVisitor.js"; +import { RelationVisitor } from "./relation/RelationVisitor.js"; + +const traverse = (<{ default: typeof _traverse }>(_traverse)).default; export class TypeExtractor extends Factory { extractElements(filepath: string, ast: t.Node) { diff --git a/libraries/analysis-javascript/lib/type/discovery/element/ElementVisitor.ts b/libraries/analysis-javascript/lib/type/discovery/element/ElementVisitor.ts index 88cd1805a..243f3c3fb 100644 --- a/libraries/analysis-javascript/lib/type/discovery/element/ElementVisitor.ts +++ b/libraries/analysis-javascript/lib/type/discovery/element/ElementVisitor.ts @@ -22,7 +22,7 @@ import { MemberSeparator, } from "@syntest/ast-visitor-javascript"; -import { Element, ElementType } from "../element/Element"; +import { Element, ElementType } from "../element/Element.js"; export class ElementVisitor extends AbstractSyntaxTreeVisitor { private _elementMap: Map; @@ -84,7 +84,11 @@ export class ElementVisitor extends AbstractSyntaxTreeVisitor { return; } - throw new Error(`Overriding element with id: ${id}`); + // known cases + // ({ x = 5 }) => {...} (x is recorded twice) + + ElementVisitor.LOGGER.warn(`Overriding element with id: ${id}`); + return; } if (type === ElementType.Identifier) { diff --git a/libraries/analysis-javascript/lib/type/discovery/object/ObjectVisitor.ts b/libraries/analysis-javascript/lib/type/discovery/object/ObjectVisitor.ts index be8c043d4..ab2b5e806 100644 --- a/libraries/analysis-javascript/lib/type/discovery/object/ObjectVisitor.ts +++ b/libraries/analysis-javascript/lib/type/discovery/object/ObjectVisitor.ts @@ -19,7 +19,7 @@ import { NodePath } from "@babel/core"; import * as t from "@babel/types"; import { AbstractSyntaxTreeVisitor } from "@syntest/ast-visitor-javascript"; -import { DiscoveredObjectKind, DiscoveredType } from "./DiscoveredType"; +import { DiscoveredObjectKind, DiscoveredType } from "./DiscoveredType.js"; export class ObjectVisitor extends AbstractSyntaxTreeVisitor { private _objectTypeMap: Map; @@ -59,28 +59,36 @@ export class ObjectVisitor extends AbstractSyntaxTreeVisitor { } } - private _getPropertyName(node: t.ClassProperty["key"]) { - if (node.type === "Identifier") { + private _getPropertyName( + path: NodePath + ): string | undefined { + if ("computed" in path.parent && path.parent.computed) { + // e.g. { [x.y]: 5 } + return undefined; + } + + if (path.isIdentifier()) { // e.g. class A { x = class {} } // e.g. class A { x = function () {} } // e.g. class A { x = () => {} } - return node.name; - } else if (node.type.includes("Literal")) { + return path.node.name; + } else if (path.isLiteral()) { // e.g. class A { "x" = class {} } // e.g. class A { "x" = function () {} } // e.g. class A { "x" = () => {} } - return "value" in node ? node.value.toString() : "null"; - } else { - // e.g. const {x} = class {} - // e.g. const {x} = function {} - // e.g. const {x} = () => {} - // Should not be possible - throw new Error( - `Unexpected property name type: ${node.type} at ${this._getNodeId( - node - )}` - ); + return "value" in path.node ? path.node.value.toString() : "null"; } + // e.g. const {x} = class {} + // e.g. const {x} = function {} + // e.g. const {x} = () => {} + // Should not be possible + + ObjectVisitor.LOGGER.warn( + `Unexpected property name type: ${path.node.type} at ${this._getNodeId( + path + )}` + ); + return undefined; } // classes @@ -123,7 +131,7 @@ export class ObjectVisitor extends AbstractSyntaxTreeVisitor { public ClassMethod: (path: NodePath) => void = ( path: NodePath ) => { - const name = this._getPropertyName(path.node.key); + const name = this._getPropertyName(path.get("key")); const currentObject = this._getCurrentObject(path); currentObject.properties.set(name, this._getNodeId(path)); @@ -132,7 +140,7 @@ export class ObjectVisitor extends AbstractSyntaxTreeVisitor { public ClassPrivateMethod: (path: NodePath) => void = ( path: NodePath ) => { - const name = this._getPropertyName(path.node.key.id); + const name = this._getPropertyName(path.get("key").get("id")); const currentObject = this._getCurrentObject(path); currentObject.properties.set(`#${name}`, this._getNodeId(path)); @@ -141,7 +149,7 @@ export class ObjectVisitor extends AbstractSyntaxTreeVisitor { public ClassProperty: (path: NodePath) => void = ( path: NodePath ) => { - const name = this._getPropertyName(path.node.key); + const name = this._getPropertyName(path.get("key")); const currentObject = this._getCurrentObject(path); currentObject.properties.set(name, this._getNodeId(path)); @@ -150,7 +158,7 @@ export class ObjectVisitor extends AbstractSyntaxTreeVisitor { public ClassPrivateProperty: ( path: NodePath ) => void = (path: NodePath) => { - const name = this._getPropertyName(path.node.key.id); + const name = this._getPropertyName(path.get("key").get("id")); const currentObject = this._getCurrentObject(path); currentObject.properties.set(`#${name}`, this._getNodeId(path)); @@ -209,7 +217,7 @@ export class ObjectVisitor extends AbstractSyntaxTreeVisitor { public ObjectMethod: (path: NodePath) => void = ( path: NodePath ) => { - const name = this._getPropertyName(path.node.key); + const name = this._getPropertyName(path.get("key")); const currentObject = this._getCurrentObject(path); currentObject.properties.set(name, this._getNodeId(path)); @@ -229,12 +237,14 @@ export class ObjectVisitor extends AbstractSyntaxTreeVisitor { return; } - if (path.node.key.type === "PrivateName") { - const name = this._getPropertyName(path.node.key.id); + if (path.get("key").isPrivateName()) { + const name = this._getPropertyName( + (>path.get("key")).get("id") + ); currentObject.properties.set(`#${name}`, this._getNodeId(path)); } else { - const name = this._getPropertyName(path.node.key); + const name = this._getPropertyName(path.get("key")); currentObject.properties.set(name, this._getNodeId(path)); } @@ -319,12 +329,14 @@ export class ObjectVisitor extends AbstractSyntaxTreeVisitor { ); } - if (path.node.property.type === "PrivateName") { - const name = this._getPropertyName(path.node.property.id); + if (path.get("property").isPrivateName()) { + const name = this._getPropertyName( + (>path.get("property")).get("id") + ); _object.properties.set(`#${name}`, this._getNodeId(path)); } else { - const name = this._getPropertyName(path.node.property); + const name = this._getPropertyName(path.get("property")); _object.properties.set(name, this._getNodeId(path)); } @@ -341,12 +353,14 @@ export class ObjectVisitor extends AbstractSyntaxTreeVisitor { this._objectTypeMap.set(bindingId, _object); } - if (path.node.property.type === "PrivateName") { - const name = this._getPropertyName(path.node.property.id); + if (path.get("property").isPrivateName()) { + const name = this._getPropertyName( + (>path.get("property")).get("id") + ); _object.properties.set(`#${name}`, this._getNodeId(path)); } else { - const name = this._getPropertyName(path.node.property); + const name = this._getPropertyName(path.get("property")); _object.properties.set(name, this._getNodeId(path)); } diff --git a/libraries/analysis-javascript/lib/type/discovery/relation/RelationVisitor.ts b/libraries/analysis-javascript/lib/type/discovery/relation/RelationVisitor.ts index 7edeaf8a5..a71fa0893 100644 --- a/libraries/analysis-javascript/lib/type/discovery/relation/RelationVisitor.ts +++ b/libraries/analysis-javascript/lib/type/discovery/relation/RelationVisitor.ts @@ -19,7 +19,11 @@ import { NodePath } from "@babel/core"; import * as t from "@babel/types"; import { AbstractSyntaxTreeVisitor } from "@syntest/ast-visitor-javascript"; -import { getRelationType, Relation, RelationType } from "../relation/Relation"; +import { + getRelationType, + Relation, + RelationType, +} from "../relation/Relation.js"; export class RelationVisitor extends AbstractSyntaxTreeVisitor { private _relationMap: Map; diff --git a/libraries/analysis-javascript/lib/type/resolving/InferenceTypeModelFactory.ts b/libraries/analysis-javascript/lib/type/resolving/InferenceTypeModelFactory.ts index 8632e6297..1cd612f5e 100644 --- a/libraries/analysis-javascript/lib/type/resolving/InferenceTypeModelFactory.ts +++ b/libraries/analysis-javascript/lib/type/resolving/InferenceTypeModelFactory.ts @@ -16,16 +16,16 @@ * limitations under the License. */ -import { Element, ElementType } from "../discovery/element/Element"; +import { Element, ElementType } from "../discovery/element/Element.js"; import { getRelationName, Relation, RelationType, -} from "../discovery/relation/Relation"; +} from "../discovery/relation/Relation.js"; -import { elementTypeToTypingType, TypeEnum } from "./TypeEnum"; -import { TypeModel } from "./TypeModel"; -import { TypeModelFactory } from "./TypeModelFactory"; +import { elementTypeToTypingType, TypeEnum } from "./TypeEnum.js"; +import { TypeModel } from "./TypeModel.js"; +import { TypeModelFactory } from "./TypeModelFactory.js"; export class InferenceTypeModelFactory extends TypeModelFactory { private _typeModel: TypeModel; diff --git a/libraries/analysis-javascript/lib/type/resolving/TypeEnum.ts b/libraries/analysis-javascript/lib/type/resolving/TypeEnum.ts index 6a1fbf57a..db7780f01 100644 --- a/libraries/analysis-javascript/lib/type/resolving/TypeEnum.ts +++ b/libraries/analysis-javascript/lib/type/resolving/TypeEnum.ts @@ -16,7 +16,7 @@ * limitations under the License. */ -import { ElementType } from "../discovery/element/Element"; +import { ElementType } from "../discovery/element/Element.js"; export enum TypeEnum { NUMERIC = "numeric", diff --git a/libraries/analysis-javascript/lib/type/resolving/TypeModel.ts b/libraries/analysis-javascript/lib/type/resolving/TypeModel.ts index 70367584c..fd9b87409 100644 --- a/libraries/analysis-javascript/lib/type/resolving/TypeModel.ts +++ b/libraries/analysis-javascript/lib/type/resolving/TypeModel.ts @@ -23,8 +23,8 @@ import { functionProperties, ObjectType, stringProperties, -} from "./Type"; -import { TypeEnum } from "./TypeEnum"; +} from "./Type.js"; +import { TypeEnum } from "./TypeEnum.js"; export class TypeModel { private _elements: Set; diff --git a/libraries/analysis-javascript/lib/type/resolving/TypeModelFactory.ts b/libraries/analysis-javascript/lib/type/resolving/TypeModelFactory.ts index 6c6a6aeb1..c4646ea25 100644 --- a/libraries/analysis-javascript/lib/type/resolving/TypeModelFactory.ts +++ b/libraries/analysis-javascript/lib/type/resolving/TypeModelFactory.ts @@ -16,10 +16,10 @@ * limitations under the License. */ -import { Element } from "../discovery/element/Element"; -import { Relation } from "../discovery/relation/Relation"; +import { Element } from "../discovery/element/Element.js"; +import { Relation } from "../discovery/relation/Relation.js"; -import { TypeModel } from "./TypeModel"; +import { TypeModel } from "./TypeModel.js"; /** * Abstract TypeResolver class diff --git a/libraries/analysis-javascript/lib/type/resolving/TypePool.ts b/libraries/analysis-javascript/lib/type/resolving/TypePool.ts index 07a809dc1..e9ef36f4f 100644 --- a/libraries/analysis-javascript/lib/type/resolving/TypePool.ts +++ b/libraries/analysis-javascript/lib/type/resolving/TypePool.ts @@ -18,10 +18,10 @@ import { prng } from "@syntest/prng"; -import { Export } from "../../target/export/Export"; -import { DiscoveredObjectType } from "../discovery/object/DiscoveredType"; +import { Export } from "../../target/export/Export.js"; +import { DiscoveredObjectType } from "../discovery/object/DiscoveredType.js"; -import { ObjectType } from "./Type"; +import { ObjectType } from "./Type.js"; // TODO we could cache some of this stuff (unless we do dynamic adding of properties at some point) export class TypePool { diff --git a/libraries/analysis-javascript/lib/utils/diagnostics.ts b/libraries/analysis-javascript/lib/utils/diagnostics.ts index c6e76c8d5..a48828422 100644 --- a/libraries/analysis-javascript/lib/utils/diagnostics.ts +++ b/libraries/analysis-javascript/lib/utils/diagnostics.ts @@ -22,3 +22,7 @@ export function unsupportedSyntax( ): string { return `Unsupported syntax found in ${pathType} at ${locationId}`; } + +export function computedProperty(pathType: string, locationId: string): string { + return `Computed property found in ${pathType} at ${locationId}`; +} diff --git a/libraries/analysis-javascript/package.json b/libraries/analysis-javascript/package.json index 81552ae61..32c4251a0 100644 --- a/libraries/analysis-javascript/package.json +++ b/libraries/analysis-javascript/package.json @@ -6,6 +6,7 @@ "syntest", "control-flow-graph" ], + "type": "module", "homepage": "https://www.syntest.org", "bugs": { "url": "https://github.com/syntest-framework/syntest-javascript/issues" diff --git a/libraries/analysis-javascript/test/AbstractSyntaxTreeGenerator.test.ts b/libraries/analysis-javascript/test/AbstractSyntaxTreeGenerator.test.ts index 79f412f29..5ccbb2728 100644 --- a/libraries/analysis-javascript/test/AbstractSyntaxTreeGenerator.test.ts +++ b/libraries/analysis-javascript/test/AbstractSyntaxTreeGenerator.test.ts @@ -17,7 +17,7 @@ */ import * as chai from "chai"; -import { AbstractSyntaxTreeFactory } from "../lib/ast/AbstractSyntaxTreeFactory"; +import { AbstractSyntaxTreeFactory } from "../lib/ast/AbstractSyntaxTreeFactory.js"; const expect = chai.expect; diff --git a/libraries/analysis-javascript/test/AbstractSyntaxTreeVisitor.test.ts b/libraries/analysis-javascript/test/AbstractSyntaxTreeVisitor.test.ts index 5fe242c3c..5413e9060 100644 --- a/libraries/analysis-javascript/test/AbstractSyntaxTreeVisitor.test.ts +++ b/libraries/analysis-javascript/test/AbstractSyntaxTreeVisitor.test.ts @@ -19,7 +19,7 @@ import { traverse } from "@babel/core"; import { AbstractSyntaxTreeVisitor } from "@syntest/ast-visitor-javascript"; import * as chai from "chai"; -import { AbstractSyntaxTreeFactory } from "../lib/ast/AbstractSyntaxTreeFactory"; +import { AbstractSyntaxTreeFactory } from "../lib/ast/AbstractSyntaxTreeFactory.js"; const expect = chai.expect; diff --git a/libraries/analysis-javascript/test/cfg/ControlFlowGraphVisitor.test.ts b/libraries/analysis-javascript/test/cfg/ControlFlowGraphVisitor.test.ts index b3fa2ddd4..8c7fe349f 100644 --- a/libraries/analysis-javascript/test/cfg/ControlFlowGraphVisitor.test.ts +++ b/libraries/analysis-javascript/test/cfg/ControlFlowGraphVisitor.test.ts @@ -19,8 +19,8 @@ import { traverse } from "@babel/core"; import { contractControlFlowProgram, EdgeType } from "@syntest/cfg"; import * as chai from "chai"; -import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory"; -import { ControlFlowGraphVisitor } from "../../lib/cfg/ControlFlowGraphVisitor"; +import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory.js"; +import { ControlFlowGraphVisitor } from "../../lib/cfg/ControlFlowGraphVisitor.js"; const expect = chai.expect; diff --git a/libraries/analysis-javascript/test/cfg/ForControlFlowGraphVisitor.test.ts b/libraries/analysis-javascript/test/cfg/ForControlFlowGraphVisitor.test.ts index 9cd702726..270b8fd55 100644 --- a/libraries/analysis-javascript/test/cfg/ForControlFlowGraphVisitor.test.ts +++ b/libraries/analysis-javascript/test/cfg/ForControlFlowGraphVisitor.test.ts @@ -18,8 +18,8 @@ import { traverse } from "@babel/core"; import * as chai from "chai"; -import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory"; -import { ControlFlowGraphVisitor } from "../../lib/cfg/ControlFlowGraphVisitor"; +import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory.js"; +import { ControlFlowGraphVisitor } from "../../lib/cfg/ControlFlowGraphVisitor.js"; const expect = chai.expect; diff --git a/libraries/analysis-javascript/test/cfg/TernaryControlFlowGraphVisitor.test.ts b/libraries/analysis-javascript/test/cfg/TernaryControlFlowGraphVisitor.test.ts index 5eb386b12..50723599b 100644 --- a/libraries/analysis-javascript/test/cfg/TernaryControlFlowGraphVisitor.test.ts +++ b/libraries/analysis-javascript/test/cfg/TernaryControlFlowGraphVisitor.test.ts @@ -18,8 +18,8 @@ import { traverse } from "@babel/core"; import * as chai from "chai"; -import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory"; -import { ControlFlowGraphVisitor } from "../../lib/cfg/ControlFlowGraphVisitor"; +import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory.js"; +import { ControlFlowGraphVisitor } from "../../lib/cfg/ControlFlowGraphVisitor.js"; const expect = chai.expect; diff --git a/libraries/analysis-javascript/test/dependency/DependencyVisitor.test.ts b/libraries/analysis-javascript/test/dependency/DependencyVisitor.test.ts index 0fe6df188..40508d97c 100644 --- a/libraries/analysis-javascript/test/dependency/DependencyVisitor.test.ts +++ b/libraries/analysis-javascript/test/dependency/DependencyVisitor.test.ts @@ -18,8 +18,8 @@ import { traverse } from "@babel/core"; import * as chai from "chai"; -import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory"; -import { DependencyVisitor } from "../../lib/dependency/DependencyVisitor"; +import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory.js"; +import { DependencyVisitor } from "../../lib/dependency/DependencyVisitor.js"; const expect = chai.expect; diff --git a/libraries/analysis-javascript/test/target/TargetFactory.test.ts b/libraries/analysis-javascript/test/target/TargetFactory.test.ts index 5718d3643..d63104c38 100644 --- a/libraries/analysis-javascript/test/target/TargetFactory.test.ts +++ b/libraries/analysis-javascript/test/target/TargetFactory.test.ts @@ -17,8 +17,8 @@ */ import { expect } from "chai"; -import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory"; -import { TargetFactory } from "../../lib/target/TargetFactory"; +import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory.js"; +import { TargetFactory } from "../../lib/target/TargetFactory.js"; describe("TargetFactory", () => { it("class with getter and setters", () => { diff --git a/libraries/analysis-javascript/test/target/TargetVisitor.test.ts b/libraries/analysis-javascript/test/target/TargetVisitor.test.ts index dcde99eb3..7411a826d 100644 --- a/libraries/analysis-javascript/test/target/TargetVisitor.test.ts +++ b/libraries/analysis-javascript/test/target/TargetVisitor.test.ts @@ -19,8 +19,8 @@ import { traverse } from "@babel/core"; import { TargetType } from "@syntest/analysis"; import * as chai from "chai"; -import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory"; -import { ExportVisitor } from "../../lib/target/export/ExportVisitor"; +import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory.js"; +import { ExportVisitor } from "../../lib/target/export/ExportVisitor.js"; import { ClassTarget, FunctionTarget, @@ -28,8 +28,8 @@ import { ObjectFunctionTarget, ObjectTarget, SubTarget, -} from "../../lib/target/Target"; -import { TargetVisitor } from "../../lib/target/TargetVisitor"; +} from "../../lib/target/Target.js"; +import { TargetVisitor } from "../../lib/target/TargetVisitor.js"; const expect = chai.expect; diff --git a/libraries/analysis-javascript/test/target/export/ExportVisitor.test.ts b/libraries/analysis-javascript/test/target/export/ExportVisitor.test.ts index 0e88d0f6c..4b18de54c 100644 --- a/libraries/analysis-javascript/test/target/export/ExportVisitor.test.ts +++ b/libraries/analysis-javascript/test/target/export/ExportVisitor.test.ts @@ -18,8 +18,8 @@ import { traverse } from "@babel/core"; import * as chai from "chai"; -import { AbstractSyntaxTreeFactory } from "../../../lib/ast/AbstractSyntaxTreeFactory"; -import { ExportVisitor } from "../../../lib/target/export/ExportVisitor"; +import { AbstractSyntaxTreeFactory } from "../../../lib/ast/AbstractSyntaxTreeFactory.js"; +import { ExportVisitor } from "../../../lib/target/export/ExportVisitor.js"; const expect = chai.expect; diff --git a/libraries/analysis-javascript/test/type/ElementVisitor.test.ts b/libraries/analysis-javascript/test/type/ElementVisitor.test.ts index 3a4573bff..217b0110b 100644 --- a/libraries/analysis-javascript/test/type/ElementVisitor.test.ts +++ b/libraries/analysis-javascript/test/type/ElementVisitor.test.ts @@ -18,9 +18,9 @@ import { traverse } from "@babel/core"; import * as chai from "chai"; -import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory"; -import { Identifier } from "../../lib/type/discovery/element/Element"; -import { ElementVisitor } from "../../lib/type/discovery/element/ElementVisitor"; +import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory.js"; +import { Identifier } from "../../lib/type/discovery/element/Element.js"; +import { ElementVisitor } from "../../lib/type/discovery/element/ElementVisitor.js"; const expect = chai.expect; diff --git a/libraries/analysis-javascript/test/type/InferenceTypeModelFactory.test.ts b/libraries/analysis-javascript/test/type/InferenceTypeModelFactory.test.ts index aa99debec..e0a4c1a65 100644 --- a/libraries/analysis-javascript/test/type/InferenceTypeModelFactory.test.ts +++ b/libraries/analysis-javascript/test/type/InferenceTypeModelFactory.test.ts @@ -17,11 +17,11 @@ */ import traverse from "@babel/traverse"; -import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory"; -import { ElementVisitor } from "../../lib/type/discovery/element/ElementVisitor"; -import { RelationType } from "../../lib/type/discovery/relation/Relation"; -import { RelationVisitor } from "../../lib/type/discovery/relation/RelationVisitor"; -import { InferenceTypeModelFactory } from "../../lib/type/resolving/InferenceTypeModelFactory"; +import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory.js"; +import { ElementVisitor } from "../../lib/type/discovery/element/ElementVisitor.js"; +import { RelationType } from "../../lib/type/discovery/relation/Relation.js"; +import { RelationVisitor } from "../../lib/type/discovery/relation/RelationVisitor.js"; +import { InferenceTypeModelFactory } from "../../lib/type/resolving/InferenceTypeModelFactory.js"; function helper(source: string) { const generator = new AbstractSyntaxTreeFactory(); diff --git a/libraries/analysis-javascript/test/type/RelationVisitor.test.ts b/libraries/analysis-javascript/test/type/RelationVisitor.test.ts index 84dd1fdaf..df61ea240 100644 --- a/libraries/analysis-javascript/test/type/RelationVisitor.test.ts +++ b/libraries/analysis-javascript/test/type/RelationVisitor.test.ts @@ -18,8 +18,8 @@ import { traverse } from "@babel/core"; import * as chai from "chai"; -import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory"; -import { RelationVisitor } from "../../lib/type/discovery/relation/RelationVisitor"; +import { AbstractSyntaxTreeFactory } from "../../lib/ast/AbstractSyntaxTreeFactory.js"; +import { RelationVisitor } from "../../lib/type/discovery/relation/RelationVisitor.js"; const expect = chai.expect; diff --git a/libraries/ast-visitor-javascript/index.ts b/libraries/ast-visitor-javascript/index.ts index 8470a7845..0b034862c 100644 --- a/libraries/ast-visitor-javascript/index.ts +++ b/libraries/ast-visitor-javascript/index.ts @@ -16,6 +16,6 @@ * limitations under the License. */ -export * from "./lib/AbstractSyntaxTreeVisitor"; -export * from "./lib/globalVariables"; -export * from "./lib/reservedKeywords"; +export * from "./lib/AbstractSyntaxTreeVisitor.js"; +export * from "./lib/globalVariables.js"; +export * from "./lib/reservedKeywords.js"; diff --git a/libraries/ast-visitor-javascript/lib/AbstractSyntaxTreeVisitor.ts b/libraries/ast-visitor-javascript/lib/AbstractSyntaxTreeVisitor.ts index 72e8c51f1..649efce8a 100644 --- a/libraries/ast-visitor-javascript/lib/AbstractSyntaxTreeVisitor.ts +++ b/libraries/ast-visitor-javascript/lib/AbstractSyntaxTreeVisitor.ts @@ -20,12 +20,18 @@ import { Scope as BabelScope, TraverseOptions } from "@babel/traverse"; import * as t from "@babel/types"; import { getLogger, Logger } from "@syntest/logging"; -import { globalVariables } from "./globalVariables"; -import { reservedKeywords } from "./reservedKeywords"; +import { globalVariables } from "./globalVariables.js"; +import { reservedKeywords } from "./reservedKeywords.js"; export const MemberSeparator = " <-> "; export class AbstractSyntaxTreeVisitor implements TraverseOptions { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [k: `${string}|${string}`]: ( + this: any, + path: NodePath, + state: any + ) => void; protected static LOGGER: Logger; protected _filePath: string; diff --git a/libraries/ast-visitor-javascript/lib/globalVariables.ts b/libraries/ast-visitor-javascript/lib/globalVariables.ts index f689f900a..ff59b71a2 100644 --- a/libraries/ast-visitor-javascript/lib/globalVariables.ts +++ b/libraries/ast-visitor-javascript/lib/globalVariables.ts @@ -15,7 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as globals from "globals"; +import globals from "globals"; export const globalVariables = new Set( // eslint-disable-next-line @typescript-eslint/no-unsafe-argument diff --git a/libraries/ast-visitor-javascript/package.json b/libraries/ast-visitor-javascript/package.json index 7a17f21de..7e7f1af80 100644 --- a/libraries/ast-visitor-javascript/package.json +++ b/libraries/ast-visitor-javascript/package.json @@ -6,6 +6,7 @@ "syntest", "abstract-syntax-tree" ], + "type": "module", "homepage": "https://www.syntest.org", "bugs": { "url": "https://github.com/syntest-framework/syntest-javascript/issues" diff --git a/libraries/ast-visitor-javascript/test/example.test.ts b/libraries/ast-visitor-javascript/test/example.test.ts index d31f1d9d8..90f2ae38c 100644 --- a/libraries/ast-visitor-javascript/test/example.test.ts +++ b/libraries/ast-visitor-javascript/test/example.test.ts @@ -17,7 +17,7 @@ */ import * as chai from "chai"; -import { AbstractSyntaxTreeVisitor } from "../lib/AbstractSyntaxTreeVisitor"; +import { AbstractSyntaxTreeVisitor } from "../lib/AbstractSyntaxTreeVisitor.js"; const expect = chai.expect; diff --git a/libraries/instrumentation-javascript/index.ts b/libraries/instrumentation-javascript/index.ts index 046edcd1d..d4eed3af3 100644 --- a/libraries/instrumentation-javascript/index.ts +++ b/libraries/instrumentation-javascript/index.ts @@ -16,9 +16,11 @@ * limitations under the License. */ -export * from "./lib/datastructures/InstrumentationData"; -export * from "./lib/datastructures/MetaData"; +export * from "./lib/datastructures/AssertionData.js"; +export * from "./lib/datastructures/InstrumentationData.js"; +export * from "./lib/datastructures/MetaData.js"; -export * from "./lib/instrumentation/Instrumenter"; -export * from "./lib/instrumentation/Visitor"; -export * from "./lib/instrumentation/VisitState"; +export * from "./lib/instrumentation/Global.js"; +export * from "./lib/instrumentation/Instrumenter.js"; +export * from "./lib/instrumentation/Visitor.js"; +export * from "./lib/instrumentation/VisitState.js"; diff --git a/libraries/search-javascript/lib/testcase/execution/AssertionData.ts b/libraries/instrumentation-javascript/lib/datastructures/AssertionData.ts similarity index 100% rename from libraries/search-javascript/lib/testcase/execution/AssertionData.ts rename to libraries/instrumentation-javascript/lib/datastructures/AssertionData.ts diff --git a/libraries/instrumentation-javascript/lib/datastructures/InstrumentationData.ts b/libraries/instrumentation-javascript/lib/datastructures/InstrumentationData.ts index eb1210816..691c42b86 100644 --- a/libraries/instrumentation-javascript/lib/datastructures/InstrumentationData.ts +++ b/libraries/instrumentation-javascript/lib/datastructures/InstrumentationData.ts @@ -38,7 +38,7 @@ export type BranchMap = { line: number; type: string; loc: Location; - locations: [Location, Location]; + locations: Location[]; }; }; @@ -64,7 +64,7 @@ export type InstrumentationData = { }; b: { // 0 is true, 1 is false - [id: string]: [number, number]; + [id: string]: number[]; }; }; diff --git a/commitlint.config.js b/libraries/instrumentation-javascript/lib/instrumentation/Global.ts similarity index 66% rename from commitlint.config.js rename to libraries/instrumentation-javascript/lib/instrumentation/Global.ts index 24b57c75d..e2087dcbe 100644 --- a/commitlint.config.js +++ b/libraries/instrumentation-javascript/lib/instrumentation/Global.ts @@ -15,6 +15,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -module.exports = { - extends: ["@commitlint/config-conventional"], + +import { AssertionData } from "../datastructures/AssertionData"; +import { InstrumentationDataMap } from "../datastructures/InstrumentationData"; +import { MetaDataMap } from "../datastructures/MetaData"; + +type GlobalType = { + __coverage__?: InstrumentationDataMap; + __meta__?: MetaDataMap; + __assertion__?: AssertionData; }; + +export const Global: GlobalType = {}; diff --git a/libraries/instrumentation-javascript/lib/instrumentation/Instrumenter.ts b/libraries/instrumentation-javascript/lib/instrumentation/Instrumenter.ts index 0046b4d3d..9149f68a0 100644 --- a/libraries/instrumentation-javascript/lib/instrumentation/Instrumenter.ts +++ b/libraries/instrumentation-javascript/lib/instrumentation/Instrumenter.ts @@ -17,7 +17,7 @@ */ import { transformSync } from "@babel/core"; -import { Visitor } from "./Visitor"; +import { Visitor } from "./Visitor.js"; import { RootContext, Target, diff --git a/libraries/instrumentation-javascript/lib/instrumentation/VisitState.ts b/libraries/instrumentation-javascript/lib/instrumentation/VisitState.ts index 1b510b759..5ad02618c 100644 --- a/libraries/instrumentation-javascript/lib/instrumentation/VisitState.ts +++ b/libraries/instrumentation-javascript/lib/instrumentation/VisitState.ts @@ -18,7 +18,7 @@ import { createHash } from "crypto"; -import { SourceCoverage } from "./source-coverage"; +import { SourceCoverage } from "./source-coverage.js"; const SHA = "sha1"; @@ -41,7 +41,7 @@ export class VisitState { public metaVarName: string; public attrs: any; public nextIgnore: any; - public cov: any; + public cov: SourceCoverage; public ignoreClassMethods: any; public types: any; @@ -390,13 +390,13 @@ export class VisitState { return metaTracker; } - getBranchLogicIncrement(path, branchName, loc) { - const index = this.cov.addBranchPath(branchName, loc); - return [ - this.increase("b", branchName, index), - this.increaseTrue("bT", branchName, index, path.node), - ]; - } + // getBranchLogicIncrement(path, branchName, loc) { + // const index = this.cov.addBranchPath(branchName, loc); + // return [ + // this.increase("b", branchName, index), + // this.increaseTrue("bT", branchName, index, path.node), + // ]; + // } insertBranchCounter(ifPath, path, branchName, placeholder = false) { const increment = this.getBranchIncrement( diff --git a/libraries/instrumentation-javascript/lib/instrumentation/Visitor.ts b/libraries/instrumentation-javascript/lib/instrumentation/Visitor.ts index 397ddf1a8..867e2f751 100644 --- a/libraries/instrumentation-javascript/lib/instrumentation/Visitor.ts +++ b/libraries/instrumentation-javascript/lib/instrumentation/Visitor.ts @@ -17,7 +17,7 @@ */ import { defaults } from "@istanbuljs/schema"; -import { VisitState } from "./VisitState"; +import { VisitState } from "./VisitState.js"; import { createHash } from "crypto"; import { NodePath, template } from "@babel/core"; import * as t from "@babel/types"; @@ -26,6 +26,7 @@ import { globalVariables, reservedKeywords, } from "@syntest/ast-visitor-javascript"; +import { InstrumentationData } from "../datastructures/InstrumentationData.js"; const name = "syntest"; @@ -79,7 +80,7 @@ export class Visitor { return undefined; } this.visitState.cov.freeze(); - const coverageData = this.visitState.cov.toJSON(); + const coverageData: InstrumentationData = this.visitState.cov.toJSON(); if (shouldIgnoreFile(path.find((p) => p.isProgram()))) { return { fileCoverage: coverageData, diff --git a/libraries/instrumentation-javascript/lib/instrumentation/source-coverage.ts b/libraries/instrumentation-javascript/lib/instrumentation/source-coverage.ts index 85ccee6f0..8a423bbdc 100644 --- a/libraries/instrumentation-javascript/lib/instrumentation/source-coverage.ts +++ b/libraries/instrumentation-javascript/lib/instrumentation/source-coverage.ts @@ -17,7 +17,7 @@ */ import { NodePath } from "@babel/traverse"; import * as t from "@babel/types"; -const { classes } = require("istanbul-lib-coverage"); +import { InstrumentationData } from "../datastructures/InstrumentationData"; /** * SourceCoverage provides mutation methods to manipulate the structure of @@ -29,12 +29,11 @@ const { classes } = require("istanbul-lib-coverage"); * @extends FileCoverage * @constructor */ -export class SourceCoverage extends classes.FileCoverage { +export class SourceCoverage { private meta: any; - private data: any; + private data: InstrumentationData; private _filePath: string; constructor(pathOrObj) { - super(pathOrObj); this._filePath = pathOrObj; this.meta = { last: { @@ -43,6 +42,15 @@ export class SourceCoverage extends classes.FileCoverage { b: 0, }, }; + this.data = { + hash: "", + statementMap: {}, + fnMap: {}, + branchMap: {}, + s: {}, + f: {}, + b: {}, + }; } public _getNodeId(loc): string { @@ -157,8 +165,8 @@ export class SourceCoverage extends classes.FileCoverage { if (type !== "binary-expr") { return; } - this.data.bT = this.data.bT || {}; - this.data.bT[name] = []; + (<{ bT }>(this.data)).bT = (<{ bT }>(this.data)).bT || {}; + (<{ bT }>(this.data)).bT[name] = []; } addBranchPath(ifPath: NodePath, name, location) { @@ -188,10 +196,10 @@ export class SourceCoverage extends classes.FileCoverage { } maybeAddBranchTrue(name) { - if (!this.data.bT) { + if (!(<{ bT }>(this.data)).bT) { return; } - const countsTrue = this.data.bT[name]; + const countsTrue = (<{ bT }>(this.data)).bT[name]; if (!countsTrue) { return; } @@ -204,14 +212,14 @@ export class SourceCoverage extends classes.FileCoverage { * @param sourceMap {object} the source map */ inputSourceMap(sourceMap) { - this.data.inputSourceMap = sourceMap; + (<{ inputSourceMap }>(this.data)).inputSourceMap = sourceMap; } freeze() { // prune empty branches const map = this.data.branchMap; const branches = this.data.b; - const branchesT = this.data.bT || {}; + const branchesT = (<{ bT }>(this.data)).bT || {}; Object.keys(map).forEach((b) => { if (map[b].locations.length === 0) { delete map[b]; @@ -220,4 +228,8 @@ export class SourceCoverage extends classes.FileCoverage { } }); } + + toJSON() { + return this.data; + } } diff --git a/libraries/instrumentation-javascript/package.json b/libraries/instrumentation-javascript/package.json index 54979b39a..39a48ca78 100644 --- a/libraries/instrumentation-javascript/package.json +++ b/libraries/instrumentation-javascript/package.json @@ -6,6 +6,7 @@ "syntest", "abstract-syntax-tree" ], + "type": "module", "homepage": "https://www.syntest.org", "bugs": { "url": "https://github.com/syntest-framework/syntest-javascript/issues" @@ -56,7 +57,8 @@ }, "devDependencies": { "@babel/types": "^7.21.5", - "@types/babel__core": "7.20.0" + "@types/babel__core": "7.20.0", + "@types/istanbul-lib-coverage": "^2.0.4" }, "engines": { "node": ">=10.24.0" diff --git a/libraries/instrumentation-javascript/test/example.test.ts b/libraries/instrumentation-javascript/test/example.test.ts index 744b35563..4d641e330 100644 --- a/libraries/instrumentation-javascript/test/example.test.ts +++ b/libraries/instrumentation-javascript/test/example.test.ts @@ -17,7 +17,7 @@ */ import * as chai from "chai"; -import { Instrumenter } from "../lib/instrumentation/Instrumenter"; +import { Instrumenter } from "../lib/instrumentation/Instrumenter.js"; const expect = chai.expect; diff --git a/libraries/search-javascript/index.ts b/libraries/search-javascript/index.ts index 32ca9ee65..2a2da74d7 100644 --- a/libraries/search-javascript/index.ts +++ b/libraries/search-javascript/index.ts @@ -16,43 +16,43 @@ * limitations under the License. */ -export * from "./lib/criterion/BranchDistance"; +export * from "./lib/criterion/BranchDistance.js"; -export * from "./lib/search/crossover/TreeCrossover"; +export * from "./lib/search/crossover/TreeCrossover.js"; -export * from "./lib/search/JavaScriptExecutionResult"; -export * from "./lib/search/JavaScriptSubject"; +export * from "./lib/search/JavaScriptExecutionResult.js"; +export * from "./lib/search/JavaScriptSubject.js"; -export * from "./lib/testbuilding/JavaScriptDecoder"; -export * from "./lib/testbuilding/JavaScriptSuiteBuilder"; +export * from "./lib/testbuilding/JavaScriptDecoder.js"; +export * from "./lib/testbuilding/JavaScriptSuiteBuilder.js"; -export * from "./lib/testcase/execution/ExecutionInformationIntegrator"; -export * from "./lib/testcase/execution/JavaScriptRunner"; -export * from "./lib/testcase/execution/SilentMochaReporter"; +export * from "./lib/testcase/execution/ExecutionInformationIntegrator.js"; +export * from "./lib/testcase/execution/JavaScriptRunner.js"; +export * from "./lib/testcase/execution/SilentMochaReporter.js"; -export * from "./lib/testcase/sampling/JavaScriptRandomSampler"; -export * from "./lib/testcase/sampling/JavaScriptTestCaseSampler"; +export * from "./lib/testcase/sampling/JavaScriptRandomSampler.js"; +export * from "./lib/testcase/sampling/JavaScriptTestCaseSampler.js"; -export * from "./lib/testcase/statements/action/ActionStatement"; -export * from "./lib/testcase/statements/action/Getter"; -export * from "./lib/testcase/statements/action/MethodCall"; -export * from "./lib/testcase/statements/action/Setter"; +export * from "./lib/testcase/statements/action/ActionStatement.js"; +export * from "./lib/testcase/statements/action/Getter.js"; +export * from "./lib/testcase/statements/action/MethodCall.js"; +export * from "./lib/testcase/statements/action/Setter.js"; -export * from "./lib/testcase/statements/complex/ArrayStatement"; -export * from "./lib/testcase/statements/complex/ArrowFunctionStatement"; -export * from "./lib/testcase/statements/complex/ObjectStatement"; +export * from "./lib/testcase/statements/complex/ArrayStatement.js"; +export * from "./lib/testcase/statements/complex/ArrowFunctionStatement.js"; +export * from "./lib/testcase/statements/complex/ObjectStatement.js"; -export * from "./lib/testcase/statements/primitive/BoolStatement"; -export * from "./lib/testcase/statements/primitive/NullStatement"; -export * from "./lib/testcase/statements/primitive/NumericStatement"; -export * from "./lib/testcase/statements/primitive/PrimitiveStatement"; -export * from "./lib/testcase/statements/primitive/StringStatement"; -export * from "./lib/testcase/statements/primitive/UndefinedStatement"; +export * from "./lib/testcase/statements/primitive/BoolStatement.js"; +export * from "./lib/testcase/statements/primitive/NullStatement.js"; +export * from "./lib/testcase/statements/primitive/NumericStatement.js"; +export * from "./lib/testcase/statements/primitive/PrimitiveStatement.js"; +export * from "./lib/testcase/statements/primitive/StringStatement.js"; +export * from "./lib/testcase/statements/primitive/UndefinedStatement.js"; -export * from "./lib/testcase/statements/action/ConstructorCall"; -export * from "./lib/testcase/statements/action/FunctionCall"; -export * from "./lib/testcase/statements/action/ConstantObject"; +export * from "./lib/testcase/statements/action/ConstructorCall.js"; +export * from "./lib/testcase/statements/action/FunctionCall.js"; +export * from "./lib/testcase/statements/action/ConstantObject.js"; -export * from "./lib/testcase/statements/Statement"; +export * from "./lib/testcase/statements/Statement.js"; -export * from "./lib/testcase/JavaScriptTestCase"; +export * from "./lib/testcase/JavaScriptTestCase.js"; diff --git a/libraries/search-javascript/lib/criterion/BranchDistance.ts b/libraries/search-javascript/lib/criterion/BranchDistance.ts index fd75f3016..302291166 100644 --- a/libraries/search-javascript/lib/criterion/BranchDistance.ts +++ b/libraries/search-javascript/lib/criterion/BranchDistance.ts @@ -24,7 +24,7 @@ import { shouldNeverHappen, } from "@syntest/search"; -import { BranchDistanceVisitor } from "./BranchDistanceVisitor"; +import { BranchDistanceVisitor } from "./BranchDistanceVisitor.js"; export class BranchDistance extends CoreBranchDistance { protected static LOGGER: Logger; diff --git a/libraries/search-javascript/lib/search/JavaScriptSubject.ts b/libraries/search-javascript/lib/search/JavaScriptSubject.ts index db303fb24..d547e152d 100644 --- a/libraries/search-javascript/lib/search/JavaScriptSubject.ts +++ b/libraries/search-javascript/lib/search/JavaScriptSubject.ts @@ -27,8 +27,8 @@ import { shouldNeverHappen, } from "@syntest/search"; -import { BranchDistance } from "../criterion/BranchDistance"; -import { JavaScriptTestCase } from "../testcase/JavaScriptTestCase"; +import { BranchDistance } from "../criterion/BranchDistance.js"; +import { JavaScriptTestCase } from "../testcase/JavaScriptTestCase.js"; export class JavaScriptSubject extends SearchSubject { protected syntaxForgiving: boolean; diff --git a/libraries/search-javascript/lib/search/crossover/TreeCrossover.ts b/libraries/search-javascript/lib/search/crossover/TreeCrossover.ts index e953d7710..5c3807ff5 100644 --- a/libraries/search-javascript/lib/search/crossover/TreeCrossover.ts +++ b/libraries/search-javascript/lib/search/crossover/TreeCrossover.ts @@ -19,11 +19,11 @@ import { prng } from "@syntest/prng"; import { Crossover } from "@syntest/search"; -import { JavaScriptTestCase } from "../../testcase/JavaScriptTestCase"; -import { ActionStatement } from "../../testcase/statements/action/ActionStatement"; -import { ConstantObject } from "../../testcase/statements/action/ConstantObject"; -import { ConstructorCall } from "../../testcase/statements/action/ConstructorCall"; -import { Statement } from "../../testcase/statements/Statement"; +import { JavaScriptTestCase } from "../../testcase/JavaScriptTestCase.js"; +import { ActionStatement } from "../../testcase/statements/action/ActionStatement.js"; +import { ConstantObject } from "../../testcase/statements/action/ConstantObject.js"; +import { ConstructorCall } from "../../testcase/statements/action/ConstructorCall.js"; +import { Statement } from "../../testcase/statements/Statement.js"; type SwapStatement = { parent: Statement; diff --git a/libraries/search-javascript/lib/testbuilding/ContextBuilder.ts b/libraries/search-javascript/lib/testbuilding/ContextBuilder.ts index 88652e472..cacd8bb98 100644 --- a/libraries/search-javascript/lib/testbuilding/ContextBuilder.ts +++ b/libraries/search-javascript/lib/testbuilding/ContextBuilder.ts @@ -25,10 +25,10 @@ import { } from "@syntest/ast-visitor-javascript"; import { getLogger, Logger } from "@syntest/logging"; -import { ClassActionStatement } from "../testcase/statements/action/ClassActionStatement"; -import { FunctionCall } from "../testcase/statements/action/FunctionCall"; -import { ObjectFunctionCall } from "../testcase/statements/action/ObjectFunctionCall"; -import { Statement } from "../testcase/statements/Statement"; +import { ClassActionStatement } from "../testcase/statements/action/ClassActionStatement.js"; +import { FunctionCall } from "../testcase/statements/action/FunctionCall.js"; +import { ObjectFunctionCall } from "../testcase/statements/action/ObjectFunctionCall.js"; +import { Statement } from "../testcase/statements/Statement.js"; type Import = RegularImport | RenamedImport; @@ -93,15 +93,9 @@ export class ContextBuilder { let variableName = statement.name; - variableName = - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_".includes( - variableName[0] - ) - ? variableName[0].toLowerCase() + variableName.slice(1) - : (ContextBuilder.LOGGER.warn( - `Found variable name starting with a non-alphabetic character, variable: '${variableName}'` - ), - "var" + variableName); + variableName = variableName.replaceAll(/[^A-Za-z]/g, ""); + + variableName = variableName[0].toLowerCase() + variableName.slice(1); variableName = reservedKeywords.has(variableName) || globalVariables.has(variableName) @@ -219,41 +213,66 @@ export class ContextBuilder { // TODO we could gather all the imports of a certain path together into one import private _getImportString(_path: string, import_: Import): string { + // if (import_.module) { + // throw new Error("Only non module imports can use import statements"); + // } + if (import_.module) { - throw new Error("Only non module imports can use import statements"); + if (!import_.default) { + throw new Error("TODO"); + } + if (import_.renamed) { + return import_.default + ? `import * as ${import_.renamedTo} from "${_path}";` + : `import {${import_.name} as ${import_.renamedTo}} from "${_path}";`; + } else { + return import_.default + ? `import * as ${import_.name} from "${_path}";` + : `import {${import_.name}} from "${_path}";`; + } } if (import_.renamed) { return import_.default - ? `import ${import_.renamedTo} from "${_path}";` - : `import {${import_.name} as ${import_.renamedTo}} from "${_path}";`; + ? `const ${import_.renamedTo} = require("${_path}");` + : `const {${import_.name} as ${import_.renamedTo}} = require("${_path}");`; } else { return import_.default - ? `import ${import_.name} from "${_path}";` - : `import {${import_.name}} from "${_path}";`; + ? `const ${import_.name} = require("${_path}");` + : `const {${import_.name}} = require("${_path}");`; } + + // if (import_.renamed) { + // return import_.default + // ? `import ${import_.renamedTo} from "${_path}";` + // : `import {${import_.name} as ${import_.renamedTo}} from "${_path}";`; + // } else { + // return import_.default + // ? `import ${import_.name} from "${_path}";` + // : `import {${import_.name}} from "${_path}";`; + // } } - private _getRequireString(_path: string, import_: Import): Require { - if (!import_.module) { - throw new Error("Only module imports can use require statements"); - } + // private _getRequireString(_path: string, import_: Import): Require { + // if (!import_.module) { + // throw new Error("Only module imports can use require statements"); + // } - const require: Require = { - left: "", - right: `require("${_path}")`, - }; + // const require: Require = { + // left: "", + // right: `import("${_path}")`, + // }; - if (import_.renamed) { - require.left = import_.default - ? import_.renamedTo - : `{${import_.name}: ${import_.renamedTo}}`; - } else { - require.left = import_.default ? import_.name : `{${import_.name}}`; - } + // if (import_.renamed) { + // require.left = import_.default + // ? import_.renamedTo + // : `{${import_.name}: ${import_.renamedTo}}`; + // } else { + // require.left = import_.default ? import_.name : `{${import_.name}}`; + // } - return require; - } + // return require; + // } getImports(assertionsPresent: boolean) { let requires: Require[] = []; @@ -262,11 +281,15 @@ export class ContextBuilder { for (const [path_, imports_] of this.imports.entries()) { // TODO remove unused imports for (const import_ of imports_) { - if (import_.module) { - requires.push(this._getRequireString(path_, import_)); - } else { - imports.push(this._getImportString(path_, import_)); - } + imports.push(this._getImportString(path_, import_)); + + // if (import_.module) { + // imports.push(this._getImportString(path_, import_)); + + // // requires.push(this._getRequireString(path_, import_)); + // } else { + // imports.push(this._getImportString(path_, import_)); + // } } } diff --git a/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts b/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts index 5760320b9..a0ecb10c1 100644 --- a/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts +++ b/libraries/search-javascript/lib/testbuilding/JavaScriptDecoder.ts @@ -18,15 +18,15 @@ import { Decoder } from "@syntest/search"; -import { JavaScriptTestCase } from "../testcase/JavaScriptTestCase"; -import { ActionStatement } from "../testcase/statements/action/ActionStatement"; -import { ClassActionStatement } from "../testcase/statements/action/ClassActionStatement"; -import { FunctionCall } from "../testcase/statements/action/FunctionCall"; -import { ObjectFunctionCall } from "../testcase/statements/action/ObjectFunctionCall"; -import { Decoding } from "../testcase/statements/Statement"; +import { JavaScriptTestCase } from "../testcase/JavaScriptTestCase.js"; +import { ActionStatement } from "../testcase/statements/action/ActionStatement.js"; +import { ClassActionStatement } from "../testcase/statements/action/ClassActionStatement.js"; +import { FunctionCall } from "../testcase/statements/action/FunctionCall.js"; +import { ObjectFunctionCall } from "../testcase/statements/action/ObjectFunctionCall.js"; +import { Decoding } from "../testcase/statements/Statement.js"; -import { assertionFunction } from "./assertionFunctionTemplate"; -import { ContextBuilder } from "./ContextBuilder"; +import { assertionFunction } from "./assertionFunctionTemplate.js"; +import { ContextBuilder } from "./ContextBuilder.js"; export class JavaScriptDecoder implements Decoder { private targetRootDirectory: string; @@ -110,6 +110,7 @@ export class JavaScriptDecoder implements Decoder { `\tbeforeEach(() => {`, "\t\t// This is a hack to force the require cache to be emptied", "\t\t// Without this we would be using the same required object for each test", + "\t\trequire = require('esm')(module);", ...requires.map( (m) => `\t\tdelete require.cache[${m.right.replace( @@ -125,13 +126,16 @@ export class JavaScriptDecoder implements Decoder { const lines = [ "// Imports", + "require = require('esm')(module);", ...imports, gatherAssertionData ? assertionFunction : "", `describe('SynTest Test Suite', function() {`, ...beforeEachLines, ...tests.flatMap((testLines: string[], index) => [ `\tit("Test ${index + 1}", async () => {`, + "\t\tconsole.log(__setProxy)", ...testLines.map((line) => `\t\t${line}`), + "\t\tconsole.log(global)", index === tests.length - 1 ? "\t})" : "\t})\n", ]), "})", diff --git a/libraries/search-javascript/lib/testbuilding/JavaScriptSuiteBuilder.ts b/libraries/search-javascript/lib/testbuilding/JavaScriptSuiteBuilder.ts index ecc97ffa7..548729028 100644 --- a/libraries/search-javascript/lib/testbuilding/JavaScriptSuiteBuilder.ts +++ b/libraries/search-javascript/lib/testbuilding/JavaScriptSuiteBuilder.ts @@ -18,10 +18,10 @@ import { Target } from "@syntest/analysis"; import { StorageManager } from "@syntest/storage"; -import { JavaScriptRunner } from "../testcase/execution/JavaScriptRunner"; -import { JavaScriptTestCase } from "../testcase/JavaScriptTestCase"; +import { JavaScriptRunner } from "../testcase/execution/JavaScriptRunner.js"; +import { JavaScriptTestCase } from "../testcase/JavaScriptTestCase.js"; -import { JavaScriptDecoder } from "./JavaScriptDecoder"; +import { JavaScriptDecoder } from "./JavaScriptDecoder.js"; export class JavaScriptSuiteBuilder { private storageManager: StorageManager; @@ -48,7 +48,6 @@ export class JavaScriptSuiteBuilder { ) { const paths: string[] = []; - // write the test cases with logs to know what to assert let totalAmount = 0; if (compact) { for (const target of archive.keys()) { diff --git a/libraries/search-javascript/lib/testcase/JavaScriptTestCase.ts b/libraries/search-javascript/lib/testcase/JavaScriptTestCase.ts index f423be009..9df122868 100644 --- a/libraries/search-javascript/lib/testcase/JavaScriptTestCase.ts +++ b/libraries/search-javascript/lib/testcase/JavaScriptTestCase.ts @@ -16,14 +16,14 @@ * limitations under the License. */ +import { AssertionDataTestCase } from "@syntest/instrumentation-javascript"; import { getLogger, Logger } from "@syntest/logging"; import { prng } from "@syntest/prng"; import { Decoder, Encoding } from "@syntest/search"; -import { AssertionDataTestCase } from "./execution/AssertionData"; -import { JavaScriptTestCaseSampler } from "./sampling/JavaScriptTestCaseSampler"; -import { StatementPool } from "./StatementPool"; -import { ActionStatement } from "./statements/action/ActionStatement"; +import { JavaScriptTestCaseSampler } from "./sampling/JavaScriptTestCaseSampler.js"; +import { StatementPool } from "./StatementPool.js"; +import { ActionStatement } from "./statements/action/ActionStatement.js"; /** * JavaScriptTestCase class diff --git a/libraries/search-javascript/lib/testcase/StatementPool.ts b/libraries/search-javascript/lib/testcase/StatementPool.ts index 423bad572..a81732822 100644 --- a/libraries/search-javascript/lib/testcase/StatementPool.ts +++ b/libraries/search-javascript/lib/testcase/StatementPool.ts @@ -17,13 +17,13 @@ */ import { prng } from "@syntest/prng"; -import { ActionStatement } from "./statements/action/ActionStatement"; -import { ClassActionStatement } from "./statements/action/ClassActionStatement"; -import { ConstantObject } from "./statements/action/ConstantObject"; -import { ConstructorCall } from "./statements/action/ConstructorCall"; -import { FunctionCall } from "./statements/action/FunctionCall"; -import { ObjectFunctionCall } from "./statements/action/ObjectFunctionCall"; -import { Statement } from "./statements/Statement"; +import { ActionStatement } from "./statements/action/ActionStatement.js"; +import { ClassActionStatement } from "./statements/action/ClassActionStatement.js"; +import { ConstantObject } from "./statements/action/ConstantObject.js"; +import { ConstructorCall } from "./statements/action/ConstructorCall.js"; +import { FunctionCall } from "./statements/action/FunctionCall.js"; +import { ObjectFunctionCall } from "./statements/action/ObjectFunctionCall.js"; +import { Statement } from "./statements/Statement.js"; export class StatementPool { // type -> statement array diff --git a/libraries/search-javascript/lib/testcase/execution/ExecutionInformationIntegrator.ts b/libraries/search-javascript/lib/testcase/execution/ExecutionInformationIntegrator.ts index 9af9b8bb7..652b6d4da 100644 --- a/libraries/search-javascript/lib/testcase/execution/ExecutionInformationIntegrator.ts +++ b/libraries/search-javascript/lib/testcase/execution/ExecutionInformationIntegrator.ts @@ -17,12 +17,12 @@ */ import { TypeModel } from "@syntest/analysis-javascript"; -import Mocha = require("mocha"); +import * as Mocha from "mocha"; -import { JavaScriptTestCase } from "../JavaScriptTestCase"; -import { Statement } from "../statements/Statement"; +import { JavaScriptTestCase } from "../JavaScriptTestCase.js"; +import { Statement } from "../statements/Statement.js"; -import { Test } from "./TestExecutor"; +import { Test } from "./TestExecutor.js"; export class ExecutionInformationIntegrator { private _typeModel: TypeModel; diff --git a/libraries/search-javascript/lib/testcase/execution/JavaScriptRunner.ts b/libraries/search-javascript/lib/testcase/execution/JavaScriptRunner.ts index ba41d8b10..778a8604c 100644 --- a/libraries/search-javascript/lib/testcase/execution/JavaScriptRunner.ts +++ b/libraries/search-javascript/lib/testcase/execution/JavaScriptRunner.ts @@ -18,6 +18,7 @@ import { ChildProcess, fork } from "node:child_process"; import * as path from "node:path"; +import { fileURLToPath } from "node:url"; import { InstrumentationData, @@ -32,12 +33,12 @@ import { StorageManager } from "@syntest/storage"; import { JavaScriptExecutionResult, JavaScriptExecutionStatus, -} from "../../search/JavaScriptExecutionResult"; -import { JavaScriptDecoder } from "../../testbuilding/JavaScriptDecoder"; -import { JavaScriptTestCase } from "../JavaScriptTestCase"; +} from "../../search/JavaScriptExecutionResult.js"; +import { JavaScriptDecoder } from "../../testbuilding/JavaScriptDecoder.js"; +import { JavaScriptTestCase } from "../JavaScriptTestCase.js"; -import { ExecutionInformationIntegrator } from "./ExecutionInformationIntegrator"; -import { DoneMessage, Message } from "./TestExecutor"; +import { ExecutionInformationIntegrator } from "./ExecutionInformationIntegrator.js"; +import { DoneMessage, Message } from "./TestExecutor.js"; export class JavaScriptRunner implements EncodingRunner { protected static LOGGER: Logger; @@ -73,8 +74,8 @@ export class JavaScriptRunner implements EncodingRunner { this.testTimeout = testTimeout; this.silenceTestOutput = silenceTestOutput; - // eslint-disable-next-line unicorn/prefer-module - this._process = fork(path.join(__dirname, "TestExecutor.js")); + const _dirname = path.dirname(fileURLToPath(import.meta.url)); + this._process = fork(path.join(_dirname, "TestExecutor")); } async run( @@ -87,8 +88,8 @@ export class JavaScriptRunner implements EncodingRunner { paths = paths.map((p) => path.resolve(p)); if (!this._process.connected || this._process.killed) { - // eslint-disable-next-line unicorn/prefer-module - this._process = fork(path.join(__dirname, "TestExecutor.js")); + const _dirname = path.dirname(fileURLToPath(import.meta.url)); + this._process = fork(path.join(_dirname, "TestExecutor")); } const childProcess = this._process; @@ -261,7 +262,7 @@ export class JavaScriptRunner implements EncodingRunner { const traces: Trace[] = []; for (const branchKey of Object.keys(instrumentationData.branchMap)) { const branch = instrumentationData.branchMap[branchKey]; - const hits = instrumentationData.b[branchKey]; + const hits = instrumentationData.b[branchKey]; let meta; if (metaData !== undefined) { diff --git a/libraries/search-javascript/lib/testcase/execution/SilentMochaReporter.ts b/libraries/search-javascript/lib/testcase/execution/SilentMochaReporter.ts index 3d37b3221..501f735d6 100644 --- a/libraries/search-javascript/lib/testcase/execution/SilentMochaReporter.ts +++ b/libraries/search-javascript/lib/testcase/execution/SilentMochaReporter.ts @@ -16,7 +16,7 @@ * limitations under the License. */ -import Mocha = require("mocha"); +import * as Mocha from "mocha"; const { EVENT_RUN_BEGIN, diff --git a/libraries/search-javascript/lib/testcase/execution/TestExecutor.ts b/libraries/search-javascript/lib/testcase/execution/TestExecutor.ts index c5b9eedcb..76277c53c 100644 --- a/libraries/search-javascript/lib/testcase/execution/TestExecutor.ts +++ b/libraries/search-javascript/lib/testcase/execution/TestExecutor.ts @@ -16,18 +16,19 @@ * limitations under the License. */ +import { createRequire } from "node:module"; + import { + AssertionData, InstrumentationDataMap, MetaDataMap, } from "@syntest/instrumentation-javascript"; -import cloneDeep = require("lodash.clonedeep"); -import { Runner } from "mocha"; -import Mocha = require("mocha"); +import cloneDeep from "lodash.clonedeep"; +import Mocha, { Runner } from "mocha"; -import { JavaScriptExecutionStatus } from "../../search/JavaScriptExecutionResult"; +import { JavaScriptExecutionStatus } from "../../search/JavaScriptExecutionResult.js"; -import { AssertionData } from "./AssertionData"; -import { SilentMochaReporter } from "./SilentMochaReporter"; +import { SilentMochaReporter } from "./SilentMochaReporter.js"; export type Message = RunMessage | DoneMessage; @@ -89,26 +90,50 @@ async function runMocha(silent: boolean, paths: string[], timeout: number) { // sort: false, }); - const mocha = new Mocha(argv); // require('ts-node/register') - // eslint-disable-next-line unicorn/prefer-module + const mocha = new Mocha(argv); + + const require = createRequire(import.meta.url); + + // eslint-disable-next-line unicorn/prefer-module, import/extensions require("regenerator-runtime/runtime"); // eslint-disable-next-line unicorn/prefer-module, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-var-requires require("@babel/register")({ // eslint-disable-next-line unicorn/prefer-module - presets: [require.resolve("@babel/preset-env")], + presets: [ + [ + require.resolve("@babel/preset-env"), + { + modules: false, + }, + ], + ], }); + // const babelRegister = await import("@babel/register") + // babelRegister({ + // presets: [ + // new URL("@babel/preset-env", import.meta.url).href; + + // await import.meta.resolve('@babel/preset-env') + // ] + // }) + for (const _path of paths) { // eslint-disable-next-line unicorn/prefer-module - delete require.cache[_path]; + // delete require.cache[_path]; mocha.addFile(_path); } let runner: Runner; // Finally, run mocha. - await new Promise((resolve) => { - runner = mocha.run((failures) => resolve(failures)); + await new Promise((resolve, reject) => { + // runner = mocha.run((failures) => resolve(failures)); + + mocha + .loadFilesAsync() + .then(() => (runner = mocha.run((failures) => resolve(failures)))) + .catch((error) => reject(error)); }); const suites: Suite[] = runner.suite.suites.map((suite) => { @@ -139,6 +164,7 @@ async function runMocha(silent: boolean, paths: string[], timeout: number) { }; }); + console.log(global); // Retrieve execution traces const result: DoneMessage = { message: "done", diff --git a/libraries/search-javascript/lib/testcase/sampling/JavaScriptRandomSampler.ts b/libraries/search-javascript/lib/testcase/sampling/JavaScriptRandomSampler.ts index d0c6f921d..4b8f0258e 100644 --- a/libraries/search-javascript/lib/testcase/sampling/JavaScriptRandomSampler.ts +++ b/libraries/search-javascript/lib/testcase/sampling/JavaScriptRandomSampler.ts @@ -29,29 +29,29 @@ import { } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; -import { JavaScriptSubject } from "../../search/JavaScriptSubject"; -import { JavaScriptTestCase } from "../JavaScriptTestCase"; -import { StatementPool } from "../StatementPool"; -import { ActionStatement } from "../statements/action/ActionStatement"; -import { ConstantObject } from "../statements/action/ConstantObject"; -import { ConstructorCall } from "../statements/action/ConstructorCall"; -import { FunctionCall } from "../statements/action/FunctionCall"; -import { Getter } from "../statements/action/Getter"; -import { MethodCall } from "../statements/action/MethodCall"; -import { ObjectFunctionCall } from "../statements/action/ObjectFunctionCall"; -import { Setter } from "../statements/action/Setter"; -import { ArrayStatement } from "../statements/complex/ArrayStatement"; -import { ArrowFunctionStatement } from "../statements/complex/ArrowFunctionStatement"; -import { ObjectStatement } from "../statements/complex/ObjectStatement"; -import { BoolStatement } from "../statements/primitive/BoolStatement"; -import { IntegerStatement } from "../statements/primitive/IntegerStatement"; -import { NullStatement } from "../statements/primitive/NullStatement"; -import { NumericStatement } from "../statements/primitive/NumericStatement"; -import { StringStatement } from "../statements/primitive/StringStatement"; -import { UndefinedStatement } from "../statements/primitive/UndefinedStatement"; -import { Statement } from "../statements/Statement"; - -import { JavaScriptTestCaseSampler } from "./JavaScriptTestCaseSampler"; +import { JavaScriptSubject } from "../../search/JavaScriptSubject.js"; +import { JavaScriptTestCase } from "../JavaScriptTestCase.js"; +import { StatementPool } from "../StatementPool.js"; +import { ActionStatement } from "../statements/action/ActionStatement.js"; +import { ConstantObject } from "../statements/action/ConstantObject.js"; +import { ConstructorCall } from "../statements/action/ConstructorCall.js"; +import { FunctionCall } from "../statements/action/FunctionCall.js"; +import { Getter } from "../statements/action/Getter.js"; +import { MethodCall } from "../statements/action/MethodCall.js"; +import { ObjectFunctionCall } from "../statements/action/ObjectFunctionCall.js"; +import { Setter } from "../statements/action/Setter.js"; +import { ArrayStatement } from "../statements/complex/ArrayStatement.js"; +import { ArrowFunctionStatement } from "../statements/complex/ArrowFunctionStatement.js"; +import { ObjectStatement } from "../statements/complex/ObjectStatement.js"; +import { BoolStatement } from "../statements/primitive/BoolStatement.js"; +import { IntegerStatement } from "../statements/primitive/IntegerStatement.js"; +import { NullStatement } from "../statements/primitive/NullStatement.js"; +import { NumericStatement } from "../statements/primitive/NumericStatement.js"; +import { StringStatement } from "../statements/primitive/StringStatement.js"; +import { UndefinedStatement } from "../statements/primitive/UndefinedStatement.js"; +import { Statement } from "../statements/Statement.js"; + +import { JavaScriptTestCaseSampler } from "./JavaScriptTestCaseSampler.js"; export class JavaScriptRandomSampler extends JavaScriptTestCaseSampler { constructor( diff --git a/libraries/search-javascript/lib/testcase/sampling/JavaScriptTestCaseSampler.ts b/libraries/search-javascript/lib/testcase/sampling/JavaScriptTestCaseSampler.ts index 3082386ee..54d0b3867 100644 --- a/libraries/search-javascript/lib/testcase/sampling/JavaScriptTestCaseSampler.ts +++ b/libraries/search-javascript/lib/testcase/sampling/JavaScriptTestCaseSampler.ts @@ -19,35 +19,35 @@ import { ConstantPoolManager, RootContext } from "@syntest/analysis-javascript"; import { EncodingSampler } from "@syntest/search"; -import { JavaScriptSubject } from "../../search/JavaScriptSubject"; -import { JavaScriptTestCase } from "../JavaScriptTestCase"; -import { StatementPool } from "../StatementPool"; -import { ActionStatement } from "../statements/action/ActionStatement"; -import { ConstantObject } from "../statements/action/ConstantObject"; -import { ConstructorCall } from "../statements/action/ConstructorCall"; -import { FunctionCall } from "../statements/action/FunctionCall"; -import { Getter } from "../statements/action/Getter"; -import { MethodCall } from "../statements/action/MethodCall"; -import { ObjectFunctionCall } from "../statements/action/ObjectFunctionCall"; -import { Setter } from "../statements/action/Setter"; -import { ArrayStatement } from "../statements/complex/ArrayStatement"; -import { ArrowFunctionStatement } from "../statements/complex/ArrowFunctionStatement"; -import { ObjectStatement } from "../statements/complex/ObjectStatement"; -import { BoolStatement } from "../statements/primitive/BoolStatement"; -import { IntegerStatement } from "../statements/primitive/IntegerStatement"; -import { NullStatement } from "../statements/primitive/NullStatement"; -import { NumericStatement } from "../statements/primitive/NumericStatement"; -import { StringStatement } from "../statements/primitive/StringStatement"; -import { UndefinedStatement } from "../statements/primitive/UndefinedStatement"; -import { Statement } from "../statements/Statement"; - -import { ConstantObjectGenerator } from "./generators/action/ConstantObjectGenerator"; -import { ConstructorCallGenerator } from "./generators/action/ConstructorCallGenerator"; -import { FunctionCallGenerator } from "./generators/action/FunctionCallGenerator"; -import { GetterGenerator } from "./generators/action/GetterGenerator"; -import { MethodCallGenerator } from "./generators/action/MethodCallGenerator"; -import { ObjectFunctionCallGenerator } from "./generators/action/ObjectFunctionCallGenerator"; -import { SetterGenerator } from "./generators/action/SetterGenerator"; +import { JavaScriptSubject } from "../../search/JavaScriptSubject.js"; +import { JavaScriptTestCase } from "../JavaScriptTestCase.js"; +import { StatementPool } from "../StatementPool.js"; +import { ActionStatement } from "../statements/action/ActionStatement.js"; +import { ConstantObject } from "../statements/action/ConstantObject.js"; +import { ConstructorCall } from "../statements/action/ConstructorCall.js"; +import { FunctionCall } from "../statements/action/FunctionCall.js"; +import { Getter } from "../statements/action/Getter.js"; +import { MethodCall } from "../statements/action/MethodCall.js"; +import { ObjectFunctionCall } from "../statements/action/ObjectFunctionCall.js"; +import { Setter } from "../statements/action/Setter.js"; +import { ArrayStatement } from "../statements/complex/ArrayStatement.js"; +import { ArrowFunctionStatement } from "../statements/complex/ArrowFunctionStatement.js"; +import { ObjectStatement } from "../statements/complex/ObjectStatement.js"; +import { BoolStatement } from "../statements/primitive/BoolStatement.js"; +import { IntegerStatement } from "../statements/primitive/IntegerStatement.js"; +import { NullStatement } from "../statements/primitive/NullStatement.js"; +import { NumericStatement } from "../statements/primitive/NumericStatement.js"; +import { StringStatement } from "../statements/primitive/StringStatement.js"; +import { UndefinedStatement } from "../statements/primitive/UndefinedStatement.js"; +import { Statement } from "../statements/Statement.js"; + +import { ConstantObjectGenerator } from "./generators/action/ConstantObjectGenerator.js"; +import { ConstructorCallGenerator } from "./generators/action/ConstructorCallGenerator.js"; +import { FunctionCallGenerator } from "./generators/action/FunctionCallGenerator.js"; +import { GetterGenerator } from "./generators/action/GetterGenerator.js"; +import { MethodCallGenerator } from "./generators/action/MethodCallGenerator.js"; +import { ObjectFunctionCallGenerator } from "./generators/action/ObjectFunctionCallGenerator.js"; +import { SetterGenerator } from "./generators/action/SetterGenerator.js"; /** * JavaScriptRandomSampler class diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/Generator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/Generator.ts index 6b97c629e..e9724248b 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/Generator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/Generator.ts @@ -17,9 +17,9 @@ */ import { RootContext } from "@syntest/analysis-javascript"; -import { StatementPool } from "../../StatementPool"; -import { Statement } from "../../statements/Statement"; -import { JavaScriptTestCaseSampler } from "../JavaScriptTestCaseSampler"; +import { StatementPool } from "../../StatementPool.js"; +import { Statement } from "../../statements/Statement.js"; +import { JavaScriptTestCaseSampler } from "../JavaScriptTestCaseSampler.js"; export abstract class Generator { protected _sampler: JavaScriptTestCaseSampler; diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/action/CallGenerator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/action/CallGenerator.ts index cd0bc8235..f8c0ee3da 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/action/CallGenerator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/action/CallGenerator.ts @@ -18,8 +18,8 @@ import { ObjectType } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; -import { Statement } from "../../../statements/Statement"; -import { Generator } from "../Generator"; +import { Statement } from "../../../statements/Statement.js"; +import { Generator } from "../Generator.js"; export abstract class CallGenerator extends Generator { sampleArguments(depth: number, type_: ObjectType): Statement[] { diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/action/ConstantObjectGenerator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/action/ConstantObjectGenerator.ts index 0d0a7d691..d1dee2397 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/action/ConstantObjectGenerator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/action/ConstantObjectGenerator.ts @@ -17,10 +17,10 @@ */ import { prng } from "@syntest/prng"; -import { StatementPool } from "../../../StatementPool"; -import { ConstantObject } from "../../../statements/action/ConstantObject"; +import { StatementPool } from "../../../StatementPool.js"; +import { ConstantObject } from "../../../statements/action/ConstantObject.js"; -import { CallGenerator } from "./CallGenerator"; +import { CallGenerator } from "./CallGenerator.js"; export class ConstantObjectGenerator extends CallGenerator { override generate( diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/action/ConstructorCallGenerator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/action/ConstructorCallGenerator.ts index d8174f7f2..8a1db4429 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/action/ConstructorCallGenerator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/action/ConstructorCallGenerator.ts @@ -17,11 +17,11 @@ */ import { prng } from "@syntest/prng"; -import { StatementPool } from "../../../StatementPool"; -import { ConstructorCall } from "../../../statements/action/ConstructorCall"; -import { Statement } from "../../../statements/Statement"; +import { StatementPool } from "../../../StatementPool.js"; +import { ConstructorCall } from "../../../statements/action/ConstructorCall.js"; +import { Statement } from "../../../statements/Statement.js"; -import { CallGenerator } from "./CallGenerator"; +import { CallGenerator } from "./CallGenerator.js"; export class ConstructorCallGenerator extends CallGenerator { override generate( diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/action/FunctionCallGenerator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/action/FunctionCallGenerator.ts index 405a94913..b367e3da4 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/action/FunctionCallGenerator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/action/FunctionCallGenerator.ts @@ -17,11 +17,11 @@ */ import { prng } from "@syntest/prng"; -import { StatementPool } from "../../../StatementPool"; -import { FunctionCall } from "../../../statements/action/FunctionCall"; -import { Statement } from "../../../statements/Statement"; +import { StatementPool } from "../../../StatementPool.js"; +import { FunctionCall } from "../../../statements/action/FunctionCall.js"; +import { Statement } from "../../../statements/Statement.js"; -import { CallGenerator } from "./CallGenerator"; +import { CallGenerator } from "./CallGenerator.js"; export class FunctionCallGenerator extends CallGenerator { override generate( diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/action/GetterGenerator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/action/GetterGenerator.ts index b86c529c7..ccb141a08 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/action/GetterGenerator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/action/GetterGenerator.ts @@ -17,10 +17,10 @@ */ import { prng } from "@syntest/prng"; -import { StatementPool } from "../../../StatementPool"; -import { Getter } from "../../../statements/action/Getter"; +import { StatementPool } from "../../../StatementPool.js"; +import { Getter } from "../../../statements/action/Getter.js"; -import { CallGenerator } from "./CallGenerator"; +import { CallGenerator } from "./CallGenerator.js"; export class GetterGenerator extends CallGenerator { override generate( diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/action/MethodCallGenerator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/action/MethodCallGenerator.ts index 15403e612..4d251256d 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/action/MethodCallGenerator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/action/MethodCallGenerator.ts @@ -17,11 +17,11 @@ */ import { prng } from "@syntest/prng"; -import { StatementPool } from "../../../StatementPool"; -import { MethodCall } from "../../../statements/action/MethodCall"; -import { Statement } from "../../../statements/Statement"; +import { StatementPool } from "../../../StatementPool.js"; +import { MethodCall } from "../../../statements/action/MethodCall.js"; +import { Statement } from "../../../statements/Statement.js"; -import { CallGenerator } from "./CallGenerator"; +import { CallGenerator } from "./CallGenerator.js"; export class MethodCallGenerator extends CallGenerator { override generate( diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/action/ObjectFunctionCallGenerator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/action/ObjectFunctionCallGenerator.ts index d92680ab4..6577899f5 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/action/ObjectFunctionCallGenerator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/action/ObjectFunctionCallGenerator.ts @@ -17,11 +17,11 @@ */ import { prng } from "@syntest/prng"; -import { StatementPool } from "../../../StatementPool"; -import { ObjectFunctionCall } from "../../../statements/action/ObjectFunctionCall"; -import { Statement } from "../../../statements/Statement"; +import { StatementPool } from "../../../StatementPool.js"; +import { ObjectFunctionCall } from "../../../statements/action/ObjectFunctionCall.js"; +import { Statement } from "../../../statements/Statement.js"; -import { CallGenerator } from "./CallGenerator"; +import { CallGenerator } from "./CallGenerator.js"; export class ObjectFunctionCallGenerator extends CallGenerator { override generate( diff --git a/libraries/search-javascript/lib/testcase/sampling/generators/action/SetterGenerator.ts b/libraries/search-javascript/lib/testcase/sampling/generators/action/SetterGenerator.ts index 009ce27e5..348075759 100644 --- a/libraries/search-javascript/lib/testcase/sampling/generators/action/SetterGenerator.ts +++ b/libraries/search-javascript/lib/testcase/sampling/generators/action/SetterGenerator.ts @@ -17,11 +17,11 @@ */ import { prng } from "@syntest/prng"; -import { StatementPool } from "../../../StatementPool"; -import { Setter } from "../../../statements/action/Setter"; -import { Statement } from "../../../statements/Statement"; +import { StatementPool } from "../../../StatementPool.js"; +import { Setter } from "../../../statements/action/Setter.js"; +import { Statement } from "../../../statements/Statement.js"; -import { CallGenerator } from "./CallGenerator"; +import { CallGenerator } from "./CallGenerator.js"; export class SetterGenerator extends CallGenerator { override generate( diff --git a/libraries/search-javascript/lib/testcase/statements/Statement.ts b/libraries/search-javascript/lib/testcase/statements/Statement.ts index f01740c10..069a2c220 100644 --- a/libraries/search-javascript/lib/testcase/statements/Statement.ts +++ b/libraries/search-javascript/lib/testcase/statements/Statement.ts @@ -19,7 +19,7 @@ import { TypeEnum } from "@syntest/analysis-javascript"; import { Encoding, EncodingSampler } from "@syntest/search"; -import { ContextBuilder } from "../../testbuilding/ContextBuilder"; +import { ContextBuilder } from "../../testbuilding/ContextBuilder.js"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/action/ActionStatement.ts b/libraries/search-javascript/lib/testcase/statements/action/ActionStatement.ts index 8656acf13..12c8377a7 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/ActionStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/ActionStatement.ts @@ -19,7 +19,7 @@ import { Export, TypeEnum } from "@syntest/analysis-javascript"; import { Encoding, EncodingSampler, shouldNeverHappen } from "@syntest/search"; -import { Statement } from "../Statement"; +import { Statement } from "../Statement.js"; /** * ActionStatement diff --git a/libraries/search-javascript/lib/testcase/statements/action/ClassActionStatement.ts b/libraries/search-javascript/lib/testcase/statements/action/ClassActionStatement.ts index aa6f9e791..b846d3d24 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/ClassActionStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/ClassActionStatement.ts @@ -18,10 +18,10 @@ import { TypeEnum } from "@syntest/analysis-javascript"; import { shouldNeverHappen } from "@syntest/search"; -import { Statement } from "../Statement"; +import { Statement } from "../Statement.js"; -import { ActionStatement } from "./ActionStatement"; -import { ConstructorCall } from "./ConstructorCall"; +import { ActionStatement } from "./ActionStatement.js"; +import { ConstructorCall } from "./ConstructorCall.js"; export abstract class ClassActionStatement extends ActionStatement { private _constructor: ConstructorCall; diff --git a/libraries/search-javascript/lib/testcase/statements/action/ConstantObject.ts b/libraries/search-javascript/lib/testcase/statements/action/ConstantObject.ts index 5106b19da..2761d6f10 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/ConstantObject.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/ConstantObject.ts @@ -19,11 +19,11 @@ import { Export, TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; -import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { Decoding } from "../Statement"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder.js"; +import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler.js"; +import { Decoding } from "../Statement.js"; -import { ActionStatement } from "./ActionStatement"; +import { ActionStatement } from "./ActionStatement.js"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/action/ConstructorCall.ts b/libraries/search-javascript/lib/testcase/statements/action/ConstructorCall.ts index f4e8db67b..5a93a6976 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/ConstructorCall.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/ConstructorCall.ts @@ -19,11 +19,11 @@ import { Export, TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; -import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { Decoding, Statement } from "../Statement"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder.js"; +import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler.js"; +import { Decoding, Statement } from "../Statement.js"; -import { ActionStatement } from "./ActionStatement"; +import { ActionStatement } from "./ActionStatement.js"; /** * ConstructorCall diff --git a/libraries/search-javascript/lib/testcase/statements/action/FunctionCall.ts b/libraries/search-javascript/lib/testcase/statements/action/FunctionCall.ts index 0907d551f..eec8b6897 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/FunctionCall.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/FunctionCall.ts @@ -19,11 +19,11 @@ import { Export, TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; -import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { Decoding, Statement } from "../Statement"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder.js"; +import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler.js"; +import { Decoding, Statement } from "../Statement.js"; -import { ActionStatement } from "./ActionStatement"; +import { ActionStatement } from "./ActionStatement.js"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/action/Getter.ts b/libraries/search-javascript/lib/testcase/statements/action/Getter.ts index f49387978..c9c29d41b 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/Getter.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/Getter.ts @@ -19,12 +19,12 @@ import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; -import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { Decoding } from "../Statement"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder.js"; +import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler.js"; +import { Decoding } from "../Statement.js"; -import { ClassActionStatement } from "./ClassActionStatement"; -import { ConstructorCall } from "./ConstructorCall"; +import { ClassActionStatement } from "./ClassActionStatement.js"; +import { ConstructorCall } from "./ConstructorCall.js"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/action/MethodCall.ts b/libraries/search-javascript/lib/testcase/statements/action/MethodCall.ts index 90d0904a6..8d348012f 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/MethodCall.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/MethodCall.ts @@ -19,12 +19,12 @@ import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; -import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { Decoding, Statement } from "../Statement"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder.js"; +import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler.js"; +import { Decoding, Statement } from "../Statement.js"; -import { ClassActionStatement } from "./ClassActionStatement"; -import { ConstructorCall } from "./ConstructorCall"; +import { ClassActionStatement } from "./ClassActionStatement.js"; +import { ConstructorCall } from "./ConstructorCall.js"; /** * MethodCall diff --git a/libraries/search-javascript/lib/testcase/statements/action/ObjectFunctionCall.ts b/libraries/search-javascript/lib/testcase/statements/action/ObjectFunctionCall.ts index c356b9d2e..596a062ab 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/ObjectFunctionCall.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/ObjectFunctionCall.ts @@ -20,12 +20,12 @@ import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; import { shouldNeverHappen } from "@syntest/search"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; -import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { Decoding, Statement } from "../Statement"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder.js"; +import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler.js"; +import { Decoding, Statement } from "../Statement.js"; -import { ActionStatement } from "./ActionStatement"; -import { ConstantObject } from "./ConstantObject"; +import { ActionStatement } from "./ActionStatement.js"; +import { ConstantObject } from "./ConstantObject.js"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/action/Setter.ts b/libraries/search-javascript/lib/testcase/statements/action/Setter.ts index 60e44ee65..16b17cf02 100644 --- a/libraries/search-javascript/lib/testcase/statements/action/Setter.ts +++ b/libraries/search-javascript/lib/testcase/statements/action/Setter.ts @@ -19,14 +19,14 @@ import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; -import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { Decoding, Statement } from "../Statement"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder.js"; +import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler.js"; +import { Decoding, Statement } from "../Statement.js"; -import { ClassActionStatement } from "./ClassActionStatement"; -import { ConstructorCall } from "./ConstructorCall"; -import { Getter } from "./Getter"; -import { MethodCall } from "./MethodCall"; +import { ClassActionStatement } from "./ClassActionStatement.js"; +import { ConstructorCall } from "./ConstructorCall.js"; +import { Getter } from "./Getter.js"; +import { MethodCall } from "./MethodCall.js"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/complex/ArrayStatement.ts b/libraries/search-javascript/lib/testcase/statements/complex/ArrayStatement.ts index ddc216554..7732ab104 100644 --- a/libraries/search-javascript/lib/testcase/statements/complex/ArrayStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/complex/ArrayStatement.ts @@ -20,9 +20,9 @@ import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; import { shouldNeverHappen } from "@syntest/search"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; -import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { Decoding, Statement } from "../Statement"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder.js"; +import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler.js"; +import { Decoding, Statement } from "../Statement.js"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/complex/ArrowFunctionStatement.ts b/libraries/search-javascript/lib/testcase/statements/complex/ArrowFunctionStatement.ts index 84a1d3717..a337b77f7 100644 --- a/libraries/search-javascript/lib/testcase/statements/complex/ArrowFunctionStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/complex/ArrowFunctionStatement.ts @@ -20,9 +20,9 @@ import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; import { shouldNeverHappen } from "@syntest/search"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; -import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { Decoding, Statement } from "../Statement"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder.js"; +import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler.js"; +import { Decoding, Statement } from "../Statement.js"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/complex/ObjectStatement.ts b/libraries/search-javascript/lib/testcase/statements/complex/ObjectStatement.ts index fafdb6733..44bf7ed51 100644 --- a/libraries/search-javascript/lib/testcase/statements/complex/ObjectStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/complex/ObjectStatement.ts @@ -20,9 +20,9 @@ import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; import { shouldNeverHappen } from "@syntest/search"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; -import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { Decoding, Statement } from "../Statement"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder.js"; +import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler.js"; +import { Decoding, Statement } from "../Statement.js"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/primitive/BoolStatement.ts b/libraries/search-javascript/lib/testcase/statements/primitive/BoolStatement.ts index 1208b81fd..cff926647 100644 --- a/libraries/search-javascript/lib/testcase/statements/primitive/BoolStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/primitive/BoolStatement.ts @@ -19,10 +19,10 @@ import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; -import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { Statement } from "../Statement"; +import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler.js"; +import { Statement } from "../Statement.js"; -import { PrimitiveStatement } from "./PrimitiveStatement"; +import { PrimitiveStatement } from "./PrimitiveStatement.js"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/primitive/IntegerStatement.ts b/libraries/search-javascript/lib/testcase/statements/primitive/IntegerStatement.ts index da6047b2e..a5aeafca7 100644 --- a/libraries/search-javascript/lib/testcase/statements/primitive/IntegerStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/primitive/IntegerStatement.ts @@ -19,11 +19,11 @@ import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; -import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { Statement } from "../Statement"; +import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler.js"; +import { Statement } from "../Statement.js"; -import { NumericStatement } from "./NumericStatement"; -import { PrimitiveStatement } from "./PrimitiveStatement"; +import { NumericStatement } from "./NumericStatement.js"; +import { PrimitiveStatement } from "./PrimitiveStatement.js"; /** * Generic number class diff --git a/libraries/search-javascript/lib/testcase/statements/primitive/NullStatement.ts b/libraries/search-javascript/lib/testcase/statements/primitive/NullStatement.ts index bb3937b4d..37f0021f7 100644 --- a/libraries/search-javascript/lib/testcase/statements/primitive/NullStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/primitive/NullStatement.ts @@ -19,10 +19,10 @@ import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; -import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { Statement } from "../Statement"; +import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler.js"; +import { Statement } from "../Statement.js"; -import { PrimitiveStatement } from "./PrimitiveStatement"; +import { PrimitiveStatement } from "./PrimitiveStatement.js"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/primitive/NumericStatement.ts b/libraries/search-javascript/lib/testcase/statements/primitive/NumericStatement.ts index fcbaf00f0..07a9be3d2 100644 --- a/libraries/search-javascript/lib/testcase/statements/primitive/NumericStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/primitive/NumericStatement.ts @@ -19,11 +19,11 @@ import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; -import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { Statement } from "../Statement"; +import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler.js"; +import { Statement } from "../Statement.js"; -import { IntegerStatement } from "./IntegerStatement"; -import { PrimitiveStatement } from "./PrimitiveStatement"; +import { IntegerStatement } from "./IntegerStatement.js"; +import { PrimitiveStatement } from "./PrimitiveStatement.js"; /** * Generic number class diff --git a/libraries/search-javascript/lib/testcase/statements/primitive/PrimitiveStatement.ts b/libraries/search-javascript/lib/testcase/statements/primitive/PrimitiveStatement.ts index 5e996ffbb..28db7c2c3 100644 --- a/libraries/search-javascript/lib/testcase/statements/primitive/PrimitiveStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/primitive/PrimitiveStatement.ts @@ -18,9 +18,9 @@ import { TypeEnum } from "@syntest/analysis-javascript"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; -import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { Decoding, Statement } from "../Statement"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder.js"; +import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler.js"; +import { Decoding, Statement } from "../Statement.js"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/primitive/StringStatement.ts b/libraries/search-javascript/lib/testcase/statements/primitive/StringStatement.ts index 19d301225..6a3736056 100644 --- a/libraries/search-javascript/lib/testcase/statements/primitive/StringStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/primitive/StringStatement.ts @@ -19,11 +19,11 @@ import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; -import { ContextBuilder } from "../../../testbuilding/ContextBuilder"; -import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { Decoding, Statement } from "../Statement"; +import { ContextBuilder } from "../../../testbuilding/ContextBuilder.js"; +import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler.js"; +import { Decoding, Statement } from "../Statement.js"; -import { PrimitiveStatement } from "./PrimitiveStatement"; +import { PrimitiveStatement } from "./PrimitiveStatement.js"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/lib/testcase/statements/primitive/UndefinedStatement.ts b/libraries/search-javascript/lib/testcase/statements/primitive/UndefinedStatement.ts index 6b59d139f..8df9224a9 100644 --- a/libraries/search-javascript/lib/testcase/statements/primitive/UndefinedStatement.ts +++ b/libraries/search-javascript/lib/testcase/statements/primitive/UndefinedStatement.ts @@ -19,10 +19,10 @@ import { TypeEnum } from "@syntest/analysis-javascript"; import { prng } from "@syntest/prng"; -import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler"; -import { Statement } from "../Statement"; +import { JavaScriptTestCaseSampler } from "../../sampling/JavaScriptTestCaseSampler.js"; +import { Statement } from "../Statement.js"; -import { PrimitiveStatement } from "./PrimitiveStatement"; +import { PrimitiveStatement } from "./PrimitiveStatement.js"; /** * @author Dimitri Stallenberg diff --git a/libraries/search-javascript/package.json b/libraries/search-javascript/package.json index 8e5e1a00c..e050450c2 100644 --- a/libraries/search-javascript/package.json +++ b/libraries/search-javascript/package.json @@ -6,6 +6,7 @@ "syntest", "automatic-test-generation" ], + "type": "module", "homepage": "https://www.syntest.org", "bugs": { "url": "https://github.com/syntest-framework/syntest-javascript/issues" @@ -61,6 +62,7 @@ "@syntest/storage": "^0.2.0", "chai": "4.3.7", "chai-as-promised": "7.1.1", + "esm": "^3.2.25", "lodash.clonedeep": "4.5.0", "mocha": "10.2.0", "regenerator-runtime": "0.13.9" diff --git a/libraries/search-javascript/test/criterion/BranchDistanceBinaryDoubleEqual.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceBinaryDoubleEqual.test.ts index d9450a65a..0c100dae2 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceBinaryDoubleEqual.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceBinaryDoubleEqual.test.ts @@ -17,7 +17,7 @@ */ import { expect } from "chai"; -import { BranchDistance } from "../../lib/criterion/BranchDistance"; +import { BranchDistance } from "../../lib/criterion/BranchDistance.js"; describe("BranchDistance a == b test", () => { // number diff --git a/libraries/search-javascript/test/criterion/BranchDistanceBinaryDoubleNotEqual.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceBinaryDoubleNotEqual.test.ts index af962097e..fa306cc6e 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceBinaryDoubleNotEqual.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceBinaryDoubleNotEqual.test.ts @@ -17,7 +17,7 @@ */ import { expect } from "chai"; -import { BranchDistance } from "../../lib/criterion/BranchDistance"; +import { BranchDistance } from "../../lib/criterion/BranchDistance.js"; describe("BranchDistance a != b test", () => { // number diff --git a/libraries/search-javascript/test/criterion/BranchDistanceBinaryGreater.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceBinaryGreater.test.ts index f8adc6a2d..5b91a427a 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceBinaryGreater.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceBinaryGreater.test.ts @@ -17,7 +17,7 @@ */ import { expect } from "chai"; -import { BranchDistance } from "../../lib/criterion/BranchDistance"; +import { BranchDistance } from "../../lib/criterion/BranchDistance.js"; describe("BranchDistance a > b test", () => { // number diff --git a/libraries/search-javascript/test/criterion/BranchDistanceBinaryGreaterOrEqual.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceBinaryGreaterOrEqual.test.ts index 8690ac939..aeefb0edb 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceBinaryGreaterOrEqual.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceBinaryGreaterOrEqual.test.ts @@ -17,7 +17,7 @@ */ import { expect } from "chai"; -import { BranchDistance } from "../../lib/criterion/BranchDistance"; +import { BranchDistance } from "../../lib/criterion/BranchDistance.js"; describe("BranchDistance a >= b test", () => { // number diff --git a/libraries/search-javascript/test/criterion/BranchDistanceBinarySmaller.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceBinarySmaller.test.ts index 82b030529..d4ea12166 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceBinarySmaller.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceBinarySmaller.test.ts @@ -17,7 +17,7 @@ */ import { expect } from "chai"; -import { BranchDistance } from "../../lib/criterion/BranchDistance"; +import { BranchDistance } from "../../lib/criterion/BranchDistance.js"; describe("BranchDistance a < b test", () => { // number diff --git a/libraries/search-javascript/test/criterion/BranchDistanceBinarySmallerOrEqual.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceBinarySmallerOrEqual.test.ts index f36bf4603..a6d6522c2 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceBinarySmallerOrEqual.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceBinarySmallerOrEqual.test.ts @@ -17,7 +17,7 @@ */ import { expect } from "chai"; -import { BranchDistance } from "../../lib/criterion/BranchDistance"; +import { BranchDistance } from "../../lib/criterion/BranchDistance.js"; describe("BranchDistance a <= b test", () => { // number diff --git a/libraries/search-javascript/test/criterion/BranchDistanceBinaryTrippleEqual.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceBinaryTrippleEqual.test.ts index 3f2353e80..3e8c52325 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceBinaryTrippleEqual.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceBinaryTrippleEqual.test.ts @@ -17,7 +17,7 @@ */ import { expect } from "chai"; -import { BranchDistance } from "../../lib/criterion/BranchDistance"; +import { BranchDistance } from "../../lib/criterion/BranchDistance.js"; describe("BranchDistance a === b test", () => { // number diff --git a/libraries/search-javascript/test/criterion/BranchDistanceBinaryTrippleNotEqual.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceBinaryTrippleNotEqual.test.ts index f57b42c14..0e5229cb6 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceBinaryTrippleNotEqual.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceBinaryTrippleNotEqual.test.ts @@ -17,7 +17,7 @@ */ import { expect } from "chai"; -import { BranchDistance } from "../../lib/criterion/BranchDistance"; +import { BranchDistance } from "../../lib/criterion/BranchDistance.js"; describe("BranchDistance a !== b test", () => { // number diff --git a/libraries/search-javascript/test/criterion/BranchDistanceLogicalOr.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceLogicalOr.test.ts index f6fe6245c..474cadff8 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceLogicalOr.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceLogicalOr.test.ts @@ -17,7 +17,7 @@ */ import { expect } from "chai"; -import { BranchDistance } from "../../lib/criterion/BranchDistance"; +import { BranchDistance } from "../../lib/criterion/BranchDistance.js"; describe("BranchDistance a || b test", () => { // number diff --git a/libraries/search-javascript/test/criterion/BranchDistanceStringFunctions.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceStringFunctions.test.ts index 28e45a70a..d22e23a57 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceStringFunctions.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceStringFunctions.test.ts @@ -17,7 +17,7 @@ */ import { expect } from "chai"; -import { BranchDistance } from "../../lib/criterion/BranchDistance"; +import { BranchDistance } from "../../lib/criterion/BranchDistance.js"; describe("BranchDistance string functions", () => { // endsWith diff --git a/libraries/search-javascript/test/criterion/BranchDistanceUnaryNot.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceUnaryNot.test.ts index 01c0dd875..f652af551 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceUnaryNot.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceUnaryNot.test.ts @@ -17,7 +17,7 @@ */ import { expect } from "chai"; -import { BranchDistance } from "../../lib/criterion/BranchDistance"; +import { BranchDistance } from "../../lib/criterion/BranchDistance.js"; describe("BranchDistance !a test", () => { // number diff --git a/libraries/search-javascript/test/criterion/BranchDistanceVisitor.test.ts b/libraries/search-javascript/test/criterion/BranchDistanceVisitor.test.ts index 924c27060..74dd7a49a 100644 --- a/libraries/search-javascript/test/criterion/BranchDistanceVisitor.test.ts +++ b/libraries/search-javascript/test/criterion/BranchDistanceVisitor.test.ts @@ -17,7 +17,7 @@ */ import { expect } from "chai"; -import { BranchDistanceVisitor } from "../../lib/criterion/BranchDistanceVisitor"; +import { BranchDistanceVisitor } from "../../lib/criterion/BranchDistanceVisitor.js"; describe("BranchDistance string functions", () => { it("'abc'.endsWith('bc') true", () => { diff --git a/libraries/search-javascript/test/criterion/RandomBranchDistanceTests.test.ts b/libraries/search-javascript/test/criterion/RandomBranchDistanceTests.test.ts index f919cef05..deec44668 100644 --- a/libraries/search-javascript/test/criterion/RandomBranchDistanceTests.test.ts +++ b/libraries/search-javascript/test/criterion/RandomBranchDistanceTests.test.ts @@ -17,7 +17,7 @@ */ import { expect } from "chai"; -import { BranchDistance } from "../../lib/criterion/BranchDistance"; +import { BranchDistance } from "../../lib/criterion/BranchDistance.js"; describe("Random Tests", () => { it("a !== undefined && !b true", () => { diff --git a/package-lock.json b/package-lock.json index 6b76cea8d..719c7cdf3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,8 +18,10 @@ "@commitlint/cli": "17.4.2", "@commitlint/config-conventional": "17.4.2", "@types/babel__core": "7.20.0", - "@types/babel__traverse": "7.18.5", + "@types/babel__register": "^7.17.1", + "@types/babel__traverse": "7.20.2", "@types/chai": "4.3.4", + "@types/esm": "^3.2.0", "@types/figlet": "1.5.4", "@types/lodash.clonedeep": "^4.5.7", "@types/mocha": "10.0.1", @@ -35,6 +37,7 @@ "eslint-plugin-import": "^2.27.5", "eslint-plugin-notice": "^0.9.10", "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-require-extensions": "^0.1.3", "eslint-plugin-sonarjs": "^0.19.0", "eslint-plugin-unicorn": "^45.0.2", "eslint-plugin-unused-imports": "^2.0.0", @@ -46,7 +49,6 @@ "nyc": "15.1.0", "prettier": "2.8.1", "sinon": "15.0.1", - "ts-node": "10.9.1", "typed-emitter": "^2.1.0", "typescript": "4.9.4", "winston": "3.8.2" @@ -182,7 +184,8 @@ }, "devDependencies": { "@babel/types": "^7.21.5", - "@types/babel__core": "7.20.0" + "@types/babel__core": "7.20.0", + "@types/istanbul-lib-coverage": "^2.0.4" }, "engines": { "node": ">=10.24.0" @@ -245,6 +248,7 @@ "@syntest/storage": "^0.2.0", "chai": "4.3.7", "chai-as-promised": "7.1.1", + "esm": "^3.2.25", "lodash.clonedeep": "4.5.0", "mocha": "10.2.0", "regenerator-runtime": "0.13.9" @@ -5125,6 +5129,15 @@ "@babel/types": "^7.0.0" } }, + "node_modules/@types/babel__register": { + "version": "7.17.1", + "resolved": "https://registry.npmjs.org/@types/babel__register/-/babel__register-7.17.1.tgz", + "integrity": "sha512-BhoiDd6xMy8nbTCpObR5QEqQnyKNjTzlgk/HF5bK2zXbTX7uZq126DufGMVHBaoFvDfpQb3SWTvO7uIC97WK5w==", + "dev": true, + "dependencies": { + "@types/babel__core": "*" + } + }, "node_modules/@types/babel__template": { "version": "7.4.2", "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.2.tgz", @@ -5136,12 +5149,12 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.18.5", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.5.tgz", - "integrity": "sha512-enCvTL8m/EHS/zIvJno9nE+ndYPh1/oNFzRYRmtUqJICG2VnCSBzMLW5VN2KCQU91f23tsNKR8v7VJJQMatl7Q==", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.2.tgz", + "integrity": "sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==", "dev": true, "dependencies": { - "@babel/types": "^7.3.0" + "@babel/types": "^7.20.7" } }, "node_modules/@types/chai": { @@ -5150,12 +5163,27 @@ "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", "dev": true }, + "node_modules/@types/esm": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@types/esm/-/esm-3.2.0.tgz", + "integrity": "sha512-aXemgVPnF1s0PQin04Ei8zTWaNwUdc4pmhZDg8LBW6QEl9kBWVItAUOLGUY5H5xduAmbL1pLGH1X/PN0+4R9tg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/figlet": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/@types/figlet/-/figlet-1.5.4.tgz", "integrity": "sha512-cskPTju7glYgzvkJy/hftqw7Fen3fsd0yrPOqcbBLJu+YdDQuA438akS1g+2XVKGzsQOnXGV2I9ePv6xUBnKMQ==", "dev": true }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, "node_modules/@types/json-schema": { "version": "7.0.13", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", @@ -7843,6 +7871,18 @@ "eslint": "^7.0.0 || ^8.0.0" } }, + "node_modules/eslint-plugin-require-extensions": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-require-extensions/-/eslint-plugin-require-extensions-0.1.3.tgz", + "integrity": "sha512-T3c1PZ9PIdI3hjV8LdunfYI8gj017UQjzAnCrxuo3wAjneDbTPHdE3oNWInOjMA+z/aBkUtlW5vC0YepYMZIug==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "eslint": "*" + } + }, "node_modules/eslint-plugin-sonarjs": { "version": "0.19.0", "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.19.0.tgz", @@ -8017,6 +8057,14 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "engines": { + "node": ">=6" + } + }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", diff --git a/package.json b/package.json index 86ea21ac3..07b999693 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "syntest", "automatic-test-generation" ], + "type": "module", "homepage": "https://www.syntest.org", "bugs": { "url": "https://github.com/syntest-framework/syntest-javascript/issues" @@ -51,8 +52,10 @@ "@commitlint/cli": "17.4.2", "@commitlint/config-conventional": "17.4.2", "@types/babel__core": "7.20.0", - "@types/babel__traverse": "7.18.5", + "@types/babel__register": "^7.17.1", + "@types/babel__traverse": "7.20.2", "@types/chai": "4.3.4", + "@types/esm": "^3.2.0", "@types/figlet": "1.5.4", "@types/lodash.clonedeep": "^4.5.7", "@types/mocha": "10.0.1", @@ -68,6 +71,7 @@ "eslint-plugin-import": "^2.27.5", "eslint-plugin-notice": "^0.9.10", "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-require-extensions": "^0.1.3", "eslint-plugin-sonarjs": "^0.19.0", "eslint-plugin-unicorn": "^45.0.2", "eslint-plugin-unused-imports": "^2.0.0", @@ -79,7 +83,6 @@ "nyc": "15.1.0", "prettier": "2.8.1", "sinon": "15.0.1", - "ts-node": "10.9.1", "typed-emitter": "^2.1.0", "typescript": "4.9.4", "winston": "3.8.2" diff --git a/plugins/plugin-javascript-event-listener-state-storage/index.ts b/plugins/plugin-javascript-event-listener-state-storage/index.ts index 5846fdbc6..bf8932e8e 100644 --- a/plugins/plugin-javascript-event-listener-state-storage/index.ts +++ b/plugins/plugin-javascript-event-listener-state-storage/index.ts @@ -16,4 +16,4 @@ * limitations under the License. */ -export * as module from "./lib/StateStorageModule"; +export * as module from "./lib/StateStorageModule.js"; diff --git a/plugins/plugin-javascript-event-listener-state-storage/lib/StateStorageEventListenerPlugin.ts b/plugins/plugin-javascript-event-listener-state-storage/lib/StateStorageEventListenerPlugin.ts index d11d5e7a3..1c8116dec 100644 --- a/plugins/plugin-javascript-event-listener-state-storage/lib/StateStorageEventListenerPlugin.ts +++ b/plugins/plugin-javascript-event-listener-state-storage/lib/StateStorageEventListenerPlugin.ts @@ -20,9 +20,9 @@ import { Events, RootContext } from "@syntest/analysis-javascript"; import { EventListenerPlugin } from "@syntest/module"; import { StorageManager } from "@syntest/storage"; import TypedEventEmitter from "typed-emitter"; -import Yargs = require("yargs"); +import * as Yargs from "yargs"; -import { StateStorage } from "./StateStorage"; +import { StateStorage } from "./StateStorage.js"; export type StateStorageOptions = { javascriptStateStorageDirectory: string; @@ -30,8 +30,6 @@ export type StateStorageOptions = { /** * This graphing plugin creates a listener that creates an SVG based on the generated CFG. - * - * @author Dimitri Stallenberg */ export class StateStorageEventListenerPlugin extends EventListenerPlugin { private storageManager: StorageManager; @@ -39,8 +37,7 @@ export class StateStorageEventListenerPlugin extends EventListenerPlugin { constructor(storageManager: StorageManager) { super( "javascript-state-storage", - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-var-requires, unicorn/prefer-module, @typescript-eslint/no-unsafe-member-access - require("../../package.json").description + "A listener plugin for SynTest JavaScript containing state storage functionalities" ); this.storageManager = storageManager; } diff --git a/plugins/plugin-javascript-event-listener-state-storage/lib/StateStorageModule.ts b/plugins/plugin-javascript-event-listener-state-storage/lib/StateStorageModule.ts index ed3635f5d..cacabb3a7 100644 --- a/plugins/plugin-javascript-event-listener-state-storage/lib/StateStorageModule.ts +++ b/plugins/plugin-javascript-event-listener-state-storage/lib/StateStorageModule.ts @@ -20,16 +20,13 @@ import { MetricManager } from "@syntest/metric"; import { Module, ModuleManager } from "@syntest/module"; import { StorageManager } from "@syntest/storage"; -import { StateStorageEventListenerPlugin } from "./StateStorageEventListenerPlugin"; +import package_ from "../package.json" assert { type: "json" }; + +import { StateStorageEventListenerPlugin } from "./StateStorageEventListenerPlugin.js"; export default class StateStorageModule extends Module { constructor() { - super( - // eslint-disable-next-line @typescript-eslint/no-var-requires,unicorn/prefer-module, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access - require("../../package.json").name, - // eslint-disable-next-line @typescript-eslint/no-var-requires,unicorn/prefer-module, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access - require("../../package.json").version - ); + super(package_.name, package_.version); } register( diff --git a/plugins/plugin-javascript-event-listener-state-storage/package.json b/plugins/plugin-javascript-event-listener-state-storage/package.json index 8de3878a9..98d53fd15 100644 --- a/plugins/plugin-javascript-event-listener-state-storage/package.json +++ b/plugins/plugin-javascript-event-listener-state-storage/package.json @@ -6,6 +6,7 @@ "syntest", "automatic-test-generation" ], + "type": "module", "homepage": "https://www.syntest.org", "bugs": { "url": "https://github.com/syntest-framework/syntest-core/issues" diff --git a/plugins/plugin-javascript-event-listener-state-storage/test/simulation.test.ts b/plugins/plugin-javascript-event-listener-state-storage/test/simulation.test.ts index e9385b5bc..a15a3d2e8 100644 --- a/plugins/plugin-javascript-event-listener-state-storage/test/simulation.test.ts +++ b/plugins/plugin-javascript-event-listener-state-storage/test/simulation.test.ts @@ -18,7 +18,7 @@ import { StorageManager } from "@syntest/storage"; import * as chai from "chai"; -import { StateStorage } from "../lib/StateStorage"; +import { StateStorage } from "../lib/StateStorage.js"; const expect = chai.expect; diff --git a/plugins/plugin-javascript-event-listener-state-storage/tsconfig.json b/plugins/plugin-javascript-event-listener-state-storage/tsconfig.json index 97ea4a6a1..be63429b8 100644 --- a/plugins/plugin-javascript-event-listener-state-storage/tsconfig.json +++ b/plugins/plugin-javascript-event-listener-state-storage/tsconfig.json @@ -5,5 +5,5 @@ "rootDir": ".", "composite": true }, - "include": ["**/*.ts"] + "include": ["**/*.ts", "package.json"] } diff --git a/tools/javascript/index.ts b/tools/javascript/index.ts index 799f9957a..b515e0818 100644 --- a/tools/javascript/index.ts +++ b/tools/javascript/index.ts @@ -15,4 +15,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export * as module from "./lib/JavaScriptModule"; +export * as module from "./lib/JavaScriptModule.js"; diff --git a/tools/javascript/lib/JavaScriptLauncher.ts b/tools/javascript/lib/JavaScriptLauncher.ts index 2c7b343a7..415a380c4 100644 --- a/tools/javascript/lib/JavaScriptLauncher.ts +++ b/tools/javascript/lib/JavaScriptLauncher.ts @@ -79,10 +79,10 @@ import { } from "@syntest/search-javascript"; import { StorageManager } from "@syntest/storage"; -import { TestCommandOptions } from "./commands/test"; -import { DeDuplicator } from "./workflows/DeDuplicator"; -import { addMetaComments } from "./workflows/MetaComment"; -import { TestSplitting } from "./workflows/TestSplitter"; +import { TestCommandOptions } from "./commands/test.js"; +import { DeDuplicator } from "./workflows/DeDuplicator.js"; +import { addMetaComments } from "./workflows/MetaComment.js"; +import { TestSplitting } from "./workflows/TestSplitter.js"; export type JavaScriptArguments = ArgumentsObject & TestCommandOptions; export class JavaScriptLauncher extends Launcher { @@ -550,7 +550,6 @@ export class JavaScriptLauncher extends Launcher { finalEncodings = new Map( [...newArchives.entries()].map(([target, archive]) => { - console.log("archive size", archive.size); return [target, archive.getEncodings()]; }) ); @@ -919,13 +918,13 @@ export class JavaScriptLauncher extends Launcher { } // TODO should be cleanup step in tool // Finish - JavaScriptLauncher.LOGGER.info("Deleting temporary directories"); - this.storageManager.deleteTemporaryDirectories([ - [this.arguments_.testDirectory], - [this.arguments_.logDirectory], - [this.arguments_.instrumentedDirectory], - ]); - - this.storageManager.deleteMainTemporary(); + // JavaScriptLauncher.LOGGER.info("Deleting temporary directories"); + // this.storageManager.deleteTemporaryDirectories([ + // [this.arguments_.testDirectory], + // [this.arguments_.logDirectory], + // [this.arguments_.instrumentedDirectory], + // ]); + + // this.storageManager.deleteMainTemporary(); } } diff --git a/tools/javascript/lib/JavaScriptModule.ts b/tools/javascript/lib/JavaScriptModule.ts index 6bbe0f207..d5ce7619a 100644 --- a/tools/javascript/lib/JavaScriptModule.ts +++ b/tools/javascript/lib/JavaScriptModule.ts @@ -21,20 +21,17 @@ import { UserInterface } from "@syntest/cli-graphics"; import { MetricManager } from "@syntest/metric"; import { Module, ModuleManager, Tool } from "@syntest/module"; import { StorageManager } from "@syntest/storage"; -import yargs = require("yargs"); +import * as yargs from "yargs"; -import { getTestCommand } from "./commands/test"; -import { TreeCrossoverPlugin } from "./plugins/crossover/TreeCrossoverPlugin"; -import { RandomSamplerPlugin } from "./plugins/sampler/RandomSamplerPlugin"; +import package_ from "../package.json" assert { type: "json" }; + +import { getTestCommand } from "./commands/test.js"; +import { TreeCrossoverPlugin } from "./plugins/crossover/TreeCrossoverPlugin.js"; +import { RandomSamplerPlugin } from "./plugins/sampler/RandomSamplerPlugin.js"; export default class JavaScriptModule extends TestingToolModule { constructor() { - super( - // eslint-disable-next-line @typescript-eslint/no-var-requires, unicorn/prefer-module, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access - require("../../package.json").name, - // eslint-disable-next-line @typescript-eslint/no-var-requires, unicorn/prefer-module, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access - require("../../package.json").version - ); + super(package_.name, package_.version); } override register( diff --git a/tools/javascript/lib/commands/test.ts b/tools/javascript/lib/commands/test.ts index 65da41f32..e41e6399a 100644 --- a/tools/javascript/lib/commands/test.ts +++ b/tools/javascript/lib/commands/test.ts @@ -19,9 +19,12 @@ import { UserInterface } from "@syntest/cli-graphics"; import { MetricManager } from "@syntest/metric"; import { Command, ModuleManager } from "@syntest/module"; import { StorageManager } from "@syntest/storage"; -import Yargs = require("yargs"); +import * as yargs from "yargs"; -import { JavaScriptArguments, JavaScriptLauncher } from "../JavaScriptLauncher"; +import { + JavaScriptArguments, + JavaScriptLauncher, +} from "../JavaScriptLauncher.js"; export function getTestCommand( tool: string, @@ -30,7 +33,7 @@ export function getTestCommand( storageManager: StorageManager, userInterface: UserInterface ): Command { - const options = new Map(); + const options = new Map(); const commandGroup = "Type Inference Options:"; const samplingGroup = "Sampling Options:"; @@ -164,7 +167,7 @@ export function getTestCommand( "test", "Run the test case generation tool on a certain JavaScript project.", options, - async (arguments_: Yargs.ArgumentsCamelCase) => { + async (arguments_: yargs.ArgumentsCamelCase) => { const launcher = new JavaScriptLauncher( (arguments_), moduleManager, diff --git a/tools/javascript/lib/plugins/sampler/RandomSamplerPlugin.ts b/tools/javascript/lib/plugins/sampler/RandomSamplerPlugin.ts index d65808052..d4fa3d585 100644 --- a/tools/javascript/lib/plugins/sampler/RandomSamplerPlugin.ts +++ b/tools/javascript/lib/plugins/sampler/RandomSamplerPlugin.ts @@ -23,7 +23,7 @@ import { JavaScriptTestCase, } from "@syntest/search-javascript"; -import { JavaScriptArguments } from "../../JavaScriptLauncher"; +import { JavaScriptArguments } from "../../JavaScriptLauncher.js"; /** * Plugin for RandomSampler diff --git a/tools/javascript/package.json b/tools/javascript/package.json index d32c9941f..af178da00 100644 --- a/tools/javascript/package.json +++ b/tools/javascript/package.json @@ -6,6 +6,7 @@ "syntest", "automatic-test-generation" ], + "type": "module", "homepage": "https://www.syntest.org", "bugs": { "url": "https://github.com/syntest-framework/syntest-javascript/issues" diff --git a/tools/javascript/test/example.test.ts b/tools/javascript/test/example.test.ts index d14d7f7e8..a74946d6a 100644 --- a/tools/javascript/test/example.test.ts +++ b/tools/javascript/test/example.test.ts @@ -17,7 +17,7 @@ */ import * as chai from "chai"; -import { RandomSamplerPlugin } from "../lib/plugins/sampler/RandomSamplerPlugin"; +import { RandomSamplerPlugin } from "../lib/plugins/sampler/RandomSamplerPlugin.js"; const expect = chai.expect; diff --git a/tools/javascript/tsconfig.json b/tools/javascript/tsconfig.json index 97ea4a6a1..be63429b8 100644 --- a/tools/javascript/tsconfig.json +++ b/tools/javascript/tsconfig.json @@ -5,5 +5,5 @@ "rootDir": ".", "composite": true }, - "include": ["**/*.ts"] + "include": ["**/*.ts", "package.json"] } diff --git a/tsconfig-base.json b/tsconfig-base.json index 35251540e..e472358e5 100644 --- a/tsconfig-base.json +++ b/tsconfig-base.json @@ -4,11 +4,12 @@ /* Basic Options */ //"incremental": true /* Enable incremental compilation */, - "target": "ES2021" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, - "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + "target": "ESNext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, + "module": "ESNext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, "lib": [ - "ES2021" + "ESNext" ] /* Specify library files to be included in the compilation. */, + //"allowJs": true /* Allow javascript files to be compiled. */, //"checkJs": true /* Report errors in .js files. */, //"jsx": "preserve" /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */, @@ -50,14 +51,14 @@ // "exactOptionalPropertyTypes": true /** Only works with strictNullChecks */, /* Module Resolution Options */ - //"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, + "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, //"baseUrl": "./" /* Base directory to resolve non-absolute module names. */, //"paths": {} /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */, //"rootDirs": [] /* List of root folders whose combined content represents the structure of the project at runtime. */, //"typeRoots": [] /* List of folders to include type definitions from. */, //"types": [] /* Type declaration files to be included in compilation. */, - //"allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */, - //"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + "allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */, + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, //"preserveSymlinks": true /* Do not resolve the real path of symlinks. */, //"allowUmdGlobalAccess": true /* Allow accessing UMD globals from modules. */, @@ -71,6 +72,8 @@ //"experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, //"emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */, + "resolveJsonModule": true, + /* Advanced Options */ "skipLibCheck": true /* Skip type checking of declaration files. */, "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ diff --git a/tsconfig.json b/tsconfig.json index 8082293a0..be8c6ab2c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,5 +5,8 @@ "rootDir": ".", "composite": true }, - "include": ["**/*.ts"] + "include": [ + "**/*.ts", + "libraries/instrumentation-javascript/lib/global/Global.cjs" + ] }