mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-120443 Groovy: Idea can't compile valid code in implicitly typed statically compiled extension module
This commit is contained in:
+1
-3
@@ -124,8 +124,6 @@ public class GroovyBuilder extends ModuleLevelBuilder {
|
||||
Map<ModuleBuildTarget, String> generationOutputs = myForStubs ? getStubGenerationOutputs(chunk, context) : finalOutputs;
|
||||
String compilerOutput = generationOutputs.get(chunk.representativeTarget());
|
||||
|
||||
String finalOutput = FileUtil.toSystemDependentName(finalOutputs.get(chunk.representativeTarget()));
|
||||
|
||||
Collection<String> classpath = generateClasspath(context, chunk);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Optimized class loading: " + optimizeClassLoading);
|
||||
@@ -133,7 +131,7 @@ public class GroovyBuilder extends ModuleLevelBuilder {
|
||||
}
|
||||
|
||||
final File tempFile = GroovycOSProcessHandler.fillFileWithGroovycParameters(
|
||||
compilerOutput, toCompilePaths, finalOutput, class2Src, encoding, patchers,
|
||||
compilerOutput, toCompilePaths, finalOutputs.values(), class2Src, encoding, patchers,
|
||||
optimizeClassLoading ? StringUtil.join(classpath, File.pathSeparator) : ""
|
||||
);
|
||||
final GroovycOSProcessHandler handler = runGroovyc(context, chunk, tempFile, settings, classpath, optimizeClassLoading);
|
||||
|
||||
+2
-2
@@ -246,7 +246,7 @@ public class GroovycOSProcessHandler extends BaseOSProcessHandler {
|
||||
|
||||
public static File fillFileWithGroovycParameters(final String outputDir,
|
||||
final Collection<String> changedSources,
|
||||
String finalOutput,
|
||||
Collection<String> finalOutputs,
|
||||
Map<String, String> class2Src,
|
||||
@Nullable final String encoding,
|
||||
List<String> patchers,
|
||||
@@ -284,7 +284,7 @@ public class GroovycOSProcessHandler extends BaseOSProcessHandler {
|
||||
writer.write(outputDir);
|
||||
writer.write("\n");
|
||||
writer.write(GroovyRtConstants.FINAL_OUTPUTPATH + "\n");
|
||||
writer.write(finalOutput);
|
||||
writer.write(StringUtil.join(finalOutputs, File.pathSeparator));
|
||||
writer.write("\n");
|
||||
}
|
||||
finally {
|
||||
|
||||
+43
-43
@@ -29,8 +29,6 @@ import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.*;
|
||||
@@ -39,6 +37,9 @@ import java.util.*;
|
||||
* @author peter
|
||||
*/
|
||||
public class DependentGroovycRunner {
|
||||
public static final String TEMP_RESOURCE_SUFFIX = "___" + new Random().nextInt() + "_neverHappen";
|
||||
public static final String[] RESOURCES_TO_MASK = {"META-INF/services/org.codehaus.groovy.transform.ASTTransformation", "META-INF/services/org.codehaus.groovy.runtime.ExtensionModule"};
|
||||
|
||||
public static boolean runGroovyc(boolean forStubs, String argsPath) {
|
||||
File argsFile = new File(argsPath);
|
||||
final CompilerConfiguration config = new CompilerConfiguration();
|
||||
@@ -51,8 +52,8 @@ public class DependentGroovycRunner {
|
||||
final List<File> srcFiles = new ArrayList<File>();
|
||||
final Map<String, File> class2File = new HashMap<String, File>();
|
||||
|
||||
final String[] finalOutput = new String[1];
|
||||
fillFromArgsFile(argsFile, config, patchers, compilerMessages, srcFiles, class2File, finalOutput);
|
||||
final String[] finalOutputRef = new String[1];
|
||||
fillFromArgsFile(argsFile, config, patchers, compilerMessages, srcFiles, class2File, finalOutputRef);
|
||||
if (srcFiles.isEmpty()) return true;
|
||||
|
||||
if (forStubs) {
|
||||
@@ -63,23 +64,32 @@ public class DependentGroovycRunner {
|
||||
}
|
||||
|
||||
System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Groovyc: loading sources...");
|
||||
final AstAwareResourceLoader resourceLoader = new AstAwareResourceLoader(class2File);
|
||||
final CompilationUnit unit = createCompilationUnit(forStubs, config, finalOutput[0], buildClassLoaderFor(config, resourceLoader));
|
||||
unit.addPhaseOperation(new CompilationUnit.SourceUnitOperation() {
|
||||
public void call(SourceUnit source) throws CompilationFailedException {
|
||||
File file = new File(source.getName());
|
||||
for (ClassNode aClass : source.getAST().getClasses()) {
|
||||
resourceLoader.myClass2File.put(aClass.getName(), file);
|
||||
String[] finalOutputs = finalOutputRef[0].split(File.pathSeparator);
|
||||
renameResources(finalOutputs, "", TEMP_RESOURCE_SUFFIX);
|
||||
|
||||
final List<GroovyCompilerWrapper.OutputItem> compiledFiles;
|
||||
try {
|
||||
final AstAwareResourceLoader resourceLoader = new AstAwareResourceLoader(class2File);
|
||||
final CompilationUnit unit = createCompilationUnit(forStubs, config, buildClassLoaderFor(config, resourceLoader));
|
||||
unit.addPhaseOperation(new CompilationUnit.SourceUnitOperation() {
|
||||
public void call(SourceUnit source) throws CompilationFailedException {
|
||||
File file = new File(source.getName());
|
||||
for (ClassNode aClass : source.getAST().getClasses()) {
|
||||
resourceLoader.myClass2File.put(aClass.getName(), file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, Phases.CONVERSION);
|
||||
}, Phases.CONVERSION);
|
||||
|
||||
addSources(forStubs, srcFiles, unit);
|
||||
runPatchers(patchers, compilerMessages, unit, resourceLoader, srcFiles);
|
||||
addSources(forStubs, srcFiles, unit);
|
||||
runPatchers(patchers, compilerMessages, unit, resourceLoader, srcFiles);
|
||||
|
||||
System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Groovyc: compiling...");
|
||||
final List<GroovyCompilerWrapper.OutputItem> compiledFiles = new GroovyCompilerWrapper(compilerMessages, forStubs).compile(unit);
|
||||
System.out.println(GroovyRtConstants.CLEAR_PRESENTABLE);
|
||||
System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Groovyc: compiling...");
|
||||
compiledFiles = new GroovyCompilerWrapper(compilerMessages, forStubs).compile(unit);
|
||||
}
|
||||
finally {
|
||||
renameResources(finalOutputs, TEMP_RESOURCE_SUFFIX, "");
|
||||
System.out.println(GroovyRtConstants.CLEAR_PRESENTABLE);
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
reportCompiledItems(compiledFiles);
|
||||
@@ -103,8 +113,19 @@ public class DependentGroovycRunner {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void renameResources(String[] finalOutputs, String removeSuffix, String addSuffix) {
|
||||
for (String output : finalOutputs) {
|
||||
for (String res : RESOURCES_TO_MASK) {
|
||||
File file = new File(output, res + removeSuffix);
|
||||
if (file.exists()) {
|
||||
file.renameTo(new File(output, res + addSuffix));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String fillFromArgsFile(File argsFile, CompilerConfiguration compilerConfiguration, List<CompilationUnitPatcher> patchers, List<CompilerMessage> compilerMessages,
|
||||
List<File> srcFiles, Map<String, File> class2File, String[] finalOutput) {
|
||||
List<File> srcFiles, Map<String, File> class2File, String[] finalOutputs) {
|
||||
String moduleClasspath = null;
|
||||
|
||||
BufferedReader reader = null;
|
||||
@@ -157,7 +178,7 @@ public class DependentGroovycRunner {
|
||||
compilerConfiguration.setTargetDirectory(reader.readLine());
|
||||
}
|
||||
else if (line.startsWith(GroovyRtConstants.FINAL_OUTPUTPATH)) {
|
||||
finalOutput[0] = reader.readLine();
|
||||
finalOutputs[0] = reader.readLine();
|
||||
}
|
||||
|
||||
line = reader.readLine();
|
||||
@@ -256,30 +277,9 @@ public class DependentGroovycRunner {
|
||||
|
||||
private static CompilationUnit createCompilationUnit(final boolean forStubs,
|
||||
final CompilerConfiguration config,
|
||||
final String finalOutput, final GroovyClassLoader classLoader) {
|
||||
final GroovyClassLoader classLoader) {
|
||||
|
||||
final GroovyClassLoader transformLoader = new GroovyClassLoader(classLoader) {
|
||||
public Enumeration<URL> getResources(String name) throws IOException {
|
||||
if (name.endsWith("org.codehaus.groovy.transform.ASTTransformation")) {
|
||||
final Enumeration<URL> resources = super.getResources(name);
|
||||
final ArrayList<URL> list = Collections.list(resources);
|
||||
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
|
||||
final URL url = (URL)iterator.next();
|
||||
try {
|
||||
final String file = new File(new URI(url.toString())).getCanonicalPath();
|
||||
if (file.startsWith(finalOutput) || file.startsWith("/" + finalOutput)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
System.out.println("Invalid URI syntax: " + url.toString());
|
||||
}
|
||||
}
|
||||
return Collections.enumeration(list);
|
||||
}
|
||||
return super.getResources(name);
|
||||
}
|
||||
};
|
||||
final GroovyClassLoader transformLoader = new GroovyClassLoader(classLoader);
|
||||
|
||||
try {
|
||||
if (forStubs) {
|
||||
|
||||
@@ -55,7 +55,7 @@ import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.encoding.EncodingProjectManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
@@ -166,10 +166,14 @@ public abstract class GroovyCompilerBase implements TranslatingCompiler {
|
||||
|
||||
parameters.setMainClass(GroovycRunner.class.getName());
|
||||
|
||||
final VirtualFile finalOutputDir = getMainOutput(compileContext, module, tests);
|
||||
if (finalOutputDir == null) {
|
||||
compileContext.addMessage(CompilerMessageCategory.ERROR, "No output directory for module " + module.getName() + (tests ? " tests" : " production"), null, -1, -1);
|
||||
return;
|
||||
List<String> finalOutputs = ContainerUtil.newArrayList();
|
||||
for (Module eachModule : chunk.getModules()) {
|
||||
final VirtualFile finalOutputDir = getMainOutput(compileContext, eachModule, tests);
|
||||
if (finalOutputDir == null) {
|
||||
compileContext.addMessage(CompilerMessageCategory.ERROR, "No output directory for module " + eachModule.getName() + (tests ? " tests" : " production"), null, -1, -1);
|
||||
return;
|
||||
}
|
||||
finalOutputs.add(FileUtil.toSystemDependentName(finalOutputDir.getPath()));
|
||||
}
|
||||
|
||||
final Charset ideCharset = EncodingProjectManager.getInstance(myProject).getDefaultCharset();
|
||||
@@ -193,7 +197,7 @@ public abstract class GroovyCompilerBase implements TranslatingCompiler {
|
||||
final File fileWithParameters;
|
||||
try {
|
||||
fileWithParameters = GroovycOSProcessHandler
|
||||
.fillFileWithGroovycParameters(outputDir.getPath(), paths2Compile, FileUtil.toSystemDependentName(finalOutputDir.getPath()),
|
||||
.fillFileWithGroovycParameters(outputDir.getPath(), paths2Compile, finalOutputs,
|
||||
class2Src, encoding, patchers, "");
|
||||
}
|
||||
catch (IOException e) {
|
||||
@@ -228,7 +232,7 @@ public abstract class GroovyCompilerBase implements TranslatingCompiler {
|
||||
for (CompilerMessage compilerMessage : processHandler.getCompilerMessages(module.getName())) {
|
||||
final String url = compilerMessage.getSourcePath();
|
||||
compileContext.addMessage(getMessageCategory(compilerMessage), compilerMessage.getMessageText(),
|
||||
url == null ? null : VfsUtil.pathToUrl(FileUtil.toSystemIndependentName(url)),
|
||||
url == null ? null : VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(url)),
|
||||
(int)compilerMessage.getLine(),
|
||||
(int)compilerMessage.getColumn());
|
||||
}
|
||||
@@ -280,7 +284,7 @@ public abstract class GroovyCompilerBase implements TranslatingCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
sink.add(outputDir.getPath(), items, VfsUtil.toVirtualFileArray(toRecompile));
|
||||
sink.add(outputDir.getPath(), items, VfsUtilCore.toVirtualFileArray(toRecompile));
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
LOG.info(e);
|
||||
|
||||
+32
-9
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.plugins.groovy.compiler
|
||||
import com.intellij.compiler.CompilerConfiguration
|
||||
import com.intellij.compiler.CompilerConfigurationImpl
|
||||
import com.intellij.compiler.impl.TranslatingCompilerFilesMonitor
|
||||
import com.intellij.compiler.server.BuildManager
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.compiler.CompilerMessage
|
||||
@@ -41,12 +40,6 @@ public abstract class GroovyCompilerTest extends GroovyCompilerTestCase {
|
||||
addGroovyLibrary(myModule);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
TranslatingCompilerFilesMonitor.ourDebugMode = false
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
public void testPlainGroovy() throws Throwable {
|
||||
myFixture.addFileToProject("A.groovy", "println '239'");
|
||||
assertEmpty(make());
|
||||
@@ -134,8 +127,6 @@ public abstract class GroovyCompilerTest extends GroovyCompilerTestCase {
|
||||
}
|
||||
|
||||
public void testTransitiveJavaDependencyThroughGroovy() throws Throwable {
|
||||
TranslatingCompilerFilesMonitor.ourDebugMode = true
|
||||
|
||||
myFixture.addClass("public class IFoo { void foo() {} }").getContainingFile().getVirtualFile();
|
||||
myFixture.addFileToProject("Foo.groovy", "class Foo {\n" +
|
||||
" static IFoo f\n" +
|
||||
@@ -796,6 +787,38 @@ string
|
||||
assertEmpty make()
|
||||
}
|
||||
|
||||
public void "test compiling static extension"() {
|
||||
setupTestSources()
|
||||
myFixture.addFileToProject "src/extension/Extension.groovy", """
|
||||
package extension
|
||||
import groovy.transform.CompileStatic
|
||||
|
||||
@CompileStatic class Extension {
|
||||
static <T> T test2(List<T> self) {
|
||||
self.first()
|
||||
}
|
||||
}"""
|
||||
myFixture.addFileToProject "src/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule", """
|
||||
moduleName=extension-verify
|
||||
moduleVersion=1.0-test
|
||||
extensionClasses=extension.Extension
|
||||
staticExtensionClasses=
|
||||
"""
|
||||
myFixture.addFileToProject "tests/AppTest.groovy", """
|
||||
class AppTest {
|
||||
@groovy.transform.CompileStatic
|
||||
static main(args) {
|
||||
List<String> list = new ArrayList<>()
|
||||
list.add("b")
|
||||
list.add("c")
|
||||
println list.test2()
|
||||
}
|
||||
}
|
||||
"""
|
||||
assertEmpty make()
|
||||
assertOutput 'AppTest', 'b'
|
||||
}
|
||||
|
||||
public static class IdeaModeTest extends GroovyCompilerTest {
|
||||
@Override protected boolean useJps() { false }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user