diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java index d4a69206c3ba..a5685017d365 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java @@ -71,9 +71,9 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; -import org.jetbrains.jps.api.BasicFuture; import org.jetbrains.jps.api.CmdlineProtoUtil; import org.jetbrains.jps.api.CmdlineRemoteProto; +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 BasicFuture 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 BasicFuture 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 paths = CompileScopeUtil.fetchFiles(compileContext); @@ -400,7 +400,7 @@ public class CompileDriver { return; } - final BasicFuture future = compileInExternalProcess(compileContext, false); + final TaskFuture future = compileInExternalProcess(compileContext, false); if (future != null) { while (!future.waitFor(200L, TimeUnit.MILLISECONDS)) { if (indicator.isCanceled()) { diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java index 2c5b378d96ea..efaf9e2b4346 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -100,7 +100,8 @@ import org.jetbrains.jps.cmdline.ClasspathBootstrap; import org.jetbrains.jps.incremental.Utils; import org.jetbrains.jps.model.serialization.JpsGlobalLoader; -import javax.tools.*; +import javax.tools.JavaCompiler; +import javax.tools.ToolProvider; import java.awt.*; import java.io.File; import java.io.IOException; @@ -108,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; @@ -148,10 +148,10 @@ public class BuildManager implements ApplicationComponent{ private final File mySystemDirectory; private final ProjectManager myProjectManager; - private final Map myAutomakeFutures = Collections.synchronizedMap(new HashMap()); + private final Map myAutomakeFutures = Collections.synchronizedMap(new HashMap()); private final Map myBuildsInProgress = Collections.synchronizedMap(new HashMap()); - private final Map, OSProcessHandler>> myPreloadedBuilds = - Collections.synchronizedMap(new HashMap, OSProcessHandler>>()); + private final Map, OSProcessHandler>>> myPreloadedBuilds = + Collections.synchronizedMap(new HashMap, OSProcessHandler>>>()); private final BuildProcessClasspathManager myClasspathManager = new BuildProcessClasspathManager(); private final SequentialTaskExecutor myRequestsProcessor = new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE); private final Map myProjectDataMap = Collections.synchronizedMap(new HashMap()); @@ -447,7 +447,7 @@ public class BuildManager implements ApplicationComponent{ } final List scopes = CmdlineProtoUtil.createAllModulesScopes(false); final AutoMakeMessageHandler handler = new AutoMakeMessageHandler(project); - final BasicFuture future = scheduleBuild( + final TaskFuture future = scheduleBuild( project, false, true, false, scopes, Collections.emptyList(), Collections.emptyMap(), handler ); if (future != null) { @@ -526,12 +526,12 @@ public class BuildManager implements ApplicationComponent{ return false; } - public Collection cancelAutoMakeTasks(Project project) { - final Collection futures = new SmartList(); + public Collection cancelAutoMakeTasks(Project project) { + final Collection futures = new SmartList(); synchronized (myAutomakeFutures) { - for (Map.Entry entry : myAutomakeFutures.entrySet()) { + for (Map.Entry entry : myAutomakeFutures.entrySet()) { if (entry.getValue().equals(project)) { - final BasicFuture future = entry.getKey(); + final TaskFuture future = entry.getKey(); future.cancel(false); futures.add(future); } @@ -542,15 +542,15 @@ public class BuildManager implements ApplicationComponent{ private void cancelPreloadedBuilds(Project project) { final String projectPath = getProjectPath(project); - final Pair, OSProcessHandler> pair = myPreloadedBuilds.remove(projectPath); - if (pair != null) { - final RequestFuture future = pair.first; - myMessageDispatcher.cancelSession(future.getRequestID()); - runCommand(new Runnable() { - @Override - public void run() { + runCommand(new Runnable() { + @Override + public void run() { + Pair, OSProcessHandler> pair = takePreloadedProcess(projectPath); + if (pair != null) { + final RequestFuture 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 + // until this one gracefully exits and closes all its storages getProjectData(projectPath).taskQueue.submit(new Runnable() { @Override public void run() { @@ -558,207 +558,221 @@ public class BuildManager implements ApplicationComponent{ } }); } - }); - } + } + }); } @Nullable - public BasicFuture scheduleBuild( + private Pair, OSProcessHandler> takePreloadedProcess(String projectPath) { + Pair, OSProcessHandler> result; + final Future, 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 scopes, final Collection paths, final Map userData, final DefaultMessageHandler messageHandler) { final String projectPath = getProjectPath(project); - - final Pair, OSProcessHandler> preloaded = myPreloadedBuilds.remove(projectPath); - final RequestFuture preloadedFuture = preloaded != null? preloaded.first : null; - final boolean usingPreloadedProcess = preloadedFuture != null; - - final UUID sessionId; final BuilderMessageHandler handler = new NotifyingMessageHandler(project, messageHandler, messageHandler instanceof AutoMakeMessageHandler); - if (usingPreloadedProcess) { - LOG.info("Using preloaded build process to compile " + projectPath); - sessionId = preloadedFuture.getRequestID(); - preloadedFuture.getMessageHandler().setDelegateHandler(handler); - } - else { - sessionId = UUID.randomUUID(); - } - 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 future = usingPreloadedProcess? preloadedFuture : new RequestFuture(handler, sessionId, new RequestFuture.CancelAction() { - @Override - public void cancel(RequestFuture future) throws Exception { - myMessageDispatcher.cancelSession(future.getRequestID()); + final DelegateFuture _future = new DelegateFuture(); + // 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, OSProcessHandler> preloaded = takePreloadedProcess(projectPath); + final RequestFuture 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 (!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); - 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) { - data.dropChanges(); - } - if (IS_UNIT_TEST_MODE) { - LOG.info("Scheduling build for " + - projectPath + - "; CHANGED: " + - new HashSet(convertToStringPaths(data.myChanged)) + - "; DELETED: " + - new HashSet(convertToStringPaths(data.myDeleted))); - } - currentFSChanges = data.getAndResetRescanFlag() ? null : data.createNextEvent(); - projectTaskQueue = data.taskQueue; + final RequestFuture future = usingPreloadedProcess? preloadedFuture : new RequestFuture(handler, sessionId, new RequestFuture.CancelAction() { + @Override + public void cancel(RequestFuture 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.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.emptyList() : paths, userData, globals, currentFSChanges); - } - if (!usingPreloadedProcess) { - myMessageDispatcher.registerBuildMessageHandler(future, params); + if (IS_UNIT_TEST_MODE) { + LOG.info("Scheduling build for " + + projectPath + + "; CHANGED: " + + new HashSet(convertToStringPaths(data.myChanged)) + + "; DELETED: " + + new HashSet(convertToStringPaths(data.myDeleted))); } + currentFSChanges = data.getAndResetRescanFlag() ? null : data.createNextEvent(); + projectTaskQueue = data.taskQueue; + } - try { - projectTaskQueue.submit(new Runnable() { - @Override - public void run() { - Throwable execFailure = null; - try { - if (project.isDisposed()) { - if (usingPreloadedProcess) { - future.cancel(true); - } - else { - return; - } - } - myBuildsInProgress.put(projectPath, future); - final OSProcessHandler processHandler; - final StringBuilder errorsOnLaunch = new StringBuilder(); + final CmdlineRemoteProto.Message.ControllerMessage params; + if (isRebuild) { + params = CmdlineProtoUtil.createBuildRequest(projectPath, scopes, Collections.emptyList(), userData, globals, null); + } + else if (onlyCheckUpToDate) { + params = CmdlineProtoUtil.createUpToDateCheckRequest(projectPath, scopes, paths, userData, globals, currentFSChanges); + } + else { + params = CmdlineProtoUtil.createBuildRequest(projectPath, scopes, isMake ? Collections.emptyList() : paths, userData, globals, currentFSChanges); + } + if (!usingPreloadedProcess) { + myMessageDispatcher.registerBuildMessageHandler(future, params); + } + + try { + projectTaskQueue.submit(new Runnable() { + @Override + public void run() { + Throwable execFailure = null; + try { + if (project.isDisposed()) { if (usingPreloadedProcess) { - final boolean paramsSent = myMessageDispatcher.sendBuildParameters(future.getRequestID(), params); - if (!paramsSent) { - myMessageDispatcher.cancelSession(future.getRequestID()); - } - processHandler = preloaded.second; + future.cancel(true); } else { - processHandler = launchBuildProcess(project, myListenPort, sessionId, false); - processHandler.addProcessListener(new ProcessAdapter() { - @Override - public void onTextAvailable(ProcessEvent event, Key outputType) { - if (ProcessOutputTypes.STDERR.equals(outputType)) { - if (errorsOnLaunch.length() < 1024) { - final String text = event.getText(); - if (!StringUtil.isEmptyOrSpaces(text)) { - errorsOnLaunch.append(text); - } + return; + } + } + 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) { + 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 (errorsOnLaunch.length() > 0) { - msg.append("\n").append(errorsOnLaunch); - } - else { - msg.append("unknown error"); - } - handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(msg.toString(), null)); } - } - else { - handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure("Disconnected from build process", null)); + }); + 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 (errorsOnLaunch.length() > 0) { + msg.append("\n").append(errorsOnLaunch); + } + 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); - } - } - - if (Registry.is("compiler.process.preload") && !project.isDisposed()) { - try { - final Pair, OSProcessHandler> pair = launchPreloadedBuildProcess(project); - myPreloadedBuilds.put(projectPath, pair); - } - catch (Exception e) { - LOG.info("Error pre-loading build process for project " + projectPath, e); - } - } - + 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, 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 null; + return _future; } @NotNull @@ -798,37 +812,42 @@ public class BuildManager implements ApplicationComponent{ return "com.intellij.compiler.server.BuildManager"; } - private Pair, OSProcessHandler> launchPreloadedBuildProcess(final Project project) throws Exception { + private Future, OSProcessHandler>> launchPreloadedBuildProcess(final Project project, SequentialTaskExecutor projectTaskQueue) throws Exception { ensureListening(); - final RequestFuture future = new RequestFuture(new PreloadedProcessMessageHandler(project), UUID.randomUUID(), new RequestFuture.CancelAction() { - @Override - public void cancel(RequestFuture future) throws Exception { - myMessageDispatcher.cancelSession(future.getRequestID()); + // launching build process from projectTaskQueue ensures that no other build process for this project is currently running + return projectTaskQueue.submit(new Callable, OSProcessHandler>>() { + public Pair, OSProcessHandler> call() throws Exception { + final RequestFuture future = new RequestFuture(new PreloadedProcessMessageHandler(project), UUID.randomUUID(), new RequestFuture.CancelAction() { + @Override + public void cancel(RequestFuture 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; + } } }); - myMessageDispatcher.registerBuildMessageHandler(future, null); - try { - 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 { @@ -1300,7 +1319,7 @@ public class BuildManager implements ApplicationComponent{ @Override public void projectClosing(Project project) { cancelPreloadedBuilds(project); - for (BasicFuture future : cancelAutoMakeTasks(project)) { + for (TaskFuture future : cancelAutoMakeTasks(project)) { future.waitFor(500, TimeUnit.MILLISECONDS); } } @@ -1460,5 +1479,88 @@ public class BuildManager implements ApplicationComponent{ return "/"; } } - + + private static final class DelegateFuture implements TaskFuture { + @Nullable + private TaskFuture myDelegate; + private Boolean myRequestedCancelState = null; + + @NotNull + public synchronized TaskFuture getDelegate() { + TaskFuture delegate = myDelegate; + while (delegate == null) { + try { + wait(); + } + catch (InterruptedException ignored) { + } + delegate = myDelegate; + } + return delegate; + } + + public synchronized boolean setDelegate(@NotNull TaskFuture 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 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 delegate; + synchronized (this) { + delegate = myDelegate; + if (delegate == null) { + return myRequestedCancelState != null; + } + } + return delegate.isCancelled(); + } + + public boolean isDone() { + final TaskFuture 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); + } + } + } diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JavaReferringObjectsValue.java b/java/debugger/impl/src/com/intellij/debugger/actions/JavaReferringObjectsValue.java index e892a425ca75..34959665d0cf 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/JavaReferringObjectsValue.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/JavaReferringObjectsValue.java @@ -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; + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java index 3df508e331a9..9cba64ac544a 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java @@ -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) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/api/BasicFuture.java b/jps/jps-builders/src/org/jetbrains/jps/api/BasicFuture.java index 0717de1c61e7..514ec5efc8d4 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/api/BasicFuture.java +++ b/jps/jps-builders/src/org/jetbrains/jps/api/BasicFuture.java @@ -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 implements Future { +public class BasicFuture implements TaskFuture { protected final Semaphore mySemaphore = new Semaphore(1); private final AtomicBoolean myDone = new AtomicBoolean(false); private final AtomicBoolean myCanceledState = new AtomicBoolean(false); diff --git a/jps/jps-builders/src/org/jetbrains/jps/api/TaskFuture.java b/jps/jps-builders/src/org/jetbrains/jps/api/TaskFuture.java new file mode 100644 index 000000000000..c09c8446422b --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/api/TaskFuture.java @@ -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 extends Future { + void waitFor(); + + boolean waitFor(long timeout, TimeUnit unit); +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java index e42d009d7122..7837b954da81 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java @@ -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; @@ -124,9 +125,12 @@ public class BuildMain { 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); @@ -162,10 +166,11 @@ public class BuildMain { 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 + // just failed to preload the project, the situation will be handled later, when real build starts } } else if (projectPathToPreload != null || globalsPathToPreload != null){ diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java index ac4f4a0b78fc..751b74b459e2 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java @@ -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 getSourceTransformers() { final Class transformerClass = JavaSourceTransformer.class; final ServiceLoader loader = ServiceLoader.load(transformerClass, transformerClass.getClassLoader()); diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsLoaderBase.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsLoaderBase.java index 18ad56192055..cf8c0cba3667 100644 --- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsLoaderBase.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsLoaderBase.java @@ -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"); } diff --git a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java index e03244e0e0e9..0bc853c76815 100644 --- a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java +++ b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java @@ -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 myPool; private final LimitedPool 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; } diff --git a/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesIndex.java b/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesIndex.java index b3e94c465e70..cf4249cecd65 100644 --- a/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesIndex.java +++ b/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesIndex.java @@ -55,7 +55,7 @@ import java.util.Map; public class DuplicatesIndex extends FileBasedIndexExtension implements PsiDependentIndex { static boolean ourEnabled = SystemProperties.getBooleanProperty("idea.enable.duplicates.online.calculation", isEnabledByDefault()); - static boolean ourEnabledLightProfiles = false; + static boolean ourEnabledLightProfiles = true; private static boolean isEnabledByDefault() { Application application = ApplicationManager.getApplication(); diff --git a/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesInspectionBase.java b/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesInspectionBase.java index f015fe21213b..f44a3e2953c7 100644 --- a/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesInspectionBase.java +++ b/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesInspectionBase.java @@ -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 descriptors = new SmartList(); + final Ref myProcessorRef = new Ref(); - final TreeMap reportedRanges = new TreeMap(); - final TIntObjectHashMap reportedFiles = new TIntObjectHashMap(); - final TIntObjectHashMap reportedPsi = new TIntObjectHashMap(); - 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 myProcessor; + @Override + public void process(final LighterAST ast, final LighterASTNode node, int hash) { + class LightDuplicatedCodeProcessor extends DuplicatedCodeProcessor { + + 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 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() { - 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 { - 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 map = reportedRanges.subMap(fragmentStartOffsetInteger, endOffset); - int newFragmentSize = !map.isEmpty() ? 0:1; + @Override + protected PsiElement getPsi(PsiFragment node) { + PsiElement[] elements = node.getElements(); - Iterator 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 descriptors = new SmartList(); + + if (processor != null) { + + for(Map.Entry 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 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 implements FileBasedIndex.ValueProcessor { + final TreeMap reportedRanges = new TreeMap(); + final TIntObjectHashMap reportedFiles = new TIntObjectHashMap(); + final TIntObjectHashMap reportedPsi = new TIntObjectHashMap(); + 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 map = reportedRanges.subMap(fragmentStartOffsetInteger, endOffset); + int newFragmentSize = !map.isEmpty() ? 0:1; + + Iterator 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); + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java index 37e9dc583628..1891e59711bd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java @@ -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 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 trinity = myUnresolvedRemovedMappings.get(matcher); + myRemovedMappings.put(matcher, Pair.create(fileType, trinity != null && trinity.third)); + } + } + Map> getRemovedMappings() { return myRemovedMappings; } diff --git a/platform/remote-servers/impl/src/META-INF/RemoteServers.xml b/platform/remote-servers/impl/src/META-INF/RemoteServers.xml index 0ce5eae571a9..eae970f46594 100644 --- a/platform/remote-servers/impl/src/META-INF/RemoteServers.xml +++ b/platform/remote-servers/impl/src/META-INF/RemoteServers.xml @@ -38,14 +38,16 @@ - - - - - - + + + + + + + + \ No newline at end of file diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowContent.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowContent.java index 8a46887be6cf..2d3fb8cc1b86 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowContent.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowContent.java @@ -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 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 getSelectedServerNodes() { - return myBuilder.getSelectedElements(ServerNode.class); - } - - public Set getSelectedDeploymentNodes() { - return myBuilder.getSelectedElements(DeploymentNode.class); - } - - public Set getSelectedRemoteServerNodes() { - return myBuilder.getSelectedElements(ServersTreeStructure.RemoteServerNode.class); - } - @Override public void dispose() { } diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/DeploymentNode.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/DeploymentNode.java index d859d61b7f3e..b147ee72df6c 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/DeploymentNode.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/DeploymentNode.java @@ -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(); diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/ServerNode.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/ServerNode.java index d17a730002fb..d3d160cff2e3 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/ServerNode.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/ServerNode.java @@ -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(); } diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/ServersTreeNode.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/ServersTreeNode.java new file mode 100644 index 000000000000..84cd735aaba6 --- /dev/null +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/ServersTreeNode.java @@ -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 { + +} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/ServersTreeStructure.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/ServersTreeStructure.java index 7a2a053779d5..5f1969ecbea3 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/ServersTreeStructure.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/ServersTreeStructure.java @@ -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 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 serverType = server.getType(); final DeploymentConfigurationManager configurationManager = DeploymentConfigurationManager.getInstance(doGetProject()); - List list = new ArrayList(configurationManager.getDeploymentConfigurations(serverType)); - list.add(null); - ListPopup popup = JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep("Deploy Configuration", list) { - @Override - public Icon getIconFor(RunnerAndConfigurationSettings value) { - return value != null ? serverType.getIcon() : null; - } + List list + = ContainerUtil.filter(configurationManager.getDeploymentConfigurations(serverType), + new Condition() { - @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(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> implements LogProvidingNode { + public class DeploymentLogNode extends AbstractTreeNode> implements ServersTreeNode, LogProvidingNode { @NotNull private final DeploymentNodeImpl myDeploymentNode; public DeploymentLogNode(@NotNull Pair value, @NotNull DeploymentNodeImpl deploymentNode) { diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/ChooseDeploymentAction.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/ChooseDeploymentAction.java new file mode 100644 index 000000000000..1a762f75cf01 --- /dev/null +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/ChooseDeploymentAction.java @@ -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 { + + public ChooseDeploymentAction() { + super("Deploy", "Deploy a chosen item to the selected remote server", AllIcons.Nodes.Deploy); + } + + @Override + protected Class getTargetNodeClass() { + return ServersTreeStructure.RemoteServerNode.class; + } + + @Override + protected void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e, ServersTreeStructure.RemoteServerNode node) { + node.deploy(e); + } +} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/ChooseDeploymentWithDebugAction.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/ChooseDeploymentWithDebugAction.java new file mode 100644 index 000000000000..55e2b1cb509f --- /dev/null +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/ChooseDeploymentWithDebugAction.java @@ -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 { + + public ChooseDeploymentWithDebugAction() { + super("Debug", "Deploy and debug a chosen item on the selected remote server", AllIcons.Actions.StartDebugger); + } + + @Override + protected Class getTargetNodeClass() { + return ServersTreeStructure.RemoteServerNode.class; + } + + @Override + protected void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e, ServersTreeStructure.RemoteServerNode node) { + node.deployWithDebug(e); + } +} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DebugServerAction.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DebugServerAction.java deleted file mode 100644 index f519478ef84c..000000000000 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DebugServerAction.java +++ /dev/null @@ -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(); - } -} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DeployAction.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DeployAction.java index c6a38404192e..4b8bbeeea7e7 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DeployAction.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DeployAction.java @@ -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 { + 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 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 getTargetNodeClass() { + return DeploymentNode.class; } @Override - protected boolean isEnabled(@NotNull ServersToolWindowContent content, AnActionEvent e) { - Set deploymentNodes = content.getSelectedDeploymentNodes(); - Set 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(); } } diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DeployAllAction.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DeployAllAction.java deleted file mode 100644 index 818f0ad7619e..000000000000 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DeployAllAction.java +++ /dev/null @@ -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(); - } -} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DeployWithDebugAction.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DeployWithDebugAction.java new file mode 100644 index 000000000000..d9c00380b9e2 --- /dev/null +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DeployWithDebugAction.java @@ -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 { + + public DeployWithDebugAction() { + super("Debug", "Deploy and debug the selected item", AllIcons.Actions.StartDebugger); + } + + @Override + protected Class 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(); + } +} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DeploymentActionBase.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DeploymentActionBase.java deleted file mode 100644 index 27bace389c41..000000000000 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DeploymentActionBase.java +++ /dev/null @@ -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 nodes, ServersToolWindowContent content, AnActionEvent e); - - protected abstract boolean isApplicable(@NotNull DeploymentNode node); - - @Override - public void doActionPerformed(@NotNull ServersToolWindowContent content, AnActionEvent e) { - List toPerform = new ArrayList(); - 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; - } -} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DeploymentConfigAction.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DeploymentConfigAction.java new file mode 100644 index 000000000000..e7f1960ae41f --- /dev/null +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/DeploymentConfigAction.java @@ -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 { + + public DeploymentConfigAction() { + super("Edit the selected deployment run configuration"); + } + + @Override + protected Class getTargetNodeClass() { + return ServersTreeStructure.DeploymentNodeImpl.class; + } + + @Override + protected boolean isVisible4(ServersTreeStructure.DeploymentNodeImpl node) { + return node.isEditConfigurationActionVisible(); + } + + @Override + protected void doActionPerformed(ServersTreeStructure.DeploymentNodeImpl node) { + node.editConfiguration(); + } +} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/EditConfigurationAction.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/EditConfigurationAction.java deleted file mode 100644 index 75d22a854114..000000000000 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/EditConfigurationAction.java +++ /dev/null @@ -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 deploymentNodes = content.getSelectedDeploymentNodes(); - Set 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 deploymentNodes = content.getSelectedDeploymentNodes(); - Set serverNodes = content.getSelectedServerNodes(); - if (deploymentNodes.size() + serverNodes.size() != 1) return false; - if (deploymentNodes.size() == 1) { - return deploymentNodes.iterator().next().isEditConfigurationActionEnabled(); - } - return true; - } -} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/EditConfigurationActionBase.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/EditConfigurationActionBase.java new file mode 100644 index 000000000000..05fcb95fede5 --- /dev/null +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/EditConfigurationActionBase.java @@ -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 extends ServersTreeAction { + + public EditConfigurationActionBase(String description) { + super("Edit Configuration", description, AllIcons.Actions.EditSource); + } +} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/RemoteServerConfigAction.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/RemoteServerConfigAction.java new file mode 100644 index 000000000000..b5f5456318da --- /dev/null +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/RemoteServerConfigAction.java @@ -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 { + + public RemoteServerConfigAction() { + super("Edit the selected remote server configuration"); + } + + @Override + protected Class getTargetNodeClass() { + return ServersTreeStructure.RemoteServerNode.class; + } + + @Override + protected void doActionPerformed(ServersTreeStructure.RemoteServerNode node) { + node.editConfiguration(); + } +} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/RemoteServerConnectAction.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/RemoteServerConnectAction.java new file mode 100644 index 000000000000..8fd5f7891748 --- /dev/null +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/RemoteServerConnectAction.java @@ -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 { + + public RemoteServerConnectAction() { + super("Connect", "Connect to the selected remote server", AllIcons.Actions.Execute); + } + + @Override + protected Class 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()); + } +} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/RemoteServerDisconnectAction.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/RemoteServerDisconnectAction.java new file mode 100644 index 000000000000..96f21e56671f --- /dev/null +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/RemoteServerDisconnectAction.java @@ -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 { + + public RemoteServerDisconnectAction() { + super("Disconnect", "Disconnect from the selected remote server", AllIcons.Actions.Suspend); + } + + @Override + protected Class 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(); + } + } +} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/RunServerAction.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/RunServerAction.java deleted file mode 100644 index aa16c77e2aeb..000000000000 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/RunServerAction.java +++ /dev/null @@ -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(); - } -} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/RunServerActionBase.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/RunServerActionBase.java deleted file mode 100644 index 07b1e4b683f1..000000000000 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/RunServerActionBase.java +++ /dev/null @@ -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(); -} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/ServerActionBase.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/ServerActionBase.java deleted file mode 100644 index 1b4d4f8bbd89..000000000000 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/ServerActionBase.java +++ /dev/null @@ -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 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); -} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/ServersTreeAction.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/ServersTreeAction.java new file mode 100644 index 000000000000..d86a708196d2 --- /dev/null +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/ServersTreeAction.java @@ -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 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 selectedElements = content.getBuilder().getSelectedElements(); + if (selectedElements.size() != 1) { + return null; + } + ServersTreeNode node = (ServersTreeNode)selectedElements.iterator().next(); + Class 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 getTargetNodeClass(); +} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/ServersTreeActionBase.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/ServersTreeActionBase.java deleted file mode 100644 index 7e505bd06aab..000000000000 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/ServersTreeActionBase.java +++ /dev/null @@ -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); -} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/SingleServerActionBase.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/SingleServerActionBase.java deleted file mode 100644 index 50ec63646922..000000000000 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/SingleServerActionBase.java +++ /dev/null @@ -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 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); -} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/StopServerAction.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/StopServerAction.java deleted file mode 100644 index 7984c119036c..000000000000 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/StopServerAction.java +++ /dev/null @@ -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(); - } -} diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/UndeployAction.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/UndeployAction.java index bc11f8aa94a8..50c247eabd91 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/UndeployAction.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/actions/UndeployAction.java @@ -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 { + public UndeployAction() { super("Undeploy", "Undeploy the selected item", AllIcons.Nodes.Undeploy); } @Override - protected boolean isApplicable(@NotNull DeploymentNode node) { + protected Class getTargetNodeClass() { + return DeploymentNode.class; + } + + @Override + protected boolean isEnabled4(DeploymentNode node) { return node.isUndeployActionEnabled(); } @Override - protected void perform(@NotNull List nodes, ServersToolWindowContent content, AnActionEvent e) { - for (DeploymentNode node : nodes) { - node.undeploy(); - } + protected void doActionPerformed(DeploymentNode node) { + node.undeploy(); } } diff --git a/platform/util/testSrc/com/intellij/util/text/DateFormatUtilTest.java b/platform/util/testSrc/com/intellij/util/text/DateFormatUtilTest.java index 4268ce9fc1bb..01046586dc5d 100644 --- a/platform/util/testSrc/com/intellij/util/text/DateFormatUtilTest.java +++ b/platform/util/testSrc/com/intellij/util/text/DateFormatUtilTest.java @@ -38,7 +38,7 @@ public class DateFormatUtilTest { @Test public void testBasics() throws ParseException { - Clock.setTime(2004, 11, 10, 17, 10); + Clock.setTime(2004, Calendar.DECEMBER, 10, 17, 10); doTestPrettyDate("Today", "10.12.2004 17.00.00"); doTestPrettyDate("Today", "10.12.2004 00.00.00"); @@ -49,7 +49,7 @@ public class DateFormatUtilTest { @Test public void testTime() throws Exception { - Clock.setTime(2004, 11, 10, 17, 10, 15); + Clock.setTime(1980, Calendar.DECEMBER, 10, 17, 10, 15); if (SystemInfo.isMac) { assertEquals("17:10", DateFormatUtil.formatTime(Clock.getTime())); @@ -60,7 +60,7 @@ public class DateFormatUtilTest { assertEquals("17:10:15", printTimeForLocale("de_DE.UTF-8", Clock.getTime())); } else if (SystemInfo.isWinVistaOrNewer) { - long time = new Date().getTime(); + long time = Clock.getTime(); assertEquals(printWindowsTime(time), DateFormatUtil.formatTimeWithSeconds(time)); } else { @@ -73,7 +73,7 @@ public class DateFormatUtilTest { @Test public void testPrettyDateTime() throws ParseException { - Clock.setTime(2004, 11, 10, 17, 0); + Clock.setTime(2004, Calendar.DECEMBER, 10, 17, 0); doTestDateTime("Moments ago", "10.12.2004 16.59.31"); doTestDateTime("A minute ago", "10.12.2004 16.59.29"); doTestDateTime("5 minutes ago", "10.12.2004 16.55.00"); @@ -82,7 +82,7 @@ public class DateFormatUtilTest { doTestDateTime("Yesterday " + DateFormatUtil.formatTime(DATE_FORMAT.parse("09.12.2004 15.00.00")), "09.12.2004 15.00.00"); doTestDateTime("Today " + DateFormatUtil.formatTime(DATE_FORMAT.parse("10.12.2004 19.00.00")), "10.12.2004 19.00.00"); - Clock.setTime(2004, 0, 1, 15, 53); + Clock.setTime(2004, Calendar.JANUARY, 1, 15, 53); doTestDateTime(DateFormatUtil.formatDateTime(DATE_FORMAT.parse("01.01.2003 15.53.00")), "01.01.2003 15.53.00"); doTestDateTime("Yesterday " + DateFormatUtil.formatTime(DATE_FORMAT.parse("31.12.2003 15.00.00")), "31.12.2003 15.00.00"); } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/UnnecessaryUnboxingInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/UnnecessaryUnboxingInspection.java index 9118a798f612..3da2504df69a 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/UnnecessaryUnboxingInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/UnnecessaryUnboxingInspection.java @@ -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; } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_superfluous_unboxing/UnnecessaryUnboxing.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_superfluous_unboxing/UnnecessaryUnboxing.java index 96d22a045a7a..e2a096e059ca 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_superfluous_unboxing/UnnecessaryUnboxing.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_superfluous_unboxing/UnnecessaryUnboxing.java @@ -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()); + } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_unboxing/UnnecessaryUnboxing.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_unboxing/UnnecessaryUnboxing.java index 366d21ddbae8..414960e321d6 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_unboxing/UnnecessaryUnboxing.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_unboxing/UnnecessaryUnboxing.java @@ -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()); + } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_unboxing/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_unboxing/expected.xml index 35c78be16577..d208b3f7867a 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_unboxing/expected.xml +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/unnecessary_unboxing/expected.xml @@ -55,5 +55,10 @@ Unnecessary unboxing Unnecessary unboxing <code>b.byteValue()</code> #loc - + + UnnecessaryUnboxing.java + 57 + Unnecessary unboxing + Unnecessary unboxing <code>((Double) o).doubleValue()</code> #loc + \ No newline at end of file diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java index eafe341d3989..8ea6b8618d71 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java @@ -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")) { diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryEditor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryEditor.java index 31584497f43a..3ad4b12de380 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryEditor.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryEditor.java @@ -43,7 +43,7 @@ import java.util.List; * @author Mikhail Golubev */ public class TrelloRepositoryEditor extends BaseRepositoryEditor { - 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 download() throws Exception { + LOG.debug("Updating information about boards available to user when repository setting are shown"); List boards = super.download(); if (myBoard == null) { return boards; @@ -157,6 +159,7 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor download() throws Exception { + LOG.debug("Updating information about lists of board " + myRepository.getCurrentBoard() + " when repository setting are shown"); List lists = super.download(); if (myList == null) { return lists; @@ -266,6 +269,7 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor boards) { myBoardComboBox.setModel(new DefaultComboBoxModel(boards.toArray())); @@ -296,6 +300,7 @@ public class TrelloRepositoryEditor extends BaseRepositoryEditor lists) { myListComboBox.setModel(new DefaultComboBoxModel(lists.toArray())); diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCChangeCourseInfo.java b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCChangeCourseInfo.java index 0f3b3ae4a092..a556cd1113f1 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCChangeCourseInfo.java +++ b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCChangeCourseInfo.java @@ -1,6 +1,7 @@ package org.jetbrains.plugins.coursecreator.actions; import com.intellij.ide.IdeView; +import com.intellij.ide.projectView.ProjectView; import com.intellij.ide.util.DirectoryChooserUtil; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; @@ -20,7 +21,7 @@ import javax.swing.*; public class CCChangeCourseInfo extends DumbAwareAction { public CCChangeCourseInfo() { - super("Change course information", "Change course information", null); + super("Change Course information", "Change Course Information", null); } @Override @@ -85,6 +86,7 @@ public class CCChangeCourseInfo extends DumbAwareAction { course.setAuthor(panel.getAuthor()); course.setName(panel.getName()); course.setDescription(panel.getDescription()); + ProjectView.getInstance(project).refresh(); } } @@ -93,6 +95,7 @@ public class CCChangeCourseInfo extends DumbAwareAction { CCNewProjectPanel myNewProjectPanel; public ChangeCourseInfoDialog(@Nullable Project project, CCNewProjectPanel panel) { super(project); + setTitle("Change Course Information"); myNewProjectPanel = panel; init(); } diff --git a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCRunTestsAction.java b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCRunTestsAction.java index 462678c477ad..777afc4e1a85 100644 --- a/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCRunTestsAction.java +++ b/python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCRunTestsAction.java @@ -84,6 +84,7 @@ public class CCRunTestsAction extends AnAction { if (lessonDir == null) return; if (course == null) return; final Lesson lesson = course.getLesson(lessonDir.getName()); + if (lesson == null) return; final Task task = lesson.getTask(taskDir.getName()); if (task == null) { presentation.setVisible(false); diff --git a/python/edu/src/com/jetbrains/python/edu/PyExecuteFileLineMarkerProvider.java b/python/edu/src/com/jetbrains/python/edu/PyExecuteFileLineMarkerProvider.java index 19acded8f238..0c0208b1f144 100644 --- a/python/edu/src/com/jetbrains/python/edu/PyExecuteFileLineMarkerProvider.java +++ b/python/edu/src/com/jetbrains/python/edu/PyExecuteFileLineMarkerProvider.java @@ -54,23 +54,28 @@ public class PyExecuteFileLineMarkerProvider implements LineMarkerProvider { return new LineMarkerGutterIconRenderer(this){ @Override public AnAction getClickAction() { - final DefaultActionGroup group = new DefaultActionGroup(); - group.add(new PyRunCurrentFileAction()); - final PyExecuteFileExtensionPoint[] extensions = - ApplicationManager.getApplication().getExtensions(PyExecuteFileExtensionPoint.EP_NAME); - for (PyExecuteFileExtensionPoint extension : extensions) { - final AnAction action = extension.getRunAction(); - group.add(action); - } - if (group.getChildrenCount() == 1) { - return new PyRunCurrentFileAction(); - } + return new AnAction() { @Override public void actionPerformed(@NotNull AnActionEvent e) { - final ListPopup popup = - new PopupFactoryImpl().createActionGroupPopup(null, group, e.getDataContext(), false, false, false, null, 5); - popup.showInBestPositionFor(e.getDataContext()); + final DefaultActionGroup group = new DefaultActionGroup(); + group.add(new PyRunCurrentFileAction()); + final PyExecuteFileExtensionPoint[] extensions = + ApplicationManager.getApplication().getExtensions(PyExecuteFileExtensionPoint.EP_NAME); + for (PyExecuteFileExtensionPoint extension : extensions) { + final AnAction action = extension.getRunAction(); + action.update(e); + if (e.getPresentation().isEnabled()) + group.add(action); + } + if (group.getChildrenCount() == 1) { + new PyRunCurrentFileAction().actionPerformed(e); + } + else { + final ListPopup popup = + new PopupFactoryImpl().createActionGroupPopup(null, group, e.getDataContext(), false, false, false, null, 5); + popup.showInBestPositionFor(e.getDataContext()); + } } }; } diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlEntityRefImpl.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlEntityRefImpl.java index b74834a28162..ee6248b6c1bf 100644 --- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlEntityRefImpl.java +++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlEntityRefImpl.java @@ -16,7 +16,10 @@ package com.intellij.psi.impl.source.xml; import com.intellij.ide.highlighter.DTDFileType; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.RecursionManager; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; import com.intellij.psi.search.PsiElementProcessor; @@ -49,8 +52,6 @@ public class XmlEntityRefImpl extends XmlElementImpl implements XmlEntityRef { super(XmlElementType.XML_ENTITY_REF); } - private static final Key EVALUATION_IN_PROCESS = Key.create("EvalKey"); - @Override public XmlEntityDecl resolve(PsiFile targetFile) { String text = getText(); @@ -77,12 +78,12 @@ public class XmlEntityRefImpl extends XmlElementImpl implements XmlEntityRef { if (value == null) { final PsiManager manager = element.getManager(); if(manager == null){ - return resolveEntity(targetElement, entityName, containingFile).getValue(); + return doResolveEntity(targetElement, entityName, containingFile).getValue(); } value = CachedValuesManager.getManager(manager.getProject()).createCachedValue(new CachedValueProvider() { @Override public Result compute() { - return resolveEntity(targetElement, entityName, containingFile); + return doResolveEntity(targetElement, entityName, containingFile); } }); @@ -95,95 +96,94 @@ public class XmlEntityRefImpl extends XmlElementImpl implements XmlEntityRef { private static final Key DISABLE_ENTITY_EXPAND = Key.create("disable.entity.expand"); - private static CachedValueProvider.Result resolveEntity(final PsiElement targetElement, final String entityName, PsiFile contextFile) { - if (targetElement.getUserData(EVALUATION_IN_PROCESS) != null) { - return new CachedValueProvider.Result(null,targetElement); - } - try { - targetElement.putUserData(EVALUATION_IN_PROCESS, ""); - final List deps = new ArrayList(); - final XmlEntityDecl[] result = {null}; + private static CachedValueProvider.Result doResolveEntity(final PsiElement targetElement, + final String entityName, + final PsiFile contextFile) { + return RecursionManager.doPreventingRecursion(targetElement, true, new Computable>() { + @Override + public CachedValueProvider.Result compute() { + final List deps = new ArrayList(); + final XmlEntityDecl[] result = {null}; - PsiElementProcessor processor = new PsiElementProcessor() { - @Override - public boolean execute(@NotNull PsiElement element) { - if (element instanceof XmlDoctype) { - XmlDoctype xmlDoctype = (XmlDoctype)element; - final String dtdUri = getDtdForEntity(xmlDoctype); - if (dtdUri != null) { - XmlFile file = XmlUtil.getContainingFile(element); - if (file == null) return true; - final XmlFile xmlFile = XmlUtil.findNamespace(file, dtdUri); - if (xmlFile != null) { - if (xmlFile != targetElement) { - deps.add(xmlFile); - if(!XmlUtil.processXmlElements(xmlFile, this,true)) return false; + PsiElementProcessor processor = new PsiElementProcessor() { + @Override + public boolean execute(@NotNull PsiElement element) { + if (element instanceof XmlDoctype) { + XmlDoctype xmlDoctype = (XmlDoctype)element; + final String dtdUri = getDtdForEntity(xmlDoctype); + if (dtdUri != null) { + XmlFile file = XmlUtil.getContainingFile(element); + if (file == null) return true; + final XmlFile xmlFile = XmlUtil.findNamespace(file, dtdUri); + if (xmlFile != null) { + if (xmlFile != targetElement) { + deps.add(xmlFile); + if (!XmlUtil.processXmlElements(xmlFile, this, true)) return false; + } } } + final XmlMarkupDecl markupDecl = xmlDoctype.getMarkupDecl(); + if (markupDecl != null) { + if (!XmlUtil.processXmlElements(markupDecl, this, true)) return false; + } } - final XmlMarkupDecl markupDecl = xmlDoctype.getMarkupDecl(); - if (markupDecl != null) { - if (!XmlUtil.processXmlElements(markupDecl, this, true)) return false; + else if (element instanceof XmlEntityDecl) { + XmlEntityDecl entityDecl = (XmlEntityDecl)element; + final String declName = entityDecl.getName(); + if (StringUtil.equals(declName, entityName)) { + result[0] = entityDecl; + return false; + } } + + return true; } - else if (element instanceof XmlEntityDecl) { - XmlEntityDecl entityDecl = (XmlEntityDecl)element; - final String declName = entityDecl.getName(); - if (declName.equals(entityName)) { - result[0] = entityDecl; - return false; - } + }; + FileViewProvider provider = targetElement.getContainingFile().getViewProvider(); + deps.add(provider.getPsi(provider.getBaseLanguage())); + + boolean notfound = PsiTreeUtil.processElements(targetElement, processor); + if (notfound) { + if (contextFile != targetElement && contextFile != null && contextFile.isValid()) { + notfound = PsiTreeUtil.processElements(contextFile, processor); } - - return true; } - }; - FileViewProvider provider = targetElement.getContainingFile().getViewProvider(); - deps.add(provider.getPsi(provider.getBaseLanguage())); - boolean notfound = PsiTreeUtil.processElements(targetElement, processor); - if (notfound) { - if (contextFile != targetElement && contextFile != null && contextFile.isValid()) { - notfound = PsiTreeUtil.processElements(contextFile, processor); - } - } + if (notfound && // no dtd ref at all + targetElement instanceof XmlFile && + deps.size() == 1 && + ((XmlFile)targetElement).getFileType() != DTDFileType.INSTANCE + ) { + XmlDocument document = ((XmlFile)targetElement).getDocument(); + final XmlTag rootTag = document != null ? document.getRootTag() : null; + XmlFile descriptorFile = null; - if (notfound && // no dtd ref at all - targetElement instanceof XmlFile && - deps.size() == 1 && - ((XmlFile)targetElement).getFileType() != DTDFileType.INSTANCE - ) { - XmlDocument document = ((XmlFile)targetElement).getDocument(); - final XmlTag rootTag = document.getRootTag(); - XmlFile descriptorFile = null; - - if (HtmlUtil.isHtml5Document(document)) { - descriptorFile = XmlUtil.findXmlFile((XmlFile)targetElement, Html5SchemaProvider.getCharsDtdLocation()); - } else if (rootTag != null && document.getUserData(DISABLE_ENTITY_EXPAND) == null) { - final XmlElementDescriptor descriptor = rootTag.getDescriptor(); + if (HtmlUtil.isHtml5Document(document)) { + descriptorFile = XmlUtil.findXmlFile((XmlFile)targetElement, Html5SchemaProvider.getCharsDtdLocation()); + } + else if (rootTag != null && document.getUserData(DISABLE_ENTITY_EXPAND) == null) { + final XmlElementDescriptor descriptor = rootTag.getDescriptor(); if (descriptor != null && !(descriptor instanceof AnyXmlElementDescriptor)) { PsiElement element = descriptor.getDeclaration(); - final PsiFile containingFile = element != null ? element.getContainingFile():null; - descriptorFile = containingFile instanceof XmlFile ? (XmlFile)containingFile:null; + final PsiFile containingFile = element != null ? element.getContainingFile() : null; + descriptorFile = containingFile instanceof XmlFile ? (XmlFile)containingFile : null; } + } + if (descriptorFile != null && + !descriptorFile.getName().equals(((XmlFile)targetElement).getName() + ".dtd")) { + deps.add(descriptorFile); + XmlUtil.processXmlElements( + descriptorFile, + processor, + true + ); + } } - if (descriptorFile != null && - !descriptorFile.getName().equals(((XmlFile)targetElement).getName() + ".dtd")) { - deps.add(descriptorFile); - XmlUtil.processXmlElements( - descriptorFile, - processor, - true - ); - } - } - return new CachedValueProvider.Result(result[0], ArrayUtil.toObjectArray(deps)); - } - finally { - targetElement.putUserData(EVALUATION_IN_PROCESS, null); - } + return new CachedValueProvider.Result(result[0], ArrayUtil.toObjectArray(deps)); + } + }); } private static String getDtdForEntity(XmlDoctype xmlDoctype) { @@ -214,7 +214,7 @@ public class XmlEntityRefImpl extends XmlElementImpl implements XmlEntityRef { @Override @NotNull public PsiReference[] getReferences() { - return ReferenceProvidersRegistry.getReferencesFromProviders(this,XmlEntityRef.class); + return ReferenceProvidersRegistry.getReferencesFromProviders(this); } @Override