eclipse-aspectj / aspectj

Other
303 stars 86 forks source link

XML-configured aspect scoping for ITD targets #253

Open kriegaex opened 1 year ago

kriegaex commented 1 year ago

As described at the end of my Stack Overflow answer and also in my Bugzilla 455014 comment, something like

<aspect name="de.scrum_master.aspect.MyAspect" scope="de.scrum_master.app..*" />

has no effect on ITD, only on regular pointcuts.

Here is a reproducer Eclipse project (created in Eclipse 2023-06), please adjust absolute path to aop.xml in .settings/org.eclipse.ajdt.core.prefs: SO_AJ_ITDXmlConfigured_76854550.zip

Outside Eclipse, just unzip the project, enter the base directory and try this (example for Windows CMD shell):

$ del /s /q bin\*
(...)

$ ajc -cp "C:\Program Files\Java\AspectJ\lib\aspectjrt.jar" -8 -d bin -xmlConfigured aop.xml src\org\acme\MyOtherPanel.java src\de\scrum_master\app\Application.java src\de\scrum_master\app\MyTargetPanel.java src\de\scrum_master\aspect\MyAspect.aj
(...)

$ java -ea -cp "C:\Program Files\Java\AspectJ\lib\aspectjrt.jar;bin" de.scrum_master.app.Application
Exception in thread "main" java.lang.AssertionError: out-of-scope class parent should not have been altered by aspect
        at de.scrum_master.app.Application.main(Application.java:18)

The assertion fails, because ITD did have an effect on the out-of-scope class. It would pass after we extend XML config scoping for AJC to respect ITD targets, too.

For reference, here is the complete code:

package de.scrum_master.app;

import javax.swing.JPanel;

public class MyTargetPanel extends JPanel {
  public static int getMeaningOfLife() {
    return 42;
  }
}
package org.acme;

import javax.swing.JPanel;

public class MyOtherPanel extends JPanel {
  public static int getMeaningOfLife() {
    return 42;
  }
}
package de.scrum_master.aspect;

import java.beans.JavaBean;
import javax.swing.JPanel;

public aspect MyAspect {
  public static class MyPanel extends JPanel {}

  declare parents: (!@JavaBean JPanel+) extends MyPanel;

  int around() : (execution(int getMeaningOfLife())) {
    return 11;
  }
}
<aspectj>
  <aspects>
    <aspect name="de.scrum_master.aspect.MyAspect" scope="de.scrum_master.app..*" />
    <!-- other aspects go here, with or without scope -->
  </aspects>
</aspectj>
package de.scrum_master.app;

import javax.swing.JPanel;
import org.acme.MyOtherPanel;
import de.scrum_master.aspect.MyAspect;

public class Application {
  public static void main(String[] args) {
    assert MyTargetPanel.getMeaningOfLife() != 42
      : "in-scope class method result should have been altered by aspect";
    assert MyOtherPanel.getMeaningOfLife() == 42
      : "out-of-scope class method result should not have been altered by aspect";
    assert MyTargetPanel.class.getSuperclass().equals(MyAspect.MyPanel.class)
      : "in-scope class parent should have been altered by aspect";
    assert MyOtherPanel.class.getSuperclass().equals(JPanel.class)
      : "out-of-scope class parent should not have been altered by aspect";
  }
}

@aclement, I do not even dare to ask you to implement this, but I would be glad for advice about how to tackle this.

kriegaex commented 1 year ago

Now there is a Maven project with a JUnit test reproducing the problem at https://github.com/kriegaex/SO_AJ_ITDXmlConfigured_76854550.