]> source.dussan.org Git - aspectj.git/commitdiff
New Xlint warning 'arrayCannotBeVoid' when resolving 'void[]'
authorAlexander Kriegisch <Alexander@Kriegisch.name>
Tue, 17 Jan 2023 18:23:26 +0000 (19:23 +0100)
committerAlexander Kriegisch <Alexander@Kriegisch.name>
Fri, 12 Apr 2024 13:32:39 +0000 (15:32 +0200)
Because void arrays are illegal (and nonsensical), now there is a new
Xlint warning whenever World.resolve resolves a new 'void[]'. Because
in the World class we do not have any source context, no path + line
number are logged. The user only sees something like:

  [warning] arrays cannot have a void type, but found 'void[]' in
  pointcut [Xlint:arrayCannotBeVoid]

Then later, if due to the returned MissingResolvedTypeWithKnownSignature
type a joinpoint does not match, there is an additional

  my/path/MyAspect.aj:42 [warning] advice defined in MyAspect has not
  been applied [Xlint:adviceDidNotMatch]

log line, but not necessarily anywhere near the former one.

On the one hand, this is better than nothing. OTOH, comparing the
situation with no logging message other than Xlint:adviceDidNotMatch in
case of something equally illegal like 'Foo<int>' (primitive generic
type parameter), this is actually more than we have in several other
situations and might even be regarded as superfluous. In case of
multiple 'void[]' cases within a big number of aspects, the same aspect
or even the same pointcut, the user would have no clue where exactly to
search for it. He would just see multiple log messages without source
context.

One option would be to set 'arrayCannotBeVoid=ignore' in
XlintDefault.properties, so the user would have to explicitly activate
it. But IMO, this message should be visible by default.

Another option would be to find out how to defer logging the messages
until later similarly to BcelWeaver.warnOnUnmatchedAdvice and then to
bulk-print them. But in order to achieve that, the information about the
existence of any 'void[]' occurrences would have to be stored in a flag
similar to BcelAdvice.hasMatchedAtLeastOnce, bloating BcelAdvice for
that rare case. Alternatively, each advice pointcut could be
heuristically scanned for the literal substring 'void[]', logging the
Xlint message if it is found anywhere.

Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>
org.aspectj.matcher/src/main/java/org/aspectj/weaver/Lint.java
org.aspectj.matcher/src/main/java/org/aspectj/weaver/World.java
org.aspectj.matcher/src/main/resources/org/aspectj/weaver/XlintDefault.properties
org.aspectj.matcher/src/test/java/org/aspectj/weaver/CommonWorldTests.java

index 3963e09f4b895cc0270adc72e3bfb4e5be883890..70d6a8b73e9857eaa6136cf9f2e4177518428b25 100644 (file)
@@ -138,6 +138,8 @@ public class Lint {
        public final Kind missingAspectForReweaving = new Kind("missingAspectForReweaving",
                        "aspect {0} cannot be found when reweaving {1}");
 
+       public final Kind arrayCannotBeVoid = new Kind("arrayCannotBeVoid", "arrays cannot have a void type, but found ''{0}'' in pointcut");
+
        private static final Trace trace = TraceFactory.getTraceFactory().getTrace(Lint.class);
 
        public Lint(World world) {
index 6eab96f150aa6eaf733d3f4a0f3ee2634a4aa26f..c5f43da8fcd6985387e36923b8f06cb1d448a662 100644 (file)
@@ -316,7 +316,15 @@ public abstract class World implements Dump.INode {
                synchronized (buildingTypeLock) {
                        if (ty.isArray()) {
                                ResolvedType componentType = resolve(ty.getComponentType(), allowMissing);
+                               if (componentType.isVoid()) {
+                                       if (isInJava5Mode() && getLint().adviceDidNotMatch.isEnabled()) {
+                                               getLint().arrayCannotBeVoid.signal(ty.toString(), null);
+                                       }
+                                       ret = new MissingResolvedTypeWithKnownSignature(signature, this);
+                               }
+                               else {
                                ret = new ArrayReferenceType(signature, "[" + componentType.getErasureSignature(), this, componentType);
+                               }
                        } else {
                                ret = resolveToReferenceType(ty, allowMissing);
                                if (!allowMissing && ret.isMissing()) {
index f996d040b91d53534edd9d032c15f6e15e96e84a..b7a982246365dee51d83d5666cbe51b298a4694a 100644 (file)
@@ -48,3 +48,5 @@ missingAspectForReweaving=error
 cannotAdviseJoinpointInInterfaceWithAroundAdvice=warning
 
 nonReweavableTypeEncountered=error
+
+arrayCannotBeVoid=warning
index cf9a944fb69f1b7e2561425e05b856f1b3a352c6..550476b4d050bdd0d5087e31deb6a6c47f5e5035 100644 (file)
@@ -110,6 +110,9 @@ public abstract class CommonWorldTests extends TestCase {
                ResolvedType[] primitives = world.resolve(primitiveTypes);
                for (ResolvedType ty : primitives) {
                        UnresolvedType tx = UnresolvedType.forSignature("[" + ty.getSignature());
+                       // 'void[]' is an illegal type -> skip
+                       if (tx.getSignature().equals("[V"))
+                               continue;
                        ResolvedType aty = world.resolve(tx, true);
                        assertTrue("Couldnt find type " + tx, !aty.isMissing());
                        modifiersTest(aty, Modifier.PUBLIC | Modifier.FINAL);
@@ -128,6 +131,9 @@ public abstract class CommonWorldTests extends TestCase {
                        for (ResolvedType ty1 : primitives) {
                                isCoerceableFromTest(aty, ty1, false);
                                tx = UnresolvedType.forSignature("[" + ty1.getSignature());
+                               // 'void[]' is an illegal type -> skip
+                               if (tx.getSignature().equals("[V"))
+                                       continue;
                                ResolvedType aty1 = getWorld().resolve(tx, true);
                                assertTrue("Couldnt find type " + tx, !aty1.isMissing());
                                if (ty.equals(ty1)) {
@@ -142,6 +148,9 @@ public abstract class CommonWorldTests extends TestCase {
                // double dimension arrays
                for (ResolvedType ty : primitives) {
                        UnresolvedType tx = UnresolvedType.forSignature("[[" + ty.getSignature());
+                       // 'void[][]' is an illegal type -> skip
+                       if (tx.getSignature().equals("[[V"))
+                               continue;
                        ResolvedType aty = world.resolve(tx, true);
                        assertTrue("Couldnt find type " + tx, !aty.isMissing());
                        modifiersTest(aty, Modifier.PUBLIC | Modifier.FINAL);
@@ -160,6 +169,9 @@ public abstract class CommonWorldTests extends TestCase {
                        for (ResolvedType ty1 : primitives) {
                                isCoerceableFromTest(aty, ty1, false);
                                tx = UnresolvedType.forSignature("[[" + ty1.getSignature());
+                               // 'void[][]' is an illegal type -> skip
+                               if (tx.getSignature().equals("[[V"))
+                                       continue;
                                ResolvedType aty1 = getWorld().resolve(tx, true);
                                assertTrue("Couldnt find type " + tx, !aty1.isMissing());
                                if (ty.equals(ty1)) {