TNG / ArchUnit

A Java architecture test library, to specify and assert architecture rules in plain Java
http://archunit.org
Apache License 2.0
3.17k stars 287 forks source link

Get modifiers of JavaParameter #1230

Open priyanthabuddhika opened 7 months ago

priyanthabuddhika commented 7 months ago

I am trying to create a custom arch unit rule to validate if method parameters have a final modifier. However, JavaParameter class does not seems to have a getModifiers method like JavaMethod class. Is this achievable with current ArchUnit API ?

I'm using ArchUnit 1.2.1 version.

This is a code sample of what I'm trying to achieve.

public void check(JavaMethod method, ConditionEvents events) {
            boolean allParametersAreFinal = true;

            for (JavaParameter parameter : method.getParameters()) {
                if (!parameter.getModifiers().contains(JavaModifier.FINAL)) {  // <---------- Something like this ?
                    allParametersAreFinal = false;
                    events.add(SimpleConditionEvent.violated(method,
                            String.format("Parameter %s of method %s is not final",
                                    parameter.getOwner().getFullName(), method.getSourceCodeLocation())));
                }
            }

            if (allParametersAreFinal) {
                events.add(SimpleConditionEvent.satisfied(method,
                        "Parameters of method " + method.getFullName() + " are final"));
            }
        }
    }
hankem commented 7 months ago

I fear that final method parameters might just exist in the Java language, but and in the byte code/JVM. (I'm saying "might" because I don't know much about the JVM specification...)

I've just observed that for the simple example

class C {
   void method(int p1, final int p2) {
   }
}

javap does not show any difference between the parameters p1 and p2 in the byte code:

  void method(int, int);
    descriptor: (II)V
    flags: (0x0000)
    Code:
      stack=0, locals=3, args_size=3
         0: return

So the descriptor: (II)V might be everything that is available to ArchUnit. (I'm saying "might"...)