Git Product home page Git Product logo

saker.java.compiler's People

Contributors

sipkab avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

saker.java.compiler's Issues

Examine if we can trick javac to compile for older targets when using --release

The goal is to use javac from a version that is higher than the --release we're compiling for, and create class files for a version that is lower than --release. E.g.

We want to use Javac 10 to compile against Java 9 while targetting Java 8. This entails using --release with the argument 9 and -target with 8.

We might (and probably) not succeed and may require hacking into some of the private APIs of javac. There may be very well unsupported combinations of such versions. E.g. we can't target Java 7 and use lambdas in Java 8.

Only add --add-exports if the compiler supports it

If we specify the AddExports input configuration for the compiler task, an exception is thrown if we compile on JDK8.

Solution

Only add the --add-exports arguments to the compiler of it is 9 or more recent.

Examine performing compilation against API JARs

As suggested on Reddit, the compilation performance could be improved by compiling against API JARs instead of full implementation JARs.

This can be achieved by taking the impl JARs and performing API extraction on them. Every non-anonymous class should be in it (even private ones) and every non-private members. Module-info and package-infos as well.

The private and package-private classes should be present, as there may be declarations that expose them as:

public class Main {
	private static class Inner {

	}

	public static <T extends Inner> T f() {
		return null;
	}
}

In the second iteration of the issue, we may perform deep analysis of the accessability of non-public elements, however, it may be unfeasible, as the analysis may incure greater performance cost than the improvement.

Solution

This shouldn't be performed by the compiler task itself. This is the responsibility of the code that sets up the input classpath. Therefore a solution could be to introduce a new build task that performs the API extraction. Something along the lines of:

saker.java.compile(
    ClassPath: task.that.extracts.api(lib/mylib.jar)
)

Another thing that could be examined is if repositories are able to directly provide compilation input JARs. If a JAR is uploaded to some common repository, it could perform the API extraction themselves, and provide it alongside of the implementation JAR. Therefore, if the client wants to compile for the given JAR, it could download the API instead of the implementation. However, if they want to use it, they can download the implementation as usual.

This issue may be moved from this repository.

Refactor saker.java.processor implementation to employ classpath caching in the bundle storage

The saker.java.processor() task currently loads the classpath for the annotation processors by opening the files in-place. This can cause JAR files to be locked, and may prevent issues when the user tries to delete/overwrite them.

The classpath input for the task should be cached off-site, meaning that it should be copied to a location private to the saker.java.compiler bundle. The saker.nest repository provides access to such directory, and the classpaths should be copied there.

Note that this cache location is shared by all concurrently running build executions, therefore proper file-system level locking should be ensured.

The deprecated part of the ProcessorCreationContextImpl class should be removed when this issue is done.

The ClassLoader creation for the classpath should be cached by the build environment, so they won't be recreated between subsequent builds.

Both the bug and enhancement labels are added to the issue as it qualifies as both. Currently the issue can be easily worked around.

Superclass not recompiled when static method is added to subclass

Describe the bug
The superclass is not recompiled when a static method is added that is potentially referenced by the superclass.

To Reproduce

class SuperClass {
    public static SuperClass create(CharSequence obj) {
        if (obj instanceof String) {
             return SubClass.create((String)obj);
        }
        //...
    }
}
class SubClass extends SuperClass {
    public static SubClass create(String s) {
        // this new method is added, and the SuperClass is not recompiled
    }}}
}

Or something like the above.

Expected behavior
SuperClass is recompiled

Handle generated class files by annotation processors

Currently the incremental Java compiler task doesn't allow generating class files. They are generally unhandled in relation with the annotation processors.

As most processors generate sources instead of class files, the implementation for this was not done previously.

The generated class files should be handled as the solution to this issue.

Annotation processors are not reinvoked if member element order changes

If an annotation processor queries the Element.getEnclosedElements() and generates results that implicitly depends on the order of the elements, then the processor will not be reinvoked when the enclosed element order is changed. As an example:

public class Subject {
    public int a;
    public int b;
}

The processor may generate a resource with the following contents

a[...]
b[...]

If the developer decides to only change up the order of the elements as:

public class Subject {
    public int b;
    public int a;
}

Then the processor would generate:

b[...]
a[...]

However, the processor is not reinvoked by the incremental compiler task.

This is a bug.

Workaround

Perform a clean build or the processor shouldn't depend on the element order. Alphabetic sorting may be a good solution.

Solution

Track the behaviour of the processors and the expected indexes for the associated elements. If the indexes change, reinvoke the processors.

We might consider adding a flag to the processor configuration to signal that a given processor actually depends on the element order. As most processors probably don't, tracking them could introduce some overhead.

Another note that is that we might get away by only tracking the relative order between elements that were reported as input dependencies to a given resource generation. This should be much easier to implement and more straight forward from a Processor perspective.

Fix leftover deprecation warnings

If a Java element has @Deprecated annotation on it, and also has the @deprecated tag in its Javadoc, then removing only the annotation leaves the deprecated warnings on the referencing source parts. This is okay.

However, removing the @deprecated Javadoc tag won't remove the warnings, and will cause them to linger until the source files with the warning are modified by hand.

Import change in superclass doesn't trigger recompilation in implementation

Describe the bug
If an import statement in a superinterface of a class is changed, and thus modifying the signature of a method, then the implementation class is not recompiled.

To Reproduce
Use the following classes in a separate files according to their package names:

package test;

import test.p1.ImportedClass;

public interface Itf {
	public void f(ImportedClass i);
}

package test;

import test.p1.ImportedClass;

public class ItfImpl implements Itf {

	@Override
	public void f(ImportedClass i) {
		i.p1();
	}

}

package test.p1;

public class ImportedClass {
	public void p1() {
	}
}

package test.p2;

public class ImportedClass {
	public void p2() {
	}
}

Change import test.p1.ImportedClass; to import test.p2.ImportedClass; in Itf. ItfImpl should be recompiled, but it isn't.

Bug nature

  • What component is the bug related to? incremental builds
  • When does it happen: incremental builds only
  • How often does the bug happen: always

Solution
The information is already there for tracking this dependency change. The solution should be straight forward to implement. Create test case and solution.

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.