diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant index 2799ae550865..8e2376b71c55 100644 --- a/build/scripts/utils.gant +++ b/build/scripts/utils.gant @@ -691,6 +691,26 @@ private String submapToXml(Map properties, List keys) { return buff.toString() } +private List getChildren(File file) { + if (!file.isDirectory()) return [] + return file.listFiles().sort { File f -> f.name.toLowerCase() } +} + +binding.setVariable("getCustomJDK", { File customJdkDir -> + getChildren(customJdkDir).each { + if (it.getName().endsWith(".tar.gz")) { + def customJdkFileName = it.getAbsolutePath().substring(0, it.getAbsolutePath().length() - 3) + if (new File(customJdkFileName).exists()){ ant.delete(file: customJdkFileName) } + if (new File("${home}/build/jdk/custom_jdk_${buildNumber}.tar").exists()){ + ant.delete(file: "${home}/build/jdk/custom_jdk_${buildNumber}.tar") + } + ant.gunzip(src: it.getAbsolutePath()) + projectBuilder.info("customJdkFileName: " + customJdkFileName) + ant.copy(file: customJdkFileName, tofile: "${home}/build/jdk/custom_jdk_${buildNumber}.tar") + } + } +}) + binding.setVariable("buildWinZip", { String zipPath, List paths -> projectBuilder.stage(".win.zip") 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 a35a03630ad9..a5685017d365 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java @@ -73,7 +73,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; import org.jetbrains.jps.api.CmdlineProtoUtil; import org.jetbrains.jps.api.CmdlineRemoteProto; -import org.jetbrains.jps.api.RequestFuture; +import org.jetbrains.jps.api.TaskFuture; import org.jetbrains.jps.model.java.JavaSourceRootType; import javax.swing.*; @@ -138,7 +138,7 @@ public class CompileDriver { return; } try { - final RequestFuture future = compileInExternalProcess(compileContext, true); + final TaskFuture future = compileInExternalProcess(compileContext, true); if (future != null) { while (!future.waitFor(200L, TimeUnit.MILLISECONDS)) { if (indicator.isCanceled()) { @@ -194,7 +194,7 @@ public class CompileDriver { } @Nullable - private RequestFuture compileInExternalProcess(final @NotNull CompileContextImpl compileContext, final boolean onlyCheckUpToDate) + private TaskFuture compileInExternalProcess(final @NotNull CompileContextImpl compileContext, final boolean onlyCheckUpToDate) throws Exception { final CompileScope scope = compileContext.getCompileScope(); final Collection paths = CompileScopeUtil.fetchFiles(compileContext); @@ -400,7 +400,7 @@ public class CompileDriver { return; } - final RequestFuture future = compileInExternalProcess(compileContext, false); + final TaskFuture future = compileInExternalProcess(compileContext, false); if (future != null) { while (!future.waitFor(200L, TimeUnit.MILLISECONDS)) { if (indicator.isCanceled()) { @@ -646,7 +646,6 @@ public class CompileDriver { final Module[] scopeModules = scope.getAffectedModules(); final List modulesWithoutOutputPathSpecified = new ArrayList(); final List modulesWithoutJdkAssigned = new ArrayList(); - final CompilerConfiguration config = CompilerConfiguration.getInstance(myProject); final CompilerManager compilerManager = CompilerManager.getInstance(myProject); for (final Module module : scopeModules) { if (!compilerManager.isValidationEnabled(module)) { 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 bc31490a54b6..efaf9e2b4346 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -58,10 +58,7 @@ import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl; import com.intellij.openapi.roots.*; import com.intellij.openapi.startup.StartupManager; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.ShutDownTracker; -import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; @@ -112,8 +109,7 @@ import java.net.InetSocketAddress; import java.nio.charset.Charset; import java.util.*; import java.util.List; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicBoolean; import static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope; @@ -152,8 +148,10 @@ public class BuildManager implements ApplicationComponent{ private final File mySystemDirectory; private final ProjectManager myProjectManager; - private final Map 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 BuildProcessClasspathManager myClasspathManager = new BuildProcessClasspathManager(); private final SequentialTaskExecutor myRequestsProcessor = new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE); private final Map myProjectDataMap = Collections.synchronizedMap(new HashMap()); @@ -385,6 +383,8 @@ public class BuildManager implements ApplicationComponent{ } public void clearState(Project project) { + cancelPreloadedBuilds(project); + final String projectPath = getProjectPath(project); synchronized (myProjectDataMap) { final ProjectData data = myProjectDataMap.get(projectPath); @@ -447,7 +447,7 @@ public class BuildManager implements ApplicationComponent{ } final List scopes = CmdlineProtoUtil.createAllModulesScopes(false); final AutoMakeMessageHandler handler = new AutoMakeMessageHandler(project); - final RequestFuture 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 RequestFuture future = entry.getKey(); + final TaskFuture future = entry.getKey(); future.cancel(false); futures.add(future); } @@ -540,211 +540,261 @@ public class BuildManager implements ApplicationComponent{ return futures; } + private void cancelPreloadedBuilds(Project project) { + final String projectPath = getProjectPath(project); + runCommand(new Runnable() { + @Override + public void run() { + Pair, 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 + getProjectData(projectPath).taskQueue.submit(new Runnable() { + @Override + public void run() { + future.waitFor(); + } + }); + } + } + }); + } + @Nullable - public RequestFuture 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 UUID sessionId = UUID.randomUUID(); - final boolean isAutomake = messageHandler instanceof AutoMakeMessageHandler; - final BuilderMessageHandler handler = new MessageHandlerWrapper(messageHandler) { - @Override - public void buildStarted(UUID sessionId) { - super.buildStarted(sessionId); - try { - ApplicationManager.getApplication().getMessageBus().syncPublisher(BuildManagerListener.TOPIC).buildStarted(project, sessionId, isAutomake); - } - catch (Throwable e) { - LOG.error(e); - } - } - - @Override - public void sessionTerminated(UUID sessionId) { - try { - super.sessionTerminated(sessionId); - } - finally { - try { - ApplicationManager.getApplication().getMessageBus().syncPublisher(BuildManagerListener.TOPIC).buildFinished(project, sessionId, isAutomake); - } - catch (Throwable e) { - LOG.error(e); - } - } - } - }; - // ensure server is listening - if (myListenPort < 0) { - try { - synchronized (this) { - if (myListenPort < 0) { - myListenPort = startListening(); - } - } - } - catch (Exception e) { - handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), null)); - handler.sessionTerminated(sessionId); - return null; - } + final BuilderMessageHandler handler = new NotifyingMessageHandler(project, messageHandler, messageHandler instanceof AutoMakeMessageHandler); + try { + ensureListening(); + } + catch (Exception e) { + final UUID sessionId = UUID.randomUUID(); // the actual session did not start, use random UUID + handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), null)); + handler.sessionTerminated(sessionId); + return null; } - try { - final RequestFuture future = 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 (future.isCancelled() || project.isDisposed()) { - handler.sessionTerminated(sessionId); - future.setDone(); - return; - } - final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals = - CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings.newBuilder() - .setGlobalOptionsPath(PathManager.getOptionsPath()) - .build(); - CmdlineRemoteProto.Message.ControllerMessage.FSEvent currentFSChanges; - final SequentialTaskExecutor projectTaskQueue; - synchronized (myProjectDataMap) { - ProjectData data = myProjectDataMap.get(projectPath); - if (data == null) { - data = new ProjectData(new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE)); - myProjectDataMap.put(projectPath, data); - } - if (isRebuild) { - data.dropChanges(); - } - if (IS_UNIT_TEST_MODE) { - LOG.info("Scheduling build for " + - projectPath + - "; CHANGED: " + - new HashSet(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 (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; + } - myMessageDispatcher.registerBuildMessageHandler(sessionId, new MessageHandlerWrapper(handler) { + 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 sessionTerminated(UUID sessionId) { + public void run() { + Throwable execFailure = null; try { - super.sessionTerminated(sessionId); - } - finally { - future.setDone(); - } - } - }, params); - - try { - projectTaskQueue.submit(new Runnable() { - @Override - public void run() { - Throwable execFailure = null; - try { - if (project.isDisposed()) { + if (project.isDisposed()) { + if (usingPreloadedProcess) { + future.cancel(true); + } + else { return; } - myBuildsInProgress.put(projectPath, future); - final OSProcessHandler processHandler = launchBuildProcess(project, myListenPort, sessionId); - final StringBuilder stdErrOutput = new StringBuilder(); + } + myBuildsInProgress.put(projectPath, future); + final OSProcessHandler processHandler; + final StringBuilder errorsOnLaunch = new StringBuilder(); + if (usingPreloadedProcess) { + final boolean paramsSent = myMessageDispatcher.sendBuildParameters(future.getRequestID(), params); + if (!paramsSent) { + myMessageDispatcher.cancelSession(future.getRequestID()); + } + processHandler = preloaded.second; + } + else { + processHandler = launchBuildProcess(project, myListenPort, sessionId, false); processHandler.addProcessListener(new ProcessAdapter() { @Override public void onTextAvailable(ProcessEvent event, Key outputType) { - // re-translate builder's output to idea.log - final String text = event.getText(); - if (!StringUtil.isEmptyOrSpaces(text)) { - LOG.info("BUILDER_PROCESS [" + outputType.toString() + "]: " + text.trim()); - if (stdErrOutput.length() < 1024 && ProcessOutputTypes.STDERR.equals(outputType)) { - stdErrOutput.append(text); + if (ProcessOutputTypes.STDERR.equals(outputType)) { + if (errorsOnLaunch.length() < 1024) { + final String text = event.getText(); + if (!StringUtil.isEmptyOrSpaces(text)) { + errorsOnLaunch.append(text); + } } } } }); processHandler.startNotify(); - final boolean terminated = processHandler.waitFor(); - if (terminated) { - final int exitValue = processHandler.getProcess().exitValue(); - if (exitValue != 0) { - final StringBuilder msg = new StringBuilder(); - msg.append("Abnormal build process termination: "); - if (stdErrOutput.length() > 0) { - msg.append("\n").append(stdErrOutput); - } - else { - msg.append("unknown error"); - } - handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(msg.toString(), null)); + } + + final boolean terminated = processHandler.waitFor(); + if (terminated) { + final int exitValue = processHandler.getProcess().exitValue(); + if (exitValue != 0) { + final StringBuilder msg = new StringBuilder(); + msg.append("Abnormal build process termination: "); + if (errorsOnLaunch.length() > 0) { + msg.append("\n").append(errorsOnLaunch); } - } - else { - handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure("Disconnected from build process", null)); + else { + msg.append("unknown error"); + } + handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(msg.toString(), null)); } } - catch (Throwable e) { - execFailure = e; - } - finally { - myBuildsInProgress.remove(projectPath); - if (myMessageDispatcher.getAssociatedChannel(sessionId) == null) { - // either the connection has never been established (process not started or execution failed), or no messages were sent from the launched process. - // in this case the session cannot be unregistered by the message dispatcher - final BuilderMessageHandler unregistered = myMessageDispatcher.unregisterBuildMessageHandler(sessionId); - if (unregistered != null) { - if (execFailure != null) { - unregistered.handleFailure(sessionId, CmdlineProtoUtil.createFailure(execFailure.getMessage(), execFailure)); - } - unregistered.sessionTerminated(sessionId); - } - } + else { + handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure("Disconnected from build process", null)); } } - }); - } - catch (Throwable e) { - final BuilderMessageHandler unregistered = myMessageDispatcher.unregisterBuildMessageHandler(sessionId); - if (unregistered != null) { - unregistered.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), e)); - unregistered.sessionTerminated(sessionId); + catch (Throwable e) { + execFailure = e; + } + finally { + myBuildsInProgress.remove(projectPath); + if (myMessageDispatcher.getAssociatedChannel(sessionId) == null) { + // either the connection has never been established (process not started or execution failed), or no messages were sent from the launched process. + // in this case the session cannot be unregistered by the message dispatcher + final BuilderMessageHandler unregistered = myMessageDispatcher.unregisterBuildMessageHandler(sessionId); + if (unregistered != null) { + if (execFailure != null) { + unregistered.handleFailure(sessionId, CmdlineProtoUtil.createFailure(execFailure.getMessage(), execFailure)); + } + unregistered.sessionTerminated(sessionId); + } + } + + if (Registry.is("compiler.process.preload") && !project.isDisposed()) { + runCommand(new Runnable() { + public void run() { + try { + final Future, OSProcessHandler>> preloadResult = launchPreloadedBuildProcess(project, projectTaskQueue); + myPreloadedBuilds.put(projectPath, preloadResult); + } + catch (Exception e) { + LOG.info("Error pre-loading build process for project " + projectPath, e); + } + } + }); + } + + } } + }); + } + catch (Throwable e) { + final BuilderMessageHandler unregistered = myMessageDispatcher.unregisterBuildMessageHandler(sessionId); + if (unregistered != null) { + unregistered.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), e)); + unregistered.sessionTerminated(sessionId); } } - }); + } + }); - return future; - } - catch (Throwable e) { - handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), e)); - handler.sessionTerminated(sessionId); - } + return _future; + } - return null; + @NotNull + private ProjectData getProjectData(String projectPath) { + synchronized (myProjectDataMap) { + ProjectData data = myProjectDataMap.get(projectPath); + if (data == null) { + data = new ProjectData(new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE)); + myProjectDataMap.put(projectPath, data); + } + return data; + } + } + + private void ensureListening() throws Exception { + if (myListenPort < 0) { + synchronized (this) { + if (myListenPort < 0) { + myListenPort = startListening(); + } + } + } } @Override @@ -762,7 +812,45 @@ public class BuildManager implements ApplicationComponent{ return "com.intellij.compiler.server.BuildManager"; } - private OSProcessHandler launchBuildProcess(Project project, final int port, final UUID sessionId) throws ExecutionException { + private Future, OSProcessHandler>> launchPreloadedBuildProcess(final Project project, SequentialTaskExecutor projectTaskQueue) throws Exception { + ensureListening(); + + // launching build process from projectTaskQueue ensures that no other build process for this project is currently running + return projectTaskQueue.submit(new Callable, 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; + } + } + }); + } + + private OSProcessHandler launchBuildProcess(Project project, final int port, final UUID sessionId, boolean requestProjectPreload) throws ExecutionException { final String compilerPath; final String vmExecutablePath; JavaSdkVersion sdkVersion = null; @@ -863,6 +951,11 @@ public class BuildManager implements ApplicationComponent{ } cmdLine.addParameter("-Djdt.compiler.useSingleThread=true"); // always run eclipse compiler in single-threaded mode + if (requestProjectPreload) { + cmdLine.addParameter("-Dpreload.project.path=" + FileUtil.toCanonicalPath(getProjectPath(project))); + cmdLine.addParameter("-Dpreload.config.path=" + FileUtil.toCanonicalPath(PathManager.getOptionsPath())); + } + final String shouldGenerateIndex = System.getProperty(GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION); if (shouldGenerateIndex != null) { cmdLine.addParameter("-D"+ GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION +"=" + shouldGenerateIndex); @@ -961,12 +1054,24 @@ public class BuildManager implements ApplicationComponent{ final Process process = cmdLine.createProcess(); - return new OSProcessHandler(process, null, mySystemCharset) { + final OSProcessHandler processHandler = new OSProcessHandler(process, null, mySystemCharset) { @Override protected boolean shouldDestroyProcessRecursively() { return true; } }; + processHandler.addProcessListener(new ProcessAdapter() { + @Override + public void onTextAvailable(ProcessEvent event, Key outputType) { + // re-translate builder's output to idea.log + final String text = event.getText(); + if (!StringUtil.isEmptyOrSpaces(text)) { + LOG.info("BUILDER_PROCESS [" + outputType.toString() + "]: " + text.trim()); + } + } + }); + + return processHandler; } public File getBuildSystemDirectory() { @@ -1086,6 +1191,50 @@ public class BuildManager implements ApplicationComponent{ } } + private static class NotifyingMessageHandler extends DelegatingMessageHandler { + private final Project myProject; + private final BuilderMessageHandler myDelegateHandler; + private boolean myIsAutomake; + + public NotifyingMessageHandler(@NotNull Project project, @NotNull BuilderMessageHandler delegateHandler, final boolean isAutomake) { + myProject = project; + myDelegateHandler = delegateHandler; + myIsAutomake = isAutomake; + } + + @Override + protected BuilderMessageHandler getDelegateHandler() { + return myDelegateHandler; + } + + @Override + public void buildStarted(UUID sessionId) { + super.buildStarted(sessionId); + try { + ApplicationManager + .getApplication().getMessageBus().syncPublisher(BuildManagerListener.TOPIC).buildStarted(myProject, sessionId, myIsAutomake); + } + catch (Throwable e) { + LOG.error(e); + } + } + + @Override + public void sessionTerminated(UUID sessionId) { + try { + super.sessionTerminated(sessionId); + } + finally { + try { + ApplicationManager.getApplication().getMessageBus().syncPublisher(BuildManagerListener.TOPIC).buildFinished(myProject, sessionId, myIsAutomake); + } + catch (Throwable e) { + LOG.error(e); + } + } + } + } + private class ProjectWatcher extends ProjectManagerAdapter { private final Map myConnections = new HashMap(); @@ -1169,7 +1318,8 @@ public class BuildManager implements ApplicationComponent{ @Override public void projectClosing(Project project) { - for (RequestFuture future : cancelAutoMakeTasks(project)) { + cancelPreloadedBuilds(project); + for (TaskFuture future : cancelAutoMakeTasks(project)) { future.waitFor(500, TimeUnit.MILLISECONDS); } } @@ -1185,13 +1335,14 @@ public class BuildManager implements ApplicationComponent{ } private static class ProjectData { + @NotNull final SequentialTaskExecutor taskQueue; private final Set myChanged = new THashSet(); private final Set myDeleted = new THashSet(); private long myNextEventOrdinal = 0L; private boolean myNeedRescan = true; - private ProjectData(SequentialTaskExecutor taskQueue) { + private ProjectData(@NotNull SequentialTaskExecutor taskQueue) { this.taskQueue = taskQueue; } @@ -1328,5 +1479,88 @@ public class BuildManager implements ApplicationComponent{ return "/"; } } - + + private static final class DelegateFuture 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/compiler/impl/src/com/intellij/compiler/server/BuildMessageDispatcher.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildMessageDispatcher.java index d324a620155b..59c19f0ad7fe 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildMessageDispatcher.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildMessageDispatcher.java @@ -21,10 +21,12 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.util.AttributeKey; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.io.SimpleChannelInboundHandlerAdapter; import org.jetbrains.jps.api.CmdlineProtoUtil; import org.jetbrains.jps.api.CmdlineRemoteProto; +import org.jetbrains.jps.api.RequestFuture; import java.util.Map; import java.util.Set; @@ -41,19 +43,34 @@ class BuildMessageDispatcher extends SimpleChannelInboundHandlerAdapter SESSION_DATA = AttributeKey.valueOf("BuildMessageDispatcher.sessionData"); - private final Map myMessageHandlers = new ConcurrentHashMap(16, 0.75f, 1); + private final Map mySessionDescriptors = new ConcurrentHashMap(16, 0.75f, 1); private final Set myCanceledSessions = new ConcurrentHashSet(); - public void registerBuildMessageHandler(UUID sessionId, - BuilderMessageHandler handler, - CmdlineRemoteProto.Message.ControllerMessage params) { - myMessageHandlers.put(sessionId, new SessionData(sessionId, handler, params)); + public void registerBuildMessageHandler(@NotNull final RequestFuture future, @Nullable CmdlineRemoteProto.Message.ControllerMessage params) { + final BuilderMessageHandler wrappedHandler = new DelegatingMessageHandler() { + @Override + protected BuilderMessageHandler getDelegateHandler() { + return future.getMessageHandler(); + } + + @Override + public void sessionTerminated(UUID sessionId) { + try { + super.sessionTerminated(sessionId); + } + finally { + future.setDone(); + } + } + }; + final UUID sessionId = future.getRequestID(); + mySessionDescriptors.put(sessionId, new SessionData(sessionId, wrappedHandler, params)); } @Nullable public BuilderMessageHandler unregisterBuildMessageHandler(UUID sessionId) { myCanceledSessions.remove(sessionId); - final SessionData data = myMessageHandlers.remove(sessionId); + final SessionData data = mySessionDescriptors.remove(sessionId); return data != null? data.handler : null; } @@ -74,11 +91,36 @@ class BuildMessageDispatcher extends SimpleChannelInboundHandlerAdapter {}", lambdaExpression); + .createExpressionFromText(lambdaExpression.getParameterList().getText() + " -> {}", lambdaExpression.getParent()); PsiCodeBlock newBody = (PsiCodeBlock)expressionFromText.getBody(); LOG.assertTrue(newBody != null); newBody.add(declaration); - PsiStatement lastBodyStatement = elementFactory.createStatementFromText("a;", lambdaExpression); - ((PsiExpressionStatement)lastBodyStatement).getExpression().replace(lambdaExpressionBody); + lambdaExpression = + (PsiLambdaExpression)lambdaExpression.replace(elementFactory.createExpressionFromText( + lambdaExpression.getParameterList().getText() + " -> " + invalidBody.getText(), lambdaExpression)); + + final PsiElement lambdaExpressionBody = lambdaExpression.getBody(); + LOG.assertTrue(lambdaExpressionBody != null); + final PsiStatement lastBodyStatement; + if (LambdaUtil.getFunctionalInterfaceReturnType(lambdaExpression) == PsiType.VOID) { + lastBodyStatement = elementFactory.createStatementFromText("a;", lambdaExpression); + ((PsiExpressionStatement)lastBodyStatement).getExpression().replace(lambdaExpressionBody); + } + else { + lastBodyStatement = elementFactory.createStatementFromText("return a;", lambdaExpression); + final PsiExpression returnValue = ((PsiReturnStatement)lastBodyStatement).getReturnValue(); + LOG.assertTrue(returnValue != null); + returnValue.replace(lambdaExpressionBody); + } newBody.add(lastBodyStatement); - PsiLambdaExpression copy = (PsiLambdaExpression)lambdaExpression.replace(expressionFromText); + final PsiLambdaExpression copy = (PsiLambdaExpression)lambdaExpression.replace(expressionFromText); newBody = (PsiCodeBlock)copy.getBody(); LOG.assertTrue(newBody != null); - - if (LambdaUtil.getFunctionalInterfaceReturnType(copy) != PsiType.VOID) { - PsiExpressionStatement lastStatement = (PsiExpressionStatement)newBody.getStatements()[1]; - PsiReturnStatement returnStatement = (PsiReturnStatement)elementFactory.createStatementFromText("return a;", copy); - final PsiExpression returnValue = returnStatement.getReturnValue(); - LOG.assertTrue(returnValue != null); - returnValue.replace(lastStatement.getExpression()); - lastStatement.replace(returnStatement); - } declaration = newBody.getStatements()[0]; declaration = (PsiStatement)JavaCodeStyleManager.getInstance(declaration.getProject()).shortenClassReferences(declaration); } diff --git a/java/java-tests/testData/refactoring/extractMethodObject4Debugger/OnClosingBrace.java b/java/java-tests/testData/refactoring/extractMethodObject4Debugger/OnClosingBrace.java new file mode 100644 index 000000000000..48a25567d205 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodObject4Debugger/OnClosingBrace.java @@ -0,0 +1,10 @@ +class Sample { + + void a() { + System.out.println(""); + } + + private int foo() { + return 1; + } +} diff --git a/java/java-tests/testData/refactoring/extractMethodObject4Debugger/OnClosingBraceLocalClass.java b/java/java-tests/testData/refactoring/extractMethodObject4Debugger/OnClosingBraceLocalClass.java new file mode 100644 index 000000000000..010af145aaca --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodObject4Debugger/OnClosingBraceLocalClass.java @@ -0,0 +1,12 @@ +class Sample { + + void a() { + class Local { + + } + } + + private int foo() { + return 1; + } +} diff --git a/java/java-tests/testData/refactoring/extractMethodObject4Debugger/OnEmptyMethod.java b/java/java-tests/testData/refactoring/extractMethodObject4Debugger/OnEmptyMethod.java new file mode 100644 index 000000000000..6436369d9d84 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodObject4Debugger/OnEmptyMethod.java @@ -0,0 +1,7 @@ +class Sample { + static {} + + int foo() { + return 1; + } +} diff --git a/java/java-tests/testData/refactoring/extractMethodObject4Debugger/OnFieldInitialization.java b/java/java-tests/testData/refactoring/extractMethodObject4Debugger/OnFieldInitialization.java new file mode 100644 index 000000000000..e1746e57ed23 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodObject4Debugger/OnFieldInitialization.java @@ -0,0 +1,7 @@ +class Sample { + int i = 0; + + int foo() { + return 1; + } +} diff --git a/java/java-tests/testData/refactoring/extractMethodObject4Debugger/OnSuperConstructorCall.java b/java/java-tests/testData/refactoring/extractMethodObject4Debugger/OnSuperConstructorCall.java new file mode 100644 index 000000000000..69d6f91a4643 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodObject4Debugger/OnSuperConstructorCall.java @@ -0,0 +1,9 @@ +class Sample { + public Sample() { + super(); + } + + int foo() { + return 1; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/PutInLambdaBodyVoidValueConflict.after.java b/java/java-tests/testData/refactoring/introduceVariable/PutInLambdaBodyVoidValueConflict.after.java new file mode 100644 index 000000000000..6315c2590032 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/PutInLambdaBodyVoidValueConflict.after.java @@ -0,0 +1,20 @@ +class Foo { + interface I { + T m(Object op); + } + + interface J { + void m(T o); + } + + + void f(J r) {} + void f(I r) {} + + { + f((a) -> { + int c = 1; + return c; + }); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/PutInLambdaBodyVoidValueConflict.java b/java/java-tests/testData/refactoring/introduceVariable/PutInLambdaBodyVoidValueConflict.java new file mode 100644 index 000000000000..bdea215a08a4 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/PutInLambdaBodyVoidValueConflict.java @@ -0,0 +1,17 @@ +class Foo { + interface I { + T m(Object op); + } + + interface J { + void m(T o); + } + + + void f(J r) {} + void f(I r) {} + + { + f((a) -> 1); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodObject4DebuggerTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodObject4DebuggerTest.java index af1fee9363dc..d6440fd5de19 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodObject4DebuggerTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodObject4DebuggerTest.java @@ -214,6 +214,56 @@ public class ExtractMethodObject4DebuggerTest extends LightRefactoringTestCase { " }", false); } + public void testOnClosingBrace() throws Exception { + doTest(" foo()", "int result = new Test().invoke();", + + "public class Test {\n" + + " public int invoke() {\n" + + " return foo();\n" + + " }\n" + + " }"); + } + + public void testOnClosingBraceLocalClass() throws Exception { + doTest(" foo()", "int result = new Test().invoke();", + + "public class Test {\n" + + " public int invoke() {\n" + + " return foo();\n" + + " }\n" + + " }"); + } + + public void testOnFieldInitialization() throws Exception { + doTest(" foo()", "int result = new Test().invoke();", + + "public class Test {\n" + + " public int invoke() {\n" + + " return foo();\n" + + " }\n" + + " }"); + } + + public void testOnEmptyMethod() throws Exception { + doTest(" foo()", "int result = Test.invoke();", + + "public static class Test {\n" + + " public static int invoke() {\n" + + " return foo();\n" + + " }\n" + + " }"); + } + + public void testOnSuperConstructorCall() throws Exception { + doTest(" foo()", "int result = new Test().invoke();", + + "public class Test {\n" + + " public int invoke() {\n" + + " return foo();\n" + + " }\n" + + " }"); + } + @Override protected Sdk getProjectJDK() { return IdeaTestUtil.getMockJdk18(); diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java index 29f792330bbf..2e2a6cc488a3 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java @@ -441,6 +441,10 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase { doTest(new MockIntroduceVariableHandler("c", false, false, false, "int")); } + public void testPutInLambdaBodyVoidValueConflict() { + doTest(new MockIntroduceVariableHandler("c", false, false, false, "int")); + } + public void testNormalizeDeclarations() { doTest(new MockIntroduceVariableHandler("i3", false, false, false, "int")); } 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 8a082740ebee..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; @@ -35,7 +36,11 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.api.CmdlineProtoUtil; import org.jetbrains.jps.api.CmdlineRemoteProto; import org.jetbrains.jps.api.GlobalOptions; +import org.jetbrains.jps.incremental.MessageHandler; import org.jetbrains.jps.incremental.Utils; +import org.jetbrains.jps.incremental.fs.BuildFSState; +import org.jetbrains.jps.incremental.fs.FSState; +import org.jetbrains.jps.incremental.messages.BuildMessage; import org.jetbrains.jps.service.SharedThreadPool; import java.io.*; @@ -49,6 +54,9 @@ import java.util.concurrent.TimeUnit; */ @SuppressWarnings("UseOfSystemOutOrSystemErr") public class BuildMain { + private static final String PRELOAD_PROJECT_PATH = "preload.project.path"; + private static final String PRELOAD_CONFIG_PATH = "preload.config.path"; + private static final String LOG_CONFIG_FILE_NAME = "build-log.xml"; private static final String LOG_FILE_NAME = "build.log"; private static final String DEFAULT_LOGGER_CONFIG = "defaultLogConfig.xml"; @@ -65,19 +73,10 @@ public class BuildMain { private static final int SYSTEM_DIR_ARG = SESSION_ID_ARG + 1; private static NioEventLoopGroup ourEventLoopGroup; + @Nullable + private static PreloadedData ourPreloadedData; public static void main(String[] args){ - final long start = System.nanoTime(); - Runtime.getRuntime().addShutdownHook(new Thread("TimeLogger"){ - public void run() { - final long totalTime = (System.nanoTime() - start) / 1000000L; - - final long millis = totalTime % 1000L ; - final long seconds = totalTime / 1000L; - - LOG.info("Total build time " + seconds + " sec " + millis + " ms"); - } - }); System.out.println("Build process started. Classpath: " + System.getProperty("java.class.path")); final String host = args[HOST_ARG]; final int port = Integer.parseInt(args[PORT_ARG]); @@ -123,6 +122,60 @@ public class BuildMain { final ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port)).awaitUninterruptibly(); final boolean success = future.isSuccess(); if (success) { + final String projectPathToPreload = System.getProperty(PRELOAD_PROJECT_PATH, null); + final String globalsPathToPreload = System.getProperty(PRELOAD_CONFIG_PATH, null); + if (projectPathToPreload != null && globalsPathToPreload != null) { + final long preloadStart = System.currentTimeMillis(); + final PreloadedData data = new PreloadedData(); + ourPreloadedData = data; + try { + FileSystemUtil.getAttributes(projectPathToPreload); // this will pre-load all FS optimizations + + final BuildRunner runner = new BuildRunner(new JpsModelLoaderImpl(projectPathToPreload, globalsPathToPreload, null)); + data.setRunner(runner); + + final File dataStorageRoot = Utils.getDataStorageRoot(projectPathToPreload); + final BuildFSState fsState = new BuildFSState(false); + final ProjectDescriptor pd = runner.load(new MessageHandler() { + @Override + public void processMessage(BuildMessage msg) { + data.addMessage(msg); + } + }, dataStorageRoot, fsState); + data.setProjectDescriptor(pd); + + try { + final File fsStateFile = new File(dataStorageRoot, BuildSession.FS_STATE_FILE); + final DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(fsStateFile))); + try { + final int version = in.readInt(); + if (version == FSState.VERSION) { + final long savedOrdinal = in.readLong(); + in.readBoolean(); // must skip "has-work-to-do" flag + fsState.load(in, pd.getModel(), pd.getBuildRootIndex()); + data.setFsEventOrdinal(savedOrdinal); + } + } + finally { + in.close(); + } + } + catch (FileNotFoundException ignored) { + } + catch (IOException e) { + LOG.info("Error pre-loading FS state", e); + fsState.clearAll(); + } + LOG.info("Pre-loaded project model in " + (System.currentTimeMillis() - preloadStart) + " ms"); + } + catch (Throwable e) { + LOG.info("Failed to pre-load project " + projectPathToPreload, e); + // just failed to preload the project, the situation will be handled later, when real build starts + } + } + else if (projectPathToPreload != null || globalsPathToPreload != null){ + LOG.info("Skipping project pre-loading step: both paths to project configuration files and path to global settings must be specified"); + } future.channel().writeAndFlush(CmdlineProtoUtil.toMessage(sessionId, CmdlineProtoUtil.createParamRequest())); } else { @@ -159,7 +212,7 @@ public class BuildMain { case BUILD_PARAMETERS: { if (mySession == null) { final CmdlineRemoteProto.Message.ControllerMessage.FSEvent delta = controllerMessage.hasFsEvent()? controllerMessage.getFsEvent() : null; - final BuildSession session = new BuildSession(mySessionId, channel, controllerMessage.getParamsMessage(), delta); + final BuildSession session = new BuildSession(mySessionId, channel, controllerMessage.getParamsMessage(), delta, ourPreloadedData); mySession = session; SharedThreadPool.getInstance().executeOnPooledThread(new Runnable() { @Override diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java index a03c127af2c6..1b893a45a302 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java @@ -58,14 +58,20 @@ public class BuildRunner { public static final boolean PARALLEL_BUILD_ENABLED = Boolean.parseBoolean(System.getProperty(GlobalOptions.COMPILE_PARALLEL_OPTION, "false")); private static final boolean STORE_TEMP_CACHES_IN_MEMORY = PARALLEL_BUILD_ENABLED || Boolean.valueOf(System.getProperty(GlobalOptions.USE_MEMORY_TEMP_CACHE_OPTION, "true")); private final JpsModelLoader myModelLoader; - private final List myFilePaths; - private final Map myBuilderParams; + private List myFilePaths = Collections.emptyList(); + private Map myBuilderParams = Collections.emptyMap(); private boolean myForceCleanCaches; - public BuildRunner(JpsModelLoader modelLoader, List filePaths, Map builderParams) { + public BuildRunner(JpsModelLoader modelLoader) { myModelLoader = modelLoader; - myFilePaths = filePaths; - myBuilderParams = builderParams; + } + + public void setFilePaths(List filePaths) { + myFilePaths = filePaths != null? filePaths : Collections.emptyList(); + } + + public void setBuilderParams(Map builderParams) { + myBuilderParams = builderParams != null? builderParams : Collections.emptyMap(); } public ProjectDescriptor load(MessageHandler msgHandler, File dataStorageRoot, BuildFSState fsState) throws IOException { diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java index 9dd87443eae0..0fc6039dfb90 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java @@ -25,6 +25,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.concurrency.SequentialTaskExecutor; import com.intellij.util.io.DataOutputStream; import io.netty.channel.Channel; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.TimingLog; import org.jetbrains.jps.api.*; @@ -57,9 +58,11 @@ import static org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage */ final class BuildSession implements Runnable, CanceledStatus { private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.cmdline.BuildSession"); - private static final String FS_STATE_FILE = "fs_state.dat"; + public static final String FS_STATE_FILE = "fs_state.dat"; private final UUID mySessionId; private final Channel myChannel; + @Nullable + private final PreloadedData myPreloadedData; private volatile boolean myCanceled = false; private final String myProjectPath; @Nullable @@ -70,6 +73,7 @@ final class BuildSession implements Runnable, CanceledStatus { private volatile ProjectDescriptor myProjectDescriptor; private final Map, ConstantSearchFuture> mySearchTasks = Collections.synchronizedMap(new HashMap, ConstantSearchFuture>()); private final ConstantSearch myConstantSearch = new ConstantSearch(); + @NotNull private final BuildRunner myBuildRunner; private final boolean myForceModelLoading; private final BuildType myBuildType; @@ -78,24 +82,31 @@ final class BuildSession implements Runnable, CanceledStatus { BuildSession(UUID sessionId, Channel channel, CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage params, - @Nullable CmdlineRemoteProto.Message.ControllerMessage.FSEvent delta) { + @Nullable CmdlineRemoteProto.Message.ControllerMessage.FSEvent delta, @Nullable PreloadedData preloaded) { mySessionId = sessionId; myChannel = channel; - + myPreloadedData = preloaded; + final CmdlineRemoteProto.Message.ControllerMessage.GlobalSettings globals = params.getGlobalSettings(); myProjectPath = FileUtil.toCanonicalPath(params.getProjectId()); String globalOptionsPath = FileUtil.toCanonicalPath(globals.getGlobalOptionsPath()); myBuildType = convertCompileType(params.getBuildType()); myScopes = params.getScopeList(); List filePaths = params.getFilePathList(); - Map builderParams = new HashMap(); + final Map builderParams = new HashMap(); for (CmdlineRemoteProto.Message.KeyValuePair pair : params.getBuilderParameterList()) { builderParams.put(pair.getKey(), pair.getValue()); } myInitialFSDelta = delta; - JpsModelLoaderImpl loader = new JpsModelLoaderImpl(myProjectPath, globalOptionsPath, null); - myForceModelLoading = Boolean.parseBoolean(builderParams.get(BuildParametersKeys.FORCE_MODEL_LOADING)); - myBuildRunner = new BuildRunner(loader, filePaths, builderParams); + if (preloaded == null || preloaded.getRunner() == null) { + myBuildRunner = new BuildRunner(new JpsModelLoaderImpl(myProjectPath, globalOptionsPath, null)); + } + else { + myBuildRunner = preloaded.getRunner(); + } + myBuildRunner.setFilePaths(filePaths); + myBuildRunner.setBuilderParams(builderParams); + myForceModelLoading = (preloaded != null && preloaded.getProjectDescriptor() != null) || Boolean.parseBoolean(builderParams.get(BuildParametersKeys.FORCE_MODEL_LOADING)); } @Override @@ -185,8 +196,9 @@ final class BuildSession implements Runnable, CanceledStatus { // invoked the very first time for this project myBuildRunner.setForceCleanCaches(true); } - - final DataInputStream fsStateStream = createFSDataStream(dataStorageRoot); + final ProjectDescriptor preloadedProject = myPreloadedData != null? myPreloadedData.getProjectDescriptor() : null; + final DataInputStream fsStateStream = + preloadedProject != null || myInitialFSDelta == null /*this will force FS rescan*/? null : createFSDataStream(dataStorageRoot, myInitialFSDelta.getOrdinal()); if (fsStateStream != null) { // optimization: check whether we can skip the build @@ -198,27 +210,56 @@ final class BuildSession implements Runnable, CanceledStatus { } } - final BuildFSState fsState = new BuildFSState(false); + final BuildFSState fsState = preloadedProject != null? preloadedProject.fsState : new BuildFSState(false); try { - final ProjectDescriptor pd = myBuildRunner.load(msgHandler, dataStorageRoot, fsState); - TimingLog.LOG.debug("Project descriptor loaded"); - myProjectDescriptor = pd; - if (fsStateStream != null) { - try { - try { - fsState.load(fsStateStream, pd.getModel(), pd.getBuildRootIndex()); - applyFSEvent(pd, myInitialFSDelta, false); - TimingLog.LOG.debug("FS Delta loaded"); - } - finally { - fsStateStream.close(); + final ProjectDescriptor pd; + if (preloadedProject != null) { + pd = preloadedProject; + final List preloadMessages = myPreloadedData.getLoadMessages(); + if (!preloadMessages.isEmpty()) { + // replay preload-time messages, so that they are delivered to the IDE + for (BuildMessage message : preloadMessages) { + msgHandler.processMessage(message); } } - catch (Throwable e) { - LOG.error(e); - fsState.clearAll(); + if (myInitialFSDelta == null || myPreloadedData.getFsEventOrdinal() + 1L != myInitialFSDelta.getOrdinal()) { + // FS rescan was forced + fsState.clearAll(); + } + else { + // apply events to already loaded state + try { + applyFSEvent(pd, myInitialFSDelta, false); + } + catch (Throwable e) { + LOG.error(e); + fsState.clearAll(); + } } } + else { + // standard case + pd = myBuildRunner.load(msgHandler, dataStorageRoot, fsState); + TimingLog.LOG.debug("Project descriptor loaded"); + if (fsStateStream != null) { + try { + try { + fsState.load(fsStateStream, pd.getModel(), pd.getBuildRootIndex()); + applyFSEvent(pd, myInitialFSDelta, false); + TimingLog.LOG.debug("FS Delta loaded"); + } + finally { + fsStateStream.close(); + } + } + catch (Throwable e) { + LOG.error(e); + fsState.clearAll(); + } + } + } + myProjectDescriptor = pd; + myLastEventOrdinal = myInitialFSDelta != null? myInitialFSDelta.getOrdinal() : 0L; // free memory @@ -469,11 +510,7 @@ final class BuildSession implements Runnable, CanceledStatus { } @Nullable - private DataInputStream createFSDataStream(File dataStorageRoot) { - if (myInitialFSDelta == null) { - // this will force FS rescan - return null; - } + private static DataInputStream createFSDataStream(File dataStorageRoot, final long currentEventOrdinal) { try { final File file = new File(dataStorageRoot, FS_STATE_FILE); byte[] bytes; @@ -490,7 +527,7 @@ final class BuildSession implements Runnable, CanceledStatus { return null; } final long savedOrdinal = in.readLong(); - if (savedOrdinal + 1L != myInitialFSDelta.getOrdinal()) { + if (savedOrdinal + 1L != currentEventOrdinal) { return null; } return in; diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/PreloadedData.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/PreloadedData.java new file mode 100644 index 000000000000..bf5ece5d6fdd --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/PreloadedData.java @@ -0,0 +1,71 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.jps.cmdline; + +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.incremental.messages.BuildMessage; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Eugene Zhuravlev + * Date: 22-Oct-14 + */ +public class PreloadedData { + @Nullable + private BuildRunner runner; + @Nullable + private ProjectDescriptor projectDescriptor; + + private final List loadMessages = new ArrayList(); + + private long fsEventOrdinal; + + @Nullable + public BuildRunner getRunner() { + return runner; + } + + public void setRunner(@Nullable BuildRunner runner) { + this.runner = runner; + } + + @Nullable + public ProjectDescriptor getProjectDescriptor() { + return projectDescriptor; + } + + public void setProjectDescriptor(@Nullable ProjectDescriptor projectDescriptor) { + this.projectDescriptor = projectDescriptor; + } + + public long getFsEventOrdinal() { + return fsEventOrdinal; + } + + public void setFsEventOrdinal(long fsEventOrdinal) { + this.fsEventOrdinal = fsEventOrdinal; + } + + public List getLoadMessages() { + return loadMessages; + } + + public void addMessage(BuildMessage msg) { + loadMessages.add(msg); + } +} 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/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java b/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java index 979fd78703f1..7b7d425f1a09 100644 --- a/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java +++ b/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java @@ -193,8 +193,7 @@ public class Standalone { public static void runBuild(JpsModelLoader loader, File dataStorageRoot, MessageHandler messageHandler, List scopes, boolean includeDependenciesToScope) throws Exception { - final BuildRunner buildRunner = new BuildRunner(loader, Collections.emptyList(), Collections.emptyMap() - ); + final BuildRunner buildRunner = new BuildRunner(loader); ProjectDescriptor descriptor = buildRunner.load(messageHandler, dataStorageRoot, new BuildFSState(true)); try { buildRunner.runBuild(descriptor, CanceledStatus.NULL, null, messageHandler, BuildType.BUILD, scopes, includeDependenciesToScope); diff --git a/platform/core-api/src/com/intellij/lang/FCTSBackedLighterAST.java b/platform/core-api/src/com/intellij/lang/FCTSBackedLighterAST.java index b393f8d37707..2df20519e18d 100644 --- a/platform/core-api/src/com/intellij/lang/FCTSBackedLighterAST.java +++ b/platform/core-api/src/com/intellij/lang/FCTSBackedLighterAST.java @@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull; import java.util.List; -class FCTSBackedLighterAST extends LighterAST { +public class FCTSBackedLighterAST extends LighterAST { private final FlyweightCapableTreeStructure myTreeStructure; public FCTSBackedLighterAST(final CharTable charTable, final FlyweightCapableTreeStructure treeStructure) { diff --git a/platform/core-api/src/com/intellij/lang/FileASTNode.java b/platform/core-api/src/com/intellij/lang/FileASTNode.java index 136530822a23..193e2421ebd1 100644 --- a/platform/core-api/src/com/intellij/lang/FileASTNode.java +++ b/platform/core-api/src/com/intellij/lang/FileASTNode.java @@ -17,6 +17,7 @@ package com.intellij.lang; import com.intellij.util.CharTable; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * Top-level node in AST, corresponds to PsiFile. @@ -28,4 +29,7 @@ public interface FileASTNode extends ASTNode { CharTable getCharTable(); boolean isParsed(); + + @Nullable + LighterAST getLighterAST(); } diff --git a/platform/core-api/src/com/intellij/lang/LighterAST.java b/platform/core-api/src/com/intellij/lang/LighterAST.java index 71305c5937be..de2c44aa1299 100644 --- a/platform/core-api/src/com/intellij/lang/LighterAST.java +++ b/platform/core-api/src/com/intellij/lang/LighterAST.java @@ -15,8 +15,6 @@ */ package com.intellij.lang; -import com.intellij.psi.tree.IFileElementType; -import com.intellij.psi.tree.ILightStubFileElementType; import com.intellij.util.CharTable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -46,19 +44,4 @@ public abstract class LighterAST { @NotNull public abstract List getChildren(@NotNull final LighterASTNode parent); - - public static @Nullable LighterAST getLighterASTFromFileAST(@NotNull FileASTNode node, @NotNull Language language) { - final IFileElementType contentType = LanguageParserDefinitions.INSTANCE.forLanguage(language).getFileNodeType(); - assert contentType instanceof ILightStubFileElementType; - - final LighterAST tree; - if (!node.isParsed()) { - final ILightStubFileElementType type = (ILightStubFileElementType)contentType; - tree = new FCTSBackedLighterAST(node.getCharTable(), type.parseContentsLight(node)); - } - else { - tree = new TreeBackedLighterAST(node); - } - return tree; - } } \ No newline at end of file diff --git a/platform/core-api/src/com/intellij/psi/stubs/LightStubBuilder.java b/platform/core-api/src/com/intellij/psi/stubs/LightStubBuilder.java index 102288e1a9a0..e9dec24fca2c 100644 --- a/platform/core-api/src/com/intellij/psi/stubs/LightStubBuilder.java +++ b/platform/core-api/src/com/intellij/psi/stubs/LightStubBuilder.java @@ -47,7 +47,7 @@ public class LightStubBuilder implements StubBuilder { LOG.error("File is not of ILightStubFileElementType: " + contentType + ", " + file); return null; } - final LighterAST tree = LighterAST.getLighterASTFromFileAST(file.getNode(), language); + final LighterAST tree = file.getNode().getLighterAST(); if (tree == null) return null; final StubElement rootStub = createStubForFile(file, tree); diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java index d80d36822eb1..c4681c4d77e9 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java +++ b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java @@ -30,7 +30,10 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.util.io.ZipFileCache; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.*; +import com.intellij.util.ArrayUtil; +import com.intellij.util.Function; +import com.intellij.util.PlatformUtilsCore; +import com.intellij.util.ReflectionUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.util.execution.ParametersListUtil; @@ -166,7 +169,7 @@ public class PluginManagerCore { return app != null && app.isUnitTestMode(); } - public static void savePluginsList(Collection ids, boolean append, File plugins) throws IOException { + public static void savePluginsList(@NotNull Collection ids, boolean append, @NotNull File plugins) throws IOException { if (!plugins.isFile()) { FileUtil.ensureCanCreateFile(plugins); } @@ -700,7 +703,13 @@ public class PluginManagerCore { List result, @Nullable StartupProgress progress, int pluginsCount) { - final File pluginsHome = new File(pluginsPath); + loadDescriptors(new File(pluginsPath), result, progress, pluginsCount); + } + + public static void loadDescriptors(@NotNull File pluginsHome, + List result, + @Nullable StartupProgress progress, + int pluginsCount) { final File[] files = pluginsHome.listFiles(); if (files != null) { int i = result.size(); 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/core-impl/src/com/intellij/psi/impl/source/tree/FileElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/FileElement.java index d3071ddbca7d..a2348eabbe97 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/FileElement.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/FileElement.java @@ -16,16 +16,19 @@ package com.intellij.psi.impl.source.tree; -import com.intellij.lang.ASTNode; -import com.intellij.lang.FileASTNode; +import com.intellij.lang.*; import com.intellij.openapi.util.Getter; +import com.intellij.openapi.util.Key; import com.intellij.psi.PsiElement; import com.intellij.psi.impl.PsiManagerEx; import com.intellij.psi.impl.source.CharTableImpl; import com.intellij.psi.impl.source.PsiFileImpl; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.IFileElementType; +import com.intellij.psi.tree.ILightStubFileElementType; import com.intellij.util.CharTable; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class FileElement extends LazyParseableElement implements FileASTNode, Getter { private volatile CharTable myCharTable = new CharTableImpl(); @@ -47,6 +50,35 @@ public class FileElement extends LazyParseableElement implements FileASTNode, Ge return myCharTable; } + private static final Key ourTreeKey = Key.create("lighter.key"); + + @Nullable + @Override + public LighterAST getLighterAST() { + final IFileElementType contentType = (IFileElementType)getElementType(); + assert contentType instanceof ILightStubFileElementType; + + LighterAST tree; + if (!isParsed()) { + tree = getUserData(ourTreeKey); + if (tree == null) { + final ILightStubFileElementType type = (ILightStubFileElementType)contentType; + tree = new FCTSBackedLighterAST(getCharTable(), type.parseContentsLight(this)); + putUserData(ourTreeKey, tree); + } + } + else { + tree = new TreeBackedLighterAST(this); + } + return tree; + } + + @Override + protected void resetCachesOnParsedStateUpdate() { + putUserData(ourTreeKey, null); + super.resetCachesOnParsedStateUpdate(); + } + public FileElement(IElementType type, CharSequence text) { super(type, text); } diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java index ebc699aaf181..85a28f195282 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java @@ -181,8 +181,8 @@ public class LazyParseableElement extends CompositeElement { if (rawFirstChild() != null) { LOG.error("Reentrant parsing?"); } - - myText = null; + + resetCachesOnParsedStateUpdate(); if (parsedNode == null) return; super.rawAddChildrenWithoutNotifications((TreeElement)parsedNode); @@ -199,6 +199,10 @@ public class LazyParseableElement extends CompositeElement { } } + protected void resetCachesOnParsedStateUpdate() { + myText = null; + } + @Override public void rawAddChildrenWithoutNotifications(@NotNull TreeElement first) { if (myText() != null) { diff --git a/platform/duplicates-analysis/src/com/intellij/dupLocator/LightDuplicateProfile.java b/platform/duplicates-analysis/src/com/intellij/dupLocator/LightDuplicateProfile.java new file mode 100644 index 000000000000..c3011c11454e --- /dev/null +++ b/platform/duplicates-analysis/src/com/intellij/dupLocator/LightDuplicateProfile.java @@ -0,0 +1,31 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.dupLocator; + +import com.intellij.lang.LighterAST; +import com.intellij.lang.LighterASTNode; +import com.intellij.psi.PsiFile; + +/** + * Created by Maxim.Mossienko on 10/1/2014. + */ +public interface LightDuplicateProfile { + void process(PsiFile file, Callback callback); + + interface Callback { + void process(LighterAST ast, LighterASTNode node, int hash); + } +} 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 55367ae4a19d..cf4249cecd65 100644 --- a/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesIndex.java +++ b/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesIndex.java @@ -18,15 +18,18 @@ package com.intellij.dupLocator.index; import com.intellij.dupLocator.DuplicatesProfile; import com.intellij.dupLocator.DuplocateVisitor; import com.intellij.dupLocator.DuplocatorState; +import com.intellij.dupLocator.LightDuplicateProfile; import com.intellij.dupLocator.treeHash.FragmentsCollector; import com.intellij.dupLocator.util.PsiFragment; import com.intellij.lang.Language; +import com.intellij.lang.LighterAST; +import com.intellij.lang.LighterASTNode; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.LanguageFileType; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiFile; import com.intellij.util.SystemProperties; import com.intellij.util.indexing.*; import com.intellij.util.io.DataExternalizer; @@ -52,6 +55,7 @@ import java.util.Map; public class DuplicatesIndex extends FileBasedIndexExtension implements PsiDependentIndex { static boolean ourEnabled = SystemProperties.getBooleanProperty("idea.enable.duplicates.online.calculation", isEnabledByDefault()); + static boolean ourEnabledLightProfiles = true; private static boolean isEnabledByDefault() { Application application = ApplicationManager.getApplication(); @@ -59,7 +63,7 @@ public class DuplicatesIndex extends FileBasedIndexExtension NAME = ID.create("DuplicatesIndex"); - private static final int myBaseVersion = 10; + private static final int myBaseVersion = 12; private final FileBasedIndex.InputFilter myInputFilter = new FileBasedIndex.InputFilter() { @Override @@ -107,21 +111,31 @@ public class DuplicatesIndex extends FileBasedIndexExtension map(@NotNull final FileContent inputData) { - return ApplicationManager.getApplication().runReadAction(new Computable>() { - @Override - public Map compute() { - FileType type = inputData.getFileType(); + FileType type = inputData.getFileType(); - DuplicatesProfile profile = findDuplicatesProfile(type); - if (profile == null) return Collections.emptyMap(); + DuplicatesProfile profile = findDuplicatesProfile(type); + if (profile == null) return Collections.emptyMap(); - MyFragmentsCollector collector = new MyFragmentsCollector(profile, ((LanguageFileType)type).getLanguage()); - DuplocateVisitor visitor = profile.createVisitor(collector, true); - visitor.visitNode(((FileContentImpl)inputData).getPsiFileAccountingForUnsavedDocument()); + PsiFile psiFile = ((FileContentImpl)inputData).getPsiFileAccountingForUnsavedDocument(); - return collector.getMap(); - } - }); + if (profile instanceof LightDuplicateProfile && ourEnabledLightProfiles) { + final THashMap result = new THashMap(); + ((LightDuplicateProfile)profile).process(psiFile, new LightDuplicateProfile.Callback() { + @Override + public void process(LighterAST ast, LighterASTNode node, int hash) { + TIntArrayList list = result.get(hash); + if (list == null) { result.put(hash, list = new TIntArrayList(1)); } + list.add(node.getStartOffset()); + } + }); + return result; + } + MyFragmentsCollector collector = new MyFragmentsCollector(profile, ((LanguageFileType)type).getLanguage()); + DuplocateVisitor visitor = profile.createVisitor(collector, true); + + visitor.visitNode(psiFile); + + return collector.getMap(); } }; @@ -135,7 +149,7 @@ public class DuplicatesIndex extends FileBasedIndexExtension 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/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java index c9dae095522c..b7f56a69f887 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java @@ -38,6 +38,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ProjectManagerListener; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Key; @@ -421,7 +422,11 @@ public class RunContentManagerImpl implements RunContentManager, Disposable { } //Stage two: try to get content from descriptor itself final Content attachedContent = descriptor.getAttachedContent(); - if (attachedContent != null && attachedContent.isValid() && contentManager.getIndexOfContent(attachedContent) != -1) { + + if (attachedContent != null + && attachedContent.isValid() + && contentManager.getIndexOfContent(attachedContent) != -1 + && (Comparing.equal(descriptor.getDisplayName(), attachedContent.getDisplayName()) || !attachedContent.isPinned())) { content = attachedContent; } } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java index ec0b9dd8b6c6..7447fa3006c5 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java @@ -321,9 +321,13 @@ public class PsiDirectoryNode extends BasePsiNode implements Navig @Override public Comparable getTypeSortKey() { VirtualFile file = getVirtualFile(); - if (file == null) return null; - String extension = file.getExtension(); - return extension == null ? null : new PsiFileNode.ExtensionSortKey(extension); + if (file != null) { + String extension = file.getExtension(); + if (extension != null) { + return new PsiFileNode.ExtensionSortKey(extension); + } + } + return null; } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java index 068cb4b7e0f2..b376ad8c324d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java @@ -17,11 +17,14 @@ package com.intellij.openapi.application; import com.intellij.ide.plugins.IdeaPluginDescriptorImpl; import com.intellij.ide.plugins.PluginManager; +import com.intellij.ide.plugins.PluginManagerCore; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.AppUIUtil; import com.intellij.util.PlatformUtils; +import com.intellij.util.ReflectionUtil; +import com.intellij.util.SmartList; import com.intellij.util.ThreeState; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -30,8 +33,6 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.io.*; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import java.util.PropertyResourceBundle; @@ -55,21 +56,25 @@ public class ConfigImportHelper { private ConfigImportHelper() { } - public static void importConfigsTo(String newConfigPath) { + public static void importConfigsTo(@NotNull String newConfigPath) { ConfigImportSettings settings = getConfigImportSettings(); - File oldConfigDir = findOldConfigDir(newConfigPath, settings.getCustomPathsSelector()); + File newConfigDir = new File(newConfigPath); + File oldConfigDir = findOldConfigDir(newConfigDir, settings.getCustomPathsSelector()); do { ImportOldConfigsPanel dialog = new ImportOldConfigsPanel(oldConfigDir, settings); dialog.setModalityType(Dialog.ModalityType.TOOLKIT_MODAL); AppUIUtil.updateWindowIcon(dialog); dialog.setVisible(true); if (dialog.isImportEnabled()) { - File instHome = dialog.getSelectedFile(); - oldConfigDir = getOldConfigDir(instHome, settings); - if (!validateOldConfigDir(instHome, oldConfigDir, settings)) continue; + File installationHome = dialog.getSelectedFile(); + oldConfigDir = getOldConfigDir(installationHome, settings); + if (!validateOldConfigDir(installationHome, oldConfigDir, settings)) { + continue; + } - doImport(newConfigPath, oldConfigDir); + assert oldConfigDir != null; + doImport(newConfigDir, oldConfigDir); settings.importFinished(newConfigPath); System.setProperty(CONFIG_IMPORTED_IN_CURRENT_SESSION_KEY, Boolean.TRUE.toString()); } @@ -79,38 +84,30 @@ public class ConfigImportHelper { while (true); } + @NotNull private static ConfigImportSettings getConfigImportSettings() { try { - Class customProviderClass = - Class.forName("com.intellij.openapi.application." + PlatformUtils.getPlatformPrefix() + "ConfigImportSettings"); - if (customProviderClass != null) { - if (ConfigImportSettings.class.isAssignableFrom(customProviderClass)) { - Constructor constructor = customProviderClass.getDeclaredConstructor(); - if (constructor != null) { - return (ConfigImportSettings)constructor.newInstance(); - } - } + @SuppressWarnings("unchecked") + Class customProviderClass = + (Class)Class.forName("com.intellij.openapi.application." + PlatformUtils.getPlatformPrefix() + "ConfigImportSettings"); + if (ConfigImportSettings.class.isAssignableFrom(customProviderClass)) { + return ReflectionUtil.newInstance(customProviderClass); } } catch (ClassNotFoundException ignored) { } - catch (NoSuchMethodException ignored) { - } - catch (InvocationTargetException ignored) { - } - catch (InstantiationException ignored) { - } - catch (IllegalAccessException ignored) { + catch (RuntimeException ignored) { } return new ConfigImportSettings(); } @Nullable - private static File findOldConfigDir(String newConfigPath, @Nullable String customPathSelector) { - final File configDir = new File(newConfigPath); - final File selectorDir = CONFIG_RELATED_PATH.length() == 0 ? configDir : configDir.getParentFile(); + private static File findOldConfigDir(@NotNull File configDir, @Nullable String customPathSelector) { + final File selectorDir = CONFIG_RELATED_PATH.isEmpty() ? configDir : configDir.getParentFile(); final File parent = selectorDir.getParentFile(); - if (parent == null || !parent.exists()) return null; + if (parent == null || !parent.exists()) { + return null; + } File maxFile = null; long lastModified = 0; final String selector = PathManager.getPathsSelector() != null ? PathManager.getPathsSelector() : selectorDir.getName(); @@ -119,14 +116,17 @@ public class ConfigImportHelper { final String customPrefix = customPathSelector != null ? getPrefixFromSelector(customPathSelector) : null; for (File file : parent.listFiles(new FilenameFilter() { @Override - public boolean accept(File file, String name) { + public boolean accept(@NotNull File file, @NotNull String name) { return StringUtil.startsWithIgnoreCase(name, prefix) || customPrefix != null && StringUtil.startsWithIgnoreCase(name, customPrefix); } })) { - final File options = new File(file, CONFIG_RELATED_PATH + OPTIONS_XML); - if (!options.exists()) continue; - final long modified = options.lastModified(); + File options = new File(file, CONFIG_RELATED_PATH + OPTIONS_XML); + if (!options.exists()) { + continue; + } + + long modified = options.lastModified(); if (modified > lastModified) { lastModified = modified; maxFile = file; @@ -139,9 +139,9 @@ public class ConfigImportHelper { return (SystemInfo.isMac ? "" : ".") + selector.replaceAll("\\d", ""); } - public static void doImport(final String newConfigPath, final File oldConfigDir) { + private static void doImport(@NotNull File newConfigDir, @NotNull File oldConfigDir) { try { - xcopy(oldConfigDir, new File(newConfigPath)); + copy(oldConfigDir, newConfigDir); } catch (IOException e) { JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), @@ -150,14 +150,12 @@ public class ConfigImportHelper { } } - public static boolean validateOldConfigDir(final File instHome, final File oldConfigDir, ConfigImportSettings settings) { + private static boolean validateOldConfigDir(@Nullable File installationHome, @Nullable File oldConfigDir, @NotNull ConfigImportSettings settings) { if (oldConfigDir == null) { - final String message = !instHome.equals(oldConfigDir) ? - ApplicationBundle.message("error.invalid.installation.home", instHome.getAbsolutePath(), - settings.getProductName(ThreeState.YES)) : - ApplicationBundle.message("error.invalid.config.folder", instHome.getAbsolutePath(), - settings.getProductName(ThreeState.YES)); - JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), message); + if (installationHome != null) { + JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), + ApplicationBundle.message("error.invalid.installation.home", installationHome.getAbsolutePath(), settings.getProductName(ThreeState.YES))); + } return false; } @@ -171,7 +169,7 @@ public class ConfigImportHelper { return true; } - public static void xcopy(File src, File dest) throws IOException { + private static void copy(@NotNull File src, @NotNull File dest) throws IOException { src = src.getCanonicalFile(); dest = dest.getCanonicalFile(); if (!src.isDirectory()) { @@ -184,32 +182,53 @@ public class ConfigImportHelper { return; } - FileUtil.copyDir(src, dest); + FileUtil.ensureExists(dest); - // Delete plugins just imported. They're most probably incompatible with newer idea version. - File plugins = new File(dest, PLUGINS_PATH); + File[] childFiles = src.listFiles(new FilenameFilter() { + @Override + public boolean accept(@NotNull File dir, @NotNull String name) { + // Don't copy plugins just imported. They're most probably incompatible with newer idea version. + return !StringUtil.startsWithChar(name, '.') && !name.equals(PLUGINS_PATH); + } + }); + + if (childFiles == null || childFiles.length == 0) { + return; + } + + for (File from : childFiles) { + File to = new File(dest, from.getName()); + if (from.isDirectory()) { + FileUtil.copyDir(from, to, false); + } + else { + FileUtil.copy(from, to); + } + } + + File plugins = new File(src, PLUGINS_PATH); if (plugins.exists()) { - final ArrayList descriptors = new ArrayList(); - PluginManager.loadDescriptors(plugins.getPath(), descriptors, null, 0); - final ArrayList oldPlugins = new ArrayList(); + List descriptors = new SmartList(); + PluginManagerCore.loadDescriptors(plugins, descriptors, null, 0); + List oldPlugins = new SmartList(); for (IdeaPluginDescriptorImpl descriptor : descriptors) { - oldPlugins.add(descriptor.getPluginId().getIdString()); + // check isBundled also - probably plugin is bundled in new IDE version + if (descriptor.isEnabled() && !descriptor.isBundled()) { + oldPlugins.add(descriptor.getPluginId().getIdString()); + } } if (!oldPlugins.isEmpty()) { - PluginManager.savePluginsList(oldPlugins, false, new File(dest, PluginManager.INSTALLED_TXT)); + PluginManagerCore.savePluginsList(oldPlugins, false, new File(dest, PluginManager.INSTALLED_TXT)); } - FileUtil.delete(plugins); - } - - File pluginsSettings = new File(new File(dest, "options"), "plugin_ui.xml"); - if (pluginsSettings.exists()) { - FileUtil.delete(pluginsSettings); } } @Nullable - public static File getOldConfigDir(File oldInstallHome, ConfigImportSettings settings) { - if (oldInstallHome == null) return null; + public static File getOldConfigDir(@Nullable File oldInstallHome, ConfigImportSettings settings) { + if (oldInstallHome == null) { + return null; + } + // check if it's already config dir if (new File(oldInstallHome, OPTIONS_XML).exists()) { return oldInstallHome; @@ -299,8 +318,8 @@ public class ConfigImportHelper { @NotNull final String propertyName) { if (file.getName().endsWith(".properties")) { try { - InputStream fis = new BufferedInputStream(new FileInputStream(file)); PropertyResourceBundle bundle; + InputStream fis = new BufferedInputStream(new FileInputStream(file)); try { bundle = new PropertyResourceBundle(fis); } @@ -374,7 +393,7 @@ public class ConfigImportHelper { @Nullable private static String getContent(File file) { try { - StringBuffer content = new StringBuffer(); + StringBuilder content = new StringBuilder(); BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file))); try { do { 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/platform-impl/src/com/intellij/openapi/updateSettings/impl/Product.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/Product.java index 56ae855dc317..2a576abf538a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/Product.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/Product.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,19 +33,17 @@ public class Product { private final Set myCodes; private final List myChannels; - public Product(Element node) { + public Product(@NotNull Element node) { myName = node.getAttributeValue("name"); myCodes = new LinkedHashSet(); myChannels = new ArrayList(); - List codes = node.getChildren("code"); - for (Object code : codes) { - myCodes.add(((Element)code).getValue()); + for (Element code : node.getChildren("code")) { + myCodes.add(code.getValue()); } - List channels = node.getChildren("channel"); - for (Object channel : channels) { - myChannels.add(new UpdateChannel((Element)channel)); + for (Element channel : node.getChildren("channel")) { + myChannels.add(new UpdateChannel(channel)); } } @@ -56,7 +54,9 @@ public class Product { @Nullable public UpdateChannel findUpdateChannelById(String id) { for (UpdateChannel channel : myChannels) { - if (id.equals(channel.getId())) return channel; + if (id.equals(channel.getId())) { + return channel; + } } return null; } diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChannel.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChannel.java index 3a3869146e94..4d986b4a3cc2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChannel.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChannel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ package com.intellij.openapi.updateSettings.impl; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -39,12 +40,11 @@ public class UpdateChannel { public static final String LICENSING_EAP = "eap"; public static final String LICENSING_PRODUCTION = "production"; - public UpdateChannel(Element node) { + public UpdateChannel(@NotNull Element node) { myId = node.getAttributeValue("id"); myName = node.getAttributeValue("name"); myStatus = ChannelStatus.fromCode(node.getAttributeValue("status")); - String licensing = node.getAttributeValue("licensing"); - myLicensing = licensing != null ? licensing : LICENSING_PRODUCTION; + myLicensing = node.getAttributeValue("licensing", LICENSING_PRODUCTION); String majorVersion = node.getAttributeValue("majorVersion"); myMajorVersion = majorVersion != null ? Integer.parseInt(majorVersion) : -1; @@ -56,8 +56,8 @@ public class UpdateChannel { myFeedbackUrl = node.getAttributeValue("feedback"); myBuilds = new ArrayList(); - for (Object child : node.getChildren("build")) { - myBuilds.add(new BuildInfo((Element)child)); + for (Element child : node.getChildren("build")) { + myBuilds.add(new BuildInfo(child)); } } @@ -69,7 +69,6 @@ public class UpdateChannel { build = info; } } - return build; } diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java index 6e879427859a..14366fc46aa7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java @@ -93,7 +93,7 @@ public final class UpdateChecker { @NonNls private static final String DISABLED_UPDATE = "disabled_update.txt"; private static Set ourDisabledToUpdatePlugins; - private static Map ourAdditionalRequestOptions = new HashMap(); + private static final Map ourAdditionalRequestOptions = new HashMap(); private static class Holder { private static final String UPDATE_URL = ApplicationInfoEx.getInstanceEx().getUpdateUrls().getCheckingUrl(); @@ -464,8 +464,7 @@ public final class UpdateChecker { private static CheckForUpdateResult checkForUpdates(final UpdateSettings settings) { UpdatesInfo info; try { - UpdatesXmlLoader loader = new UpdatesXmlLoader(getUpdateUrl()); - info = loader.loadUpdatesInfo(); + info = UpdatesXmlLoader.loadUpdatesInfo(getUpdateUrl()); if (info == null) { return new CheckForUpdateResult(UpdateStrategy.State.NOTHING_LOADED); } @@ -660,14 +659,12 @@ public final class UpdateChecker { return uid; } } - String uid; - if (!propertiesComponent.isValueSet(INSTALLATION_UID)) { + + String uid = propertiesComponent.getValue(INSTALLATION_UID); + if (uid == null) { uid = generateUUID(); propertiesComponent.setValue(INSTALLATION_UID, uid); } - else { - uid = propertiesComponent.getValue(INSTALLATION_UID); - } return uid; } @@ -683,11 +680,8 @@ public final class UpdateChecker { return FileUtil.loadFile(permanentIdFile).trim(); } - String uuid; - if (propertiesComponent.isValueSet(INSTALLATION_UID)) { - uuid = propertiesComponent.getValue(INSTALLATION_UID); - } - else { + String uuid = propertiesComponent.getValue(INSTALLATION_UID); + if (uuid == null) { uuid = generateUUID(); } FileUtil.writeToFile(permanentIdFile, uuid); @@ -764,7 +758,11 @@ public final class UpdateChecker { String fromBuildNumber = patch.getFromBuild().asStringWithoutProductCode(); String toBuildNumber = newVersion.getNumber().asStringWithoutProductCode(); - String bundledJdk = "jdk-bundled".equals(System.getProperty("idea.java.redist")) ? "-jdk-bundled" : ""; + String jdkMacRedist = System.getProperty("idea.java.redist"); + String bundledJdk = ""; + if (jdkMacRedist.lastIndexOf("jdk-bundled") >= 0 ){ + bundledJdk = "jdk-bundled".equals(jdkMacRedist) ? "-jdk-bundled" : "-custom-jdk-bundled"; + } String fileName = productCode + "-" + fromBuildNumber + "-" + toBuildNumber + "-patch" + bundledJdk + osSuffix + ".jar"; @@ -812,7 +810,7 @@ public final class UpdateChecker { out.close(); } - String patchFileName = ("jetbrains.patch.jar." + platform).toLowerCase(); + String patchFileName = ("jetbrains.patch.jar." + platform).toLowerCase(Locale.ENGLISH); File patchFile = new File(FileUtil.getTempDirectory(), patchFileName); FileUtil.copy(tempFile, patchFile); FileUtil.delete(tempFile); diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesInfo.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesInfo.java index 46bd1182db61..0e2d93753958 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesInfo.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ */ package com.intellij.openapi.updateSettings.impl; - import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,11 +25,10 @@ import java.util.List; public class UpdatesInfo { @NotNull private final List myProducts; - public UpdatesInfo(Element element) { + public UpdatesInfo(@NotNull Element element) { myProducts = new ArrayList(); - List children = element.getChildren(); - for (Object child : children) { - myProducts.add(new Product((Element) child)); + for (Element child : element.getChildren()) { + myProducts.add(new Product(child)); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java index 9c6c6a2020e5..f8f9a71c120c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,33 +25,19 @@ import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.net.HttpConfigurable; import org.jdom.JDOMException; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.URL; -import java.net.URLConnection; -import java.util.concurrent.Callable; -import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -public class UpdatesXmlLoader { - - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.updateSettings.impl.UpdatesXmlLoader"); - - private final String updateUrl; - - public UpdatesXmlLoader(final String updatesUrl) { - this.updateUrl = updatesUrl; - } +import java.util.concurrent.*; +class UpdatesXmlLoader { + private static final Logger LOG = Logger.getInstance(UpdatesXmlLoader.class); @Nullable - public UpdatesInfo loadUpdatesInfo() throws ConnectionException{ - LOG.debug("load update xml (UPDATE_URL='" + updateUrl + "' )"); + public static UpdatesInfo loadUpdatesInfo(@Nullable final String updateUrl) throws ConnectionException { + if (LOG.isDebugEnabled()) { + LOG.debug("load update xml (UPDATE_URL='" + updateUrl + "' )"); + } if (StringUtil.isEmpty(updateUrl)) { LOG.debug("update url is empty: updates will not be checked"); @@ -59,20 +45,13 @@ public class UpdatesXmlLoader { } final Ref error = new Ref(); - FutureTask ft = new FutureTask(new Callable() { + Future future = ApplicationManager.getApplication().executeOnPooledThread(new Callable() { @Nullable @Override public UpdatesInfo call() throws Exception { try { - prepareUrl(updateUrl); - - URL requestUrl = prepareRequestUrl(updateUrl); - - URLConnection connection = requestUrl.openConnection(); - connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT); - connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT); - final InputStream inputStream = connection.getInputStream(); - Reader reader = new InputStreamReader(inputStream); + String url = updateUrl.startsWith("file:") ? updateUrl : updateUrl + '?' + UpdateChecker.prepareUpdateCheckArgs(); + InputStream inputStream = HttpConfigurable.getInstance().openConnection(url).getInputStream(); try { return new UpdatesInfo(JDOMUtil.loadDocument(inputStream).getRootElement()); } @@ -80,59 +59,41 @@ public class UpdatesXmlLoader { LOG.info(e); // Broken xml downloaded. Don't bother telling user. } finally { - reader.close(); inputStream.close(); } } catch (Exception e) { + LOG.debug(e); error.set(e); } return null; } }); - ApplicationManager.getApplication().executeOnPooledThread(ft); + + UpdatesInfo result = null; try { - UpdatesInfo result = ft.get(5, TimeUnit.SECONDS); - if (!error.isNull()) { - //noinspection ThrowableResultOfMethodCallIgnored - throw new ConnectionException(error.get()); - } - return result; + result = future.get(5, TimeUnit.SECONDS); } - catch (TimeoutException e) { - // ignore + catch (TimeoutException ignored) { } - catch (Exception e) { + catch (InterruptedException e) { LOG.debug(e); - throw new ConnectionException(e.getMessage(),e); + error.set(e); } - if (!ft.isDone()) { - ft.cancel(true); - throw new ConnectionException(IdeBundle.message("updates.timeout.error")); + catch (ExecutionException e) { + LOG.debug(e); + error.set(e); } - return null; - } - - - protected static void prepareUrl(@NotNull String url) throws ConnectionException { - try { - HttpConfigurable.getInstance().prepareURL(url); - } - catch (Exception e) { - throw new ConnectionException(e); - } - } - - protected URL prepareRequestUrl(@NotNull String url) throws ConnectionException { - try { - if (url.startsWith("file:")) { - return new URL(url); + if (!future.isDone()) { + future.cancel(true); + if (error.isNull()) { + throw new ConnectionException(IdeBundle.message("updates.timeout.error")); } - return new URL(url + "?" + UpdateChecker.prepareUpdateCheckArgs()); } - catch (Exception e) { - throw new ConnectionException(e); + if (!error.isNull()) { + throw new ConnectionException(error.get()); } + return result; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java index 4ae3caee88e1..b08adda9d2f9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginsAdvertiser.java @@ -245,6 +245,7 @@ public class PluginsAdvertiser implements StartupActivity { final KnownExtensions extensions = loadExtensions(); if (extensions != null && unknownFeatures.isEmpty()) return; final Runnable runnable = new Runnable() { + @Override public void run() { final Application application = ApplicationManager.getApplication(); if (application.isUnitTestMode() || application.isHeadlessEnvironment()) return; @@ -252,9 +253,10 @@ public class PluginsAdvertiser implements StartupActivity { private final Set myPlugins = new HashSet(); private List myAllPlugins; - private Map myDisabledPlugins = new HashMap(); + private final Map myDisabledPlugins = new HashMap(); private List myBundledPlugin; + @Override public void run() { try { myAllPlugins = RepositoryHelper.loadPluginsFromRepository(null); @@ -349,6 +351,7 @@ public class PluginsAdvertiser implements StartupActivity { @MapAnnotation(surroundWithTag = false, surroundKeyWithTag = false, surroundValueWithTag = false) public Map myExtensions = new HashMap(); + @SuppressWarnings("unused") public KnownExtensions() { } @@ -371,6 +374,7 @@ public class PluginsAdvertiser implements StartupActivity { public static class PluginSet { public Set myPlugins = new HashSet(); + @SuppressWarnings("unused") public PluginSet() { } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewWelcomeScreen.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewWelcomeScreen.java index 2994fede233a..ff94a4d5391f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewWelcomeScreen.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewWelcomeScreen.java @@ -28,7 +28,6 @@ import com.intellij.openapi.updateSettings.impl.UpdateChecker; import com.intellij.openapi.updateSettings.impl.UpdateSettings; import com.intellij.openapi.util.DimensionService; import com.intellij.openapi.util.IconLoader; -import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.wm.WelcomeScreen; import com.intellij.ui.ScreenUtil; import com.intellij.ui.components.labels.LinkLabel; @@ -150,7 +149,7 @@ public class NewWelcomeScreen extends JPanel implements WelcomeScreen { } public static boolean isNewWelcomeScreen(@NotNull AnActionEvent e) { - return e.getPlace() == ActionPlaces.WELCOME_SCREEN && Registry.is("ide.new.welcome.screen"); + return e.getPlace() == ActionPlaces.WELCOME_SCREEN && FlatWelcomeFrameProvider.isAvailable(); } private static class WelcomeScreenGroup extends DefaultActionGroup { diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index 6162300942a0..b02ba924695f 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -1,5 +1,4 @@ error.invalid.installation.home=Unable to import settings. ''{0}'' doesn''t appear to be valid {1} installation home. -error.invalid.config.folder=Unable to import settings. ''{0}'' doesn''t appear to be valid {1} config folder. error.no.settings.path=Unable to import settings. {0} does not exist. title.settings.import.failed=Settings Import Failed error.unable.to.import.settings=Unable to import settings. {0} diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml index 64f737ce376b..00f42a06cd93 100644 --- a/platform/platform-resources/src/META-INF/XmlPlugin.xml +++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml @@ -116,8 +116,8 @@ - + diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index f989604a8c65..014c6306a701 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -583,8 +583,8 @@ - + 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/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index e5be37cd7b30..d9f47ad0209a 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -51,7 +51,7 @@ ide.debugger.inline.dark.fg.color=61,128,101 ide.debugger.inline.dark.fg.color.description=Inline values foreground for dark editor scheme ide.debugger.inline.fg.modified.color=202,128,33 ide.debugger.inline.fg.modified.color.description=Inline modified values foreground -ide.debugger.inline.dark.fg.modified.color=161,131,10 +ide.debugger.inline.dark.fg.modified.color=202,126,3 ide.debugger.inline.dark.fg.modified.color.description=Inline modified values foreground for dark editor scheme ide.debugMode.description=Record additional information to make bug reports more informative. @@ -198,6 +198,9 @@ compiler.process.use.memory.temp.cache=true compiler.process.use.memory.temp.cache.description=Store temporary data in memory for faster compilation;\ requires larger heap size for the build process. If parallel build is enabled, the option is ignored and temp data is always stored in memory. +compiler.process.preload=false +compiler.process.preload.description=After build finishes, the IDE will pre-load and leave waiting in memory the build process for the next compilation. This will save time for process start and project model loading (may be noticeable for big projects).\ + compiler.process.debug.port=-1 compiler.automake.trigger.delay=300 diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java index cce3eac58098..a71b6ec5de7a 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java @@ -26,7 +26,10 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.ui.*; +import com.intellij.ui.ColorUtil; +import com.intellij.ui.JBColor; +import com.intellij.ui.SimpleColoredText; +import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.NotNullProducer; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XSourcePosition; @@ -95,7 +98,7 @@ public class XDebuggerEditorLinePainter extends EditorLinePainter { catch (Exception e) { continue; } - final Color color = bpLine == lineNumber ? new JBColor(Gray._180, new Color(147, 217, 186)) : getForeground(); + final Color color = bpLine == lineNumber ? new JBColor(new Color(0, 255, 86), new Color(255, 235, 9)) : getForeground(); final String name = value.getName(); if (StringUtil.isEmpty(text.toString())) { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java index 84e391b21a1a..1edfa484421a 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java @@ -89,6 +89,10 @@ public abstract class TreeInplaceEditor implements AWTEventListener { protected abstract Project getProject(); + private static void setInplaceEditorBounds(JComponent component, int x, int y, int width, int height) { + component.setBounds(x, y, width, Math.max(height, component.getPreferredSize().height)); + } + public final void show() { LOG.assertTrue(myInplaceEditorComponent == null, "editor is not released"); final JTree tree = getTree(); @@ -108,12 +112,7 @@ public abstract class TreeInplaceEditor implements AWTEventListener { final JComponent inplaceEditorComponent = createInplaceEditorComponent(); myInplaceEditorComponent = inplaceEditorComponent; LOG.assertTrue(inplaceEditorComponent != null); - inplaceEditorComponent.setBounds( - layeredPanePoint.x, - layeredPanePoint.y, - bounds.width, - Math.max(bounds.height, inplaceEditorComponent.getPreferredSize().height) - ); + setInplaceEditorBounds(inplaceEditorComponent, layeredPanePoint.x, layeredPanePoint.y, bounds.width, bounds.height); layeredPane.add(inplaceEditorComponent, new Integer(250)); @@ -145,7 +144,7 @@ public abstract class TreeInplaceEditor implements AWTEventListener { return; } Point layeredPanePoint = SwingUtilities.convertPoint(tree, bounds.x, bounds.y, layeredPane); - inplaceEditorComponent.setBounds(layeredPanePoint.x, layeredPanePoint.y, bounds.width, bounds.height); + setInplaceEditorBounds(inplaceEditorComponent, layeredPanePoint.x, layeredPanePoint.y, bounds.width, bounds.height); inplaceEditorComponent.revalidate(); } }); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java index 7020c9a5cf84..6f911b28cd68 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java @@ -160,10 +160,11 @@ public class XValueNodeImpl extends XValueContainerNode implements XValu }; if (getValueContainer().computeInlineDebuggerData(callback) == ThreeState.UNSURE) { - getValueContainer().computeSourcePosition(new XNearestSourcePosition() { + class ValueDeclaration implements XNavigatable { @Override public void setSourcePosition(@Nullable XSourcePosition sourcePosition) { - final Map, Set> map = myTree.getProject().getUserData(XVariablesView.DEBUG_VARIABLES); + final Map, Set> map = + myTree.getProject().getUserData(XVariablesView.DEBUG_VARIABLES); final Map timestamps = myTree.getProject().getUserData(XVariablesView.DEBUG_VARIABLES_TIMESTAMPS); if (map == null || timestamps == null || sourcePosition == null) return; VirtualFile file = sourcePosition.getFile(); @@ -172,7 +173,10 @@ public class XValueNodeImpl extends XValueContainerNode implements XValu int line = sourcePosition.getLine(); callback.computed(file, doc, line); } - }); + } + class NearestValuePosition extends ValueDeclaration implements XNearestSourcePosition {} + getValueContainer().computeSourcePosition(new ValueDeclaration()); + getValueContainer().computeSourcePosition(new NearestValuePosition()); } } } 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/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdateEnvironment.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdateEnvironment.java index 038c1c24121f..d4d40d791bed 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdateEnvironment.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdateEnvironment.java @@ -35,7 +35,7 @@ import java.util.List; public class HgUpdateEnvironment implements UpdateEnvironment { private final Project project; - private final HgUpdateConfigurationSettings updateConfiguration; + @NotNull private final HgUpdateConfigurationSettings updateConfiguration; public HgUpdateEnvironment(Project project) { this.project = project; @@ -89,7 +89,7 @@ public class HgUpdateEnvironment implements UpdateEnvironment { private final HgUpdateConfigurationSettings updateConfiguration; protected HgUpdateDialog updateDialog; - public UpdateConfigurable(HgUpdateConfigurationSettings updateConfiguration) { + public UpdateConfigurable(@NotNull HgUpdateConfigurationSettings updateConfiguration) { this.updateConfiguration = updateConfiguration; } 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/plugins/tasks/tasks-core/src/icons/TasksIcons.java b/plugins/tasks/tasks-core/src/icons/TasksIcons.java index 68a2e24608ea..0beca234c217 100644 --- a/plugins/tasks/tasks-core/src/icons/TasksIcons.java +++ b/plugins/tasks/tasks-core/src/icons/TasksIcons.java @@ -40,15 +40,15 @@ public class TasksIcons { public static final Icon Github = load("/icons/github.png"); // 16x16 public static final Icon Gitlab = load("/icons/gitlab.png"); // 16x16 public static final Icon Jira = load("/icons/jira.png"); // 16x16 - public static final Icon Lighthouse = load("/icons/lighthouse.gif"); // 16x16 + public static final Icon Lighthouse = load("/icons/lighthouse.png"); // 16x16 public static final Icon Mantis = load("/icons/mantis.png"); // 16x16 public static final Icon Other = load("/icons/other.png"); // 16x16 public static class Pivotal { - public static final Icon Bug = load("/icons/pivotal/bug.png"); // 14x14 - public static final Icon Chore = load("/icons/pivotal/chore.png"); // 14x14 - public static final Icon Feature = load("/icons/pivotal/feature.png"); // 14x14 - public static final Icon Release = load("/icons/pivotal/release.png"); // 14x14 + public static final Icon Bug = load("/icons/pivotal/bug.png"); // 16x16 + public static final Icon Chore = load("/icons/pivotal/chore.png"); // 16x16 + public static final Icon Feature = load("/icons/pivotal/feature.png"); // 16x16 + public static final Icon Release = load("/icons/pivotal/release.png"); // 16x16 } public static final Icon Pivotal = load("/icons/pivotal.png"); // 16x16 diff --git a/plugins/tasks/tasks-core/src/icons/asana.png b/plugins/tasks/tasks-core/src/icons/asana.png index 25cea9634766..2d2958fc7f73 100644 Binary files a/plugins/tasks/tasks-core/src/icons/asana.png and b/plugins/tasks/tasks-core/src/icons/asana.png differ diff --git a/plugins/tasks/tasks-core/src/icons/asana@2x.png b/plugins/tasks/tasks-core/src/icons/asana@2x.png new file mode 100644 index 000000000000..eafd61a24989 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/asana@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/assembla.png b/plugins/tasks/tasks-core/src/icons/assembla.png index 5198524088cb..3e570c9880aa 100644 Binary files a/plugins/tasks/tasks-core/src/icons/assembla.png and b/plugins/tasks/tasks-core/src/icons/assembla.png differ diff --git a/plugins/tasks/tasks-core/src/icons/assembla@2x.png b/plugins/tasks/tasks-core/src/icons/assembla@2x.png new file mode 100644 index 000000000000..9b2e1daa0276 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/assembla@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/autoMode.png b/plugins/tasks/tasks-core/src/icons/autoMode.png index 9355db4b2de6..8b4cf8c4b6cf 100644 Binary files a/plugins/tasks/tasks-core/src/icons/autoMode.png and b/plugins/tasks/tasks-core/src/icons/autoMode.png differ diff --git a/plugins/tasks/tasks-core/src/icons/autoMode@2x.png b/plugins/tasks/tasks-core/src/icons/autoMode@2x.png new file mode 100644 index 000000000000..572d3356fb60 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/autoMode@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/bug.png b/plugins/tasks/tasks-core/src/icons/bug.png index 9303d5a019dd..412b67006dc2 100644 Binary files a/plugins/tasks/tasks-core/src/icons/bug.png and b/plugins/tasks/tasks-core/src/icons/bug.png differ diff --git a/plugins/tasks/tasks-core/src/icons/bug@2x.png b/plugins/tasks/tasks-core/src/icons/bug@2x.png new file mode 100644 index 000000000000..2fc69150f98f Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/bug@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/bug@2x_dark.png b/plugins/tasks/tasks-core/src/icons/bug@2x_dark.png new file mode 100644 index 000000000000..6d02836719e9 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/bug@2x_dark.png differ diff --git a/plugins/tasks/tasks-core/src/icons/bug_dark.png b/plugins/tasks/tasks-core/src/icons/bug_dark.png new file mode 100644 index 000000000000..5926f1dd2b1b Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/bug_dark.png differ diff --git a/plugins/tasks/tasks-core/src/icons/bugzilla.png b/plugins/tasks/tasks-core/src/icons/bugzilla.png index b06da57f512e..7dc4666337d2 100644 Binary files a/plugins/tasks/tasks-core/src/icons/bugzilla.png and b/plugins/tasks/tasks-core/src/icons/bugzilla.png differ diff --git a/plugins/tasks/tasks-core/src/icons/bugzilla@2x.png b/plugins/tasks/tasks-core/src/icons/bugzilla@2x.png new file mode 100644 index 000000000000..d010d4fe95fa Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/bugzilla@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/exception.png b/plugins/tasks/tasks-core/src/icons/exception.png index 3edaf7ab9785..02ce6b16d348 100644 Binary files a/plugins/tasks/tasks-core/src/icons/exception.png and b/plugins/tasks/tasks-core/src/icons/exception.png differ diff --git a/plugins/tasks/tasks-core/src/icons/exception@2x.png b/plugins/tasks/tasks-core/src/icons/exception@2x.png new file mode 100644 index 000000000000..1d1607adb7f1 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/exception@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/feature.png b/plugins/tasks/tasks-core/src/icons/feature.png index 9051b6eadf38..26793add948f 100644 Binary files a/plugins/tasks/tasks-core/src/icons/feature.png and b/plugins/tasks/tasks-core/src/icons/feature.png differ diff --git a/plugins/tasks/tasks-core/src/icons/feature@2x.png b/plugins/tasks/tasks-core/src/icons/feature@2x.png new file mode 100644 index 000000000000..66f44bd2ad51 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/feature@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/fogbugz.png b/plugins/tasks/tasks-core/src/icons/fogbugz.png index 70c2d7ffef58..1b1f086720ae 100644 Binary files a/plugins/tasks/tasks-core/src/icons/fogbugz.png and b/plugins/tasks/tasks-core/src/icons/fogbugz.png differ diff --git a/plugins/tasks/tasks-core/src/icons/fogbugz@2x.png b/plugins/tasks/tasks-core/src/icons/fogbugz@2x.png new file mode 100644 index 000000000000..58ba46497423 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/fogbugz@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/github.png b/plugins/tasks/tasks-core/src/icons/github.png index b2f329a2756c..1cd6d256b56c 100644 Binary files a/plugins/tasks/tasks-core/src/icons/github.png and b/plugins/tasks/tasks-core/src/icons/github.png differ diff --git a/plugins/tasks/tasks-core/src/icons/github@2x.png b/plugins/tasks/tasks-core/src/icons/github@2x.png new file mode 100644 index 000000000000..1f02f43021ee Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/github@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/github@2x_dark.png b/plugins/tasks/tasks-core/src/icons/github@2x_dark.png new file mode 100644 index 000000000000..6bc758ad325b Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/github@2x_dark.png differ diff --git a/plugins/tasks/tasks-core/src/icons/github_dark.png b/plugins/tasks/tasks-core/src/icons/github_dark.png new file mode 100644 index 000000000000..97224b46d1a7 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/github_dark.png differ diff --git a/plugins/tasks/tasks-core/src/icons/gitlab.png b/plugins/tasks/tasks-core/src/icons/gitlab.png index 12a06e757436..b581196c21f8 100644 Binary files a/plugins/tasks/tasks-core/src/icons/gitlab.png and b/plugins/tasks/tasks-core/src/icons/gitlab.png differ diff --git a/plugins/tasks/tasks-core/src/icons/gitlab@2x.png b/plugins/tasks/tasks-core/src/icons/gitlab@2x.png new file mode 100644 index 000000000000..011d5d6bcc61 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/gitlab@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/jira.png b/plugins/tasks/tasks-core/src/icons/jira.png index 5375c427edc0..f6f1f416b09f 100644 Binary files a/plugins/tasks/tasks-core/src/icons/jira.png and b/plugins/tasks/tasks-core/src/icons/jira.png differ diff --git a/plugins/tasks/tasks-core/src/icons/jira@2x.png b/plugins/tasks/tasks-core/src/icons/jira@2x.png new file mode 100644 index 000000000000..3825b73930ff Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/jira@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/jira@2x_dark.png b/plugins/tasks/tasks-core/src/icons/jira@2x_dark.png new file mode 100644 index 000000000000..33cda03b2b27 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/jira@2x_dark.png differ diff --git a/plugins/tasks/tasks-core/src/icons/jira_dark.png b/plugins/tasks/tasks-core/src/icons/jira_dark.png new file mode 100644 index 000000000000..876771437d14 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/jira_dark.png differ diff --git a/plugins/tasks/tasks-core/src/icons/lighthouse.gif b/plugins/tasks/tasks-core/src/icons/lighthouse.gif deleted file mode 100644 index e12b528031e6..000000000000 Binary files a/plugins/tasks/tasks-core/src/icons/lighthouse.gif and /dev/null differ diff --git a/plugins/tasks/tasks-core/src/icons/lighthouse.png b/plugins/tasks/tasks-core/src/icons/lighthouse.png new file mode 100644 index 000000000000..bb6dc364a52e Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/lighthouse.png differ diff --git a/plugins/tasks/tasks-core/src/icons/lighthouse@2x.png b/plugins/tasks/tasks-core/src/icons/lighthouse@2x.png new file mode 100644 index 000000000000..99a00441fa3a Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/lighthouse@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/mantis.png b/plugins/tasks/tasks-core/src/icons/mantis.png index d180cfa545c7..7e783936ba3e 100644 Binary files a/plugins/tasks/tasks-core/src/icons/mantis.png and b/plugins/tasks/tasks-core/src/icons/mantis.png differ diff --git a/plugins/tasks/tasks-core/src/icons/mantis@2x.png b/plugins/tasks/tasks-core/src/icons/mantis@2x.png new file mode 100644 index 000000000000..211bd8bbcf83 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/mantis@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/other.png b/plugins/tasks/tasks-core/src/icons/other.png index fb5256180562..17988437e520 100644 Binary files a/plugins/tasks/tasks-core/src/icons/other.png and b/plugins/tasks/tasks-core/src/icons/other.png differ diff --git a/plugins/tasks/tasks-core/src/icons/other@2x.png b/plugins/tasks/tasks-core/src/icons/other@2x.png new file mode 100644 index 000000000000..8950bac515e8 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/other@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/pivotal.png b/plugins/tasks/tasks-core/src/icons/pivotal.png index 1ae1042485d4..7dcd1252a30a 100644 Binary files a/plugins/tasks/tasks-core/src/icons/pivotal.png and b/plugins/tasks/tasks-core/src/icons/pivotal.png differ diff --git a/plugins/tasks/tasks-core/src/icons/pivotal/bug.png b/plugins/tasks/tasks-core/src/icons/pivotal/bug.png index fb5bdeb8edcc..412b67006dc2 100644 Binary files a/plugins/tasks/tasks-core/src/icons/pivotal/bug.png and b/plugins/tasks/tasks-core/src/icons/pivotal/bug.png differ diff --git a/plugins/tasks/tasks-core/src/icons/pivotal/bug@2x.png b/plugins/tasks/tasks-core/src/icons/pivotal/bug@2x.png new file mode 100644 index 000000000000..2fc69150f98f Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/pivotal/bug@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/pivotal/bug@2x_dark.png b/plugins/tasks/tasks-core/src/icons/pivotal/bug@2x_dark.png new file mode 100644 index 000000000000..6d02836719e9 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/pivotal/bug@2x_dark.png differ diff --git a/plugins/tasks/tasks-core/src/icons/pivotal/bug_dark.png b/plugins/tasks/tasks-core/src/icons/pivotal/bug_dark.png new file mode 100644 index 000000000000..5926f1dd2b1b Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/pivotal/bug_dark.png differ diff --git a/plugins/tasks/tasks-core/src/icons/pivotal/chore.png b/plugins/tasks/tasks-core/src/icons/pivotal/chore.png index bfe2e63909e1..7479b84eb0df 100644 Binary files a/plugins/tasks/tasks-core/src/icons/pivotal/chore.png and b/plugins/tasks/tasks-core/src/icons/pivotal/chore.png differ diff --git a/plugins/tasks/tasks-core/src/icons/pivotal/chore@2x.png b/plugins/tasks/tasks-core/src/icons/pivotal/chore@2x.png new file mode 100644 index 000000000000..f4406c39f0a6 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/pivotal/chore@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/pivotal/feature.png b/plugins/tasks/tasks-core/src/icons/pivotal/feature.png index a68335907b15..26793add948f 100644 Binary files a/plugins/tasks/tasks-core/src/icons/pivotal/feature.png and b/plugins/tasks/tasks-core/src/icons/pivotal/feature.png differ diff --git a/plugins/tasks/tasks-core/src/icons/pivotal/feature@2x.png b/plugins/tasks/tasks-core/src/icons/pivotal/feature@2x.png new file mode 100644 index 000000000000..66f44bd2ad51 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/pivotal/feature@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/pivotal/release.png b/plugins/tasks/tasks-core/src/icons/pivotal/release.png index 10e71b0a54a3..fd41786c4d44 100644 Binary files a/plugins/tasks/tasks-core/src/icons/pivotal/release.png and b/plugins/tasks/tasks-core/src/icons/pivotal/release.png differ diff --git a/plugins/tasks/tasks-core/src/icons/pivotal/release@2x.png b/plugins/tasks/tasks-core/src/icons/pivotal/release@2x.png new file mode 100644 index 000000000000..2365649df2a4 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/pivotal/release@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/pivotal/release@2x_dark.png b/plugins/tasks/tasks-core/src/icons/pivotal/release@2x_dark.png new file mode 100644 index 000000000000..f14f527c048b Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/pivotal/release@2x_dark.png differ diff --git a/plugins/tasks/tasks-core/src/icons/pivotal/release_dark.png b/plugins/tasks/tasks-core/src/icons/pivotal/release_dark.png new file mode 100644 index 000000000000..d9e040fafe8b Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/pivotal/release_dark.png differ diff --git a/plugins/tasks/tasks-core/src/icons/pivotal@2x.png b/plugins/tasks/tasks-core/src/icons/pivotal@2x.png new file mode 100644 index 000000000000..f1afcaa3bcdb Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/pivotal@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/redmine.png b/plugins/tasks/tasks-core/src/icons/redmine.png index 391f369cba6e..d07109f4cb53 100644 Binary files a/plugins/tasks/tasks-core/src/icons/redmine.png and b/plugins/tasks/tasks-core/src/icons/redmine.png differ diff --git a/plugins/tasks/tasks-core/src/icons/redmine@2x.png b/plugins/tasks/tasks-core/src/icons/redmine@2x.png new file mode 100644 index 000000000000..55ae4db6476c Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/redmine@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/savedContext.png b/plugins/tasks/tasks-core/src/icons/savedContext.png index 84b5f8910735..4eecb92bb136 100644 Binary files a/plugins/tasks/tasks-core/src/icons/savedContext.png and b/plugins/tasks/tasks-core/src/icons/savedContext.png differ diff --git a/plugins/tasks/tasks-core/src/icons/savedContext@2x.png b/plugins/tasks/tasks-core/src/icons/savedContext@2x.png new file mode 100644 index 000000000000..1c03eaad1a36 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/savedContext@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/sprintly.png b/plugins/tasks/tasks-core/src/icons/sprintly.png index 4e1fd1d746b2..c95cc07e904c 100644 Binary files a/plugins/tasks/tasks-core/src/icons/sprintly.png and b/plugins/tasks/tasks-core/src/icons/sprintly.png differ diff --git a/plugins/tasks/tasks-core/src/icons/sprintly@2x.png b/plugins/tasks/tasks-core/src/icons/sprintly@2x.png new file mode 100644 index 000000000000..abfbc600a474 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/sprintly@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/startTimer.png b/plugins/tasks/tasks-core/src/icons/startTimer.png index d600e7979be6..2d68e012c82e 100644 Binary files a/plugins/tasks/tasks-core/src/icons/startTimer.png and b/plugins/tasks/tasks-core/src/icons/startTimer.png differ diff --git a/plugins/tasks/tasks-core/src/icons/startTimer@2x.png b/plugins/tasks/tasks-core/src/icons/startTimer@2x.png new file mode 100644 index 000000000000..c3bf2479288f Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/startTimer@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/stopTimer.png b/plugins/tasks/tasks-core/src/icons/stopTimer.png index dfeccbaf4b82..54502704d26b 100644 Binary files a/plugins/tasks/tasks-core/src/icons/stopTimer.png and b/plugins/tasks/tasks-core/src/icons/stopTimer.png differ diff --git a/plugins/tasks/tasks-core/src/icons/stopTimer@2x.png b/plugins/tasks/tasks-core/src/icons/stopTimer@2x.png new file mode 100644 index 000000000000..aa3486c09722 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/stopTimer@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/trac.png b/plugins/tasks/tasks-core/src/icons/trac.png index 2275f30a11d0..dc10451e2dbc 100644 Binary files a/plugins/tasks/tasks-core/src/icons/trac.png and b/plugins/tasks/tasks-core/src/icons/trac.png differ diff --git a/plugins/tasks/tasks-core/src/icons/trac@2x.png b/plugins/tasks/tasks-core/src/icons/trac@2x.png new file mode 100644 index 000000000000..c5c5532a7e93 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/trac@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/trello.png b/plugins/tasks/tasks-core/src/icons/trello.png index 86d6c6ea5e45..95806c6527fe 100644 Binary files a/plugins/tasks/tasks-core/src/icons/trello.png and b/plugins/tasks/tasks-core/src/icons/trello.png differ diff --git a/plugins/tasks/tasks-core/src/icons/trello@2x.png b/plugins/tasks/tasks-core/src/icons/trello@2x.png new file mode 100644 index 000000000000..e27ba0af71fd Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/trello@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/unknown.png b/plugins/tasks/tasks-core/src/icons/unknown.png index 609fd60936e6..04c30c9facae 100644 Binary files a/plugins/tasks/tasks-core/src/icons/unknown.png and b/plugins/tasks/tasks-core/src/icons/unknown.png differ diff --git a/plugins/tasks/tasks-core/src/icons/unknown@2x.png b/plugins/tasks/tasks-core/src/icons/unknown@2x.png new file mode 100644 index 000000000000..8d1e84ca4569 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/unknown@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/youtrack.png b/plugins/tasks/tasks-core/src/icons/youtrack.png index de7b35dce28e..437f9eba6993 100644 Binary files a/plugins/tasks/tasks-core/src/icons/youtrack.png and b/plugins/tasks/tasks-core/src/icons/youtrack.png differ diff --git a/plugins/tasks/tasks-core/src/icons/youtrack@2x.png b/plugins/tasks/tasks-core/src/icons/youtrack@2x.png new file mode 100644 index 000000000000..6ba3829c6ff6 Binary files /dev/null and b/plugins/tasks/tasks-core/src/icons/youtrack@2x.png differ diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/XsltSupport.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/XsltSupport.java index 3a412bf3ca8c..68c031cea400 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/XsltSupport.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/XsltSupport.java @@ -15,6 +15,8 @@ */ package org.intellij.lang.xpath.xslt; +import com.intellij.openapi.editor.DefaultLanguageHighlighterColors; +import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.util.Key; import com.intellij.psi.PsiElement; @@ -47,6 +49,8 @@ public class XsltSupport { public static final String XSLT_NS = "http://www.w3.org/1999/XSL/Transform"; public static final String PLUGIN_EXTENSIONS_NS = "urn:idea:xslt-plugin#extensions"; public static final Key> FORCE_XSLT_KEY = Key.create("FORCE_XSLT"); + public static final TextAttributesKey XSLT_DIRECTIVE = + TextAttributesKey.createTextAttributesKey("XSLT_DIRECTIVE", DefaultLanguageHighlighterColors.TEMPLATE_LANGUAGE_COLOR); private static final Map XPATH_ATTR_MAP = new THashMap(10); private static final Map> XPATH_AVT_MAP = new THashMap>(10); diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/validation/XsltColorPage.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/validation/XsltColorPage.java new file mode 100644 index 000000000000..e4f7f43057f0 --- /dev/null +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/validation/XsltColorPage.java @@ -0,0 +1,61 @@ +/* + * 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.intellij.lang.xpath.xslt.validation; + +import com.intellij.openapi.editor.colors.TextAttributesKey; +import com.intellij.openapi.options.colors.AttributesDescriptor; +import com.intellij.openapi.options.colors.pages.XMLColorsPage; +import org.intellij.lang.xpath.xslt.XsltSupport; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.Map; + +/** + * @author Dmitry Avdeev + */ +public class XsltColorPage extends XMLColorsPage { + @NotNull + @Override + public String getDisplayName() { + return "XSLT"; + } + + @NotNull + @Override + public AttributesDescriptor[] getAttributeDescriptors() { + return new AttributesDescriptor[] { new AttributesDescriptor("XSLT directive", XsltSupport.XSLT_DIRECTIVE)}; + } + + @NotNull + @Override + public String getDemoText() { + return "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + } + + @Override + public Map getAdditionalHighlightingTagToDescriptorMap() { + return Collections.singletonMap("xsl", XsltSupport.XSLT_DIRECTIVE); + } +} diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/validation/XsltNSColorProvider.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/validation/XsltNSColorProvider.java new file mode 100644 index 000000000000..6687c71e70c2 --- /dev/null +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/validation/XsltNSColorProvider.java @@ -0,0 +1,37 @@ +/* + * 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.intellij.lang.xpath.xslt.validation; + +import com.intellij.codeInsight.daemon.impl.analysis.XmlNSColorProvider; +import com.intellij.openapi.editor.colors.TextAttributesKey; +import com.intellij.psi.xml.XmlElement; +import com.intellij.psi.xml.XmlTag; +import org.intellij.lang.xpath.xslt.XsltSupport; +import org.jetbrains.annotations.Nullable; + +/** + * @author Dmitry Avdeev + */ +public class XsltNSColorProvider implements XmlNSColorProvider { + + @Nullable + @Override + public TextAttributesKey getKeyForNamespace(String namespace, XmlElement context) { + if (!(context instanceof XmlTag)) return null; + if (XsltSupport.XSLT_NS.equals(((XmlTag)context).getNamespace())) return XsltSupport.XSLT_DIRECTIVE; + return null; + } +} diff --git a/plugins/xpath/xpath-view/src/META-INF/plugin.xml b/plugins/xpath/xpath-view/src/META-INF/plugin.xml index 840cccb76aca..0be80ec48645 100644 --- a/plugins/xpath/xpath-view/src/META-INF/plugin.xml +++ b/plugins/xpath/xpath-view/src/META-INF/plugin.xml @@ -145,6 +145,9 @@ + + + diff --git a/python/edu/course-creator/resources/fileTemplates/internal/test_helper.py.ft b/python/edu/course-creator/resources/fileTemplates/internal/test_helper.py.ft index 9d1842742845..313b9150c467 100644 --- a/python/edu/course-creator/resources/fileTemplates/internal/test_helper.py.ft +++ b/python/edu/course-creator/resources/fileTemplates/internal/test_helper.py.ft @@ -46,9 +46,9 @@ def check_importable_path(path): try: import_file(path) except: - failed("File contains syntax errors", test_file_importable.func_name) + failed("File contains syntax errors", test_file_importable.__name__) return - passed(test_file_importable.func_name) + passed(test_file_importable.__name__) def import_file(path): 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/learn-python/resources/courses/introduction_course.zip b/python/edu/learn-python/resources/courses/introduction_course.zip index 07ad882088c1..c44ce1790f94 100644 Binary files a/python/edu/learn-python/resources/courses/introduction_course.zip and b/python/edu/learn-python/resources/courses/introduction_course.zip differ diff --git a/python/helpers/pydev/third_party/pkgutil_old.py b/python/helpers/pydev/_pydev_imps/_pydev_pkgutil_old.py similarity index 100% rename from python/helpers/pydev/third_party/pkgutil_old.py rename to python/helpers/pydev/_pydev_imps/_pydev_pkgutil_old.py diff --git a/python/helpers/pydev/third_party/pluginbase.py b/python/helpers/pydev/_pydev_imps/_pydev_pluginbase.py similarity index 99% rename from python/helpers/pydev/third_party/pluginbase.py rename to python/helpers/pydev/_pydev_imps/_pydev_pluginbase.py index 18bd50524fc2..ed4203fb6f89 100644 --- a/python/helpers/pydev/third_party/pluginbase.py +++ b/python/helpers/pydev/_pydev_imps/_pydev_pluginbase.py @@ -16,14 +16,14 @@ from pydevd_constants import IS_PY24, IS_PY3K, IS_JYTHON if IS_PY24: - from third_party.uuid_old import uuid4 + from _pydev_imps._pydev_uuid_old import uuid4 else: from uuid import uuid4 if IS_PY3K: import pkgutil else: - import pkgutil_old as pkgutil + from _pydev_imps import _pydev_pkgutil_old as pkgutil import errno try: diff --git a/python/helpers/pydev/third_party/uuid_old.py b/python/helpers/pydev/_pydev_imps/_pydev_uuid_old.py similarity index 100% rename from python/helpers/pydev/third_party/uuid_old.py rename to python/helpers/pydev/_pydev_imps/_pydev_uuid_old.py diff --git a/python/helpers/pydev/pydev_ipython/matplotlibtools.py b/python/helpers/pydev/pydev_ipython/matplotlibtools.py index 2b9f1e72209e..075c43781ab3 100644 --- a/python/helpers/pydev/pydev_ipython/matplotlibtools.py +++ b/python/helpers/pydev/pydev_ipython/matplotlibtools.py @@ -49,7 +49,6 @@ def patch_use(interpreter): """ Patch matplotlib function 'use' """ matplotlib = sys.modules['matplotlib'] def patched_use(*args, **kwargs): - print "patched use!" matplotlib.real_use(*args, **kwargs) gui, backend = find_gui_and_backend() interpreter.enableGui(gui) diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/MultiProcessDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/MultiProcessDebugger.java index d54bac8de85f..834916b0cf2b 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/MultiProcessDebugger.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/MultiProcessDebugger.java @@ -359,6 +359,13 @@ public class MultiProcessDebugger implements ProcessDebugger { } } + @Override + public void setBreakpointWithFuncName(String typeId, String file, int line, String condition, String logExpression, String funcName) { + for (ProcessDebugger d : allDebuggers()) { + d.setBreakpointWithFuncName(typeId, file, line, condition, logExpression, funcName); + } + } + @Override public void removeBreakpoint(String typeId, String file, int line) { for (ProcessDebugger d : allDebuggers()) { diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProcessDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProcessDebugger.java index 0fa5a5c21931..22344434252b 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProcessDebugger.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/ProcessDebugger.java @@ -78,6 +78,8 @@ public interface ProcessDebugger { void setBreakpoint(String typeId, String file, int line, String condition, String logExpression); + void setBreakpointWithFuncName(String typeId, String file, int line, String condition, String logExpression, String funcName); + void removeBreakpoint(String typeId, String file, int line); void addCloseListener(RemoteDebuggerCloseListener remoteDebuggerCloseListener); diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java index 4ce7bdf67434..2d97a3fb1a7e 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java @@ -436,6 +436,16 @@ public class RemoteDebugger implements ProcessDebugger { execute(command); } + @Override + public void setBreakpointWithFuncName(String typeId, String file, int line, String condition, String logExpression, String funcName) { + final SetBreakpointCommand command = + new SetBreakpointCommand(this, typeId, file, line, + condition, + logExpression, + funcName); + execute(command); + } + @Override public void removeBreakpoint(String typeId, String file, int line) { final RemoveBreakpointCommand command = diff --git a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java index dbeb5dedfd7c..532e374d5c74 100644 --- a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java +++ b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java @@ -24,6 +24,7 @@ import com.intellij.execution.ui.ConsoleView; import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.execution.ui.ExecutionConsole; import com.intellij.openapi.application.ApplicationInfo; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileDocumentManager; @@ -34,6 +35,9 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.remote.RemoteProcessHandlerBase; import com.intellij.util.ui.UIUtil; import com.intellij.xdebugger.*; @@ -44,9 +48,11 @@ import com.intellij.xdebugger.breakpoints.XLineBreakpoint; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; import com.intellij.xdebugger.frame.XValueChildrenList; import com.intellij.xdebugger.stepping.XSmartStepIntoHandler; +import com.jetbrains.python.PythonFileType; import com.jetbrains.python.console.PythonDebugLanguageConsoleView; import com.jetbrains.python.console.pydev.PydevCompletionVariant; import com.jetbrains.python.debugger.pydev.*; +import com.jetbrains.python.psi.PyFunction; import com.jetbrains.python.run.PythonProcessHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -594,12 +600,36 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr return frame; } + private String getFunctionName(final XLineBreakpoint breakpoint) { + final VirtualFile file = breakpoint.getSourcePosition().getFile(); + final Document document = FileDocumentManager.getInstance().getDocument(file); + final Project project = getSession().getProject(); + final String[] funcName = new String[1]; + if (document != null) { + if (file.getFileType() == PythonFileType.INSTANCE) { + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + PsiElement psiElement = XDebuggerUtil.getInstance().findContextElement(file, breakpoint.getSourcePosition().getOffset(), + project, false); + PyFunction function = PsiTreeUtil.getParentOfType(psiElement, PyFunction.class); + if (function != null) { + funcName[0] = function.getName(); + } + } + }); + } + } + return funcName[0]; + } + public void addBreakpoint(final PySourcePosition position, final XLineBreakpoint breakpoint) { myRegisteredBreakpoints.put(position, breakpoint); if (isConnected()) { - myDebugger.setBreakpoint(breakpoint.getType().getId(), position.getFile(), position.getLine(), - breakpoint.getCondition(), - breakpoint.getLogExpression()); + myDebugger.setBreakpointWithFuncName(breakpoint.getType().getId(), position.getFile(), position.getLine(), + breakpoint.getCondition(), + breakpoint.getLogExpression(), + getFunctionName(breakpoint)); } } diff --git a/python/src/com/jetbrains/python/inspections/quickfix/AddEncodingQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/AddEncodingQuickFix.java index 8b65e34ad3ca..82f61cfb1b57 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/AddEncodingQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/AddEncodingQuickFix.java @@ -17,8 +17,15 @@ package com.jetbrains.python.inspections.quickfix; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.fileEditor.FileEditor; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileEditor.TextEditor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiComment; +import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.jetbrains.python.PyBundle; @@ -32,13 +39,13 @@ import org.jetbrains.annotations.NotNull; * add missing encoding declaration * # -*- coding: -*- * to the source file - * + *

* User: catherine */ public class AddEncodingQuickFix implements LocalQuickFix { - private String myDefaultEncoding; - private int myEncodingFormatIndex; + private final String myDefaultEncoding; + private final int myEncodingFormatIndex; public AddEncodingQuickFix(String defaultEncoding, int encodingFormatIndex) { myDefaultEncoding = defaultEncoding; @@ -57,14 +64,28 @@ public class AddEncodingQuickFix implements LocalQuickFix { } public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) { - PsiFile file = descriptor.getPsiElement().getContainingFile(); + final PsiElement element = descriptor.getPsiElement(); + final PsiFile file = element.getContainingFile(); if (file == null) return; PsiElement firstLine = file.getFirstChild(); if (firstLine instanceof PsiComment && firstLine.getText().startsWith("#!")) { firstLine = firstLine.getNextSibling(); } - PsiComment encodingLine = PyElementGenerator.getInstance(project).createFromText(LanguageLevel.forElement(file), PsiComment.class, - String.format(PyEncodingUtil.ENCODING_FORMAT_PATTERN[myEncodingFormatIndex], myDefaultEncoding)); - file.addBefore(encodingLine, firstLine); + final String commentText = String.format(PyEncodingUtil.ENCODING_FORMAT_PATTERN[myEncodingFormatIndex], myDefaultEncoding); + final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project); + PsiComment encodingComment = elementGenerator.createFromText(LanguageLevel.forElement(file), PsiComment.class, commentText); + encodingComment = (PsiComment)file.addBefore(encodingComment, firstLine); + + final FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(element.getContainingFile().getVirtualFile()); + if (fileEditor instanceof TextEditor) { + final Editor editor = ((TextEditor)fileEditor).getEditor(); + final Document document = editor.getDocument(); + final int insertedLineNumber = document.getLineNumber(encodingComment.getTextOffset()); + if (insertedLineNumber == document.getLineCount() - 1) { + PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document); + document.insertString(document.getLineEndOffset(insertedLineNumber), "\n"); + } + editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(insertedLineNumber + 1, 0)); + } } } diff --git a/python/testData/inspections/AddEncodingInEmptyFile.py b/python/testData/inspections/AddEncodingInEmptyFile.py new file mode 100644 index 000000000000..376db9193fc4 --- /dev/null +++ b/python/testData/inspections/AddEncodingInEmptyFile.py @@ -0,0 +1 @@ + diff --git a/python/testData/inspections/AddEncodingInEmptyFile_after.py b/python/testData/inspections/AddEncodingInEmptyFile_after.py new file mode 100644 index 000000000000..76ea4ea7c759 --- /dev/null +++ b/python/testData/inspections/AddEncodingInEmptyFile_after.py @@ -0,0 +1,2 @@ +# coding=utf-8 + \ No newline at end of file diff --git a/python/testData/inspections/AddEncoding_after.py b/python/testData/inspections/AddEncoding_after.py index ef08f90863b7..974d8ff7f054 100644 --- a/python/testData/inspections/AddEncoding_after.py +++ b/python/testData/inspections/AddEncoding_after.py @@ -1,2 +1,2 @@ # coding=utf-8 -c = "string" +c = "string" diff --git a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java index e49b0eaee6c8..c7e8d138aa83 100644 --- a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java +++ b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java @@ -349,11 +349,18 @@ public class PyQuickFixTest extends PyTestCase { PyBundle.message("QFIX.add.super"), true, true); } - public void testAddEncoding() { //PY-491 + //PY-491, PY-13297 + public void testAddEncoding() { doInspectionTest("AddEncoding.py", PyMandatoryEncodingInspection.class, PyBundle.message("QFIX.add.encoding"), true, true); } + // PY-13297 + public void testAddEncodingInEmptyFile() { + doInspectionTest("AddEncodingInEmptyFile.py", PyMandatoryEncodingInspection.class, + PyBundle.message("QFIX.add.encoding"), true, true); + } + public void testRemoveDecorator() { //PY-3348 doInspectionTest("RemoveDecorator.py", PyDecoratorInspection.class, PyBundle.message("QFIX.remove.decorator"), true, true); diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/XmlEmmetParser.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/XmlEmmetParser.java index 01ddc3ca563f..57dc97700a74 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/XmlEmmetParser.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/XmlEmmetParser.java @@ -313,7 +313,7 @@ public class XmlEmmetParser extends EmmetParser { } if (token == ZenCodingTokens.DOT || token == ZenCodingTokens.SHARP) { - final String name = token == ZenCodingTokens.DOT ? CLASS : ID; + final String name = getAttributeName(token); advance(); token = getToken(); final String value = getAttributeValueByToken(token); @@ -326,6 +326,10 @@ public class XmlEmmetParser extends EmmetParser { return null; } + protected String getAttributeName(ZenCodingToken delimiterToken) { + return delimiterToken == ZenCodingTokens.DOT ? CLASS : ID; + } + @Nullable private List> parseAttributeList() { final List> result = new ArrayList>(); diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/ZenCodingGenerator.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/ZenCodingGenerator.java index b15df8b5da2e..846eb867d844 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/ZenCodingGenerator.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/ZenCodingGenerator.java @@ -61,8 +61,8 @@ public abstract class ZenCodingGenerator { public static List getInstances() { List generators = new ArrayList(); - generators.add(XmlZenCodingGeneratorImpl.INSTANCE); Collections.addAll(generators, EP_NAME.getExtensions()); + generators.add(XmlZenCodingGeneratorImpl.INSTANCE); return generators; } diff --git a/xml/impl/src/com/intellij/xml/util/documentation/HtmlDocumentationProvider.java b/xml/impl/src/com/intellij/xml/util/documentation/HtmlDocumentationProvider.java index 271fd5b6ff3d..1b416f37b92d 100644 --- a/xml/impl/src/com/intellij/xml/util/documentation/HtmlDocumentationProvider.java +++ b/xml/impl/src/com/intellij/xml/util/documentation/HtmlDocumentationProvider.java @@ -19,6 +19,7 @@ import com.intellij.lang.Language; import com.intellij.lang.LanguageDocumentation; import com.intellij.lang.documentation.DocumentationProvider; import com.intellij.lang.documentation.DocumentationUtil; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiManager; @@ -273,7 +274,7 @@ public class HtmlDocumentationProvider implements DocumentationProvider { if (result== null && styleProvider !=null) { result = styleProvider.getDocumentationElementForLink(psiManager, link, context); } - if (result== null && ourScriptProvider !=null) { + if (result== null && ourScriptProvider != null && !DumbService.isDumb(psiManager.getProject())) { result = ourScriptProvider.getDocumentationElementForLink(psiManager, link,context); } return result; 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