Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only create assertion class when it does not exist or when the associated class has changed #48

Open
jgerken opened this issue Nov 21, 2017 · 3 comments

Comments

@jgerken
Copy link

jgerken commented Nov 21, 2017

Currently, the generator plugin always generates the assertion class which requires the test-compile step of Maven to compile the classes in every run - even if no source code has changed. The assertion classes should only be generated:

  1. when they do not exist
  2. when the associated class changes

Example:

I want to create assertions for class A:

  • assertion class for class A do not exist -> generate assertion class
  • assertion class for class A exists and class A was not changed since the generation -> do not generate assertion class
  • assertion class for class A exists and class A was changed since the generation -> generate a new version of the assertion class
@joel-costigliola
Copy link
Member

That would be a nice improvement.
Question: how do you know a class has changed or not ?

@jgerken
Copy link
Author

jgerken commented Nov 21, 2017

The maven-compiler-plugin compares the timestamps of the source and class files. Internally, it uses the StaleSourceScanner from the plexus-compiler.

I think the class could be used in this plugin as well. From the sources, I guess the following steps are required:

  1. implement a SourceMapping that maps from the source file of the Java class to the generated source file of the corresponding assertion class.
  2. Create a new instance of the StaleSourceScanner and configure it as follows
    1. map the includes and excludes definitions of this plugin to the sourceIncludes and sourceExcludes parameters of the constructor
    2. add the source mapping to the instance
  3. call getIncludedSources() to get the classes for which the assertions need to be generated
  4. generate the assertions

@jgerken
Copy link
Author

jgerken commented Mar 11, 2019

I had a closer look at the issue. It is much more complicated than I initially thought. It is easy to determine the Java file to which a generated assertion will be written and, therefore, it is also easy to identify the time it was last modified. However, the Java classes for which the assertions are generated are loaded via the class loader (which I did not know previously). It is possible to get the root directory (e.g. target/classes/) or JAR file which contains the class. If a directory is returned, the class is part of the current Maven directory. The next step would be to iterate over all source directories (could be more than just src/main/java and src/test/java, depending on the configuration) to check if the class is present in any of the directories. Once the file is found it is trivial so check if the source is newer than the generated assertion.

For classes contained in JAR files, the story is different. They should represent dependencies, but I have no idea how to determine if the dependencies was added / changed after the last build. My current idea would be to check

  • was the JAR file modified after the last build?
    • yes: generate the assertion
    • no: check if the POM was changed after the last build
      • yes: generate the assertion (even though the change might be totally unrelated, but we cannot tell)
      • no: keep the old version of the assertion

The part regarding the assertions created for source files from the current project could be much easier, if the evaluation for the classed to include would be done based on the maven project and not on the class path. This would require a major refactoring but could also be used as basis for #53.

In such a scenario, we could do the following:

-is the generation of assertions is restricted to source directories only?

  • yes: use maven approach to find classes to include and update existing assertions only if the associated class has changed
  • no: always build all assertions

I am note sure how many projects actually generate assertions from dependencies, but it guess the majority doesn't. Thus, this approach would improve the generation for the majority of the users. And for the other a work-around to use a separate maven project which only generates the assertions from the dependencies would be possible and also improve the situation.

If you want to support #53 I could try to propose a combined PR with this issue in a way that the current behaviour remains standard (i.e. no breaking change for anyone who updates).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants