UNPKG

@specs-feup/kadabra

Version:

A Java source-to-source compiler written in Typescript

141 lines (121 loc) 3.37 kB
/** Monitor the occurences of a given join point; */ import Query from "@specs-feup/lara/api/weaver/Query.js"; import { App, Class, Field, FileJp, Method, Statement, } from "../../Joinpoints.js"; export function NewCounter(jpClass: Class, name = "counter", fullPath = false) { const jpField = jpClass.newField( ["public", "static"], "weaver.kadabra.monitor.Counter", name, "new Counter()" ); let newName = jpField.name; if (fullPath) { const prefix = jpClass.qualifiedName + "."; newName = prefix + newName; } const increment = newName + ".increment()"; const reset = newName + ".reset()"; const getValue = newName + ".getValue()"; return { increment: increment, getValue: getValue, reset: reset, newName: newName, }; } export function CountingMonitor( targetClass: Class, targetMethod: Method, targetStmt: Statement, location: "replace" | "after" | "before" = "before", monitorPackage = "pt.up.fe.specs.lara.kadabra.utils" ) { const monitorClass = GetCountingMonitor(monitorPackage, "CountingMonitor"); if (monitorClass === undefined) { throw new Error( "Expected monitorClass to be of type Class but was undefined." ); } let name = "kadabra" + monitorClass.name; let counter = 0; while ( Query.searchFrom(targetClass, Field, { name: (n) => n == name + counter, }).get().length !== 0 ) { counter++; } name += counter; const getValue = name + ".getValue()"; const reset = name + ".reset()"; const increment = name + ".increment()"; const modifiers = ["private"]; if (targetMethod?.isStatic) { modifiers.push("static"); } targetClass.newField( modifiers, monitorClass.qualifiedName, name, "new " + monitorClass.name + "()" ); if (targetStmt != undefined) { targetStmt.insert(location, `${increment};`); } return { name: name, increment: increment, getValue: getValue, reset: reset, }; } /** Returns the counting monitor. if it does not exist creates a new class */ export function GetCountingMonitor(packageName: string, simpleName: string) { const monitorClass = Query.search(FileJp) .search(Class, { name: simpleName, packageName: packageName, }) .getFirst(); if (monitorClass !== undefined) { return monitorClass; } return NewCountingMonitor(packageName, simpleName); } export function NewCountingMonitor(packageName: string, simpleName: string) { const className = packageName + "." + simpleName; const monitorClass = (Query.root() as App).newClass(className); if (monitorClass === undefined) { return undefined; } monitorClass.newField(["private"], "int", "counter"); monitorClass.newMethod( ["public"], "void", "increment", [], [], "counter++;" ); monitorClass.newMethod( ["public"], "int", "getValue", [], [], "return counter;" ); monitorClass.newMethod(["public"], "void", "reset", [], [], "counter = 0;"); return monitorClass; }