Coder Social home page Coder Social logo

Comments (3)

codecholeric avatar codecholeric commented on July 20, 2024 3

BTW, there is another way, if you don't want this in your code, you could use an ArchUnit Ignore Pattern, i.e. put archunit_ignore_patterns.txt in your src/test/resources and add a pattern that matches that specific call, e.g.

Method <.*\.values\(\)> calls method <\[L.*\.clone\(\)>.*

That should filter all those calls from .values() methods to array clone() methods. (compare https://www.archunit.org/userguide/html/000_Index.html#_ignoring_violations)

from archunit.

codecholeric avatar codecholeric commented on July 20, 2024 1

Thanks for providing the full sample to analyze 😃
The effect you experience might seem a little odd, but from the point of view of Java bytecode and the Reflection API (which ArchUnit tries to be consistent with), it's not that surprising.
An Enum like Colors defines a method Colors.values() out of the box, and the byte code (javap -v Colors.class) shows sth. like

#1 = Fieldref           #4.#39         // package1/Colors.$VALUES:[Lpackage1/Colors;

and

public static package1.Colors[] values();
    ...
    0: getstatic     #1                  // Field $VALUES:[Lpackage1/Colors;
    3: invokevirtual #2                  // Method "[Lpackage1/Colors;".clone:()Ljava/lang/Object;

So Colors.values() calls Colors[].clone() on an array of Colors, and if you check the Reflection API, you'll see that

System.out.println(Colors.values().getClass().getPackage()); // prints null

I.e. classes in the default package and array types have no package, thus ArchUnit uses an empty string there (since ArchUnit never uses null and an empty string seems equivalent in those cases).
Anyway, consequently a method defined in Colors (Colors.values()) calls a method on an object in the default package, and thus your rule reports

Method <package1.Colors.values()> calls method <[Lpackage1.Colors;.clone()> in (Colors.java:3)

(if you check Colors[].class.getName(), you'll see the weird name [Lpackage1.Colors;)
Long story short, if you allow accesses to the default package, you'll ignore those calls

noClasses()
		.that()
		.resideInAPackage("package1")
		.should()
		.accessClassesThat()
		.resideOutsideOfPackages(
				"",
				"java..",
				"..package1..",
				"..package2..")

Other than that, you could customize this, and explicitly ignore only that call, or only calls to Array.clone(), but then you'd have to write more custom code (I could show you, if you're interested, but I'm not sure, if it's really worth it for your case, because classes in the default package are likely not your problem 😉)

Unfortunately I don't know what ArchUnit could really do to make this more clear, because that is just how the code really is if you look closely, even if it's hidden from the eye during everyday coding.
But I'm open to suggestions!!

from archunit.

paolocarrasco avatar paolocarrasco commented on July 20, 2024

Yeah, that workaround helps me, thanks! I don't have any issues with the default package.

Although, I think the dependency from enum::values() to Array::clone() should be treated differently, as an exception to the rule, otherwise it would allow class members of the package to have dependencies to the default one. Maybe, to have a built-in predicate that use the custom code you have and have something like this:

noClasses()
		.that()
		.resideInAPackage("package1")
		.should()
		.accessClassesThat(skippingEnumValues)
		.resideOutsideOfPackages(
				"",
				"java..",
				"..package1..",
				"..package2..")

from archunit.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.