diff --git a/org.eclipse.wb.core.java/src/org/eclipse/wb/core/eval/ExecutionFlowUtils.java b/org.eclipse.wb.core.java/src/org/eclipse/wb/core/eval/ExecutionFlowUtils.java
index 697340f89..8fec7147f 100644
--- a/org.eclipse.wb.core.java/src/org/eclipse/wb/core/eval/ExecutionFlowUtils.java
+++ b/org.eclipse.wb.core.java/src/org/eclipse/wb/core/eval/ExecutionFlowUtils.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011, 2025 Google, Inc. and others.
+ * Copyright (c) 2011, 2026 Google, Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
@@ -32,8 +32,6 @@
import org.eclipse.wb.internal.core.utils.ast.AstNodeUtils;
import org.eclipse.wb.internal.core.utils.ast.DomGenerics;
import org.eclipse.wb.internal.core.utils.check.Assert;
-import org.eclipse.wb.internal.core.utils.exception.DesignerException;
-import org.eclipse.wb.internal.core.utils.exception.ICoreExceptionConstants;
import org.eclipse.wb.internal.core.utils.exception.MultipleConstructorsError;
import org.eclipse.wb.internal.core.utils.external.ExternalFactoriesHelper;
@@ -72,15 +70,8 @@
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import net.bytebuddy.ByteBuddy;
-import net.bytebuddy.TypeCache;
-import net.bytebuddy.dynamic.DynamicType;
-import net.bytebuddy.implementation.InvocationHandlerAdapter;
-import net.bytebuddy.matcher.ElementMatchers;
import java.lang.reflect.Field;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -120,6 +111,8 @@ private ExecutionFlowUtils() {
* @author scheglov_ke
*/
public static class ExecutionFlowFrameVisitor extends ASTVisitor {
+ private ExecutionFlowDescription flowDescription;
+ private VisitingContext context;
public Statement m_currentStatement;
////////////////////////////////////////////////////////////////////////////
@@ -157,6 +150,61 @@ public boolean enterFrame(ASTNode node) {
*/
public void leaveFrame(ASTNode node) {
}
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Execution Flow
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ @Override
+ public void endVisit(ClassInstanceCreation node) {
+ if (flowDescription == null || context == null) {
+ return;
+ }
+ // quick check
+ {
+ String identifier = flowDescription.geTypeDeclaration().getName().getIdentifier();
+ if (!node.toString().contains(identifier)) {
+ return;
+ }
+ }
+ // check for local constructor
+ MethodDeclaration methodDeclaration = getLocalConstructorDeclaration(node);
+ if (methodDeclaration != null) {
+ // redirect execution flow to constructor
+ ExecutionFlowUtils.visit(context, flowDescription, this, List.of(methodDeclaration));
+ }
+ }
+
+ @Override
+ public void endVisit(ConstructorInvocation node) {
+ if (flowDescription == null || context == null) {
+ return;
+ }
+ MethodDeclaration constructor = getConstructor(node);
+ constructor.setProperty(KEY_FRAME_INVOCATION, node);
+ ExecutionFlowUtils.visit(context, flowDescription, this, List.of(constructor));
+ }
+
+ @Override
+ public void endVisit(MethodInvocation node) {
+ if (flowDescription == null || context == null) {
+ return;
+ }
+ // check for local method invocation
+ MethodDeclaration methodDeclaration = getLocalMethodDeclaration(node);
+ if (methodDeclaration != null) {
+ methodDeclaration.setProperty(KEY_FRAME_INVOCATION, node);
+ // check for qualified local invocation, for example "appl.open()", so visit it
+ // as type
+ if (node.getExpression() != null && !(node.getExpression() instanceof ThisExpression)) {
+ ExecutionFlowUtils.visit(context, flowDescription, this, List.of(methodDeclaration));
+ } else {
+ ExecutionFlowUtils.visit(context, flowDescription, this, methodDeclaration);
+ }
+ }
+ }
}
////////////////////////////////////////////////////////////////////////////
//
@@ -356,41 +404,22 @@ && shouldVisit_IfStatement_Else(ifStatement)) {
visitStatement(context, flowDescription, ifStatement.getElseStatement(), visitor);
}
} else if (shouldVisitStatement(statement)) {
- ASTVisitor complexVisitor = getInterceptingVisitor(context, flowDescription, visitor);
- statement.accept(complexVisitor);
+ visitStatementComplex(context, flowDescription, statement, visitor);
}
}
/**
- * Local storage for the enhanced {@link ASTVisitor} class. Classes are loaded
- * with the {@link ExecutionFlowUtils} class-loader, meaning there should only
- * exists a single instance of this class at a time. All instances are should be
- * created from this class. We have to avoid creating a separate class for each
- * enhanced visitor, as the {@link ClassLoader} is never discarded and thus, the
- * classes stay in memory indefinitely. If left unchecked, this may lead to an
- * {@link OutOfMemoryError}.
+ * Visit {@link ASTNode} with additional handling of some nodes.
*/
- private static final TypeCache
- * Custom invocation handler used by {@link ByteBuddy} on an enhanced - * {@link ASTVisitor}. - *
- *- * All method invocations of the enhanced base class are delegated to the main - * visitor. This visitor is stored in an internal field of the enhanced object. - * Special code is executed for AST nodes of type - * {@link AnonymousClassDeclaration}, {@link ClassInstanceCreation}, - * {@link MethodInvocation} and {@link ConstructorInvocation}. - *
- *- * This handler may only be used for objects of type {@link VisitorStub}. - *
- * - * @see VisitorStub - */ - private static class ExecutionFlowHandler implements InvocationHandler { - @Override - public Object invoke(Object obj, Method method, Object[] args) throws Throwable { - VisitorStub stub = (VisitorStub) obj; - // routing - Class>[] parameterTypes = method.getParameterTypes(); - if (parameterTypes.length == 1) { - Class> parameterType = parameterTypes[0]; - if (method.getName().equals("endVisit")) { - if (parameterType == ClassInstanceCreation.class) { - endVisit(stub, (ClassInstanceCreation) args[0]); - } else if (parameterType == MethodInvocation.class) { - endVisit(stub, (MethodInvocation) args[0]); - } else if (parameterType == ConstructorInvocation.class) { - endVisit(stub, (ConstructorInvocation) args[0]); - } - } - } - // use main visitor - try { - return method.invoke(stub.visitor, args); - } catch (InvocationTargetException e) { - throw e.getCause(); - } - } - - private void endVisit(VisitorStub stub, ClassInstanceCreation node) { - // quick check - { - String identifier = stub.flowDescription.geTypeDeclaration().getName().getIdentifier(); - if (!node.toString().contains(identifier)) { - return; - } - } - // check for local constructor - MethodDeclaration methodDeclaration = getLocalConstructorDeclaration(node); - if (methodDeclaration != null) { - // redirect execution flow to constructor - ExecutionFlowUtils.visit(stub.context, stub.flowDescription, stub.visitor, List.of(methodDeclaration)); - } - } - - private void endVisit(VisitorStub stub, MethodInvocation node) { - // check for local method invocation - MethodDeclaration methodDeclaration = getLocalMethodDeclaration(node); - if (methodDeclaration != null) { - methodDeclaration.setProperty(KEY_FRAME_INVOCATION, node); - // check for qualified local invocation, for example "appl.open()", so visit it - // as type - if (node.getExpression() != null && !(node.getExpression() instanceof ThisExpression)) { - ExecutionFlowUtils.visit(stub.context, stub.flowDescription, stub.visitor, List.of(methodDeclaration)); - } else { - ExecutionFlowUtils.visit(stub.context, stub.flowDescription, stub.visitor, methodDeclaration); - } - } - } - - private void endVisit(VisitorStub stub, ConstructorInvocation node) { - MethodDeclaration constructor = getConstructor(node); - constructor.setProperty(KEY_FRAME_INVOCATION, node); - ExecutionFlowUtils.visit(stub.context, stub.flowDescription, stub.visitor, List.of(constructor)); - } - } } diff --git a/org.eclipse.wb.core.java/src/org/eclipse/wb/core/eval/ExecutionFlowUtils2.java b/org.eclipse.wb.core.java/src/org/eclipse/wb/core/eval/ExecutionFlowUtils2.java index 622f94cec..6bd30555c 100644 --- a/org.eclipse.wb.core.java/src/org/eclipse/wb/core/eval/ExecutionFlowUtils2.java +++ b/org.eclipse.wb.core.java/src/org/eclipse/wb/core/eval/ExecutionFlowUtils2.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2024 Google, Inc. and others. + * Copyright (c) 2011, 2026 Google, Inc. and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at @@ -338,6 +338,7 @@ public void endVisit(CastExpression node) { @Override public void endVisit(MethodInvocation node) { + super.endVisit(node); MethodDeclaration method = AstNodeUtils.getLocalMethodDeclaration(node); if (method != null) { // may be "lazy" diff --git a/org.eclipse.wb.core.java/src/org/eclipse/wb/internal/core/parser/JavaInfoParser.java b/org.eclipse.wb.core.java/src/org/eclipse/wb/internal/core/parser/JavaInfoParser.java index a16a6ff46..ac262b6ed 100644 --- a/org.eclipse.wb.core.java/src/org/eclipse/wb/internal/core/parser/JavaInfoParser.java +++ b/org.eclipse.wb.core.java/src/org/eclipse/wb/internal/core/parser/JavaInfoParser.java @@ -660,6 +660,7 @@ private boolean createJavaInfo_noModel(ASTNode node) { @Override public void endVisit(ClassInstanceCreation creation) { + super.endVisit(creation); try { if (createJavaInfo_noModel(creation)) { return; @@ -743,6 +744,7 @@ private boolean createJavaInfo_noModel(ClassInstanceCreation creation, @Override public void endVisit(MethodInvocation invocation) { + super.endVisit(invocation); try { if (createJavaInfo_noModel(invocation)) { return;