mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -691,6 +691,26 @@ private String submapToXml(Map properties, List keys) {
|
||||
return buff.toString()
|
||||
}
|
||||
|
||||
private List<File> getChildren(File file) {
|
||||
if (!file.isDirectory()) return []
|
||||
return file.listFiles().sort { File f -> f.name.toLowerCase() }
|
||||
}
|
||||
|
||||
binding.setVariable("getCustomJDK", { File customJdkDir ->
|
||||
getChildren(customJdkDir).each {
|
||||
if (it.getName().endsWith(".tar.gz")) {
|
||||
def customJdkFileName = it.getAbsolutePath().substring(0, it.getAbsolutePath().length() - 3)
|
||||
if (new File(customJdkFileName).exists()){ ant.delete(file: customJdkFileName) }
|
||||
if (new File("${home}/build/jdk/custom_jdk_${buildNumber}.tar").exists()){
|
||||
ant.delete(file: "${home}/build/jdk/custom_jdk_${buildNumber}.tar")
|
||||
}
|
||||
ant.gunzip(src: it.getAbsolutePath())
|
||||
projectBuilder.info("customJdkFileName: " + customJdkFileName)
|
||||
ant.copy(file: customJdkFileName, tofile: "${home}/build/jdk/custom_jdk_${buildNumber}.tar")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
binding.setVariable("buildWinZip", { String zipPath, List paths ->
|
||||
projectBuilder.stage(".win.zip")
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
import org.jetbrains.jps.api.CmdlineProtoUtil;
|
||||
import org.jetbrains.jps.api.CmdlineRemoteProto;
|
||||
import org.jetbrains.jps.api.RequestFuture;
|
||||
import org.jetbrains.jps.api.TaskFuture;
|
||||
import org.jetbrains.jps.model.java.JavaSourceRootType;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -138,7 +138,7 @@ public class CompileDriver {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final RequestFuture future = compileInExternalProcess(compileContext, true);
|
||||
final TaskFuture future = compileInExternalProcess(compileContext, true);
|
||||
if (future != null) {
|
||||
while (!future.waitFor(200L, TimeUnit.MILLISECONDS)) {
|
||||
if (indicator.isCanceled()) {
|
||||
@@ -194,7 +194,7 @@ public class CompileDriver {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private RequestFuture compileInExternalProcess(final @NotNull CompileContextImpl compileContext, final boolean onlyCheckUpToDate)
|
||||
private TaskFuture compileInExternalProcess(final @NotNull CompileContextImpl compileContext, final boolean onlyCheckUpToDate)
|
||||
throws Exception {
|
||||
final CompileScope scope = compileContext.getCompileScope();
|
||||
final Collection<String> paths = CompileScopeUtil.fetchFiles(compileContext);
|
||||
@@ -400,7 +400,7 @@ public class CompileDriver {
|
||||
return;
|
||||
}
|
||||
|
||||
final RequestFuture future = compileInExternalProcess(compileContext, false);
|
||||
final TaskFuture future = compileInExternalProcess(compileContext, false);
|
||||
if (future != null) {
|
||||
while (!future.waitFor(200L, TimeUnit.MILLISECONDS)) {
|
||||
if (indicator.isCanceled()) {
|
||||
@@ -646,7 +646,6 @@ public class CompileDriver {
|
||||
final Module[] scopeModules = scope.getAffectedModules();
|
||||
final List<String> modulesWithoutOutputPathSpecified = new ArrayList<String>();
|
||||
final List<String> modulesWithoutJdkAssigned = new ArrayList<String>();
|
||||
final CompilerConfiguration config = CompilerConfiguration.getInstance(myProject);
|
||||
final CompilerManager compilerManager = CompilerManager.getInstance(myProject);
|
||||
for (final Module module : scopeModules) {
|
||||
if (!compilerManager.isValidationEnabled(module)) {
|
||||
|
||||
@@ -58,10 +58,7 @@ import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.ShutDownTracker;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -112,8 +109,7 @@ import java.net.InetSocketAddress;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope;
|
||||
@@ -152,8 +148,10 @@ public class BuildManager implements ApplicationComponent{
|
||||
private final File mySystemDirectory;
|
||||
private final ProjectManager myProjectManager;
|
||||
|
||||
private final Map<RequestFuture, Project> myAutomakeFutures = Collections.synchronizedMap(new HashMap<RequestFuture, Project>());
|
||||
private final Map<TaskFuture, Project> myAutomakeFutures = Collections.synchronizedMap(new HashMap<TaskFuture, Project>());
|
||||
private final Map<String, RequestFuture> myBuildsInProgress = Collections.synchronizedMap(new HashMap<String, RequestFuture>());
|
||||
private final Map<String, Future<Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler>>> myPreloadedBuilds =
|
||||
Collections.synchronizedMap(new HashMap<String, Future<Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler>>>());
|
||||
private final BuildProcessClasspathManager myClasspathManager = new BuildProcessClasspathManager();
|
||||
private final SequentialTaskExecutor myRequestsProcessor = new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE);
|
||||
private final Map<String, ProjectData> myProjectDataMap = Collections.synchronizedMap(new HashMap<String, ProjectData>());
|
||||
@@ -385,6 +383,8 @@ public class BuildManager implements ApplicationComponent{
|
||||
}
|
||||
|
||||
public void clearState(Project project) {
|
||||
cancelPreloadedBuilds(project);
|
||||
|
||||
final String projectPath = getProjectPath(project);
|
||||
synchronized (myProjectDataMap) {
|
||||
final ProjectData data = myProjectDataMap.get(projectPath);
|
||||
@@ -447,7 +447,7 @@ public class BuildManager implements ApplicationComponent{
|
||||
}
|
||||
final List<TargetTypeBuildScope> scopes = CmdlineProtoUtil.createAllModulesScopes(false);
|
||||
final AutoMakeMessageHandler handler = new AutoMakeMessageHandler(project);
|
||||
final RequestFuture future = scheduleBuild(
|
||||
final TaskFuture future = scheduleBuild(
|
||||
project, false, true, false, scopes, Collections.<String>emptyList(), Collections.<String, String>emptyMap(), handler
|
||||
);
|
||||
if (future != null) {
|
||||
@@ -526,12 +526,12 @@ public class BuildManager implements ApplicationComponent{
|
||||
return false;
|
||||
}
|
||||
|
||||
public Collection<RequestFuture> cancelAutoMakeTasks(Project project) {
|
||||
final Collection<RequestFuture> futures = new SmartList<RequestFuture>();
|
||||
public Collection<TaskFuture> cancelAutoMakeTasks(Project project) {
|
||||
final Collection<TaskFuture> futures = new SmartList<TaskFuture>();
|
||||
synchronized (myAutomakeFutures) {
|
||||
for (Map.Entry<RequestFuture, Project> entry : myAutomakeFutures.entrySet()) {
|
||||
for (Map.Entry<TaskFuture, Project> entry : myAutomakeFutures.entrySet()) {
|
||||
if (entry.getValue().equals(project)) {
|
||||
final RequestFuture future = entry.getKey();
|
||||
final TaskFuture future = entry.getKey();
|
||||
future.cancel(false);
|
||||
futures.add(future);
|
||||
}
|
||||
@@ -540,211 +540,261 @@ public class BuildManager implements ApplicationComponent{
|
||||
return futures;
|
||||
}
|
||||
|
||||
private void cancelPreloadedBuilds(Project project) {
|
||||
final String projectPath = getProjectPath(project);
|
||||
runCommand(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler> pair = takePreloadedProcess(projectPath);
|
||||
if (pair != null) {
|
||||
final RequestFuture<PreloadedProcessMessageHandler> future = pair.first;
|
||||
myMessageDispatcher.cancelSession(future.getRequestID());
|
||||
// waiting for preloaded process from project's task queue guarantees no build is started for this project
|
||||
// until this one gracefully exits and closes all its storages
|
||||
getProjectData(projectPath).taskQueue.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
future.waitFor();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RequestFuture scheduleBuild(
|
||||
private Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler> takePreloadedProcess(String projectPath) {
|
||||
Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler> result;
|
||||
final Future<Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler>> preloadProgress = myPreloadedBuilds.remove(projectPath);
|
||||
try {
|
||||
result = preloadProgress != null ? preloadProgress.get() : null;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.info(e);
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TaskFuture scheduleBuild(
|
||||
final Project project, final boolean isRebuild, final boolean isMake,
|
||||
final boolean onlyCheckUpToDate, final List<TargetTypeBuildScope> scopes,
|
||||
final Collection<String> paths,
|
||||
final Map<String, String> userData, final DefaultMessageHandler messageHandler) {
|
||||
|
||||
final String projectPath = getProjectPath(project);
|
||||
final UUID sessionId = UUID.randomUUID();
|
||||
final boolean isAutomake = messageHandler instanceof AutoMakeMessageHandler;
|
||||
final BuilderMessageHandler handler = new MessageHandlerWrapper(messageHandler) {
|
||||
@Override
|
||||
public void buildStarted(UUID sessionId) {
|
||||
super.buildStarted(sessionId);
|
||||
try {
|
||||
ApplicationManager.getApplication().getMessageBus().syncPublisher(BuildManagerListener.TOPIC).buildStarted(project, sessionId, isAutomake);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionTerminated(UUID sessionId) {
|
||||
try {
|
||||
super.sessionTerminated(sessionId);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
ApplicationManager.getApplication().getMessageBus().syncPublisher(BuildManagerListener.TOPIC).buildFinished(project, sessionId, isAutomake);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
// ensure server is listening
|
||||
if (myListenPort < 0) {
|
||||
try {
|
||||
synchronized (this) {
|
||||
if (myListenPort < 0) {
|
||||
myListenPort = startListening();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), null));
|
||||
handler.sessionTerminated(sessionId);
|
||||
return null;
|
||||
}
|
||||
final BuilderMessageHandler handler = new NotifyingMessageHandler(project, messageHandler, messageHandler instanceof AutoMakeMessageHandler);
|
||||
try {
|
||||
ensureListening();
|
||||
}
|
||||
catch (Exception e) {
|
||||
final UUID sessionId = UUID.randomUUID(); // the actual session did not start, use random UUID
|
||||
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), null));
|
||||
handler.sessionTerminated(sessionId);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
final RequestFuture<BuilderMessageHandler> future = new RequestFuture<BuilderMessageHandler>(handler, sessionId, new RequestFuture.CancelAction<BuilderMessageHandler>() {
|
||||
@Override
|
||||
public void cancel(RequestFuture<BuilderMessageHandler> future) throws Exception {
|
||||
myMessageDispatcher.cancelSession(future.getRequestID());
|
||||
final DelegateFuture<BuilderMessageHandler> _future = new DelegateFuture<BuilderMessageHandler>();
|
||||
// by using the same queue that processes events we ensure that
|
||||
// the build will be aware of all events that have happened before this request
|
||||
runCommand(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
final Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler> preloaded = takePreloadedProcess(projectPath);
|
||||
final RequestFuture<PreloadedProcessMessageHandler> preloadedFuture = preloaded != null? preloaded.first : null;
|
||||
final boolean usingPreloadedProcess = preloadedFuture != null;
|
||||
|
||||
final UUID sessionId;
|
||||
if (usingPreloadedProcess) {
|
||||
LOG.info("Using preloaded build process to compile " + projectPath);
|
||||
sessionId = preloadedFuture.getRequestID();
|
||||
preloadedFuture.getMessageHandler().setDelegateHandler(handler);
|
||||
}
|
||||
else {
|
||||
sessionId = UUID.randomUUID();
|
||||
}
|
||||
});
|
||||
// by using the same queue that processes events we ensure that
|
||||
// the build will be aware of all events that have happened before this request
|
||||
runCommand(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (future.isCancelled() || project.isDisposed()) {
|
||||
handler.sessionTerminated(sessionId);
|
||||
future.setDone();
|
||||
return;
|
||||
}
|
||||
|
||||
final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals =
|
||||
CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.newBuilder()
|
||||
.setGlobalOptionsPath(PathManager.getOptionsPath())
|
||||
.build();
|
||||
CmdlineRemoteProto.Message.ControllerMessage.FSEvent currentFSChanges;
|
||||
final SequentialTaskExecutor projectTaskQueue;
|
||||
synchronized (myProjectDataMap) {
|
||||
ProjectData data = myProjectDataMap.get(projectPath);
|
||||
if (data == null) {
|
||||
data = new ProjectData(new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE));
|
||||
myProjectDataMap.put(projectPath, data);
|
||||
}
|
||||
if (isRebuild) {
|
||||
data.dropChanges();
|
||||
}
|
||||
if (IS_UNIT_TEST_MODE) {
|
||||
LOG.info("Scheduling build for " +
|
||||
projectPath +
|
||||
"; CHANGED: " +
|
||||
new HashSet<String>(convertToStringPaths(data.myChanged)) +
|
||||
"; DELETED: " +
|
||||
new HashSet<String>(convertToStringPaths(data.myDeleted)));
|
||||
}
|
||||
currentFSChanges = data.getAndResetRescanFlag() ? null : data.createNextEvent();
|
||||
projectTaskQueue = data.taskQueue;
|
||||
final RequestFuture<? extends BuilderMessageHandler> future = usingPreloadedProcess? preloadedFuture : new RequestFuture<BuilderMessageHandler>(handler, sessionId, new RequestFuture.CancelAction<BuilderMessageHandler>() {
|
||||
@Override
|
||||
public void cancel(RequestFuture<BuilderMessageHandler> future) throws Exception {
|
||||
myMessageDispatcher.cancelSession(future.getRequestID());
|
||||
}
|
||||
});
|
||||
_future.setDelegate(future);
|
||||
|
||||
final CmdlineRemoteProto.Message.ControllerMessage params;
|
||||
if (!usingPreloadedProcess && (future.isCancelled() || project.isDisposed())) {
|
||||
// in case of preloaded process the process was already running, so the handler will be notified upon process termination
|
||||
handler.sessionTerminated(sessionId);
|
||||
((BasicFuture)future).setDone();
|
||||
return;
|
||||
}
|
||||
|
||||
final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals =
|
||||
CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.newBuilder().setGlobalOptionsPath(PathManager.getOptionsPath()).build();
|
||||
CmdlineRemoteProto.Message.ControllerMessage.FSEvent currentFSChanges;
|
||||
final SequentialTaskExecutor projectTaskQueue;
|
||||
synchronized (myProjectDataMap) {
|
||||
final ProjectData data = getProjectData(projectPath);
|
||||
if (isRebuild) {
|
||||
params = CmdlineProtoUtil.createBuildRequest(projectPath, scopes, Collections.<String>emptyList(), userData, globals, null);
|
||||
data.dropChanges();
|
||||
}
|
||||
else if (onlyCheckUpToDate) {
|
||||
params = CmdlineProtoUtil.createUpToDateCheckRequest(projectPath, scopes, paths, userData, globals, currentFSChanges);
|
||||
}
|
||||
else {
|
||||
params = CmdlineProtoUtil.createBuildRequest(projectPath, scopes, isMake ? Collections.<String>emptyList() : paths,
|
||||
userData, globals, currentFSChanges);
|
||||
if (IS_UNIT_TEST_MODE) {
|
||||
LOG.info("Scheduling build for " +
|
||||
projectPath +
|
||||
"; CHANGED: " +
|
||||
new HashSet<String>(convertToStringPaths(data.myChanged)) +
|
||||
"; DELETED: " +
|
||||
new HashSet<String>(convertToStringPaths(data.myDeleted)));
|
||||
}
|
||||
currentFSChanges = data.getAndResetRescanFlag() ? null : data.createNextEvent();
|
||||
projectTaskQueue = data.taskQueue;
|
||||
}
|
||||
|
||||
myMessageDispatcher.registerBuildMessageHandler(sessionId, new MessageHandlerWrapper(handler) {
|
||||
final CmdlineRemoteProto.Message.ControllerMessage params;
|
||||
if (isRebuild) {
|
||||
params = CmdlineProtoUtil.createBuildRequest(projectPath, scopes, Collections.<String>emptyList(), userData, globals, null);
|
||||
}
|
||||
else if (onlyCheckUpToDate) {
|
||||
params = CmdlineProtoUtil.createUpToDateCheckRequest(projectPath, scopes, paths, userData, globals, currentFSChanges);
|
||||
}
|
||||
else {
|
||||
params = CmdlineProtoUtil.createBuildRequest(projectPath, scopes, isMake ? Collections.<String>emptyList() : paths, userData, globals, currentFSChanges);
|
||||
}
|
||||
if (!usingPreloadedProcess) {
|
||||
myMessageDispatcher.registerBuildMessageHandler(future, params);
|
||||
}
|
||||
|
||||
try {
|
||||
projectTaskQueue.submit(new Runnable() {
|
||||
@Override
|
||||
public void sessionTerminated(UUID sessionId) {
|
||||
public void run() {
|
||||
Throwable execFailure = null;
|
||||
try {
|
||||
super.sessionTerminated(sessionId);
|
||||
}
|
||||
finally {
|
||||
future.setDone();
|
||||
}
|
||||
}
|
||||
}, params);
|
||||
|
||||
try {
|
||||
projectTaskQueue.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Throwable execFailure = null;
|
||||
try {
|
||||
if (project.isDisposed()) {
|
||||
if (project.isDisposed()) {
|
||||
if (usingPreloadedProcess) {
|
||||
future.cancel(true);
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
myBuildsInProgress.put(projectPath, future);
|
||||
final OSProcessHandler processHandler = launchBuildProcess(project, myListenPort, sessionId);
|
||||
final StringBuilder stdErrOutput = new StringBuilder();
|
||||
}
|
||||
myBuildsInProgress.put(projectPath, future);
|
||||
final OSProcessHandler processHandler;
|
||||
final StringBuilder errorsOnLaunch = new StringBuilder();
|
||||
if (usingPreloadedProcess) {
|
||||
final boolean paramsSent = myMessageDispatcher.sendBuildParameters(future.getRequestID(), params);
|
||||
if (!paramsSent) {
|
||||
myMessageDispatcher.cancelSession(future.getRequestID());
|
||||
}
|
||||
processHandler = preloaded.second;
|
||||
}
|
||||
else {
|
||||
processHandler = launchBuildProcess(project, myListenPort, sessionId, false);
|
||||
processHandler.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void onTextAvailable(ProcessEvent event, Key outputType) {
|
||||
// re-translate builder's output to idea.log
|
||||
final String text = event.getText();
|
||||
if (!StringUtil.isEmptyOrSpaces(text)) {
|
||||
LOG.info("BUILDER_PROCESS [" + outputType.toString() + "]: " + text.trim());
|
||||
if (stdErrOutput.length() < 1024 && ProcessOutputTypes.STDERR.equals(outputType)) {
|
||||
stdErrOutput.append(text);
|
||||
if (ProcessOutputTypes.STDERR.equals(outputType)) {
|
||||
if (errorsOnLaunch.length() < 1024) {
|
||||
final String text = event.getText();
|
||||
if (!StringUtil.isEmptyOrSpaces(text)) {
|
||||
errorsOnLaunch.append(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
processHandler.startNotify();
|
||||
final boolean terminated = processHandler.waitFor();
|
||||
if (terminated) {
|
||||
final int exitValue = processHandler.getProcess().exitValue();
|
||||
if (exitValue != 0) {
|
||||
final StringBuilder msg = new StringBuilder();
|
||||
msg.append("Abnormal build process termination: ");
|
||||
if (stdErrOutput.length() > 0) {
|
||||
msg.append("\n").append(stdErrOutput);
|
||||
}
|
||||
else {
|
||||
msg.append("unknown error");
|
||||
}
|
||||
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(msg.toString(), null));
|
||||
}
|
||||
|
||||
final boolean terminated = processHandler.waitFor();
|
||||
if (terminated) {
|
||||
final int exitValue = processHandler.getProcess().exitValue();
|
||||
if (exitValue != 0) {
|
||||
final StringBuilder msg = new StringBuilder();
|
||||
msg.append("Abnormal build process termination: ");
|
||||
if (errorsOnLaunch.length() > 0) {
|
||||
msg.append("\n").append(errorsOnLaunch);
|
||||
}
|
||||
}
|
||||
else {
|
||||
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure("Disconnected from build process", null));
|
||||
else {
|
||||
msg.append("unknown error");
|
||||
}
|
||||
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(msg.toString(), null));
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
execFailure = e;
|
||||
}
|
||||
finally {
|
||||
myBuildsInProgress.remove(projectPath);
|
||||
if (myMessageDispatcher.getAssociatedChannel(sessionId) == null) {
|
||||
// either the connection has never been established (process not started or execution failed), or no messages were sent from the launched process.
|
||||
// in this case the session cannot be unregistered by the message dispatcher
|
||||
final BuilderMessageHandler unregistered = myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
|
||||
if (unregistered != null) {
|
||||
if (execFailure != null) {
|
||||
unregistered.handleFailure(sessionId, CmdlineProtoUtil.createFailure(execFailure.getMessage(), execFailure));
|
||||
}
|
||||
unregistered.sessionTerminated(sessionId);
|
||||
}
|
||||
}
|
||||
else {
|
||||
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure("Disconnected from build process", null));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Throwable e) {
|
||||
final BuilderMessageHandler unregistered = myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
|
||||
if (unregistered != null) {
|
||||
unregistered.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), e));
|
||||
unregistered.sessionTerminated(sessionId);
|
||||
catch (Throwable e) {
|
||||
execFailure = e;
|
||||
}
|
||||
finally {
|
||||
myBuildsInProgress.remove(projectPath);
|
||||
if (myMessageDispatcher.getAssociatedChannel(sessionId) == null) {
|
||||
// either the connection has never been established (process not started or execution failed), or no messages were sent from the launched process.
|
||||
// in this case the session cannot be unregistered by the message dispatcher
|
||||
final BuilderMessageHandler unregistered = myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
|
||||
if (unregistered != null) {
|
||||
if (execFailure != null) {
|
||||
unregistered.handleFailure(sessionId, CmdlineProtoUtil.createFailure(execFailure.getMessage(), execFailure));
|
||||
}
|
||||
unregistered.sessionTerminated(sessionId);
|
||||
}
|
||||
}
|
||||
|
||||
if (Registry.is("compiler.process.preload") && !project.isDisposed()) {
|
||||
runCommand(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
final Future<Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler>> preloadResult = launchPreloadedBuildProcess(project, projectTaskQueue);
|
||||
myPreloadedBuilds.put(projectPath, preloadResult);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.info("Error pre-loading build process for project " + projectPath, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Throwable e) {
|
||||
final BuilderMessageHandler unregistered = myMessageDispatcher.unregisterBuildMessageHandler(sessionId);
|
||||
if (unregistered != null) {
|
||||
unregistered.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), e));
|
||||
unregistered.sessionTerminated(sessionId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return future;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), e));
|
||||
handler.sessionTerminated(sessionId);
|
||||
}
|
||||
return _future;
|
||||
}
|
||||
|
||||
return null;
|
||||
@NotNull
|
||||
private ProjectData getProjectData(String projectPath) {
|
||||
synchronized (myProjectDataMap) {
|
||||
ProjectData data = myProjectDataMap.get(projectPath);
|
||||
if (data == null) {
|
||||
data = new ProjectData(new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE));
|
||||
myProjectDataMap.put(projectPath, data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureListening() throws Exception {
|
||||
if (myListenPort < 0) {
|
||||
synchronized (this) {
|
||||
if (myListenPort < 0) {
|
||||
myListenPort = startListening();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -762,7 +812,45 @@ public class BuildManager implements ApplicationComponent{
|
||||
return "com.intellij.compiler.server.BuildManager";
|
||||
}
|
||||
|
||||
private OSProcessHandler launchBuildProcess(Project project, final int port, final UUID sessionId) throws ExecutionException {
|
||||
private Future<Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler>> launchPreloadedBuildProcess(final Project project, SequentialTaskExecutor projectTaskQueue) throws Exception {
|
||||
ensureListening();
|
||||
|
||||
// launching build process from projectTaskQueue ensures that no other build process for this project is currently running
|
||||
return projectTaskQueue.submit(new Callable<Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler>>() {
|
||||
public Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler> call() throws Exception {
|
||||
final RequestFuture<PreloadedProcessMessageHandler> future = new RequestFuture<PreloadedProcessMessageHandler>(new PreloadedProcessMessageHandler(project), UUID.randomUUID(), new RequestFuture.CancelAction<PreloadedProcessMessageHandler>() {
|
||||
@Override
|
||||
public void cancel(RequestFuture<PreloadedProcessMessageHandler> future) throws Exception {
|
||||
myMessageDispatcher.cancelSession(future.getRequestID());
|
||||
}
|
||||
});
|
||||
try {
|
||||
myMessageDispatcher.registerBuildMessageHandler(future, null);
|
||||
final OSProcessHandler processHandler = launchBuildProcess(project, myListenPort, future.getRequestID(), true);
|
||||
processHandler.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void onTextAvailable(ProcessEvent event, Key outputType) {
|
||||
if (ProcessOutputTypes.STDERR.equals(outputType)) {
|
||||
final String text = event.getText();
|
||||
if (!StringUtil.isEmptyOrSpaces(text)) {
|
||||
LOG.info("PRELOADED_BUILD_PROCESS: " + text);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
processHandler.startNotify();
|
||||
return Pair.create(future, processHandler);
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
myMessageDispatcher.unregisterBuildMessageHandler(future.getRequestID());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private OSProcessHandler launchBuildProcess(Project project, final int port, final UUID sessionId, boolean requestProjectPreload) throws ExecutionException {
|
||||
final String compilerPath;
|
||||
final String vmExecutablePath;
|
||||
JavaSdkVersion sdkVersion = null;
|
||||
@@ -863,6 +951,11 @@ public class BuildManager implements ApplicationComponent{
|
||||
}
|
||||
cmdLine.addParameter("-Djdt.compiler.useSingleThread=true"); // always run eclipse compiler in single-threaded mode
|
||||
|
||||
if (requestProjectPreload) {
|
||||
cmdLine.addParameter("-Dpreload.project.path=" + FileUtil.toCanonicalPath(getProjectPath(project)));
|
||||
cmdLine.addParameter("-Dpreload.config.path=" + FileUtil.toCanonicalPath(PathManager.getOptionsPath()));
|
||||
}
|
||||
|
||||
final String shouldGenerateIndex = System.getProperty(GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION);
|
||||
if (shouldGenerateIndex != null) {
|
||||
cmdLine.addParameter("-D"+ GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION +"=" + shouldGenerateIndex);
|
||||
@@ -961,12 +1054,24 @@ public class BuildManager implements ApplicationComponent{
|
||||
|
||||
final Process process = cmdLine.createProcess();
|
||||
|
||||
return new OSProcessHandler(process, null, mySystemCharset) {
|
||||
final OSProcessHandler processHandler = new OSProcessHandler(process, null, mySystemCharset) {
|
||||
@Override
|
||||
protected boolean shouldDestroyProcessRecursively() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
processHandler.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void onTextAvailable(ProcessEvent event, Key outputType) {
|
||||
// re-translate builder's output to idea.log
|
||||
final String text = event.getText();
|
||||
if (!StringUtil.isEmptyOrSpaces(text)) {
|
||||
LOG.info("BUILDER_PROCESS [" + outputType.toString() + "]: " + text.trim());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return processHandler;
|
||||
}
|
||||
|
||||
public File getBuildSystemDirectory() {
|
||||
@@ -1086,6 +1191,50 @@ public class BuildManager implements ApplicationComponent{
|
||||
}
|
||||
}
|
||||
|
||||
private static class NotifyingMessageHandler extends DelegatingMessageHandler {
|
||||
private final Project myProject;
|
||||
private final BuilderMessageHandler myDelegateHandler;
|
||||
private boolean myIsAutomake;
|
||||
|
||||
public NotifyingMessageHandler(@NotNull Project project, @NotNull BuilderMessageHandler delegateHandler, final boolean isAutomake) {
|
||||
myProject = project;
|
||||
myDelegateHandler = delegateHandler;
|
||||
myIsAutomake = isAutomake;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BuilderMessageHandler getDelegateHandler() {
|
||||
return myDelegateHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildStarted(UUID sessionId) {
|
||||
super.buildStarted(sessionId);
|
||||
try {
|
||||
ApplicationManager
|
||||
.getApplication().getMessageBus().syncPublisher(BuildManagerListener.TOPIC).buildStarted(myProject, sessionId, myIsAutomake);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionTerminated(UUID sessionId) {
|
||||
try {
|
||||
super.sessionTerminated(sessionId);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
ApplicationManager.getApplication().getMessageBus().syncPublisher(BuildManagerListener.TOPIC).buildFinished(myProject, sessionId, myIsAutomake);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ProjectWatcher extends ProjectManagerAdapter {
|
||||
private final Map<Project, MessageBusConnection> myConnections = new HashMap<Project, MessageBusConnection>();
|
||||
|
||||
@@ -1169,7 +1318,8 @@ public class BuildManager implements ApplicationComponent{
|
||||
|
||||
@Override
|
||||
public void projectClosing(Project project) {
|
||||
for (RequestFuture future : cancelAutoMakeTasks(project)) {
|
||||
cancelPreloadedBuilds(project);
|
||||
for (TaskFuture future : cancelAutoMakeTasks(project)) {
|
||||
future.waitFor(500, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
@@ -1185,13 +1335,14 @@ public class BuildManager implements ApplicationComponent{
|
||||
}
|
||||
|
||||
private static class ProjectData {
|
||||
@NotNull
|
||||
final SequentialTaskExecutor taskQueue;
|
||||
private final Set<InternedPath> myChanged = new THashSet<InternedPath>();
|
||||
private final Set<InternedPath> myDeleted = new THashSet<InternedPath>();
|
||||
private long myNextEventOrdinal = 0L;
|
||||
private boolean myNeedRescan = true;
|
||||
|
||||
private ProjectData(SequentialTaskExecutor taskQueue) {
|
||||
private ProjectData(@NotNull SequentialTaskExecutor taskQueue) {
|
||||
this.taskQueue = taskQueue;
|
||||
}
|
||||
|
||||
@@ -1328,5 +1479,88 @@ public class BuildManager implements ApplicationComponent{
|
||||
return "/";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final class DelegateFuture<T> implements TaskFuture<T> {
|
||||
@Nullable
|
||||
private TaskFuture<? extends T> myDelegate;
|
||||
private Boolean myRequestedCancelState = null;
|
||||
|
||||
@NotNull
|
||||
public synchronized TaskFuture<? extends T> getDelegate() {
|
||||
TaskFuture<? extends T> delegate = myDelegate;
|
||||
while (delegate == null) {
|
||||
try {
|
||||
wait();
|
||||
}
|
||||
catch (InterruptedException ignored) {
|
||||
}
|
||||
delegate = myDelegate;
|
||||
}
|
||||
return delegate;
|
||||
}
|
||||
|
||||
public synchronized boolean setDelegate(@NotNull TaskFuture<? extends T> delegate) {
|
||||
if (myDelegate == null) {
|
||||
try {
|
||||
myDelegate = delegate;
|
||||
if (myRequestedCancelState != null) {
|
||||
myDelegate.cancel(myRequestedCancelState);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
notifyAll();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public synchronized boolean cancel(boolean mayInterruptIfRunning) {
|
||||
final TaskFuture<? extends T> delegate = myDelegate;
|
||||
if (delegate == null) {
|
||||
myRequestedCancelState = mayInterruptIfRunning;
|
||||
return true;
|
||||
}
|
||||
return delegate.cancel(mayInterruptIfRunning);
|
||||
}
|
||||
|
||||
public void waitFor() {
|
||||
getDelegate().waitFor();
|
||||
}
|
||||
|
||||
public boolean waitFor(long timeout, TimeUnit unit) {
|
||||
return getDelegate().waitFor(timeout, unit);
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
final TaskFuture<? extends T> delegate;
|
||||
synchronized (this) {
|
||||
delegate = myDelegate;
|
||||
if (delegate == null) {
|
||||
return myRequestedCancelState != null;
|
||||
}
|
||||
}
|
||||
return delegate.isCancelled();
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
final TaskFuture<? extends T> delegate;
|
||||
synchronized (this) {
|
||||
delegate = myDelegate;
|
||||
if (delegate == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return delegate.isDone();
|
||||
}
|
||||
|
||||
public T get() throws InterruptedException, java.util.concurrent.ExecutionException {
|
||||
return getDelegate().get();
|
||||
}
|
||||
|
||||
public T get(long timeout, TimeUnit unit) throws InterruptedException, java.util.concurrent.ExecutionException, TimeoutException {
|
||||
return getDelegate().get(timeout, unit);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,10 +21,12 @@ import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.util.AttributeKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.io.SimpleChannelInboundHandlerAdapter;
|
||||
import org.jetbrains.jps.api.CmdlineProtoUtil;
|
||||
import org.jetbrains.jps.api.CmdlineRemoteProto;
|
||||
import org.jetbrains.jps.api.RequestFuture;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -41,19 +43,34 @@ class BuildMessageDispatcher extends SimpleChannelInboundHandlerAdapter<CmdlineR
|
||||
|
||||
private static final AttributeKey<SessionData> SESSION_DATA = AttributeKey.valueOf("BuildMessageDispatcher.sessionData");
|
||||
|
||||
private final Map<UUID, SessionData> myMessageHandlers = new ConcurrentHashMap<UUID, SessionData>(16, 0.75f, 1);
|
||||
private final Map<UUID, SessionData> mySessionDescriptors = new ConcurrentHashMap<UUID, SessionData>(16, 0.75f, 1);
|
||||
private final Set<UUID> myCanceledSessions = new ConcurrentHashSet<UUID>();
|
||||
|
||||
public void registerBuildMessageHandler(UUID sessionId,
|
||||
BuilderMessageHandler handler,
|
||||
CmdlineRemoteProto.Message.ControllerMessage params) {
|
||||
myMessageHandlers.put(sessionId, new SessionData(sessionId, handler, params));
|
||||
public void registerBuildMessageHandler(@NotNull final RequestFuture<? extends BuilderMessageHandler> future, @Nullable CmdlineRemoteProto.Message.ControllerMessage params) {
|
||||
final BuilderMessageHandler wrappedHandler = new DelegatingMessageHandler() {
|
||||
@Override
|
||||
protected BuilderMessageHandler getDelegateHandler() {
|
||||
return future.getMessageHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionTerminated(UUID sessionId) {
|
||||
try {
|
||||
super.sessionTerminated(sessionId);
|
||||
}
|
||||
finally {
|
||||
future.setDone();
|
||||
}
|
||||
}
|
||||
};
|
||||
final UUID sessionId = future.getRequestID();
|
||||
mySessionDescriptors.put(sessionId, new SessionData(sessionId, wrappedHandler, params));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BuilderMessageHandler unregisterBuildMessageHandler(UUID sessionId) {
|
||||
myCanceledSessions.remove(sessionId);
|
||||
final SessionData data = myMessageHandlers.remove(sessionId);
|
||||
final SessionData data = mySessionDescriptors.remove(sessionId);
|
||||
return data != null? data.handler : null;
|
||||
}
|
||||
|
||||
@@ -74,11 +91,36 @@ class BuildMessageDispatcher extends SimpleChannelInboundHandlerAdapter<CmdlineR
|
||||
|
||||
@Nullable
|
||||
public Channel getAssociatedChannel(final UUID sessionId) {
|
||||
final SessionData data = myMessageHandlers.get(sessionId);
|
||||
final SessionData data = mySessionDescriptors.get(sessionId);
|
||||
return data != null? data.channel : null;
|
||||
}
|
||||
|
||||
|
||||
public boolean sendBuildParameters(@NotNull final UUID preloadedSessionId, @NotNull CmdlineRemoteProto.Message.ControllerMessage params) {
|
||||
boolean succeeded = false;
|
||||
final SessionData sessionData = mySessionDescriptors.get(preloadedSessionId);
|
||||
if (sessionData != null) {
|
||||
//noinspection SynchronizationOnLocalVariableOrMethodParameter
|
||||
synchronized (sessionData) {
|
||||
if (sessionData.state == SessionData.State.WAITING_PARAMS) {
|
||||
sessionData.state = SessionData.State.RUNNING;
|
||||
final Channel channel = sessionData.channel;
|
||||
if (channel != null && channel.isActive()) {
|
||||
sessionData.handler.buildStarted(preloadedSessionId);
|
||||
channel.writeAndFlush(CmdlineProtoUtil.toMessage(preloadedSessionId, params));
|
||||
succeeded = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (sessionData.state == SessionData.State.INITIAL) {
|
||||
sessionData.params = params;
|
||||
succeeded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void messageReceived(ChannelHandlerContext context, CmdlineRemoteProto.Message message) throws Exception {
|
||||
SessionData sessionData = context.attr(SESSION_DATA).get();
|
||||
@@ -89,7 +131,7 @@ class BuildMessageDispatcher extends SimpleChannelInboundHandlerAdapter<CmdlineR
|
||||
final CmdlineRemoteProto.Message.UUID id = message.getSessionId();
|
||||
sessionId = new UUID(id.getMostSigBits(), id.getLeastSigBits());
|
||||
|
||||
sessionData = myMessageHandlers.get(sessionId);
|
||||
sessionData = mySessionDescriptors.get(sessionId);
|
||||
if (sessionData != null) {
|
||||
sessionData.channel = context.channel();
|
||||
context.attr(SESSION_DATA).set(sessionData);
|
||||
@@ -119,14 +161,25 @@ class BuildMessageDispatcher extends SimpleChannelInboundHandlerAdapter<CmdlineR
|
||||
final CmdlineRemoteProto.Message.BuilderMessage builderMessage = message.getBuilderMessage();
|
||||
final CmdlineRemoteProto.Message.BuilderMessage.Type msgType = builderMessage.getType();
|
||||
if (msgType == CmdlineRemoteProto.Message.BuilderMessage.Type.PARAM_REQUEST) {
|
||||
final CmdlineRemoteProto.Message.ControllerMessage params = sessionData.params;
|
||||
if (params != null) {
|
||||
handler.buildStarted(sessionId);
|
||||
sessionData.params = null;
|
||||
context.writeAndFlush(CmdlineProtoUtil.toMessage(sessionId, params));
|
||||
}
|
||||
else {
|
||||
cancelSession(sessionId);
|
||||
//noinspection SynchronizationOnLocalVariableOrMethodParameter
|
||||
synchronized (sessionData) {
|
||||
final CmdlineRemoteProto.Message.ControllerMessage params = sessionData.params;
|
||||
if (params != null) {
|
||||
sessionData.state = SessionData.State.RUNNING;
|
||||
handler.buildStarted(sessionId);
|
||||
sessionData.params = null;
|
||||
context.writeAndFlush(CmdlineProtoUtil.toMessage(sessionId, params));
|
||||
}
|
||||
else {
|
||||
if (sessionData.state == SessionData.State.INITIAL) {
|
||||
sessionData.state = SessionData.State.WAITING_PARAMS;
|
||||
}
|
||||
else {
|
||||
// this message is expected to be sent only once.
|
||||
// To be on the safe side, cancel the session
|
||||
cancelSession(sessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -165,12 +218,19 @@ class BuildMessageDispatcher extends SimpleChannelInboundHandlerAdapter<CmdlineR
|
||||
}
|
||||
|
||||
private static final class SessionData {
|
||||
enum State {
|
||||
INITIAL, WAITING_PARAMS, RUNNING
|
||||
}
|
||||
|
||||
@NotNull
|
||||
final UUID sessionId;
|
||||
@NotNull
|
||||
final BuilderMessageHandler handler;
|
||||
volatile CmdlineRemoteProto.Message.ControllerMessage params;
|
||||
volatile Channel channel;
|
||||
State state = State.INITIAL;
|
||||
|
||||
private SessionData(UUID sessionId, BuilderMessageHandler handler, CmdlineRemoteProto.Message.ControllerMessage params) {
|
||||
private SessionData(@NotNull UUID sessionId, @NotNull BuilderMessageHandler handler, CmdlineRemoteProto.Message.ControllerMessage params) {
|
||||
this.sessionId = sessionId;
|
||||
this.handler = handler;
|
||||
this.params = params;
|
||||
|
||||
@@ -25,6 +25,24 @@ import java.util.UUID;
|
||||
* Date: 4/25/12
|
||||
*/
|
||||
public interface BuilderMessageHandler {
|
||||
BuilderMessageHandler DEAF = new BuilderMessageHandler() {
|
||||
@Override
|
||||
public void buildStarted(UUID sessionId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleBuildMessage(Channel channel, UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage msg) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFailure(UUID sessionId, CmdlineRemoteProto.Message.Failure failure) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionTerminated(UUID sessionId) {
|
||||
}
|
||||
};
|
||||
|
||||
void buildStarted(UUID sessionId);
|
||||
|
||||
void handleBuildMessage(Channel channel, UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage msg);
|
||||
|
||||
+6
-9
@@ -9,30 +9,27 @@ import java.util.UUID;
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 7/3/13
|
||||
*/
|
||||
class MessageHandlerWrapper implements BuilderMessageHandler {
|
||||
private final BuilderMessageHandler myHandler;
|
||||
abstract class DelegatingMessageHandler implements BuilderMessageHandler {
|
||||
|
||||
public MessageHandlerWrapper(BuilderMessageHandler handler) {
|
||||
myHandler = handler;
|
||||
}
|
||||
protected abstract BuilderMessageHandler getDelegateHandler();
|
||||
|
||||
@Override
|
||||
public void buildStarted(UUID sessionId) {
|
||||
myHandler.buildStarted(sessionId);
|
||||
getDelegateHandler().buildStarted(sessionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleBuildMessage(Channel channel, UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage msg) {
|
||||
myHandler.handleBuildMessage(channel, sessionId, msg);
|
||||
getDelegateHandler().handleBuildMessage(channel, sessionId, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFailure(UUID sessionId, CmdlineRemoteProto.Message.Failure failure) {
|
||||
myHandler.handleFailure(sessionId, failure);
|
||||
getDelegateHandler().handleFailure(sessionId, failure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionTerminated(UUID sessionId) {
|
||||
myHandler.sessionTerminated(sessionId);
|
||||
getDelegateHandler().sessionTerminated(sessionId);
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.compiler.server;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 20-Oct-14
|
||||
*/
|
||||
class PreloadedProcessMessageHandler extends DelegatingMessageHandler {
|
||||
@NotNull
|
||||
private final Project myProject;
|
||||
private volatile BuilderMessageHandler myDelegateHandler;
|
||||
|
||||
public PreloadedProcessMessageHandler(@NotNull Project project) {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BuilderMessageHandler getDelegateHandler() {
|
||||
final BuilderMessageHandler delegate = myDelegateHandler;
|
||||
return delegate != null? delegate : BuilderMessageHandler.DEAF;
|
||||
}
|
||||
|
||||
public void setDelegateHandler(BuilderMessageHandler delegateHandler) {
|
||||
myDelegateHandler = delegateHandler;
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ public class JavaReferringObjectsValue extends JavaValue {
|
||||
}
|
||||
|
||||
public JavaReferringObjectsValue(@NotNull JavaValue javaValue, boolean isField) {
|
||||
super(null, javaValue.getDescriptor(), javaValue.getEvaluationContext(), null, false);
|
||||
super(null, javaValue.getDescriptor(), javaValue.getEvaluationContext(), javaValue.getNodeManager(), false);
|
||||
myIsField = isField;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public class JavaReferringObjectsValue extends JavaValue {
|
||||
return reference;
|
||||
}
|
||||
};
|
||||
children.add(new JavaReferringObjectsValue(null, descriptor, getEvaluationContext(), null, true));
|
||||
children.add(new JavaReferringObjectsValue(null, descriptor, getEvaluationContext(), getNodeManager(), true));
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
@@ -109,7 +109,7 @@ public class JavaReferringObjectsValue extends JavaValue {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
children.add("Referrer " + i++, new JavaReferringObjectsValue(null, descriptor, getEvaluationContext(), null, false));
|
||||
children.add("Referrer " + i++, new JavaReferringObjectsValue(null, descriptor, getEvaluationContext(), getNodeManager(), false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,4 +168,10 @@ public class JavaReferringObjectsValue extends JavaValue {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public XValueModifier getModifier() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
private final EvaluationContextImpl myEvaluationContext;
|
||||
private final NodeManagerImpl myNodeManager;
|
||||
private final boolean myContextSet;
|
||||
private final DebuggerManagerThreadImpl myDebuggerManagerThread;
|
||||
|
||||
protected JavaValue(JavaValue parent,
|
||||
@NotNull ValueDescriptorImpl valueDescriptor,
|
||||
@@ -82,6 +83,7 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
myEvaluationContext = evaluationContext;
|
||||
myNodeManager = nodeManager;
|
||||
myContextSet = contextSet;
|
||||
myDebuggerManagerThread = evaluationContext.getDebugProcess().getManagerThread();
|
||||
}
|
||||
|
||||
static JavaValue create(JavaValue parent,
|
||||
@@ -113,6 +115,10 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
return myEvaluationContext;
|
||||
}
|
||||
|
||||
public NodeManagerImpl getNodeManager() {
|
||||
return myNodeManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void computePresentation(@NotNull final XValueNode node, @NotNull XValuePlace place) {
|
||||
final SuspendContextImpl suspendContext = myEvaluationContext.getSuspendContext();
|
||||
@@ -349,7 +355,11 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
}
|
||||
|
||||
boolean scheduleCommand(SuspendContextCommandImpl command) {
|
||||
return scheduleCommand(myEvaluationContext, null, command);
|
||||
if (myEvaluationContext.getSuspendContext().isResumed()) {
|
||||
return false;
|
||||
}
|
||||
myDebuggerManagerThread.schedule(command);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected static boolean scheduleCommand(EvaluationContextImpl evaluationContext,
|
||||
@@ -486,6 +496,7 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
@Nullable
|
||||
@Override
|
||||
public XReferrersProvider getReferrersProvider() {
|
||||
if (myEvaluationContext.getSuspendContext().isResumed()) return null;
|
||||
return new XReferrersProvider() {
|
||||
@Override
|
||||
public XValue getReferringObjectsValue() {
|
||||
@@ -497,16 +508,15 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
@Nullable
|
||||
@Override
|
||||
public XInstanceEvaluator getInstanceEvaluator() {
|
||||
final DebugProcessImpl process = myEvaluationContext.getDebugProcess();
|
||||
return new XInstanceEvaluator() {
|
||||
@Override
|
||||
public void evaluate(@NotNull final XDebuggerEvaluator.XEvaluationCallback callback, @NotNull final XStackFrame frame) {
|
||||
process.getManagerThread().schedule(new DebuggerCommandImpl() {
|
||||
myDebuggerManagerThread.schedule(new DebuggerCommandImpl() {
|
||||
@Override
|
||||
protected void action() throws Exception {
|
||||
ValueDescriptorImpl inspectDescriptor = myValueDescriptor;
|
||||
if (myValueDescriptor instanceof WatchItemDescriptor) {
|
||||
inspectDescriptor = (ValueDescriptorImpl) ((WatchItemDescriptor) myValueDescriptor).getModifier().getInspectItem(getProject());
|
||||
inspectDescriptor = (ValueDescriptorImpl)((WatchItemDescriptor)myValueDescriptor).getModifier().getInspectItem(getProject());
|
||||
}
|
||||
EvaluationContextImpl evaluationContext = ((JavaStackFrame)frame).getFrameDebuggerContext().createEvaluationContext();
|
||||
if (evaluationContext != null) {
|
||||
|
||||
+2
@@ -17,6 +17,7 @@ package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.ChangeContextUtil;
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
|
||||
import com.intellij.codeInsight.intention.HighPriorityAction;
|
||||
@@ -208,6 +209,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
if (element instanceof PsiNewExpression) {
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
|
||||
final PsiAnonymousClass anonymousClass = ((PsiNewExpression)element).getAnonymousClass();
|
||||
|
||||
LOG.assertTrue(anonymousClass != null);
|
||||
|
||||
+2
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -115,6 +116,7 @@ public class AnonymousCanBeMethodReferenceInspection extends BaseJavaBatchLocalI
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
if (element instanceof PsiNewExpression) {
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
|
||||
final PsiAnonymousClass anonymousClass = ((PsiNewExpression)element).getAnonymousClass();
|
||||
if (anonymousClass == null) return;
|
||||
final PsiMethod[] methods = anonymousClass.getMethods();
|
||||
|
||||
+4
-1
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.codeInsight.intention.HighPriorityAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -94,7 +95,9 @@ public class ExplicitTypeCanBeDiamondInspection extends BaseJavaBatchLocalInspec
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiDiamondTypeUtil.replaceExplicitWithDiamond(descriptor.getPsiElement());
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
|
||||
PsiDiamondTypeUtil.replaceExplicitWithDiamond(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -390,6 +391,7 @@ public class LambdaCanBeMethodReferenceInspection extends BaseJavaBatchLocalInsp
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
|
||||
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class);
|
||||
if (lambdaExpression == null) return;
|
||||
final PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType();
|
||||
|
||||
+2
@@ -16,6 +16,7 @@
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil;
|
||||
import com.intellij.codeInsight.intention.AddAnnotationPsiFix;
|
||||
@@ -133,6 +134,7 @@ public class PossibleHeapPollutionVarargsInspection extends BaseJavaBatchLocalIn
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PsiElement psiElement = descriptor.getPsiElement();
|
||||
if (psiElement instanceof PsiIdentifier) {
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(psiElement)) return;
|
||||
final PsiMethod psiMethod = (PsiMethod)psiElement.getParent();
|
||||
psiMethod.getModifierList().setModifierProperty(PsiModifier.FINAL, true);
|
||||
new AddAnnotationPsiFix("java.lang.SafeVarargs", psiMethod, PsiNameValuePair.EMPTY_ARRAY).applyFix(project, descriptor);
|
||||
|
||||
+2
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.codeInsight.intention.HighPriorityAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -158,6 +159,7 @@ public class RedundantLambdaCodeBlockInspection extends BaseJavaBatchLocalInspec
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
if (element != null) {
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
|
||||
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class);
|
||||
if (lambdaExpression != null) {
|
||||
final PsiElement body = lambdaExpression.getBody();
|
||||
|
||||
+20
-4
@@ -92,12 +92,28 @@ public class ExtractLightMethodObjectHandler {
|
||||
final TextRange range = originalContext.getTextRange();
|
||||
final PsiElement originalAnchor =
|
||||
CodeInsightUtil.findElementInRange(copy, range.getStartOffset(), range.getEndOffset(), originalContext.getClass());
|
||||
//todo before this or super, not found etc
|
||||
final PsiElement anchor = RefactoringUtil.getParentStatement(originalAnchor, false);
|
||||
if (anchor == null) {
|
||||
|
||||
final PsiClass containingClass = PsiTreeUtil.getParentOfType(originalAnchor, PsiClass.class);
|
||||
if (containingClass == null) {
|
||||
return null;
|
||||
}
|
||||
final PsiElement container = anchor.getParent();
|
||||
|
||||
PsiElement anchor = RefactoringUtil.getParentStatement(originalAnchor, false);
|
||||
if (anchor == null) {
|
||||
if (PsiTreeUtil.getParentOfType(originalAnchor, PsiCodeBlock.class) != null) {
|
||||
anchor = originalAnchor;
|
||||
}
|
||||
}
|
||||
|
||||
final PsiElement container;
|
||||
if (anchor == null) {
|
||||
container = ((PsiClassInitializer)containingClass.add(elementFactory.createClassInitializer())).getBody();
|
||||
anchor = container.getLastChild();
|
||||
}
|
||||
else {
|
||||
container = anchor.getParent();
|
||||
}
|
||||
|
||||
final PsiElement firstElementCopy = container.addRangeBefore(elements[0], elements[elements.length - 1], anchor);
|
||||
final PsiElement[] elementsCopy = CodeInsightUtil.findStatementsInRange(copy,
|
||||
firstElementCopy.getTextRange().getStartOffset(),
|
||||
|
||||
@@ -870,32 +870,38 @@ public class RefactoringUtil {
|
||||
JavaCodeStyleManager.getInstance(declaration.getProject()).shortenClassReferences(declaration);
|
||||
if (loopBodyCopy != null) codeBlock.add(loopBodyCopy);
|
||||
} else if (container instanceof PsiLambdaExpression) {
|
||||
final PsiLambdaExpression lambdaExpression = (PsiLambdaExpression)container;
|
||||
final PsiElement lambdaExpressionBody = lambdaExpression.getBody();
|
||||
LOG.assertTrue(lambdaExpressionBody != null);
|
||||
PsiLambdaExpression lambdaExpression = (PsiLambdaExpression)container;
|
||||
final PsiElement invalidBody = lambdaExpression.getBody();
|
||||
if (invalidBody == null) return declaration;
|
||||
|
||||
final PsiLambdaExpression expressionFromText = (PsiLambdaExpression)elementFactory
|
||||
.createExpressionFromText(lambdaExpression.getParameterList().getText() + " -> {}", lambdaExpression);
|
||||
.createExpressionFromText(lambdaExpression.getParameterList().getText() + " -> {}", lambdaExpression.getParent());
|
||||
PsiCodeBlock newBody = (PsiCodeBlock)expressionFromText.getBody();
|
||||
LOG.assertTrue(newBody != null);
|
||||
newBody.add(declaration);
|
||||
|
||||
PsiStatement lastBodyStatement = elementFactory.createStatementFromText("a;", lambdaExpression);
|
||||
((PsiExpressionStatement)lastBodyStatement).getExpression().replace(lambdaExpressionBody);
|
||||
lambdaExpression =
|
||||
(PsiLambdaExpression)lambdaExpression.replace(elementFactory.createExpressionFromText(
|
||||
lambdaExpression.getParameterList().getText() + " -> " + invalidBody.getText(), lambdaExpression));
|
||||
|
||||
final PsiElement lambdaExpressionBody = lambdaExpression.getBody();
|
||||
LOG.assertTrue(lambdaExpressionBody != null);
|
||||
final PsiStatement lastBodyStatement;
|
||||
if (LambdaUtil.getFunctionalInterfaceReturnType(lambdaExpression) == PsiType.VOID) {
|
||||
lastBodyStatement = elementFactory.createStatementFromText("a;", lambdaExpression);
|
||||
((PsiExpressionStatement)lastBodyStatement).getExpression().replace(lambdaExpressionBody);
|
||||
}
|
||||
else {
|
||||
lastBodyStatement = elementFactory.createStatementFromText("return a;", lambdaExpression);
|
||||
final PsiExpression returnValue = ((PsiReturnStatement)lastBodyStatement).getReturnValue();
|
||||
LOG.assertTrue(returnValue != null);
|
||||
returnValue.replace(lambdaExpressionBody);
|
||||
}
|
||||
newBody.add(lastBodyStatement);
|
||||
|
||||
PsiLambdaExpression copy = (PsiLambdaExpression)lambdaExpression.replace(expressionFromText);
|
||||
final PsiLambdaExpression copy = (PsiLambdaExpression)lambdaExpression.replace(expressionFromText);
|
||||
newBody = (PsiCodeBlock)copy.getBody();
|
||||
LOG.assertTrue(newBody != null);
|
||||
|
||||
if (LambdaUtil.getFunctionalInterfaceReturnType(copy) != PsiType.VOID) {
|
||||
PsiExpressionStatement lastStatement = (PsiExpressionStatement)newBody.getStatements()[1];
|
||||
PsiReturnStatement returnStatement = (PsiReturnStatement)elementFactory.createStatementFromText("return a;", copy);
|
||||
final PsiExpression returnValue = returnStatement.getReturnValue();
|
||||
LOG.assertTrue(returnValue != null);
|
||||
returnValue.replace(lastStatement.getExpression());
|
||||
lastStatement.replace(returnStatement);
|
||||
}
|
||||
declaration = newBody.getStatements()[0];
|
||||
declaration = (PsiStatement)JavaCodeStyleManager.getInstance(declaration.getProject()).shortenClassReferences(declaration);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
class Sample {
|
||||
|
||||
void a() {
|
||||
System.out.println("");
|
||||
<caret>}
|
||||
|
||||
private int foo() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
class Sample {
|
||||
|
||||
void a() {
|
||||
class Local {
|
||||
|
||||
<caret>}
|
||||
}
|
||||
|
||||
private int foo() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class Sample {
|
||||
static {<caret>}
|
||||
|
||||
int foo() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class Sample {
|
||||
int <caret>i = 0;
|
||||
|
||||
int foo() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class Sample {
|
||||
public Sample() {
|
||||
<caret>super();
|
||||
}
|
||||
|
||||
int foo() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
class Foo {
|
||||
interface I<T> {
|
||||
T m(Object op);
|
||||
}
|
||||
|
||||
interface J<T> {
|
||||
void m(T o);
|
||||
}
|
||||
|
||||
|
||||
void f(J r) {}
|
||||
void f(I<String> r) {}
|
||||
|
||||
{
|
||||
f((a) -> {
|
||||
int c = 1;
|
||||
return c;
|
||||
});
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
class Foo {
|
||||
interface I<T> {
|
||||
T m(Object op);
|
||||
}
|
||||
|
||||
interface J<T> {
|
||||
void m(T o);
|
||||
}
|
||||
|
||||
|
||||
void f(J r) {}
|
||||
void f(I<String> r) {}
|
||||
|
||||
{
|
||||
f((a) -> <selection>1</selection>);
|
||||
}
|
||||
}
|
||||
+50
@@ -214,6 +214,56 @@ public class ExtractMethodObject4DebuggerTest extends LightRefactoringTestCase {
|
||||
" }", false);
|
||||
}
|
||||
|
||||
public void testOnClosingBrace() throws Exception {
|
||||
doTest(" foo()", "int result = new Test().invoke();",
|
||||
|
||||
"public class Test {\n" +
|
||||
" public int invoke() {\n" +
|
||||
" return foo();\n" +
|
||||
" }\n" +
|
||||
" }");
|
||||
}
|
||||
|
||||
public void testOnClosingBraceLocalClass() throws Exception {
|
||||
doTest(" foo()", "int result = new Test().invoke();",
|
||||
|
||||
"public class Test {\n" +
|
||||
" public int invoke() {\n" +
|
||||
" return foo();\n" +
|
||||
" }\n" +
|
||||
" }");
|
||||
}
|
||||
|
||||
public void testOnFieldInitialization() throws Exception {
|
||||
doTest(" foo()", "int result = new Test().invoke();",
|
||||
|
||||
"public class Test {\n" +
|
||||
" public int invoke() {\n" +
|
||||
" return foo();\n" +
|
||||
" }\n" +
|
||||
" }");
|
||||
}
|
||||
|
||||
public void testOnEmptyMethod() throws Exception {
|
||||
doTest(" foo()", "int result = Test.invoke();",
|
||||
|
||||
"public static class Test {\n" +
|
||||
" public static int invoke() {\n" +
|
||||
" return foo();\n" +
|
||||
" }\n" +
|
||||
" }");
|
||||
}
|
||||
|
||||
public void testOnSuperConstructorCall() throws Exception {
|
||||
doTest(" foo()", "int result = new Test().invoke();",
|
||||
|
||||
"public class Test {\n" +
|
||||
" public int invoke() {\n" +
|
||||
" return foo();\n" +
|
||||
" }\n" +
|
||||
" }");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sdk getProjectJDK() {
|
||||
return IdeaTestUtil.getMockJdk18();
|
||||
|
||||
@@ -441,6 +441,10 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase {
|
||||
doTest(new MockIntroduceVariableHandler("c", false, false, false, "int"));
|
||||
}
|
||||
|
||||
public void testPutInLambdaBodyVoidValueConflict() {
|
||||
doTest(new MockIntroduceVariableHandler("c", false, false, false, "int"));
|
||||
}
|
||||
|
||||
public void testNormalizeDeclarations() {
|
||||
doTest(new MockIntroduceVariableHandler("i3", false, false, false, "int"));
|
||||
}
|
||||
|
||||
@@ -15,14 +15,17 @@
|
||||
*/
|
||||
package org.jetbrains.jps.api;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 5/3/12
|
||||
*/
|
||||
public class BasicFuture<T> implements Future<T> {
|
||||
public class BasicFuture<T> implements TaskFuture<T> {
|
||||
protected final Semaphore mySemaphore = new Semaphore(1);
|
||||
private final AtomicBoolean myDone = new AtomicBoolean(false);
|
||||
private final AtomicBoolean myCanceledState = new AtomicBoolean(false);
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 org.jetbrains.jps.api;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public interface TaskFuture<T> extends Future<T> {
|
||||
void waitFor();
|
||||
|
||||
boolean waitFor(long timeout, TimeUnit unit);
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.jetbrains.jps.cmdline;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.io.FileSystemUtil;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
@@ -35,7 +36,11 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.api.CmdlineProtoUtil;
|
||||
import org.jetbrains.jps.api.CmdlineRemoteProto;
|
||||
import org.jetbrains.jps.api.GlobalOptions;
|
||||
import org.jetbrains.jps.incremental.MessageHandler;
|
||||
import org.jetbrains.jps.incremental.Utils;
|
||||
import org.jetbrains.jps.incremental.fs.BuildFSState;
|
||||
import org.jetbrains.jps.incremental.fs.FSState;
|
||||
import org.jetbrains.jps.incremental.messages.BuildMessage;
|
||||
import org.jetbrains.jps.service.SharedThreadPool;
|
||||
|
||||
import java.io.*;
|
||||
@@ -49,6 +54,9 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
@SuppressWarnings("UseOfSystemOutOrSystemErr")
|
||||
public class BuildMain {
|
||||
private static final String PRELOAD_PROJECT_PATH = "preload.project.path";
|
||||
private static final String PRELOAD_CONFIG_PATH = "preload.config.path";
|
||||
|
||||
private static final String LOG_CONFIG_FILE_NAME = "build-log.xml";
|
||||
private static final String LOG_FILE_NAME = "build.log";
|
||||
private static final String DEFAULT_LOGGER_CONFIG = "defaultLogConfig.xml";
|
||||
@@ -65,19 +73,10 @@ public class BuildMain {
|
||||
private static final int SYSTEM_DIR_ARG = SESSION_ID_ARG + 1;
|
||||
|
||||
private static NioEventLoopGroup ourEventLoopGroup;
|
||||
@Nullable
|
||||
private static PreloadedData ourPreloadedData;
|
||||
|
||||
public static void main(String[] args){
|
||||
final long start = System.nanoTime();
|
||||
Runtime.getRuntime().addShutdownHook(new Thread("TimeLogger"){
|
||||
public void run() {
|
||||
final long totalTime = (System.nanoTime() - start) / 1000000L;
|
||||
|
||||
final long millis = totalTime % 1000L ;
|
||||
final long seconds = totalTime / 1000L;
|
||||
|
||||
LOG.info("Total build time " + seconds + " sec " + millis + " ms");
|
||||
}
|
||||
});
|
||||
System.out.println("Build process started. Classpath: " + System.getProperty("java.class.path"));
|
||||
final String host = args[HOST_ARG];
|
||||
final int port = Integer.parseInt(args[PORT_ARG]);
|
||||
@@ -123,6 +122,60 @@ public class BuildMain {
|
||||
final ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port)).awaitUninterruptibly();
|
||||
final boolean success = future.isSuccess();
|
||||
if (success) {
|
||||
final String projectPathToPreload = System.getProperty(PRELOAD_PROJECT_PATH, null);
|
||||
final String globalsPathToPreload = System.getProperty(PRELOAD_CONFIG_PATH, null);
|
||||
if (projectPathToPreload != null && globalsPathToPreload != null) {
|
||||
final long preloadStart = System.currentTimeMillis();
|
||||
final PreloadedData data = new PreloadedData();
|
||||
ourPreloadedData = data;
|
||||
try {
|
||||
FileSystemUtil.getAttributes(projectPathToPreload); // this will pre-load all FS optimizations
|
||||
|
||||
final BuildRunner runner = new BuildRunner(new JpsModelLoaderImpl(projectPathToPreload, globalsPathToPreload, null));
|
||||
data.setRunner(runner);
|
||||
|
||||
final File dataStorageRoot = Utils.getDataStorageRoot(projectPathToPreload);
|
||||
final BuildFSState fsState = new BuildFSState(false);
|
||||
final ProjectDescriptor pd = runner.load(new MessageHandler() {
|
||||
@Override
|
||||
public void processMessage(BuildMessage msg) {
|
||||
data.addMessage(msg);
|
||||
}
|
||||
}, dataStorageRoot, fsState);
|
||||
data.setProjectDescriptor(pd);
|
||||
|
||||
try {
|
||||
final File fsStateFile = new File(dataStorageRoot, BuildSession.FS_STATE_FILE);
|
||||
final DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(fsStateFile)));
|
||||
try {
|
||||
final int version = in.readInt();
|
||||
if (version == FSState.VERSION) {
|
||||
final long savedOrdinal = in.readLong();
|
||||
in.readBoolean(); // must skip "has-work-to-do" flag
|
||||
fsState.load(in, pd.getModel(), pd.getBuildRootIndex());
|
||||
data.setFsEventOrdinal(savedOrdinal);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException ignored) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info("Error pre-loading FS state", e);
|
||||
fsState.clearAll();
|
||||
}
|
||||
LOG.info("Pre-loaded project model in " + (System.currentTimeMillis() - preloadStart) + " ms");
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.info("Failed to pre-load project " + projectPathToPreload, e);
|
||||
// just failed to preload the project, the situation will be handled later, when real build starts
|
||||
}
|
||||
}
|
||||
else if (projectPathToPreload != null || globalsPathToPreload != null){
|
||||
LOG.info("Skipping project pre-loading step: both paths to project configuration files and path to global settings must be specified");
|
||||
}
|
||||
future.channel().writeAndFlush(CmdlineProtoUtil.toMessage(sessionId, CmdlineProtoUtil.createParamRequest()));
|
||||
}
|
||||
else {
|
||||
@@ -159,7 +212,7 @@ public class BuildMain {
|
||||
case BUILD_PARAMETERS: {
|
||||
if (mySession == null) {
|
||||
final CmdlineRemoteProto.Message.ControllerMessage.FSEvent delta = controllerMessage.hasFsEvent()? controllerMessage.getFsEvent() : null;
|
||||
final BuildSession session = new BuildSession(mySessionId, channel, controllerMessage.getParamsMessage(), delta);
|
||||
final BuildSession session = new BuildSession(mySessionId, channel, controllerMessage.getParamsMessage(), delta, ourPreloadedData);
|
||||
mySession = session;
|
||||
SharedThreadPool.getInstance().executeOnPooledThread(new Runnable() {
|
||||
@Override
|
||||
|
||||
@@ -58,14 +58,20 @@ public class BuildRunner {
|
||||
public static final boolean PARALLEL_BUILD_ENABLED = Boolean.parseBoolean(System.getProperty(GlobalOptions.COMPILE_PARALLEL_OPTION, "false"));
|
||||
private static final boolean STORE_TEMP_CACHES_IN_MEMORY = PARALLEL_BUILD_ENABLED || Boolean.valueOf(System.getProperty(GlobalOptions.USE_MEMORY_TEMP_CACHE_OPTION, "true"));
|
||||
private final JpsModelLoader myModelLoader;
|
||||
private final List<String> myFilePaths;
|
||||
private final Map<String, String> myBuilderParams;
|
||||
private List<String> myFilePaths = Collections.emptyList();
|
||||
private Map<String, String> myBuilderParams = Collections.emptyMap();
|
||||
private boolean myForceCleanCaches;
|
||||
|
||||
public BuildRunner(JpsModelLoader modelLoader, List<String> filePaths, Map<String, String> builderParams) {
|
||||
public BuildRunner(JpsModelLoader modelLoader) {
|
||||
myModelLoader = modelLoader;
|
||||
myFilePaths = filePaths;
|
||||
myBuilderParams = builderParams;
|
||||
}
|
||||
|
||||
public void setFilePaths(List<String> filePaths) {
|
||||
myFilePaths = filePaths != null? filePaths : Collections.<String>emptyList();
|
||||
}
|
||||
|
||||
public void setBuilderParams(Map<String, String> builderParams) {
|
||||
myBuilderParams = builderParams != null? builderParams : Collections.<String, String>emptyMap();
|
||||
}
|
||||
|
||||
public ProjectDescriptor load(MessageHandler msgHandler, File dataStorageRoot, BuildFSState fsState) throws IOException {
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.concurrency.SequentialTaskExecutor;
|
||||
import com.intellij.util.io.DataOutputStream;
|
||||
import io.netty.channel.Channel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.TimingLog;
|
||||
import org.jetbrains.jps.api.*;
|
||||
@@ -57,9 +58,11 @@ import static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage
|
||||
*/
|
||||
final class BuildSession implements Runnable, CanceledStatus {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.cmdline.BuildSession");
|
||||
private static final String FS_STATE_FILE = "fs_state.dat";
|
||||
public static final String FS_STATE_FILE = "fs_state.dat";
|
||||
private final UUID mySessionId;
|
||||
private final Channel myChannel;
|
||||
@Nullable
|
||||
private final PreloadedData myPreloadedData;
|
||||
private volatile boolean myCanceled = false;
|
||||
private final String myProjectPath;
|
||||
@Nullable
|
||||
@@ -70,6 +73,7 @@ final class BuildSession implements Runnable, CanceledStatus {
|
||||
private volatile ProjectDescriptor myProjectDescriptor;
|
||||
private final Map<Pair<String, String>, ConstantSearchFuture> mySearchTasks = Collections.synchronizedMap(new HashMap<Pair<String, String>, ConstantSearchFuture>());
|
||||
private final ConstantSearch myConstantSearch = new ConstantSearch();
|
||||
@NotNull
|
||||
private final BuildRunner myBuildRunner;
|
||||
private final boolean myForceModelLoading;
|
||||
private final BuildType myBuildType;
|
||||
@@ -78,24 +82,31 @@ final class BuildSession implements Runnable, CanceledStatus {
|
||||
BuildSession(UUID sessionId,
|
||||
Channel channel,
|
||||
CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage params,
|
||||
@Nullable CmdlineRemoteProto.Message.ControllerMessage.FSEvent delta) {
|
||||
@Nullable CmdlineRemoteProto.Message.ControllerMessage.FSEvent delta, @Nullable PreloadedData preloaded) {
|
||||
mySessionId = sessionId;
|
||||
myChannel = channel;
|
||||
|
||||
myPreloadedData = preloaded;
|
||||
|
||||
final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals = params.getGlobalSettings();
|
||||
myProjectPath = FileUtil.toCanonicalPath(params.getProjectId());
|
||||
String globalOptionsPath = FileUtil.toCanonicalPath(globals.getGlobalOptionsPath());
|
||||
myBuildType = convertCompileType(params.getBuildType());
|
||||
myScopes = params.getScopeList();
|
||||
List<String> filePaths = params.getFilePathList();
|
||||
Map<String, String> builderParams = new HashMap<String, String>();
|
||||
final Map<String, String> builderParams = new HashMap<String, String>();
|
||||
for (CmdlineRemoteProto.Message.KeyValuePair pair : params.getBuilderParameterList()) {
|
||||
builderParams.put(pair.getKey(), pair.getValue());
|
||||
}
|
||||
myInitialFSDelta = delta;
|
||||
JpsModelLoaderImpl loader = new JpsModelLoaderImpl(myProjectPath, globalOptionsPath, null);
|
||||
myForceModelLoading = Boolean.parseBoolean(builderParams.get(BuildParametersKeys.FORCE_MODEL_LOADING));
|
||||
myBuildRunner = new BuildRunner(loader, filePaths, builderParams);
|
||||
if (preloaded == null || preloaded.getRunner() == null) {
|
||||
myBuildRunner = new BuildRunner(new JpsModelLoaderImpl(myProjectPath, globalOptionsPath, null));
|
||||
}
|
||||
else {
|
||||
myBuildRunner = preloaded.getRunner();
|
||||
}
|
||||
myBuildRunner.setFilePaths(filePaths);
|
||||
myBuildRunner.setBuilderParams(builderParams);
|
||||
myForceModelLoading = (preloaded != null && preloaded.getProjectDescriptor() != null) || Boolean.parseBoolean(builderParams.get(BuildParametersKeys.FORCE_MODEL_LOADING));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -185,8 +196,9 @@ final class BuildSession implements Runnable, CanceledStatus {
|
||||
// invoked the very first time for this project
|
||||
myBuildRunner.setForceCleanCaches(true);
|
||||
}
|
||||
|
||||
final DataInputStream fsStateStream = createFSDataStream(dataStorageRoot);
|
||||
final ProjectDescriptor preloadedProject = myPreloadedData != null? myPreloadedData.getProjectDescriptor() : null;
|
||||
final DataInputStream fsStateStream =
|
||||
preloadedProject != null || myInitialFSDelta == null /*this will force FS rescan*/? null : createFSDataStream(dataStorageRoot, myInitialFSDelta.getOrdinal());
|
||||
|
||||
if (fsStateStream != null) {
|
||||
// optimization: check whether we can skip the build
|
||||
@@ -198,27 +210,56 @@ final class BuildSession implements Runnable, CanceledStatus {
|
||||
}
|
||||
}
|
||||
|
||||
final BuildFSState fsState = new BuildFSState(false);
|
||||
final BuildFSState fsState = preloadedProject != null? preloadedProject.fsState : new BuildFSState(false);
|
||||
try {
|
||||
final ProjectDescriptor pd = myBuildRunner.load(msgHandler, dataStorageRoot, fsState);
|
||||
TimingLog.LOG.debug("Project descriptor loaded");
|
||||
myProjectDescriptor = pd;
|
||||
if (fsStateStream != null) {
|
||||
try {
|
||||
try {
|
||||
fsState.load(fsStateStream, pd.getModel(), pd.getBuildRootIndex());
|
||||
applyFSEvent(pd, myInitialFSDelta, false);
|
||||
TimingLog.LOG.debug("FS Delta loaded");
|
||||
}
|
||||
finally {
|
||||
fsStateStream.close();
|
||||
final ProjectDescriptor pd;
|
||||
if (preloadedProject != null) {
|
||||
pd = preloadedProject;
|
||||
final List<BuildMessage> preloadMessages = myPreloadedData.getLoadMessages();
|
||||
if (!preloadMessages.isEmpty()) {
|
||||
// replay preload-time messages, so that they are delivered to the IDE
|
||||
for (BuildMessage message : preloadMessages) {
|
||||
msgHandler.processMessage(message);
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
fsState.clearAll();
|
||||
if (myInitialFSDelta == null || myPreloadedData.getFsEventOrdinal() + 1L != myInitialFSDelta.getOrdinal()) {
|
||||
// FS rescan was forced
|
||||
fsState.clearAll();
|
||||
}
|
||||
else {
|
||||
// apply events to already loaded state
|
||||
try {
|
||||
applyFSEvent(pd, myInitialFSDelta, false);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
fsState.clearAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// standard case
|
||||
pd = myBuildRunner.load(msgHandler, dataStorageRoot, fsState);
|
||||
TimingLog.LOG.debug("Project descriptor loaded");
|
||||
if (fsStateStream != null) {
|
||||
try {
|
||||
try {
|
||||
fsState.load(fsStateStream, pd.getModel(), pd.getBuildRootIndex());
|
||||
applyFSEvent(pd, myInitialFSDelta, false);
|
||||
TimingLog.LOG.debug("FS Delta loaded");
|
||||
}
|
||||
finally {
|
||||
fsStateStream.close();
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
fsState.clearAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
myProjectDescriptor = pd;
|
||||
|
||||
myLastEventOrdinal = myInitialFSDelta != null? myInitialFSDelta.getOrdinal() : 0L;
|
||||
|
||||
// free memory
|
||||
@@ -469,11 +510,7 @@ final class BuildSession implements Runnable, CanceledStatus {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private DataInputStream createFSDataStream(File dataStorageRoot) {
|
||||
if (myInitialFSDelta == null) {
|
||||
// this will force FS rescan
|
||||
return null;
|
||||
}
|
||||
private static DataInputStream createFSDataStream(File dataStorageRoot, final long currentEventOrdinal) {
|
||||
try {
|
||||
final File file = new File(dataStorageRoot, FS_STATE_FILE);
|
||||
byte[] bytes;
|
||||
@@ -490,7 +527,7 @@ final class BuildSession implements Runnable, CanceledStatus {
|
||||
return null;
|
||||
}
|
||||
final long savedOrdinal = in.readLong();
|
||||
if (savedOrdinal + 1L != myInitialFSDelta.getOrdinal()) {
|
||||
if (savedOrdinal + 1L != currentEventOrdinal) {
|
||||
return null;
|
||||
}
|
||||
return in;
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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 org.jetbrains.jps.cmdline;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.incremental.messages.BuildMessage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 22-Oct-14
|
||||
*/
|
||||
public class PreloadedData {
|
||||
@Nullable
|
||||
private BuildRunner runner;
|
||||
@Nullable
|
||||
private ProjectDescriptor projectDescriptor;
|
||||
|
||||
private final List<BuildMessage> loadMessages = new ArrayList<BuildMessage>();
|
||||
|
||||
private long fsEventOrdinal;
|
||||
|
||||
@Nullable
|
||||
public BuildRunner getRunner() {
|
||||
return runner;
|
||||
}
|
||||
|
||||
public void setRunner(@Nullable BuildRunner runner) {
|
||||
this.runner = runner;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ProjectDescriptor getProjectDescriptor() {
|
||||
return projectDescriptor;
|
||||
}
|
||||
|
||||
public void setProjectDescriptor(@Nullable ProjectDescriptor projectDescriptor) {
|
||||
this.projectDescriptor = projectDescriptor;
|
||||
}
|
||||
|
||||
public long getFsEventOrdinal() {
|
||||
return fsEventOrdinal;
|
||||
}
|
||||
|
||||
public void setFsEventOrdinal(long fsEventOrdinal) {
|
||||
this.fsEventOrdinal = fsEventOrdinal;
|
||||
}
|
||||
|
||||
public List<BuildMessage> getLoadMessages() {
|
||||
return loadMessages;
|
||||
}
|
||||
|
||||
public void addMessage(BuildMessage msg) {
|
||||
loadMessages.add(msg);
|
||||
}
|
||||
}
|
||||
@@ -168,7 +168,16 @@ public class JavacMain {
|
||||
diagnosticConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, e.getMessage()));
|
||||
}
|
||||
catch (CompilationCanceledException ignored) {
|
||||
diagnosticConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.OTHER, "Compilation was canceled"));
|
||||
handleCancelException(diagnosticConsumer);
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
final Throwable cause = e.getCause();
|
||||
if (cause instanceof CompilationCanceledException) {
|
||||
handleCancelException(diagnosticConsumer);
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
fileManager.close();
|
||||
@@ -179,6 +188,10 @@ public class JavacMain {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void handleCancelException(DiagnosticOutputConsumer diagnosticConsumer) {
|
||||
diagnosticConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.OTHER, "Compilation was canceled"));
|
||||
}
|
||||
|
||||
private static List<JavaSourceTransformer> getSourceTransformers() {
|
||||
final Class<JavaSourceTransformer> transformerClass = JavaSourceTransformer.class;
|
||||
final ServiceLoader<JavaSourceTransformer> loader = ServiceLoader.load(transformerClass, transformerClass.getClassLoader());
|
||||
|
||||
+22
-1
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.jetbrains.jps.model.serialization;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
@@ -30,6 +31,8 @@ import java.io.IOException;
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class JpsLoaderBase {
|
||||
private static final Logger LOG = Logger.getInstance(JpsLoaderBase.class);
|
||||
private static final int MAX_ATTEMPTS = 5;
|
||||
private final JpsMacroExpander myMacroExpander;
|
||||
|
||||
protected JpsLoaderBase(JpsMacroExpander macroExpander) {
|
||||
@@ -66,7 +69,7 @@ public abstract class JpsLoaderBase {
|
||||
|
||||
protected static Element loadRootElement(final File file, final JpsMacroExpander macroExpander) {
|
||||
try {
|
||||
final Element element = JDOMUtil.loadDocument(file).getRootElement();
|
||||
final Element element = tryLoadRootElement(file);
|
||||
macroExpander.substitute(element, SystemInfo.isFileSystemCaseSensitive);
|
||||
return element;
|
||||
}
|
||||
@@ -78,6 +81,24 @@ public abstract class JpsLoaderBase {
|
||||
}
|
||||
}
|
||||
|
||||
private static Element tryLoadRootElement(File file) throws IOException, JDOMException {
|
||||
for (int i = 0; i < MAX_ATTEMPTS - 1; i++) {
|
||||
try {
|
||||
return JDOMUtil.loadDocument(file).getRootElement();
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.info("Loading attempt #" + i + " failed", e);
|
||||
}
|
||||
//most likely configuration file is being written by IDE so we'll wait a little
|
||||
try {
|
||||
//noinspection BusyWait
|
||||
Thread.sleep(300);
|
||||
}
|
||||
catch (InterruptedException ignored) { }
|
||||
}
|
||||
return JDOMUtil.loadDocument(file).getRootElement();
|
||||
}
|
||||
|
||||
protected static boolean isXmlFile(File file) {
|
||||
return file.isFile() && FileUtilRt.extensionEquals(file.getName(), "xml");
|
||||
}
|
||||
|
||||
@@ -193,8 +193,7 @@ public class Standalone {
|
||||
|
||||
public static void runBuild(JpsModelLoader loader, File dataStorageRoot, MessageHandler messageHandler, List<TargetTypeBuildScope> scopes,
|
||||
boolean includeDependenciesToScope) throws Exception {
|
||||
final BuildRunner buildRunner = new BuildRunner(loader, Collections.<String>emptyList(), Collections.<String, String>emptyMap()
|
||||
);
|
||||
final BuildRunner buildRunner = new BuildRunner(loader);
|
||||
ProjectDescriptor descriptor = buildRunner.load(messageHandler, dataStorageRoot, new BuildFSState(true));
|
||||
try {
|
||||
buildRunner.runBuild(descriptor, CanceledStatus.NULL, null, messageHandler, BuildType.BUILD, scopes, includeDependenciesToScope);
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class FCTSBackedLighterAST extends LighterAST {
|
||||
public class FCTSBackedLighterAST extends LighterAST {
|
||||
private final FlyweightCapableTreeStructure<LighterASTNode> myTreeStructure;
|
||||
|
||||
public FCTSBackedLighterAST(final CharTable charTable, final FlyweightCapableTreeStructure<LighterASTNode> treeStructure) {
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.lang;
|
||||
|
||||
import com.intellij.util.CharTable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Top-level node in AST, corresponds to PsiFile.
|
||||
@@ -28,4 +29,7 @@ public interface FileASTNode extends ASTNode {
|
||||
CharTable getCharTable();
|
||||
|
||||
boolean isParsed();
|
||||
|
||||
@Nullable
|
||||
LighterAST getLighterAST();
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package com.intellij.lang;
|
||||
|
||||
import com.intellij.psi.tree.IFileElementType;
|
||||
import com.intellij.psi.tree.ILightStubFileElementType;
|
||||
import com.intellij.util.CharTable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -46,19 +44,4 @@ public abstract class LighterAST {
|
||||
|
||||
@NotNull
|
||||
public abstract List<LighterASTNode> getChildren(@NotNull final LighterASTNode parent);
|
||||
|
||||
public static @Nullable LighterAST getLighterASTFromFileAST(@NotNull FileASTNode node, @NotNull Language language) {
|
||||
final IFileElementType contentType = LanguageParserDefinitions.INSTANCE.forLanguage(language).getFileNodeType();
|
||||
assert contentType instanceof ILightStubFileElementType;
|
||||
|
||||
final LighterAST tree;
|
||||
if (!node.isParsed()) {
|
||||
final ILightStubFileElementType<?> type = (ILightStubFileElementType)contentType;
|
||||
tree = new FCTSBackedLighterAST(node.getCharTable(), type.parseContentsLight(node));
|
||||
}
|
||||
else {
|
||||
tree = new TreeBackedLighterAST(node);
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,7 @@ public class LightStubBuilder implements StubBuilder {
|
||||
LOG.error("File is not of ILightStubFileElementType: " + contentType + ", " + file);
|
||||
return null;
|
||||
}
|
||||
final LighterAST tree = LighterAST.getLighterASTFromFileAST(file.getNode(), language);
|
||||
final LighterAST tree = file.getNode().getLighterAST();
|
||||
if (tree == null) return null;
|
||||
|
||||
final StubElement rootStub = createStubForFile(file, tree);
|
||||
|
||||
@@ -30,7 +30,10 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.StreamUtil;
|
||||
import com.intellij.openapi.util.io.ZipFileCache;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.PlatformUtilsCore;
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.util.execution.ParametersListUtil;
|
||||
@@ -166,7 +169,7 @@ public class PluginManagerCore {
|
||||
return app != null && app.isUnitTestMode();
|
||||
}
|
||||
|
||||
public static void savePluginsList(Collection<String> ids, boolean append, File plugins) throws IOException {
|
||||
public static void savePluginsList(@NotNull Collection<String> ids, boolean append, @NotNull File plugins) throws IOException {
|
||||
if (!plugins.isFile()) {
|
||||
FileUtil.ensureCanCreateFile(plugins);
|
||||
}
|
||||
@@ -700,7 +703,13 @@ public class PluginManagerCore {
|
||||
List<IdeaPluginDescriptorImpl> result,
|
||||
@Nullable StartupProgress progress,
|
||||
int pluginsCount) {
|
||||
final File pluginsHome = new File(pluginsPath);
|
||||
loadDescriptors(new File(pluginsPath), result, progress, pluginsCount);
|
||||
}
|
||||
|
||||
public static void loadDescriptors(@NotNull File pluginsHome,
|
||||
List<IdeaPluginDescriptorImpl> result,
|
||||
@Nullable StartupProgress progress,
|
||||
int pluginsCount) {
|
||||
final File[] files = pluginsHome.listFiles();
|
||||
if (files != null) {
|
||||
int i = result.size();
|
||||
|
||||
@@ -89,6 +89,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
|
||||
private final ASTNode myOriginalTree;
|
||||
private final MyTreeStructure myParentLightTree;
|
||||
private final int myOffset;
|
||||
|
||||
private static TokenSet ourAnyLanguageWhitespaceTokens = TokenSet.EMPTY;
|
||||
|
||||
@@ -132,7 +133,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
@Nullable ASTNode originalTree,
|
||||
@Nullable MyTreeStructure parentLightTree) {
|
||||
this(project, containingFile, parserDefinition.getWhitespaceTokens(), parserDefinition.getCommentTokens(), lexer, charTable, text,
|
||||
originalTree, parentLightTree);
|
||||
originalTree, parentLightTree, 0);
|
||||
}
|
||||
|
||||
public PsiBuilderImpl(Project project,
|
||||
@@ -144,6 +145,19 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
@NotNull final CharSequence text,
|
||||
@Nullable ASTNode originalTree,
|
||||
@Nullable MyTreeStructure parentLightTree) {
|
||||
this(project, containingFile, whiteSpaces, comments, lexer, charTable, text, originalTree, parentLightTree, 0);
|
||||
}
|
||||
|
||||
private PsiBuilderImpl(Project project,
|
||||
PsiFile containingFile,
|
||||
@NotNull TokenSet whiteSpaces,
|
||||
@NotNull TokenSet comments,
|
||||
@NotNull Lexer lexer,
|
||||
CharTable charTable,
|
||||
@NotNull final CharSequence text,
|
||||
@Nullable ASTNode originalTree,
|
||||
@Nullable MyTreeStructure parentLightTree,
|
||||
int offset) {
|
||||
myProject = project;
|
||||
myFile = containingFile;
|
||||
|
||||
@@ -156,6 +170,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
myCharTable = charTable;
|
||||
myOriginalTree = originalTree;
|
||||
myParentLightTree = parentLightTree;
|
||||
myOffset = offset;
|
||||
|
||||
cacheLexemes();
|
||||
}
|
||||
@@ -174,8 +189,8 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
@NotNull final Lexer lexer,
|
||||
@NotNull final LighterLazyParseableNode chameleon,
|
||||
@NotNull final CharSequence text) {
|
||||
this(project, chameleon.getContainingFile(), parserDefinition, lexer, chameleon.getCharTable(), text,
|
||||
null, ((LazyParseableToken)chameleon).myParent);
|
||||
this(project, chameleon.getContainingFile(), parserDefinition.getWhitespaceTokens(), parserDefinition.getCommentTokens(), lexer,
|
||||
chameleon.getCharTable(), text, null, ((LazyParseableToken)chameleon).myParent, chameleon.getStartOffset());
|
||||
}
|
||||
|
||||
private void cacheLexemes() {
|
||||
@@ -335,12 +350,12 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
|
||||
@Override
|
||||
public int getStartOffset() {
|
||||
return myBuilder.myLexStarts[myLexemeIndex];
|
||||
return myBuilder.myLexStarts[myLexemeIndex] + myBuilder.myOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEndOffset() {
|
||||
return myBuilder.myLexStarts[myDoneMarker.myLexemeIndex];
|
||||
return myBuilder.myLexStarts[myDoneMarker.myLexemeIndex] + myBuilder.myOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -487,12 +502,12 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
|
||||
@Override
|
||||
public int getEndOffset() {
|
||||
return myTokenEnd;
|
||||
return myTokenEnd + myBuilder.myOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStartOffset() {
|
||||
return myTokenStart;
|
||||
return myTokenStart + myBuilder.myOffset;
|
||||
}
|
||||
|
||||
public CharSequence getText() {
|
||||
@@ -636,12 +651,12 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
|
||||
@Override
|
||||
public int getEndOffset() {
|
||||
return myBuilder.myLexStarts[myLexemeIndex];
|
||||
return myBuilder.myLexStarts[myLexemeIndex] + myBuilder.myOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStartOffset() {
|
||||
return myBuilder.myLexStarts[myLexemeIndex];
|
||||
return myBuilder.myLexStarts[myLexemeIndex] + myBuilder.myOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1474,6 +1489,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
private final LimitedPool<Token> myPool;
|
||||
private final LimitedPool<LazyParseableToken> myLazyPool;
|
||||
private final StartMarker myRoot;
|
||||
private final int myOffset;
|
||||
|
||||
public MyTreeStructure(@NotNull StartMarker root, @Nullable final MyTreeStructure parentTree) {
|
||||
if (parentTree == null) {
|
||||
@@ -1499,10 +1515,12 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
return new LazyParseableToken();
|
||||
}
|
||||
});
|
||||
myOffset = 0;
|
||||
}
|
||||
else {
|
||||
myPool = parentTree.myPool;
|
||||
myLazyPool = parentTree.myLazyPool;
|
||||
myOffset = parentTree.getRoot().getStartOffset();
|
||||
}
|
||||
myRoot = root;
|
||||
}
|
||||
|
||||
@@ -16,16 +16,19 @@
|
||||
|
||||
package com.intellij.psi.impl.source.tree;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.FileASTNode;
|
||||
import com.intellij.lang.*;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.psi.impl.source.CharTableImpl;
|
||||
import com.intellij.psi.impl.source.PsiFileImpl;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.IFileElementType;
|
||||
import com.intellij.psi.tree.ILightStubFileElementType;
|
||||
import com.intellij.util.CharTable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class FileElement extends LazyParseableElement implements FileASTNode, Getter<FileElement> {
|
||||
private volatile CharTable myCharTable = new CharTableImpl();
|
||||
@@ -47,6 +50,35 @@ public class FileElement extends LazyParseableElement implements FileASTNode, Ge
|
||||
return myCharTable;
|
||||
}
|
||||
|
||||
private static final Key<LighterAST> ourTreeKey = Key.create("lighter.key");
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public LighterAST getLighterAST() {
|
||||
final IFileElementType contentType = (IFileElementType)getElementType();
|
||||
assert contentType instanceof ILightStubFileElementType;
|
||||
|
||||
LighterAST tree;
|
||||
if (!isParsed()) {
|
||||
tree = getUserData(ourTreeKey);
|
||||
if (tree == null) {
|
||||
final ILightStubFileElementType<?> type = (ILightStubFileElementType)contentType;
|
||||
tree = new FCTSBackedLighterAST(getCharTable(), type.parseContentsLight(this));
|
||||
putUserData(ourTreeKey, tree);
|
||||
}
|
||||
}
|
||||
else {
|
||||
tree = new TreeBackedLighterAST(this);
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetCachesOnParsedStateUpdate() {
|
||||
putUserData(ourTreeKey, null);
|
||||
super.resetCachesOnParsedStateUpdate();
|
||||
}
|
||||
|
||||
public FileElement(IElementType type, CharSequence text) {
|
||||
super(type, text);
|
||||
}
|
||||
|
||||
@@ -181,8 +181,8 @@ public class LazyParseableElement extends CompositeElement {
|
||||
if (rawFirstChild() != null) {
|
||||
LOG.error("Reentrant parsing?");
|
||||
}
|
||||
|
||||
myText = null;
|
||||
|
||||
resetCachesOnParsedStateUpdate();
|
||||
|
||||
if (parsedNode == null) return;
|
||||
super.rawAddChildrenWithoutNotifications((TreeElement)parsedNode);
|
||||
@@ -199,6 +199,10 @@ public class LazyParseableElement extends CompositeElement {
|
||||
}
|
||||
}
|
||||
|
||||
protected void resetCachesOnParsedStateUpdate() {
|
||||
myText = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rawAddChildrenWithoutNotifications(@NotNull TreeElement first) {
|
||||
if (myText() != null) {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.dupLocator;
|
||||
|
||||
import com.intellij.lang.LighterAST;
|
||||
import com.intellij.lang.LighterASTNode;
|
||||
import com.intellij.psi.PsiFile;
|
||||
|
||||
/**
|
||||
* Created by Maxim.Mossienko on 10/1/2014.
|
||||
*/
|
||||
public interface LightDuplicateProfile {
|
||||
void process(PsiFile file, Callback callback);
|
||||
|
||||
interface Callback {
|
||||
void process(LighterAST ast, LighterASTNode node, int hash);
|
||||
}
|
||||
}
|
||||
+29
-15
@@ -18,15 +18,18 @@ package com.intellij.dupLocator.index;
|
||||
import com.intellij.dupLocator.DuplicatesProfile;
|
||||
import com.intellij.dupLocator.DuplocateVisitor;
|
||||
import com.intellij.dupLocator.DuplocatorState;
|
||||
import com.intellij.dupLocator.LightDuplicateProfile;
|
||||
import com.intellij.dupLocator.treeHash.FragmentsCollector;
|
||||
import com.intellij.dupLocator.util.PsiFragment;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.LighterAST;
|
||||
import com.intellij.lang.LighterASTNode;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import com.intellij.util.indexing.*;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
@@ -52,6 +55,7 @@ import java.util.Map;
|
||||
public class DuplicatesIndex extends FileBasedIndexExtension<Integer, TIntArrayList> implements PsiDependentIndex {
|
||||
static boolean ourEnabled = SystemProperties.getBooleanProperty("idea.enable.duplicates.online.calculation",
|
||||
isEnabledByDefault());
|
||||
static boolean ourEnabledLightProfiles = true;
|
||||
|
||||
private static boolean isEnabledByDefault() {
|
||||
Application application = ApplicationManager.getApplication();
|
||||
@@ -59,7 +63,7 @@ public class DuplicatesIndex extends FileBasedIndexExtension<Integer, TIntArrayL
|
||||
}
|
||||
|
||||
@NonNls public static final ID<Integer, TIntArrayList> NAME = ID.create("DuplicatesIndex");
|
||||
private static final int myBaseVersion = 10;
|
||||
private static final int myBaseVersion = 12;
|
||||
|
||||
private final FileBasedIndex.InputFilter myInputFilter = new FileBasedIndex.InputFilter() {
|
||||
@Override
|
||||
@@ -107,21 +111,31 @@ public class DuplicatesIndex extends FileBasedIndexExtension<Integer, TIntArrayL
|
||||
@Override
|
||||
@NotNull
|
||||
public Map<Integer, TIntArrayList> map(@NotNull final FileContent inputData) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<Map<Integer, TIntArrayList>>() {
|
||||
@Override
|
||||
public Map<Integer, TIntArrayList> compute() {
|
||||
FileType type = inputData.getFileType();
|
||||
FileType type = inputData.getFileType();
|
||||
|
||||
DuplicatesProfile profile = findDuplicatesProfile(type);
|
||||
if (profile == null) return Collections.emptyMap();
|
||||
DuplicatesProfile profile = findDuplicatesProfile(type);
|
||||
if (profile == null) return Collections.emptyMap();
|
||||
|
||||
MyFragmentsCollector collector = new MyFragmentsCollector(profile, ((LanguageFileType)type).getLanguage());
|
||||
DuplocateVisitor visitor = profile.createVisitor(collector, true);
|
||||
visitor.visitNode(((FileContentImpl)inputData).getPsiFileAccountingForUnsavedDocument());
|
||||
PsiFile psiFile = ((FileContentImpl)inputData).getPsiFileAccountingForUnsavedDocument();
|
||||
|
||||
return collector.getMap();
|
||||
}
|
||||
});
|
||||
if (profile instanceof LightDuplicateProfile && ourEnabledLightProfiles) {
|
||||
final THashMap<Integer, TIntArrayList> result = new THashMap<Integer, TIntArrayList>();
|
||||
((LightDuplicateProfile)profile).process(psiFile, new LightDuplicateProfile.Callback() {
|
||||
@Override
|
||||
public void process(LighterAST ast, LighterASTNode node, int hash) {
|
||||
TIntArrayList list = result.get(hash);
|
||||
if (list == null) { result.put(hash, list = new TIntArrayList(1)); }
|
||||
list.add(node.getStartOffset());
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
MyFragmentsCollector collector = new MyFragmentsCollector(profile, ((LanguageFileType)type).getLanguage());
|
||||
DuplocateVisitor visitor = profile.createVisitor(collector, true);
|
||||
|
||||
visitor.visitNode(psiFile);
|
||||
|
||||
return collector.getMap();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -135,7 +149,7 @@ public class DuplicatesIndex extends FileBasedIndexExtension<Integer, TIntArrayL
|
||||
|
||||
@Override
|
||||
public int getVersion() {
|
||||
return myBaseVersion + (ourEnabled ? 0xFF : 0);
|
||||
return myBaseVersion + (ourEnabled ? 0xFF : 0) + (ourEnabledLightProfiles ? 0x7F : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+176
-67
@@ -3,10 +3,16 @@ package com.intellij.dupLocator.index;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.dupLocator.DuplicatesProfile;
|
||||
import com.intellij.dupLocator.DuplocatorState;
|
||||
import com.intellij.dupLocator.LightDuplicateProfile;
|
||||
import com.intellij.dupLocator.treeHash.FragmentsCollector;
|
||||
import com.intellij.dupLocator.util.PsiFragment;
|
||||
import com.intellij.lang.LighterAST;
|
||||
import com.intellij.lang.LighterASTNode;
|
||||
import com.intellij.lang.TreeBackedLighterAST;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileWithId;
|
||||
@@ -35,94 +41,126 @@ public class DuplicatesInspectionBase extends LocalInspectionTool {
|
||||
final DuplicatesProfile profile = DuplicatesIndex.findDuplicatesProfile(psiFile.getFileType());
|
||||
if (profile == null) return ProblemDescriptor.EMPTY_ARRAY;
|
||||
|
||||
final DuplocatorState state = profile.getDuplocatorState(psiFile.getLanguage());
|
||||
final SmartList<ProblemDescriptor> descriptors = new SmartList<ProblemDescriptor>();
|
||||
final Ref<DuplicatedCodeProcessor> myProcessorRef = new Ref<DuplicatedCodeProcessor>();
|
||||
|
||||
final TreeMap<Integer, TextRange> reportedRanges = new TreeMap<Integer, TextRange>();
|
||||
final TIntObjectHashMap<VirtualFile> reportedFiles = new TIntObjectHashMap<VirtualFile>();
|
||||
final TIntObjectHashMap<PsiElement> reportedPsi = new TIntObjectHashMap<PsiElement>();
|
||||
final TIntIntHashMap reportedOffsetInOtherFiles = new TIntIntHashMap();
|
||||
final TIntIntHashMap fragmentSize = new TIntIntHashMap();
|
||||
if (profile instanceof LightDuplicateProfile && DuplicatesIndex.ourEnabledLightProfiles) {
|
||||
|
||||
profile.createVisitor(new FragmentsCollector() {
|
||||
@Override
|
||||
public void add(int hash, final int cost, @Nullable final PsiFragment frag) {
|
||||
if (!DuplicatesIndex.isIndexedFragment(frag, cost, profile, state)) {
|
||||
return;
|
||||
((LightDuplicateProfile)profile).process(psiFile, new LightDuplicateProfile.Callback() {
|
||||
DuplicatedCodeProcessor<LighterASTNode> myProcessor;
|
||||
@Override
|
||||
public void process(final LighterAST ast, final LighterASTNode node, int hash) {
|
||||
class LightDuplicatedCodeProcessor extends DuplicatedCodeProcessor<LighterASTNode> {
|
||||
|
||||
LightDuplicatedCodeProcessor(VirtualFile file, Project project) {
|
||||
super(file, project);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TextRange getRangeInElement(LighterASTNode node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PsiElement getPsi(LighterASTNode node) {
|
||||
return ((TreeBackedLighterAST)ast).unwrap(node).getPsi();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getStartOffset(LighterASTNode node) {
|
||||
return node.getStartOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getEndOffset(LighterASTNode node) {
|
||||
return node.getEndOffset();
|
||||
}
|
||||
}
|
||||
if (myProcessor == null) {
|
||||
myProcessor = new LightDuplicatedCodeProcessor(virtualFile, psiFile.getProject());
|
||||
myProcessorRef.set(myProcessor);
|
||||
}
|
||||
myProcessor.process(hash, node);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
final DuplocatorState state = profile.getDuplocatorState(psiFile.getLanguage());
|
||||
profile.createVisitor(new FragmentsCollector() {
|
||||
DuplicatedCodeProcessor<PsiFragment> myProcessor;
|
||||
@Override
|
||||
public void add(int hash, final int cost, @Nullable final PsiFragment frag) {
|
||||
if (!DuplicatesIndex.isIndexedFragment(frag, cost, profile, state)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProgressManager.checkCanceled();
|
||||
FileBasedIndex.getInstance().processValues(DuplicatesIndex.NAME, hash, null, new FileBasedIndex.ValueProcessor<TIntArrayList>() {
|
||||
final ProjectFileIndex myProjectFileIndex = ProjectFileIndex.SERVICE.getInstance(psiFile.getProject());
|
||||
@Override
|
||||
public boolean process(final VirtualFile file, final TIntArrayList list) {
|
||||
for(int i = 0, len = list.size(); i < len; ++i) {
|
||||
ProgressManager.checkCanceled();
|
||||
class OldDuplicatedCodeProcessor extends DuplicatedCodeProcessor<PsiFragment> {
|
||||
|
||||
int value = list.getQuick(i);
|
||||
OldDuplicatedCodeProcessor(VirtualFile file, Project project) {
|
||||
super(file, project);
|
||||
}
|
||||
|
||||
if (myProjectFileIndex.isInSource(virtualFile) && !myProjectFileIndex.isInSource(file)) return true;
|
||||
if (!myProjectFileIndex.isInSource(virtualFile) && myProjectFileIndex.isInSource(file)) return true;
|
||||
final int startOffset = frag.getStartOffset();
|
||||
final int endOffset = frag.getEndOffset();
|
||||
if (file.equals(virtualFile) && value >= startOffset && value < endOffset) continue;
|
||||
|
||||
PsiElement[] elements = frag.getElements();
|
||||
PsiElement target = elements[0];
|
||||
@Override
|
||||
protected TextRange getRangeInElement(PsiFragment node) {
|
||||
PsiElement[] elements = node.getElements();
|
||||
TextRange rangeInElement = null;
|
||||
if (elements.length > 1) {
|
||||
PsiElement firstElement = elements[0];
|
||||
target = firstElement.getParent();
|
||||
|
||||
PsiElement lastElement = elements[elements.length - 1];
|
||||
rangeInElement = new TextRange(
|
||||
elements[0].getStartOffsetInParent(),
|
||||
lastElement.getStartOffsetInParent() + lastElement.getTextLength()
|
||||
);
|
||||
}
|
||||
return rangeInElement;
|
||||
}
|
||||
|
||||
Integer fragmentStartOffsetInteger = startOffset;
|
||||
SortedMap<Integer,TextRange> map = reportedRanges.subMap(fragmentStartOffsetInteger, endOffset);
|
||||
int newFragmentSize = !map.isEmpty() ? 0:1;
|
||||
@Override
|
||||
protected PsiElement getPsi(PsiFragment node) {
|
||||
PsiElement[] elements = node.getElements();
|
||||
|
||||
Iterator<Integer> iterator = map.keySet().iterator();
|
||||
while(iterator.hasNext()) {
|
||||
Integer next = iterator.next();
|
||||
iterator.remove();
|
||||
reportedFiles.remove(next);
|
||||
reportedOffsetInOtherFiles.remove(next);
|
||||
reportedPsi.remove(next);
|
||||
newFragmentSize += fragmentSize.remove(next);
|
||||
}
|
||||
return elements.length > 1 ? elements[0].getParent() : elements[0];
|
||||
}
|
||||
|
||||
reportedRanges.put(fragmentStartOffsetInteger, rangeInElement);
|
||||
reportedFiles.put(fragmentStartOffsetInteger, file);
|
||||
reportedOffsetInOtherFiles.put(fragmentStartOffsetInteger, value);
|
||||
reportedPsi.put(fragmentStartOffsetInteger, target);
|
||||
fragmentSize.put(fragmentStartOffsetInteger, newFragmentSize);
|
||||
@Override
|
||||
protected int getStartOffset(PsiFragment node) {
|
||||
return node.getStartOffset();
|
||||
}
|
||||
|
||||
return false;
|
||||
@Override
|
||||
protected int getEndOffset(PsiFragment node) {
|
||||
return node.getEndOffset();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, GlobalSearchScope.projectScope(psiFile.getProject()));
|
||||
if (myProcessor == null) {
|
||||
myProcessor = new OldDuplicatedCodeProcessor(virtualFile, psiFile.getProject());
|
||||
myProcessorRef.set(myProcessor);
|
||||
}
|
||||
myProcessor.process(hash, frag);
|
||||
}
|
||||
}, true).visitNode(psiFile);
|
||||
}
|
||||
|
||||
DuplicatedCodeProcessor<?> processor = myProcessorRef.get();
|
||||
|
||||
final SmartList<ProblemDescriptor> descriptors = new SmartList<ProblemDescriptor>();
|
||||
|
||||
if (processor != null) {
|
||||
|
||||
for(Map.Entry<Integer, TextRange> entry:processor.reportedRanges.entrySet()) {
|
||||
final Integer offset = entry.getKey();
|
||||
// todo 3 statements constant
|
||||
if (processor.fragmentSize.get(offset) < 3) continue;
|
||||
final VirtualFile file = processor.reportedFiles.get(offset);
|
||||
String message = "Found duplicated code in " + file.getPath();
|
||||
|
||||
PsiElement targetElement = processor.reportedPsi.get(offset);
|
||||
TextRange rangeInElement = entry.getValue();
|
||||
final int offsetInOtherFile = processor.reportedOffsetInOtherFiles.get(offset);
|
||||
|
||||
LocalQuickFix fix = createNavigateToDupeFix(file, offsetInOtherFile);
|
||||
ProblemDescriptor descriptor = manager
|
||||
.createProblemDescriptor(targetElement, rangeInElement, message, ProblemHighlightType.WEAK_WARNING, isOnTheFly, fix);
|
||||
descriptors.add(descriptor);
|
||||
}
|
||||
}, true).visitNode(psiFile);
|
||||
|
||||
for(Map.Entry<Integer, TextRange> entry:reportedRanges.entrySet()) {
|
||||
final Integer offset = entry.getKey();
|
||||
// todo 3 statements constant
|
||||
if (fragmentSize.get(offset) < 3) continue;
|
||||
final VirtualFile file = reportedFiles.get(offset);
|
||||
String message = "Found duplicated code in " + file.getPath();
|
||||
|
||||
PsiElement targetElement = reportedPsi.get(offset);
|
||||
TextRange rangeInElement = entry.getValue();
|
||||
final int offsetInOtherFile = reportedOffsetInOtherFiles.get(offset);
|
||||
|
||||
LocalQuickFix fix = createNavigateToDupeFix(file, offsetInOtherFile);
|
||||
ProblemDescriptor descriptor = manager
|
||||
.createProblemDescriptor(targetElement, rangeInElement, message, ProblemHighlightType.WEAK_WARNING, isOnTheFly, fix);
|
||||
descriptors.add(descriptor);
|
||||
}
|
||||
|
||||
return descriptors.isEmpty() ? null : descriptors.toArray(new ProblemDescriptor[descriptors.size()]);
|
||||
@@ -131,4 +169,75 @@ public class DuplicatesInspectionBase extends LocalInspectionTool {
|
||||
protected LocalQuickFix createNavigateToDupeFix(@NotNull VirtualFile file, int offsetInOtherFile) {
|
||||
return null;
|
||||
}
|
||||
|
||||
static abstract class DuplicatedCodeProcessor<T> implements FileBasedIndex.ValueProcessor<TIntArrayList> {
|
||||
final TreeMap<Integer, TextRange> reportedRanges = new TreeMap<Integer, TextRange>();
|
||||
final TIntObjectHashMap<VirtualFile> reportedFiles = new TIntObjectHashMap<VirtualFile>();
|
||||
final TIntObjectHashMap<PsiElement> reportedPsi = new TIntObjectHashMap<PsiElement>();
|
||||
final TIntIntHashMap reportedOffsetInOtherFiles = new TIntIntHashMap();
|
||||
final TIntIntHashMap fragmentSize = new TIntIntHashMap();
|
||||
final VirtualFile virtualFile;
|
||||
final Project project;
|
||||
final ProjectFileIndex myProjectFileIndex;
|
||||
T myNode;
|
||||
|
||||
DuplicatedCodeProcessor(VirtualFile file, Project project) {
|
||||
virtualFile = file;
|
||||
this.project = project;
|
||||
myProjectFileIndex = ProjectFileIndex.SERVICE.getInstance(project);
|
||||
}
|
||||
|
||||
void process(int hash, T node) {
|
||||
ProgressManager.checkCanceled();
|
||||
myNode = node;
|
||||
FileBasedIndex.getInstance().processValues(DuplicatesIndex.NAME, hash, null, this, GlobalSearchScope.projectScope(project));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(VirtualFile file, TIntArrayList list) {
|
||||
for(int i = 0, len = list.size(); i < len; ++i) {
|
||||
ProgressManager.checkCanceled();
|
||||
|
||||
int value = list.getQuick(i);
|
||||
|
||||
if (myProjectFileIndex.isInSource(virtualFile) && !myProjectFileIndex.isInSource(file)) return true;
|
||||
if (!myProjectFileIndex.isInSource(virtualFile) && myProjectFileIndex.isInSource(file)) return true;
|
||||
final int startOffset = getStartOffset(myNode);
|
||||
final int endOffset = getEndOffset(myNode);
|
||||
if (file.equals(virtualFile) && value >= startOffset && value < endOffset) continue;
|
||||
|
||||
PsiElement target = getPsi(myNode);
|
||||
TextRange rangeInElement = getRangeInElement(myNode);
|
||||
|
||||
Integer fragmentStartOffsetInteger = startOffset;
|
||||
SortedMap<Integer,TextRange> map = reportedRanges.subMap(fragmentStartOffsetInteger, endOffset);
|
||||
int newFragmentSize = !map.isEmpty() ? 0:1;
|
||||
|
||||
Iterator<Integer> iterator = map.keySet().iterator();
|
||||
while(iterator.hasNext()) {
|
||||
Integer next = iterator.next();
|
||||
iterator.remove();
|
||||
reportedFiles.remove(next);
|
||||
reportedOffsetInOtherFiles.remove(next);
|
||||
reportedPsi.remove(next);
|
||||
newFragmentSize += fragmentSize.remove(next);
|
||||
}
|
||||
|
||||
reportedRanges.put(fragmentStartOffsetInteger, rangeInElement);
|
||||
reportedFiles.put(fragmentStartOffsetInteger, file);
|
||||
reportedOffsetInOtherFiles.put(fragmentStartOffsetInteger, value);
|
||||
reportedPsi.put(fragmentStartOffsetInteger, target);
|
||||
fragmentSize.put(fragmentStartOffsetInteger, newFragmentSize);
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract TextRange getRangeInElement(T node);
|
||||
protected abstract PsiElement getPsi(T node);
|
||||
|
||||
protected abstract int getStartOffset(T node);
|
||||
protected abstract int getEndOffset(T node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.project.ProjectManagerListener;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.Key;
|
||||
@@ -421,7 +422,11 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
|
||||
}
|
||||
//Stage two: try to get content from descriptor itself
|
||||
final Content attachedContent = descriptor.getAttachedContent();
|
||||
if (attachedContent != null && attachedContent.isValid() && contentManager.getIndexOfContent(attachedContent) != -1) {
|
||||
|
||||
if (attachedContent != null
|
||||
&& attachedContent.isValid()
|
||||
&& contentManager.getIndexOfContent(attachedContent) != -1
|
||||
&& (Comparing.equal(descriptor.getDisplayName(), attachedContent.getDisplayName()) || !attachedContent.isPinned())) {
|
||||
content = attachedContent;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-3
@@ -321,9 +321,13 @@ public class PsiDirectoryNode extends BasePsiNode<PsiDirectory> implements Navig
|
||||
@Override
|
||||
public Comparable getTypeSortKey() {
|
||||
VirtualFile file = getVirtualFile();
|
||||
if (file == null) return null;
|
||||
String extension = file.getExtension();
|
||||
return extension == null ? null : new PsiFileNode.ExtensionSortKey(extension);
|
||||
if (file != null) {
|
||||
String extension = file.getExtension();
|
||||
if (extension != null) {
|
||||
return new PsiFileNode.ExtensionSortKey(extension);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+79
-60
@@ -17,11 +17,14 @@ package com.intellij.openapi.application;
|
||||
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptorImpl;
|
||||
import com.intellij.ide.plugins.PluginManager;
|
||||
import com.intellij.ide.plugins.PluginManagerCore;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.AppUIUtil;
|
||||
import com.intellij.util.PlatformUtils;
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.ThreeState;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -30,8 +33,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.PropertyResourceBundle;
|
||||
@@ -55,21 +56,25 @@ public class ConfigImportHelper {
|
||||
private ConfigImportHelper() {
|
||||
}
|
||||
|
||||
public static void importConfigsTo(String newConfigPath) {
|
||||
public static void importConfigsTo(@NotNull String newConfigPath) {
|
||||
ConfigImportSettings settings = getConfigImportSettings();
|
||||
|
||||
File oldConfigDir = findOldConfigDir(newConfigPath, settings.getCustomPathsSelector());
|
||||
File newConfigDir = new File(newConfigPath);
|
||||
File oldConfigDir = findOldConfigDir(newConfigDir, settings.getCustomPathsSelector());
|
||||
do {
|
||||
ImportOldConfigsPanel dialog = new ImportOldConfigsPanel(oldConfigDir, settings);
|
||||
dialog.setModalityType(Dialog.ModalityType.TOOLKIT_MODAL);
|
||||
AppUIUtil.updateWindowIcon(dialog);
|
||||
dialog.setVisible(true);
|
||||
if (dialog.isImportEnabled()) {
|
||||
File instHome = dialog.getSelectedFile();
|
||||
oldConfigDir = getOldConfigDir(instHome, settings);
|
||||
if (!validateOldConfigDir(instHome, oldConfigDir, settings)) continue;
|
||||
File installationHome = dialog.getSelectedFile();
|
||||
oldConfigDir = getOldConfigDir(installationHome, settings);
|
||||
if (!validateOldConfigDir(installationHome, oldConfigDir, settings)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
doImport(newConfigPath, oldConfigDir);
|
||||
assert oldConfigDir != null;
|
||||
doImport(newConfigDir, oldConfigDir);
|
||||
settings.importFinished(newConfigPath);
|
||||
System.setProperty(CONFIG_IMPORTED_IN_CURRENT_SESSION_KEY, Boolean.TRUE.toString());
|
||||
}
|
||||
@@ -79,38 +84,30 @@ public class ConfigImportHelper {
|
||||
while (true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static ConfigImportSettings getConfigImportSettings() {
|
||||
try {
|
||||
Class customProviderClass =
|
||||
Class.forName("com.intellij.openapi.application." + PlatformUtils.getPlatformPrefix() + "ConfigImportSettings");
|
||||
if (customProviderClass != null) {
|
||||
if (ConfigImportSettings.class.isAssignableFrom(customProviderClass)) {
|
||||
Constructor constructor = customProviderClass.getDeclaredConstructor();
|
||||
if (constructor != null) {
|
||||
return (ConfigImportSettings)constructor.newInstance();
|
||||
}
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<ConfigImportSettings> customProviderClass =
|
||||
(Class<ConfigImportSettings>)Class.forName("com.intellij.openapi.application." + PlatformUtils.getPlatformPrefix() + "ConfigImportSettings");
|
||||
if (ConfigImportSettings.class.isAssignableFrom(customProviderClass)) {
|
||||
return ReflectionUtil.newInstance(customProviderClass);
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
catch (NoSuchMethodException ignored) {
|
||||
}
|
||||
catch (InvocationTargetException ignored) {
|
||||
}
|
||||
catch (InstantiationException ignored) {
|
||||
}
|
||||
catch (IllegalAccessException ignored) {
|
||||
catch (RuntimeException ignored) {
|
||||
}
|
||||
return new ConfigImportSettings();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static File findOldConfigDir(String newConfigPath, @Nullable String customPathSelector) {
|
||||
final File configDir = new File(newConfigPath);
|
||||
final File selectorDir = CONFIG_RELATED_PATH.length() == 0 ? configDir : configDir.getParentFile();
|
||||
private static File findOldConfigDir(@NotNull File configDir, @Nullable String customPathSelector) {
|
||||
final File selectorDir = CONFIG_RELATED_PATH.isEmpty() ? configDir : configDir.getParentFile();
|
||||
final File parent = selectorDir.getParentFile();
|
||||
if (parent == null || !parent.exists()) return null;
|
||||
if (parent == null || !parent.exists()) {
|
||||
return null;
|
||||
}
|
||||
File maxFile = null;
|
||||
long lastModified = 0;
|
||||
final String selector = PathManager.getPathsSelector() != null ? PathManager.getPathsSelector() : selectorDir.getName();
|
||||
@@ -119,14 +116,17 @@ public class ConfigImportHelper {
|
||||
final String customPrefix = customPathSelector != null ? getPrefixFromSelector(customPathSelector) : null;
|
||||
for (File file : parent.listFiles(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File file, String name) {
|
||||
public boolean accept(@NotNull File file, @NotNull String name) {
|
||||
return StringUtil.startsWithIgnoreCase(name, prefix) ||
|
||||
customPrefix != null && StringUtil.startsWithIgnoreCase(name, customPrefix);
|
||||
}
|
||||
})) {
|
||||
final File options = new File(file, CONFIG_RELATED_PATH + OPTIONS_XML);
|
||||
if (!options.exists()) continue;
|
||||
final long modified = options.lastModified();
|
||||
File options = new File(file, CONFIG_RELATED_PATH + OPTIONS_XML);
|
||||
if (!options.exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
long modified = options.lastModified();
|
||||
if (modified > lastModified) {
|
||||
lastModified = modified;
|
||||
maxFile = file;
|
||||
@@ -139,9 +139,9 @@ public class ConfigImportHelper {
|
||||
return (SystemInfo.isMac ? "" : ".") + selector.replaceAll("\\d", "");
|
||||
}
|
||||
|
||||
public static void doImport(final String newConfigPath, final File oldConfigDir) {
|
||||
private static void doImport(@NotNull File newConfigDir, @NotNull File oldConfigDir) {
|
||||
try {
|
||||
xcopy(oldConfigDir, new File(newConfigPath));
|
||||
copy(oldConfigDir, newConfigDir);
|
||||
}
|
||||
catch (IOException e) {
|
||||
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
|
||||
@@ -150,14 +150,12 @@ public class ConfigImportHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean validateOldConfigDir(final File instHome, final File oldConfigDir, ConfigImportSettings settings) {
|
||||
private static boolean validateOldConfigDir(@Nullable File installationHome, @Nullable File oldConfigDir, @NotNull ConfigImportSettings settings) {
|
||||
if (oldConfigDir == null) {
|
||||
final String message = !instHome.equals(oldConfigDir) ?
|
||||
ApplicationBundle.message("error.invalid.installation.home", instHome.getAbsolutePath(),
|
||||
settings.getProductName(ThreeState.YES)) :
|
||||
ApplicationBundle.message("error.invalid.config.folder", instHome.getAbsolutePath(),
|
||||
settings.getProductName(ThreeState.YES));
|
||||
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), message);
|
||||
if (installationHome != null) {
|
||||
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
|
||||
ApplicationBundle.message("error.invalid.installation.home", installationHome.getAbsolutePath(), settings.getProductName(ThreeState.YES)));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -171,7 +169,7 @@ public class ConfigImportHelper {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void xcopy(File src, File dest) throws IOException {
|
||||
private static void copy(@NotNull File src, @NotNull File dest) throws IOException {
|
||||
src = src.getCanonicalFile();
|
||||
dest = dest.getCanonicalFile();
|
||||
if (!src.isDirectory()) {
|
||||
@@ -184,32 +182,53 @@ public class ConfigImportHelper {
|
||||
return;
|
||||
}
|
||||
|
||||
FileUtil.copyDir(src, dest);
|
||||
FileUtil.ensureExists(dest);
|
||||
|
||||
// Delete plugins just imported. They're most probably incompatible with newer idea version.
|
||||
File plugins = new File(dest, PLUGINS_PATH);
|
||||
File[] childFiles = src.listFiles(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(@NotNull File dir, @NotNull String name) {
|
||||
// Don't copy plugins just imported. They're most probably incompatible with newer idea version.
|
||||
return !StringUtil.startsWithChar(name, '.') && !name.equals(PLUGINS_PATH);
|
||||
}
|
||||
});
|
||||
|
||||
if (childFiles == null || childFiles.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (File from : childFiles) {
|
||||
File to = new File(dest, from.getName());
|
||||
if (from.isDirectory()) {
|
||||
FileUtil.copyDir(from, to, false);
|
||||
}
|
||||
else {
|
||||
FileUtil.copy(from, to);
|
||||
}
|
||||
}
|
||||
|
||||
File plugins = new File(src, PLUGINS_PATH);
|
||||
if (plugins.exists()) {
|
||||
final ArrayList<IdeaPluginDescriptorImpl> descriptors = new ArrayList<IdeaPluginDescriptorImpl>();
|
||||
PluginManager.loadDescriptors(plugins.getPath(), descriptors, null, 0);
|
||||
final ArrayList<String> oldPlugins = new ArrayList<String>();
|
||||
List<IdeaPluginDescriptorImpl> descriptors = new SmartList<IdeaPluginDescriptorImpl>();
|
||||
PluginManagerCore.loadDescriptors(plugins, descriptors, null, 0);
|
||||
List<String> oldPlugins = new SmartList<String>();
|
||||
for (IdeaPluginDescriptorImpl descriptor : descriptors) {
|
||||
oldPlugins.add(descriptor.getPluginId().getIdString());
|
||||
// check isBundled also - probably plugin is bundled in new IDE version
|
||||
if (descriptor.isEnabled() && !descriptor.isBundled()) {
|
||||
oldPlugins.add(descriptor.getPluginId().getIdString());
|
||||
}
|
||||
}
|
||||
if (!oldPlugins.isEmpty()) {
|
||||
PluginManager.savePluginsList(oldPlugins, false, new File(dest, PluginManager.INSTALLED_TXT));
|
||||
PluginManagerCore.savePluginsList(oldPlugins, false, new File(dest, PluginManager.INSTALLED_TXT));
|
||||
}
|
||||
FileUtil.delete(plugins);
|
||||
}
|
||||
|
||||
File pluginsSettings = new File(new File(dest, "options"), "plugin_ui.xml");
|
||||
if (pluginsSettings.exists()) {
|
||||
FileUtil.delete(pluginsSettings);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static File getOldConfigDir(File oldInstallHome, ConfigImportSettings settings) {
|
||||
if (oldInstallHome == null) return null;
|
||||
public static File getOldConfigDir(@Nullable File oldInstallHome, ConfigImportSettings settings) {
|
||||
if (oldInstallHome == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// check if it's already config dir
|
||||
if (new File(oldInstallHome, OPTIONS_XML).exists()) {
|
||||
return oldInstallHome;
|
||||
@@ -299,8 +318,8 @@ public class ConfigImportHelper {
|
||||
@NotNull final String propertyName) {
|
||||
if (file.getName().endsWith(".properties")) {
|
||||
try {
|
||||
InputStream fis = new BufferedInputStream(new FileInputStream(file));
|
||||
PropertyResourceBundle bundle;
|
||||
InputStream fis = new BufferedInputStream(new FileInputStream(file));
|
||||
try {
|
||||
bundle = new PropertyResourceBundle(fis);
|
||||
}
|
||||
@@ -374,7 +393,7 @@ public class ConfigImportHelper {
|
||||
@Nullable
|
||||
private static String getContent(File file) {
|
||||
try {
|
||||
StringBuffer content = new StringBuffer();
|
||||
StringBuilder content = new StringBuilder();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
|
||||
try {
|
||||
do {
|
||||
|
||||
+17
-6
@@ -358,8 +358,10 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
for (final StandardFileType pair : myStandardFileTypes.values()) {
|
||||
registerFileTypeWithoutNotification(pair.fileType, pair.matchers);
|
||||
}
|
||||
for (StandardFileType pair : myStandardFileTypes.values()) {
|
||||
registerReDetectedMappings(pair);
|
||||
if (!myUnresolvedMappings.isEmpty()) {
|
||||
for (StandardFileType pair : myStandardFileTypes.values()) {
|
||||
registerReDetectedMappings(pair);
|
||||
}
|
||||
}
|
||||
// Resolve unresolved mappings initialized before certain plugin initialized.
|
||||
for (final StandardFileType pair : myStandardFileTypes.values()) {
|
||||
@@ -1297,14 +1299,23 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
|
||||
FileType fileType = pair.fileType;
|
||||
if (fileType == PlainTextFileType.INSTANCE) return;
|
||||
for (FileNameMatcher matcher : pair.matchers) {
|
||||
String typeName = myUnresolvedMappings.get(matcher);
|
||||
if (typeName != null && !typeName.equals(fileType.getName())) {
|
||||
Trinity<String, String, Boolean> trinity = myUnresolvedRemovedMappings.get(matcher);
|
||||
myRemovedMappings.put(matcher, Pair.create(fileType, trinity != null && trinity.third));
|
||||
registerReDetectedMapping(fileType, matcher);
|
||||
if (matcher instanceof ExtensionFileNameMatcher) {
|
||||
// also check exact file name matcher
|
||||
ExtensionFileNameMatcher extMatcher = (ExtensionFileNameMatcher)matcher;
|
||||
registerReDetectedMapping(fileType, new ExactFileNameMatcher("." + extMatcher.getExtension()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void registerReDetectedMapping(@NotNull FileType fileType, @NotNull FileNameMatcher matcher) {
|
||||
String typeName = myUnresolvedMappings.get(matcher);
|
||||
if (typeName != null && !typeName.equals(fileType.getName())) {
|
||||
Trinity<String, String, Boolean> trinity = myUnresolvedRemovedMappings.get(matcher);
|
||||
myRemovedMappings.put(matcher, Pair.create(fileType, trinity != null && trinity.third));
|
||||
}
|
||||
}
|
||||
|
||||
Map<FileNameMatcher, Pair<FileType, Boolean>> getRemovedMappings() {
|
||||
return myRemovedMappings;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -33,19 +33,17 @@ public class Product {
|
||||
private final Set<String> myCodes;
|
||||
private final List<UpdateChannel> myChannels;
|
||||
|
||||
public Product(Element node) {
|
||||
public Product(@NotNull Element node) {
|
||||
myName = node.getAttributeValue("name");
|
||||
myCodes = new LinkedHashSet<String>();
|
||||
myChannels = new ArrayList<UpdateChannel>();
|
||||
|
||||
List codes = node.getChildren("code");
|
||||
for (Object code : codes) {
|
||||
myCodes.add(((Element)code).getValue());
|
||||
for (Element code : node.getChildren("code")) {
|
||||
myCodes.add(code.getValue());
|
||||
}
|
||||
|
||||
List channels = node.getChildren("channel");
|
||||
for (Object channel : channels) {
|
||||
myChannels.add(new UpdateChannel((Element)channel));
|
||||
for (Element channel : node.getChildren("channel")) {
|
||||
myChannels.add(new UpdateChannel(channel));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +54,9 @@ public class Product {
|
||||
@Nullable
|
||||
public UpdateChannel findUpdateChannelById(String id) {
|
||||
for (UpdateChannel channel : myChannels) {
|
||||
if (id.equals(channel.getId())) return channel;
|
||||
if (id.equals(channel.getId())) {
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
+6
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -20,6 +20,7 @@
|
||||
package com.intellij.openapi.updateSettings.impl;
|
||||
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -39,12 +40,11 @@ public class UpdateChannel {
|
||||
public static final String LICENSING_EAP = "eap";
|
||||
public static final String LICENSING_PRODUCTION = "production";
|
||||
|
||||
public UpdateChannel(Element node) {
|
||||
public UpdateChannel(@NotNull Element node) {
|
||||
myId = node.getAttributeValue("id");
|
||||
myName = node.getAttributeValue("name");
|
||||
myStatus = ChannelStatus.fromCode(node.getAttributeValue("status"));
|
||||
String licensing = node.getAttributeValue("licensing");
|
||||
myLicensing = licensing != null ? licensing : LICENSING_PRODUCTION;
|
||||
myLicensing = node.getAttributeValue("licensing", LICENSING_PRODUCTION);
|
||||
|
||||
String majorVersion = node.getAttributeValue("majorVersion");
|
||||
myMajorVersion = majorVersion != null ? Integer.parseInt(majorVersion) : -1;
|
||||
@@ -56,8 +56,8 @@ public class UpdateChannel {
|
||||
myFeedbackUrl = node.getAttributeValue("feedback");
|
||||
|
||||
myBuilds = new ArrayList<BuildInfo>();
|
||||
for (Object child : node.getChildren("build")) {
|
||||
myBuilds.add(new BuildInfo((Element)child));
|
||||
for (Element child : node.getChildren("build")) {
|
||||
myBuilds.add(new BuildInfo(child));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,6 @@ public class UpdateChannel {
|
||||
build = info;
|
||||
}
|
||||
}
|
||||
|
||||
return build;
|
||||
}
|
||||
|
||||
|
||||
+13
-15
@@ -93,7 +93,7 @@ public final class UpdateChecker {
|
||||
@NonNls private static final String DISABLED_UPDATE = "disabled_update.txt";
|
||||
|
||||
private static Set<String> ourDisabledToUpdatePlugins;
|
||||
private static Map<String, String> ourAdditionalRequestOptions = new HashMap<String, String>();
|
||||
private static final Map<String, String> ourAdditionalRequestOptions = new HashMap<String, String>();
|
||||
|
||||
private static class Holder {
|
||||
private static final String UPDATE_URL = ApplicationInfoEx.getInstanceEx().getUpdateUrls().getCheckingUrl();
|
||||
@@ -464,8 +464,7 @@ public final class UpdateChecker {
|
||||
private static CheckForUpdateResult checkForUpdates(final UpdateSettings settings) {
|
||||
UpdatesInfo info;
|
||||
try {
|
||||
UpdatesXmlLoader loader = new UpdatesXmlLoader(getUpdateUrl());
|
||||
info = loader.loadUpdatesInfo();
|
||||
info = UpdatesXmlLoader.loadUpdatesInfo(getUpdateUrl());
|
||||
if (info == null) {
|
||||
return new CheckForUpdateResult(UpdateStrategy.State.NOTHING_LOADED);
|
||||
}
|
||||
@@ -660,14 +659,12 @@ public final class UpdateChecker {
|
||||
return uid;
|
||||
}
|
||||
}
|
||||
String uid;
|
||||
if (!propertiesComponent.isValueSet(INSTALLATION_UID)) {
|
||||
|
||||
String uid = propertiesComponent.getValue(INSTALLATION_UID);
|
||||
if (uid == null) {
|
||||
uid = generateUUID();
|
||||
propertiesComponent.setValue(INSTALLATION_UID, uid);
|
||||
}
|
||||
else {
|
||||
uid = propertiesComponent.getValue(INSTALLATION_UID);
|
||||
}
|
||||
return uid;
|
||||
}
|
||||
|
||||
@@ -683,11 +680,8 @@ public final class UpdateChecker {
|
||||
return FileUtil.loadFile(permanentIdFile).trim();
|
||||
}
|
||||
|
||||
String uuid;
|
||||
if (propertiesComponent.isValueSet(INSTALLATION_UID)) {
|
||||
uuid = propertiesComponent.getValue(INSTALLATION_UID);
|
||||
}
|
||||
else {
|
||||
String uuid = propertiesComponent.getValue(INSTALLATION_UID);
|
||||
if (uuid == null) {
|
||||
uuid = generateUUID();
|
||||
}
|
||||
FileUtil.writeToFile(permanentIdFile, uuid);
|
||||
@@ -764,7 +758,11 @@ public final class UpdateChecker {
|
||||
|
||||
String fromBuildNumber = patch.getFromBuild().asStringWithoutProductCode();
|
||||
String toBuildNumber = newVersion.getNumber().asStringWithoutProductCode();
|
||||
String bundledJdk = "jdk-bundled".equals(System.getProperty("idea.java.redist")) ? "-jdk-bundled" : "";
|
||||
String jdkMacRedist = System.getProperty("idea.java.redist");
|
||||
String bundledJdk = "";
|
||||
if (jdkMacRedist.lastIndexOf("jdk-bundled") >= 0 ){
|
||||
bundledJdk = "jdk-bundled".equals(jdkMacRedist) ? "-jdk-bundled" : "-custom-jdk-bundled";
|
||||
}
|
||||
|
||||
String fileName = productCode + "-" + fromBuildNumber + "-" + toBuildNumber + "-patch" + bundledJdk + osSuffix + ".jar";
|
||||
|
||||
@@ -812,7 +810,7 @@ public final class UpdateChecker {
|
||||
out.close();
|
||||
}
|
||||
|
||||
String patchFileName = ("jetbrains.patch.jar." + platform).toLowerCase();
|
||||
String patchFileName = ("jetbrains.patch.jar." + platform).toLowerCase(Locale.ENGLISH);
|
||||
File patchFile = new File(FileUtil.getTempDirectory(), patchFileName);
|
||||
FileUtil.copy(tempFile, patchFile);
|
||||
FileUtil.delete(tempFile);
|
||||
|
||||
+4
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.openapi.updateSettings.impl;
|
||||
|
||||
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -26,11 +25,10 @@ import java.util.List;
|
||||
public class UpdatesInfo {
|
||||
@NotNull private final List<Product> myProducts;
|
||||
|
||||
public UpdatesInfo(Element element) {
|
||||
public UpdatesInfo(@NotNull Element element) {
|
||||
myProducts = new ArrayList<Product>();
|
||||
List children = element.getChildren();
|
||||
for (Object child : children) {
|
||||
myProducts.add(new Product((Element) child));
|
||||
for (Element child : element.getChildren()) {
|
||||
myProducts.add(new Product(child));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+28
-67
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -25,33 +25,19 @@ import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.net.HttpConfigurable;
|
||||
import org.jdom.JDOMException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
public class UpdatesXmlLoader {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.updateSettings.impl.UpdatesXmlLoader");
|
||||
|
||||
private final String updateUrl;
|
||||
|
||||
public UpdatesXmlLoader(final String updatesUrl) {
|
||||
this.updateUrl = updatesUrl;
|
||||
}
|
||||
import java.util.concurrent.*;
|
||||
|
||||
class UpdatesXmlLoader {
|
||||
private static final Logger LOG = Logger.getInstance(UpdatesXmlLoader.class);
|
||||
|
||||
@Nullable
|
||||
public UpdatesInfo loadUpdatesInfo() throws ConnectionException{
|
||||
LOG.debug("load update xml (UPDATE_URL='" + updateUrl + "' )");
|
||||
public static UpdatesInfo loadUpdatesInfo(@Nullable final String updateUrl) throws ConnectionException {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("load update xml (UPDATE_URL='" + updateUrl + "' )");
|
||||
}
|
||||
|
||||
if (StringUtil.isEmpty(updateUrl)) {
|
||||
LOG.debug("update url is empty: updates will not be checked");
|
||||
@@ -59,20 +45,13 @@ public class UpdatesXmlLoader {
|
||||
}
|
||||
|
||||
final Ref<Exception> error = new Ref<Exception>();
|
||||
FutureTask<UpdatesInfo> ft = new FutureTask<UpdatesInfo>(new Callable<UpdatesInfo>() {
|
||||
Future<UpdatesInfo> future = ApplicationManager.getApplication().executeOnPooledThread(new Callable<UpdatesInfo>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public UpdatesInfo call() throws Exception {
|
||||
try {
|
||||
prepareUrl(updateUrl);
|
||||
|
||||
URL requestUrl = prepareRequestUrl(updateUrl);
|
||||
|
||||
URLConnection connection = requestUrl.openConnection();
|
||||
connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
|
||||
connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
|
||||
final InputStream inputStream = connection.getInputStream();
|
||||
Reader reader = new InputStreamReader(inputStream);
|
||||
String url = updateUrl.startsWith("file:") ? updateUrl : updateUrl + '?' + UpdateChecker.prepareUpdateCheckArgs();
|
||||
InputStream inputStream = HttpConfigurable.getInstance().openConnection(url).getInputStream();
|
||||
try {
|
||||
return new UpdatesInfo(JDOMUtil.loadDocument(inputStream).getRootElement());
|
||||
}
|
||||
@@ -80,59 +59,41 @@ public class UpdatesXmlLoader {
|
||||
LOG.info(e); // Broken xml downloaded. Don't bother telling user.
|
||||
}
|
||||
finally {
|
||||
reader.close();
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.debug(e);
|
||||
error.set(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
ApplicationManager.getApplication().executeOnPooledThread(ft);
|
||||
|
||||
UpdatesInfo result = null;
|
||||
try {
|
||||
UpdatesInfo result = ft.get(5, TimeUnit.SECONDS);
|
||||
if (!error.isNull()) {
|
||||
//noinspection ThrowableResultOfMethodCallIgnored
|
||||
throw new ConnectionException(error.get());
|
||||
}
|
||||
return result;
|
||||
result = future.get(5, TimeUnit.SECONDS);
|
||||
}
|
||||
catch (TimeoutException e) {
|
||||
// ignore
|
||||
catch (TimeoutException ignored) {
|
||||
}
|
||||
catch (Exception e) {
|
||||
catch (InterruptedException e) {
|
||||
LOG.debug(e);
|
||||
throw new ConnectionException(e.getMessage(),e);
|
||||
error.set(e);
|
||||
}
|
||||
if (!ft.isDone()) {
|
||||
ft.cancel(true);
|
||||
throw new ConnectionException(IdeBundle.message("updates.timeout.error"));
|
||||
catch (ExecutionException e) {
|
||||
LOG.debug(e);
|
||||
error.set(e);
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected static void prepareUrl(@NotNull String url) throws ConnectionException {
|
||||
try {
|
||||
HttpConfigurable.getInstance().prepareURL(url);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new ConnectionException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected URL prepareRequestUrl(@NotNull String url) throws ConnectionException {
|
||||
try {
|
||||
if (url.startsWith("file:")) {
|
||||
return new URL(url);
|
||||
if (!future.isDone()) {
|
||||
future.cancel(true);
|
||||
if (error.isNull()) {
|
||||
throw new ConnectionException(IdeBundle.message("updates.timeout.error"));
|
||||
}
|
||||
return new URL(url + "?" + UpdateChecker.prepareUpdateCheckArgs());
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new ConnectionException(e);
|
||||
if (!error.isNull()) {
|
||||
throw new ConnectionException(error.get());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -245,6 +245,7 @@ public class PluginsAdvertiser implements StartupActivity {
|
||||
final KnownExtensions extensions = loadExtensions();
|
||||
if (extensions != null && unknownFeatures.isEmpty()) return;
|
||||
final Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Application application = ApplicationManager.getApplication();
|
||||
if (application.isUnitTestMode() || application.isHeadlessEnvironment()) return;
|
||||
@@ -252,9 +253,10 @@ public class PluginsAdvertiser implements StartupActivity {
|
||||
private final Set<PluginDownloader> myPlugins = new HashSet<PluginDownloader>();
|
||||
private List<IdeaPluginDescriptor> myAllPlugins;
|
||||
|
||||
private Map<Plugin, IdeaPluginDescriptor> myDisabledPlugins = new HashMap<Plugin, IdeaPluginDescriptor>();
|
||||
private final Map<Plugin, IdeaPluginDescriptor> myDisabledPlugins = new HashMap<Plugin, IdeaPluginDescriptor>();
|
||||
private List<String> myBundledPlugin;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
myAllPlugins = RepositoryHelper.loadPluginsFromRepository(null);
|
||||
@@ -349,6 +351,7 @@ public class PluginsAdvertiser implements StartupActivity {
|
||||
@MapAnnotation(surroundWithTag = false, surroundKeyWithTag = false, surroundValueWithTag = false)
|
||||
public Map<String, PluginSet> myExtensions = new HashMap<String, PluginSet>();
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public KnownExtensions() {
|
||||
}
|
||||
|
||||
@@ -371,6 +374,7 @@ public class PluginsAdvertiser implements StartupActivity {
|
||||
public static class PluginSet {
|
||||
public Set<Plugin> myPlugins = new HashSet<Plugin>();
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public PluginSet() {
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -28,7 +28,6 @@ import com.intellij.openapi.updateSettings.impl.UpdateChecker;
|
||||
import com.intellij.openapi.updateSettings.impl.UpdateSettings;
|
||||
import com.intellij.openapi.util.DimensionService;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.wm.WelcomeScreen;
|
||||
import com.intellij.ui.ScreenUtil;
|
||||
import com.intellij.ui.components.labels.LinkLabel;
|
||||
@@ -150,7 +149,7 @@ public class NewWelcomeScreen extends JPanel implements WelcomeScreen {
|
||||
}
|
||||
|
||||
public static boolean isNewWelcomeScreen(@NotNull AnActionEvent e) {
|
||||
return e.getPlace() == ActionPlaces.WELCOME_SCREEN && Registry.is("ide.new.welcome.screen");
|
||||
return e.getPlace() == ActionPlaces.WELCOME_SCREEN && FlatWelcomeFrameProvider.isAvailable();
|
||||
}
|
||||
|
||||
private static class WelcomeScreenGroup extends DefaultActionGroup {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
error.invalid.installation.home=Unable to import settings. ''{0}'' doesn''t appear to be valid {1} installation home.
|
||||
error.invalid.config.folder=Unable to import settings. ''{0}'' doesn''t appear to be valid {1} config folder.
|
||||
error.no.settings.path=Unable to import settings. {0} does not exist.
|
||||
title.settings.import.failed=Settings Import Failed
|
||||
error.unable.to.import.settings=Unable to import settings. {0}
|
||||
|
||||
@@ -116,8 +116,8 @@
|
||||
<lang.syntaxHighlighterFactory key="XHTML" implementationClass="com.intellij.lang.xhtml.XhtmlSyntaxHighlighterFactory"/>
|
||||
<lang.syntaxHighlighterFactory key="DTD" implementationClass="com.intellij.lang.dtd.DtdSyntaxHighlighterFactory"/>
|
||||
|
||||
<annotator language="XML" implementationClass="com.intellij.codeInsight.daemon.impl.analysis.XmlNamespaceAnnotator"/>
|
||||
<annotator language="XML" implementationClass="com.intellij.codeInsight.daemon.impl.analysis.XmlNsPrefixAnnotator"/>
|
||||
<annotator language="XML" implementationClass="com.intellij.codeInsight.daemon.impl.analysis.XmlNamespaceAnnotator"/>
|
||||
|
||||
<renameHandler id="xmlTagRenameHandler" implementation="com.intellij.xml.refactoring.XmlTagRenameHandler"/>
|
||||
<renameHandler implementation="com.intellij.xml.refactoring.SchemaPrefixRenameHandler" order="before xmlTagRenameHandler"/>
|
||||
|
||||
@@ -583,8 +583,8 @@
|
||||
<group id="ChangeScheme">
|
||||
<action id="ChangeColorScheme" class="com.intellij.ide.actions.QuickChangeColorSchemeAction"/>
|
||||
<action id="ChangeKeymap" class="com.intellij.ide.actions.QuickChangeKeymapAction"/>
|
||||
<action id="ChangeLaf" class="com.intellij.ide.actions.QuickChangeLookAndFeel"/>
|
||||
<action id="ChangeView" class="com.intellij.ide.actions.QuickChangeViewModeAction"/>
|
||||
<action id="ChangeLaf" class="com.intellij.ide.actions.QuickChangeLookAndFeel"/>
|
||||
</group>
|
||||
|
||||
<action id="MaintenanceAction" class="com.intellij.ide.actions.MaintenanceAction"/>
|
||||
|
||||
@@ -38,14 +38,16 @@
|
||||
|
||||
<actions>
|
||||
<group id="RemoteServersViewToolbar">
|
||||
<action id="RemoteServers.RunServer" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.RunServerAction"/>
|
||||
<action id="RemoteServers.DebugServer" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.DebugServerAction"/>
|
||||
<action id="RemoteServers.StopServer" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.StopServerAction"/>
|
||||
<action id="RemoteServers.EditServer" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.EditConfigurationAction"/>
|
||||
<separator/>
|
||||
<action id="RemoteServers.DeployAll" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.DeployAllAction"/>
|
||||
<action id="RemoteServers.ConnectServer" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.RemoteServerConnectAction"/>
|
||||
<action id="RemoteServers.DisconnectServer" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.RemoteServerDisconnectAction"/>
|
||||
<action id="RemoteServers.EditServerConfig" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.RemoteServerConfigAction"/>
|
||||
<action id="RemoteServers.ChooseServerDeployment" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.ChooseDeploymentAction"/>
|
||||
<action id="RemoteServers.ChooseServerDeploymentWithDebug" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.ChooseDeploymentWithDebugAction"/>
|
||||
|
||||
<action id="Servers.Deploy" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.DeployAction"/>
|
||||
<action id="Servers.Undeploy" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.UndeployAction"/>
|
||||
<action id="Servers.DeployWithDebug" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.DeployWithDebugAction"/>
|
||||
<action id="RemoteServers.EditDeploymentConfig" class="com.intellij.remoteServer.impl.runtime.ui.tree.actions.DeploymentConfigAction"/>
|
||||
</group>
|
||||
</actions>
|
||||
</idea-plugin>
|
||||
+6
-23
@@ -6,18 +6,16 @@ import com.intellij.ide.util.treeView.AbstractTreeNode;
|
||||
import com.intellij.ide.util.treeView.NodeDescriptor;
|
||||
import com.intellij.ide.util.treeView.NodeRenderer;
|
||||
import com.intellij.ide.util.treeView.TreeVisitor;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Splitter;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.remoteServer.configuration.RemoteServer;
|
||||
import com.intellij.remoteServer.impl.runtime.log.LoggingHandlerImpl;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.DeploymentNode;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServerNode;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.TreeBuilderBase;
|
||||
import com.intellij.remoteServer.runtime.ConnectionStatus;
|
||||
import com.intellij.remoteServer.runtime.ServerConnection;
|
||||
@@ -108,13 +106,10 @@ public class ServersToolWindowContent extends JPanel implements Disposable {
|
||||
new DoubleClickListener() {
|
||||
@Override
|
||||
protected boolean onDoubleClick(MouseEvent event) {
|
||||
Set<ServersTreeStructure.RemoteServerNode> nodes = getSelectedRemoteServerNodes();
|
||||
if (nodes.size() == 1) {
|
||||
RemoteServer<?> server = nodes.iterator().next().getValue();
|
||||
ServerConnectionManager.getInstance().getOrCreateConnection(server);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
AnAction connectAction = ActionManager.getInstance().getAction("RemoteServers.ConnectServer");
|
||||
AnActionEvent actionEvent = AnActionEvent.createFromInputEvent(connectAction, event, ActionPlaces.UNKNOWN);
|
||||
connectAction.actionPerformed(actionEvent);
|
||||
return true;
|
||||
}
|
||||
}.installOn(myTree);
|
||||
}
|
||||
@@ -265,18 +260,6 @@ public class ServersToolWindowContent extends JPanel implements Disposable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Set<ServerNode> getSelectedServerNodes() {
|
||||
return myBuilder.getSelectedElements(ServerNode.class);
|
||||
}
|
||||
|
||||
public Set<DeploymentNode> getSelectedDeploymentNodes() {
|
||||
return myBuilder.getSelectedElements(DeploymentNode.class);
|
||||
}
|
||||
|
||||
public Set<ServersTreeStructure.RemoteServerNode> getSelectedRemoteServerNodes() {
|
||||
return myBuilder.getSelectedElements(ServersTreeStructure.RemoteServerNode.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
+11
-5
@@ -5,18 +5,24 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public interface DeploymentNode {
|
||||
public interface DeploymentNode extends ServersTreeNode {
|
||||
|
||||
@NotNull
|
||||
ServerNode getServerNode();
|
||||
|
||||
boolean isRedeployActionEnabled();
|
||||
void redeploy();
|
||||
boolean isDeployActionVisible();
|
||||
|
||||
boolean isDeployActionEnabled();
|
||||
|
||||
void deploy();
|
||||
|
||||
boolean isUndeployActionEnabled();
|
||||
|
||||
void undeploy();
|
||||
|
||||
boolean isEditConfigurationActionEnabled();
|
||||
void editConfiguration();
|
||||
boolean isDebugActionVisible();
|
||||
|
||||
void deployWithDebug();
|
||||
|
||||
boolean isDeployed();
|
||||
|
||||
|
||||
+1
-18
@@ -1,26 +1,9 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree;
|
||||
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public interface ServerNode {
|
||||
boolean isConnected();
|
||||
|
||||
boolean isStopActionEnabled();
|
||||
void stopServer();
|
||||
public interface ServerNode extends ServersTreeNode {
|
||||
|
||||
boolean isStartActionEnabled(@NotNull Executor executor);
|
||||
void startServer(@NotNull Executor executor);
|
||||
|
||||
boolean isDeployActionEnabled();
|
||||
void deploy(AnActionEvent e);
|
||||
|
||||
boolean isDeployAllActionEnabled();
|
||||
void deployAll();
|
||||
|
||||
void editConfiguration();
|
||||
}
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree;
|
||||
|
||||
public interface ServersTreeNode {
|
||||
|
||||
}
|
||||
+77
-75
@@ -3,6 +3,7 @@ package com.intellij.remoteServer.impl.runtime.ui.tree;
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.execution.ProgramRunnerUtil;
|
||||
import com.intellij.execution.RunnerAndConfigurationSettings;
|
||||
import com.intellij.execution.executors.DefaultDebugExecutor;
|
||||
import com.intellij.execution.executors.DefaultRunExecutor;
|
||||
import com.intellij.execution.impl.RunDialog;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
@@ -18,13 +19,16 @@ import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.ListPopup;
|
||||
import com.intellij.openapi.ui.popup.PopupStep;
|
||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.remoteServer.ServerType;
|
||||
import com.intellij.remoteServer.configuration.RemoteServer;
|
||||
import com.intellij.remoteServer.configuration.RemoteServersManager;
|
||||
import com.intellij.remoteServer.configuration.ServerConfiguration;
|
||||
import com.intellij.remoteServer.configuration.deployment.DeploymentConfigurationManager;
|
||||
import com.intellij.remoteServer.impl.configuration.SingleRemoteServerConfigurable;
|
||||
import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerRunConfiguration;
|
||||
import com.intellij.remoteServer.impl.runtime.deployment.DeploymentTaskImpl;
|
||||
import com.intellij.remoteServer.impl.runtime.log.DeploymentLogManagerImpl;
|
||||
import com.intellij.remoteServer.impl.runtime.log.LoggingHandlerImpl;
|
||||
@@ -38,6 +42,7 @@ import com.intellij.remoteServer.runtime.deployment.DeploymentStatus;
|
||||
import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
|
||||
import com.intellij.ui.LayeredIcon;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import icons.RemoteServersIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -160,50 +165,65 @@ public class ServersTreeStructure extends AbstractTreeStructureBase {
|
||||
return ServerConnectionManager.getInstance().getConnection(getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
ServerConnection<?> connection = getConnection();
|
||||
return connection != null && connection.getStatus() == ConnectionStatus.CONNECTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeployActionEnabled() {
|
||||
return true;
|
||||
public void deploy(AnActionEvent e) {
|
||||
doDeploy(e, DefaultRunExecutor.getRunExecutorInstance(), "Deploy Configuration", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deploy(AnActionEvent e) {
|
||||
final ServerType<? extends ServerConfiguration> serverType = getValue().getType();
|
||||
public void deployWithDebug(AnActionEvent e) {
|
||||
doDeploy(e, DefaultDebugExecutor.getDebugExecutorInstance(), "Deploy and Debug Configuration", false);
|
||||
}
|
||||
|
||||
public void doDeploy(AnActionEvent e, final Executor executor, String popupTitle, boolean canCreate) {
|
||||
final RemoteServer<?> server = getValue();
|
||||
final ServerType<? extends ServerConfiguration> serverType = server.getType();
|
||||
final DeploymentConfigurationManager configurationManager = DeploymentConfigurationManager.getInstance(doGetProject());
|
||||
List<RunnerAndConfigurationSettings> list = new ArrayList<RunnerAndConfigurationSettings>(configurationManager.getDeploymentConfigurations(serverType));
|
||||
list.add(null);
|
||||
ListPopup popup = JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep<RunnerAndConfigurationSettings>("Deploy Configuration", list) {
|
||||
@Override
|
||||
public Icon getIconFor(RunnerAndConfigurationSettings value) {
|
||||
return value != null ? serverType.getIcon() : null;
|
||||
}
|
||||
List<RunnerAndConfigurationSettings> list
|
||||
= ContainerUtil.filter(configurationManager.getDeploymentConfigurations(serverType),
|
||||
new Condition<RunnerAndConfigurationSettings>() {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getTextFor(RunnerAndConfigurationSettings value) {
|
||||
return value != null ? value.getName() : "Create...";
|
||||
}
|
||||
@Override
|
||||
public boolean value(RunnerAndConfigurationSettings settings) {
|
||||
DeployToServerRunConfiguration configuration =
|
||||
(DeployToServerRunConfiguration)settings.getConfiguration();
|
||||
return StringUtil.equals(server.getName(), configuration.getServerName());
|
||||
}
|
||||
});
|
||||
if (canCreate) {
|
||||
list.add(null);
|
||||
}
|
||||
ListPopup popup =
|
||||
JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep<RunnerAndConfigurationSettings>(popupTitle, list) {
|
||||
@Override
|
||||
public Icon getIconFor(RunnerAndConfigurationSettings value) {
|
||||
return value != null ? serverType.getIcon() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PopupStep onChosen(final RunnerAndConfigurationSettings selectedValue, boolean finalChoice) {
|
||||
return doFinalStep(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (selectedValue != null) {
|
||||
ProgramRunnerUtil.executeConfiguration(doGetProject(), selectedValue, DefaultRunExecutor.getRunExecutorInstance());
|
||||
@NotNull
|
||||
@Override
|
||||
public String getTextFor(RunnerAndConfigurationSettings value) {
|
||||
return value != null ? value.getName() : "Create...";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PopupStep onChosen(final RunnerAndConfigurationSettings selectedValue, boolean finalChoice) {
|
||||
return doFinalStep(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (selectedValue != null) {
|
||||
ProgramRunnerUtil.executeConfiguration(doGetProject(), selectedValue, executor);
|
||||
}
|
||||
else {
|
||||
configurationManager.createAndRunConfiguration(serverType, RemoteServerNode.this.getValue());
|
||||
}
|
||||
}
|
||||
else {
|
||||
configurationManager.createAndRunConfiguration(serverType, RemoteServerNode.this.getValue());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
if (e.getInputEvent() instanceof MouseEvent) {
|
||||
popup.show(new RelativePoint((MouseEvent)e.getInputEvent()));
|
||||
}
|
||||
@@ -212,45 +232,10 @@ public class ServersTreeStructure extends AbstractTreeStructureBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStopActionEnabled() {
|
||||
return isConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopServer() {
|
||||
ServerConnection<?> connection = getConnection();
|
||||
if (connection != null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void editConfiguration() {
|
||||
ShowSettingsUtil.getInstance().editConfigurable(doGetProject(), new SingleRemoteServerConfigurable(getValue(), null, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStartActionEnabled(@NotNull Executor executor) {
|
||||
ServerConnection connection = getConnection();
|
||||
return executor.equals(DefaultRunExecutor.getRunExecutorInstance()) &&
|
||||
(connection == null || connection.getStatus() == ConnectionStatus.DISCONNECTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startServer(@NotNull Executor executor) {
|
||||
ServerConnectionManager.getInstance().getOrCreateConnection(getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeployAllActionEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deployAll() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Icon getStatusIcon(final ConnectionStatus status) {
|
||||
switch (status) {
|
||||
@@ -278,23 +263,42 @@ public class ServersTreeStructure extends AbstractTreeStructureBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRedeployActionEnabled() {
|
||||
public boolean isDeployActionVisible() {
|
||||
DeploymentTask<?> deploymentTask = getValue().getDeploymentTask();
|
||||
return deploymentTask instanceof DeploymentTaskImpl<?> && ((DeploymentTaskImpl)deploymentTask).getExecutionEnvironment().getRunnerAndConfigurationSettings() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void redeploy() {
|
||||
public boolean isDeployActionEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deploy() {
|
||||
doDeploy(DefaultRunExecutor.getRunExecutorInstance());
|
||||
}
|
||||
|
||||
public void doDeploy(Executor executor) {
|
||||
DeploymentTask<?> deploymentTask = getValue().getDeploymentTask();
|
||||
if (deploymentTask != null) {
|
||||
ExecutionEnvironment environment = ((DeploymentTaskImpl)deploymentTask).getExecutionEnvironment();
|
||||
RunnerAndConfigurationSettings settings = environment.getRunnerAndConfigurationSettings();
|
||||
if (settings != null) {
|
||||
ProgramRunnerUtil.executeConfiguration(doGetProject(), settings, DefaultRunExecutor.getRunExecutorInstance());
|
||||
ProgramRunnerUtil.executeConfiguration(doGetProject(), settings, executor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugActionVisible() {
|
||||
return myParentNode.getValue().getType().createDebugConnector() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deployWithDebug() {
|
||||
doDeploy(DefaultDebugExecutor.getDebugExecutorInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUndeployActionEnabled() {
|
||||
DeploymentRuntime runtime = getValue().getRuntime();
|
||||
@@ -309,12 +313,10 @@ public class ServersTreeStructure extends AbstractTreeStructureBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEditConfigurationActionEnabled() {
|
||||
public boolean isEditConfigurationActionVisible() {
|
||||
return getValue().getDeploymentTask() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void editConfiguration() {
|
||||
DeploymentTask<?> task = getValue().getDeploymentTask();
|
||||
if (task != null) {
|
||||
@@ -396,7 +398,7 @@ public class ServersTreeStructure extends AbstractTreeStructureBase {
|
||||
}
|
||||
}
|
||||
|
||||
public class DeploymentLogNode extends AbstractTreeNode<Pair<LoggingHandlerImpl, String>> implements LogProvidingNode {
|
||||
public class DeploymentLogNode extends AbstractTreeNode<Pair<LoggingHandlerImpl, String>> implements ServersTreeNode, LogProvidingNode {
|
||||
@NotNull private final DeploymentNodeImpl myDeploymentNode;
|
||||
|
||||
public DeploymentLogNode(@NotNull Pair<LoggingHandlerImpl, String> value, @NotNull DeploymentNodeImpl deploymentNode) {
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ChooseDeploymentAction extends ServersTreeAction<ServersTreeStructure.RemoteServerNode> {
|
||||
|
||||
public ChooseDeploymentAction() {
|
||||
super("Deploy", "Deploy a chosen item to the selected remote server", AllIcons.Nodes.Deploy);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<ServersTreeStructure.RemoteServerNode> getTargetNodeClass() {
|
||||
return ServersTreeStructure.RemoteServerNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e, ServersTreeStructure.RemoteServerNode node) {
|
||||
node.deploy(e);
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ChooseDeploymentWithDebugAction extends ServersTreeAction<ServersTreeStructure.RemoteServerNode> {
|
||||
|
||||
public ChooseDeploymentWithDebugAction() {
|
||||
super("Debug", "Deploy and debug a chosen item on the selected remote server", AllIcons.Actions.StartDebugger);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<ServersTreeStructure.RemoteServerNode> getTargetNodeClass() {
|
||||
return ServersTreeStructure.RemoteServerNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e, ServersTreeStructure.RemoteServerNode node) {
|
||||
node.deployWithDebug(e);
|
||||
}
|
||||
}
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.execution.executors.DefaultDebugExecutor;
|
||||
import com.intellij.icons.AllIcons;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public class DebugServerAction extends RunServerActionBase {
|
||||
public DebugServerAction() {
|
||||
super("Debug", "Start the selected server in debug mode", AllIcons.Actions.StartDebugger);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Executor getExecutor() {
|
||||
return DefaultDebugExecutor.getDebugExecutorInstance();
|
||||
}
|
||||
}
|
||||
+23
-40
@@ -1,67 +1,50 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.DeploymentNode;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServerNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public class DeployAction extends ServersTreeActionBase {
|
||||
public class DeployAction extends ServersTreeAction<DeploymentNode> {
|
||||
|
||||
public DeployAction() {
|
||||
super("Deploy", "Deploy the selected item", AllIcons.Nodes.Deploy);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updatePresentation(@NotNull Presentation presentation, @Nullable ServersToolWindowContent content) {
|
||||
if (content != null) {
|
||||
Set<DeploymentNode> nodes = content.getSelectedDeploymentNodes();
|
||||
if (nodes.size() == 1) {
|
||||
DeploymentNode node = nodes.iterator().next();
|
||||
if (node.isDeployed()) {
|
||||
presentation.setText("Redeploy");
|
||||
presentation.setDescription("Redeploy '" + node.getDeploymentName() + "'");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
presentation.setText(getTemplatePresentation().getText());
|
||||
presentation.setDescription(getTemplatePresentation().getDescription());
|
||||
protected Class<DeploymentNode> getTargetNodeClass() {
|
||||
return DeploymentNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
Set<DeploymentNode> deploymentNodes = content.getSelectedDeploymentNodes();
|
||||
Set<ServerNode> serverNodes = content.getSelectedServerNodes();
|
||||
if (deploymentNodes.size() + serverNodes.size() != 1) return false;
|
||||
for (DeploymentNode node : deploymentNodes) {
|
||||
if (!node.isRedeployActionEnabled()) {
|
||||
return false;
|
||||
}
|
||||
protected void updatePresentation(@NotNull Presentation presentation, @Nullable DeploymentNode node) {
|
||||
if (node != null && node.isDeployed()) {
|
||||
presentation.setText("Redeploy");
|
||||
presentation.setDescription("Redeploy '" + node.getDeploymentName() + "'");
|
||||
}
|
||||
for (ServerNode serverNode : serverNodes) {
|
||||
if (!serverNode.isDeployActionEnabled()) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
presentation.setText(getTemplatePresentation().getText());
|
||||
presentation.setDescription(getTemplatePresentation().getDescription());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
for (DeploymentNode node : content.getSelectedDeploymentNodes()) {
|
||||
node.redeploy();
|
||||
}
|
||||
for (ServerNode node : content.getSelectedServerNodes()) {
|
||||
node.deploy(e);
|
||||
}
|
||||
protected boolean isVisible4(DeploymentNode node) {
|
||||
return node.isDeployActionVisible();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled4(DeploymentNode node) {
|
||||
return node.isDeployActionEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(DeploymentNode node) {
|
||||
node.deploy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServerNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public class DeployAllAction extends ServerActionBase {
|
||||
|
||||
public DeployAllAction() {
|
||||
super("Deploy All", "Deploy all the artifacts of the selected server", AllIcons.Nodes.Deploy);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performAction(@NotNull ServerNode serverNode) {
|
||||
if (serverNode.isDeployAllActionEnabled()) {
|
||||
serverNode.deployAll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabledForServer(@NotNull ServerNode serverNode) {
|
||||
return serverNode.isDeployAllActionEnabled();
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.DeploymentNode;
|
||||
|
||||
public class DeployWithDebugAction extends ServersTreeAction<DeploymentNode> {
|
||||
|
||||
public DeployWithDebugAction() {
|
||||
super("Debug", "Deploy and debug the selected item", AllIcons.Actions.StartDebugger);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<DeploymentNode> getTargetNodeClass() {
|
||||
return DeploymentNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isVisible4(DeploymentNode node) {
|
||||
return node.isDeployActionVisible() && node.isDebugActionVisible();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled4(DeploymentNode node) {
|
||||
return node.isDeployActionEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(DeploymentNode node) {
|
||||
node.deployWithDebug();
|
||||
}
|
||||
}
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.DeploymentNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class DeploymentActionBase extends ServersTreeActionBase {
|
||||
protected DeploymentActionBase(String text, String description, Icon icon) {
|
||||
super(text, description, icon);
|
||||
}
|
||||
|
||||
protected abstract void perform(@NotNull List<DeploymentNode> nodes, ServersToolWindowContent content, AnActionEvent e);
|
||||
|
||||
protected abstract boolean isApplicable(@NotNull DeploymentNode node);
|
||||
|
||||
@Override
|
||||
public void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
List<DeploymentNode> toPerform = new ArrayList<DeploymentNode>();
|
||||
for (DeploymentNode node : content.getSelectedDeploymentNodes()) {
|
||||
if (isApplicable(node)) {
|
||||
toPerform.add(node);
|
||||
}
|
||||
}
|
||||
if (!toPerform.isEmpty()) {
|
||||
perform(toPerform, content, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
Set<?> selectedElements = content.getBuilder().getSelectedElements();
|
||||
if (selectedElements.isEmpty() || selectedElements.size() != content.getSelectedDeploymentNodes().size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (DeploymentNode node : content.getSelectedDeploymentNodes()) {
|
||||
if (!isApplicable(node)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
|
||||
|
||||
public class DeploymentConfigAction extends EditConfigurationActionBase<ServersTreeStructure.DeploymentNodeImpl> {
|
||||
|
||||
public DeploymentConfigAction() {
|
||||
super("Edit the selected deployment run configuration");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<ServersTreeStructure.DeploymentNodeImpl> getTargetNodeClass() {
|
||||
return ServersTreeStructure.DeploymentNodeImpl.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isVisible4(ServersTreeStructure.DeploymentNodeImpl node) {
|
||||
return node.isEditConfigurationActionVisible();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(ServersTreeStructure.DeploymentNodeImpl node) {
|
||||
node.editConfiguration();
|
||||
}
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.DeploymentNode;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServerNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public class EditConfigurationAction extends ServersTreeActionBase {
|
||||
public EditConfigurationAction() {
|
||||
super("Edit Configuration", "Edit configuration of the selected server", AllIcons.Actions.EditSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
Set<DeploymentNode> deploymentNodes = content.getSelectedDeploymentNodes();
|
||||
Set<ServerNode> serverNodes = content.getSelectedServerNodes();
|
||||
if (deploymentNodes.size() == 1) {
|
||||
deploymentNodes.iterator().next().editConfiguration();
|
||||
}
|
||||
else {
|
||||
serverNodes.iterator().next().editConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
Set<DeploymentNode> deploymentNodes = content.getSelectedDeploymentNodes();
|
||||
Set<ServerNode> serverNodes = content.getSelectedServerNodes();
|
||||
if (deploymentNodes.size() + serverNodes.size() != 1) return false;
|
||||
if (deploymentNodes.size() == 1) {
|
||||
return deploymentNodes.iterator().next().isEditConfigurationActionEnabled();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeNode;
|
||||
|
||||
public abstract class EditConfigurationActionBase<T extends ServersTreeNode> extends ServersTreeAction<T> {
|
||||
|
||||
public EditConfigurationActionBase(String description) {
|
||||
super("Edit Configuration", description, AllIcons.Actions.EditSource);
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
|
||||
|
||||
public class RemoteServerConfigAction extends EditConfigurationActionBase<ServersTreeStructure.RemoteServerNode> {
|
||||
|
||||
public RemoteServerConfigAction() {
|
||||
super("Edit the selected remote server configuration");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<ServersTreeStructure.RemoteServerNode> getTargetNodeClass() {
|
||||
return ServersTreeStructure.RemoteServerNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(ServersTreeStructure.RemoteServerNode node) {
|
||||
node.editConfiguration();
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
|
||||
import com.intellij.remoteServer.runtime.ServerConnectionManager;
|
||||
|
||||
public class RemoteServerConnectAction extends ServersTreeAction<ServersTreeStructure.RemoteServerNode> {
|
||||
|
||||
public RemoteServerConnectAction() {
|
||||
super("Connect", "Connect to the selected remote server", AllIcons.Actions.Execute);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<ServersTreeStructure.RemoteServerNode> getTargetNodeClass() {
|
||||
return ServersTreeStructure.RemoteServerNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled4(ServersTreeStructure.RemoteServerNode node) {
|
||||
return !node.isConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(ServersTreeStructure.RemoteServerNode node) {
|
||||
ServerConnectionManager.getInstance().getOrCreateConnection(node.getValue());
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
|
||||
import com.intellij.remoteServer.runtime.ServerConnection;
|
||||
import com.intellij.remoteServer.runtime.ServerConnectionManager;
|
||||
|
||||
public class RemoteServerDisconnectAction extends ServersTreeAction<ServersTreeStructure.RemoteServerNode> {
|
||||
|
||||
public RemoteServerDisconnectAction() {
|
||||
super("Disconnect", "Disconnect from the selected remote server", AllIcons.Actions.Suspend);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<ServersTreeStructure.RemoteServerNode> getTargetNodeClass() {
|
||||
return ServersTreeStructure.RemoteServerNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled4(ServersTreeStructure.RemoteServerNode node) {
|
||||
return node.isConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(ServersTreeStructure.RemoteServerNode node) {
|
||||
ServerConnection<?> connection = ServerConnectionManager.getInstance().getConnection(node.getValue());
|
||||
if (connection != null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.execution.executors.DefaultRunExecutor;
|
||||
import com.intellij.icons.AllIcons;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public class RunServerAction extends RunServerActionBase {
|
||||
|
||||
public RunServerAction() {
|
||||
super("Run/Connect", "Run/Connect to the selected server", AllIcons.Actions.Execute);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Executor getExecutor() {
|
||||
return DefaultRunExecutor.getRunExecutorInstance();
|
||||
}
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServerNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public abstract class RunServerActionBase extends ServerActionBase {
|
||||
|
||||
protected RunServerActionBase(String text, String description, Icon icon) {
|
||||
super(text, description, icon);
|
||||
}
|
||||
|
||||
protected void performAction(@NotNull ServerNode serverNode) {
|
||||
if (serverNode.isStartActionEnabled(getExecutor())) {
|
||||
serverNode.startServer(getExecutor());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabledForServer(@NotNull ServerNode serverNode) {
|
||||
return serverNode.isStartActionEnabled(getExecutor());
|
||||
}
|
||||
|
||||
protected abstract Executor getExecutor();
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServerNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public abstract class ServerActionBase extends ServersTreeActionBase {
|
||||
|
||||
protected ServerActionBase(String text, String description, Icon icon) {
|
||||
super(text, description, icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final boolean isEnabled(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
Set<ServerNode> selectedServerNodes = content.getSelectedServerNodes();
|
||||
Set<?> selectedElements = content.getBuilder().getSelectedElements();
|
||||
if (selectedElements.size() != selectedServerNodes.size() || selectedElements.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (ServerNode selectedServer : selectedServerNodes) {
|
||||
if (!isEnabledForServer(selectedServer)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
for (ServerNode node : content.getSelectedServerNodes()) {
|
||||
performAction(node);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void performAction(@NotNull ServerNode serverNode);
|
||||
|
||||
protected abstract boolean isEnabledForServer(@NotNull ServerNode serverNode);
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class ServersTreeAction<T extends ServersTreeNode> extends AnAction {
|
||||
|
||||
protected ServersTreeAction(String text, String description, Icon icon) {
|
||||
super(text, description, icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(@NotNull AnActionEvent e) {
|
||||
Presentation presentation = e.getPresentation();
|
||||
T targetNode = getTargetNode(e);
|
||||
|
||||
boolean visible = false;
|
||||
boolean enabled = false;
|
||||
|
||||
if (targetNode != null) {
|
||||
visible = isVisible4(targetNode);
|
||||
if (visible) {
|
||||
enabled = isEnabled4(targetNode);
|
||||
}
|
||||
}
|
||||
|
||||
presentation.setVisible(visible);
|
||||
presentation.setEnabled(enabled);
|
||||
updatePresentation(presentation, targetNode);
|
||||
}
|
||||
|
||||
private T getTargetNode(AnActionEvent e) {
|
||||
ServersToolWindowContent content = getContent(e);
|
||||
if (content == null) {
|
||||
return null;
|
||||
}
|
||||
Set<Object> selectedElements = content.getBuilder().getSelectedElements();
|
||||
if (selectedElements.size() != 1) {
|
||||
return null;
|
||||
}
|
||||
ServersTreeNode node = (ServersTreeNode)selectedElements.iterator().next();
|
||||
Class<T> targetNodeClass = getTargetNodeClass();
|
||||
if (!targetNodeClass.isInstance(node)) {
|
||||
return null;
|
||||
}
|
||||
return targetNodeClass.cast(node);
|
||||
}
|
||||
|
||||
private static ServersToolWindowContent getContent(AnActionEvent e) {
|
||||
return e.getData(ServersToolWindowContent.KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
T targetNode = getTargetNode(e);
|
||||
if (targetNode != null && isVisible4(targetNode) && isEnabled4(targetNode)) {
|
||||
doActionPerformed(getContent(e), e, targetNode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected boolean isVisible4(T node) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isEnabled4(T node) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void updatePresentation(@NotNull Presentation presentation, @Nullable T node) {
|
||||
}
|
||||
|
||||
|
||||
protected void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e, T node) {
|
||||
doActionPerformed(node);
|
||||
}
|
||||
|
||||
protected void doActionPerformed(T node) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
protected abstract Class<T> getTargetNodeClass();
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public abstract class ServersTreeActionBase extends AnAction {
|
||||
|
||||
protected ServersTreeActionBase(String text, String description, Icon icon) {
|
||||
super(text, description, icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
ServersToolWindowContent content = e.getData(ServersToolWindowContent.KEY);
|
||||
Presentation presentation = e.getPresentation();
|
||||
presentation.setEnabled(content != null && isEnabled(content, e));
|
||||
updatePresentation(presentation, content);
|
||||
}
|
||||
|
||||
protected void updatePresentation(@NotNull Presentation presentation, @Nullable ServersToolWindowContent content) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
ServersToolWindowContent content = e.getData(ServersToolWindowContent.KEY);
|
||||
if (content == null) {
|
||||
return;
|
||||
}
|
||||
doActionPerformed(content, e);
|
||||
}
|
||||
|
||||
protected abstract boolean isEnabled(@NotNull ServersToolWindowContent content, AnActionEvent e);
|
||||
|
||||
protected abstract void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e);
|
||||
}
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServerNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public abstract class SingleServerActionBase extends ServersTreeActionBase {
|
||||
protected SingleServerActionBase(String text, String description, Icon icon) {
|
||||
super(text, description, icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
doActionPerformed(content, content.getSelectedServerNodes().iterator().next());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled(@NotNull ServersToolWindowContent content, AnActionEvent e) {
|
||||
Set<ServerNode> serverNodes = content.getSelectedServerNodes();
|
||||
return content.getBuilder().getSelectedElements().size() == serverNodes.size() && serverNodes.size() == 1 &&
|
||||
isEnabledForServer(serverNodes.iterator().next());
|
||||
}
|
||||
|
||||
protected abstract boolean isEnabledForServer(ServerNode serverNode);
|
||||
|
||||
protected abstract void doActionPerformed(@NotNull ServersToolWindowContent content, @NotNull ServerNode server);
|
||||
}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.ServerNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public class StopServerAction extends ServerActionBase {
|
||||
|
||||
public StopServerAction() {
|
||||
super("Stop/Disconnect", "Stop/disconnect from the selected server", AllIcons.Actions.Suspend);
|
||||
}
|
||||
|
||||
protected void performAction(@NotNull ServerNode serverNode) {
|
||||
if (serverNode.isStopActionEnabled()) {
|
||||
serverNode.stopServer();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabledForServer(@NotNull ServerNode serverNode) {
|
||||
return serverNode.isStopActionEnabled();
|
||||
}
|
||||
}
|
||||
+10
-11
@@ -1,30 +1,29 @@
|
||||
package com.intellij.remoteServer.impl.runtime.ui.tree.actions;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.ServersToolWindowContent;
|
||||
import com.intellij.remoteServer.impl.runtime.ui.tree.DeploymentNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public class UndeployAction extends DeploymentActionBase {
|
||||
public class UndeployAction extends ServersTreeAction<DeploymentNode> {
|
||||
|
||||
public UndeployAction() {
|
||||
super("Undeploy", "Undeploy the selected item", AllIcons.Nodes.Undeploy);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isApplicable(@NotNull DeploymentNode node) {
|
||||
protected Class<DeploymentNode> getTargetNodeClass() {
|
||||
return DeploymentNode.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled4(DeploymentNode node) {
|
||||
return node.isUndeployActionEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void perform(@NotNull List<DeploymentNode> nodes, ServersToolWindowContent content, AnActionEvent e) {
|
||||
for (DeploymentNode node : nodes) {
|
||||
node.undeploy();
|
||||
}
|
||||
protected void doActionPerformed(DeploymentNode node) {
|
||||
node.undeploy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ ide.debugger.inline.dark.fg.color=61,128,101
|
||||
ide.debugger.inline.dark.fg.color.description=Inline values foreground for dark editor scheme
|
||||
ide.debugger.inline.fg.modified.color=202,128,33
|
||||
ide.debugger.inline.fg.modified.color.description=Inline modified values foreground
|
||||
ide.debugger.inline.dark.fg.modified.color=161,131,10
|
||||
ide.debugger.inline.dark.fg.modified.color=202,126,3
|
||||
ide.debugger.inline.dark.fg.modified.color.description=Inline modified values foreground for dark editor scheme
|
||||
|
||||
ide.debugMode.description=Record additional information to make bug reports more informative.
|
||||
@@ -198,6 +198,9 @@ compiler.process.use.memory.temp.cache=true
|
||||
compiler.process.use.memory.temp.cache.description=Store temporary data in memory for faster compilation;\
|
||||
requires larger heap size for the build process. If parallel build is enabled, the option is ignored and temp data is always stored in memory.
|
||||
|
||||
compiler.process.preload=false
|
||||
compiler.process.preload.description=After build finishes, the IDE will pre-load and leave waiting in memory the build process for the next compilation. This will save time for process start and project model loading (may be noticeable for big projects).\
|
||||
|
||||
compiler.process.debug.port=-1
|
||||
|
||||
compiler.automake.trigger.delay=300
|
||||
|
||||
+5
-2
@@ -26,7 +26,10 @@ import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.ColorUtil;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.SimpleColoredText;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.util.NotNullProducer;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XSourcePosition;
|
||||
@@ -95,7 +98,7 @@ public class XDebuggerEditorLinePainter extends EditorLinePainter {
|
||||
catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
final Color color = bpLine == lineNumber ? new JBColor(Gray._180, new Color(147, 217, 186)) : getForeground();
|
||||
final Color color = bpLine == lineNumber ? new JBColor(new Color(0, 255, 86), new Color(255, 235, 9)) : getForeground();
|
||||
|
||||
final String name = value.getName();
|
||||
if (StringUtil.isEmpty(text.toString())) {
|
||||
|
||||
+6
-7
@@ -89,6 +89,10 @@ public abstract class TreeInplaceEditor implements AWTEventListener {
|
||||
|
||||
protected abstract Project getProject();
|
||||
|
||||
private static void setInplaceEditorBounds(JComponent component, int x, int y, int width, int height) {
|
||||
component.setBounds(x, y, width, Math.max(height, component.getPreferredSize().height));
|
||||
}
|
||||
|
||||
public final void show() {
|
||||
LOG.assertTrue(myInplaceEditorComponent == null, "editor is not released");
|
||||
final JTree tree = getTree();
|
||||
@@ -108,12 +112,7 @@ public abstract class TreeInplaceEditor implements AWTEventListener {
|
||||
final JComponent inplaceEditorComponent = createInplaceEditorComponent();
|
||||
myInplaceEditorComponent = inplaceEditorComponent;
|
||||
LOG.assertTrue(inplaceEditorComponent != null);
|
||||
inplaceEditorComponent.setBounds(
|
||||
layeredPanePoint.x,
|
||||
layeredPanePoint.y,
|
||||
bounds.width,
|
||||
Math.max(bounds.height, inplaceEditorComponent.getPreferredSize().height)
|
||||
);
|
||||
setInplaceEditorBounds(inplaceEditorComponent, layeredPanePoint.x, layeredPanePoint.y, bounds.width, bounds.height);
|
||||
|
||||
layeredPane.add(inplaceEditorComponent, new Integer(250));
|
||||
|
||||
@@ -145,7 +144,7 @@ public abstract class TreeInplaceEditor implements AWTEventListener {
|
||||
return;
|
||||
}
|
||||
Point layeredPanePoint = SwingUtilities.convertPoint(tree, bounds.x, bounds.y, layeredPane);
|
||||
inplaceEditorComponent.setBounds(layeredPanePoint.x, layeredPanePoint.y, bounds.width, bounds.height);
|
||||
setInplaceEditorBounds(inplaceEditorComponent, layeredPanePoint.x, layeredPanePoint.y, bounds.width, bounds.height);
|
||||
inplaceEditorComponent.revalidate();
|
||||
}
|
||||
});
|
||||
|
||||
+7
-3
@@ -160,10 +160,11 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu
|
||||
};
|
||||
|
||||
if (getValueContainer().computeInlineDebuggerData(callback) == ThreeState.UNSURE) {
|
||||
getValueContainer().computeSourcePosition(new XNearestSourcePosition() {
|
||||
class ValueDeclaration implements XNavigatable {
|
||||
@Override
|
||||
public void setSourcePosition(@Nullable XSourcePosition sourcePosition) {
|
||||
final Map<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>> map = myTree.getProject().getUserData(XVariablesView.DEBUG_VARIABLES);
|
||||
final Map<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>> map =
|
||||
myTree.getProject().getUserData(XVariablesView.DEBUG_VARIABLES);
|
||||
final Map<VirtualFile, Long> timestamps = myTree.getProject().getUserData(XVariablesView.DEBUG_VARIABLES_TIMESTAMPS);
|
||||
if (map == null || timestamps == null || sourcePosition == null) return;
|
||||
VirtualFile file = sourcePosition.getFile();
|
||||
@@ -172,7 +173,10 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu
|
||||
int line = sourcePosition.getLine();
|
||||
callback.computed(file, doc, line);
|
||||
}
|
||||
});
|
||||
}
|
||||
class NearestValuePosition extends ValueDeclaration implements XNearestSourcePosition {}
|
||||
getValueContainer().computeSourcePosition(new ValueDeclaration());
|
||||
getValueContainer().computeSourcePosition(new NearestValuePosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+32
-23
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.util.RefactoringChangeUtil;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
@@ -243,12 +244,9 @@ public class UnnecessaryUnboxingInspection extends BaseInspection {
|
||||
if (!(expression instanceof PsiMethodCallExpression)) {
|
||||
return false;
|
||||
}
|
||||
final PsiMethodCallExpression methodCallExpression =
|
||||
(PsiMethodCallExpression)expression;
|
||||
final PsiReferenceExpression methodExpression =
|
||||
methodCallExpression.getMethodExpression();
|
||||
final PsiExpression qualifier =
|
||||
methodExpression.getQualifierExpression();
|
||||
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
|
||||
final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
|
||||
final PsiExpression qualifier = methodExpression.getQualifierExpression();
|
||||
if (qualifier == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -261,31 +259,45 @@ public class UnnecessaryUnboxingInspection extends BaseInspection {
|
||||
return false;
|
||||
}
|
||||
final String methodName = methodExpression.getReferenceName();
|
||||
final String unboxingMethod =
|
||||
s_unboxingMethods.get(qualifierTypeName);
|
||||
final String unboxingMethod = s_unboxingMethods.get(qualifierTypeName);
|
||||
return unboxingMethod.equals(methodName);
|
||||
}
|
||||
|
||||
private boolean isSameMethodCalledWithoutUnboxing(
|
||||
@NotNull PsiCallExpression callExpression,
|
||||
@NotNull PsiMethodCallExpression unboxingExpression) {
|
||||
final PsiExpressionList argumentList =
|
||||
callExpression.getArgumentList();
|
||||
private boolean isSameMethodCalledWithoutUnboxing(@NotNull PsiCallExpression callExpression,
|
||||
@NotNull PsiMethodCallExpression unboxingExpression) {
|
||||
final PsiExpressionList argumentList = callExpression.getArgumentList();
|
||||
if (argumentList == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiExpression[] expressions = argumentList.getExpressions();
|
||||
final PsiMethod originalMethod =
|
||||
callExpression.resolveMethod();
|
||||
final PsiMethod originalMethod = callExpression.resolveMethod();
|
||||
if (originalMethod == null) {
|
||||
return false;
|
||||
}
|
||||
final String name = originalMethod.getName();
|
||||
final PsiClass containingClass =
|
||||
originalMethod.getContainingClass();
|
||||
|
||||
final PsiExpression qualifierExpression;
|
||||
if (callExpression instanceof PsiMethodCallExpression) {
|
||||
qualifierExpression = ((PsiMethodCallExpression)callExpression).getMethodExpression().getQualifierExpression();
|
||||
} else if (callExpression instanceof PsiNewExpression) {
|
||||
qualifierExpression = ((PsiNewExpression)callExpression).getQualifier();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiClass containingClass;
|
||||
if (qualifierExpression == null) {
|
||||
final PsiElement scope = callExpression.resolveMethodGenerics().getCurrentFileResolveScope();
|
||||
containingClass = scope instanceof PsiClass ? (PsiClass)scope : null;
|
||||
}
|
||||
else {
|
||||
containingClass = PsiUtil.resolveClassInType(GenericsUtil.getVariableTypeByExpressionType(qualifierExpression.getType()));
|
||||
}
|
||||
|
||||
if (containingClass == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiType[] types = PsiType.createArray(expressions.length);
|
||||
for (int i = 0; i < expressions.length; i++) {
|
||||
final PsiExpression expression = expressions[i];
|
||||
@@ -294,20 +306,17 @@ public class UnnecessaryUnboxingInspection extends BaseInspection {
|
||||
if (!(type instanceof PsiPrimitiveType)) {
|
||||
return false;
|
||||
}
|
||||
final PsiPrimitiveType primitiveType =
|
||||
(PsiPrimitiveType)type;
|
||||
final PsiPrimitiveType primitiveType = (PsiPrimitiveType)type;
|
||||
types[i] = primitiveType.getBoxedType(unboxingExpression);
|
||||
}
|
||||
else {
|
||||
types[i] = type;
|
||||
}
|
||||
}
|
||||
final PsiMethod[] methods =
|
||||
containingClass.findMethodsByName(name, true);
|
||||
final PsiMethod[] methods = containingClass.findMethodsByName(name, true);
|
||||
for (final PsiMethod method : methods) {
|
||||
if (!originalMethod.equals(method)) {
|
||||
if (MethodCallUtils.isApplicable(method,
|
||||
PsiSubstitutor.EMPTY, types)) {
|
||||
if (MethodCallUtils.isApplicable(method, PsiSubstitutor.EMPTY, types)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+15
@@ -38,4 +38,19 @@ public class UnnecessaryUnboxing {
|
||||
Integer boxcutter(Integer i) {
|
||||
return i.intValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class B23 {
|
||||
public void set(double value) {}
|
||||
}
|
||||
class A23 extends B23 {
|
||||
public void set(Object value) {}
|
||||
private A23() {
|
||||
Object o = 2d;
|
||||
set(((Double) o).doubleValue());
|
||||
|
||||
B23 b23 = new B23();
|
||||
b23.set(((Double) o).doubleValue());
|
||||
}
|
||||
}
|
||||
+13
@@ -43,4 +43,17 @@ public class UnnecessaryUnboxing {
|
||||
byte cast(Integer v) {
|
||||
return (byte)v.intValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class B23 {
|
||||
public void set(double value) {}
|
||||
}
|
||||
class A23 extends B23 {
|
||||
public void set(Object value) {}
|
||||
private A23() {
|
||||
Object o = 2d;
|
||||
B23 b23 = new B23();
|
||||
b23.set(((Double) o).doubleValue());
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -55,5 +55,10 @@
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Unnecessary unboxing</problem_class>
|
||||
<description>Unnecessary unboxing <code>b.byteValue()</code> #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>UnnecessaryUnboxing.java</file>
|
||||
<line>57</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Unnecessary unboxing</problem_class>
|
||||
<description>Unnecessary unboxing <code>((Double) o).doubleValue()</code> #loc</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -35,7 +35,7 @@ import java.util.List;
|
||||
public class HgUpdateEnvironment implements UpdateEnvironment {
|
||||
|
||||
private final Project project;
|
||||
private final HgUpdateConfigurationSettings updateConfiguration;
|
||||
@NotNull private final HgUpdateConfigurationSettings updateConfiguration;
|
||||
|
||||
public HgUpdateEnvironment(Project project) {
|
||||
this.project = project;
|
||||
@@ -89,7 +89,7 @@ public class HgUpdateEnvironment implements UpdateEnvironment {
|
||||
private final HgUpdateConfigurationSettings updateConfiguration;
|
||||
protected HgUpdateDialog updateDialog;
|
||||
|
||||
public UpdateConfigurable(HgUpdateConfigurationSettings updateConfiguration) {
|
||||
public UpdateConfigurable(@NotNull HgUpdateConfigurationSettings updateConfiguration) {
|
||||
this.updateConfiguration = updateConfiguration;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ import com.intellij.tasks.TaskBundle;
|
||||
import com.intellij.tasks.TaskRepositoryType;
|
||||
import com.intellij.tasks.impl.BaseRepository;
|
||||
import com.intellij.tasks.impl.BaseRepositoryImpl;
|
||||
import com.intellij.tasks.impl.TaskUtil;
|
||||
import com.intellij.tasks.impl.httpclient.ResponseUtil;
|
||||
import com.intellij.tasks.trello.model.TrelloBoard;
|
||||
import com.intellij.tasks.trello.model.TrelloCard;
|
||||
@@ -320,8 +319,6 @@ public final class TrelloRepository extends BaseRepositoryImpl {
|
||||
HttpClient client = getHttpClient();
|
||||
client.executeMethod(method);
|
||||
String entityContent = ResponseUtil.getResponseContentAsString(method);
|
||||
TaskUtil.prettyFormatJsonToLog(LOG, entityContent);
|
||||
// LOG.debug("Response size: " + method.getResponseHeader("Content-Length").getValue() + " bytes");
|
||||
if (method.getStatusCode() != HttpStatus.SC_OK) {
|
||||
Header header = method.getResponseHeader("Content-Type");
|
||||
if (header != null && header.getValue().startsWith("text/plain")) {
|
||||
|
||||
@@ -43,7 +43,7 @@ import java.util.List;
|
||||
* @author Mikhail Golubev
|
||||
*/
|
||||
public class TrelloRepositoryEditor extends BaseRepositoryEditor<TrelloRepository> {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.tasks.trello.TrelloRepositoryEditor");
|
||||
private static final Logger LOG = Logger.getInstance(TrelloRepositoryEditor.class);
|
||||
|
||||
private static final TrelloBoard UNSPECIFIED_BOARD = new TrelloBoard() {
|
||||
@NotNull
|
||||
@@ -83,9 +83,10 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor<TrelloRepositor
|
||||
@Override
|
||||
protected void textChanged(DocumentEvent e) {
|
||||
String password = String.valueOf(myPasswordText.getPassword());
|
||||
if (password.equals(myRepository.getPassword())) {
|
||||
if (password.isEmpty() || password.equals(myRepository.getPassword())) {
|
||||
return;
|
||||
}
|
||||
LOG.debug("Authentication token was changed");
|
||||
myRepository.setPassword(password);
|
||||
new BoardsDownloader(UNSPECIFIED_BOARD) {
|
||||
@Override
|
||||
@@ -119,7 +120,6 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor<TrelloRepositor
|
||||
}
|
||||
});
|
||||
myBoardComboBox.setRenderer(new TrelloBoardRenderer("Set token first"));
|
||||
myListComboBox.setRenderer(new TrelloListRenderer("Select board first"));
|
||||
|
||||
myListComboBox.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
@@ -132,12 +132,14 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor<TrelloRepositor
|
||||
}
|
||||
}
|
||||
});
|
||||
myListComboBox.setRenderer(new TrelloListRenderer("Select board first"));
|
||||
|
||||
// Initial setup:
|
||||
if (myRepository.getCurrentUser() != null) {
|
||||
new BoardsDownloader(myRepository.getCurrentBoard()) {
|
||||
@Override
|
||||
protected List<TrelloBoard> download() throws Exception {
|
||||
LOG.debug("Updating information about boards available to user when repository setting are shown");
|
||||
List<TrelloBoard> boards = super.download();
|
||||
if (myBoard == null) {
|
||||
return boards;
|
||||
@@ -157,6 +159,7 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor<TrelloRepositor
|
||||
new ListsDownloader(myRepository.getCurrentList()) {
|
||||
@Override
|
||||
protected List<TrelloList> download() throws Exception {
|
||||
LOG.debug("Updating information about lists of board " + myRepository.getCurrentBoard() + " when repository setting are shown");
|
||||
List<TrelloList> lists = super.download();
|
||||
if (myList == null) {
|
||||
return lists;
|
||||
@@ -266,6 +269,7 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor<TrelloRepositor
|
||||
return myRepository.fetchUserBoards();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void updateUI(List<TrelloBoard> boards) {
|
||||
myBoardComboBox.setModel(new DefaultComboBoxModel(boards.toArray()));
|
||||
@@ -296,6 +300,7 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor<TrelloRepositor
|
||||
return myRepository.fetchBoardLists();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void updateUI(List<TrelloList> lists) {
|
||||
myListComboBox.setModel(new DefaultComboBoxModel(lists.toArray()));
|
||||
|
||||
@@ -40,15 +40,15 @@ public class TasksIcons {
|
||||
public static final Icon Github = load("/icons/github.png"); // 16x16
|
||||
public static final Icon Gitlab = load("/icons/gitlab.png"); // 16x16
|
||||
public static final Icon Jira = load("/icons/jira.png"); // 16x16
|
||||
public static final Icon Lighthouse = load("/icons/lighthouse.gif"); // 16x16
|
||||
public static final Icon Lighthouse = load("/icons/lighthouse.png"); // 16x16
|
||||
public static final Icon Mantis = load("/icons/mantis.png"); // 16x16
|
||||
public static final Icon Other = load("/icons/other.png"); // 16x16
|
||||
|
||||
public static class Pivotal {
|
||||
public static final Icon Bug = load("/icons/pivotal/bug.png"); // 14x14
|
||||
public static final Icon Chore = load("/icons/pivotal/chore.png"); // 14x14
|
||||
public static final Icon Feature = load("/icons/pivotal/feature.png"); // 14x14
|
||||
public static final Icon Release = load("/icons/pivotal/release.png"); // 14x14
|
||||
public static final Icon Bug = load("/icons/pivotal/bug.png"); // 16x16
|
||||
public static final Icon Chore = load("/icons/pivotal/chore.png"); // 16x16
|
||||
public static final Icon Feature = load("/icons/pivotal/feature.png"); // 16x16
|
||||
public static final Icon Release = load("/icons/pivotal/release.png"); // 16x16
|
||||
|
||||
}
|
||||
public static final Icon Pivotal = load("/icons/pivotal.png"); // 16x16
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 737 B After Width: | Height: | Size: 325 B |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user