Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: restores behaviour of search using string as the type #72

Merged
merged 4 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions Lara-JS/src-api/LaraJoinPoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,16 @@ export function wrapJoinPoint(obj: any): any {
);
}

const jpType: string = obj.getJoinPointType();
// Get join point class from name of the Java class, since getJoinPointType() might
// not always correspond to the actual join point class (e.g., anyweaver)
const jpClass: string = obj.get_class();

for (const mapper of JoinpointMappers) {
if (mapper[jpType]) {
return new mapper[jpType](obj);
if (mapper[jpClass]) {
return new mapper[jpClass](obj);
}
}
throw new Error("No mapper found for join point type: " + jpType);
throw new Error("No mapper found for join point type: " + jpClass);
}

export function unwrapJoinPoint(obj: any): any {
Expand Down
23 changes: 12 additions & 11 deletions Lara-JS/src-api/weaver/JoinPoints.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { LaraJoinPoint, wrapJoinPoint } from "../LaraJoinPoint.js";
import Weaver from "./Weaver.js";
import JpPredicate from "./predicate/JpPredicate.js";

/**
* Object which provides low-level join point-related methods.
Expand Down Expand Up @@ -70,9 +71,9 @@ export default class JoinPoints {
*
* @returns the nodes inside the scope of the given node.
*/
static scope<T extends typeof LaraJoinPoint>(
static scope(
$jp: LaraJoinPoint,
jpType?: T
jpType?: JpPredicate
): LaraJoinPoint[] {
return JoinPoints._getNodes(jpType, JoinPoints._all_scope_nodes($jp));
}
Expand All @@ -81,9 +82,9 @@ export default class JoinPoints {
*
* @returns the children of the given node, according to the AST
*/
static children<T extends typeof LaraJoinPoint>(
static children(
$jp: LaraJoinPoint,
jpType?: T
jpType?: JpPredicate
): LaraJoinPoint[] {
return JoinPoints._getNodes(jpType, JoinPoints._all_children($jp));
}
Expand All @@ -92,9 +93,9 @@ export default class JoinPoints {
*
* @returns the descendants of the given node, according to the AST, preorder traversal
*/
static descendants<T extends typeof LaraJoinPoint>(
static descendants(
$jp: LaraJoinPoint,
jpType?: T
jpType?: JpPredicate
): LaraJoinPoint[] {
return JoinPoints._getNodes(jpType, JoinPoints._all_descendants($jp));
}
Expand All @@ -103,9 +104,9 @@ export default class JoinPoints {
*
* @returns the descendants of the given node, according to the AST, postorder traversal
*/
static descendantsPostorder<T extends typeof LaraJoinPoint>(
static descendantsPostorder(
$jp: LaraJoinPoint,
jpType?: T
jpType?: JpPredicate
): LaraJoinPoint[] {
return JoinPoints._getNodes(
jpType,
Expand All @@ -117,16 +118,16 @@ export default class JoinPoints {
*
* @returns the nodes related with the given node, according to the search function
*/
private static _getNodes<T extends typeof LaraJoinPoint>(
jpType?: T,
private static _getNodes(
jpType?: JpPredicate,
$allJps: LaraJoinPoint[] = []
): LaraJoinPoint[] {
// TODO: This function can be optimized by using streaming
if (jpType === undefined) {
return $allJps;
}

return $allJps.filter((jp) => jp instanceof jpType);
return $allJps.filter((jp) => jpType.isInstance(jp));
}

/**
Expand Down
56 changes: 26 additions & 30 deletions Lara-JS/src-api/weaver/Selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import { type JpFilterRules } from "../lara/util/JpFilter.js";
import JoinPoints from "./JoinPoints.js";
import TraversalType from "./TraversalType.js";
import Weaver from "./Weaver.js";
import JpPredicate from "./predicate/JpPredicate.js";
import StringPredicate from "./predicate/StringPredicate.js";
import TypePredicate from "./predicate/TypePredicate.js";

/**
* @internal Lara Common Language dirty hack. IMPROPER USAGE WILL BREAK THE WHOLE WEAVER!
Expand Down Expand Up @@ -275,7 +278,7 @@ export default class Selector<
* @returns The results of the search.
*/
search(
name?: string,
type?: string,
filter?: Filter_StringVariant,
traversal?: TraversalType
): Selector;
Expand All @@ -285,33 +288,31 @@ export default class Selector<
traversal: TraversalType = TraversalType.PREORDER
): Selector<T, ChU | T> {
let jpFilter: JpFilterFunction<T>;
let jpPredicate : JpPredicate;

if (typeof type === "string") {
jpFilter = Selector.convertStringFilterToWrapperFilter(
type,
filter as Filter_StringVariant
);
const jpType = Weaver.findJoinpointType(type);
if (!jpType) {
throw new Error(`Join point type '${type}' not found.`);
}
return this.search(jpType, jpFilter, traversal);
jpPredicate = new StringPredicate(type);
} else {
jpFilter = Selector.parseWrapperFilter(
type,
(filter as Filter_WrapperVariant<T>) ?? (() => true)
);
jpPredicate = new TypePredicate(type);
}

let fn;
switch (traversal) {
case TraversalType.PREORDER:
fn = function ($jp: LaraJoinPoint, name?: T) {
fn = function ($jp: LaraJoinPoint, name?: JpPredicate) {
return selectorJoinPointsClass.descendants($jp, name);
};
break;
case TraversalType.POSTORDER:
fn = function ($jp: LaraJoinPoint, name?: T) {
fn = function ($jp: LaraJoinPoint, name?: JpPredicate) {
return selectorJoinPointsClass.descendantsPostorder($jp, name);
};
break;
Expand All @@ -322,7 +323,7 @@ export default class Selector<
);
}

return this.searchPrivate(type, fn, jpFilter);
return this.searchPrivate(jpPredicate, fn, jpFilter);
}

/**
Expand Down Expand Up @@ -353,28 +354,26 @@ export default class Selector<
filter: Filter_WrapperVariant<T> | Filter_StringVariant
): Selector<T, ChU | T> {
let jpFilter: JpFilterFunction<T>;
let jpPredicate : JpPredicate;

if (typeof type === "string") {
jpFilter = Selector.convertStringFilterToWrapperFilter(
type,
filter as Filter_StringVariant
);
const jpType = Weaver.findJoinpointType(type);
if (!jpType) {
throw new Error(`Join point type '${type}' not found.`);
}
return this.children(jpType, jpFilter);
jpPredicate = new StringPredicate(type);
} else {
jpFilter = Selector.parseWrapperFilter(
type,
(filter as Filter_WrapperVariant<T>) ?? (() => true)
);
jpPredicate = new TypePredicate(type);
}

return this.searchPrivate(
type,
function ($jp: LaraJoinPoint, name?: T) {
return selectorJoinPointsClass.children($jp, name);
jpPredicate,
function ($jp: LaraJoinPoint, type?: JpPredicate) {
return selectorJoinPointsClass.children($jp, type);
},
jpFilter
);
Expand Down Expand Up @@ -408,45 +407,42 @@ export default class Selector<
filter: Filter_WrapperVariant<T> | Filter_StringVariant
): Selector<T, ChU | T> {
let jpFilter: JpFilterFunction<T>;

let jpPredicate: JpPredicate;
if (typeof type === "string") {
jpFilter = Selector.convertStringFilterToWrapperFilter(
type,
filter as Filter_StringVariant
);
const jpType = Weaver.findJoinpointType(type);
if (!jpType) {
throw new Error(`Join point type '${type}' not found.`);
}
return this.scope(jpType, jpFilter);
jpPredicate = new StringPredicate(type);
} else {
jpFilter = Selector.parseWrapperFilter(
type,
(filter as Filter_WrapperVariant<T>) ?? (() => true)
);
jpPredicate = new TypePredicate(type);
}

return this.searchPrivate(
type,
function ($jp: LaraJoinPoint, name?: T) {
jpPredicate,
function ($jp: LaraJoinPoint, name?: JpPredicate) {
return selectorJoinPointsClass.scope($jp, name);
},
jpFilter
);
}

private searchPrivate<T extends typeof LaraJoinPoint>(
type: T,
selectFunction: (jp: LaraJoinPoint, name?: T) => LaraJoinPoint[],
type: JpPredicate,
selectFunction: (jp: LaraJoinPoint, name?: JpPredicate) => LaraJoinPoint[],
jpFilter: JpFilterFunction<T> = () => true
): Selector<T, ChU | T> {
const name = Weaver.findJoinpointTypeName(type) ?? "joinpoint";
const name = type.jpName();
const $newJps: SelectorChain[] = [];

/**
* Lara Common Language dirty hack. REMOVE ME PLEASE!
*/
if (selectorJoinPointsClass !== JoinPoints && type === LaraJoinPoint) {
if (selectorJoinPointsClass !== JoinPoints && type.isLaraJoinPoint()) {
// We are in LCL mode.
throw new Error("In LCL mode you are required to specify a type in a search.");
}
Expand All @@ -463,7 +459,7 @@ export default class Selector<

// Filter does not test if the join point is of the right type
const $root = this.$currentJps[0].jpAttributes[this.lastName];
if ($root instanceof type) {
if (type.isInstance($root)) {
this.addJps(name, $newJps, [$root], jpFilter, this.$currentJps[0]);
}
}
Expand Down
21 changes: 21 additions & 0 deletions Lara-JS/src-api/weaver/predicate/JpPredicate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { LaraJoinPoint } from "../../LaraJoinPoint.js";

export default abstract class JpPredicate {

/**
* @returns the name of the join point
*/
abstract jpName() : string;

/**
* @returns true if the underlying type is THE class LaraJoinPoint
*/
abstract isLaraJoinPoint() : boolean;

/**
*
* @param jp the join point we want to test
* @returns true if the join point is accepted by this predicate
*/
abstract isInstance<T extends LaraJoinPoint>(jp: T):boolean
}
22 changes: 22 additions & 0 deletions Lara-JS/src-api/weaver/predicate/StringPredicate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { LaraJoinPoint } from "../../LaraJoinPoint.js";
import JpPredicate from "./JpPredicate.js";

export default class StringPredicate extends JpPredicate {

constructor(private name: string) {
super();
}

jpName(): string {
return this.name;
}
isLaraJoinPoint(): boolean
{
return false;
}

isInstance<T extends LaraJoinPoint>(jp: T): boolean {
return jp.instanceOf(this.name);
}

}
22 changes: 22 additions & 0 deletions Lara-JS/src-api/weaver/predicate/TypePredicate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { LaraJoinPoint } from "../../LaraJoinPoint.js";
import JpPredicate from "./JpPredicate.js";
import Weaver from "../Weaver.js";

export default class TypePredicate<T extends typeof LaraJoinPoint> extends JpPredicate {

constructor(private type: T) {
super();
}

jpName(): string {
return Weaver.findJoinpointTypeName(this.type) ?? "joinpoint"
}

isLaraJoinPoint(): boolean {
return this.type === LaraJoinPoint;
}
isInstance<T extends LaraJoinPoint>(jp: T): boolean {
return jp instanceof this.type;
}

}
3 changes: 3 additions & 0 deletions LaraApi/src-java/pt/up/fe/specs/lara/LaraApiJsResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ public enum LaraApiJsResource implements LaraResourceProvider {
WEAVER_JS("weaver/Weaver.js"),
WEAVERLAUNCHERBASE_JS("weaver/WeaverLauncherBase.js"),
WEAVEROPTIONS_JS("weaver/WeaverOptions.js"),
JPPREDICATE_JS("weaver/predicate/JpPredicate.js"),
STRINGPREDICATE_JS("weaver/predicate/StringPredicate.js"),
TYPEPREDICATE_JS("weaver/predicate/TypePredicate.js"),
ACTIONAWARECACHE_JS("weaver/util/ActionAwareCache.js"),
WEAVERDATASTORE_JS("weaver/util/WeaverDataStore.js");

Expand Down
10 changes: 6 additions & 4 deletions LaraApi/src-lara/LaraJoinPoint.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion LaraApi/src-lara/weaver/JoinPoints.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading