Search in sources :

Example 1 with JavaCompiler

use of org.codehaus.groovy.tools.javac.JavaCompiler in project intellij-community by JetBrains.

the class DependentGroovycRunner method createStubGenerator.

private static CompilationUnit createStubGenerator(final CompilerConfiguration config, final GroovyClassLoader classLoader, final GroovyClassLoader transformLoader, final Queue mailbox, final GroovyCompilerWrapper wrapper) {
    final JavaAwareCompilationUnit unit = new JavaAwareCompilationUnit(config, classLoader) {

        private boolean annoRemovedAdded;

        @Override
        public GroovyClassLoader getTransformLoader() {
            return transformLoader;
        }

        @Override
        public void addPhaseOperation(PrimaryClassNodeOperation op, int phase) {
            if (!annoRemovedAdded && mailbox == null && phase == Phases.CONVERSION && op.getClass().getName().startsWith("org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit$")) {
                annoRemovedAdded = true;
                super.addPhaseOperation(new PrimaryClassNodeOperation() {

                    @Override
                    public void call(final SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException {
                        final ClassCodeVisitorSupport annoRemover = new ClassCodeVisitorSupport() {

                            @Override
                            protected SourceUnit getSourceUnit() {
                                return source;
                            }

                            public void visitClass(ClassNode node) {
                                if (node.isEnum()) {
                                    node.setModifiers(node.getModifiers() & ~Opcodes.ACC_FINAL);
                                }
                                super.visitClass(node);
                            }

                            @Override
                            public void visitField(FieldNode fieldNode) {
                                Expression valueExpr = fieldNode.getInitialValueExpression();
                                if (valueExpr instanceof ConstantExpression && ClassHelper.STRING_TYPE.equals(valueExpr.getType())) {
                                    fieldNode.setInitialValueExpression(new MethodCallExpression(valueExpr, "toString", new ListExpression()));
                                }
                                super.visitField(fieldNode);
                            }

                            @Override
                            public void visitAnnotations(AnnotatedNode node) {
                                List<AnnotationNode> annotations = node.getAnnotations();
                                if (!annotations.isEmpty()) {
                                    annotations.clear();
                                }
                                super.visitAnnotations(node);
                            }
                        };
                        try {
                            annoRemover.visitClass(classNode);
                        } catch (LinkageError ignored) {
                        }
                    }
                }, phase);
            }
            super.addPhaseOperation(op, phase);
        }

        public void gotoPhase(int phase) throws CompilationFailedException {
            if (phase < Phases.SEMANTIC_ANALYSIS) {
                System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Groovy stub generator: " + getPhaseDescription());
            } else if (phase <= Phases.ALL) {
                System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Groovyc: " + getPhaseDescription());
            }
            super.gotoPhase(phase);
        }
    };
    unit.setCompilerFactory(new JavaCompilerFactory() {

        public JavaCompiler createCompiler(final CompilerConfiguration config) {
            return new JavaCompiler() {

                public void compile(List<String> files, CompilationUnit cu) {
                    if (mailbox != null) {
                        reportCompiledItems(GroovyCompilerWrapper.getStubOutputItems(unit, (File) config.getJointCompilationOptions().get(STUB_DIR)));
                        System.out.flush();
                        System.err.flush();
                        pauseAndWaitForJavac(mailbox);
                        wrapper.onContinuation();
                    }
                }
            };
        }
    });
    unit.addSources(new String[] { "SomeClass.java" });
    return unit;
}
Also used : JavaAwareCompilationUnit(org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) JavaCompiler(org.codehaus.groovy.tools.javac.JavaCompiler) JavaAwareCompilationUnit(org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit) GeneratorContext(org.codehaus.groovy.classgen.GeneratorContext) JavaCompilerFactory(org.codehaus.groovy.tools.javac.JavaCompilerFactory) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression)

Example 2 with JavaCompiler

use of org.codehaus.groovy.tools.javac.JavaCompiler in project gradle by gradle.

the class ApiGroovyCompiler method execute.

@Override
public WorkResult execute(final GroovyJavaJointCompileSpec spec) {
    ApiCompilerResult result = new ApiCompilerResult();
    result.getAnnotationProcessingResult().setFullRebuildCause("Incremental annotation processing is not supported by Groovy.");
    GroovySystemLoaderFactory groovySystemLoaderFactory = new GroovySystemLoaderFactory();
    ClassLoader compilerClassLoader = this.getClass().getClassLoader();
    GroovySystemLoader compilerGroovyLoader = groovySystemLoaderFactory.forClassLoader(compilerClassLoader);
    CompilerConfiguration configuration = new CompilerConfiguration();
    configuration.setVerbose(spec.getGroovyCompileOptions().isVerbose());
    configuration.setSourceEncoding(spec.getGroovyCompileOptions().getEncoding());
    configuration.setTargetBytecode(spec.getTargetCompatibility());
    configuration.setTargetDirectory(spec.getDestinationDir());
    canonicalizeValues(spec.getGroovyCompileOptions().getOptimizationOptions());
    VersionNumber version = parseGroovyVersion();
    if (version.compareTo(VersionNumber.parse("2.5")) >= 0) {
        configuration.setParameters(spec.getGroovyCompileOptions().isParameters());
    } else if (spec.getGroovyCompileOptions().isParameters()) {
        throw new GradleException("Using Groovy compiler flag '--parameters' requires Groovy 2.5+ but found Groovy " + version);
    }
    IncrementalCompilationCustomizer customizer = IncrementalCompilationCustomizer.fromSpec(spec, result);
    customizer.addToConfiguration(configuration);
    if (spec.getGroovyCompileOptions().getConfigurationScript() != null) {
        applyConfigurationScript(spec.getGroovyCompileOptions().getConfigurationScript(), configuration);
    }
    try {
        configuration.setOptimizationOptions(spec.getGroovyCompileOptions().getOptimizationOptions());
    } catch (NoSuchMethodError ignored) {
    /* method was only introduced in Groovy 1.8 */
    }
    try {
        configuration.setDisabledGlobalASTTransformations(spec.getGroovyCompileOptions().getDisabledGlobalASTTransformations());
    } catch (NoSuchMethodError ignored) {
    /* method was only introduced in Groovy 2.0.0 */
    }
    Map<String, Object> jointCompilationOptions = new HashMap<String, Object>();
    final File stubDir = spec.getGroovyCompileOptions().getStubDir();
    stubDir.mkdirs();
    jointCompilationOptions.put("stubDir", stubDir);
    jointCompilationOptions.put("keepStubs", spec.getGroovyCompileOptions().isKeepStubs());
    configuration.setJointCompilationOptions(jointCompilationOptions);
    ClassLoader classPathLoader;
    if (version.compareTo(VersionNumber.parse("2.0")) < 0) {
        // using a transforming classloader is only required for older buggy Groovy versions
        classPathLoader = new GroovyCompileTransformingClassLoader(getExtClassLoader(), DefaultClassPath.of(spec.getCompileClasspath()));
    } else {
        classPathLoader = new DefaultClassLoaderFactory().createIsolatedClassLoader("api-groovy-compile-loader", DefaultClassPath.of(spec.getCompileClasspath()));
    }
    GroovyClassLoader compileClasspathClassLoader = new GroovyClassLoader(classPathLoader, null);
    GroovySystemLoader compileClasspathLoader = groovySystemLoaderFactory.forClassLoader(classPathLoader);
    FilteringClassLoader.Spec groovyCompilerClassLoaderSpec = new FilteringClassLoader.Spec();
    groovyCompilerClassLoaderSpec.allowPackage("org.codehaus.groovy");
    groovyCompilerClassLoaderSpec.allowPackage("groovy");
    groovyCompilerClassLoaderSpec.allowPackage("groovyjarjarasm");
    // Disallow classes from Groovy Jar that reference external classes. Such classes must be loaded from astTransformClassLoader,
    // or a NoClassDefFoundError will occur. Essentially this is drawing a line between the Groovy compiler and the Groovy
    // library, albeit only for selected classes that run a high risk of being statically referenced from a transform.
    groovyCompilerClassLoaderSpec.disallowClass("groovy.util.GroovyTestCase");
    groovyCompilerClassLoaderSpec.disallowClass("org.codehaus.groovy.transform.NotYetImplementedASTTransformation");
    groovyCompilerClassLoaderSpec.disallowPackage("groovy.servlet");
    FilteringClassLoader groovyCompilerClassLoader = new FilteringClassLoader(GroovyClassLoader.class.getClassLoader(), groovyCompilerClassLoaderSpec);
    // AST transforms need their own class loader that shares compiler classes with the compiler itself
    final GroovyClassLoader astTransformClassLoader = new GroovyClassLoader(groovyCompilerClassLoader, null);
    // where the transform class is loaded from)
    for (File file : spec.getCompileClasspath()) {
        astTransformClassLoader.addClasspath(file.getPath());
    }
    JavaAwareCompilationUnit unit = new JavaAwareCompilationUnit(configuration, compileClasspathClassLoader) {

        @Override
        public GroovyClassLoader getTransformLoader() {
            return astTransformClassLoader;
        }
    };
    final boolean shouldProcessAnnotations = shouldProcessAnnotations(spec);
    if (shouldProcessAnnotations) {
        // If an annotation processor is detected, we need to force Java stub generation, so the we can process annotations on Groovy classes
        // We are forcing stub generation by tricking the groovy compiler into thinking there are java files to compile.
        // All java files are just passed to the compile method of the JavaCompiler and aren't processed internally by the Groovy Compiler.
        // Since we're maintaining our own list of Java files independent of what's passed by the Groovy compiler, adding a non-existent java file
        // to the sources won't cause any issues.
        unit.addSources(new File[] { new File("ForceStubGeneration.java") });
    }
    unit.addSources(getSortedSourceFiles(spec));
    unit.setCompilerFactory(new JavaCompilerFactory() {

        @Override
        public JavaCompiler createCompiler(final CompilerConfiguration config) {
            return new JavaCompiler() {

                @Override
                public void compile(List<String> files, CompilationUnit cu) {
                    if (shouldProcessAnnotations) {
                        // In order for the Groovy stubs to have annotation processors invoked against them, they must be compiled as source.
                        // Classes compiled as a result of being on the -sourcepath do not have the annotation processor run against them
                        spec.setSourceFiles(Iterables.concat(spec.getSourceFiles(), projectLayout.files(stubDir).getAsFileTree()));
                    } else {
                        // When annotation processing isn't required, it's better to add the Groovy stubs as part of the source path.
                        // This allows compilations to complete faster, because only the Groovy stubs that are needed by the java source are compiled.
                        ImmutableList.Builder<File> sourcepathBuilder = ImmutableList.builder();
                        sourcepathBuilder.add(stubDir);
                        if (spec.getCompileOptions().getSourcepath() != null) {
                            sourcepathBuilder.addAll(spec.getCompileOptions().getSourcepath());
                        }
                        spec.getCompileOptions().setSourcepath(sourcepathBuilder.build());
                    }
                    spec.setSourceFiles(Iterables.filter(spec.getSourceFiles(), new Predicate<File>() {

                        @Override
                        public boolean apply(File file) {
                            return hasExtension(file, ".java");
                        }
                    }));
                    try {
                        WorkResult javaCompilerResult = javaCompiler.execute(spec);
                        if (javaCompilerResult instanceof ApiCompilerResult) {
                            result.getSourceClassesMapping().putAll(((ApiCompilerResult) javaCompilerResult).getSourceClassesMapping());
                        }
                    } catch (CompilationFailedException e) {
                        cu.getErrorCollector().addFatalError(new SimpleMessage(e.getMessage(), cu));
                    }
                }
            };
        }
    });
    try {
        unit.compile();
        return result;
    } catch (org.codehaus.groovy.control.CompilationFailedException e) {
        System.err.println(e.getMessage());
        // Explicit flush, System.err is an auto-flushing PrintWriter unless it is replaced.
        System.err.flush();
        throw new CompilationFailedException();
    } finally {
        // Remove compile and AST types from the Groovy loader
        compilerGroovyLoader.discardTypesFrom(classPathLoader);
        compilerGroovyLoader.discardTypesFrom(astTransformClassLoader);
        // Discard the compile loader
        compileClasspathLoader.shutdown();
        CompositeStoppable.stoppable(classPathLoader, astTransformClassLoader).stop();
    }
}
Also used : HashMap(java.util.HashMap) JavaAwareCompilationUnit(org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit) GroovyClassLoader(groovy.lang.GroovyClassLoader) CompilerConfiguration(org.codehaus.groovy.control.CompilerConfiguration) FilteringClassLoader(org.gradle.internal.classloader.FilteringClassLoader) GroovyClassLoader(groovy.lang.GroovyClassLoader) GroovySystemLoader(org.gradle.api.internal.classloading.GroovySystemLoader) GroovySystemLoaderFactory(org.gradle.api.internal.classloading.GroovySystemLoaderFactory) DefaultClassLoaderFactory(org.gradle.internal.classloader.DefaultClassLoaderFactory) JavaAwareCompilationUnit(org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit) CompilationUnit(org.codehaus.groovy.control.CompilationUnit) SimpleMessage(org.codehaus.groovy.control.messages.SimpleMessage) JavaCompiler(org.codehaus.groovy.tools.javac.JavaCompiler) JavaCompilerFactory(org.codehaus.groovy.tools.javac.JavaCompilerFactory) VersionNumber(org.gradle.util.internal.VersionNumber) GradleException(org.gradle.api.GradleException) FilteringClassLoader(org.gradle.internal.classloader.FilteringClassLoader) WorkResult(org.gradle.api.tasks.WorkResult) File(java.io.File)

Aggregations

JavaAwareCompilationUnit (org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit)2 JavaCompiler (org.codehaus.groovy.tools.javac.JavaCompiler)2 JavaCompilerFactory (org.codehaus.groovy.tools.javac.JavaCompilerFactory)2 GroovyClassLoader (groovy.lang.GroovyClassLoader)1 File (java.io.File)1 HashMap (java.util.HashMap)1 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)1 Expression (org.codehaus.groovy.ast.expr.Expression)1 ListExpression (org.codehaus.groovy.ast.expr.ListExpression)1 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)1 GeneratorContext (org.codehaus.groovy.classgen.GeneratorContext)1 CompilationUnit (org.codehaus.groovy.control.CompilationUnit)1 CompilerConfiguration (org.codehaus.groovy.control.CompilerConfiguration)1 SimpleMessage (org.codehaus.groovy.control.messages.SimpleMessage)1 GradleException (org.gradle.api.GradleException)1 GroovySystemLoader (org.gradle.api.internal.classloading.GroovySystemLoader)1 GroovySystemLoaderFactory (org.gradle.api.internal.classloading.GroovySystemLoaderFactory)1 WorkResult (org.gradle.api.tasks.WorkResult)1 DefaultClassLoaderFactory (org.gradle.internal.classloader.DefaultClassLoaderFactory)1 FilteringClassLoader (org.gradle.internal.classloader.FilteringClassLoader)1