Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c8c6832

Browse files
feat: implement storage library (#138)
1 parent b39fc49 commit c8c6832

File tree

12 files changed

+2304
-4254
lines changed

12 files changed

+2304
-4254
lines changed

‎libraries/analysis-javascript/lib/RootContext.ts‎

Lines changed: 1 addition & 302 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
*/
1818

1919
import { existsSync, lstatSync } from "node:fs";
20-
import * as path from "node:path";
2120

2221
import * as t from "@babel/types";
2322
import { RootContext as CoreRootContext } from "@syntest/analysis";
@@ -82,7 +81,7 @@ export class RootContext extends CoreRootContext<t.Node> {
8281
// TODO something with the types
8382

8483
override getSource(filePath: string) {
85-
let absoluteTargetPath = path.resolve(filePath);
84+
let absoluteTargetPath = this.resolvePath(filePath);
8685

8786
if (!this._sources.has(absoluteTargetPath)) {
8887
if (!existsSync(absoluteTargetPath)) {
@@ -158,306 +157,6 @@ export class RootContext extends CoreRootContext<t.Node> {
158157
return this._typeModel;
159158
}
160159

161-
// getTargetMap(targetPath: string): Map<string, JavaScriptTargetMetaData> {
162-
// const absoluteTargetPath = path.resolve(targetPath);
163-
164-
// if (!this._targetMap.has(absoluteTargetPath)) {
165-
// const targetAST = this.getAST(absoluteTargetPath);
166-
// const { targetMap, functionMap } = this.targetMapGenerator.generate(
167-
// absoluteTargetPath,
168-
// targetAST
169-
// );
170-
171-
// const exports = this.getExports(targetPath);
172-
173-
// const finalTargetMap = new Map<string, JavaScriptTargetMetaData>();
174-
175-
// for (const key of targetMap.keys()) {
176-
// const name = targetMap.get(key).name;
177-
// const export_ = exports.find((export_) => export_.name === name);
178-
179-
// if (!export_) {
180-
// // No export found so we cannot import it and thus not test it
181-
// continue;
182-
// }
183-
184-
// if (
185-
// export_.type === ExportType.const &&
186-
// functionMap.get(key).size === 0
187-
// ) {
188-
// throw new Error(
189-
// `Target cannot be constant: ${name} -> ${JSON.stringify(export_)}`
190-
// );
191-
// }
192-
193-
// let isPrototypeClass = false;
194-
// for (const function_ of functionMap.get(key).values()) {
195-
// if (function_.isConstructor) {
196-
// isPrototypeClass = true;
197-
// break;
198-
// }
199-
// }
200-
201-
// // let isClass = false
202-
// // if (functionMap.get(key).size > 1) {
203-
// // isClass = true
204-
// // }
205-
206-
// // threat everything as a function if we don't know
207-
// finalTargetMap.set(key, {
208-
// name: name,
209-
// type:
210-
// export_.type === ExportType.class || isPrototypeClass
211-
// ? SubjectType.class
212-
// : export_.type === ExportType.const
213-
// ? SubjectType.object
214-
// : SubjectType.function,
215-
// export: export_,
216-
// });
217-
// }
218-
219-
// this._targetMap.set(absoluteTargetPath, finalTargetMap);
220-
// this._functionMaps.set(absoluteTargetPath, functionMap);
221-
// }
222-
223-
// return this._targetMap.get(absoluteTargetPath);
224-
// }
225-
226-
// getDependencies(targetPath: string): Export[] {
227-
// const absoluteTargetPath = path.resolve(targetPath);
228-
229-
// if (!this._dependencyMaps.has(absoluteTargetPath)) {
230-
// // Find all external imports in the file under test
231-
// const imports = this.importGenerator.generate(
232-
// absoluteTargetPath,
233-
// this.getAST(targetPath)
234-
// );
235-
236-
// // For each external import scan the file for libraries with exported functions
237-
// const libraries: Export[] = [];
238-
// for (const importPath of imports) {
239-
// // Full path to the imported file
240-
// const pathLibrary = path.join(path.dirname(targetPath), importPath);
241-
242-
// // External libraries have a different path!
243-
// try {
244-
// this.getSource(pathLibrary);
245-
// } catch (error) {
246-
// if (error.message.includes("Cannot find source")) {
247-
// // TODO would be nice if we could get the actual path! (node modules)
248-
// continue;
249-
250-
// // pathLib = path.join
251-
// } else {
252-
// throw error;
253-
// }
254-
// }
255-
256-
// // Scan for libraries with public or external functions
257-
// const exports = this.getExports(pathLibrary);
258-
259-
// // Import the found libraries
260-
// // TODO: check for duplicates in libraries
261-
// libraries.push(...exports);
262-
// }
263-
264-
// return libraries;
265-
266-
// // this._dependencyMaps.set(targetPath, libraries);
267-
// }
268-
269-
// return this._dependencyMaps.get(absoluteTargetPath);
270-
// }
271-
272-
// scanTargetRootDirectory(targetRootDirectory: string): void {
273-
// const absoluteRootPath = path.resolve(targetRootDirectory);
274-
275-
// // TODO remove the filters
276-
// const files = getAllFiles(absoluteRootPath, ".js").filter(
277-
// (x) =>
278-
// !x.includes("/test/") &&
279-
// !x.includes(".test.js") &&
280-
// !x.includes("node_modules")
281-
// ); // maybe we should also take those into account
282-
283-
// const objects: ComplexType[] = [];
284-
// const objectGenerator = new ObjectGenerator();
285-
286-
// for (const file of files) {
287-
// const exports = this.getExports(file);
288-
// objects.push(
289-
// ...objectGenerator.generate(
290-
// file,
291-
// this.getAbstractSyntaxTree(file),
292-
// exports
293-
// )
294-
// );
295-
// }
296-
297-
// // standard stuff
298-
// // function https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function
299-
// objects.push(
300-
// {
301-
// name: "function",
302-
// properties: new Set([
303-
// "arguments",
304-
// "caller",
305-
// "displayName",
306-
// "length",
307-
// "name",
308-
// ]),
309-
// functions: new Set(["apply", "bind", "call", "toString"]),
310-
// propertyType: new Map<string, TypeProbability>([
311-
// ["arguments", new TypeProbability([[TypeEnum.ARRAY, 1, undefined]])],
312-
// ["caller", new TypeProbability([[TypeEnum.FUNCTION, 1, undefined]])],
313-
// [
314-
// "displayName",
315-
// new TypeProbability([[TypeEnum.STRING, 1, undefined]]),
316-
// ],
317-
// ["length", new TypeProbability([[TypeEnum.NUMERIC, 1, undefined]])],
318-
// ["name", new TypeProbability([[TypeEnum.STRING, 1, undefined]])],
319-
// ]),
320-
// },
321-
322-
// // array https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
323-
// {
324-
// name: "array",
325-
// properties: new Set(["length"]),
326-
// functions: new Set([
327-
// "at",
328-
// "concat",
329-
// "copyWithin",
330-
// "entries",
331-
// "fill",
332-
// "filter",
333-
// "find",
334-
// "findIndex",
335-
// "flat",
336-
// "flatMap",
337-
// "includes",
338-
// "indexOf",
339-
// "join",
340-
// "keys",
341-
// "lastIndexOf",
342-
// "map",
343-
// "pop",
344-
// "push",
345-
// "reduce",
346-
// "reduceRight",
347-
// "reverse",
348-
// "shift",
349-
// "slice",
350-
// "toLocaleString",
351-
// "toString",
352-
// "unshift",
353-
// "values",
354-
// ]),
355-
// propertyType: new Map<string, TypeProbability>([
356-
// ["length", new TypeProbability([[TypeEnum.NUMERIC, 1, undefined]])],
357-
// ]),
358-
// },
359-
360-
// // string
361-
// {
362-
// name: "string",
363-
// properties: new Set(["length"]),
364-
// functions: new Set([
365-
// "at",
366-
// "charAt",
367-
// "charCodeAt",
368-
// "codePointAt",
369-
// "concat",
370-
// "includes",
371-
// "endsWith",
372-
// "indexOf",
373-
// "lastIndexOf",
374-
// "localeCompare",
375-
// "match",
376-
// "matchAll",
377-
// "normalize",
378-
// "padEnd",
379-
// "padStart",
380-
// "repeat",
381-
// "replace",
382-
// "replaceAll",
383-
// "search",
384-
// "slice",
385-
// "split",
386-
// "startsWith",
387-
// "substring",
388-
// "toLocaleLowerCase",
389-
// "toLocaleUpperCase",
390-
// "toLowerCase",
391-
// "toString",
392-
// "toUpperCase",
393-
// "trim",
394-
// "trimStart",
395-
// "trimEnd",
396-
// "valueOf",
397-
// ]),
398-
// propertyType: new Map<string, TypeProbability>([
399-
// ["length", new TypeProbability([[TypeEnum.NUMERIC, 1, undefined]])],
400-
// ]),
401-
// }
402-
// );
403-
404-
// // TODO npm dependencies
405-
// // TODO get rid of duplicates
406-
407-
// const finalObjects: ComplexType[] = [];
408-
409-
// // eslint-disable-next-line unicorn/consistent-function-scoping
410-
// function eqSet(as: Set<unknown>, bs: Set<unknown>) {
411-
// if (as.size !== bs.size) return false;
412-
// for (const a of as) if (!bs.has(a)) return false;
413-
// return true;
414-
// }
415-
416-
// for (const o of objects) {
417-
// if (o.properties.size === 0 && o.functions.size === 0) {
418-
// continue;
419-
// }
420-
421-
// const found = finalObjects.find((o2) => {
422-
// return (
423-
// o.export === o2.export && // TODO not sure if you can compare exports like this
424-
// o.name === o2.name &&
425-
// eqSet(o.properties, o2.properties) &&
426-
// eqSet(o.functions, o2.functions)
427-
// );
428-
// });
429-
430-
// if (!found) {
431-
// finalObjects.push(o);
432-
// }
433-
// }
434-
435-
// const generator = new VariableGenerator();
436-
// const elements: Element[] = [];
437-
// const relations: Relation[] = [];
438-
// const wrapperElementIsRelation: Map<string, Relation> = new Map();
439-
440-
// for (const file of files) {
441-
// const [_elements, _relations, _wrapperElementIsRelation] =
442-
// generator.generate(file, this.getAbstractSyntaxTree(file));
443-
444-
// elements.push(..._elements);
445-
// relations.push(..._relations);
446-
447-
// for (const key of _wrapperElementIsRelation.keys()) {
448-
// wrapperElementIsRelation.set(key, _wrapperElementIsRelation.get(key));
449-
// }
450-
// }
451-
452-
// this._typeResolver.resolveTypes(
453-
// elements,
454-
// relations,
455-
// wrapperElementIsRelation,
456-
// finalObjects
457-
// );
458-
459-
// }
460-
461160
getElement(id: string): Element {
462161
if (!this._elementMap || !this._elementMap.has(id)) {
463162
this.extractTypes();

‎libraries/analysis-javascript/package.json‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@
4848
"dependencies": {
4949
"@babel/core": "7.20.12",
5050
"@babel/traverse": "7.20.12",
51-
"@syntest/analysis": "^0.1.0-beta.4",
51+
"@syntest/analysis": "^0.1.0-beta.7",
5252
"@syntest/ast-visitor-javascript": "*",
53-
"@syntest/cfg": "^0.3.0-beta.16",
53+
"@syntest/cfg": "^0.3.0-beta.18",
5454
"@syntest/logging": "^0.1.0-beta.6",
55-
"@syntest/search": "^0.4.0-beta.25"
55+
"@syntest/search": "^0.4.0-beta.32"
5656
},
5757
"engines": {
5858
"node": ">=10.24.0"

‎libraries/instrumentation-javascript/lib/instrumentation/Instrumenter.ts‎

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ import {
2424
defaultBabelOptions,
2525
} from "@syntest/analysis-javascript";
2626
import * as path from "node:path";
27-
import { copySync, outputFileSync } from "fs-extra";
28-
27+
import { StorageManager } from "@syntest/storage";
2928
export interface OutputObject {
3029
fileCoverage?: any;
3130
sourceMappingURL?: any;
@@ -34,19 +33,21 @@ export interface OutputObject {
3433
export class Instrumenter {
3534
// TODO maybe the instrumenter should not be responsible for copying the files
3635
async instrumentAll(
36+
storageManager: StorageManager,
3737
rootContext: RootContext,
3838
targets: Target[],
39-
temporaryInstrumentedDirectory: string
39+
instrumentedDirectory: string
4040
): Promise<void> {
4141
const absoluteRootPath = path.resolve(rootContext.rootPath);
42-
43-
const destinationPath = path.resolve(
44-
temporaryInstrumentedDirectory,
42+
const destinationPath = path.join(
43+
instrumentedDirectory,
4544
path.basename(absoluteRootPath)
4645
);
47-
4846
// copy everything
49-
await copySync(absoluteRootPath, destinationPath);
47+
storageManager.copyToTemporaryDirectory(
48+
[absoluteRootPath],
49+
[...destinationPath.split(path.sep)]
50+
);
5051

5152
// overwrite the stuff that needs instrumentation
5253

@@ -60,7 +61,15 @@ export class Instrumenter {
6061
.normalize(targetPath)
6162
.replace(absoluteRootPath, destinationPath);
6263

63-
await outputFileSync(_path, instrumentedSource);
64+
const directory = path.dirname(_path);
65+
const file = path.basename(_path);
66+
67+
storageManager.store(
68+
[...directory.split(path.sep)],
69+
file,
70+
instrumentedSource,
71+
true
72+
);
6473
}
6574
}
6675

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /