mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Running java scratches (IDEA-140228)
This commit is contained in:
@@ -17,6 +17,7 @@ package com.intellij.compiler;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.compiler.impl.*;
|
||||
import com.intellij.compiler.server.BuildManager;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.compiler.*;
|
||||
@@ -29,20 +30,38 @@ import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkType;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.SdkTypeId;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import com.intellij.util.net.NetUtils;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.api.CanceledStatus;
|
||||
import org.jetbrains.jps.builders.impl.java.JavacCompilerTool;
|
||||
import org.jetbrains.jps.incremental.BinaryContent;
|
||||
import org.jetbrains.jps.javac.DiagnosticOutputConsumer;
|
||||
import org.jetbrains.jps.javac.ExternalJavacManager;
|
||||
import org.jetbrains.jps.javac.OutputFileConsumer;
|
||||
import org.jetbrains.jps.javac.OutputFileObject;
|
||||
|
||||
import javax.tools.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.net.URI;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
@@ -58,6 +77,7 @@ public class CompilerManagerImpl extends CompilerManager {
|
||||
private final Semaphore myCompilationSemaphore = new Semaphore(1, true);
|
||||
private final Set<ModuleType> myValidationDisabledModuleTypes = new HashSet<ModuleType>();
|
||||
private final Set<LocalFileSystem.WatchRequest> myWatchRoots;
|
||||
private volatile ExternalJavacManager myExternalJavacManager;
|
||||
|
||||
public CompilerManagerImpl(final Project project, MessageBus messageBus) {
|
||||
myProject = project;
|
||||
@@ -85,6 +105,11 @@ public class CompilerManagerImpl extends CompilerManager {
|
||||
myWatchRoots = lfs.addRootsToWatch(Collections.singletonList(FileUtil.toCanonicalPath(projectGeneratedSrcRoot.getPath())), true);
|
||||
Disposer.register(project, new Disposable() {
|
||||
public void dispose() {
|
||||
final ExternalJavacManager manager = myExternalJavacManager;
|
||||
myExternalJavacManager = null;
|
||||
if (manager != null) {
|
||||
manager.stop();
|
||||
}
|
||||
lfs.removeWatchedRoots(myWatchRoots);
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) { // force cleanup for created compiler system directory with generated sources
|
||||
FileUtil.delete(CompilerPaths.getCompilerSystemDirectory(project));
|
||||
@@ -310,6 +335,144 @@ public class CompilerManagerImpl extends CompilerManager {
|
||||
return !myValidationDisabledModuleTypes.contains(ModuleType.get(module));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ClassObject> compileJavaCode(List<String> options,
|
||||
Collection<File> platformCp,
|
||||
Collection<File> classpath,
|
||||
Collection<File> sourcePath,
|
||||
Collection<File> files,
|
||||
File outputDir) throws IOException, CompilationException {
|
||||
|
||||
final Pair<Sdk, JavaSdkVersion> runtime = BuildManager.getBuildProcessRuntimeSdk(myProject);
|
||||
|
||||
String javaHome = null;
|
||||
final Sdk sdk = runtime.getFirst();
|
||||
final SdkTypeId type = sdk.getSdkType();
|
||||
if (type instanceof JavaSdkType) {
|
||||
javaHome = sdk.getHomePath();
|
||||
}
|
||||
if (javaHome == null) {
|
||||
throw new IOException("Was not able to determine JDK for project " + myProject.getName());
|
||||
}
|
||||
|
||||
final OutputCollector outputCollector = new OutputCollector();
|
||||
DiagnosticCollector diagnostic = new DiagnosticCollector();
|
||||
|
||||
final Set<File> sourceRoots = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
|
||||
if (!sourcePath.isEmpty()) {
|
||||
for (File file : sourcePath) {
|
||||
sourceRoots.add(file);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (File file : files) {
|
||||
final File parentFile = file.getParentFile();
|
||||
if (parentFile != null) {
|
||||
sourceRoots.add(parentFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
final Map<File, Set<File>> outs = Collections.singletonMap(outputDir, sourceRoots);
|
||||
|
||||
final ExternalJavacManager javacManager = getJavacManager();
|
||||
boolean compiledOk = javacManager != null && javacManager.forkJavac(
|
||||
javaHome, -1, Collections.<String>emptyList(), options, platformCp, classpath, sourcePath, files, outs, diagnostic, outputCollector,
|
||||
new JavacCompilerTool(), CanceledStatus.NULL
|
||||
);
|
||||
|
||||
if (!compiledOk) {
|
||||
final List<CompilationException.Message> messages = new SmartList<CompilationException.Message>();
|
||||
for (Diagnostic<? extends JavaFileObject> d : diagnostic.getDiagnostics()) {
|
||||
final JavaFileObject source = d.getSource();
|
||||
final URI uri = source != null ? source.toUri() : null;
|
||||
messages.add(new CompilationException.Message(
|
||||
kindToCategory(d.getKind()), d.getMessage(Locale.US), uri != null? uri.toURL().toString() : null, (int)d.getLineNumber(), (int)d.getColumnNumber()
|
||||
));
|
||||
}
|
||||
throw new CompilationException("Compilation failed", messages);
|
||||
}
|
||||
|
||||
final List<ClassObject> result = new ArrayList<ClassObject>();
|
||||
for (OutputFileObject fileObject : outputCollector.getCompiledClasses()) {
|
||||
final BinaryContent content = fileObject.getContent();
|
||||
result.add(new CompiledClass(fileObject.getName(), fileObject.getClassName(), content != null ? content.toByteArray() : null));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static CompilerMessageCategory kindToCategory(Diagnostic.Kind kind) {
|
||||
switch (kind) {
|
||||
case ERROR: return CompilerMessageCategory.ERROR;
|
||||
case MANDATORY_WARNING: return CompilerMessageCategory.WARNING;
|
||||
case WARNING: return CompilerMessageCategory.WARNING;
|
||||
case NOTE: return CompilerMessageCategory.INFORMATION;
|
||||
default:
|
||||
return CompilerMessageCategory.INFORMATION;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private ExternalJavacManager getJavacManager() throws IOException {
|
||||
ExternalJavacManager manager = myExternalJavacManager;
|
||||
if (manager == null) {
|
||||
synchronized (this) {
|
||||
manager = myExternalJavacManager;
|
||||
if (manager == null) {
|
||||
final File compilerWorkingDir = getJavacCompilerWorkingDir();
|
||||
if (compilerWorkingDir == null) {
|
||||
return null; // should not happen for real projects
|
||||
}
|
||||
final int listenPort = NetUtils.findAvailableSocketPort();
|
||||
manager = new ExternalJavacManager(compilerWorkingDir);
|
||||
manager.start(listenPort);
|
||||
myExternalJavacManager = manager;
|
||||
}
|
||||
}
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public File getJavacCompilerWorkingDir() {
|
||||
final File projectBuildDir = BuildManager.getInstance().getProjectSystemDirectory(myProject);
|
||||
if (projectBuildDir == null) {
|
||||
return null;
|
||||
}
|
||||
projectBuildDir.mkdirs();
|
||||
return projectBuildDir;
|
||||
}
|
||||
|
||||
private static class CompiledClass implements ClassObject {
|
||||
private final String myPath;
|
||||
private final String myClassName;
|
||||
private final byte[] myBytes;
|
||||
|
||||
public CompiledClass(String path, String className, byte[] bytes) {
|
||||
myPath = path;
|
||||
myClassName = className;
|
||||
myBytes = bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return myPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClassName() {
|
||||
return myClassName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public byte[] getContent() {
|
||||
return myBytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class ListenerNotificator implements CompileStatusNotification {
|
||||
private final @Nullable CompileStatusNotification myDelegate;
|
||||
|
||||
@@ -326,4 +489,42 @@ public class CompilerManagerImpl extends CompilerManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class DiagnosticCollector implements DiagnosticOutputConsumer {
|
||||
private final List<Diagnostic<? extends JavaFileObject>> myDiagnostics = new ArrayList<Diagnostic<? extends JavaFileObject>>();
|
||||
public void outputLineAvailable(String line) {
|
||||
// for debugging purposes uncomment this line
|
||||
//System.out.println(line);
|
||||
}
|
||||
|
||||
public void registerImports(String className, Collection<String> imports, Collection<String> staticImports) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
public void javaFileLoaded(File file) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
|
||||
myDiagnostics.add(diagnostic);
|
||||
}
|
||||
|
||||
public List<Diagnostic<? extends JavaFileObject>> getDiagnostics() {
|
||||
return myDiagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class OutputCollector implements OutputFileConsumer {
|
||||
private List<OutputFileObject> myClasses = new ArrayList<OutputFileObject>();
|
||||
|
||||
public void save(@NotNull OutputFileObject fileObject) {
|
||||
myClasses.add(fileObject);
|
||||
}
|
||||
|
||||
public List<OutputFileObject> getCompiledClasses() {
|
||||
return myClasses;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.compiler;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface ClassObject {
|
||||
String getPath();
|
||||
|
||||
String getClassName();
|
||||
|
||||
@Nullable
|
||||
byte[] getContent();
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.compiler;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public class CompilationException extends Exception {
|
||||
|
||||
private final Collection<Message> myMessages;
|
||||
|
||||
public static class Message {
|
||||
@NotNull
|
||||
private final CompilerMessageCategory myCategory;
|
||||
@NotNull
|
||||
private final String myMessage;
|
||||
@Nullable
|
||||
private final String myUrl;
|
||||
private final int myLine;
|
||||
private final int myColumn;
|
||||
|
||||
public Message(CompilerMessageCategory category, String message) {
|
||||
this(category, message, null, -1, -1);
|
||||
}
|
||||
|
||||
public Message(@NotNull CompilerMessageCategory category, @NotNull String message, @Nullable String url, int line, int column) {
|
||||
myCategory = category;
|
||||
myMessage = message;
|
||||
myUrl = url;
|
||||
myLine = line;
|
||||
myColumn = column;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CompilerMessageCategory getCategory() {
|
||||
return myCategory;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getText() {
|
||||
return myMessage;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getUrl() {
|
||||
return myUrl;
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
return myLine;
|
||||
}
|
||||
|
||||
public int getColumn() {
|
||||
return myColumn;
|
||||
}
|
||||
}
|
||||
|
||||
public CompilationException(String message) {
|
||||
this(message, Collections.<Message>emptyList());
|
||||
}
|
||||
|
||||
public CompilationException(String message, Collection<Message> messages) {
|
||||
super(message);
|
||||
myMessages = messages;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<Message> getMessages() {
|
||||
return myMessages;
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,10 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -289,4 +293,14 @@ public abstract class CompilerManager {
|
||||
public abstract void setValidationEnabled(ModuleType moduleType, boolean enabled);
|
||||
|
||||
public abstract boolean isValidationEnabled(Module moduleType);
|
||||
|
||||
public abstract Collection<ClassObject> compileJavaCode(List<String> options,
|
||||
Collection<File> platformCp,
|
||||
Collection<File> classpath,
|
||||
Collection<File> sourcePath,
|
||||
Collection<File> files,
|
||||
File outputDir) throws IOException, CompilationException;
|
||||
|
||||
@Nullable
|
||||
public abstract File getJavacCompilerWorkingDir();
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.intellij.debugger.impl.ClassLoadingUtils;
|
||||
import com.intellij.debugger.impl.DebuggerUtilsEx;
|
||||
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.compiler.ClassObject;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.JdkVersionUtil;
|
||||
@@ -38,8 +39,6 @@ import com.sun.jdi.ClassType;
|
||||
import com.sun.jdi.Value;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.incremental.BinaryContent;
|
||||
import org.jetbrains.jps.javac.OutputFileObject;
|
||||
import org.jetbrains.org.objectweb.asm.ClassReader;
|
||||
import org.jetbrains.org.objectweb.asm.ClassVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.ClassWriter;
|
||||
@@ -80,7 +79,7 @@ public abstract class CompilingEvaluator implements ExpressionEvaluator {
|
||||
ClassLoaderReference classLoader = ClassLoadingUtils.getClassLoader(evaluationContext, process);
|
||||
|
||||
String version = ((VirtualMachineProxyImpl)process.getVirtualMachineProxy()).version();
|
||||
Collection<OutputFileObject> classes = compile(JdkVersionUtil.getVersion(version));
|
||||
Collection<ClassObject> classes = compile(JdkVersionUtil.getVersion(version));
|
||||
|
||||
defineClasses(classes, evaluationContext, process, classLoader);
|
||||
|
||||
@@ -112,15 +111,15 @@ public abstract class CompilingEvaluator implements ExpressionEvaluator {
|
||||
}
|
||||
}
|
||||
|
||||
private ClassType defineClasses(Collection<OutputFileObject> classes,
|
||||
private ClassType defineClasses(Collection<ClassObject> classes,
|
||||
EvaluationContext context,
|
||||
DebugProcess process,
|
||||
ClassLoaderReference classLoader) throws EvaluateException {
|
||||
for (OutputFileObject cls : classes) {
|
||||
if (cls.getName().contains(GEN_CLASS_NAME)) {
|
||||
final BinaryContent content = cls.getContent();
|
||||
for (ClassObject cls : classes) {
|
||||
if (cls.getPath().contains(GEN_CLASS_NAME)) {
|
||||
final byte[] content = cls.getContent();
|
||||
if (content != null) {
|
||||
byte[] bytes = changeSuperToMagicAccessor(content.toByteArray());
|
||||
final byte[] bytes = changeSuperToMagicAccessor(content);
|
||||
ClassLoadingUtils.defineClass(cls.getClassName(), bytes, context, process, classLoader);
|
||||
}
|
||||
}
|
||||
@@ -165,6 +164,6 @@ public abstract class CompilingEvaluator implements ExpressionEvaluator {
|
||||
///////////////// Compiler stuff
|
||||
|
||||
@NotNull
|
||||
protected abstract Collection<OutputFileObject> compile(@Nullable JavaSdkVersion debuggeeVersion) throws EvaluateException;
|
||||
protected abstract Collection<ClassObject> compile(@Nullable JavaSdkVersion debuggeeVersion) throws EvaluateException;
|
||||
|
||||
}
|
||||
|
||||
+19
-128
@@ -16,39 +16,28 @@
|
||||
package com.intellij.debugger.ui.impl.watch;
|
||||
|
||||
import com.intellij.compiler.server.BuildManager;
|
||||
import com.intellij.debugger.engine.DebugProcess;
|
||||
import com.intellij.debugger.engine.DebugProcessAdapter;
|
||||
import com.intellij.debugger.engine.DebugProcessImpl;
|
||||
import com.intellij.debugger.engine.DebuggerManagerThreadImpl;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.compiler.ClassObject;
|
||||
import com.intellij.openapi.compiler.CompilationException;
|
||||
import com.intellij.openapi.compiler.CompilerManager;
|
||||
import com.intellij.openapi.compiler.CompilerMessageCategory;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkType;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.SdkTypeId;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.refactoring.extractMethodObject.ExtractLightMethodObjectHandler;
|
||||
import com.intellij.util.net.NetUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.api.CanceledStatus;
|
||||
import org.jetbrains.jps.builders.impl.java.JavacCompilerTool;
|
||||
import org.jetbrains.jps.javac.DiagnosticOutputConsumer;
|
||||
import org.jetbrains.jps.javac.ExternalJavacManager;
|
||||
import org.jetbrains.jps.javac.OutputFileConsumer;
|
||||
import org.jetbrains.jps.javac.OutputFileObject;
|
||||
|
||||
import javax.tools.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
@@ -65,23 +54,13 @@ public class CompilingEvaluatorImpl extends CompilingEvaluator {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected Collection<OutputFileObject> compile(@Nullable JavaSdkVersion debuggeeVersion) throws EvaluateException {
|
||||
final Pair<Sdk, JavaSdkVersion> runtime = BuildManager.getBuildProcessRuntimeSdk(myEvaluationContext.getProject());
|
||||
protected Collection<ClassObject> compile(@Nullable JavaSdkVersion debuggeeVersion) throws EvaluateException {
|
||||
final Module module = ApplicationManager.getApplication().runReadAction(new Computable<Module>() {
|
||||
@Override
|
||||
public Module compute() {
|
||||
return ModuleUtilCore.findModuleForPsiElement(myPsiContext);
|
||||
}
|
||||
});
|
||||
String javaHome = null;
|
||||
final Sdk sdk = runtime.getFirst();
|
||||
final SdkTypeId type = sdk.getSdkType();
|
||||
if (type instanceof JavaSdkType) {
|
||||
javaHome = sdk.getHomePath();
|
||||
}
|
||||
if (javaHome == null) {
|
||||
throw new EvaluateException("Was not able to determine JDK for current evaluation context");
|
||||
}
|
||||
final List<String> options = new ArrayList<String>();
|
||||
options.add("-proc:none"); // for our purposes annotation processing is not needed
|
||||
options.add("-encoding");
|
||||
@@ -98,6 +77,7 @@ public class CompilingEvaluatorImpl extends CompilingEvaluator {
|
||||
}
|
||||
}
|
||||
|
||||
final Pair<Sdk, JavaSdkVersion> runtime = BuildManager.getBuildProcessRuntimeSdk(myEvaluationContext.getProject());
|
||||
final JavaSdkVersion buildRuntimeVersion = runtime.getSecond();
|
||||
// if compiler or debuggee version or both are unknown, let source and target be the compiler's defaults
|
||||
if (buildRuntimeVersion != null && debuggeeVersion != null) {
|
||||
@@ -109,36 +89,25 @@ public class CompilingEvaluatorImpl extends CompilingEvaluator {
|
||||
options.add(sourceOption);
|
||||
}
|
||||
|
||||
final CompilerManager compilerManager = CompilerManager.getInstance(myEvaluationContext.getProject());
|
||||
|
||||
File sourceFile = null;
|
||||
final OutputCollector outputSink = new OutputCollector();
|
||||
try {
|
||||
final ExternalJavacManager javacManager = getJavacManager();
|
||||
if (javacManager == null) {
|
||||
throw new EvaluateException("Cannot compile java code");
|
||||
}
|
||||
sourceFile = generateTempSourceFile(javacManager.getWorkingDir());
|
||||
sourceFile = generateTempSourceFile(compilerManager.getJavacCompilerWorkingDir());
|
||||
final File srcDir = sourceFile.getParentFile();
|
||||
final Map<File, Set<File>> output = Collections.singletonMap(srcDir, Collections.singleton(srcDir));
|
||||
DiagnosticCollector diagnostic = new DiagnosticCollector();
|
||||
final List<String> vmOptions = Collections.emptyList();
|
||||
final List<File> sourcePath = Collections.emptyList();
|
||||
final Set<File> sources = Collections.singleton(sourceFile);
|
||||
boolean compiledOK = javacManager.forkJavac(
|
||||
javaHome, -1, vmOptions, options, platformClasspath, classpath, sourcePath, sources, output, diagnostic, outputSink, new JavacCompilerTool(), CanceledStatus.NULL
|
||||
);
|
||||
|
||||
if (!compiledOK) {
|
||||
final StringBuilder res = new StringBuilder("Compilation failed:\n");
|
||||
for (Diagnostic<? extends JavaFileObject> d : diagnostic.getDiagnostics()) {
|
||||
if (d.getKind() == Diagnostic.Kind.ERROR) {
|
||||
res.append(d.getMessage(Locale.US));
|
||||
}
|
||||
}
|
||||
throw new EvaluateException(res.toString());
|
||||
}
|
||||
return compilerManager.compileJavaCode(options, platformClasspath, classpath, sourcePath, sources, srcDir);
|
||||
}
|
||||
catch (EvaluateException e) {
|
||||
throw e;
|
||||
catch (CompilationException e) {
|
||||
final StringBuilder res = new StringBuilder("Compilation failed:\n");
|
||||
for (CompilationException.Message m : e.getMessages()) {
|
||||
if (m.getCategory() == CompilerMessageCategory.ERROR) {
|
||||
res.append(m.getText()).append("\n");
|
||||
}
|
||||
}
|
||||
throw new EvaluateException(res.toString());
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new EvaluateException(e.getMessage());
|
||||
@@ -148,7 +117,6 @@ public class CompilingEvaluatorImpl extends CompilingEvaluator {
|
||||
FileUtil.delete(sourceFile);
|
||||
}
|
||||
}
|
||||
return outputSink.getCompiledClasses();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -170,85 +138,8 @@ public class CompilingEvaluatorImpl extends CompilingEvaluator {
|
||||
if (fileData.second == null) {
|
||||
throw new IOException("Class source code not specified");
|
||||
}
|
||||
final File file = new File(workingDir, "src/"+fileData.first);
|
||||
final File file = new File(workingDir, "debugger/src/"+fileData.first);
|
||||
FileUtil.writeToFile(file, fileData.second);
|
||||
return file;
|
||||
}
|
||||
|
||||
private static final Key<ExternalJavacManager> JAVAC_MANAGER_KEY = Key.create("_external_java_compiler_manager_");
|
||||
|
||||
@Nullable
|
||||
private ExternalJavacManager getJavacManager() throws IOException {
|
||||
// need dedicated thread access to be able to cache the manager in the user data
|
||||
DebuggerManagerThreadImpl.assertIsManagerThread();
|
||||
|
||||
final DebugProcessImpl debugProcess = myEvaluationContext.getDebugProcess();
|
||||
ExternalJavacManager manager = JAVAC_MANAGER_KEY.get(debugProcess);
|
||||
if (manager == null && debugProcess.isAttached()) {
|
||||
final File compilerWorkingDir = getCompilerWorkingDir();
|
||||
if (compilerWorkingDir == null) {
|
||||
return null; // should not happen for real projects
|
||||
}
|
||||
final int listenPort = NetUtils.findAvailableSocketPort();
|
||||
manager = new ExternalJavacManager(compilerWorkingDir);
|
||||
manager.start(listenPort);
|
||||
final ExternalJavacManager _manager = manager;
|
||||
debugProcess.addDebugProcessListener(new DebugProcessAdapter() {
|
||||
public void processDetached(DebugProcess process, boolean closedByUser) {
|
||||
if (process == debugProcess) {
|
||||
_manager.stop();
|
||||
}
|
||||
}
|
||||
});
|
||||
JAVAC_MANAGER_KEY.set(debugProcess, manager);
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private File getCompilerWorkingDir() {
|
||||
final File projectBuildDir = BuildManager.getInstance().getProjectSystemDirectory(myEvaluationContext.getProject());
|
||||
if (projectBuildDir == null) {
|
||||
return null;
|
||||
}
|
||||
final File root = new File(projectBuildDir, "debugger");
|
||||
root.mkdirs();
|
||||
return root;
|
||||
}
|
||||
|
||||
private static class DiagnosticCollector implements DiagnosticOutputConsumer {
|
||||
private final List<Diagnostic<? extends JavaFileObject>> myDiagnostics = new ArrayList<Diagnostic<? extends JavaFileObject>>();
|
||||
public void outputLineAvailable(String line) {
|
||||
// for debugging purposes uncomment this line
|
||||
//System.out.println(line);
|
||||
}
|
||||
|
||||
public void registerImports(String className, Collection<String> imports, Collection<String> staticImports) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
public void javaFileLoaded(File file) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
|
||||
myDiagnostics.add(diagnostic);
|
||||
}
|
||||
|
||||
public List<Diagnostic<? extends JavaFileObject>> getDiagnostics() {
|
||||
return myDiagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
private static class OutputCollector implements OutputFileConsumer {
|
||||
private List<OutputFileObject> myClasses = new ArrayList<OutputFileObject>();
|
||||
|
||||
public void save(@NotNull OutputFileObject fileObject) {
|
||||
myClasses.add(fileObject);
|
||||
}
|
||||
|
||||
public List<OutputFileObject> getCompiledClasses() {
|
||||
return myClasses;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.execution.impl;
|
||||
|
||||
import com.intellij.compiler.options.CompileStepBeforeRun;
|
||||
import com.intellij.execution.configurations.ModuleBasedConfiguration;
|
||||
import com.intellij.execution.configurations.RunConfiguration;
|
||||
import com.intellij.openapi.compiler.*;
|
||||
import com.intellij.openapi.components.ProjectComponent;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdk;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkType;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 08-Sep-15
|
||||
*/
|
||||
public class JavaScratchCompilationSupport implements ProjectComponent, CompileTask{
|
||||
|
||||
public JavaScratchCompilationSupport(Project project, CompilerManager compileManager) {
|
||||
compileManager.addAfterTask(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(CompileContext context) {
|
||||
final Project project = context.getProject();
|
||||
|
||||
File outputDir = null;
|
||||
File srcDir = null;
|
||||
|
||||
if (context.isRebuild()) {
|
||||
// perform cleanup
|
||||
outputDir = JavaScratchRunConfigurationExtension.getScratchOutputDirectory(project);
|
||||
if (outputDir == null) { // should not happen for normal projects
|
||||
return true;
|
||||
}
|
||||
FileUtil.delete(outputDir);
|
||||
srcDir = JavaScratchRunConfigurationExtension.getScratchTempDirectory(project);
|
||||
if (srcDir != null) {
|
||||
FileUtil.delete(srcDir);
|
||||
}
|
||||
}
|
||||
|
||||
final RunConfiguration configuration = CompileStepBeforeRun.getRunConfiguration(context);
|
||||
if (!(configuration instanceof ModuleBasedConfiguration)) {
|
||||
return true;
|
||||
}
|
||||
final String scratchUrl = JavaScratchRunConfigurationExtension.getScratchFileUrl(configuration);
|
||||
if (scratchUrl == null) {
|
||||
return true;
|
||||
}
|
||||
final Module configModule = ((ModuleBasedConfiguration)configuration).getConfigurationModule().getModule();
|
||||
if (configModule == null) {
|
||||
return true; // todo: show error?
|
||||
}
|
||||
final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(configModule);
|
||||
final Sdk targetSdk = moduleRootManager.getSdk();
|
||||
if (targetSdk == null || !(targetSdk.getSdkType() instanceof JavaSdkType)) {
|
||||
return true; // todo: show error?
|
||||
}
|
||||
if (outputDir == null) {
|
||||
outputDir = JavaScratchRunConfigurationExtension.getScratchOutputDirectory(project);
|
||||
if (outputDir == null) { // should not happen for normal projects
|
||||
return true;
|
||||
}
|
||||
}
|
||||
try {
|
||||
final File scratchFile = new File(VirtualFileManager.extractPath(scratchUrl));
|
||||
File srcFile = scratchFile;
|
||||
if (!StringUtil.endsWith(srcFile.getName(), ".java")) {
|
||||
if (srcDir == null) {
|
||||
srcDir = JavaScratchRunConfigurationExtension.getScratchTempDirectory(project);
|
||||
if (srcDir == null) { // should not happen for normal projects
|
||||
return true;
|
||||
}
|
||||
}
|
||||
srcFile = new File(srcDir, FileUtil.getNameWithoutExtension(scratchFile) + ".java");
|
||||
FileUtil.copy(scratchFile, srcFile);
|
||||
}
|
||||
|
||||
final Collection<File> files = Collections.singleton(srcFile);
|
||||
|
||||
final Set<File> cp = new LinkedHashSet<File>();
|
||||
for (String s : moduleRootManager.orderEntries().compileOnly().recursively().exportedOnly().withoutSdk().getPathsList().getPathList()) {
|
||||
cp.add(new File(s));
|
||||
}
|
||||
final List<File> platformCp = new ArrayList<File>();
|
||||
for (String s : moduleRootManager.orderEntries().compileOnly().sdkOnly().getPathsList().getPathList()) {
|
||||
platformCp.add(new File(s));
|
||||
}
|
||||
|
||||
final List<String> options = new ArrayList<String>();
|
||||
final JavaSdkVersion sdkVersion = JavaSdk.getInstance().getVersion(targetSdk);
|
||||
if (sdkVersion != null) {
|
||||
final String langLevel = "1." + Integer.valueOf(3 + sdkVersion.getMaxLanguageLevel().ordinal());
|
||||
options.add("-source");
|
||||
options.add(langLevel);
|
||||
options.add("-target");
|
||||
options.add(langLevel);
|
||||
}
|
||||
options.add("-proc:none"); // disable annotation processing
|
||||
|
||||
final Collection<ClassObject> result = CompilerManager.getInstance(project).compileJavaCode(
|
||||
options, platformCp, cp, Collections.<File>emptyList(), files, outputDir
|
||||
);
|
||||
for (ClassObject classObject : result) {
|
||||
final byte[] bytes = classObject.getContent();
|
||||
if (bytes != null) {
|
||||
FileUtil.writeToFile(new File(classObject.getPath()), bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (CompilationException e) {
|
||||
for (CompilationException.Message m : e.getMessages()) {
|
||||
context.addMessage(m.getCategory(), m.getText(), scratchUrl, m.getLine(), m.getColumn());
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), scratchUrl, -1, -1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void projectOpened() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void projectClosed() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initComponent() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disposeComponent() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getComponentName() {
|
||||
return "JavaScratchCompilationSupport";
|
||||
}
|
||||
}
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.execution.impl;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.Location;
|
||||
import com.intellij.execution.RunConfigurationExtension;
|
||||
import com.intellij.execution.application.ApplicationConfiguration;
|
||||
import com.intellij.execution.configurations.JavaParameters;
|
||||
import com.intellij.execution.configurations.RunConfiguration;
|
||||
import com.intellij.execution.configurations.RunConfigurationBase;
|
||||
import com.intellij.execution.configurations.RunnerSettings;
|
||||
import com.intellij.ide.scratch.ScratchFileType;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.compiler.CompilerManager;
|
||||
import com.intellij.openapi.options.SettingsEditor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
/*
|
||||
execution-impl -> lang-impl(scratches are here)
|
||||
compiler-impl -> lang-impl
|
||||
|
||||
java-impl ->execution-impl, compiler-impl
|
||||
*/
|
||||
public class JavaScratchRunConfigurationExtension extends RunConfigurationExtension{
|
||||
|
||||
public static final Key<String> SCRATCH_FILE_URL = Key.create("_scratch_file_path_");
|
||||
|
||||
public void cleanUserData(RunConfigurationBase configuration) {
|
||||
super.cleanUserData(configuration);
|
||||
configuration.putCopyableUserData(SCRATCH_FILE_URL, null);
|
||||
}
|
||||
|
||||
protected void extendCreatedConfiguration(@NotNull RunConfigurationBase configuration, @NotNull Location location) {
|
||||
final VirtualFile vFile = location.getVirtualFile();
|
||||
if (vFile != null && vFile.getFileType() == ScratchFileType.INSTANCE) {
|
||||
final PsiFile psiFile = location.getPsiElement().getContainingFile();
|
||||
if (psiFile != null && psiFile.getLanguage() == JavaLanguage.INSTANCE) {
|
||||
configuration.putCopyableUserData(SCRATCH_FILE_URL, vFile.getUrl());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateConfiguration(@NotNull RunConfigurationBase configuration, boolean isExecution) throws Exception {
|
||||
super.validateConfiguration(configuration, isExecution);
|
||||
}
|
||||
|
||||
public <T extends RunConfigurationBase> void updateJavaParameters(T configuration, JavaParameters params, RunnerSettings runnerSettings) throws ExecutionException {
|
||||
final File scrachesOutput = getScratchOutputDirectory(configuration.getProject());
|
||||
if (scrachesOutput != null) {
|
||||
params.getClassPath().add(scrachesOutput);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected String getSerializationId() {
|
||||
return "java-scratch-properties";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getScratchFileUrl(RunConfiguration configuration) {
|
||||
return configuration instanceof RunConfigurationBase? ((RunConfigurationBase)configuration).getCopyableUserData(SCRATCH_FILE_URL) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static File getScratchOutputDirectory(Project project) {
|
||||
final File root = CompilerManager.getInstance(project).getJavacCompilerWorkingDir();
|
||||
return root != null? new File(root, "scratches/out") : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static File getScratchTempDirectory(Project project) {
|
||||
final File root = CompilerManager.getInstance(project).getJavacCompilerWorkingDir();
|
||||
return root != null? new File(root, "scratches/src") : null;
|
||||
}
|
||||
|
||||
|
||||
protected void readExternal(@NotNull RunConfigurationBase runConfiguration, @NotNull Element element) throws InvalidDataException {
|
||||
final Element sourceElement = element.getChild("source");
|
||||
if (sourceElement != null) {
|
||||
final String scratchUrl = sourceElement.getAttributeValue("url");
|
||||
if (scratchUrl != null) {
|
||||
runConfiguration.putCopyableUserData(SCRATCH_FILE_URL, scratchUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeExternal(@NotNull RunConfigurationBase runConfiguration, @NotNull Element element) throws WriteExternalException {
|
||||
final String url = getScratchFileUrl(runConfiguration);
|
||||
if (url == null) {
|
||||
super.writeExternal(runConfiguration, element);
|
||||
}
|
||||
else {
|
||||
final Element urlElement = new Element("source");
|
||||
urlElement.setAttribute("url", url);
|
||||
element.addContent(urlElement);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected <P extends RunConfigurationBase> SettingsEditor<P> createEditor(@NotNull P configuration) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected String getEditorTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean isApplicableFor(@NotNull RunConfigurationBase configuration) {
|
||||
return configuration instanceof ApplicationConfiguration;
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,10 @@
|
||||
<component>
|
||||
<implementation-class>com.intellij.execution.testDiscovery.TestDiscoveryIndex</implementation-class>
|
||||
</component>
|
||||
|
||||
<component>
|
||||
<implementation-class>com.intellij.execution.impl.JavaScratchCompilationSupport</implementation-class>
|
||||
</component>
|
||||
</project-components>
|
||||
|
||||
<extensionPoints>
|
||||
@@ -1616,6 +1620,7 @@
|
||||
|
||||
<applicationService serviceImplementation="com.intellij.execution.JavaRunConfigurationExtensionManager"/>
|
||||
<runConfigurationExtension implementation="com.intellij.execution.testDiscovery.TestDiscoveryExtension"/>
|
||||
<runConfigurationExtension implementation="com.intellij.execution.impl.JavaScratchRunConfigurationExtension"/>
|
||||
|
||||
<regExpLanguageHost forClass="com.intellij.psi.impl.source.tree.java.PsiLiteralExpressionImpl"
|
||||
implementationClass="com.intellij.psi.impl.JavaRegExpHost"/>
|
||||
|
||||
Reference in New Issue
Block a user