From 4aa5edbfa469d0726f96b79140397b3bd7b4d255 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Mon, 8 Jul 2024 15:34:33 +0100 Subject: [PATCH 01/38] draft: initial implementation of event listener for inserts --- Clava-JS/src-api/Joinpoints.ts | 11 +++++++++-- Clava-JS/src-api/clava/history/eventListener.ts | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 Clava-JS/src-api/clava/history/eventListener.ts diff --git a/Clava-JS/src-api/Joinpoints.ts b/Clava-JS/src-api/Joinpoints.ts index 575d3768c..83428cbdd 100644 --- a/Clava-JS/src-api/Joinpoints.ts +++ b/Clava-JS/src-api/Joinpoints.ts @@ -17,6 +17,7 @@ import { wrapJoinPoint, unwrapJoinPoint, } from "lara-js/api/LaraJoinPoint.js"; +import eventListener from "./clava/history/eventListener.js"; export class Joinpoint extends LaraJoinPoint { /** @@ -310,7 +311,10 @@ export class Joinpoint extends LaraJoinPoint { /** * Inserts the given join point after this join point */ - insertAfter(p1: Joinpoint | string): Joinpoint | Joinpoint { return wrapJoinPoint(this._javaObject.insertAfter(unwrapJoinPoint(p1))); } + insertAfter(p1: Joinpoint | string): Joinpoint | Joinpoint { + eventListener.emit("storeAST", p1.toString()); + return wrapJoinPoint(this._javaObject.insertAfter(unwrapJoinPoint(p1))); + } /** * Inserts the given join point before this join point */ @@ -322,7 +326,10 @@ export class Joinpoint extends LaraJoinPoint { /** * Inserts the given join point before this join point */ - insertBefore(p1: Joinpoint | string): Joinpoint | Joinpoint { return wrapJoinPoint(this._javaObject.insertBefore(unwrapJoinPoint(p1))); } + insertBefore(p1: Joinpoint | string): Joinpoint | Joinpoint { + eventListener.emit("storeAST", p1.toString()); + return wrapJoinPoint(this._javaObject.insertBefore(unwrapJoinPoint(p1))); + } /** * Adds a message that will be printed to the user after weaving finishes. Identical messages are removed */ diff --git a/Clava-JS/src-api/clava/history/eventListener.ts b/Clava-JS/src-api/clava/history/eventListener.ts new file mode 100644 index 000000000..023488bd3 --- /dev/null +++ b/Clava-JS/src-api/clava/history/eventListener.ts @@ -0,0 +1,15 @@ +import { EventEmitter } from "events"; +import * as fs from "fs"; +import Clava from "../Clava.js"; + +const eventListener = new EventEmitter(); + +let idx = 0; + +eventListener.on("storeAST", (data: string) => { + console.log(`Waypoint ${idx}`); + fs.writeFileSync(`history/waypoint_${idx}.txt`, Clava.getProgram().code); + idx++; +}); + +export default eventListener; From 8b61d9e771bbc21a260ce37d68ba8b74caa22951 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Mon, 8 Jul 2024 15:51:14 +0100 Subject: [PATCH 02/38] feat: finished code waypoints for Inserts and Detach --- Clava-JS/src-api/Joinpoints.ts | 9 ++++++--- Clava-JS/src-api/clava/history/eventListener.ts | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Clava-JS/src-api/Joinpoints.ts b/Clava-JS/src-api/Joinpoints.ts index 83428cbdd..f69b15178 100644 --- a/Clava-JS/src-api/Joinpoints.ts +++ b/Clava-JS/src-api/Joinpoints.ts @@ -299,7 +299,10 @@ export class Joinpoint extends LaraJoinPoint { /** * Removes the node associated to this joinpoint from the AST */ - detach(): Joinpoint { return wrapJoinPoint(this._javaObject.detach()); } + detach(): Joinpoint { + eventListener.emit("storeAST"); + return wrapJoinPoint(this._javaObject.detach()); + } /** * Inserts the given join point after this join point */ @@ -312,7 +315,7 @@ export class Joinpoint extends LaraJoinPoint { * Inserts the given join point after this join point */ insertAfter(p1: Joinpoint | string): Joinpoint | Joinpoint { - eventListener.emit("storeAST", p1.toString()); + eventListener.emit("storeAST"); return wrapJoinPoint(this._javaObject.insertAfter(unwrapJoinPoint(p1))); } /** @@ -327,7 +330,7 @@ export class Joinpoint extends LaraJoinPoint { * Inserts the given join point before this join point */ insertBefore(p1: Joinpoint | string): Joinpoint | Joinpoint { - eventListener.emit("storeAST", p1.toString()); + eventListener.emit("storeAST"); return wrapJoinPoint(this._javaObject.insertBefore(unwrapJoinPoint(p1))); } /** diff --git a/Clava-JS/src-api/clava/history/eventListener.ts b/Clava-JS/src-api/clava/history/eventListener.ts index 023488bd3..e07bc1fb2 100644 --- a/Clava-JS/src-api/clava/history/eventListener.ts +++ b/Clava-JS/src-api/clava/history/eventListener.ts @@ -6,7 +6,7 @@ const eventListener = new EventEmitter(); let idx = 0; -eventListener.on("storeAST", (data: string) => { +eventListener.on("storeAST", () => { console.log(`Waypoint ${idx}`); fs.writeFileSync(`history/waypoint_${idx}.txt`, Clava.getProgram().code); idx++; From e96221b9086e579352cc8a735281f80e78d39400 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Tue, 9 Jul 2024 14:25:19 +0100 Subject: [PATCH 03/38] feat: finished code waypoints for other changes --- Clava-JS/src-api/Joinpoints.ts | 30 +++++++++++++++---- .../src-api/clava/history/eventListener.ts | 2 +- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/Clava-JS/src-api/Joinpoints.ts b/Clava-JS/src-api/Joinpoints.ts index f69b15178..d9dac14b5 100644 --- a/Clava-JS/src-api/Joinpoints.ts +++ b/Clava-JS/src-api/Joinpoints.ts @@ -340,7 +340,10 @@ export class Joinpoint extends LaraJoinPoint { /** * Removes the children of this node */ - removeChildren(): void { return wrapJoinPoint(this._javaObject.removeChildren()); } + removeChildren(): void { + eventListener.emit("storeAST"); + return wrapJoinPoint(this._javaObject.removeChildren()); + } /** * Replaces this node with the given node */ @@ -356,11 +359,17 @@ export class Joinpoint extends LaraJoinPoint { /** * Replaces this node with the given node */ - replaceWith(p1: Joinpoint | string | Joinpoint[]): Joinpoint | Joinpoint | Joinpoint { return wrapJoinPoint(this._javaObject.replaceWith(unwrapJoinPoint(p1))); } + replaceWith(p1: Joinpoint | string | Joinpoint[]): Joinpoint | Joinpoint | Joinpoint { + eventListener.emit("storeAST"); + return wrapJoinPoint(this._javaObject.replaceWith(unwrapJoinPoint(p1))); + } /** * Overload which accepts a list of strings */ - replaceWithStrings(node: string[]): Joinpoint { return wrapJoinPoint(this._javaObject.replaceWithStrings(unwrapJoinPoint(node))); } + replaceWithStrings(node: string[]): Joinpoint { + eventListener.emit("storeAST"); + return wrapJoinPoint(this._javaObject.replaceWithStrings(unwrapJoinPoint(node))); + } /** * Setting data directly is not supported, this action just emits a warning and does nothing */ @@ -368,7 +377,10 @@ export class Joinpoint extends LaraJoinPoint { /** * Replaces the first child, or inserts the join point if no child is present */ - setFirstChild(node: Joinpoint): void { return wrapJoinPoint(this._javaObject.setFirstChild(unwrapJoinPoint(node))); } + setFirstChild(node: Joinpoint): void { + eventListener.emit("storeAST"); + return wrapJoinPoint(this._javaObject.setFirstChild(unwrapJoinPoint(node))); + } /** * Sets the commented that are embedded in a node */ @@ -380,11 +392,17 @@ export class Joinpoint extends LaraJoinPoint { /** * Sets the commented that are embedded in a node */ - setInlineComments(p1: string[] | string): void | void { return wrapJoinPoint(this._javaObject.setInlineComments(unwrapJoinPoint(p1))); } + setInlineComments(p1: string[] | string): void | void { + eventListener.emit("storeAST"); + return wrapJoinPoint(this._javaObject.setInlineComments(unwrapJoinPoint(p1))); + } /** * Replaces the last child, or inserts the join point if no child is present */ - setLastChild(node: Joinpoint): void { return wrapJoinPoint(this._javaObject.setLastChild(unwrapJoinPoint(node))); } + setLastChild(node: Joinpoint): void { + eventListener.emit("storeAST"); + return wrapJoinPoint(this._javaObject.setLastChild(unwrapJoinPoint(node))); + } /** * Sets the type of a node, if it has a type */ diff --git a/Clava-JS/src-api/clava/history/eventListener.ts b/Clava-JS/src-api/clava/history/eventListener.ts index e07bc1fb2..c5dcfc4a1 100644 --- a/Clava-JS/src-api/clava/history/eventListener.ts +++ b/Clava-JS/src-api/clava/history/eventListener.ts @@ -8,7 +8,7 @@ let idx = 0; eventListener.on("storeAST", () => { console.log(`Waypoint ${idx}`); - fs.writeFileSync(`history/waypoint_${idx}.txt`, Clava.getProgram().code); + fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); idx++; }); From d1c61d75e1c8238861ec68c3636eb57b5a5e9f20 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Tue, 9 Jul 2024 15:15:28 +0100 Subject: [PATCH 04/38] fix: fixing support for all transformations --- Clava-JS/src-api/Joinpoints.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Clava-JS/src-api/Joinpoints.ts b/Clava-JS/src-api/Joinpoints.ts index abed1eb14..b42a7a331 100644 --- a/Clava-JS/src-api/Joinpoints.ts +++ b/Clava-JS/src-api/Joinpoints.ts @@ -551,7 +551,10 @@ export class Joinpoint extends LaraJoinPoint { /** * Replaces this join point with a comment with the same contents as .code */ - toComment(prefix: string = "", suffix: string = ""): Joinpoint { return wrapJoinPoint(this._javaObject.toComment(unwrapJoinPoint(prefix), unwrapJoinPoint(suffix))); } + toComment(prefix: string = "", suffix: string = ""): Joinpoint { + eventListener.emit("storeAST"); + return wrapJoinPoint(this._javaObject.toComment(unwrapJoinPoint(prefix), unwrapJoinPoint(suffix))); + } } export class Attribute extends Joinpoint { From 024d523b7c36d52c81d5a7640c17b0b2095efcf8 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Fri, 19 Jul 2024 15:38:31 +0100 Subject: [PATCH 05/38] feat: changes to event system, new Event object --- Clava-JS/src-api/Joinpoints.ts | 9 ++++-- .../{eventListener.ts => EventListener.ts} | 7 +++++ Clava-JS/src-api/clava/history/Events.ts | 28 +++++++++++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) rename Clava-JS/src-api/clava/history/{eventListener.ts => EventListener.ts} (64%) create mode 100644 Clava-JS/src-api/clava/history/Events.ts diff --git a/Clava-JS/src-api/Joinpoints.ts b/Clava-JS/src-api/Joinpoints.ts index b42a7a331..229521b4c 100644 --- a/Clava-JS/src-api/Joinpoints.ts +++ b/Clava-JS/src-api/Joinpoints.ts @@ -17,7 +17,8 @@ import { wrapJoinPoint, unwrapJoinPoint, } from "lara-js/api/LaraJoinPoint.js"; -import eventListener from "./clava/history/eventListener.js"; +import eventListener from "./clava/history/EventListener.js"; +import { Event, EventTime } from "./clava/history/Events.js"; type PrivateMapper = { "Joinpoint": typeof Joinpoint, @@ -425,8 +426,10 @@ export class Joinpoint extends LaraJoinPoint { * Removes the node associated to this joinpoint from the AST */ detach(): Joinpoint { - eventListener.emit("storeAST"); - return wrapJoinPoint(this._javaObject.detach()); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "detach", this)); + const jp = wrapJoinPoint(this._javaObject.detach()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "detach", this, jp as Joinpoint)); + return jp; } /** * Inserts the given join point after this join point diff --git a/Clava-JS/src-api/clava/history/eventListener.ts b/Clava-JS/src-api/clava/history/EventListener.ts similarity index 64% rename from Clava-JS/src-api/clava/history/eventListener.ts rename to Clava-JS/src-api/clava/history/EventListener.ts index c5dcfc4a1..8397b021b 100644 --- a/Clava-JS/src-api/clava/history/eventListener.ts +++ b/Clava-JS/src-api/clava/history/EventListener.ts @@ -1,6 +1,7 @@ import { EventEmitter } from "events"; import * as fs from "fs"; import Clava from "../Clava.js"; +import { Event } from "./Events.js"; const eventListener = new EventEmitter(); @@ -11,5 +12,11 @@ eventListener.on("storeAST", () => { fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); idx++; }); +eventListener.on("ACTION", (e: Event) => { + console.log(e.timing); + console.log(e.description); + console.log(e.mainJP); + console.log(e.returnJP); +}); export default eventListener; diff --git a/Clava-JS/src-api/clava/history/Events.ts b/Clava-JS/src-api/clava/history/Events.ts new file mode 100644 index 000000000..879d56805 --- /dev/null +++ b/Clava-JS/src-api/clava/history/Events.ts @@ -0,0 +1,28 @@ +import { Joinpoint } from "../../Joinpoints.js"; + +export enum EventTime { + BEFORE = "Before", + AFTER = "After" +} + +export class Event { + public timing: EventTime; + public description: string; + public mainJP: Joinpoint; + public returnJP?: Joinpoint; + public inputs: unknown[]; + + constructor( + timing: EventTime, + description: string, + mainJP: Joinpoint, + returnJP?: Joinpoint, + ...inputs: unknown[] + ) { + this.timing = timing; + this.description = description; + this.mainJP = mainJP; + this.returnJP = returnJP; + this.inputs = inputs; + } +} \ No newline at end of file From 339767bc9af7cb4c3bd39f16929049af6d23607d Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Fri, 19 Jul 2024 15:52:42 +0100 Subject: [PATCH 06/38] feat: standardized event calls on JoinPoints.ts --- Clava-JS/src-api/Joinpoints.ts | 75 ++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/Clava-JS/src-api/Joinpoints.ts b/Clava-JS/src-api/Joinpoints.ts index 229521b4c..e86922443 100644 --- a/Clava-JS/src-api/Joinpoints.ts +++ b/Clava-JS/src-api/Joinpoints.ts @@ -443,8 +443,10 @@ export class Joinpoint extends LaraJoinPoint { * Inserts the given join point after this join point */ insertAfter(p1: Joinpoint | string): Joinpoint { - eventListener.emit("storeAST"); - return wrapJoinPoint(this._javaObject.insertAfter(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "insertAfter", this)); + const jp = wrapJoinPoint(this._javaObject.insertAfter(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "insertAfter", this, jp as Joinpoint, p1)); + return jp; } /** * Inserts the given join point before this join point @@ -458,8 +460,10 @@ export class Joinpoint extends LaraJoinPoint { * Inserts the given join point before this join point */ insertBefore(p1: Joinpoint | string): Joinpoint { - eventListener.emit("storeAST"); - return wrapJoinPoint(this._javaObject.insertBefore(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "insertBefore", this)); + const jp = wrapJoinPoint(this._javaObject.insertBefore(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "insertBefore", this, jp as Joinpoint, p1)); + return jp; } /** * Adds a message that will be printed to the user after weaving finishes. Identical messages are removed @@ -469,8 +473,10 @@ export class Joinpoint extends LaraJoinPoint { * Removes the children of this node */ removeChildren(): void { - eventListener.emit("storeAST"); - return wrapJoinPoint(this._javaObject.removeChildren()); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "removeChildren", this)); + const jp = wrapJoinPoint(this._javaObject.removeChildren()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "removeChildren", this, jp as Joinpoint)); + return jp; } /** * Replaces this node with the given node @@ -488,15 +494,19 @@ export class Joinpoint extends LaraJoinPoint { * Replaces this node with the given node */ replaceWith(p1: Joinpoint | string | Joinpoint[]): Joinpoint { - eventListener.emit("storeAST"); - return wrapJoinPoint(this._javaObject.replaceWith(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "replaceWith", this)); + const jp = wrapJoinPoint(this._javaObject.replaceWith(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "replaceWith", this, jp as Joinpoint, p1)); + return jp; } /** * Overload which accepts a list of strings */ replaceWithStrings(node: string[]): Joinpoint { - eventListener.emit("storeAST"); - return wrapJoinPoint(this._javaObject.replaceWithStrings(unwrapJoinPoint(node))); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "replaceWithStrings", this)); + const jp = wrapJoinPoint(this._javaObject.replaceWithStrings(unwrapJoinPoint(node))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "replaceWithStrings", this, jp as Joinpoint, node)); + return jp; } /** * Setting data directly is not supported, this action just emits a warning and does nothing @@ -506,8 +516,10 @@ export class Joinpoint extends LaraJoinPoint { * Replaces the first child, or inserts the join point if no child is present */ setFirstChild(node: Joinpoint): void { - eventListener.emit("storeAST"); - return wrapJoinPoint(this._javaObject.setFirstChild(unwrapJoinPoint(node))); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setFirstChild", this)); + const jp = wrapJoinPoint(this._javaObject.setFirstChild(unwrapJoinPoint(node))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setFirstChild", this, jp as Joinpoint, node)); + return jp; } /** * Sets the commented that are embedded in a node @@ -521,20 +533,29 @@ export class Joinpoint extends LaraJoinPoint { * Sets the commented that are embedded in a node */ setInlineComments(p1: string[] | string): void { - eventListener.emit("storeAST"); - return wrapJoinPoint(this._javaObject.setInlineComments(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setInlineComments", this)); + const jp = wrapJoinPoint(this._javaObject.setInlineComments(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setInlineComments", this, jp as Joinpoint, p1)); + return jp; } /** * Replaces the last child, or inserts the join point if no child is present */ setLastChild(node: Joinpoint): void { - eventListener.emit("storeAST"); - return wrapJoinPoint(this._javaObject.setLastChild(unwrapJoinPoint(node))); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setLastChild", this)); + const jp = wrapJoinPoint(this._javaObject.setLastChild(unwrapJoinPoint(node))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setLastChild", this, jp as Joinpoint, node)); + return jp; } /** * Sets the type of a node, if it has a type */ - setType(type: Type): void { return wrapJoinPoint(this._javaObject.setType(unwrapJoinPoint(type))); } + setType(type: Type): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setType", this)); + const jp = wrapJoinPoint(this._javaObject.setType(unwrapJoinPoint(type))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setType", this, jp as Joinpoint, type)); + return jp; + } /** * Associates arbitrary values to nodes of the AST */ @@ -546,17 +567,29 @@ export class Joinpoint extends LaraJoinPoint { /** * Associates arbitrary values to nodes of the AST */ - setUserField(p1: string | Record, p2?: object): object { return wrapJoinPoint(this._javaObject.setUserField(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); } + setUserField(p1: string | Record, p2?: object): object { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setUserField", this)); + const jp = wrapJoinPoint(this._javaObject.setUserField(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setUserField", this, jp as Joinpoint, p1, p2)); + return jp; + } /** * Sets the value associated with the given property key */ - setValue(key: string, value: object): Joinpoint { return wrapJoinPoint(this._javaObject.setValue(unwrapJoinPoint(key), unwrapJoinPoint(value))); } + setValue(key: string, value: object): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setValue", this)); + const jp = wrapJoinPoint(this._javaObject.setValue(unwrapJoinPoint(key), unwrapJoinPoint(value))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setValue", this, jp as Joinpoint, key, value)); + return jp; + } /** * Replaces this join point with a comment with the same contents as .code */ toComment(prefix: string = "", suffix: string = ""): Joinpoint { - eventListener.emit("storeAST"); - return wrapJoinPoint(this._javaObject.toComment(unwrapJoinPoint(prefix), unwrapJoinPoint(suffix))); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "toComment", this)); + const jp = wrapJoinPoint(this._javaObject.toComment(unwrapJoinPoint(prefix), unwrapJoinPoint(suffix))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "toComment", this, jp as Joinpoint, prefix, suffix)); + return jp; } } From 8a58471db120288807c7ec15675d7ed062844693 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Fri, 19 Jul 2024 16:00:29 +0100 Subject: [PATCH 07/38] feat: added History and Operation Interface --- Clava-JS/src-api/clava/history/History.ts | 43 ++++++++++++++++++++ Clava-JS/src-api/clava/history/Operations.ts | 4 ++ 2 files changed, 47 insertions(+) create mode 100644 Clava-JS/src-api/clava/history/History.ts create mode 100644 Clava-JS/src-api/clava/history/Operations.ts diff --git a/Clava-JS/src-api/clava/history/History.ts b/Clava-JS/src-api/clava/history/History.ts new file mode 100644 index 000000000..463c3c57e --- /dev/null +++ b/Clava-JS/src-api/clava/history/History.ts @@ -0,0 +1,43 @@ +import { Operation } from "./Operations.js" + +class OperationHistory { + private operations: Operation[]; + private locked: boolean; + + constructor() { + this.operations = []; + this.locked = false; + } + + private lock() { + this.locked = true; + } + + private unlock() { + this.locked = false; + } + + newOperation(operation: Operation) { + if (!this.locked) { + this.operations.push(operation); + } + } + + rollback() { + const op = this.operations.pop(); + if (op !== undefined) { + try { + this.lock(); + op.undo(); + } catch (error) { + console.error("Failed to undo operation:", error); + } finally { + this.unlock(); + } + } + } +} + +const ophistory = new OperationHistory(); + +export default ophistory; \ No newline at end of file diff --git a/Clava-JS/src-api/clava/history/Operations.ts b/Clava-JS/src-api/clava/history/Operations.ts new file mode 100644 index 000000000..0eedd3412 --- /dev/null +++ b/Clava-JS/src-api/clava/history/Operations.ts @@ -0,0 +1,4 @@ + +export interface Operation { + undo(): void; +} \ No newline at end of file From 7ec1d6f342445e8364abdbae8510387a928e6efe Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Fri, 19 Jul 2024 17:36:54 +0100 Subject: [PATCH 08/38] feat: added InsertBefore and InsertAfter events --- .../src-api/clava/history/EventListener.ts | 44 ++++++++++++++++++- Clava-JS/src-api/clava/history/Operations.ts | 11 ++++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/Clava-JS/src-api/clava/history/EventListener.ts b/Clava-JS/src-api/clava/history/EventListener.ts index 8397b021b..b3c7548b4 100644 --- a/Clava-JS/src-api/clava/history/EventListener.ts +++ b/Clava-JS/src-api/clava/history/EventListener.ts @@ -1,7 +1,9 @@ import { EventEmitter } from "events"; import * as fs from "fs"; import Clava from "../Clava.js"; -import { Event } from "./Events.js"; +import { Event, EventTime } from "./Events.js"; +import ophistory from "./History.js"; +import { InsertOperation } from "./Operations.js"; const eventListener = new EventEmitter(); @@ -12,11 +14,51 @@ eventListener.on("storeAST", () => { fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); idx++; }); + eventListener.on("ACTION", (e: Event) => { + + // Event Logs for debugging + + console.log("\nReceived ACTION event"); console.log(e.timing); console.log(e.description); console.log(e.mainJP); console.log(e.returnJP); + console.log(e.inputs); + console.log("\n"); + + switch (e.timing) { + case EventTime.BEFORE: + break; + + case EventTime.AFTER: + switch (e.description){ + case "insertAfter": + case "insertBefore": + if (e.returnJP !== undefined){ + ophistory.newOperation(new InsertOperation(e.returnJP)) + } + break; + default: + break; + } + break; + default: + break; + } + + // Manual testing the rollback + /* + console.log(`Waypoint ${idx}`); + fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); + idx++; + + ophistory.rollback(); + + console.log(`Waypoint ${idx}`); + fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); + idx++; + */ }); export default eventListener; diff --git a/Clava-JS/src-api/clava/history/Operations.ts b/Clava-JS/src-api/clava/history/Operations.ts index 0eedd3412..7381c5c5e 100644 --- a/Clava-JS/src-api/clava/history/Operations.ts +++ b/Clava-JS/src-api/clava/history/Operations.ts @@ -1,4 +1,13 @@ +import { Joinpoint } from "../../Joinpoints.js"; export interface Operation { - undo(): void; + undo(): void; +} + +export class InsertOperation implements Operation { + constructor(private newJP: Joinpoint) {} + + undo(): void { + this.newJP.detach(); + } } \ No newline at end of file From 8a2a0bcccc6097ebd46aa52fe21363b49e21cc9c Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Fri, 19 Jul 2024 17:42:13 +0100 Subject: [PATCH 09/38] test: insertBefore and insertAfter behaviour --- .../src-api/clava/history/EventListener.ts | 3 +- .../src-api/clava/history/History.test.ts | 56 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 Clava-JS/src-api/clava/history/History.test.ts diff --git a/Clava-JS/src-api/clava/history/EventListener.ts b/Clava-JS/src-api/clava/history/EventListener.ts index b3c7548b4..714bd81be 100644 --- a/Clava-JS/src-api/clava/history/EventListener.ts +++ b/Clava-JS/src-api/clava/history/EventListener.ts @@ -18,7 +18,7 @@ eventListener.on("storeAST", () => { eventListener.on("ACTION", (e: Event) => { // Event Logs for debugging - + /* console.log("\nReceived ACTION event"); console.log(e.timing); console.log(e.description); @@ -26,6 +26,7 @@ eventListener.on("ACTION", (e: Event) => { console.log(e.returnJP); console.log(e.inputs); console.log("\n"); + */ switch (e.timing) { case EventTime.BEFORE: diff --git a/Clava-JS/src-api/clava/history/History.test.ts b/Clava-JS/src-api/clava/history/History.test.ts new file mode 100644 index 000000000..51eafb149 --- /dev/null +++ b/Clava-JS/src-api/clava/history/History.test.ts @@ -0,0 +1,56 @@ +import { registerSourceCode } from "lara-js/jest/jestHelpers"; +import Clava from "../../../api/clava/Clava"; +import Query from "lara-js/api/weaver/Query"; +import ophistory from "./History"; +import { Loop } from "../../Joinpoints"; + +const code: string = `void func() { + for (int i = 0; i < 1; i++){ + i++; + } + for (int i = 0; i < 2; i++){ + i++; + } +} + +int main(int argc, char *argv[]) { + func(); + return 0; +} +`; + + +describe("History of Transformations", () => { + registerSourceCode(code); + + it("Initial code, insert before and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + loopStmt?.insertBefore(loopStmt.deepCopy()); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, insert after and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + loopStmt?.insertAfter(loopStmt.deepCopy()); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); +}); + From 98c0f8fe90fe0b85bb42aa6b19c0a4ea6fcf2c74 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Fri, 19 Jul 2024 18:11:52 +0100 Subject: [PATCH 10/38] feat: replaceWith, replaceWithStrings and toComment operations --- .../src-api/clava/history/EventListener.ts | 49 ++++++++++++++++--- Clava-JS/src-api/clava/history/Operations.ts | 12 +++++ 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/Clava-JS/src-api/clava/history/EventListener.ts b/Clava-JS/src-api/clava/history/EventListener.ts index 714bd81be..ea700dd72 100644 --- a/Clava-JS/src-api/clava/history/EventListener.ts +++ b/Clava-JS/src-api/clava/history/EventListener.ts @@ -3,7 +3,8 @@ import * as fs from "fs"; import Clava from "../Clava.js"; import { Event, EventTime } from "./Events.js"; import ophistory from "./History.js"; -import { InsertOperation } from "./Operations.js"; +import { InsertOperation, ReplaceOperation } from "./Operations.js"; +import { Joinpoint } from "../../Joinpoints.js"; const eventListener = new EventEmitter(); @@ -18,7 +19,7 @@ eventListener.on("storeAST", () => { eventListener.on("ACTION", (e: Event) => { // Event Logs for debugging - /* + console.log("\nReceived ACTION event"); console.log(e.timing); console.log(e.description); @@ -26,7 +27,7 @@ eventListener.on("ACTION", (e: Event) => { console.log(e.returnJP); console.log(e.inputs); console.log("\n"); - */ + switch (e.timing) { case EventTime.BEFORE: @@ -36,10 +37,26 @@ eventListener.on("ACTION", (e: Event) => { switch (e.description){ case "insertAfter": case "insertBefore": - if (e.returnJP !== undefined){ - ophistory.newOperation(new InsertOperation(e.returnJP)) + insertOperationFromEvent(e); + break; + case "replaceWith": + if (e.inputs.length > 0){ + if (typeof e.inputs[0] === 'string' || e.inputs[0] instanceof Joinpoint){ + replaceSingleOperationFromEvent(e); + } + else { + replaceMultipleOperationFromEvent(e); + } } break; + case "replaceWithStrings": + if (e.inputs.length > 0){ + replaceMultipleOperationFromEvent(e); + } + break; + case "toComment": + replaceSingleOperationFromEvent(e); + break; default: break; } @@ -49,7 +66,7 @@ eventListener.on("ACTION", (e: Event) => { } // Manual testing the rollback - /* + console.log(`Waypoint ${idx}`); fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); idx++; @@ -59,7 +76,25 @@ eventListener.on("ACTION", (e: Event) => { console.log(`Waypoint ${idx}`); fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); idx++; - */ + }); +function insertOperationFromEvent(e: Event) { + if (e.returnJP !== undefined){ + ophistory.newOperation(new InsertOperation(e.returnJP)) + } +} + +function replaceSingleOperationFromEvent(e: Event) { + if (e.returnJP !== undefined){ + ophistory.newOperation(new ReplaceOperation(e.mainJP, e.returnJP, 1)); + } +} + +function replaceMultipleOperationFromEvent(e: Event) { + if (e.returnJP !== undefined){ + ophistory.newOperation(new ReplaceOperation(e.mainJP, e.returnJP, (e.inputs[0] as (Joinpoint[] | string[])).length)); + } +} + export default eventListener; diff --git a/Clava-JS/src-api/clava/history/Operations.ts b/Clava-JS/src-api/clava/history/Operations.ts index 7381c5c5e..85313a29f 100644 --- a/Clava-JS/src-api/clava/history/Operations.ts +++ b/Clava-JS/src-api/clava/history/Operations.ts @@ -10,4 +10,16 @@ export class InsertOperation implements Operation { undo(): void { this.newJP.detach(); } +} + +export class ReplaceOperation implements Operation { + constructor(private oldJP: Joinpoint, private newJP: Joinpoint, private count: number) {} + + undo(): void { + const siblings: Joinpoint[] = this.newJP.siblingsRight; + for (let i = 0; i < this.count - 1; i++){ + siblings.at(i)?.detach(); + } + this.newJP.replaceWith(this.oldJP); + } } \ No newline at end of file From 4b8673a27e01fb784c371286636391998acbbff1 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Fri, 19 Jul 2024 18:12:59 +0100 Subject: [PATCH 11/38] feat: replaceWith, replaceWithStrings and toComment operations --- Clava-JS/src-api/clava/history/EventListener.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Clava-JS/src-api/clava/history/EventListener.ts b/Clava-JS/src-api/clava/history/EventListener.ts index ea700dd72..b0e51e69c 100644 --- a/Clava-JS/src-api/clava/history/EventListener.ts +++ b/Clava-JS/src-api/clava/history/EventListener.ts @@ -19,7 +19,7 @@ eventListener.on("storeAST", () => { eventListener.on("ACTION", (e: Event) => { // Event Logs for debugging - + /* console.log("\nReceived ACTION event"); console.log(e.timing); console.log(e.description); @@ -27,7 +27,7 @@ eventListener.on("ACTION", (e: Event) => { console.log(e.returnJP); console.log(e.inputs); console.log("\n"); - + */ switch (e.timing) { case EventTime.BEFORE: @@ -66,7 +66,7 @@ eventListener.on("ACTION", (e: Event) => { } // Manual testing the rollback - + /* console.log(`Waypoint ${idx}`); fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); idx++; @@ -76,7 +76,7 @@ eventListener.on("ACTION", (e: Event) => { console.log(`Waypoint ${idx}`); fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); idx++; - + */ }); function insertOperationFromEvent(e: Event) { From c108726409e33ca9c6e23c673acc027d1d15b07a Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Fri, 19 Jul 2024 18:27:32 +0100 Subject: [PATCH 12/38] test: replaceWith with singular string and JoinPoint, replaceWithStrings and toComment behaviour --- .../src-api/clava/history/History.test.ts | 84 ++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/Clava-JS/src-api/clava/history/History.test.ts b/Clava-JS/src-api/clava/history/History.test.ts index 51eafb149..038fe5a0a 100644 --- a/Clava-JS/src-api/clava/history/History.test.ts +++ b/Clava-JS/src-api/clava/history/History.test.ts @@ -2,7 +2,7 @@ import { registerSourceCode } from "lara-js/jest/jestHelpers"; import Clava from "../../../api/clava/Clava"; import Query from "lara-js/api/weaver/Query"; import ophistory from "./History"; -import { Loop } from "../../Joinpoints"; +import { Loop, ReturnStmt } from "../../Joinpoints"; const code: string = `void func() { for (int i = 0; i < 1; i++){ @@ -52,5 +52,87 @@ describe("History of Transformations", () => { expect(a).toEqual(c); expect(b).not.toEqual(c); }); + + it("Initial code, replace singular string and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + loopStmt?.replaceWith("aaaaa"); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, replace singular joinpoint and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + const returnStmt = Query.search(ReturnStmt).first(); + if (returnStmt !== undefined){ + loopStmt?.replaceWith(returnStmt.deepCopy()); + } + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, replace multiple joinpoints and rollback code comparison", () => { + // TODO: fix error regarding Joinpoint[] overload not found + /*const a: string = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + const returnStmt = Query.search(ReturnStmt).first(); + if (returnStmt !== undefined){ + loopStmt?.replaceWith(returnStmt.deepCopy()); + } + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c);*/ + }); + + it("Initial code, replace multiple strings and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + loopStmt?.replaceWithStrings(["aaaa", "bbbb", "cccc"]); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, comment joinpoint and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + loopStmt?.toComment(); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); }); From b2e6f62f25f4c6f4a75cf5bd30b471cae6270d9d Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Fri, 19 Jul 2024 18:48:34 +0100 Subject: [PATCH 13/38] feat: setType operation is implemented --- Clava-JS/src-api/clava/history/EventListener.ts | 15 ++++++++++++--- Clava-JS/src-api/clava/history/Operations.ts | 10 +++++++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/Clava-JS/src-api/clava/history/EventListener.ts b/Clava-JS/src-api/clava/history/EventListener.ts index b0e51e69c..cf936e56e 100644 --- a/Clava-JS/src-api/clava/history/EventListener.ts +++ b/Clava-JS/src-api/clava/history/EventListener.ts @@ -3,7 +3,7 @@ import * as fs from "fs"; import Clava from "../Clava.js"; import { Event, EventTime } from "./Events.js"; import ophistory from "./History.js"; -import { InsertOperation, ReplaceOperation } from "./Operations.js"; +import { InsertOperation, ReplaceOperation, TypeChangeOperation } from "./Operations.js"; import { Joinpoint } from "../../Joinpoints.js"; const eventListener = new EventEmitter(); @@ -31,8 +31,13 @@ eventListener.on("ACTION", (e: Event) => { switch (e.timing) { case EventTime.BEFORE: - break; - + switch (e.description) { + case "setType": + changeTypeFromEvent(e); + break; + default: + break; + } case EventTime.AFTER: switch (e.description){ case "insertAfter": @@ -97,4 +102,8 @@ function replaceMultipleOperationFromEvent(e: Event) { } } +function changeTypeFromEvent(e: Event) { + ophistory.newOperation(new TypeChangeOperation(e.mainJP, e.mainJP.type)) +} + export default eventListener; diff --git a/Clava-JS/src-api/clava/history/Operations.ts b/Clava-JS/src-api/clava/history/Operations.ts index 85313a29f..1b25f0567 100644 --- a/Clava-JS/src-api/clava/history/Operations.ts +++ b/Clava-JS/src-api/clava/history/Operations.ts @@ -1,4 +1,4 @@ -import { Joinpoint } from "../../Joinpoints.js"; +import { Joinpoint, Type } from "../../Joinpoints.js"; export interface Operation { undo(): void; @@ -22,4 +22,12 @@ export class ReplaceOperation implements Operation { } this.newJP.replaceWith(this.oldJP); } +} + +export class TypeChangeOperation implements Operation { + constructor(private jp: Joinpoint, private oldType: Type) {} + + undo(): void { + this.jp.setType(this.oldType); + } } \ No newline at end of file From cf8c41ef531af9c269539a5a09c0af6df6b81bf6 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Fri, 19 Jul 2024 18:49:02 +0100 Subject: [PATCH 14/38] test: setType behaviour --- Clava-JS/src-api/clava/history/History.test.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Clava-JS/src-api/clava/history/History.test.ts b/Clava-JS/src-api/clava/history/History.test.ts index 038fe5a0a..68e426bc4 100644 --- a/Clava-JS/src-api/clava/history/History.test.ts +++ b/Clava-JS/src-api/clava/history/History.test.ts @@ -2,7 +2,8 @@ import { registerSourceCode } from "lara-js/jest/jestHelpers"; import Clava from "../../../api/clava/Clava"; import Query from "lara-js/api/weaver/Query"; import ophistory from "./History"; -import { Loop, ReturnStmt } from "../../Joinpoints"; +import { Loop, ReturnStmt, Vardecl } from "../../Joinpoints"; +import ClavaJoinPoints from "../../../api/clava/ClavaJoinPoints"; const code: string = `void func() { for (int i = 0; i < 1; i++){ @@ -134,5 +135,20 @@ describe("History of Transformations", () => { expect(a).toEqual(c); expect(b).not.toEqual(c); }); + + it("Change type and rollback comparison", () => { + const a: string = Clava.getProgram().code; + + const vd = Query.search(Vardecl).first(); + vd?.setType(ClavaJoinPoints.type("test")); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(a).not.toEqual(b); + }); }); From 12e1b0eea2d7dc84a3116662d0621595efa7e071 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Sat, 20 Jul 2024 14:39:45 +0100 Subject: [PATCH 15/38] feat: setFirstChild and setLastChild operations implemented --- .../src-api/clava/history/EventListener.ts | 24 ++++++++++++++++++- Clava-JS/src-api/clava/history/Operations.ts | 13 ++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Clava-JS/src-api/clava/history/EventListener.ts b/Clava-JS/src-api/clava/history/EventListener.ts index cf936e56e..5d3e390a6 100644 --- a/Clava-JS/src-api/clava/history/EventListener.ts +++ b/Clava-JS/src-api/clava/history/EventListener.ts @@ -3,12 +3,13 @@ import * as fs from "fs"; import Clava from "../Clava.js"; import { Event, EventTime } from "./Events.js"; import ophistory from "./History.js"; -import { InsertOperation, ReplaceOperation, TypeChangeOperation } from "./Operations.js"; +import { InsertOperation, ReplaceOperation, SetChildOperation, TypeChangeOperation } from "./Operations.js"; import { Joinpoint } from "../../Joinpoints.js"; const eventListener = new EventEmitter(); let idx = 0; +let auxJP: Joinpoint; eventListener.on("storeAST", () => { console.log(`Waypoint ${idx}`); @@ -35,9 +36,16 @@ eventListener.on("ACTION", (e: Event) => { case "setType": changeTypeFromEvent(e); break; + case "setFirstChild": + auxJP = e.mainJP.firstChild; + break; + case "setLastChild": + auxJP = e.mainJP.lastChild; + break; default: break; } + break; case EventTime.AFTER: switch (e.description){ case "insertAfter": @@ -62,6 +70,12 @@ eventListener.on("ACTION", (e: Event) => { case "toComment": replaceSingleOperationFromEvent(e); break; + case "setFirstChild": + setFirstChildFromEvent(e, auxJP); + break; + case "setLastChild": + setLastChildFromEvent(e, auxJP); + break; default: break; } @@ -102,6 +116,14 @@ function replaceMultipleOperationFromEvent(e: Event) { } } +function setFirstChildFromEvent(e: Event, aux: Joinpoint) { + ophistory.newOperation(new SetChildOperation(e.mainJP.firstChild, aux)); +} + +function setLastChildFromEvent(e: Event, aux: Joinpoint) { + ophistory.newOperation(new SetChildOperation(e.mainJP.lastChild, aux)); +} + function changeTypeFromEvent(e: Event) { ophistory.newOperation(new TypeChangeOperation(e.mainJP, e.mainJP.type)) } diff --git a/Clava-JS/src-api/clava/history/Operations.ts b/Clava-JS/src-api/clava/history/Operations.ts index 1b25f0567..63eef25d9 100644 --- a/Clava-JS/src-api/clava/history/Operations.ts +++ b/Clava-JS/src-api/clava/history/Operations.ts @@ -24,6 +24,19 @@ export class ReplaceOperation implements Operation { } } +export class SetChildOperation implements Operation { + constructor(private newChildJP: Joinpoint, private oldChildJP?: Joinpoint) {} + + undo(): void { + if (this.oldChildJP){ + this.newChildJP.replaceWith(this.oldChildJP); + } + else { + this.newChildJP.detach(); + } + } +} + export class TypeChangeOperation implements Operation { constructor(private jp: Joinpoint, private oldType: Type) {} From 19a9d886998a0f988cf83ab7e648d34a91505bf5 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Sat, 20 Jul 2024 14:40:17 +0100 Subject: [PATCH 16/38] test: setFirstChild and setLastChild replace/set behaviour --- .../src-api/clava/history/History.test.ts | 76 ++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/Clava-JS/src-api/clava/history/History.test.ts b/Clava-JS/src-api/clava/history/History.test.ts index 68e426bc4..2a6237b64 100644 --- a/Clava-JS/src-api/clava/history/History.test.ts +++ b/Clava-JS/src-api/clava/history/History.test.ts @@ -2,7 +2,7 @@ import { registerSourceCode } from "lara-js/jest/jestHelpers"; import Clava from "../../../api/clava/Clava"; import Query from "lara-js/api/weaver/Query"; import ophistory from "./History"; -import { Loop, ReturnStmt, Vardecl } from "../../Joinpoints"; +import { FunctionJp, Loop, ReturnStmt, Vardecl } from "../../Joinpoints"; import ClavaJoinPoints from "../../../api/clava/ClavaJoinPoints"; const code: string = `void func() { @@ -14,6 +14,8 @@ const code: string = `void func() { } } +void test() {} + int main(int argc, char *argv[]) { func(); return 0; @@ -136,6 +138,78 @@ describe("History of Transformations", () => { expect(b).not.toEqual(c); }); + it("Initial code, replace first child and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const func = Query.search(FunctionJp).first(); + const returnStmt = Query.search(ReturnStmt).first(); + if (returnStmt !== undefined){ + func?.body.setFirstChild(returnStmt); + } + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, set first child and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const testFunc = Query.search(FunctionJp).get().at(1); + const returnStmt = Query.search(ReturnStmt).first(); + if (returnStmt !== undefined){ + testFunc?.body.setFirstChild(returnStmt); + } + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, replace last child and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const func = Query.search(FunctionJp).first(); + const returnStmt = Query.search(ReturnStmt).first(); + if (returnStmt !== undefined){ + func?.body.setLastChild(returnStmt); + } + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, set first child and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const testFunc = Query.search(FunctionJp).get().at(1); + const returnStmt = Query.search(ReturnStmt).first(); + if (returnStmt !== undefined){ + testFunc?.body.setLastChild(returnStmt); + } + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + it("Change type and rollback comparison", () => { const a: string = Clava.getProgram().code; From c46da777afcc592fb635e3d9dbe73abb731bd2fc Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Sat, 20 Jul 2024 14:54:49 +0100 Subject: [PATCH 17/38] feat: removeChildren operation implemented --- .../src-api/clava/history/EventListener.ts | 31 ++++++++++++------- Clava-JS/src-api/clava/history/Operations.ts | 18 +++++++++++ 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/Clava-JS/src-api/clava/history/EventListener.ts b/Clava-JS/src-api/clava/history/EventListener.ts index 5d3e390a6..531413a0f 100644 --- a/Clava-JS/src-api/clava/history/EventListener.ts +++ b/Clava-JS/src-api/clava/history/EventListener.ts @@ -3,7 +3,7 @@ import * as fs from "fs"; import Clava from "../Clava.js"; import { Event, EventTime } from "./Events.js"; import ophistory from "./History.js"; -import { InsertOperation, ReplaceOperation, SetChildOperation, TypeChangeOperation } from "./Operations.js"; +import { InsertOperation, RemoveChildrenOperation, ReplaceOperation, SetChildOperation, TypeChangeOperation } from "./Operations.js"; import { Joinpoint } from "../../Joinpoints.js"; const eventListener = new EventEmitter(); @@ -33,6 +33,9 @@ eventListener.on("ACTION", (e: Event) => { switch (e.timing) { case EventTime.BEFORE: switch (e.description) { + case "removeChildren": + removeChildrenOperationFromEvent(e); + break; case "setType": changeTypeFromEvent(e); break; @@ -86,15 +89,17 @@ eventListener.on("ACTION", (e: Event) => { // Manual testing the rollback /* - console.log(`Waypoint ${idx}`); - fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); - idx++; - - ophistory.rollback(); - - console.log(`Waypoint ${idx}`); - fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); - idx++; + if (e.description === "removeChildren" && e.timing === EventTime.AFTER) { + console.log(`Waypoint ${idx}`); + fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); + idx++; + + ophistory.rollback(); + + console.log(`Waypoint ${idx}`); + fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); + idx++; + } */ }); @@ -124,8 +129,12 @@ function setLastChildFromEvent(e: Event, aux: Joinpoint) { ophistory.newOperation(new SetChildOperation(e.mainJP.lastChild, aux)); } +function removeChildrenOperationFromEvent(e: Event) { + ophistory.newOperation(new RemoveChildrenOperation(e.mainJP, e.mainJP.children)); +} + function changeTypeFromEvent(e: Event) { - ophistory.newOperation(new TypeChangeOperation(e.mainJP, e.mainJP.type)) + ophistory.newOperation(new TypeChangeOperation(e.mainJP, e.mainJP.type)); } export default eventListener; diff --git a/Clava-JS/src-api/clava/history/Operations.ts b/Clava-JS/src-api/clava/history/Operations.ts index 63eef25d9..58f1c8b81 100644 --- a/Clava-JS/src-api/clava/history/Operations.ts +++ b/Clava-JS/src-api/clava/history/Operations.ts @@ -37,6 +37,24 @@ export class SetChildOperation implements Operation { } } +export class RemoveChildrenOperation implements Operation { + constructor(private parentJP: Joinpoint, private childrenJPs: Joinpoint[]) {} + + undo(): void { + if (this.childrenJPs.length > 0) { + if (this.childrenJPs.at(0)){ + this.parentJP.setFirstChild(this.childrenJPs.at(0) as Joinpoint); + let prev = this.parentJP.firstChild; + for (let i = 1; i < this.childrenJPs.length; i++) { + if (i < this.childrenJPs.length && this.childrenJPs.at(i)) { + prev = prev.insertAfter(this.childrenJPs.at(i) as Joinpoint); + } + } + } + } + } +} + export class TypeChangeOperation implements Operation { constructor(private jp: Joinpoint, private oldType: Type) {} From d4242ac770e228b6c86df7b299bc80b308f1b4bc Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Sat, 20 Jul 2024 14:55:06 +0100 Subject: [PATCH 18/38] test: removeChildren behaviour --- Clava-JS/src-api/clava/history/History.test.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Clava-JS/src-api/clava/history/History.test.ts b/Clava-JS/src-api/clava/history/History.test.ts index 2a6237b64..cb720bf56 100644 --- a/Clava-JS/src-api/clava/history/History.test.ts +++ b/Clava-JS/src-api/clava/history/History.test.ts @@ -192,7 +192,7 @@ describe("History of Transformations", () => { expect(b).not.toEqual(c); }); - it("Initial code, set first child and rollback code comparison", () => { + it("Initial code, set last child and rollback code comparison", () => { const a: string = Clava.getProgram().code; const testFunc = Query.search(FunctionJp).get().at(1); @@ -210,6 +210,21 @@ describe("History of Transformations", () => { expect(b).not.toEqual(c); }); + it("Initial code, remove children and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const func = Query.search(FunctionJp).first(); + func?.body.removeChildren(); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + it("Change type and rollback comparison", () => { const a: string = Clava.getProgram().code; From 15689ee508f0f5d8dd2abe50b40a23f6a5339f95 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Sat, 20 Jul 2024 15:10:50 +0100 Subject: [PATCH 19/38] feat: setInlineComments operation implemented --- Clava-JS/src-api/clava/history/EventListener.ts | 17 +++++++++++++++-- Clava-JS/src-api/clava/history/Operations.ts | 13 +++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Clava-JS/src-api/clava/history/EventListener.ts b/Clava-JS/src-api/clava/history/EventListener.ts index 531413a0f..2faec8191 100644 --- a/Clava-JS/src-api/clava/history/EventListener.ts +++ b/Clava-JS/src-api/clava/history/EventListener.ts @@ -3,12 +3,15 @@ import * as fs from "fs"; import Clava from "../Clava.js"; import { Event, EventTime } from "./Events.js"; import ophistory from "./History.js"; -import { InsertOperation, RemoveChildrenOperation, ReplaceOperation, SetChildOperation, TypeChangeOperation } from "./Operations.js"; +import { InlineCommentOperation, InsertOperation, RemoveChildrenOperation, ReplaceOperation, SetChildOperation, TypeChangeOperation } from "./Operations.js"; import { Joinpoint } from "../../Joinpoints.js"; const eventListener = new EventEmitter(); +// Used for counting number of waypoints let idx = 0; + +// Used for saving previous child in setFirstChild and setLastChild let auxJP: Joinpoint; eventListener.on("storeAST", () => { @@ -45,6 +48,9 @@ eventListener.on("ACTION", (e: Event) => { case "setLastChild": auxJP = e.mainJP.lastChild; break; + case "setInlineComments": + inlineCommentOperationFromEvent(e); + break; default: break; } @@ -89,7 +95,7 @@ eventListener.on("ACTION", (e: Event) => { // Manual testing the rollback /* - if (e.description === "removeChildren" && e.timing === EventTime.AFTER) { + if (e.description === "setInlineComments" && e.timing === EventTime.AFTER) { console.log(`Waypoint ${idx}`); fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); idx++; @@ -137,4 +143,11 @@ function changeTypeFromEvent(e: Event) { ophistory.newOperation(new TypeChangeOperation(e.mainJP, e.mainJP.type)); } +function inlineCommentOperationFromEvent(e: Event) { + const comments = e.mainJP.inlineComments + .map((comment) => comment.text) + .filter((comment): comment is string => comment !== null); + ophistory.newOperation(new InlineCommentOperation(e.mainJP, comments)); +} + export default eventListener; diff --git a/Clava-JS/src-api/clava/history/Operations.ts b/Clava-JS/src-api/clava/history/Operations.ts index 58f1c8b81..0c5c20c7f 100644 --- a/Clava-JS/src-api/clava/history/Operations.ts +++ b/Clava-JS/src-api/clava/history/Operations.ts @@ -61,4 +61,17 @@ export class TypeChangeOperation implements Operation { undo(): void { this.jp.setType(this.oldType); } +} + +export class InlineCommentOperation implements Operation { + constructor(private jp: Joinpoint, private oldComments: string[]) {} + + undo(): void { + if (this.oldComments.length === 0) { + this.jp.setInlineComments(""); + } + else { + this.jp.setInlineComments(this.oldComments); + } + } } \ No newline at end of file From b00b8729696670b6d02a0c621d9b6d4289791819 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Sat, 20 Jul 2024 15:11:07 +0100 Subject: [PATCH 20/38] test: setInlineComments behaviour --- .../src-api/clava/history/History.test.ts | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/Clava-JS/src-api/clava/history/History.test.ts b/Clava-JS/src-api/clava/history/History.test.ts index cb720bf56..65c39ebcb 100644 --- a/Clava-JS/src-api/clava/history/History.test.ts +++ b/Clava-JS/src-api/clava/history/History.test.ts @@ -239,5 +239,77 @@ describe("History of Transformations", () => { expect(a).toEqual(c); expect(a).not.toEqual(b); }); + + it("Initial code, set inline comment and rollback code comparison", () => { + const a = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + loopStmt?.setInlineComments("aaaaa"); + + const b = Clava.getProgram().code; + + ophistory.rollback(); + const c = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, set inline comments and rollback code comparison", () => { + const a = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + loopStmt?.setInlineComments(["aaaaa", "bbbbb"]); + + const b = Clava.getProgram().code; + + ophistory.rollback(); + const c = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, set inline comments and rollback code comparison", () => { + const a = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + + loopStmt?.setInlineComments(["aaaaa", "bbbbb"]); + const b = Clava.getProgram().code; + + loopStmt?.setInlineComments([""]); + const c = Clava.getProgram().code; + + loopStmt?.setInlineComments("ccccc"); + const d = Clava.getProgram().code; + + loopStmt?.setInlineComments(""); + const e = Clava.getProgram().code; + + ophistory.rollback(); + const f = Clava.getProgram().code; + + ophistory.rollback(); + const g = Clava.getProgram().code; + + ophistory.rollback(); + const h = Clava.getProgram().code; + + ophistory.rollback(); + const i = Clava.getProgram().code; + + expect(a).toEqual(i); + expect(a).toEqual(e); + expect(b).toEqual(h); + expect(c).toEqual(g); + expect(d).toEqual(f); + expect(a).not.toEqual(b); + expect(a).not.toEqual(c); + expect(a).not.toEqual(d); + expect(b).not.toEqual(c); + expect(b).not.toEqual(d); + expect(c).not.toEqual(d); + }); }); From e12f3d377647e33ef53cdab1b32de743991eee10 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Sat, 20 Jul 2024 16:45:50 +0100 Subject: [PATCH 21/38] feat: detach operation implemented --- .../src-api/clava/history/EventListener.ts | 26 +++++++++++++++++-- Clava-JS/src-api/clava/history/Operations.ts | 22 ++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/Clava-JS/src-api/clava/history/EventListener.ts b/Clava-JS/src-api/clava/history/EventListener.ts index 2faec8191..c099a8e3e 100644 --- a/Clava-JS/src-api/clava/history/EventListener.ts +++ b/Clava-JS/src-api/clava/history/EventListener.ts @@ -3,7 +3,7 @@ import * as fs from "fs"; import Clava from "../Clava.js"; import { Event, EventTime } from "./Events.js"; import ophistory from "./History.js"; -import { InlineCommentOperation, InsertOperation, RemoveChildrenOperation, ReplaceOperation, SetChildOperation, TypeChangeOperation } from "./Operations.js"; +import { DetachOperation, DetachReference, InlineCommentOperation, InsertOperation, RemoveChildrenOperation, ReplaceOperation, SetChildOperation, TypeChangeOperation } from "./Operations.js"; import { Joinpoint } from "../../Joinpoints.js"; const eventListener = new EventEmitter(); @@ -14,6 +14,10 @@ let idx = 0; // Used for saving previous child in setFirstChild and setLastChild let auxJP: Joinpoint; +// Used for saving reference JP in detach +let refJP: Joinpoint; +let ref: string; + eventListener.on("storeAST", () => { console.log(`Waypoint ${idx}`); fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); @@ -36,6 +40,9 @@ eventListener.on("ACTION", (e: Event) => { switch (e.timing) { case EventTime.BEFORE: switch (e.description) { + case "detach": + detachOperationFromEvent(e); + break; case "removeChildren": removeChildrenOperationFromEvent(e); break; @@ -95,7 +102,7 @@ eventListener.on("ACTION", (e: Event) => { // Manual testing the rollback /* - if (e.description === "setInlineComments" && e.timing === EventTime.AFTER) { + if (e.description === "detach" && e.timing === EventTime.AFTER) { console.log(`Waypoint ${idx}`); fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); idx++; @@ -127,6 +134,21 @@ function replaceMultipleOperationFromEvent(e: Event) { } } +function detachOperationFromEvent(e: Event) { + let refJP: Joinpoint, ref: DetachReference; + if (e.mainJP.siblingsLeft.length >= 1){ + refJP = e.mainJP.leftJp; + ref = DetachReference.LEFT; + } else if (e.mainJP.siblingsRight.length >= 1) { + refJP = e.mainJP.rightJp; + ref = DetachReference.RIGHT; + } else { + refJP = e.mainJP.parent; + ref = DetachReference.TOP; + } + ophistory.newOperation(new DetachOperation(e.mainJP, refJP, ref)); +} + function setFirstChildFromEvent(e: Event, aux: Joinpoint) { ophistory.newOperation(new SetChildOperation(e.mainJP.firstChild, aux)); } diff --git a/Clava-JS/src-api/clava/history/Operations.ts b/Clava-JS/src-api/clava/history/Operations.ts index 0c5c20c7f..5061cdcef 100644 --- a/Clava-JS/src-api/clava/history/Operations.ts +++ b/Clava-JS/src-api/clava/history/Operations.ts @@ -24,6 +24,28 @@ export class ReplaceOperation implements Operation { } } +export enum DetachReference { + LEFT = "Left", + RIGHT = "Right", + TOP = "Top" +} + +export class DetachOperation implements Operation { + constructor(private mainJP: Joinpoint, private refJP: Joinpoint, private ref: string) {} + + undo(): void { + if (this.ref === DetachReference.LEFT){ + this.refJP.insertAfter(this.mainJP) + } + else if (this.ref === DetachReference.RIGHT){ + this.refJP.insertBefore(this.mainJP); + } + else { + this.refJP.setFirstChild(this.mainJP); + } + } +} + export class SetChildOperation implements Operation { constructor(private newChildJP: Joinpoint, private oldChildJP?: Joinpoint) {} From c061a99a3b88a38fd4bcb954e25def33b87b9faa Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Sat, 20 Jul 2024 16:46:07 +0100 Subject: [PATCH 22/38] test: detach behaviour --- .../src-api/clava/history/History.test.ts | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/Clava-JS/src-api/clava/history/History.test.ts b/Clava-JS/src-api/clava/history/History.test.ts index 65c39ebcb..dcc90e89f 100644 --- a/Clava-JS/src-api/clava/history/History.test.ts +++ b/Clava-JS/src-api/clava/history/History.test.ts @@ -2,7 +2,7 @@ import { registerSourceCode } from "lara-js/jest/jestHelpers"; import Clava from "../../../api/clava/Clava"; import Query from "lara-js/api/weaver/Query"; import ophistory from "./History"; -import { FunctionJp, Loop, ReturnStmt, Vardecl } from "../../Joinpoints"; +import { FunctionJp, Joinpoint, Loop, ReturnStmt, Vardecl } from "../../Joinpoints"; import ClavaJoinPoints from "../../../api/clava/ClavaJoinPoints"; const code: string = `void func() { @@ -22,7 +22,6 @@ int main(int argc, char *argv[]) { } `; - describe("History of Transformations", () => { registerSourceCode(code); @@ -138,6 +137,51 @@ describe("History of Transformations", () => { expect(b).not.toEqual(c); }); + it("Initial code, detach first child and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const func = Query.search(FunctionJp).first(); + func?.body.firstChild.detach(); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, detach only child and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const func = Query.search(FunctionJp).first(); + func?.body.detach(); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, detach last child and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const func = Query.search(FunctionJp).first(); + func?.body.lastChild.detach(); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + it("Initial code, replace first child and rollback code comparison", () => { const a: string = Clava.getProgram().code; From 08cd0de611ee029666047bf11adc0659fd33ef6a Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Mon, 22 Jul 2024 15:10:06 +0100 Subject: [PATCH 23/38] feat: rollback now receives an optional number of operations to undo (if possible) --- Clava-JS/src-api/clava/history/EventListener.ts | 6 ------ Clava-JS/src-api/clava/history/History.ts | 16 ++++++++++------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Clava-JS/src-api/clava/history/EventListener.ts b/Clava-JS/src-api/clava/history/EventListener.ts index c099a8e3e..ef35082f0 100644 --- a/Clava-JS/src-api/clava/history/EventListener.ts +++ b/Clava-JS/src-api/clava/history/EventListener.ts @@ -14,10 +14,6 @@ let idx = 0; // Used for saving previous child in setFirstChild and setLastChild let auxJP: Joinpoint; -// Used for saving reference JP in detach -let refJP: Joinpoint; -let ref: string; - eventListener.on("storeAST", () => { console.log(`Waypoint ${idx}`); fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); @@ -96,8 +92,6 @@ eventListener.on("ACTION", (e: Event) => { break; } break; - default: - break; } // Manual testing the rollback diff --git a/Clava-JS/src-api/clava/history/History.ts b/Clava-JS/src-api/clava/history/History.ts index 463c3c57e..172c135cc 100644 --- a/Clava-JS/src-api/clava/history/History.ts +++ b/Clava-JS/src-api/clava/history/History.ts @@ -23,17 +23,21 @@ class OperationHistory { } } - rollback() { - const op = this.operations.pop(); - if (op !== undefined) { - try { + rollback(n: number = 1) { + if (n > 0){ + while (n--){ + const op = this.operations.pop(); + if (op !== undefined) { + try { this.lock(); op.undo(); - } catch (error) { + } catch (error) { console.error("Failed to undo operation:", error); - } finally { + } finally { this.unlock(); + } } + } } } } From 133a0c227ffb43a66b0fc2cbb2d51476eabc0215 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Mon, 22 Jul 2024 16:27:16 +0100 Subject: [PATCH 24/38] test: more complex tests focused on the History --- .../src-api/clava/history/EventListener.ts | 52 ++- Clava-JS/src-api/clava/history/Events.ts | 10 +- .../src-api/clava/history/History.test.ts | 352 +++-------------- .../src-api/clava/history/Operations.test.ts | 359 ++++++++++++++++++ 4 files changed, 449 insertions(+), 324 deletions(-) create mode 100644 Clava-JS/src-api/clava/history/Operations.test.ts diff --git a/Clava-JS/src-api/clava/history/EventListener.ts b/Clava-JS/src-api/clava/history/EventListener.ts index ef35082f0..b1e8dc7db 100644 --- a/Clava-JS/src-api/clava/history/EventListener.ts +++ b/Clava-JS/src-api/clava/history/EventListener.ts @@ -3,7 +3,16 @@ import * as fs from "fs"; import Clava from "../Clava.js"; import { Event, EventTime } from "./Events.js"; import ophistory from "./History.js"; -import { DetachOperation, DetachReference, InlineCommentOperation, InsertOperation, RemoveChildrenOperation, ReplaceOperation, SetChildOperation, TypeChangeOperation } from "./Operations.js"; +import { + DetachOperation, + DetachReference, + InlineCommentOperation, + InsertOperation, + RemoveChildrenOperation, + ReplaceOperation, + SetChildOperation, + TypeChangeOperation, +} from "./Operations.js"; import { Joinpoint } from "../../Joinpoints.js"; const eventListener = new EventEmitter(); @@ -21,7 +30,6 @@ eventListener.on("storeAST", () => { }); eventListener.on("ACTION", (e: Event) => { - // Event Logs for debugging /* console.log("\nReceived ACTION event"); @@ -59,23 +67,25 @@ eventListener.on("ACTION", (e: Event) => { } break; case EventTime.AFTER: - switch (e.description){ + switch (e.description) { case "insertAfter": case "insertBefore": insertOperationFromEvent(e); break; case "replaceWith": - if (e.inputs.length > 0){ - if (typeof e.inputs[0] === 'string' || e.inputs[0] instanceof Joinpoint){ + if (e.inputs.length > 0) { + if ( + typeof e.inputs[0] === "string" || + e.inputs[0] instanceof Joinpoint + ) { replaceSingleOperationFromEvent(e); - } - else { + } else { replaceMultipleOperationFromEvent(e); } } break; case "replaceWithStrings": - if (e.inputs.length > 0){ + if (e.inputs.length > 0) { replaceMultipleOperationFromEvent(e); } break; @@ -111,29 +121,35 @@ eventListener.on("ACTION", (e: Event) => { }); function insertOperationFromEvent(e: Event) { - if (e.returnJP !== undefined){ - ophistory.newOperation(new InsertOperation(e.returnJP)) + if (e.returnValue !== undefined) { + ophistory.newOperation(new InsertOperation(e.returnValue)); } } function replaceSingleOperationFromEvent(e: Event) { - if (e.returnJP !== undefined){ - ophistory.newOperation(new ReplaceOperation(e.mainJP, e.returnJP, 1)); + if (e.returnValue !== undefined) { + ophistory.newOperation(new ReplaceOperation(e.mainJP, e.returnValue, 1)); } } function replaceMultipleOperationFromEvent(e: Event) { - if (e.returnJP !== undefined){ - ophistory.newOperation(new ReplaceOperation(e.mainJP, e.returnJP, (e.inputs[0] as (Joinpoint[] | string[])).length)); + if (e.returnValue !== undefined) { + ophistory.newOperation( + new ReplaceOperation( + e.mainJP, + e.returnValue, + (e.inputs[0] as Joinpoint[] | string[]).length + ) + ); } } function detachOperationFromEvent(e: Event) { let refJP: Joinpoint, ref: DetachReference; - if (e.mainJP.siblingsLeft.length >= 1){ + if (e.mainJP.siblingsLeft.length >= 1) { refJP = e.mainJP.leftJp; ref = DetachReference.LEFT; - } else if (e.mainJP.siblingsRight.length >= 1) { + } else if (e.mainJP.siblingsRight.length >= 1) { refJP = e.mainJP.rightJp; ref = DetachReference.RIGHT; } else { @@ -152,7 +168,9 @@ function setLastChildFromEvent(e: Event, aux: Joinpoint) { } function removeChildrenOperationFromEvent(e: Event) { - ophistory.newOperation(new RemoveChildrenOperation(e.mainJP, e.mainJP.children)); + ophistory.newOperation( + new RemoveChildrenOperation(e.mainJP, e.mainJP.children) + ); } function changeTypeFromEvent(e: Event) { diff --git a/Clava-JS/src-api/clava/history/Events.ts b/Clava-JS/src-api/clava/history/Events.ts index 879d56805..494f77208 100644 --- a/Clava-JS/src-api/clava/history/Events.ts +++ b/Clava-JS/src-api/clava/history/Events.ts @@ -1,15 +1,15 @@ import { Joinpoint } from "../../Joinpoints.js"; export enum EventTime { - BEFORE = "Before", - AFTER = "After" + BEFORE = "Before", + AFTER = "After", } export class Event { public timing: EventTime; public description: string; public mainJP: Joinpoint; - public returnJP?: Joinpoint; + public returnValue?: Joinpoint; public inputs: unknown[]; constructor( @@ -22,7 +22,7 @@ export class Event { this.timing = timing; this.description = description; this.mainJP = mainJP; - this.returnJP = returnJP; + this.returnValue = returnJP; this.inputs = inputs; } -} \ No newline at end of file +} diff --git a/Clava-JS/src-api/clava/history/History.test.ts b/Clava-JS/src-api/clava/history/History.test.ts index dcc90e89f..d488e8c34 100644 --- a/Clava-JS/src-api/clava/history/History.test.ts +++ b/Clava-JS/src-api/clava/history/History.test.ts @@ -1,9 +1,10 @@ import { registerSourceCode } from "lara-js/jest/jestHelpers"; -import Clava from "../../../api/clava/Clava"; +import Clava from "../Clava"; +import { FunctionJp, Joinpoint, Loop, ReturnStmt } from "../../Joinpoints"; import Query from "lara-js/api/weaver/Query"; import ophistory from "./History"; -import { FunctionJp, Joinpoint, Loop, ReturnStmt, Vardecl } from "../../Joinpoints"; -import ClavaJoinPoints from "../../../api/clava/ClavaJoinPoints"; +import {jest} from '@jest/globals' + const code: string = `void func() { for (int i = 0; i < 1; i++){ @@ -22,338 +23,85 @@ int main(int argc, char *argv[]) { } `; -describe("History of Transformations", () => { +describe("Transformation History: Multiple operations", () => { registerSourceCode(code); - it("Initial code, insert before and rollback code comparison", () => { + it("Inserts and detaches code comparison", () => { const a: string = Clava.getProgram().code; - const loopStmt = Query.search(Loop).get().at(0); - loopStmt?.insertBefore(loopStmt.deepCopy()); + const loopStmt1 = Query.search(Loop).get().at(0) as Joinpoint; + const loopStmt2 = Query.search(Loop).get().at(1) as Joinpoint; + loopStmt1.insertBefore(loopStmt2.deepCopy()); + loopStmt2.insertAfter(loopStmt1.deepCopy()); + + loopStmt1.detach(); + loopStmt2.detach(); const b: string = Clava.getProgram().code; - - ophistory.rollback(); + + ophistory.rollback(4); const c: string = Clava.getProgram().code; expect(a).toEqual(c); expect(b).not.toEqual(c); }); - it("Initial code, insert after and rollback code comparison", () => { + it("Replaces and detach code comparison", () => { const a: string = Clava.getProgram().code; - const loopStmt = Query.search(Loop).get().at(0); - loopStmt?.insertAfter(loopStmt.deepCopy()); - - const b: string = Clava.getProgram().code; + const loopStmt1 = Query.search(Loop).get().at(0) as Joinpoint; + const returnStmt = Query.search(ReturnStmt).get().at(0) as Joinpoint; + + let cur = loopStmt1.replaceWith(returnStmt.deepCopy()); + cur = cur.replaceWith("aaaaa"); + cur = cur.replaceWithStrings(["aaaaa", "bbbbb", "ccccc"]); + cur = cur.toComment(); + cur.detach(); - ophistory.rollback(); - const c: string = Clava.getProgram().code; - - expect(a).toEqual(c); - expect(b).not.toEqual(c); - }); - - it("Initial code, replace singular string and rollback code comparison", () => { - const a: string = Clava.getProgram().code; - - const loopStmt = Query.search(Loop).get().at(0); - loopStmt?.replaceWith("aaaaa"); - - const b: string = Clava.getProgram().code; - - ophistory.rollback(); - const c: string = Clava.getProgram().code; - - expect(a).toEqual(c); - expect(b).not.toEqual(c); - }); - - it("Initial code, replace singular joinpoint and rollback code comparison", () => { - const a: string = Clava.getProgram().code; - - const loopStmt = Query.search(Loop).get().at(0); - const returnStmt = Query.search(ReturnStmt).first(); - if (returnStmt !== undefined){ - loopStmt?.replaceWith(returnStmt.deepCopy()); - } - - const b: string = Clava.getProgram().code; - - ophistory.rollback(); - const c: string = Clava.getProgram().code; - - expect(a).toEqual(c); - expect(b).not.toEqual(c); - }); - - it("Initial code, replace multiple joinpoints and rollback code comparison", () => { - // TODO: fix error regarding Joinpoint[] overload not found - /*const a: string = Clava.getProgram().code; - - const loopStmt = Query.search(Loop).get().at(0); - const returnStmt = Query.search(ReturnStmt).first(); - if (returnStmt !== undefined){ - loopStmt?.replaceWith(returnStmt.deepCopy()); - } - - const b: string = Clava.getProgram().code; - - ophistory.rollback(); - const c: string = Clava.getProgram().code; - - expect(a).toEqual(c); - expect(b).not.toEqual(c);*/ - }); - - it("Initial code, replace multiple strings and rollback code comparison", () => { - const a: string = Clava.getProgram().code; - - const loopStmt = Query.search(Loop).get().at(0); - loopStmt?.replaceWithStrings(["aaaa", "bbbb", "cccc"]); - - const b: string = Clava.getProgram().code; - - ophistory.rollback(); - const c: string = Clava.getProgram().code; - - expect(a).toEqual(c); - expect(b).not.toEqual(c); - }); - - it("Initial code, comment joinpoint and rollback code comparison", () => { - const a: string = Clava.getProgram().code; - - const loopStmt = Query.search(Loop).get().at(0); - loopStmt?.toComment(); - - const b: string = Clava.getProgram().code; - - ophistory.rollback(); - const c: string = Clava.getProgram().code; - - expect(a).toEqual(c); - expect(b).not.toEqual(c); - }); - - it("Initial code, detach first child and rollback code comparison", () => { - const a: string = Clava.getProgram().code; - - const func = Query.search(FunctionJp).first(); - func?.body.firstChild.detach(); - - const b: string = Clava.getProgram().code; - - ophistory.rollback(); - const c: string = Clava.getProgram().code; - - expect(a).toEqual(c); - expect(b).not.toEqual(c); - }); - - it("Initial code, detach only child and rollback code comparison", () => { - const a: string = Clava.getProgram().code; - - const func = Query.search(FunctionJp).first(); - func?.body.detach(); - - const b: string = Clava.getProgram().code; - - ophistory.rollback(); - const c: string = Clava.getProgram().code; - - expect(a).toEqual(c); - expect(b).not.toEqual(c); - }); - - it("Initial code, detach last child and rollback code comparison", () => { - const a: string = Clava.getProgram().code; - - const func = Query.search(FunctionJp).first(); - func?.body.lastChild.detach(); - - const b: string = Clava.getProgram().code; - - ophistory.rollback(); - const c: string = Clava.getProgram().code; - - expect(a).toEqual(c); - expect(b).not.toEqual(c); - }); - - it("Initial code, replace first child and rollback code comparison", () => { - const a: string = Clava.getProgram().code; - - const func = Query.search(FunctionJp).first(); - const returnStmt = Query.search(ReturnStmt).first(); - if (returnStmt !== undefined){ - func?.body.setFirstChild(returnStmt); - } - const b: string = Clava.getProgram().code; - - ophistory.rollback(); - const c: string = Clava.getProgram().code; - - expect(a).toEqual(c); - expect(b).not.toEqual(c); - }); - it("Initial code, set first child and rollback code comparison", () => { - const a: string = Clava.getProgram().code; - - const testFunc = Query.search(FunctionJp).get().at(1); - const returnStmt = Query.search(ReturnStmt).first(); - if (returnStmt !== undefined){ - testFunc?.body.setFirstChild(returnStmt); - } - - const b: string = Clava.getProgram().code; - - ophistory.rollback(); + ophistory.rollback(5); const c: string = Clava.getProgram().code; - + expect(a).toEqual(c); expect(b).not.toEqual(c); }); - it("Initial code, replace last child and rollback code comparison", () => { + it("Children set and removes code comparison", () => { const a: string = Clava.getProgram().code; - - const func = Query.search(FunctionJp).first(); - const returnStmt = Query.search(ReturnStmt).first(); - if (returnStmt !== undefined){ - func?.body.setLastChild(returnStmt); - } - + + const loopStmt1 = Query.search(Loop).get().at(0) as Joinpoint; + const testFunc = Query.search(FunctionJp).get().at(1) as FunctionJp; + const returnStmt = Query.search(ReturnStmt).get().at(0) as Joinpoint; + + testFunc.body.setFirstChild(loopStmt1.deepCopy()); + testFunc.body.setLastChild(returnStmt.deepCopy()); + testFunc.body.setFirstChild(loopStmt1.deepCopy()); + testFunc.body.setLastChild(returnStmt.deepCopy()); + const b: string = Clava.getProgram().code; - - ophistory.rollback(); - const c: string = Clava.getProgram().code; - - expect(a).toEqual(c); - expect(b).not.toEqual(c); - }); - it("Initial code, set last child and rollback code comparison", () => { - const a: string = Clava.getProgram().code; - - const testFunc = Query.search(FunctionJp).get().at(1); - const returnStmt = Query.search(ReturnStmt).first(); - if (returnStmt !== undefined){ - testFunc?.body.setLastChild(returnStmt); - } - - const b: string = Clava.getProgram().code; - - ophistory.rollback(); + ophistory.rollback(4); const c: string = Clava.getProgram().code; - - expect(a).toEqual(c); - expect(b).not.toEqual(c); - }); - - it("Initial code, remove children and rollback code comparison", () => { - const a: string = Clava.getProgram().code; - - const func = Query.search(FunctionJp).first(); - func?.body.removeChildren(); - - const b: string = Clava.getProgram().code; - - ophistory.rollback(); - const c: string = Clava.getProgram().code; - + expect(a).toEqual(c); expect(b).not.toEqual(c); }); - it("Change type and rollback comparison", () => { - const a: string = Clava.getProgram().code; + it("Log an error message on undo operation", () => { + const errorSpy = jest.spyOn(global.console, "error") + .mockImplementation(() => {}); - const vd = Query.search(Vardecl).first(); - vd?.setType(ClavaJoinPoints.type("test")); - - const b: string = Clava.getProgram().code; + const loopStmt1 = Query.search(Loop).get().at(0) as Joinpoint; - ophistory.rollback(); - const c: string = Clava.getProgram().code; - - expect(a).toEqual(c); - expect(a).not.toEqual(b); - }); + loopStmt1.replaceWith("aaaa"); + loopStmt1.detach(); + + ophistory.rollback(2); - it("Initial code, set inline comment and rollback code comparison", () => { - const a = Clava.getProgram().code; - - const loopStmt = Query.search(Loop).get().at(0); - loopStmt?.setInlineComments("aaaaa"); - - const b = Clava.getProgram().code; + expect(errorSpy).toHaveBeenCalledTimes(1); - ophistory.rollback(); - const c = Clava.getProgram().code; - - expect(a).toEqual(c); - expect(b).not.toEqual(c); + errorSpy.mockRestore(); }); - it("Initial code, set inline comments and rollback code comparison", () => { - const a = Clava.getProgram().code; - - const loopStmt = Query.search(Loop).get().at(0); - loopStmt?.setInlineComments(["aaaaa", "bbbbb"]); - - const b = Clava.getProgram().code; - - ophistory.rollback(); - const c = Clava.getProgram().code; - - expect(a).toEqual(c); - expect(b).not.toEqual(c); - }); - - it("Initial code, set inline comments and rollback code comparison", () => { - const a = Clava.getProgram().code; - - const loopStmt = Query.search(Loop).get().at(0); - - loopStmt?.setInlineComments(["aaaaa", "bbbbb"]); - const b = Clava.getProgram().code; - - loopStmt?.setInlineComments([""]); - const c = Clava.getProgram().code; - - loopStmt?.setInlineComments("ccccc"); - const d = Clava.getProgram().code; - - loopStmt?.setInlineComments(""); - const e = Clava.getProgram().code; - - ophistory.rollback(); - const f = Clava.getProgram().code; - - ophistory.rollback(); - const g = Clava.getProgram().code; - - ophistory.rollback(); - const h = Clava.getProgram().code; - - ophistory.rollback(); - const i = Clava.getProgram().code; - - expect(a).toEqual(i); - expect(a).toEqual(e); - expect(b).toEqual(h); - expect(c).toEqual(g); - expect(d).toEqual(f); - expect(a).not.toEqual(b); - expect(a).not.toEqual(c); - expect(a).not.toEqual(d); - expect(b).not.toEqual(c); - expect(b).not.toEqual(d); - expect(c).not.toEqual(d); - }); -}); - +}); \ No newline at end of file diff --git a/Clava-JS/src-api/clava/history/Operations.test.ts b/Clava-JS/src-api/clava/history/Operations.test.ts new file mode 100644 index 000000000..f78be51cd --- /dev/null +++ b/Clava-JS/src-api/clava/history/Operations.test.ts @@ -0,0 +1,359 @@ +import { registerSourceCode } from "lara-js/jest/jestHelpers"; +import Clava from "../../../api/clava/Clava"; +import Query from "lara-js/api/weaver/Query"; +import ophistory from "./History"; +import { FunctionJp, Joinpoint, Loop, ReturnStmt, Vardecl } from "../../Joinpoints"; +import ClavaJoinPoints from "../../../api/clava/ClavaJoinPoints"; + +const code: string = `void func() { + for (int i = 0; i < 1; i++){ + i++; + } + for (int i = 0; i < 2; i++){ + i++; + } +} + +void test() {} + +int main(int argc, char *argv[]) { + func(); + return 0; +} +`; + +describe("Transformation History: Operations", () => { + registerSourceCode(code); + + it("Initial code, insert before and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + loopStmt?.insertBefore(loopStmt.deepCopy()); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, insert after and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + loopStmt?.insertAfter(loopStmt.deepCopy()); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, replace singular string and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + loopStmt?.replaceWith("aaaaa"); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, replace singular joinpoint and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + const returnStmt = Query.search(ReturnStmt).first(); + if (returnStmt !== undefined){ + loopStmt?.replaceWith(returnStmt.deepCopy()); + } + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, replace multiple joinpoints and rollback code comparison", () => { + // TODO: fix error regarding Joinpoint[] overload not found + /*const a: string = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + const returnStmt = Query.search(ReturnStmt).first(); + if (returnStmt !== undefined){ + loopStmt?.replaceWith(returnStmt.deepCopy()); + } + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c);*/ + }); + + it("Initial code, replace multiple strings and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + loopStmt?.replaceWithStrings(["aaaa", "bbbb", "cccc"]); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, comment joinpoint and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + loopStmt?.toComment(); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, detach first child and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const func = Query.search(FunctionJp).first(); + func?.body.firstChild.detach(); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, detach only child and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const func = Query.search(FunctionJp).first(); + func?.body.detach(); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, detach last child and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const func = Query.search(FunctionJp).first(); + func?.body.lastChild.detach(); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, replace first child and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const func = Query.search(FunctionJp).first(); + const returnStmt = Query.search(ReturnStmt).first(); + if (returnStmt !== undefined){ + func?.body.setFirstChild(returnStmt); + } + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, set first child and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const testFunc = Query.search(FunctionJp).get().at(1); + const returnStmt = Query.search(ReturnStmt).first(); + if (returnStmt !== undefined){ + testFunc?.body.setFirstChild(returnStmt); + } + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, replace last child and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const func = Query.search(FunctionJp).first(); + const returnStmt = Query.search(ReturnStmt).first(); + if (returnStmt !== undefined){ + func?.body.setLastChild(returnStmt); + } + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, set last child and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const testFunc = Query.search(FunctionJp).get().at(1); + const returnStmt = Query.search(ReturnStmt).first(); + if (returnStmt !== undefined){ + testFunc?.body.setLastChild(returnStmt); + } + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, remove children and rollback code comparison", () => { + const a: string = Clava.getProgram().code; + + const func = Query.search(FunctionJp).first(); + func?.body.removeChildren(); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Change type and rollback comparison", () => { + const a: string = Clava.getProgram().code; + + const vd = Query.search(Vardecl).first(); + vd?.setType(ClavaJoinPoints.type("test")); + + const b: string = Clava.getProgram().code; + + ophistory.rollback(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(a).not.toEqual(b); + }); + + it("Initial code, set inline comment and rollback code comparison", () => { + const a = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + loopStmt?.setInlineComments("aaaaa"); + + const b = Clava.getProgram().code; + + ophistory.rollback(); + const c = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, set inline comments and rollback code comparison", () => { + const a = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + loopStmt?.setInlineComments(["aaaaa", "bbbbb"]); + + const b = Clava.getProgram().code; + + ophistory.rollback(); + const c = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Initial code, set inline comments and rollback code comparison", () => { + const a = Clava.getProgram().code; + + const loopStmt = Query.search(Loop).get().at(0); + + loopStmt?.setInlineComments(["aaaaa", "bbbbb"]); + const b = Clava.getProgram().code; + + loopStmt?.setInlineComments([""]); + const c = Clava.getProgram().code; + + loopStmt?.setInlineComments("ccccc"); + const d = Clava.getProgram().code; + + loopStmt?.setInlineComments(""); + const e = Clava.getProgram().code; + + ophistory.rollback(); + const f = Clava.getProgram().code; + + ophistory.rollback(); + const g = Clava.getProgram().code; + + ophistory.rollback(); + const h = Clava.getProgram().code; + + ophistory.rollback(); + const i = Clava.getProgram().code; + + expect(a).toEqual(i); + expect(a).toEqual(e); + expect(b).toEqual(h); + expect(c).toEqual(g); + expect(d).toEqual(f); + expect(a).not.toEqual(b); + expect(a).not.toEqual(c); + expect(a).not.toEqual(d); + expect(b).not.toEqual(c); + expect(b).not.toEqual(d); + expect(c).not.toEqual(d); + }); +}); + From cd948e9d7dab98ff5cfbe14c9454097a00137ba8 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Mon, 22 Jul 2024 16:46:29 +0100 Subject: [PATCH 25/38] feat: added Checkpoint logic to History --- .../src-api/clava/history/EventListener.ts | 50 ++++++------------- Clava-JS/src-api/clava/history/History.ts | 20 ++++++++ 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/Clava-JS/src-api/clava/history/EventListener.ts b/Clava-JS/src-api/clava/history/EventListener.ts index b1e8dc7db..e61fc8ba6 100644 --- a/Clava-JS/src-api/clava/history/EventListener.ts +++ b/Clava-JS/src-api/clava/history/EventListener.ts @@ -3,16 +3,7 @@ import * as fs from "fs"; import Clava from "../Clava.js"; import { Event, EventTime } from "./Events.js"; import ophistory from "./History.js"; -import { - DetachOperation, - DetachReference, - InlineCommentOperation, - InsertOperation, - RemoveChildrenOperation, - ReplaceOperation, - SetChildOperation, - TypeChangeOperation, -} from "./Operations.js"; +import { DetachOperation, DetachReference, InlineCommentOperation, InsertOperation, RemoveChildrenOperation, ReplaceOperation, SetChildOperation, TypeChangeOperation } from "./Operations.js"; import { Joinpoint } from "../../Joinpoints.js"; const eventListener = new EventEmitter(); @@ -30,6 +21,7 @@ eventListener.on("storeAST", () => { }); eventListener.on("ACTION", (e: Event) => { + // Event Logs for debugging /* console.log("\nReceived ACTION event"); @@ -67,25 +59,23 @@ eventListener.on("ACTION", (e: Event) => { } break; case EventTime.AFTER: - switch (e.description) { + switch (e.description){ case "insertAfter": case "insertBefore": insertOperationFromEvent(e); break; case "replaceWith": - if (e.inputs.length > 0) { - if ( - typeof e.inputs[0] === "string" || - e.inputs[0] instanceof Joinpoint - ) { + if (e.inputs.length > 0){ + if (typeof e.inputs[0] === 'string' || e.inputs[0] instanceof Joinpoint){ replaceSingleOperationFromEvent(e); - } else { + } + else { replaceMultipleOperationFromEvent(e); } } break; case "replaceWithStrings": - if (e.inputs.length > 0) { + if (e.inputs.length > 0){ replaceMultipleOperationFromEvent(e); } break; @@ -121,35 +111,29 @@ eventListener.on("ACTION", (e: Event) => { }); function insertOperationFromEvent(e: Event) { - if (e.returnValue !== undefined) { - ophistory.newOperation(new InsertOperation(e.returnValue)); + if (e.returnValue !== undefined){ + ophistory.newOperation(new InsertOperation(e.returnValue)) } } function replaceSingleOperationFromEvent(e: Event) { - if (e.returnValue !== undefined) { + if (e.returnValue !== undefined){ ophistory.newOperation(new ReplaceOperation(e.mainJP, e.returnValue, 1)); } } function replaceMultipleOperationFromEvent(e: Event) { - if (e.returnValue !== undefined) { - ophistory.newOperation( - new ReplaceOperation( - e.mainJP, - e.returnValue, - (e.inputs[0] as Joinpoint[] | string[]).length - ) - ); + if (e.returnValue !== undefined){ + ophistory.newOperation(new ReplaceOperation(e.mainJP, e.returnValue, (e.inputs[0] as (Joinpoint[] | string[])).length)); } } function detachOperationFromEvent(e: Event) { let refJP: Joinpoint, ref: DetachReference; - if (e.mainJP.siblingsLeft.length >= 1) { + if (e.mainJP.siblingsLeft.length >= 1){ refJP = e.mainJP.leftJp; ref = DetachReference.LEFT; - } else if (e.mainJP.siblingsRight.length >= 1) { + } else if (e.mainJP.siblingsRight.length >= 1) { refJP = e.mainJP.rightJp; ref = DetachReference.RIGHT; } else { @@ -168,9 +152,7 @@ function setLastChildFromEvent(e: Event, aux: Joinpoint) { } function removeChildrenOperationFromEvent(e: Event) { - ophistory.newOperation( - new RemoveChildrenOperation(e.mainJP, e.mainJP.children) - ); + ophistory.newOperation(new RemoveChildrenOperation(e.mainJP, e.mainJP.children)); } function changeTypeFromEvent(e: Event) { diff --git a/Clava-JS/src-api/clava/history/History.ts b/Clava-JS/src-api/clava/history/History.ts index 172c135cc..020ec62f1 100644 --- a/Clava-JS/src-api/clava/history/History.ts +++ b/Clava-JS/src-api/clava/history/History.ts @@ -40,6 +40,26 @@ class OperationHistory { } } } + + checkpoint() { + this.operations.length = 0; + } + + returnToLastCheckpoint() { + while (this.operations.length > 0) { + const op = this.operations.pop(); + if (op !== undefined) { + try { + this.lock(); + op.undo(); + } catch (error) { + console.error("Failed to undo operation:", error); + } finally { + this.unlock(); + } + } + } + } } const ophistory = new OperationHistory(); From 1d1844df186355db49fbe389cef1e07b4dde3610 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Mon, 22 Jul 2024 16:46:55 +0100 Subject: [PATCH 26/38] test: added tests for checkpoints and checkpoint errors --- .../src-api/clava/history/History.test.ts | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/Clava-JS/src-api/clava/history/History.test.ts b/Clava-JS/src-api/clava/history/History.test.ts index d488e8c34..3f543edc3 100644 --- a/Clava-JS/src-api/clava/history/History.test.ts +++ b/Clava-JS/src-api/clava/history/History.test.ts @@ -88,7 +88,7 @@ describe("Transformation History: Multiple operations", () => { expect(b).not.toEqual(c); }); - it("Log an error message on undo operation", () => { + it("Log an error message on undo operation (single rollback)", () => { const errorSpy = jest.spyOn(global.console, "error") .mockImplementation(() => {}); @@ -104,4 +104,43 @@ describe("Transformation History: Multiple operations", () => { errorSpy.mockRestore(); }); + it("Checkpoints code comparison", () => { + + const loopStmt1 = Query.search(Loop).get().at(0) as Joinpoint; + const loopStmt2 = Query.search(Loop).get().at(1) as Joinpoint; + loopStmt1.insertBefore(loopStmt2.deepCopy()); + loopStmt2.insertAfter(loopStmt1.deepCopy()); + + ophistory.checkpoint(); + const a: string = Clava.getProgram().code; + + loopStmt1.detach(); + loopStmt2.detach(); + + const b: string = Clava.getProgram().code; + + ophistory.returnToLastCheckpoint(); + const c: string = Clava.getProgram().code; + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); + + it("Log an error message on undo operation (checkpoint rollback)", () => { + const errorSpy = jest.spyOn(global.console, "error") + .mockImplementation(() => {}); + + const loopStmt1 = Query.search(Loop).get().at(0) as Joinpoint; + + ophistory.checkpoint(); + loopStmt1.replaceWith("aaaa"); + loopStmt1.detach(); + + ophistory.returnToLastCheckpoint(); + + expect(errorSpy).toHaveBeenCalledTimes(1); + + errorSpy.mockRestore(); + }); + }); \ No newline at end of file From f0dd10e61b05488fb55d4b8307b2503f8c723206 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Tue, 23 Jul 2024 09:50:32 +0100 Subject: [PATCH 27/38] feat: added setValue operation --- Clava-JS/src-api/Joinpoints.ts | 4 ++-- .../src-api/clava/history/EventListener.ts | 19 ++++++++++++++++--- Clava-JS/src-api/clava/history/Operations.ts | 10 +++++++++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/Clava-JS/src-api/Joinpoints.ts b/Clava-JS/src-api/Joinpoints.ts index af90611ce..857c1e4ac 100644 --- a/Clava-JS/src-api/Joinpoints.ts +++ b/Clava-JS/src-api/Joinpoints.ts @@ -571,7 +571,7 @@ export class Joinpoint extends LaraJoinPoint { * Associates arbitrary values to nodes of the AST */ setUserField(p1: string | Record, p2?: object): object { - eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setUserField", this)); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setUserField", this, undefined, p1, p2)); const jp = wrapJoinPoint(this._javaObject.setUserField(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); eventListener.emit("ACTION", new Event(EventTime.AFTER, "setUserField", this, jp as Joinpoint, p1, p2)); return jp; @@ -580,7 +580,7 @@ export class Joinpoint extends LaraJoinPoint { * Sets the value associated with the given property key */ setValue(key: string, value: object): Joinpoint { - eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setValue", this)); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setValue", this, undefined, key, value)); const jp = wrapJoinPoint(this._javaObject.setValue(unwrapJoinPoint(key), unwrapJoinPoint(value))); eventListener.emit("ACTION", new Event(EventTime.AFTER, "setValue", this, jp as Joinpoint, key, value)); return jp; diff --git a/Clava-JS/src-api/clava/history/EventListener.ts b/Clava-JS/src-api/clava/history/EventListener.ts index e61fc8ba6..fd7afe894 100644 --- a/Clava-JS/src-api/clava/history/EventListener.ts +++ b/Clava-JS/src-api/clava/history/EventListener.ts @@ -3,7 +3,7 @@ import * as fs from "fs"; import Clava from "../Clava.js"; import { Event, EventTime } from "./Events.js"; import ophistory from "./History.js"; -import { DetachOperation, DetachReference, InlineCommentOperation, InsertOperation, RemoveChildrenOperation, ReplaceOperation, SetChildOperation, TypeChangeOperation } from "./Operations.js"; +import { DetachOperation, DetachReference, InlineCommentOperation, InsertOperation, RemoveChildrenOperation, ReplaceOperation, SetChildOperation, TypeChangeOperation, ValueOperation } from "./Operations.js"; import { Joinpoint } from "../../Joinpoints.js"; const eventListener = new EventEmitter(); @@ -28,7 +28,7 @@ eventListener.on("ACTION", (e: Event) => { console.log(e.timing); console.log(e.description); console.log(e.mainJP); - console.log(e.returnJP); + console.log(e.returnValue); console.log(e.inputs); console.log("\n"); */ @@ -54,6 +54,9 @@ eventListener.on("ACTION", (e: Event) => { case "setInlineComments": inlineCommentOperationFromEvent(e); break; + case "setValue": + setValueOperationFromEvent(e); + break; default: break; } @@ -96,16 +99,20 @@ eventListener.on("ACTION", (e: Event) => { // Manual testing the rollback /* - if (e.description === "detach" && e.timing === EventTime.AFTER) { + if (e.description === "setValue" && e.timing === EventTime.AFTER) { console.log(`Waypoint ${idx}`); fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); idx++; + + console.log(e.mainJP.getValue(e.inputs.at(0) as string)); ophistory.rollback(); console.log(`Waypoint ${idx}`); fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); idx++; + console.log(e.mainJP.getValue(e.inputs.at(0) as string)); + } */ }); @@ -166,4 +173,10 @@ function inlineCommentOperationFromEvent(e: Event) { ophistory.newOperation(new InlineCommentOperation(e.mainJP, comments)); } +function setValueOperationFromEvent(e: Event) { + if (e.inputs && e.inputs.at(0)) { + ophistory.newOperation(new ValueOperation(e.mainJP, e.inputs.at(0) as string, e.mainJP.getValue(e.inputs.at(0) as string))); + } +} + export default eventListener; diff --git a/Clava-JS/src-api/clava/history/Operations.ts b/Clava-JS/src-api/clava/history/Operations.ts index 5061cdcef..881d7f7bb 100644 --- a/Clava-JS/src-api/clava/history/Operations.ts +++ b/Clava-JS/src-api/clava/history/Operations.ts @@ -96,4 +96,12 @@ export class InlineCommentOperation implements Operation { this.jp.setInlineComments(this.oldComments); } } -} \ No newline at end of file +} + +export class ValueOperation implements Operation { + constructor(private jp: Joinpoint, private key: string, private oldValue: object) {} + + undo(): void { + this.jp.setValue(this.key, this.oldValue); + } +} From 9a0aab7e92302a45d7be740a404dcdf7184c4ca7 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Tue, 23 Jul 2024 09:51:09 +0100 Subject: [PATCH 28/38] test: setValue behaviour --- Clava-JS/src-api/clava/history/Operations.test.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Clava-JS/src-api/clava/history/Operations.test.ts b/Clava-JS/src-api/clava/history/Operations.test.ts index f78be51cd..41e5a8f36 100644 --- a/Clava-JS/src-api/clava/history/Operations.test.ts +++ b/Clava-JS/src-api/clava/history/Operations.test.ts @@ -355,5 +355,20 @@ describe("Transformation History: Operations", () => { expect(b).not.toEqual(d); expect(c).not.toEqual(d); }); + + it("Initial code, set id value and rollback value comparison", () => { + const key = "id"; + const loopStmt = Query.search(Loop).get().at(0); + const a = loopStmt?.getValue(key); + loopStmt?.setValue(key, {}); + + const b = loopStmt?.getValue(key); + + ophistory.rollback(); + const c = loopStmt?.getValue(key); + + expect(a).toEqual(c); + expect(b).not.toEqual(c); + }); }); From 4172c538851dcd585fab1a68afce153a303409c8 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Tue, 23 Jul 2024 09:57:51 +0100 Subject: [PATCH 29/38] fix: standardization of event calls and type fix for return values --- Clava-JS/src-api/Joinpoints.ts | 48 ++++++++++++------------ Clava-JS/src-api/clava/history/Events.ts | 2 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Clava-JS/src-api/Joinpoints.ts b/Clava-JS/src-api/Joinpoints.ts index 857c1e4ac..2d2ef575c 100644 --- a/Clava-JS/src-api/Joinpoints.ts +++ b/Clava-JS/src-api/Joinpoints.ts @@ -429,9 +429,9 @@ export class Joinpoint extends LaraJoinPoint { * Removes the node associated to this joinpoint from the AST */ detach(): Joinpoint { - eventListener.emit("ACTION", new Event(EventTime.BEFORE, "detach", this)); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "detach", this, undefined)); const jp = wrapJoinPoint(this._javaObject.detach()); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "detach", this, jp as Joinpoint)); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "detach", this, jp)); return jp; } /** @@ -446,9 +446,9 @@ export class Joinpoint extends LaraJoinPoint { * Inserts the given join point after this join point */ insertAfter(p1: Joinpoint | string): Joinpoint { - eventListener.emit("ACTION", new Event(EventTime.BEFORE, "insertAfter", this)); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "insertAfter", this, undefined, p1)); const jp = wrapJoinPoint(this._javaObject.insertAfter(unwrapJoinPoint(p1))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "insertAfter", this, jp as Joinpoint, p1)); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "insertAfter", this, jp, p1)); return jp; } /** @@ -463,9 +463,9 @@ export class Joinpoint extends LaraJoinPoint { * Inserts the given join point before this join point */ insertBefore(p1: Joinpoint | string): Joinpoint { - eventListener.emit("ACTION", new Event(EventTime.BEFORE, "insertBefore", this)); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "insertBefore", this, undefined, p1)); const jp = wrapJoinPoint(this._javaObject.insertBefore(unwrapJoinPoint(p1))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "insertBefore", this, jp as Joinpoint, p1)); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "insertBefore", this, jp, p1)); return jp; } /** @@ -476,9 +476,9 @@ export class Joinpoint extends LaraJoinPoint { * Removes the children of this node */ removeChildren(): void { - eventListener.emit("ACTION", new Event(EventTime.BEFORE, "removeChildren", this)); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "removeChildren", this, undefined)); const jp = wrapJoinPoint(this._javaObject.removeChildren()); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "removeChildren", this, jp as Joinpoint)); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "removeChildren", this, jp)); return jp; } /** @@ -497,18 +497,18 @@ export class Joinpoint extends LaraJoinPoint { * Replaces this node with the given node */ replaceWith(p1: Joinpoint | string | Joinpoint[]): Joinpoint { - eventListener.emit("ACTION", new Event(EventTime.BEFORE, "replaceWith", this)); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "replaceWith", this, undefined, p1)); const jp = wrapJoinPoint(this._javaObject.replaceWith(unwrapJoinPoint(p1))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "replaceWith", this, jp as Joinpoint, p1)); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "replaceWith", this, jp, p1)); return jp; } /** * Overload which accepts a list of strings */ replaceWithStrings(node: string[]): Joinpoint { - eventListener.emit("ACTION", new Event(EventTime.BEFORE, "replaceWithStrings", this)); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "replaceWithStrings", this, undefined, node)); const jp = wrapJoinPoint(this._javaObject.replaceWithStrings(unwrapJoinPoint(node))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "replaceWithStrings", this, jp as Joinpoint, node)); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "replaceWithStrings", this, jp, node)); return jp; } /** @@ -519,9 +519,9 @@ export class Joinpoint extends LaraJoinPoint { * Replaces the first child, or inserts the join point if no child is present */ setFirstChild(node: Joinpoint): void { - eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setFirstChild", this)); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setFirstChild", this, undefined, node)); const jp = wrapJoinPoint(this._javaObject.setFirstChild(unwrapJoinPoint(node))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "setFirstChild", this, jp as Joinpoint, node)); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setFirstChild", this, jp, node)); return jp; } /** @@ -536,27 +536,27 @@ export class Joinpoint extends LaraJoinPoint { * Sets the commented that are embedded in a node */ setInlineComments(p1: string[] | string): void { - eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setInlineComments", this)); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setInlineComments", this, undefined, p1)); const jp = wrapJoinPoint(this._javaObject.setInlineComments(unwrapJoinPoint(p1))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "setInlineComments", this, jp as Joinpoint, p1)); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setInlineComments", this, jp, p1)); return jp; } /** * Replaces the last child, or inserts the join point if no child is present */ setLastChild(node: Joinpoint): void { - eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setLastChild", this)); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setLastChild", this, undefined, node)); const jp = wrapJoinPoint(this._javaObject.setLastChild(unwrapJoinPoint(node))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "setLastChild", this, jp as Joinpoint, node)); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setLastChild", this, jp, node)); return jp; } /** * Sets the type of a node, if it has a type */ setType(type: Type): void { - eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setType", this)); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setType", this, undefined, type)); const jp = wrapJoinPoint(this._javaObject.setType(unwrapJoinPoint(type))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "setType", this, jp as Joinpoint, type)); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setType", this, jp, type)); return jp; } /** @@ -573,7 +573,7 @@ export class Joinpoint extends LaraJoinPoint { setUserField(p1: string | Record, p2?: object): object { eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setUserField", this, undefined, p1, p2)); const jp = wrapJoinPoint(this._javaObject.setUserField(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "setUserField", this, jp as Joinpoint, p1, p2)); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setUserField", this, jp, p1, p2)); return jp; } /** @@ -582,16 +582,16 @@ export class Joinpoint extends LaraJoinPoint { setValue(key: string, value: object): Joinpoint { eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setValue", this, undefined, key, value)); const jp = wrapJoinPoint(this._javaObject.setValue(unwrapJoinPoint(key), unwrapJoinPoint(value))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "setValue", this, jp as Joinpoint, key, value)); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setValue", this, jp, key, value)); return jp; } /** * Replaces this join point with a comment with the same contents as .code */ toComment(prefix: string = "", suffix: string = ""): Joinpoint { - eventListener.emit("ACTION", new Event(EventTime.BEFORE, "toComment", this)); + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "toComment", this, undefined, prefix, suffix)); const jp = wrapJoinPoint(this._javaObject.toComment(unwrapJoinPoint(prefix), unwrapJoinPoint(suffix))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "toComment", this, jp as Joinpoint, prefix, suffix)); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "toComment", this, jp, prefix, suffix)); return jp; } } diff --git a/Clava-JS/src-api/clava/history/Events.ts b/Clava-JS/src-api/clava/history/Events.ts index 494f77208..ce11a0ac0 100644 --- a/Clava-JS/src-api/clava/history/Events.ts +++ b/Clava-JS/src-api/clava/history/Events.ts @@ -9,7 +9,7 @@ export class Event { public timing: EventTime; public description: string; public mainJP: Joinpoint; - public returnValue?: Joinpoint; + public returnValue?: any; public inputs: unknown[]; constructor( From 957f904e1519a1d600943c5e3be8663f619e49ca Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Tue, 23 Jul 2024 17:24:27 +0100 Subject: [PATCH 30/38] fix: code cleanup --- .../src-api/clava/history/EventListener.ts | 30 ------------------- .../src-api/clava/history/Operations.test.ts | 3 +- 2 files changed, 1 insertion(+), 32 deletions(-) diff --git a/Clava-JS/src-api/clava/history/EventListener.ts b/Clava-JS/src-api/clava/history/EventListener.ts index fd7afe894..ed8f4243e 100644 --- a/Clava-JS/src-api/clava/history/EventListener.ts +++ b/Clava-JS/src-api/clava/history/EventListener.ts @@ -21,17 +21,6 @@ eventListener.on("storeAST", () => { }); eventListener.on("ACTION", (e: Event) => { - - // Event Logs for debugging - /* - console.log("\nReceived ACTION event"); - console.log(e.timing); - console.log(e.description); - console.log(e.mainJP); - console.log(e.returnValue); - console.log(e.inputs); - console.log("\n"); - */ switch (e.timing) { case EventTime.BEFORE: @@ -96,25 +85,6 @@ eventListener.on("ACTION", (e: Event) => { } break; } - - // Manual testing the rollback - /* - if (e.description === "setValue" && e.timing === EventTime.AFTER) { - console.log(`Waypoint ${idx}`); - fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); - idx++; - - console.log(e.mainJP.getValue(e.inputs.at(0) as string)); - - ophistory.rollback(); - - console.log(`Waypoint ${idx}`); - fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); - idx++; - console.log(e.mainJP.getValue(e.inputs.at(0) as string)); - - } - */ }); function insertOperationFromEvent(e: Event) { diff --git a/Clava-JS/src-api/clava/history/Operations.test.ts b/Clava-JS/src-api/clava/history/Operations.test.ts index 41e5a8f36..0c33bb458 100644 --- a/Clava-JS/src-api/clava/history/Operations.test.ts +++ b/Clava-JS/src-api/clava/history/Operations.test.ts @@ -2,7 +2,7 @@ import { registerSourceCode } from "lara-js/jest/jestHelpers"; import Clava from "../../../api/clava/Clava"; import Query from "lara-js/api/weaver/Query"; import ophistory from "./History"; -import { FunctionJp, Joinpoint, Loop, ReturnStmt, Vardecl } from "../../Joinpoints"; +import { FunctionJp, Loop, ReturnStmt, Vardecl } from "../../Joinpoints"; import ClavaJoinPoints from "../../../api/clava/ClavaJoinPoints"; const code: string = `void func() { @@ -371,4 +371,3 @@ describe("Transformation History: Operations", () => { expect(b).not.toEqual(c); }); }); - From 13159e450e0a0527ce7041a798bd91b2a2a017a9 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Tue, 23 Jul 2024 17:26:27 +0100 Subject: [PATCH 31/38] feat: standardized Joinpoints.ts --- Clava-JS/src-api/Joinpoints.ts | 1348 +++++++++++++++++++++----------- 1 file changed, 905 insertions(+), 443 deletions(-) diff --git a/Clava-JS/src-api/Joinpoints.ts b/Clava-JS/src-api/Joinpoints.ts index 2d2ef575c..c0e741679 100644 --- a/Clava-JS/src-api/Joinpoints.ts +++ b/Clava-JS/src-api/Joinpoints.ts @@ -143,9 +143,6 @@ type DefaultAttributeMap = { } export class Joinpoint extends LaraJoinPoint { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -356,83 +353,173 @@ export class Joinpoint extends LaraJoinPoint { /** * True, if this node is a Java instance of the given name, which corresponds to a simple Java class name of an AST node. For an equivalent function for join point names, use 'instanceOf(joinPointName)' */ - astIsInstance(className: string): boolean { return wrapJoinPoint(this._javaObject.astIsInstance(unwrapJoinPoint(className))); } + astIsInstance(className: string): boolean { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "astIsInstance", this, undefined, className)); + const res = wrapJoinPoint(this._javaObject.astIsInstance(unwrapJoinPoint(className))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "astIsInstance", this, res, className)); + return res; + } /** * True if the given node is a descendant of this node */ - contains(jp: Joinpoint): boolean { return wrapJoinPoint(this._javaObject.contains(unwrapJoinPoint(jp))); } + contains(jp: Joinpoint): boolean { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "contains", this, undefined, jp)); + const res = wrapJoinPoint(this._javaObject.contains(unwrapJoinPoint(jp))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "contains", this, res, jp)); + return res; + } /** * Looks for an ancestor joinpoint name, walking back on the AST */ - getAncestor(type: string): Joinpoint { return wrapJoinPoint(this._javaObject.getAncestor(unwrapJoinPoint(type))); } + getAncestor(type: string): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getAncestor", this, undefined, type)); + const res = wrapJoinPoint(this._javaObject.getAncestor(unwrapJoinPoint(type))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getAncestor", this, res, type)); + return res; + } /** * @deprecated Looks for an ancestor AST name, walking back on the AST */ - getAstAncestor(type: string): Joinpoint { return wrapJoinPoint(this._javaObject.getAstAncestor(unwrapJoinPoint(type))); } + getAstAncestor(type: string): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getAstAncestor", this, undefined, type)); + const res = wrapJoinPoint(this._javaObject.getAstAncestor(unwrapJoinPoint(type))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getAstAncestor", this, res, type)); + return res; + } /** * Returns the child of the node at the given index, considering null nodes */ - getAstChild(index: number): Joinpoint { return wrapJoinPoint(this._javaObject.getAstChild(unwrapJoinPoint(index))); } + getAstChild(index: number): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getAstChild", this, undefined, index)); + const res = wrapJoinPoint(this._javaObject.getAstChild(unwrapJoinPoint(index))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getAstChild", this, res, index)); + return res; + } /** * Looks for an ancestor joinpoint name, walking back on the joinpoint chain */ - getChainAncestor(type: string): Joinpoint { return wrapJoinPoint(this._javaObject.getChainAncestor(unwrapJoinPoint(type))); } + getChainAncestor(type: string): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getChainAncestor", this, undefined, type)); + const res = wrapJoinPoint(this._javaObject.getChainAncestor(unwrapJoinPoint(type))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getChainAncestor", this, res, type)); + return res; + } /** * Returns the child of the node at the given index, ignoring null nodes */ - getChild(index: number): Joinpoint { return wrapJoinPoint(this._javaObject.getChild(unwrapJoinPoint(index))); } + getChild(index: number): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getChild", this, undefined, index)); + const res = wrapJoinPoint(this._javaObject.getChild(unwrapJoinPoint(index))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getChild", this, res, index)); + return res; + } /** * Retrieves the descendants of the given type */ - getDescendants(type: string): Joinpoint[] { return wrapJoinPoint(this._javaObject.getDescendants(unwrapJoinPoint(type))); } + getDescendants(type: string): Joinpoint[] { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getDescendants", this, undefined, type)); + const res = wrapJoinPoint(this._javaObject.getDescendants(unwrapJoinPoint(type))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getDescendants", this, res, type)); + return res; + } /** * Retrieves the descendants of the given type, including the node itself */ - getDescendantsAndSelf(type: string): Joinpoint[] { return wrapJoinPoint(this._javaObject.getDescendantsAndSelf(unwrapJoinPoint(type))); } + getDescendantsAndSelf(type: string): Joinpoint[] { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getDescendantsAndSelf", this, undefined, type)); + const res = wrapJoinPoint(this._javaObject.getDescendantsAndSelf(unwrapJoinPoint(type))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getDescendantsAndSelf", this, res, type)); + return res; + } /** * Looks in the descendants for the first node of the given type */ - getFirstJp(type: string): Joinpoint { return wrapJoinPoint(this._javaObject.getFirstJp(unwrapJoinPoint(type))); } + getFirstJp(type: string): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getFirstJp", this, undefined, type)); + const res = wrapJoinPoint(this._javaObject.getFirstJp(unwrapJoinPoint(type))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getFirstJp", this, res, type)); + return res; + } /** * String with the full Java class name of the type of the Java field with the provided name */ - getJavaFieldType(fieldName: string): string { return wrapJoinPoint(this._javaObject.getJavaFieldType(unwrapJoinPoint(fieldName))); } + getJavaFieldType(fieldName: string): string { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getJavaFieldType", this, undefined, fieldName)); + const res = wrapJoinPoint(this._javaObject.getJavaFieldType(unwrapJoinPoint(fieldName))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getJavaFieldType", this, res, fieldName)); + return res; + } /** * Java Class instance with the type of the given key */ - getKeyType(key: string): object { return wrapJoinPoint(this._javaObject.getKeyType(unwrapJoinPoint(key))); } + getKeyType(key: string): object { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getKeyType", this, undefined, key)); + const res = wrapJoinPoint(this._javaObject.getKeyType(unwrapJoinPoint(key))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getKeyType", this, res, key)); + return res; + } /** * Retrives values that have been associated to nodes of the AST with 'setUserField' */ - getUserField(fieldName: string): object { return wrapJoinPoint(this._javaObject.getUserField(unwrapJoinPoint(fieldName))); } + getUserField(fieldName: string): object { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getUserField", this, undefined, fieldName)); + const res = wrapJoinPoint(this._javaObject.getUserField(unwrapJoinPoint(fieldName))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getUserField", this, res, fieldName)); + return res; + } /** * The value associated with the given property key */ - getValue(key: string): object { return wrapJoinPoint(this._javaObject.getValue(unwrapJoinPoint(key))); } + getValue(key: string): object { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getValue", this, undefined, key)); + const res = wrapJoinPoint(this._javaObject.getValue(unwrapJoinPoint(key))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getValue", this, res, key)); + return res; + } /** * True, if the given join point or AST node is the same (== test) as the current join point AST node */ - hasNode(nodeOrJp: object): boolean { return wrapJoinPoint(this._javaObject.hasNode(unwrapJoinPoint(nodeOrJp))); } + hasNode(nodeOrJp: object): boolean { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "hasNode", this, undefined, nodeOrJp)); + const res = wrapJoinPoint(this._javaObject.hasNode(unwrapJoinPoint(nodeOrJp))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "hasNode", this, res, nodeOrJp)); + return res; + } /** * Performs a copy of the node and its children, but not of the nodes in its fields */ - copy(): Joinpoint { return wrapJoinPoint(this._javaObject.copy()); } + copy(): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "copy", this, undefined)); + const res = wrapJoinPoint(this._javaObject.copy()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "copy", this, res)); + return res; + } /** * Clears all properties from the .data object */ - dataClear(): void { return wrapJoinPoint(this._javaObject.dataClear()); } + dataClear(): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "dataClear", this, undefined)); + const res = wrapJoinPoint(this._javaObject.dataClear()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "dataClear", this, res)); + return res; + } /** * Performs a copy of the node and its children, including the nodes in their fields (only the first level of field nodes, this function is not recursive) */ - deepCopy(): Joinpoint { return wrapJoinPoint(this._javaObject.deepCopy()); } + deepCopy(): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "deepCopy", this, undefined)); + const res = wrapJoinPoint(this._javaObject.deepCopy()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "deepCopy", this, res)); + return res; + } /** * Removes the node associated to this joinpoint from the AST */ detach(): Joinpoint { - eventListener.emit("ACTION", new Event(EventTime.BEFORE, "detach", this, undefined)); - const jp = wrapJoinPoint(this._javaObject.detach()); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "detach", this, jp)); - return jp; + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "detach", this, undefined)); + const res = wrapJoinPoint(this._javaObject.detach()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "detach", this, res)); + return res; } /** * Inserts the given join point after this join point @@ -446,10 +533,10 @@ export class Joinpoint extends LaraJoinPoint { * Inserts the given join point after this join point */ insertAfter(p1: Joinpoint | string): Joinpoint { - eventListener.emit("ACTION", new Event(EventTime.BEFORE, "insertAfter", this, undefined, p1)); - const jp = wrapJoinPoint(this._javaObject.insertAfter(unwrapJoinPoint(p1))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "insertAfter", this, jp, p1)); - return jp; + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "insertAfter", this, undefined, p1)); + const res = wrapJoinPoint(this._javaObject.insertAfter(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "insertAfter", this, res, p1)); + return res; } /** * Inserts the given join point before this join point @@ -464,22 +551,27 @@ export class Joinpoint extends LaraJoinPoint { */ insertBefore(p1: Joinpoint | string): Joinpoint { eventListener.emit("ACTION", new Event(EventTime.BEFORE, "insertBefore", this, undefined, p1)); - const jp = wrapJoinPoint(this._javaObject.insertBefore(unwrapJoinPoint(p1))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "insertBefore", this, jp, p1)); - return jp; + const res = wrapJoinPoint(this._javaObject.insertBefore(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "insertBefore", this, res, p1)); + return res; } /** * Adds a message that will be printed to the user after weaving finishes. Identical messages are removed */ - messageToUser(message: string): void { return wrapJoinPoint(this._javaObject.messageToUser(unwrapJoinPoint(message))); } + messageToUser(message: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "messageToUser", this, undefined, message)); + const res = wrapJoinPoint(this._javaObject.messageToUser(unwrapJoinPoint(message))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "messageToUser", this, res, message)); + return res; + } /** * Removes the children of this node */ removeChildren(): void { eventListener.emit("ACTION", new Event(EventTime.BEFORE, "removeChildren", this, undefined)); - const jp = wrapJoinPoint(this._javaObject.removeChildren()); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "removeChildren", this, jp)); - return jp; + const res = wrapJoinPoint(this._javaObject.removeChildren()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "removeChildren", this, res)); + return res; } /** * Replaces this node with the given node @@ -498,31 +590,36 @@ export class Joinpoint extends LaraJoinPoint { */ replaceWith(p1: Joinpoint | string | Joinpoint[]): Joinpoint { eventListener.emit("ACTION", new Event(EventTime.BEFORE, "replaceWith", this, undefined, p1)); - const jp = wrapJoinPoint(this._javaObject.replaceWith(unwrapJoinPoint(p1))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "replaceWith", this, jp, p1)); - return jp; + const res = wrapJoinPoint(this._javaObject.replaceWith(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "replaceWith", this, res, p1)); + return res; } /** * Overload which accepts a list of strings */ replaceWithStrings(node: string[]): Joinpoint { eventListener.emit("ACTION", new Event(EventTime.BEFORE, "replaceWithStrings", this, undefined, node)); - const jp = wrapJoinPoint(this._javaObject.replaceWithStrings(unwrapJoinPoint(node))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "replaceWithStrings", this, jp, node)); - return jp; + const res = wrapJoinPoint(this._javaObject.replaceWithStrings(unwrapJoinPoint(node))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "replaceWithStrings", this, res, node)); + return res; } /** * Setting data directly is not supported, this action just emits a warning and does nothing */ - setData(source: object): void { return wrapJoinPoint(this._javaObject.setData(JSON.stringify(source))); } + setData(source: object): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setData", this, undefined, source)); + const res = wrapJoinPoint(this._javaObject.setData(JSON.stringify(source))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setData", this, res, source)); + return res; + } /** * Replaces the first child, or inserts the join point if no child is present */ setFirstChild(node: Joinpoint): void { eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setFirstChild", this, undefined, node)); - const jp = wrapJoinPoint(this._javaObject.setFirstChild(unwrapJoinPoint(node))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "setFirstChild", this, jp, node)); - return jp; + const res = wrapJoinPoint(this._javaObject.setFirstChild(unwrapJoinPoint(node))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setFirstChild", this, res, node)); + return res; } /** * Sets the commented that are embedded in a node @@ -537,27 +634,27 @@ export class Joinpoint extends LaraJoinPoint { */ setInlineComments(p1: string[] | string): void { eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setInlineComments", this, undefined, p1)); - const jp = wrapJoinPoint(this._javaObject.setInlineComments(unwrapJoinPoint(p1))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "setInlineComments", this, jp, p1)); - return jp; + const res = wrapJoinPoint(this._javaObject.setInlineComments(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setInlineComments", this, res, p1)); + return res; } /** * Replaces the last child, or inserts the join point if no child is present */ setLastChild(node: Joinpoint): void { eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setLastChild", this, undefined, node)); - const jp = wrapJoinPoint(this._javaObject.setLastChild(unwrapJoinPoint(node))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "setLastChild", this, jp, node)); - return jp; + const res = wrapJoinPoint(this._javaObject.setLastChild(unwrapJoinPoint(node))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setLastChild", this, res, node)); + return res; } /** * Sets the type of a node, if it has a type */ setType(type: Type): void { eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setType", this, undefined, type)); - const jp = wrapJoinPoint(this._javaObject.setType(unwrapJoinPoint(type))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "setType", this, jp, type)); - return jp; + const res = wrapJoinPoint(this._javaObject.setType(unwrapJoinPoint(type))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setType", this, res, type)); + return res; } /** * Associates arbitrary values to nodes of the AST @@ -572,34 +669,31 @@ export class Joinpoint extends LaraJoinPoint { */ setUserField(p1: string | Record, p2?: object): object { eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setUserField", this, undefined, p1, p2)); - const jp = wrapJoinPoint(this._javaObject.setUserField(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "setUserField", this, jp, p1, p2)); - return jp; + const res = wrapJoinPoint(this._javaObject.setUserField(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setUserField", this, res, p1, p2)); + return res; } /** * Sets the value associated with the given property key */ setValue(key: string, value: object): Joinpoint { eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setValue", this, undefined, key, value)); - const jp = wrapJoinPoint(this._javaObject.setValue(unwrapJoinPoint(key), unwrapJoinPoint(value))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "setValue", this, jp, key, value)); - return jp; + const res = wrapJoinPoint(this._javaObject.setValue(unwrapJoinPoint(key), unwrapJoinPoint(value))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setValue", this, res, key, value)); + return res; } /** * Replaces this join point with a comment with the same contents as .code */ toComment(prefix: string = "", suffix: string = ""): Joinpoint { eventListener.emit("ACTION", new Event(EventTime.BEFORE, "toComment", this, undefined, prefix, suffix)); - const jp = wrapJoinPoint(this._javaObject.toComment(unwrapJoinPoint(prefix), unwrapJoinPoint(suffix))); - eventListener.emit("ACTION", new Event(EventTime.AFTER, "toComment", this, jp, prefix, suffix)); - return jp; + const res = wrapJoinPoint(this._javaObject.toComment(unwrapJoinPoint(prefix), unwrapJoinPoint(suffix))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "toComment", this, res, prefix, suffix)); + return res; } } export class Attribute extends Joinpoint { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -610,9 +704,6 @@ export class Attribute extends Joinpoint { * Utility joinpoint, to represent certain problems when generating join points */ export class ClavaException extends Joinpoint { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -622,24 +713,23 @@ export class ClavaException extends Joinpoint { } export class Comment extends Joinpoint { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; get text(): string { return wrapJoinPoint(this._javaObject.getText()) } set text(value: string) { this._javaObject.setText(unwrapJoinPoint(value)); } - setText(text: string): void { return wrapJoinPoint(this._javaObject.setText(unwrapJoinPoint(text))); } + setText(text: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setText", this, undefined, text)); + const res = wrapJoinPoint(this._javaObject.setText(unwrapJoinPoint(text))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setText", this, res, text)); + return res; + } } /** * Represents one declaration (e.g., int foo(){return 0;}) or definition (e.g., int foo();) in the code */ export class Decl extends Joinpoint { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -653,18 +743,12 @@ export class Decl extends Joinpoint { * Utility joinpoint, to represent empty nodes when directly accessing the tree */ export class Empty extends Joinpoint { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; } export class Expression extends Joinpoint { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -688,9 +772,6 @@ export class Expression extends Joinpoint { * Represents a source file (.c, .cpp., .cl, etc) */ export class FileJp extends Joinpoint { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -761,27 +842,57 @@ export class FileJp extends Joinpoint { /** * The complete path to the file that will be generated by the weaver, given a destination folder */ - getDestinationFilepath(destinationFolderpath?: string): string { return wrapJoinPoint(this._javaObject.getDestinationFilepath(unwrapJoinPoint(destinationFolderpath))); } + getDestinationFilepath(destinationFolderpath?: string): string { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getDestinationFilepath", this, undefined, destinationFolderpath)); + const res = wrapJoinPoint(this._javaObject.getDestinationFilepath(unwrapJoinPoint(destinationFolderpath))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getDestinationFilepath", this, res, destinationFolderpath)); + return res; + } /** * Adds a C include to the current file. If the file already has the include, it does nothing */ - addCInclude(name: string, isAngled: boolean = false): void { return wrapJoinPoint(this._javaObject.addCInclude(unwrapJoinPoint(name), unwrapJoinPoint(isAngled))); } + addCInclude(name: string, isAngled: boolean = false): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addCInclude", this, undefined, name, isAngled)); + const res = wrapJoinPoint(this._javaObject.addCInclude(unwrapJoinPoint(name), unwrapJoinPoint(isAngled))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addCInclude", this, res, name, isAngled)); + return res; + } /** * Adds a function to the file that returns void and has no parameters */ - addFunction(name: string): Joinpoint { return wrapJoinPoint(this._javaObject.addFunction(unwrapJoinPoint(name))); } + addFunction(name: string): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addFunction", this, undefined, name)); + const res = wrapJoinPoint(this._javaObject.addFunction(unwrapJoinPoint(name))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addFunction", this, res, name)); + return res; + } /** * Adds a global variable to this file */ - addGlobal(name: string, type: Joinpoint, initValue: string): Vardecl { return wrapJoinPoint(this._javaObject.addGlobal(unwrapJoinPoint(name), unwrapJoinPoint(type), unwrapJoinPoint(initValue))); } + addGlobal(name: string, type: Joinpoint, initValue: string): Vardecl { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addGlobal", this, undefined, name, type, initValue)); + const res = wrapJoinPoint(this._javaObject.addGlobal(unwrapJoinPoint(name), unwrapJoinPoint(type), unwrapJoinPoint(initValue))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addGlobal", this, res, name, type, initValue)); + return res; + } /** * Adds an include to the current file. If the file already has the include, it does nothing */ - addInclude(name: string, isAngled: boolean = false): void { return wrapJoinPoint(this._javaObject.addInclude(unwrapJoinPoint(name), unwrapJoinPoint(isAngled))); } + addInclude(name: string, isAngled: boolean = false): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addInclude", this, undefined, name, isAngled)); + const res = wrapJoinPoint(this._javaObject.addInclude(unwrapJoinPoint(name), unwrapJoinPoint(isAngled))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addInclude", this, res, name, isAngled)); + return res; + } /** * Overload of addInclude which accepts a join point */ - addIncludeJp(jp: Joinpoint): void { return wrapJoinPoint(this._javaObject.addIncludeJp(unwrapJoinPoint(jp))); } + addIncludeJp(jp: Joinpoint): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addIncludeJp", this, undefined, jp)); + const res = wrapJoinPoint(this._javaObject.addIncludeJp(unwrapJoinPoint(jp))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addIncludeJp", this, res, jp)); + return res; + } /** * Adds the node in the join point to the start of the file */ @@ -793,7 +904,12 @@ export class FileJp extends Joinpoint { /** * Adds the node in the join point to the start of the file */ - insertBegin(p1: Joinpoint | string): void { return wrapJoinPoint(this._javaObject.insertBegin(unwrapJoinPoint(p1))); } + insertBegin(p1: Joinpoint | string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "insertBegin", this, undefined, p1)); + const res = wrapJoinPoint(this._javaObject.insertBegin(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "insertBegin", this, res, p1)); + return res; + } /** * Adds the node in the join point to the end of the file */ @@ -805,33 +921,60 @@ export class FileJp extends Joinpoint { /** * Adds the node in the join point to the end of the file */ - insertEnd(p1: Joinpoint | string): void { return wrapJoinPoint(this._javaObject.insertEnd(unwrapJoinPoint(p1))); } + insertEnd(p1: Joinpoint | string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "insertEnd", this, undefined, p1)); + const res = wrapJoinPoint(this._javaObject.insertEnd(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "insertEnd", this, res, p1)); + return res; + } /** * Recompiles only this file, returns a join point to the new recompiled file, or throws an exception if a problem happens */ - rebuild(): FileJp { return wrapJoinPoint(this._javaObject.rebuild()); } + rebuild(): FileJp { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "rebuild", this, undefined)); + const res = wrapJoinPoint(this._javaObject.rebuild()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "rebuild", this, res)); + return res; + } /** * Recompiles only this file, returns a join point to the new recompiled file, or returns a clavaException join point if a problem happens */ - rebuildTry(): Joinpoint { return wrapJoinPoint(this._javaObject.rebuildTry()); } + rebuildTry(): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "rebuildTry", this, undefined)); + const res = wrapJoinPoint(this._javaObject.rebuildTry()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "rebuildTry", this, res)); + return res; + } /** * Changes the name of the file */ - setName(filename: string): void { return wrapJoinPoint(this._javaObject.setName(unwrapJoinPoint(filename))); } + setName(filename: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setName", this, undefined, filename)); + const res = wrapJoinPoint(this._javaObject.setName(unwrapJoinPoint(filename))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setName", this, res, filename)); + return res; + } /** * Sets the path to the folder of the source file relative to the base source path */ - setRelativeFolderpath(path: string): void { return wrapJoinPoint(this._javaObject.setRelativeFolderpath(unwrapJoinPoint(path))); } + setRelativeFolderpath(path: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setRelativeFolderpath", this, undefined, path)); + const res = wrapJoinPoint(this._javaObject.setRelativeFolderpath(unwrapJoinPoint(path))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setRelativeFolderpath", this, res, path)); + return res; + } /** * Writes the code of this file to a given folder */ - write(destinationFoldername: string): string { return wrapJoinPoint(this._javaObject.write(unwrapJoinPoint(destinationFoldername))); } + write(destinationFoldername: string): string { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "write", this, undefined, destinationFoldername)); + const res = wrapJoinPoint(this._javaObject.write(unwrapJoinPoint(destinationFoldername))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "write", this, res, destinationFoldername)); + return res; + } } export class ImplicitValue extends Expression { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -841,9 +984,6 @@ export class ImplicitValue extends Expression { * Represents an include directive (e.g., #include ) */ export class Include extends Decl { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -862,9 +1002,6 @@ export class Include extends Decl { } export class InitList extends Expression { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -875,18 +1012,12 @@ export class InitList extends Expression { } export class Literal extends Expression { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; } export class MemberAccess extends Expression { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -905,16 +1036,18 @@ export class MemberAccess extends Expression { get memberChain(): Expression[] { return wrapJoinPoint(this._javaObject.getMemberChain()) } get memberChainNames(): string[] { return wrapJoinPoint(this._javaObject.getMemberChainNames()) } get name(): string { return wrapJoinPoint(this._javaObject.getName()) } - setArrow(isArrow: boolean): void { return wrapJoinPoint(this._javaObject.setArrow(unwrapJoinPoint(isArrow))); } + setArrow(isArrow: boolean): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setArrow", this, undefined, isArrow)); + const res = wrapJoinPoint(this._javaObject.setArrow(unwrapJoinPoint(isArrow))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setArrow", this, res, isArrow)); + return res; + } } /** * Represents a decl with a name */ export class NamedDecl extends Decl { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -928,30 +1061,39 @@ export class NamedDecl extends Decl { /** * Sets the name of this namedDecl */ - setName(name: string): void { return wrapJoinPoint(this._javaObject.setName(unwrapJoinPoint(name))); } + setName(name: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setName", this, undefined, name)); + const res = wrapJoinPoint(this._javaObject.setName(unwrapJoinPoint(name))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setName", this, res, name)); + return res; + } /** * Sets the qualified name of this namedDecl (changes both the name and qualified prefix) */ - setQualifiedName(name: string): void { return wrapJoinPoint(this._javaObject.setQualifiedName(unwrapJoinPoint(name))); } + setQualifiedName(name: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setQualifiedName", this, undefined, name)); + const res = wrapJoinPoint(this._javaObject.setQualifiedName(unwrapJoinPoint(name))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setQualifiedName", this, res, name)); + return res; + } /** * Sets the qualified prefix of this namedDecl */ - setQualifiedPrefix(qualifiedPrefix: string): void { return wrapJoinPoint(this._javaObject.setQualifiedPrefix(unwrapJoinPoint(qualifiedPrefix))); } + setQualifiedPrefix(qualifiedPrefix: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setQualifiedPrefix", this, undefined, qualifiedPrefix)); + const res = wrapJoinPoint(this._javaObject.setQualifiedPrefix(unwrapJoinPoint(qualifiedPrefix))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setQualifiedPrefix", this, res, qualifiedPrefix)); + return res; + } } export class NewExpr extends Expression { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; } export class Op extends Expression { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -964,9 +1106,6 @@ export class Op extends Expression { } export class ParenExpr extends Expression { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -980,9 +1119,6 @@ export class ParenExpr extends Expression { * Represents a pragma in the code (e.g., #pragma kernel) */ export class Pragma extends Joinpoint { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1009,18 +1145,30 @@ export class Pragma extends Joinpoint { /** * All the nodes below the target node, including the target node, up until a pragma with the name given by argument 'endPragma'. If no end pragma is found, returns the same result as if not providing the argument */ - getTargetNodes(endPragma?: string): Joinpoint[] { return wrapJoinPoint(this._javaObject.getTargetNodes(unwrapJoinPoint(endPragma))); } - setContent(content: string): void { return wrapJoinPoint(this._javaObject.setContent(unwrapJoinPoint(content))); } - setName(name: string): void { return wrapJoinPoint(this._javaObject.setName(unwrapJoinPoint(name))); } + getTargetNodes(endPragma?: string): Joinpoint[] { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getTargetNodes", this, undefined, endPragma)); + const res = wrapJoinPoint(this._javaObject.getTargetNodes(unwrapJoinPoint(endPragma))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getTargetNodes", this, res, endPragma)); + return res; + } + setContent(content: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setContent", this, undefined, content)); + const res = wrapJoinPoint(this._javaObject.setContent(unwrapJoinPoint(content))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setContent", this, res, content)); + return res; + } + setName(name: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setName", this, undefined, name)); + const res = wrapJoinPoint(this._javaObject.setName(unwrapJoinPoint(name))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setName", this, res, name)); + return res; + } } /** * Represents the complete program and is the top-most joinpoint in the hierarchy */ export class Program extends Joinpoint { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1069,64 +1217,126 @@ export class Program extends Joinpoint { /** * Adds a path to an include that the current program depends on */ - addExtraInclude(path: string): void { return wrapJoinPoint(this._javaObject.addExtraInclude(unwrapJoinPoint(path))); } + addExtraInclude(path: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addExtraInclude", this, undefined, path)); + const res = wrapJoinPoint(this._javaObject.addExtraInclude(unwrapJoinPoint(path))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addExtraInclude", this, res, path)); + return res; + } /** * Adds a path based on a git repository to an include that the current program depends on */ - addExtraIncludeFromGit(gitRepo: string, path?: string): void { return wrapJoinPoint(this._javaObject.addExtraIncludeFromGit(unwrapJoinPoint(gitRepo), unwrapJoinPoint(path))); } + addExtraIncludeFromGit(gitRepo: string, path?: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addExtraIncludeFromGit", this, undefined, gitRepo, path)); + const res = wrapJoinPoint(this._javaObject.addExtraIncludeFromGit(unwrapJoinPoint(gitRepo), unwrapJoinPoint(path))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addExtraIncludeFromGit", this, res, gitRepo, path)); + return res; + } /** * Adds a library (e.g., -pthreads) that the current program depends on */ - addExtraLib(lib: string): void { return wrapJoinPoint(this._javaObject.addExtraLib(unwrapJoinPoint(lib))); } + addExtraLib(lib: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addExtraLib", this, undefined, lib)); + const res = wrapJoinPoint(this._javaObject.addExtraLib(unwrapJoinPoint(lib))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addExtraLib", this, res, lib)); + return res; + } /** * Adds a path to a source that the current program depends on */ - addExtraSource(path: string): void { return wrapJoinPoint(this._javaObject.addExtraSource(unwrapJoinPoint(path))); } + addExtraSource(path: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addExtraSource", this, undefined, path)); + const res = wrapJoinPoint(this._javaObject.addExtraSource(unwrapJoinPoint(path))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addExtraSource", this, res, path)); + return res; + } /** * Adds a path based on a git repository to a source that the current program depends on */ - addExtraSourceFromGit(gitRepo: string, path?: string): void { return wrapJoinPoint(this._javaObject.addExtraSourceFromGit(unwrapJoinPoint(gitRepo), unwrapJoinPoint(path))); } + addExtraSourceFromGit(gitRepo: string, path?: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addExtraSourceFromGit", this, undefined, gitRepo, path)); + const res = wrapJoinPoint(this._javaObject.addExtraSourceFromGit(unwrapJoinPoint(gitRepo), unwrapJoinPoint(path))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addExtraSourceFromGit", this, res, gitRepo, path)); + return res; + } /** * Adds a file join point to the current program */ - addFile(file: FileJp): Joinpoint { return wrapJoinPoint(this._javaObject.addFile(unwrapJoinPoint(file))); } + addFile(file: FileJp): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addFile", this, undefined, file)); + const res = wrapJoinPoint(this._javaObject.addFile(unwrapJoinPoint(file))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addFile", this, res, file)); + return res; + } /** * Adds a file join point to the current program, from the given path, which can be either a Java File or a String */ - addFileFromPath(filepath: object): Joinpoint { return wrapJoinPoint(this._javaObject.addFileFromPath(unwrapJoinPoint(filepath))); } + addFileFromPath(filepath: object): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addFileFromPath", this, undefined, filepath)); + const res = wrapJoinPoint(this._javaObject.addFileFromPath(unwrapJoinPoint(filepath))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addFileFromPath", this, res, filepath)); + return res; + } /** * Adds a path based on a git repository to a project that the current program depends on */ - addProjectFromGit(gitRepo: string, libs: string[], path?: string): void { return wrapJoinPoint(this._javaObject.addProjectFromGit(unwrapJoinPoint(gitRepo), unwrapJoinPoint(libs), unwrapJoinPoint(path))); } + addProjectFromGit(gitRepo: string, libs: string[], path?: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addProjectFromGit", this, undefined, gitRepo, libs, path)); + const res = wrapJoinPoint(this._javaObject.addProjectFromGit(unwrapJoinPoint(gitRepo), unwrapJoinPoint(libs), unwrapJoinPoint(path))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addProjectFromGit", this, res, gitRepo, libs, path)); + return res; + } /** * Registers a function to be executed when the program exits */ - atexit(func: FunctionJp): void { return wrapJoinPoint(this._javaObject.atexit(unwrapJoinPoint(func))); } + atexit(func: FunctionJp): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "atexit", this, undefined, func)); + const res = wrapJoinPoint(this._javaObject.atexit(unwrapJoinPoint(func))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "atexit", this, res, func)); + return res; + } /** * Discards the AST at the top of the ASt stack */ - pop(): void { return wrapJoinPoint(this._javaObject.pop()); } + pop(): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "pop", this, undefined)); + const res = wrapJoinPoint(this._javaObject.pop()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "pop", this, res)); + return res; + } /** * Creates a copy of the current AST and pushes it to the top of the AST stack */ - push(): void { return wrapJoinPoint(this._javaObject.push()); } + push(): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "push", this, undefined)); + const res = wrapJoinPoint(this._javaObject.push()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "push", this, res)); + return res; + } /** * Recompiles the program currently represented by the AST, transforming literal code into AST nodes. Returns true if all files could be parsed correctly, or false otherwise */ - rebuild(): boolean { return wrapJoinPoint(this._javaObject.rebuild()); } + rebuild(): boolean { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "rebuild", this, undefined)); + const res = wrapJoinPoint(this._javaObject.rebuild()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "rebuild", this, res)); + return res; + } /** * Similar to rebuild, but tries to fix compilation errors. Resulting program may not represent the originally intended functionality */ - rebuildFuzzy(): void { return wrapJoinPoint(this._javaObject.rebuildFuzzy()); } + rebuildFuzzy(): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "rebuildFuzzy", this, undefined)); + const res = wrapJoinPoint(this._javaObject.rebuildFuzzy()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "rebuildFuzzy", this, res)); + return res; + } } /** * Common class of struct, union and class */ export class RecordJp extends NamedDecl { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1144,13 +1354,15 @@ export class RecordJp extends NamedDecl { /** * Adds a field to a record (struct, class). */ - addField(field: Field): void { return wrapJoinPoint(this._javaObject.addField(unwrapJoinPoint(field))); } + addField(field: Field): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addField", this, undefined, field)); + const res = wrapJoinPoint(this._javaObject.addField(unwrapJoinPoint(field))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addField", this, res, field)); + return res; + } } export class Statement extends Joinpoint { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1162,18 +1374,12 @@ export class Statement extends Joinpoint { * Represets a struct declaration */ export class Struct extends RecordJp { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; } export class Switch extends Statement { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1199,9 +1405,6 @@ export class Switch extends Statement { * A pragma that references a point in the code and sticks to it */ export class Tag extends Pragma { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "id", }; @@ -1212,9 +1415,6 @@ export class Tag extends Pragma { } export class TernaryOp extends Op { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1224,18 +1424,12 @@ export class TernaryOp extends Op { } export class This extends Expression { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; } export class Type extends Joinpoint { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1287,36 +1481,63 @@ export class Type extends Joinpoint { /** * Returns a new node based on this type with the qualifier const */ - asConst(): Type { return wrapJoinPoint(this._javaObject.asConst()); } + asConst(): Type { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "asConst", this, undefined)); + const res = wrapJoinPoint(this._javaObject.asConst()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "asConst", this, res)); + return res; + } /** * Sets the desugared type of this type */ - setDesugar(desugaredType: Type): void { return wrapJoinPoint(this._javaObject.setDesugar(unwrapJoinPoint(desugaredType))); } + setDesugar(desugaredType: Type): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setDesugar", this, undefined, desugaredType)); + const res = wrapJoinPoint(this._javaObject.setDesugar(unwrapJoinPoint(desugaredType))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setDesugar", this, res, desugaredType)); + return res; + } /** * Sets a single template argument type of a template type */ - setTemplateArgType(index: number, templateArgType: Type): void { return wrapJoinPoint(this._javaObject.setTemplateArgType(unwrapJoinPoint(index), unwrapJoinPoint(templateArgType))); } + setTemplateArgType(index: number, templateArgType: Type): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setTemplateArgType", this, undefined, index, templateArgType)); + const res = wrapJoinPoint(this._javaObject.setTemplateArgType(unwrapJoinPoint(index), unwrapJoinPoint(templateArgType))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setTemplateArgType", this, res, index, templateArgType)); + return res; + } /** * Sets the template argument types of a template type */ - setTemplateArgsTypes(templateArgTypes: Type[]): void { return wrapJoinPoint(this._javaObject.setTemplateArgsTypes(unwrapJoinPoint(templateArgTypes))); } + setTemplateArgsTypes(templateArgTypes: Type[]): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setTemplateArgsTypes", this, undefined, templateArgTypes)); + const res = wrapJoinPoint(this._javaObject.setTemplateArgsTypes(unwrapJoinPoint(templateArgTypes))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setTemplateArgsTypes", this, res, templateArgTypes)); + return res; + } /** * Changes a single occurence of a type field that has the current value with new value. Returns true if there was a change */ - setTypeFieldByValueRecursive(currentValue: object, newValue: object): boolean { return wrapJoinPoint(this._javaObject.setTypeFieldByValueRecursive(unwrapJoinPoint(currentValue), unwrapJoinPoint(newValue))); } + setTypeFieldByValueRecursive(currentValue: object, newValue: object): boolean { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setTypeFieldByValueRecursive", this, undefined, currentValue, newValue)); + const res = wrapJoinPoint(this._javaObject.setTypeFieldByValueRecursive(unwrapJoinPoint(currentValue), unwrapJoinPoint(newValue))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setTypeFieldByValueRecursive", this, res, currentValue, newValue)); + return res; + } /** * Replaces an underlying type of this instance with new type, if it matches the old type. Returns true if there were changes */ - setUnderlyingType(oldValue: Type, newValue: Type): Type { return wrapJoinPoint(this._javaObject.setUnderlyingType(unwrapJoinPoint(oldValue), unwrapJoinPoint(newValue))); } + setUnderlyingType(oldValue: Type, newValue: Type): Type { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setUnderlyingType", this, undefined, oldValue, newValue)); + const res = wrapJoinPoint(this._javaObject.setUnderlyingType(unwrapJoinPoint(oldValue), unwrapJoinPoint(newValue))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setUnderlyingType", this, res, oldValue, newValue)); + return res; + } } /** * Base node for declarations which introduce a typedef-name */ export class TypedefNameDecl extends NamedDecl { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1326,9 +1547,6 @@ export class TypedefNameDecl extends NamedDecl { * Represents the type of a typedef. */ export class TypedefType extends Type { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1343,9 +1561,6 @@ export class TypedefType extends Type { } export class UnaryExprOrType extends Expression { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1355,13 +1570,15 @@ export class UnaryExprOrType extends Expression { get hasArgExpr(): boolean { return wrapJoinPoint(this._javaObject.getHasArgExpr()) } get hasTypeExpr(): boolean { return wrapJoinPoint(this._javaObject.getHasTypeExpr()) } get kind(): string { return wrapJoinPoint(this._javaObject.getKind()) } - setArgType(argType: Type): void { return wrapJoinPoint(this._javaObject.setArgType(unwrapJoinPoint(argType))); } + setArgType(argType: Type): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setArgType", this, undefined, argType)); + const res = wrapJoinPoint(this._javaObject.setArgType(unwrapJoinPoint(argType))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setArgType", this, res, argType)); + return res; + } } export class UnaryOp extends Op { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1370,9 +1587,6 @@ export class UnaryOp extends Op { } export class UndefinedType extends Type { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1382,9 +1596,6 @@ export class UndefinedType extends Type { * A reference to a variable */ export class Varref extends Expression { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1408,13 +1619,15 @@ export class Varref extends Expression { * Expression from where the attribute 'use' is calculated. In certain cases (e.g., array access, pointer dereference) the 'use' attribute is not calculated on the node itself, but on an ancestor of the node. This attribute returns that node */ get useExpr(): Expression { return wrapJoinPoint(this._javaObject.getUseExpr()) } - setName(name: string): void { return wrapJoinPoint(this._javaObject.setName(unwrapJoinPoint(name))); } + setName(name: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setName", this, undefined, name)); + const res = wrapJoinPoint(this._javaObject.setName(unwrapJoinPoint(name))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setName", this, res, name)); + return res; + } } export class WrapperStmt extends Statement { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1423,9 +1636,6 @@ export class WrapperStmt extends Statement { } export class AccessSpecifier extends Decl { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "kind", }; @@ -1436,9 +1646,6 @@ export class AccessSpecifier extends Decl { } export class AdjustedType extends Type { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1449,9 +1656,6 @@ export class AdjustedType extends Type { } export class ArrayAccess extends Expression { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1478,9 +1682,6 @@ export class ArrayAccess extends Expression { } export class ArrayType extends Type { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1489,13 +1690,15 @@ export class ArrayType extends Type { /** * Sets the element type of the array */ - setElementType(arrayElementType: Type): void { return wrapJoinPoint(this._javaObject.setElementType(unwrapJoinPoint(arrayElementType))); } + setElementType(arrayElementType: Type): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setElementType", this, undefined, arrayElementType)); + const res = wrapJoinPoint(this._javaObject.setElementType(unwrapJoinPoint(arrayElementType))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setElementType", this, res, arrayElementType)); + return res; + } } export class BinaryOp extends Op { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1504,14 +1707,21 @@ export class BinaryOp extends Op { set left(value: Expression) { this._javaObject.setLeft(unwrapJoinPoint(value)); } get right(): Expression { return wrapJoinPoint(this._javaObject.getRight()) } set right(value: Expression) { this._javaObject.setRight(unwrapJoinPoint(value)); } - setLeft(left: Expression): void { return wrapJoinPoint(this._javaObject.setLeft(unwrapJoinPoint(left))); } - setRight(right: Expression): void { return wrapJoinPoint(this._javaObject.setRight(unwrapJoinPoint(right))); } + setLeft(left: Expression): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setLeft", this, undefined, left)); + const res = wrapJoinPoint(this._javaObject.setLeft(unwrapJoinPoint(left))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setLeft", this, res, left)); + return res; + } + setRight(right: Expression): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setRight", this, undefined, right)); + const res = wrapJoinPoint(this._javaObject.setRight(unwrapJoinPoint(right))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setRight", this, res, right)); + return res; + } } export class BoolLiteral extends Literal { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1519,9 +1729,6 @@ export class BoolLiteral extends Literal { } export class Break extends Statement { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1532,9 +1739,6 @@ export class Break extends Statement { } export class BuiltinType extends Type { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1562,9 +1766,6 @@ export class BuiltinType extends Type { } export class Call extends Expression { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1611,7 +1812,12 @@ export class Call extends Expression { * Similar to $function.signature, but if no function decl could be found (e.g., function from system include), returns a signature based on just the name of the function */ get signature(): string { return wrapJoinPoint(this._javaObject.getSignature()) } - getArg(index: number): Expression { return wrapJoinPoint(this._javaObject.getArg(unwrapJoinPoint(index))); } + getArg(index: number): Expression { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getArg", this, undefined, index)); + const res = wrapJoinPoint(this._javaObject.getArg(unwrapJoinPoint(index))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getArg", this, res, index)); + return res; + } /** * Adds an argument at the end of the call, creating an expression using the given code and type. If a type is not provided, a dummy type is used */ @@ -1623,27 +1829,54 @@ export class Call extends Expression { /** * Adds an argument at the end of the call, creating an expression using the given code and type. If a type is not provided, a dummy type is used */ - addArg(p1: string, p2?: Type | string): void { return wrapJoinPoint(this._javaObject.addArg(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); } + addArg(p1: string, p2?: Type | string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addArg", this, undefined, p1, p2)); + const res = wrapJoinPoint(this._javaObject.addArg(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addArg", this, res, p1, p2)); + return res; + } /** * Tries to inline this call */ - inline(): boolean { return wrapJoinPoint(this._javaObject.inline()); } - setArg(index: number, expr: Expression): void { return wrapJoinPoint(this._javaObject.setArg(unwrapJoinPoint(index), unwrapJoinPoint(expr))); } - setArgFromString(index: number, expr: string): void { return wrapJoinPoint(this._javaObject.setArgFromString(unwrapJoinPoint(index), unwrapJoinPoint(expr))); } + inline(): boolean { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "inline", this, undefined)); + const res = wrapJoinPoint(this._javaObject.inline()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "inline", this, res)); + return res; + } + setArg(index: number, expr: Expression): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setArg", this, undefined, index, expr)); + const res = wrapJoinPoint(this._javaObject.setArg(unwrapJoinPoint(index), unwrapJoinPoint(expr))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setArg", this, res, index, expr)); + return res; + } + setArgFromString(index: number, expr: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setArgFromString", this, undefined, index, expr)); + const res = wrapJoinPoint(this._javaObject.setArgFromString(unwrapJoinPoint(index), unwrapJoinPoint(expr))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setArgFromString", this, res, index, expr)); + return res; + } /** * Changes the name of the call */ - setName(name: string): void { return wrapJoinPoint(this._javaObject.setName(unwrapJoinPoint(name))); } + setName(name: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setName", this, undefined, name)); + const res = wrapJoinPoint(this._javaObject.setName(unwrapJoinPoint(name))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setName", this, res, name)); + return res; + } /** * Wraps this call with a possibly new wrapping function */ - wrap(name: string): void { return wrapJoinPoint(this._javaObject.wrap(unwrapJoinPoint(name))); } + wrap(name: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "wrap", this, undefined, name)); + const res = wrapJoinPoint(this._javaObject.wrap(unwrapJoinPoint(name))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "wrap", this, res, name)); + return res; + } } export class Case extends Statement { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1674,9 +1907,6 @@ export class Case extends Statement { } export class Cast extends Expression { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1690,18 +1920,12 @@ export class Cast extends Expression { } export class CilkSpawn extends Call { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; } export class CilkSync extends Statement { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1711,9 +1935,6 @@ export class CilkSync extends Statement { * Represents a C++ class */ export class Class extends RecordJp { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1760,35 +1981,41 @@ export class Class extends RecordJp { /** * Adds a method to a class. If the given method has a definition, creates an equivalent declaration and adds it to the class, otherwise simply added the declaration to the class. In both cases, the declaration is only added to the class if there is no declaration already with the same signature. */ - addMethod(method: Method): void { return wrapJoinPoint(this._javaObject.addMethod(unwrapJoinPoint(method))); } + addMethod(method: Method): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addMethod", this, undefined, method)); + const res = wrapJoinPoint(this._javaObject.addMethod(unwrapJoinPoint(method))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addMethod", this, res, method)); + return res; + } } export class Continue extends Statement { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; } export class CudaKernelCall extends Call { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; get config(): Expression[] { return wrapJoinPoint(this._javaObject.getConfig()) } set config(value: Expression[]) { this._javaObject.setConfig(unwrapJoinPoint(value)); } - setConfig(args: Expression[]): void { return wrapJoinPoint(this._javaObject.setConfig(unwrapJoinPoint(args))); } - setConfigFromStrings(args: string[]): void { return wrapJoinPoint(this._javaObject.setConfigFromStrings(unwrapJoinPoint(args))); } + setConfig(args: Expression[]): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setConfig", this, undefined, args)); + const res = wrapJoinPoint(this._javaObject.setConfig(unwrapJoinPoint(args))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setConfig", this, res, args)); + return res; + } + setConfigFromStrings(args: string[]): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setConfigFromStrings", this, undefined, args)); + const res = wrapJoinPoint(this._javaObject.setConfigFromStrings(unwrapJoinPoint(args))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setConfigFromStrings", this, res, args)); + return res; + } } export class DeclStmt extends Statement { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1802,18 +2029,12 @@ export class DeclStmt extends Statement { * Represents a decl that comes from a declarator (e.g., function, field, variable) */ export class Declarator extends NamedDecl { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; } export class DeleteExpr extends Expression { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1823,9 +2044,6 @@ export class DeleteExpr extends Expression { * Represents a type that was referred to using an elaborated type keyword, e.g., struct S, or via a qualified name, e.g., N::M::type, or both. This type is used to keep track of a type name as written in the source code, including tag keywords and any nested-name-specifiers. The type itself is always 'sugar', used to express what was written in the source code but containing no additional semantic information. */ export class ElaboratedType extends Type { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1844,9 +2062,6 @@ export class ElaboratedType extends Type { } export class EmptyStmt extends Statement { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1856,9 +2071,6 @@ export class EmptyStmt extends Statement { * Represents an enum */ export class EnumDecl extends NamedDecl { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1866,18 +2078,12 @@ export class EnumDecl extends NamedDecl { } export class EnumeratorDecl extends NamedDecl { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; } export class ExprStmt extends Statement { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1891,18 +2097,12 @@ export class ExprStmt extends Statement { * Represents a member of a struct/union/class */ export class Field extends Declarator { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; } export class FloatLiteral extends Literal { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1913,9 +2113,6 @@ export class FloatLiteral extends Literal { * Represents a function declaration or definition */ export class FunctionJp extends Declarator { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1981,7 +2178,12 @@ export class FunctionJp extends Declarator { */ get signature(): string { return wrapJoinPoint(this._javaObject.getSignature()) } get storageClass(): StorageClass { return wrapJoinPoint(this._javaObject.getStorageClass()) } - getDeclaration(withReturnType: boolean): string { return wrapJoinPoint(this._javaObject.getDeclaration(unwrapJoinPoint(withReturnType))); } + getDeclaration(withReturnType: boolean): string { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getDeclaration", this, undefined, withReturnType)); + const res = wrapJoinPoint(this._javaObject.getDeclaration(unwrapJoinPoint(withReturnType))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getDeclaration", this, res, withReturnType)); + return res; + } /** * Adds a new parameter to the function */ @@ -1993,11 +2195,21 @@ export class FunctionJp extends Declarator { /** * Adds a new parameter to the function */ - addParam(p1: Param | string, p2?: Type): void { return wrapJoinPoint(this._javaObject.addParam(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); } + addParam(p1: Param | string, p2?: Type): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addParam", this, undefined, p1, p2)); + const res = wrapJoinPoint(this._javaObject.addParam(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addParam", this, res, p1, p2)); + return res; + } /** * Clones this function assigning it a new name, inserts the cloned function after the original function. If the name is the same and the original method, automatically removes the cloned method from the class */ - clone(newName: string, insert: boolean = true): FunctionJp { return wrapJoinPoint(this._javaObject.clone(unwrapJoinPoint(newName), unwrapJoinPoint(insert))); } + clone(newName: string, insert: boolean = true): FunctionJp { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "clone", this, undefined, newName, insert)); + const res = wrapJoinPoint(this._javaObject.clone(unwrapJoinPoint(newName), unwrapJoinPoint(insert))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "clone", this, res, newName, insert)); + return res; + } /** * Generates a clone of the provided function on a new file with the provided name (or with a weaver-generated name if one is not provided). */ @@ -2009,7 +2221,12 @@ export class FunctionJp extends Declarator { /** * Generates a clone of the provided function on a new file with the provided name (or with a weaver-generated name if one is not provided). */ - cloneOnFile(p1: string, p2?: string | FileJp): FunctionJp { return wrapJoinPoint(this._javaObject.cloneOnFile(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); } + cloneOnFile(p1: string, p2?: string | FileJp): FunctionJp { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "cloneOnFile", this, undefined, p1, p2)); + const res = wrapJoinPoint(this._javaObject.cloneOnFile(unwrapJoinPoint(p1), unwrapJoinPoint(p2))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "cloneOnFile", this, res, p1, p2)); + return res; + } /** * Inserts the joinpoint before the return points of the function (return statements and implicitly, at the end of the function). Returns the last inserted node */ @@ -2021,19 +2238,39 @@ export class FunctionJp extends Declarator { /** * Inserts the joinpoint before the return points of the function (return statements and implicitly, at the end of the function). Returns the last inserted node */ - insertReturn(p1: Joinpoint | string): Joinpoint { return wrapJoinPoint(this._javaObject.insertReturn(unwrapJoinPoint(p1))); } + insertReturn(p1: Joinpoint | string): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "insertReturn", this, undefined, p1)); + const res = wrapJoinPoint(this._javaObject.insertReturn(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "insertReturn", this, res, p1)); + return res; + } /** * Creates a new call to this function */ - newCall(args: Joinpoint[]): Call { return wrapJoinPoint(this._javaObject.newCall(unwrapJoinPoint(args))); } + newCall(args: Joinpoint[]): Call { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "newCall", this, undefined, args)); + const res = wrapJoinPoint(this._javaObject.newCall(unwrapJoinPoint(args))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "newCall", this, res, args)); + return res; + } /** * Sets the body of the function */ - setBody(body: Scope): void { return wrapJoinPoint(this._javaObject.setBody(unwrapJoinPoint(body))); } + setBody(body: Scope): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setBody", this, undefined, body)); + const res = wrapJoinPoint(this._javaObject.setBody(unwrapJoinPoint(body))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setBody", this, res, body)); + return res; + } /** * Sets the type of the function */ - setFunctionType(functionType: FunctionType): void { return wrapJoinPoint(this._javaObject.setFunctionType(unwrapJoinPoint(functionType))); } + setFunctionType(functionType: FunctionType): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setFunctionType", this, undefined, functionType)); + const res = wrapJoinPoint(this._javaObject.setFunctionType(unwrapJoinPoint(functionType))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setFunctionType", this, res, functionType)); + return res; + } /** * Sets the parameter of the function at the given position */ @@ -2045,29 +2282,51 @@ export class FunctionJp extends Declarator { /** * Sets the parameter of the function at the given position */ - setParam(p1: number, p2: Param | string, p3?: Type): void { return wrapJoinPoint(this._javaObject.setParam(unwrapJoinPoint(p1), unwrapJoinPoint(p2), unwrapJoinPoint(p3))); } + setParam(p1: number, p2: Param | string, p3?: Type): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setParam", this, undefined, p1, p2, p3)); + const res = wrapJoinPoint(this._javaObject.setParam(unwrapJoinPoint(p1), unwrapJoinPoint(p2), unwrapJoinPoint(p3))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setParam", this, res, p1, p2, p3)); + return res; + } /** * Sets the type of a parameter of the function */ - setParamType(index: number, newType: Type): void { return wrapJoinPoint(this._javaObject.setParamType(unwrapJoinPoint(index), unwrapJoinPoint(newType))); } + setParamType(index: number, newType: Type): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setParamType", this, undefined, index, newType)); + const res = wrapJoinPoint(this._javaObject.setParamType(unwrapJoinPoint(index), unwrapJoinPoint(newType))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setParamType", this, res, index, newType)); + return res; + } /** * Sets the parameters of the function */ - setParams(params: Param[]): void { return wrapJoinPoint(this._javaObject.setParams(unwrapJoinPoint(params))); } + setParams(params: Param[]): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setParams", this, undefined, params)); + const res = wrapJoinPoint(this._javaObject.setParams(unwrapJoinPoint(params))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setParams", this, res, params)); + return res; + } /** * Overload that accepts strings that represent type-varname pairs (e.g., int param1) */ - setParamsFromStrings(params: string[]): void { return wrapJoinPoint(this._javaObject.setParamsFromStrings(unwrapJoinPoint(params))); } + setParamsFromStrings(params: string[]): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setParamsFromStrings", this, undefined, params)); + const res = wrapJoinPoint(this._javaObject.setParamsFromStrings(unwrapJoinPoint(params))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setParamsFromStrings", this, res, params)); + return res; + } /** * Sets the return type of the function */ - setReturnType(returnType: Type): void { return wrapJoinPoint(this._javaObject.setReturnType(unwrapJoinPoint(returnType))); } + setReturnType(returnType: Type): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setReturnType", this, undefined, returnType)); + const res = wrapJoinPoint(this._javaObject.setReturnType(unwrapJoinPoint(returnType))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setReturnType", this, res, returnType)); + return res; + } } export class FunctionType extends Type { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2077,17 +2336,24 @@ export class FunctionType extends Type { /** * Sets the type of a parameter of the FunctionType. Be careful that if you directly change the type of a paramemter and the function type is associated with a function declaration, this change will not be reflected in the function. If you want to change the type of a parameter of a function declaration, use $function.setParaType */ - setParamType(index: number, newType: Type): void { return wrapJoinPoint(this._javaObject.setParamType(unwrapJoinPoint(index), unwrapJoinPoint(newType))); } + setParamType(index: number, newType: Type): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setParamType", this, undefined, index, newType)); + const res = wrapJoinPoint(this._javaObject.setParamType(unwrapJoinPoint(index), unwrapJoinPoint(newType))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setParamType", this, res, index, newType)); + return res; + } /** * Sets the return type of the FunctionType */ - setReturnType(newType: Type): void { return wrapJoinPoint(this._javaObject.setReturnType(unwrapJoinPoint(newType))); } + setReturnType(newType: Type): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setReturnType", this, undefined, newType)); + const res = wrapJoinPoint(this._javaObject.setReturnType(unwrapJoinPoint(newType))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setReturnType", this, res, newType)); + return res; + } } export class GotoStmt extends Statement { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2096,13 +2362,15 @@ export class GotoStmt extends Statement { /** * Sets the label of the goto */ - setLabel(label: LabelDecl): void { return wrapJoinPoint(this._javaObject.setLabel(unwrapJoinPoint(label))); } + setLabel(label: LabelDecl): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setLabel", this, undefined, label)); + const res = wrapJoinPoint(this._javaObject.setLabel(unwrapJoinPoint(label))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setLabel", this, res, label)); + return res; + } } export class If extends Statement { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2116,21 +2384,33 @@ export class If extends Statement { /** * Sets the condition of the if */ - setCond(cond: Expression): void { return wrapJoinPoint(this._javaObject.setCond(unwrapJoinPoint(cond))); } + setCond(cond: Expression): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setCond", this, undefined, cond)); + const res = wrapJoinPoint(this._javaObject.setCond(unwrapJoinPoint(cond))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setCond", this, res, cond)); + return res; + } /** * Sets the body of the else */ - setElse(elseStatement: Statement): void { return wrapJoinPoint(this._javaObject.setElse(unwrapJoinPoint(elseStatement))); } + setElse(elseStatement: Statement): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setElse", this, undefined, elseStatement)); + const res = wrapJoinPoint(this._javaObject.setElse(unwrapJoinPoint(elseStatement))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setElse", this, res, elseStatement)); + return res; + } /** * Sets the body of the if */ - setThen(then: Statement): void { return wrapJoinPoint(this._javaObject.setThen(unwrapJoinPoint(then))); } + setThen(then: Statement): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setThen", this, undefined, then)); + const res = wrapJoinPoint(this._javaObject.setThen(unwrapJoinPoint(then))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setThen", this, res, then)); + return res; + } } export class IntLiteral extends Literal { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2138,18 +2418,12 @@ export class IntLiteral extends Literal { } export class LabelDecl extends NamedDecl { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; } export class LabelStmt extends Statement { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2158,13 +2432,15 @@ export class LabelStmt extends Statement { /** * Sets the label of the label statement */ - setDecl(label: LabelDecl): void { return wrapJoinPoint(this._javaObject.setDecl(unwrapJoinPoint(label))); } + setDecl(label: LabelDecl): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setDecl", this, undefined, label)); + const res = wrapJoinPoint(this._javaObject.setDecl(unwrapJoinPoint(label))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setDecl", this, res, label)); + return res; + } } export class Loop extends Statement { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "kind", }; @@ -2238,60 +2514,117 @@ export class Loop extends Statement { /** * Tests whether the loops are interchangeable. This is a conservative test. */ - isInterchangeable(otherLoop: Loop): boolean { return wrapJoinPoint(this._javaObject.isInterchangeable(unwrapJoinPoint(otherLoop))); } + isInterchangeable(otherLoop: Loop): boolean { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "isInterchangeable", this, undefined, otherLoop)); + const res = wrapJoinPoint(this._javaObject.isInterchangeable(unwrapJoinPoint(otherLoop))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "isInterchangeable", this, res, otherLoop)); + return res; + } /** * Interchanges two for loops, if possible */ - interchange(otherLoop: Loop): void { return wrapJoinPoint(this._javaObject.interchange(unwrapJoinPoint(otherLoop))); } + interchange(otherLoop: Loop): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "interchange", this, undefined, otherLoop)); + const res = wrapJoinPoint(this._javaObject.interchange(unwrapJoinPoint(otherLoop))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "interchange", this, res, otherLoop)); + return res; + } /** * Sets the body of the loop */ - setBody(body: Scope): void { return wrapJoinPoint(this._javaObject.setBody(unwrapJoinPoint(body))); } + setBody(body: Scope): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setBody", this, undefined, body)); + const res = wrapJoinPoint(this._javaObject.setBody(unwrapJoinPoint(body))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setBody", this, res, body)); + return res; + } /** * Sets the conditional statement of the loop. Works with loops of kind 'for' */ - setCond(condCode: string): void { return wrapJoinPoint(this._javaObject.setCond(unwrapJoinPoint(condCode))); } + setCond(condCode: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setCond", this, undefined, condCode)); + const res = wrapJoinPoint(this._javaObject.setCond(unwrapJoinPoint(condCode))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setCond", this, res, condCode)); + return res; + } /** * Changes the operator of a canonical condition, if possible. Supported operators: lt, le, gt, ge */ - setCondRelation(operator: Relation): void { return wrapJoinPoint(this._javaObject.setCondRelation(unwrapJoinPoint(operator))); } + setCondRelation(operator: Relation): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setCondRelation", this, undefined, operator)); + const res = wrapJoinPoint(this._javaObject.setCondRelation(unwrapJoinPoint(operator))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setCondRelation", this, res, operator)); + return res; + } /** * Sets the end value of the loop. Works with loops of kind 'for' */ - setEndValue(initCode: string): void { return wrapJoinPoint(this._javaObject.setEndValue(unwrapJoinPoint(initCode))); } + setEndValue(initCode: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setEndValue", this, undefined, initCode)); + const res = wrapJoinPoint(this._javaObject.setEndValue(unwrapJoinPoint(initCode))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setEndValue", this, res, initCode)); + return res; + } /** * Sets the init statement of the loop */ - setInit(initCode: string): void { return wrapJoinPoint(this._javaObject.setInit(unwrapJoinPoint(initCode))); } + setInit(initCode: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setInit", this, undefined, initCode)); + const res = wrapJoinPoint(this._javaObject.setInit(unwrapJoinPoint(initCode))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setInit", this, res, initCode)); + return res; + } /** * Sets the init value of the loop. Works with loops of kind 'for' */ - setInitValue(initCode: string): void { return wrapJoinPoint(this._javaObject.setInitValue(unwrapJoinPoint(initCode))); } + setInitValue(initCode: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setInitValue", this, undefined, initCode)); + const res = wrapJoinPoint(this._javaObject.setInitValue(unwrapJoinPoint(initCode))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setInitValue", this, res, initCode)); + return res; + } /** * Sets the attribute 'isParallel' of the loop */ - setIsParallel(isParallel: boolean): void { return wrapJoinPoint(this._javaObject.setIsParallel(unwrapJoinPoint(isParallel))); } + setIsParallel(isParallel: boolean): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setIsParallel", this, undefined, isParallel)); + const res = wrapJoinPoint(this._javaObject.setIsParallel(unwrapJoinPoint(isParallel))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setIsParallel", this, res, isParallel)); + return res; + } /** * Sets the kind of the loop */ - setKind(kind: string): void { return wrapJoinPoint(this._javaObject.setKind(unwrapJoinPoint(kind))); } + setKind(kind: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setKind", this, undefined, kind)); + const res = wrapJoinPoint(this._javaObject.setKind(unwrapJoinPoint(kind))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setKind", this, res, kind)); + return res; + } /** * Sets the step statement of the loop. Works with loops of kind 'for' */ - setStep(stepCode: string): void { return wrapJoinPoint(this._javaObject.setStep(unwrapJoinPoint(stepCode))); } + setStep(stepCode: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setStep", this, undefined, stepCode)); + const res = wrapJoinPoint(this._javaObject.setStep(unwrapJoinPoint(stepCode))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setStep", this, res, stepCode)); + return res; + } /** * Applies loop tiling to this loop. */ - tile(blockSize: string, reference: Statement, useTernary: boolean = true): Statement { return wrapJoinPoint(this._javaObject.tile(unwrapJoinPoint(blockSize), unwrapJoinPoint(reference), unwrapJoinPoint(useTernary))); } + tile(blockSize: string, reference: Statement, useTernary: boolean = true): Statement { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "tile", this, undefined, blockSize, reference, useTernary)); + const res = wrapJoinPoint(this._javaObject.tile(unwrapJoinPoint(blockSize), unwrapJoinPoint(reference), unwrapJoinPoint(useTernary))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "tile", this, res, blockSize, reference, useTernary)); + return res; + } } /** * Special pragma that can be used to mark scopes (e.g., #pragma lara marker loop1) */ export class Marker extends Pragma { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "id", }; @@ -2303,9 +2636,6 @@ export class Marker extends Pragma { } export class MemberCall extends Call { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -2317,9 +2647,6 @@ export class MemberCall extends Call { * Represents a C++ class method declaration or definition */ export class Method extends FunctionJp { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -2327,16 +2654,18 @@ export class Method extends FunctionJp { /** * Removes the of the method */ - removeRecord(): void { return wrapJoinPoint(this._javaObject.removeRecord()); } + removeRecord(): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "removeRecord", this, undefined)); + const res = wrapJoinPoint(this._javaObject.removeRecord()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "removeRecord", this, res)); + return res; + } } /** * Represents an OpenMP pragma (e.g., #pragma omp parallel) */ export class Omp extends Pragma { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "kind", }; @@ -2463,19 +2792,39 @@ export class Omp extends Pragma { /** * The variable names for the given reduction kind, or empty array if no reduction of that kind is defined */ - getReduction(kind: string): string[] { return wrapJoinPoint(this._javaObject.getReduction(unwrapJoinPoint(kind))); } + getReduction(kind: string): string[] { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getReduction", this, undefined, kind)); + const res = wrapJoinPoint(this._javaObject.getReduction(unwrapJoinPoint(kind))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getReduction", this, res, kind)); + return res; + } /** * True if the directive has at least one clause of the given clause kind, false otherwise */ - hasClause(clauseName: string): boolean { return wrapJoinPoint(this._javaObject.hasClause(unwrapJoinPoint(clauseName))); } + hasClause(clauseName: string): boolean { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "hasClause", this, undefined, clauseName)); + const res = wrapJoinPoint(this._javaObject.hasClause(unwrapJoinPoint(clauseName))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "hasClause", this, res, clauseName)); + return res; + } /** * True if it is legal to use the given clause kind in this directive, false otherwise */ - isClauseLegal(clauseName: string): boolean { return wrapJoinPoint(this._javaObject.isClauseLegal(unwrapJoinPoint(clauseName))); } + isClauseLegal(clauseName: string): boolean { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "isClauseLegal", this, undefined, clauseName)); + const res = wrapJoinPoint(this._javaObject.isClauseLegal(unwrapJoinPoint(clauseName))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "isClauseLegal", this, res, clauseName)); + return res; + } /** * Removes any clause of the given kind from the OpenMP pragma */ - removeClause(clauseKind: string): void { return wrapJoinPoint(this._javaObject.removeClause(unwrapJoinPoint(clauseKind))); } + removeClause(clauseKind: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "removeClause", this, undefined, clauseKind)); + const res = wrapJoinPoint(this._javaObject.removeClause(unwrapJoinPoint(clauseKind))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "removeClause", this, res, clauseKind)); + return res; + } /** * Sets the value of the collapse clause of an OpenMP pragma */ @@ -2487,47 +2836,102 @@ export class Omp extends Pragma { /** * Sets the value of the collapse clause of an OpenMP pragma */ - setCollapse(p1: string | number): void { return wrapJoinPoint(this._javaObject.setCollapse(unwrapJoinPoint(p1))); } + setCollapse(p1: string | number): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setCollapse", this, undefined, p1)); + const res = wrapJoinPoint(this._javaObject.setCollapse(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setCollapse", this, res, p1)); + return res; + } /** * Sets the variables of a copyin clause of an OpenMP pragma */ - setCopyin(newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setCopyin(unwrapJoinPoint(newVariables))); } + setCopyin(newVariables: string[]): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setCopyin", this, undefined, newVariables)); + const res = wrapJoinPoint(this._javaObject.setCopyin(unwrapJoinPoint(newVariables))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setCopyin", this, res, newVariables)); + return res; + } /** * Sets the value of the default clause of an OpenMP pragma */ - setDefault(newDefault: string): void { return wrapJoinPoint(this._javaObject.setDefault(unwrapJoinPoint(newDefault))); } + setDefault(newDefault: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setDefault", this, undefined, newDefault)); + const res = wrapJoinPoint(this._javaObject.setDefault(unwrapJoinPoint(newDefault))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setDefault", this, res, newDefault)); + return res; + } /** * Sets the variables of a firstprivate clause of an OpenMP pragma */ - setFirstprivate(newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setFirstprivate(unwrapJoinPoint(newVariables))); } + setFirstprivate(newVariables: string[]): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setFirstprivate", this, undefined, newVariables)); + const res = wrapJoinPoint(this._javaObject.setFirstprivate(unwrapJoinPoint(newVariables))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setFirstprivate", this, res, newVariables)); + return res; + } /** * Sets the directive kind of the OpenMP pragma. Any unsupported clauses will be discarded */ - setKind(directiveKind: string): void { return wrapJoinPoint(this._javaObject.setKind(unwrapJoinPoint(directiveKind))); } + setKind(directiveKind: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setKind", this, undefined, directiveKind)); + const res = wrapJoinPoint(this._javaObject.setKind(unwrapJoinPoint(directiveKind))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setKind", this, res, directiveKind)); + return res; + } /** * Sets the variables of a lastprivate clause of an OpenMP pragma */ - setLastprivate(newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setLastprivate(unwrapJoinPoint(newVariables))); } + setLastprivate(newVariables: string[]): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setLastprivate", this, undefined, newVariables)); + const res = wrapJoinPoint(this._javaObject.setLastprivate(unwrapJoinPoint(newVariables))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setLastprivate", this, res, newVariables)); + return res; + } /** * Sets the value of the num_threads clause of an OpenMP pragma */ - setNumThreads(newExpr: string): void { return wrapJoinPoint(this._javaObject.setNumThreads(unwrapJoinPoint(newExpr))); } + setNumThreads(newExpr: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setNumThreads", this, undefined, newExpr)); + const res = wrapJoinPoint(this._javaObject.setNumThreads(unwrapJoinPoint(newExpr))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setNumThreads", this, res, newExpr)); + return res; + } /** * Sets the value of the ordered clause of an OpenMP pragma */ - setOrdered(parameters?: string): void { return wrapJoinPoint(this._javaObject.setOrdered(unwrapJoinPoint(parameters))); } + setOrdered(parameters?: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setOrdered", this, undefined, parameters)); + const res = wrapJoinPoint(this._javaObject.setOrdered(unwrapJoinPoint(parameters))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setOrdered", this, res, parameters)); + return res; + } /** * Sets the variables of a private clause of an OpenMP pragma */ - setPrivate(newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setPrivate(unwrapJoinPoint(newVariables))); } + setPrivate(newVariables: string[]): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setPrivate", this, undefined, newVariables)); + const res = wrapJoinPoint(this._javaObject.setPrivate(unwrapJoinPoint(newVariables))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setPrivate", this, res, newVariables)); + return res; + } /** * Sets the value of the proc_bind clause of an OpenMP pragma */ - setProcBind(newBind: string): void { return wrapJoinPoint(this._javaObject.setProcBind(unwrapJoinPoint(newBind))); } + setProcBind(newBind: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setProcBind", this, undefined, newBind)); + const res = wrapJoinPoint(this._javaObject.setProcBind(unwrapJoinPoint(newBind))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setProcBind", this, res, newBind)); + return res; + } /** * Sets the variables for a given kind of a reduction clause of an OpenMP pragma */ - setReduction(kind: string, newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setReduction(unwrapJoinPoint(kind), unwrapJoinPoint(newVariables))); } + setReduction(kind: string, newVariables: string[]): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setReduction", this, undefined, kind, newVariables)); + const res = wrapJoinPoint(this._javaObject.setReduction(unwrapJoinPoint(kind), unwrapJoinPoint(newVariables))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setReduction", this, res, kind, newVariables)); + return res; + } /** * Sets the value of the chunck size in the schedule clause of an OpenMP pragma. Can only be called if there is already a schedule clause in the directive, otherwise throws an exception */ @@ -2539,25 +2943,42 @@ export class Omp extends Pragma { /** * Sets the value of the chunck size in the schedule clause of an OpenMP pragma. Can only be called if there is already a schedule clause in the directive, otherwise throws an exception */ - setScheduleChunkSize(p1: string | number): void { return wrapJoinPoint(this._javaObject.setScheduleChunkSize(unwrapJoinPoint(p1))); } + setScheduleChunkSize(p1: string | number): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setScheduleChunkSize", this, undefined, p1)); + const res = wrapJoinPoint(this._javaObject.setScheduleChunkSize(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setScheduleChunkSize", this, res, p1)); + return res; + } /** * Sets the value of the schedule clause of an OpenMP pragma */ - setScheduleKind(scheduleKind: string): void { return wrapJoinPoint(this._javaObject.setScheduleKind(unwrapJoinPoint(scheduleKind))); } + setScheduleKind(scheduleKind: string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setScheduleKind", this, undefined, scheduleKind)); + const res = wrapJoinPoint(this._javaObject.setScheduleKind(unwrapJoinPoint(scheduleKind))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setScheduleKind", this, res, scheduleKind)); + return res; + } /** * Sets the value of the modifiers in the schedule clause of an OpenMP pragma. Can only be called if there is already a schedule clause in the directive, otherwise throws an exception */ - setScheduleModifiers(modifiers: string[]): void { return wrapJoinPoint(this._javaObject.setScheduleModifiers(unwrapJoinPoint(modifiers))); } + setScheduleModifiers(modifiers: string[]): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setScheduleModifiers", this, undefined, modifiers)); + const res = wrapJoinPoint(this._javaObject.setScheduleModifiers(unwrapJoinPoint(modifiers))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setScheduleModifiers", this, res, modifiers)); + return res; + } /** * Sets the variables of a shared clause of an OpenMP pragma */ - setShared(newVariables: string[]): void { return wrapJoinPoint(this._javaObject.setShared(unwrapJoinPoint(newVariables))); } + setShared(newVariables: string[]): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setShared", this, undefined, newVariables)); + const res = wrapJoinPoint(this._javaObject.setShared(unwrapJoinPoint(newVariables))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setShared", this, res, newVariables)); + return res; + } } export class ParenType extends Type { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2566,13 +2987,15 @@ export class ParenType extends Type { /** * Sets the inner type of this paren type */ - setInnerType(innerType: Type): void { return wrapJoinPoint(this._javaObject.setInnerType(unwrapJoinPoint(innerType))); } + setInnerType(innerType: Type): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setInnerType", this, undefined, innerType)); + const res = wrapJoinPoint(this._javaObject.setInnerType(unwrapJoinPoint(innerType))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setInnerType", this, res, innerType)); + return res; + } } export class PointerType extends Type { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2585,13 +3008,15 @@ export class PointerType extends Type { /** * Sets the pointee type of this pointer type */ - setPointee(pointeeType: Type): void { return wrapJoinPoint(this._javaObject.setPointee(unwrapJoinPoint(pointeeType))); } + setPointee(pointeeType: Type): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setPointee", this, undefined, pointeeType)); + const res = wrapJoinPoint(this._javaObject.setPointee(unwrapJoinPoint(pointeeType))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setPointee", this, res, pointeeType)); + return res; + } } export class QualType extends Type { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2600,9 +3025,6 @@ export class QualType extends Type { } export class ReturnStmt extends Statement { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2613,9 +3035,6 @@ export class ReturnStmt extends Statement { * Represents a group of statements */ export class Scope extends Statement { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2644,29 +3063,64 @@ export class Scope extends Statement { /** * The number of statements in the scope, including the statements inside the declaration and bodies of structures such as ifs and loops, and not considering comments and pragmas. If flat is true, does not consider the statements inside structures such as ifs and loops (e.g., a loop counts as one statement) */ - getNumStatements(flat: boolean = false): number { return wrapJoinPoint(this._javaObject.getNumStatements(unwrapJoinPoint(flat))); } + getNumStatements(flat: boolean = false): number { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "getNumStatements", this, undefined, flat)); + const res = wrapJoinPoint(this._javaObject.getNumStatements(unwrapJoinPoint(flat))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "getNumStatements", this, res, flat)); + return res; + } /** * Adds a new local variable to this scope */ - addLocal(name: string, type: Joinpoint, initValue?: string): Joinpoint { return wrapJoinPoint(this._javaObject.addLocal(unwrapJoinPoint(name), unwrapJoinPoint(type), unwrapJoinPoint(initValue))); } + addLocal(name: string, type: Joinpoint, initValue?: string): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "addLocal", this, undefined, name, type, initValue)); + const res = wrapJoinPoint(this._javaObject.addLocal(unwrapJoinPoint(name), unwrapJoinPoint(type), unwrapJoinPoint(initValue))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "addLocal", this, res, name, type, initValue)); + return res; + } /** * CFG tester */ - cfg(): string { return wrapJoinPoint(this._javaObject.cfg()); } + cfg(): string { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "cfg", this, undefined)); + const res = wrapJoinPoint(this._javaObject.cfg()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "cfg", this, res)); + return res; + } /** * Clears the contents of this scope (untested) */ - clear(): void { return wrapJoinPoint(this._javaObject.clear()); } + clear(): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "clear", this, undefined)); + const res = wrapJoinPoint(this._javaObject.clear()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "clear", this, res)); + return res; + } /** * DFG tester */ - dfg(): string { return wrapJoinPoint(this._javaObject.dfg()); } + dfg(): string { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "dfg", this, undefined)); + const res = wrapJoinPoint(this._javaObject.dfg()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "dfg", this, res)); + return res; + } insertBegin(node: Joinpoint): Joinpoint; insertBegin(code: string): Joinpoint; - insertBegin(p1: Joinpoint | string): Joinpoint { return wrapJoinPoint(this._javaObject.insertBegin(unwrapJoinPoint(p1))); } + insertBegin(p1: Joinpoint | string): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "insertBegin", this, undefined, p1)); + const res = wrapJoinPoint(this._javaObject.insertBegin(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "insertBegin", this, res, p1)); + return res; + } insertEnd(node: Joinpoint): Joinpoint; insertEnd(code: string): Joinpoint; - insertEnd(p1: Joinpoint | string): Joinpoint { return wrapJoinPoint(this._javaObject.insertEnd(unwrapJoinPoint(p1))); } + insertEnd(p1: Joinpoint | string): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "insertEnd", this, undefined, p1)); + const res = wrapJoinPoint(this._javaObject.insertEnd(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "insertEnd", this, res, p1)); + return res; + } /** * Inserts the joinpoint before the return points of the scope (return statements and implicitly, at the end of the scope). Returns the last inserted node */ @@ -2678,17 +3132,24 @@ export class Scope extends Statement { /** * Inserts the joinpoint before the return points of the scope (return statements and implicitly, at the end of the scope). Returns the last inserted node */ - insertReturn(p1: Joinpoint | string): Joinpoint { return wrapJoinPoint(this._javaObject.insertReturn(unwrapJoinPoint(p1))); } + insertReturn(p1: Joinpoint | string): Joinpoint { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "insertReturn", this, undefined, p1)); + const res = wrapJoinPoint(this._javaObject.insertReturn(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "insertReturn", this, res, p1)); + return res; + } /** * Sets the 'naked' status of a scope (a scope is naked if it does not have curly braces) */ - setNaked(isNaked: boolean): void { return wrapJoinPoint(this._javaObject.setNaked(unwrapJoinPoint(isNaked))); } + setNaked(isNaked: boolean): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setNaked", this, undefined, isNaked)); + const res = wrapJoinPoint(this._javaObject.setNaked(unwrapJoinPoint(isNaked))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setNaked", this, res, isNaked)); + return res; + } } export class TagType extends Type { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2700,9 +3161,6 @@ export class TagType extends Type { } export class TemplateSpecializationType extends Type { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2716,9 +3174,6 @@ export class TemplateSpecializationType extends Type { * Declaration of a typedef-name via the 'typedef' type specifier */ export class TypedefDecl extends TypedefNameDecl { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -2728,9 +3183,6 @@ export class TypedefDecl extends TypedefNameDecl { * Represents a variable declaration or definition */ export class Vardecl extends Declarator { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -2773,7 +3225,12 @@ export class Vardecl extends Declarator { /** * If vardecl already has an initialization, removes it. */ - removeInit(removeConst: boolean = true): void { return wrapJoinPoint(this._javaObject.removeInit(unwrapJoinPoint(removeConst))); } + removeInit(removeConst: boolean = true): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "removeInit", this, undefined, removeConst)); + const res = wrapJoinPoint(this._javaObject.removeInit(unwrapJoinPoint(removeConst))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "removeInit", this, res, removeConst)); + return res; + } /** * Sets the given expression as the initialization of this vardecl. If undefined is passed and vardecl already has an initialization, removes that initialization */ @@ -2785,21 +3242,33 @@ export class Vardecl extends Declarator { /** * Sets the given expression as the initialization of this vardecl. If undefined is passed and vardecl already has an initialization, removes that initialization */ - setInit(p1: Expression | string): void { return wrapJoinPoint(this._javaObject.setInit(unwrapJoinPoint(p1))); } + setInit(p1: Expression | string): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setInit", this, undefined, p1)); + const res = wrapJoinPoint(this._javaObject.setInit(unwrapJoinPoint(p1))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setInit", this, res, p1)); + return res; + } /** * Sets the storage class specifier, which can be none, extern, static, __private_extern__, autovardecl */ - setStorageClass(storageClass: StorageClass): void { return wrapJoinPoint(this._javaObject.setStorageClass(unwrapJoinPoint(storageClass))); } + setStorageClass(storageClass: StorageClass): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setStorageClass", this, undefined, storageClass)); + const res = wrapJoinPoint(this._javaObject.setStorageClass(unwrapJoinPoint(storageClass))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setStorageClass", this, res, storageClass)); + return res; + } /** * Creates a new varref based on this vardecl */ - varref(): Varref { return wrapJoinPoint(this._javaObject.varref()); } + varref(): Varref { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "varref", this, undefined)); + const res = wrapJoinPoint(this._javaObject.varref()); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "varref", this, res)); + return res; + } } export class VariableArrayType extends ArrayType { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2808,31 +3277,27 @@ export class VariableArrayType extends ArrayType { /** * Sets the size expression of this variable array type */ - setSizeExpr(sizeExpr: Expression): void { return wrapJoinPoint(this._javaObject.setSizeExpr(unwrapJoinPoint(sizeExpr))); } + setSizeExpr(sizeExpr: Expression): void { + eventListener.emit("ACTION", new Event(EventTime.BEFORE, "setSizeExpr", this, undefined, sizeExpr)); + const res = wrapJoinPoint(this._javaObject.setSizeExpr(unwrapJoinPoint(sizeExpr))); + eventListener.emit("ACTION", new Event(EventTime.AFTER, "setSizeExpr", this, res, sizeExpr)); + return res; + } } export class Body extends Scope { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; } export class CilkFor extends Loop { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "kind", }; } export class EnumType extends TagType { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2840,9 +3305,6 @@ export class EnumType extends TagType { } export class Param extends Vardecl { - /** - * @hidden - */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; From 8c4904653e3da0fc05624b8290b90f41424d3247 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Wed, 24 Jul 2024 14:46:52 +0100 Subject: [PATCH 32/38] feat: updated Joinpoints.ts --- Clava-JS/src-api/Joinpoints.ts | 258 +++++++++++++++++++++++++++++++++ 1 file changed, 258 insertions(+) diff --git a/Clava-JS/src-api/Joinpoints.ts b/Clava-JS/src-api/Joinpoints.ts index c0e741679..d11c442a5 100644 --- a/Clava-JS/src-api/Joinpoints.ts +++ b/Clava-JS/src-api/Joinpoints.ts @@ -143,6 +143,9 @@ type DefaultAttributeMap = { } export class Joinpoint extends LaraJoinPoint { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -694,6 +697,9 @@ export class Joinpoint extends LaraJoinPoint { } export class Attribute extends Joinpoint { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -704,6 +710,9 @@ export class Attribute extends Joinpoint { * Utility joinpoint, to represent certain problems when generating join points */ export class ClavaException extends Joinpoint { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -713,6 +722,9 @@ export class ClavaException extends Joinpoint { } export class Comment extends Joinpoint { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -730,6 +742,9 @@ export class Comment extends Joinpoint { * Represents one declaration (e.g., int foo(){return 0;}) or definition (e.g., int foo();) in the code */ export class Decl extends Joinpoint { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -743,12 +758,18 @@ export class Decl extends Joinpoint { * Utility joinpoint, to represent empty nodes when directly accessing the tree */ export class Empty extends Joinpoint { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; } export class Expression extends Joinpoint { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -772,6 +793,9 @@ export class Expression extends Joinpoint { * Represents a source file (.c, .cpp., .cl, etc) */ export class FileJp extends Joinpoint { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -975,6 +999,9 @@ export class FileJp extends Joinpoint { } export class ImplicitValue extends Expression { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -984,6 +1011,9 @@ export class ImplicitValue extends Expression { * Represents an include directive (e.g., #include ) */ export class Include extends Decl { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1002,6 +1032,9 @@ export class Include extends Decl { } export class InitList extends Expression { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1012,12 +1045,18 @@ export class InitList extends Expression { } export class Literal extends Expression { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; } export class MemberAccess extends Expression { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1048,6 +1087,9 @@ export class MemberAccess extends Expression { * Represents a decl with a name */ export class NamedDecl extends Decl { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1088,12 +1130,18 @@ export class NamedDecl extends Decl { } export class NewExpr extends Expression { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; } export class Op extends Expression { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1106,6 +1154,9 @@ export class Op extends Expression { } export class ParenExpr extends Expression { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1119,6 +1170,9 @@ export class ParenExpr extends Expression { * Represents a pragma in the code (e.g., #pragma kernel) */ export class Pragma extends Joinpoint { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1169,6 +1223,9 @@ export class Pragma extends Joinpoint { * Represents the complete program and is the top-most joinpoint in the hierarchy */ export class Program extends Joinpoint { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1337,6 +1394,9 @@ export class Program extends Joinpoint { * Common class of struct, union and class */ export class RecordJp extends NamedDecl { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1363,6 +1423,9 @@ export class RecordJp extends NamedDecl { } export class Statement extends Joinpoint { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1374,12 +1437,18 @@ export class Statement extends Joinpoint { * Represets a struct declaration */ export class Struct extends RecordJp { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; } export class Switch extends Statement { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1405,6 +1474,9 @@ export class Switch extends Statement { * A pragma that references a point in the code and sticks to it */ export class Tag extends Pragma { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "id", }; @@ -1415,6 +1487,9 @@ export class Tag extends Pragma { } export class TernaryOp extends Op { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1424,12 +1499,18 @@ export class TernaryOp extends Op { } export class This extends Expression { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; } export class Type extends Joinpoint { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1538,6 +1619,9 @@ export class Type extends Joinpoint { * Base node for declarations which introduce a typedef-name */ export class TypedefNameDecl extends NamedDecl { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1547,6 +1631,9 @@ export class TypedefNameDecl extends NamedDecl { * Represents the type of a typedef. */ export class TypedefType extends Type { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1561,6 +1648,9 @@ export class TypedefType extends Type { } export class UnaryExprOrType extends Expression { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1579,6 +1669,9 @@ export class UnaryExprOrType extends Expression { } export class UnaryOp extends Op { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1587,6 +1680,9 @@ export class UnaryOp extends Op { } export class UndefinedType extends Type { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1596,6 +1692,9 @@ export class UndefinedType extends Type { * A reference to a variable */ export class Varref extends Expression { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1628,6 +1727,9 @@ export class Varref extends Expression { } export class WrapperStmt extends Statement { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1636,6 +1738,9 @@ export class WrapperStmt extends Statement { } export class AccessSpecifier extends Decl { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "kind", }; @@ -1646,6 +1751,9 @@ export class AccessSpecifier extends Decl { } export class AdjustedType extends Type { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1656,6 +1764,9 @@ export class AdjustedType extends Type { } export class ArrayAccess extends Expression { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1682,6 +1793,9 @@ export class ArrayAccess extends Expression { } export class ArrayType extends Type { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1699,6 +1813,9 @@ export class ArrayType extends Type { } export class BinaryOp extends Op { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1722,6 +1839,9 @@ export class BinaryOp extends Op { } export class BoolLiteral extends Literal { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1729,6 +1849,9 @@ export class BoolLiteral extends Literal { } export class Break extends Statement { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1739,6 +1862,9 @@ export class Break extends Statement { } export class BuiltinType extends Type { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1766,6 +1892,9 @@ export class BuiltinType extends Type { } export class Call extends Expression { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1877,6 +2006,9 @@ export class Call extends Expression { } export class Case extends Statement { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1907,6 +2039,9 @@ export class Case extends Statement { } export class Cast extends Expression { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1920,12 +2055,18 @@ export class Cast extends Expression { } export class CilkSpawn extends Call { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; } export class CilkSync extends Statement { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -1935,6 +2076,9 @@ export class CilkSync extends Statement { * Represents a C++ class */ export class Class extends RecordJp { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -1990,12 +2134,18 @@ export class Class extends RecordJp { } export class Continue extends Statement { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; } export class CudaKernelCall extends Call { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -2016,6 +2166,9 @@ export class CudaKernelCall extends Call { } export class DeclStmt extends Statement { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2029,12 +2182,18 @@ export class DeclStmt extends Statement { * Represents a decl that comes from a declarator (e.g., function, field, variable) */ export class Declarator extends NamedDecl { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; } export class DeleteExpr extends Expression { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2044,6 +2203,9 @@ export class DeleteExpr extends Expression { * Represents a type that was referred to using an elaborated type keyword, e.g., struct S, or via a qualified name, e.g., N::M::type, or both. This type is used to keep track of a type name as written in the source code, including tag keywords and any nested-name-specifiers. The type itself is always 'sugar', used to express what was written in the source code but containing no additional semantic information. */ export class ElaboratedType extends Type { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2062,6 +2224,9 @@ export class ElaboratedType extends Type { } export class EmptyStmt extends Statement { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2071,6 +2236,9 @@ export class EmptyStmt extends Statement { * Represents an enum */ export class EnumDecl extends NamedDecl { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -2078,12 +2246,18 @@ export class EnumDecl extends NamedDecl { } export class EnumeratorDecl extends NamedDecl { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; } export class ExprStmt extends Statement { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2097,12 +2271,18 @@ export class ExprStmt extends Statement { * Represents a member of a struct/union/class */ export class Field extends Declarator { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; } export class FloatLiteral extends Literal { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2113,6 +2293,9 @@ export class FloatLiteral extends Literal { * Represents a function declaration or definition */ export class FunctionJp extends Declarator { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -2327,6 +2510,9 @@ export class FunctionJp extends Declarator { } export class FunctionType extends Type { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2354,6 +2540,9 @@ export class FunctionType extends Type { } export class GotoStmt extends Statement { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2371,6 +2560,9 @@ export class GotoStmt extends Statement { } export class If extends Statement { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2411,6 +2603,9 @@ export class If extends Statement { } export class IntLiteral extends Literal { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2418,12 +2613,18 @@ export class IntLiteral extends Literal { } export class LabelDecl extends NamedDecl { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; } export class LabelStmt extends Statement { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2441,6 +2642,9 @@ export class LabelStmt extends Statement { } export class Loop extends Statement { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "kind", }; @@ -2625,6 +2829,9 @@ export class Loop extends Statement { * Special pragma that can be used to mark scopes (e.g., #pragma lara marker loop1) */ export class Marker extends Pragma { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "id", }; @@ -2636,6 +2843,9 @@ export class Marker extends Pragma { } export class MemberCall extends Call { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -2647,6 +2857,9 @@ export class MemberCall extends Call { * Represents a C++ class method declaration or definition */ export class Method extends FunctionJp { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -2666,6 +2879,9 @@ export class Method extends FunctionJp { * Represents an OpenMP pragma (e.g., #pragma omp parallel) */ export class Omp extends Pragma { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "kind", }; @@ -2979,6 +3195,9 @@ export class Omp extends Pragma { } export class ParenType extends Type { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -2996,6 +3215,9 @@ export class ParenType extends Type { } export class PointerType extends Type { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -3017,6 +3239,9 @@ export class PointerType extends Type { } export class QualType extends Type { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -3025,6 +3250,9 @@ export class QualType extends Type { } export class ReturnStmt extends Statement { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -3035,6 +3263,9 @@ export class ReturnStmt extends Statement { * Represents a group of statements */ export class Scope extends Statement { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -3150,6 +3381,9 @@ export class Scope extends Statement { } export class TagType extends Type { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -3161,6 +3395,9 @@ export class TagType extends Type { } export class TemplateSpecializationType extends Type { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -3174,6 +3411,9 @@ export class TemplateSpecializationType extends Type { * Declaration of a typedef-name via the 'typedef' type specifier */ export class TypedefDecl extends TypedefNameDecl { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -3183,6 +3423,9 @@ export class TypedefDecl extends TypedefNameDecl { * Represents a variable declaration or definition */ export class Vardecl extends Declarator { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; @@ -3269,6 +3512,9 @@ export class Vardecl extends Declarator { } export class VariableArrayType extends ArrayType { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -3286,18 +3532,27 @@ export class VariableArrayType extends ArrayType { } export class Body extends Scope { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; } export class CilkFor extends Loop { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "kind", }; } export class EnumType extends TagType { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: null, }; @@ -3305,6 +3560,9 @@ export class EnumType extends TagType { } export class Param extends Vardecl { + /** + * @hidden + */ static readonly _defaultAttributeInfo: {readonly map?: DefaultAttributeMap, readonly name: string | null, readonly type?: PrivateMapper, readonly jpMapper?: typeof JoinpointMapper} = { name: "name", }; From 789b726f930473834f8104e9c23829cba844983a Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Wed, 24 Jul 2024 14:57:58 +0100 Subject: [PATCH 33/38] fix: code cleanup --- Clava-JS/src-api/clava/history/EventListener.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Clava-JS/src-api/clava/history/EventListener.ts b/Clava-JS/src-api/clava/history/EventListener.ts index ed8f4243e..e95f0f53a 100644 --- a/Clava-JS/src-api/clava/history/EventListener.ts +++ b/Clava-JS/src-api/clava/history/EventListener.ts @@ -8,18 +8,9 @@ import { Joinpoint } from "../../Joinpoints.js"; const eventListener = new EventEmitter(); -// Used for counting number of waypoints -let idx = 0; - // Used for saving previous child in setFirstChild and setLastChild let auxJP: Joinpoint; -eventListener.on("storeAST", () => { - console.log(`Waypoint ${idx}`); - fs.writeFileSync(`history/waypoint_${idx}.cpp`, Clava.getProgram().code); - idx++; -}); - eventListener.on("ACTION", (e: Event) => { switch (e.timing) { From 6e87725e067a1876350ff0def4c6791063b4b25c Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Wed, 24 Jul 2024 17:45:35 +0100 Subject: [PATCH 34/38] fix: restructure the undo operations in the History class --- Clava-JS/src-api/clava/history/History.ts | 38 ++++++++++------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/Clava-JS/src-api/clava/history/History.ts b/Clava-JS/src-api/clava/history/History.ts index 020ec62f1..b2e99ba66 100644 --- a/Clava-JS/src-api/clava/history/History.ts +++ b/Clava-JS/src-api/clava/history/History.ts @@ -17,6 +17,20 @@ class OperationHistory { this.locked = false; } + private undo() { + const op = this.operations.pop(); + if (op !== undefined) { + try { + this.lock(); + op.undo(); + } catch (error) { + console.error("Failed to undo operation:", error); + } finally { + this.unlock(); + } + } + } + newOperation(operation: Operation) { if (!this.locked) { this.operations.push(operation); @@ -26,17 +40,7 @@ class OperationHistory { rollback(n: number = 1) { if (n > 0){ while (n--){ - const op = this.operations.pop(); - if (op !== undefined) { - try { - this.lock(); - op.undo(); - } catch (error) { - console.error("Failed to undo operation:", error); - } finally { - this.unlock(); - } - } + this.undo(); } } } @@ -47,17 +51,7 @@ class OperationHistory { returnToLastCheckpoint() { while (this.operations.length > 0) { - const op = this.operations.pop(); - if (op !== undefined) { - try { - this.lock(); - op.undo(); - } catch (error) { - console.error("Failed to undo operation:", error); - } finally { - this.unlock(); - } - } + this.undo(); } } } From b07b0dec22736f6f61fadced6dddd82537dee27e Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Fri, 26 Jul 2024 09:46:08 +0100 Subject: [PATCH 35/38] feat: added start and stop operations to history to improve performance when not being used --- .../src-api/clava/history/EventListener.ts | 2 -- .../src-api/clava/history/History.test.ts | 33 +++++++++++++++++++ Clava-JS/src-api/clava/history/History.ts | 11 ++++++- .../src-api/clava/history/Operations.test.ts | 1 + 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/Clava-JS/src-api/clava/history/EventListener.ts b/Clava-JS/src-api/clava/history/EventListener.ts index e95f0f53a..7c62dad28 100644 --- a/Clava-JS/src-api/clava/history/EventListener.ts +++ b/Clava-JS/src-api/clava/history/EventListener.ts @@ -1,6 +1,4 @@ import { EventEmitter } from "events"; -import * as fs from "fs"; -import Clava from "../Clava.js"; import { Event, EventTime } from "./Events.js"; import ophistory from "./History.js"; import { DetachOperation, DetachReference, InlineCommentOperation, InsertOperation, RemoveChildrenOperation, ReplaceOperation, SetChildOperation, TypeChangeOperation, ValueOperation } from "./Operations.js"; diff --git a/Clava-JS/src-api/clava/history/History.test.ts b/Clava-JS/src-api/clava/history/History.test.ts index 3f543edc3..0fa4f1cd4 100644 --- a/Clava-JS/src-api/clava/history/History.test.ts +++ b/Clava-JS/src-api/clava/history/History.test.ts @@ -25,6 +25,7 @@ int main(int argc, char *argv[]) { describe("Transformation History: Multiple operations", () => { registerSourceCode(code); + ophistory.start(); it("Inserts and detaches code comparison", () => { const a: string = Clava.getProgram().code; @@ -143,4 +144,36 @@ describe("Transformation History: Multiple operations", () => { errorSpy.mockRestore(); }); + it("Start and stop history recording", () => { + ophistory.stop(); + + const a: string = Clava.getProgram().code; + + const loopStmt1 = Query.search(Loop).get().at(0) as Joinpoint; + loopStmt1.replaceWith("aaaa"); + + const b: string = Clava.getProgram().code; + + ophistory.start(); + + const returnStmt = Query.search(Loop).get().at(0) as Joinpoint; + const comment = returnStmt.toComment(); + ophistory.checkpoint(); + const c: string = Clava.getProgram().code; + + comment.detach(); + const d: string = Clava.getProgram().code; + + ophistory.returnToLastCheckpoint(); + const e: string = Clava.getProgram().code; + + expect(c).toEqual(e); + expect(a).not.toEqual(b); + expect(a).not.toEqual(c); + expect(a).not.toEqual(d); + expect(b).not.toEqual(c); + expect(b).not.toEqual(d); + expect(c).not.toEqual(d); + }); + }); \ No newline at end of file diff --git a/Clava-JS/src-api/clava/history/History.ts b/Clava-JS/src-api/clava/history/History.ts index b2e99ba66..b23abdcf0 100644 --- a/Clava-JS/src-api/clava/history/History.ts +++ b/Clava-JS/src-api/clava/history/History.ts @@ -6,7 +6,7 @@ class OperationHistory { constructor() { this.operations = []; - this.locked = false; + this.locked = true; } private lock() { @@ -31,6 +31,15 @@ class OperationHistory { } } + start() { + this.unlock(); + } + + stop() { + this.lock(); + this.checkpoint(); + } + newOperation(operation: Operation) { if (!this.locked) { this.operations.push(operation); diff --git a/Clava-JS/src-api/clava/history/Operations.test.ts b/Clava-JS/src-api/clava/history/Operations.test.ts index 0c33bb458..c1bef0548 100644 --- a/Clava-JS/src-api/clava/history/Operations.test.ts +++ b/Clava-JS/src-api/clava/history/Operations.test.ts @@ -24,6 +24,7 @@ int main(int argc, char *argv[]) { describe("Transformation History: Operations", () => { registerSourceCode(code); + ophistory.start(); it("Initial code, insert before and rollback code comparison", () => { const a: string = Clava.getProgram().code; From 51f8691a24c03de28e7b12c1d01986e556c0f3ca Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Fri, 26 Jul 2024 11:39:48 +0100 Subject: [PATCH 36/38] fix: changed the start, stop, checkpoint behaviour --- Clava-JS/src-api/clava/history/History.test.ts | 2 +- Clava-JS/src-api/clava/history/History.ts | 4 +++- Clava-JS/src-api/clava/history/Operations.test.ts | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Clava-JS/src-api/clava/history/History.test.ts b/Clava-JS/src-api/clava/history/History.test.ts index 0fa4f1cd4..5037aed00 100644 --- a/Clava-JS/src-api/clava/history/History.test.ts +++ b/Clava-JS/src-api/clava/history/History.test.ts @@ -25,7 +25,7 @@ int main(int argc, char *argv[]) { describe("Transformation History: Multiple operations", () => { registerSourceCode(code); - ophistory.start(); + ophistory.checkpoint(); it("Inserts and detaches code comparison", () => { const a: string = Clava.getProgram().code; diff --git a/Clava-JS/src-api/clava/history/History.ts b/Clava-JS/src-api/clava/history/History.ts index b23abdcf0..572348726 100644 --- a/Clava-JS/src-api/clava/history/History.ts +++ b/Clava-JS/src-api/clava/history/History.ts @@ -32,12 +32,13 @@ class OperationHistory { } start() { + this.operations.length = 0; this.unlock(); } stop() { this.lock(); - this.checkpoint(); + this.operations.length = 0; } newOperation(operation: Operation) { @@ -56,6 +57,7 @@ class OperationHistory { checkpoint() { this.operations.length = 0; + this.unlock(); } returnToLastCheckpoint() { diff --git a/Clava-JS/src-api/clava/history/Operations.test.ts b/Clava-JS/src-api/clava/history/Operations.test.ts index c1bef0548..36e5c6313 100644 --- a/Clava-JS/src-api/clava/history/Operations.test.ts +++ b/Clava-JS/src-api/clava/history/Operations.test.ts @@ -24,7 +24,7 @@ int main(int argc, char *argv[]) { describe("Transformation History: Operations", () => { registerSourceCode(code); - ophistory.start(); + ophistory.checkpoint(); it("Initial code, insert before and rollback code comparison", () => { const a: string = Clava.getProgram().code; From 236b31a28c1e9fa03effb57c353907fb91338489 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Fri, 26 Jul 2024 11:45:31 +0100 Subject: [PATCH 37/38] fix: changed the Event API into a separate module --- Clava-JS/src-api/Joinpoints.ts | 4 ++-- Clava-JS/src-api/clava/{history => events}/EventListener.ts | 4 ++-- Clava-JS/src-api/clava/{history => events}/Events.ts | 0 3 files changed, 4 insertions(+), 4 deletions(-) rename Clava-JS/src-api/clava/{history => events}/EventListener.ts (96%) rename Clava-JS/src-api/clava/{history => events}/Events.ts (100%) diff --git a/Clava-JS/src-api/Joinpoints.ts b/Clava-JS/src-api/Joinpoints.ts index d11c442a5..df2fab366 100644 --- a/Clava-JS/src-api/Joinpoints.ts +++ b/Clava-JS/src-api/Joinpoints.ts @@ -17,8 +17,8 @@ import { wrapJoinPoint, unwrapJoinPoint, } from "lara-js/api/LaraJoinPoint.js"; -import eventListener from "./clava/history/EventListener.js"; -import { Event, EventTime } from "./clava/history/Events.js"; +import eventListener from "./clava/events/EventListener.js"; +import { Event, EventTime } from "./clava/events/Events.js"; type PrivateMapper = { "Joinpoint": typeof Joinpoint, diff --git a/Clava-JS/src-api/clava/history/EventListener.ts b/Clava-JS/src-api/clava/events/EventListener.ts similarity index 96% rename from Clava-JS/src-api/clava/history/EventListener.ts rename to Clava-JS/src-api/clava/events/EventListener.ts index 7c62dad28..ed86bc31b 100644 --- a/Clava-JS/src-api/clava/history/EventListener.ts +++ b/Clava-JS/src-api/clava/events/EventListener.ts @@ -1,7 +1,7 @@ import { EventEmitter } from "events"; import { Event, EventTime } from "./Events.js"; -import ophistory from "./History.js"; -import { DetachOperation, DetachReference, InlineCommentOperation, InsertOperation, RemoveChildrenOperation, ReplaceOperation, SetChildOperation, TypeChangeOperation, ValueOperation } from "./Operations.js"; +import ophistory from "../history/History.js" +import { DetachOperation, DetachReference, InlineCommentOperation, InsertOperation, RemoveChildrenOperation, ReplaceOperation, SetChildOperation, TypeChangeOperation, ValueOperation } from "../history/Operations.js"; import { Joinpoint } from "../../Joinpoints.js"; const eventListener = new EventEmitter(); diff --git a/Clava-JS/src-api/clava/history/Events.ts b/Clava-JS/src-api/clava/events/Events.ts similarity index 100% rename from Clava-JS/src-api/clava/history/Events.ts rename to Clava-JS/src-api/clava/events/Events.ts From c363c12293e743e758cb9d9db812b542a3f9ed02 Mon Sep 17 00:00:00 2001 From: racoelhosilva Date: Sun, 8 Sep 2024 20:41:38 +0100 Subject: [PATCH 38/38] fix: separated the Event Listener from the History Event Handlers --- .../src-api/clava/events/EventListener.ts | 136 ----------------- Clava-JS/src-api/clava/history/History.ts | 1 + .../src-api/clava/history/OperationEvents.ts | 137 ++++++++++++++++++ 3 files changed, 138 insertions(+), 136 deletions(-) create mode 100644 Clava-JS/src-api/clava/history/OperationEvents.ts diff --git a/Clava-JS/src-api/clava/events/EventListener.ts b/Clava-JS/src-api/clava/events/EventListener.ts index ed86bc31b..378119bd9 100644 --- a/Clava-JS/src-api/clava/events/EventListener.ts +++ b/Clava-JS/src-api/clava/events/EventListener.ts @@ -1,141 +1,5 @@ import { EventEmitter } from "events"; -import { Event, EventTime } from "./Events.js"; -import ophistory from "../history/History.js" -import { DetachOperation, DetachReference, InlineCommentOperation, InsertOperation, RemoveChildrenOperation, ReplaceOperation, SetChildOperation, TypeChangeOperation, ValueOperation } from "../history/Operations.js"; -import { Joinpoint } from "../../Joinpoints.js"; const eventListener = new EventEmitter(); -// Used for saving previous child in setFirstChild and setLastChild -let auxJP: Joinpoint; - -eventListener.on("ACTION", (e: Event) => { - - switch (e.timing) { - case EventTime.BEFORE: - switch (e.description) { - case "detach": - detachOperationFromEvent(e); - break; - case "removeChildren": - removeChildrenOperationFromEvent(e); - break; - case "setType": - changeTypeFromEvent(e); - break; - case "setFirstChild": - auxJP = e.mainJP.firstChild; - break; - case "setLastChild": - auxJP = e.mainJP.lastChild; - break; - case "setInlineComments": - inlineCommentOperationFromEvent(e); - break; - case "setValue": - setValueOperationFromEvent(e); - break; - default: - break; - } - break; - case EventTime.AFTER: - switch (e.description){ - case "insertAfter": - case "insertBefore": - insertOperationFromEvent(e); - break; - case "replaceWith": - if (e.inputs.length > 0){ - if (typeof e.inputs[0] === 'string' || e.inputs[0] instanceof Joinpoint){ - replaceSingleOperationFromEvent(e); - } - else { - replaceMultipleOperationFromEvent(e); - } - } - break; - case "replaceWithStrings": - if (e.inputs.length > 0){ - replaceMultipleOperationFromEvent(e); - } - break; - case "toComment": - replaceSingleOperationFromEvent(e); - break; - case "setFirstChild": - setFirstChildFromEvent(e, auxJP); - break; - case "setLastChild": - setLastChildFromEvent(e, auxJP); - break; - default: - break; - } - break; - } -}); - -function insertOperationFromEvent(e: Event) { - if (e.returnValue !== undefined){ - ophistory.newOperation(new InsertOperation(e.returnValue)) - } -} - -function replaceSingleOperationFromEvent(e: Event) { - if (e.returnValue !== undefined){ - ophistory.newOperation(new ReplaceOperation(e.mainJP, e.returnValue, 1)); - } -} - -function replaceMultipleOperationFromEvent(e: Event) { - if (e.returnValue !== undefined){ - ophistory.newOperation(new ReplaceOperation(e.mainJP, e.returnValue, (e.inputs[0] as (Joinpoint[] | string[])).length)); - } -} - -function detachOperationFromEvent(e: Event) { - let refJP: Joinpoint, ref: DetachReference; - if (e.mainJP.siblingsLeft.length >= 1){ - refJP = e.mainJP.leftJp; - ref = DetachReference.LEFT; - } else if (e.mainJP.siblingsRight.length >= 1) { - refJP = e.mainJP.rightJp; - ref = DetachReference.RIGHT; - } else { - refJP = e.mainJP.parent; - ref = DetachReference.TOP; - } - ophistory.newOperation(new DetachOperation(e.mainJP, refJP, ref)); -} - -function setFirstChildFromEvent(e: Event, aux: Joinpoint) { - ophistory.newOperation(new SetChildOperation(e.mainJP.firstChild, aux)); -} - -function setLastChildFromEvent(e: Event, aux: Joinpoint) { - ophistory.newOperation(new SetChildOperation(e.mainJP.lastChild, aux)); -} - -function removeChildrenOperationFromEvent(e: Event) { - ophistory.newOperation(new RemoveChildrenOperation(e.mainJP, e.mainJP.children)); -} - -function changeTypeFromEvent(e: Event) { - ophistory.newOperation(new TypeChangeOperation(e.mainJP, e.mainJP.type)); -} - -function inlineCommentOperationFromEvent(e: Event) { - const comments = e.mainJP.inlineComments - .map((comment) => comment.text) - .filter((comment): comment is string => comment !== null); - ophistory.newOperation(new InlineCommentOperation(e.mainJP, comments)); -} - -function setValueOperationFromEvent(e: Event) { - if (e.inputs && e.inputs.at(0)) { - ophistory.newOperation(new ValueOperation(e.mainJP, e.inputs.at(0) as string, e.mainJP.getValue(e.inputs.at(0) as string))); - } -} - export default eventListener; diff --git a/Clava-JS/src-api/clava/history/History.ts b/Clava-JS/src-api/clava/history/History.ts index 572348726..98e25b554 100644 --- a/Clava-JS/src-api/clava/history/History.ts +++ b/Clava-JS/src-api/clava/history/History.ts @@ -1,4 +1,5 @@ import { Operation } from "./Operations.js" +import "./OperationEvents.js" class OperationHistory { private operations: Operation[]; diff --git a/Clava-JS/src-api/clava/history/OperationEvents.ts b/Clava-JS/src-api/clava/history/OperationEvents.ts new file mode 100644 index 000000000..872661f27 --- /dev/null +++ b/Clava-JS/src-api/clava/history/OperationEvents.ts @@ -0,0 +1,137 @@ +import { Event, EventTime } from "../events/Events.js"; +import ophistory from "../history/History.js" +import { DetachOperation, DetachReference, InlineCommentOperation, InsertOperation, RemoveChildrenOperation, ReplaceOperation, SetChildOperation, TypeChangeOperation, ValueOperation } from "../history/Operations.js"; +import { Joinpoint } from "../../Joinpoints.js"; +import eventListener from "../events/EventListener.js"; + +// Used for saving previous child in setFirstChild and setLastChild +let auxJP: Joinpoint; + +eventListener.on("ACTION", (e: Event) => { + + switch (e.timing) { + case EventTime.BEFORE: + switch (e.description) { + case "detach": + detachOperationFromEvent(e); + break; + case "removeChildren": + removeChildrenOperationFromEvent(e); + break; + case "setType": + changeTypeFromEvent(e); + break; + case "setFirstChild": + auxJP = e.mainJP.firstChild; + break; + case "setLastChild": + auxJP = e.mainJP.lastChild; + break; + case "setInlineComments": + inlineCommentOperationFromEvent(e); + break; + case "setValue": + setValueOperationFromEvent(e); + break; + default: + break; + } + break; + case EventTime.AFTER: + switch (e.description){ + case "insertAfter": + case "insertBefore": + insertOperationFromEvent(e); + break; + case "replaceWith": + if (e.inputs.length > 0){ + if (typeof e.inputs[0] === 'string' || e.inputs[0] instanceof Joinpoint){ + replaceSingleOperationFromEvent(e); + } + else { + replaceMultipleOperationFromEvent(e); + } + } + break; + case "replaceWithStrings": + if (e.inputs.length > 0){ + replaceMultipleOperationFromEvent(e); + } + break; + case "toComment": + replaceSingleOperationFromEvent(e); + break; + case "setFirstChild": + setFirstChildFromEvent(e, auxJP); + break; + case "setLastChild": + setLastChildFromEvent(e, auxJP); + break; + default: + break; + } + break; + } +}); + +function insertOperationFromEvent(e: Event) { + if (e.returnValue !== undefined){ + ophistory.newOperation(new InsertOperation(e.returnValue)) + } +} + +function replaceSingleOperationFromEvent(e: Event) { + if (e.returnValue !== undefined){ + ophistory.newOperation(new ReplaceOperation(e.mainJP, e.returnValue, 1)); + } +} + +function replaceMultipleOperationFromEvent(e: Event) { + if (e.returnValue !== undefined){ + ophistory.newOperation(new ReplaceOperation(e.mainJP, e.returnValue, (e.inputs[0] as (Joinpoint[] | string[])).length)); + } +} + +function detachOperationFromEvent(e: Event) { + let refJP: Joinpoint, ref: DetachReference; + if (e.mainJP.siblingsLeft.length >= 1){ + refJP = e.mainJP.leftJp; + ref = DetachReference.LEFT; + } else if (e.mainJP.siblingsRight.length >= 1) { + refJP = e.mainJP.rightJp; + ref = DetachReference.RIGHT; + } else { + refJP = e.mainJP.parent; + ref = DetachReference.TOP; + } + ophistory.newOperation(new DetachOperation(e.mainJP, refJP, ref)); +} + +function setFirstChildFromEvent(e: Event, aux: Joinpoint) { + ophistory.newOperation(new SetChildOperation(e.mainJP.firstChild, aux)); +} + +function setLastChildFromEvent(e: Event, aux: Joinpoint) { + ophistory.newOperation(new SetChildOperation(e.mainJP.lastChild, aux)); +} + +function removeChildrenOperationFromEvent(e: Event) { + ophistory.newOperation(new RemoveChildrenOperation(e.mainJP, e.mainJP.children)); +} + +function changeTypeFromEvent(e: Event) { + ophistory.newOperation(new TypeChangeOperation(e.mainJP, e.mainJP.type)); +} + +function inlineCommentOperationFromEvent(e: Event) { + const comments = e.mainJP.inlineComments + .map((comment) => comment.text) + .filter((comment): comment is string => comment !== null); + ophistory.newOperation(new InlineCommentOperation(e.mainJP, comments)); +} + +function setValueOperationFromEvent(e: Event) { + if (e.inputs && e.inputs.at(0)) { + ophistory.newOperation(new ValueOperation(e.mainJP, e.inputs.at(0) as string, e.mainJP.getValue(e.inputs.at(0) as string))); + } +} \ No newline at end of file