From 004feaf21ed44dbb60ee23dd0ab7dbb9c59f56c8 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 20 Mar 2015 18:35:59 +0300 Subject: [PATCH 01/67] IDEA-137092 Ctrl+N must not be located within screen bounds --- .../src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java index cebe481c3d1e..e4dfaf2f37e2 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java @@ -881,6 +881,7 @@ public abstract class ChooseByNameBase { (10, (paneHeight - (y + preferredTextFieldPanelSize.height)) / (preferredTextFieldPanelSize.height / 2) - 1); ComponentPopupBuilder builder = JBPopupFactory.getInstance().createComponentPopupBuilder(myTextFieldPanel, myTextField); + builder.setLocateWithinScreenBounds(false); builder.setCancelCallback(new Computable() { @Override public Boolean compute() { From 1a876bb2429b3dc3db3a0737fa1044c7774943d5 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Fri, 20 Mar 2015 17:45:51 +0300 Subject: [PATCH 02/67] diff: fix assertion parent Window can be already disposed, throwing exception on setTitle() --- .../src/com/intellij/diff/impl/DiffRequestProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java b/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java index 1a39c5b5e658..0c6669125855 100644 --- a/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java +++ b/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java @@ -242,7 +242,7 @@ public abstract class DiffRequestProcessor implements Disposable { IdRunnable task = new IdRunnable(this) { @Override public void run() { - if (myApplyData == null) return; + if (myApplyData == null || myDisposed) return; doApplyRequest(myApplyData.request, myApplyData.force, myApplyData.scrollToChangePolicy); myApplyData = null; } From 096149ffc03a86c09ef7952530150e5241c6c674 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Fri, 20 Mar 2015 18:33:58 +0300 Subject: [PATCH 03/67] IDEA-137724 distraction free mode does not tell you subdirectory of file viewed in header --- .../fileEditor/impl/UniqueNameEditorTabTitleProvider.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/UniqueNameEditorTabTitleProvider.java b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/UniqueNameEditorTabTitleProvider.java index b84513d4b774..4ba54e5ee461 100644 --- a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/UniqueNameEditorTabTitleProvider.java +++ b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/UniqueNameEditorTabTitleProvider.java @@ -30,7 +30,10 @@ public class UniqueNameEditorTabTitleProvider implements EditorTabTitleProvider if (!UISettings.getInstance().SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES || DumbService.isDumb(project)) { return null; } - final String uniqueName = UniqueVFilePathBuilder.getInstance().getUniqueVirtualFilePathWithinOpenedFileEditors(project, file); + // Even though this is a 'tab title provider' it is used also when tabs are not shown, namely for building IDE frame title. + final String uniqueName = UISettings.getInstance().EDITOR_TAB_PLACEMENT == UISettings.TABS_NONE ? + UniqueVFilePathBuilder.getInstance().getUniqueVirtualFilePath(project, file) : + UniqueVFilePathBuilder.getInstance().getUniqueVirtualFilePathWithinOpenedFileEditors(project, file); return uniqueName.equals(file.getName()) ? null : uniqueName; } } From 995c551678f067cefafa842e0e44d336525d0cdc Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Fri, 20 Mar 2015 12:03:00 +0300 Subject: [PATCH 04/67] IDEA-137757 diff: fix memory leak myMainPanel has longer lifetime than toolbar. toolbars recteated on every DiffViewer change, while myMainPanes does not change. the issue was in adding listeners on myMainPanel in setTargetComponent(), preventing tollbar from collecting. this fix replaces TargetComponent with toolbar itself, thus these listeners will have same lifetime and will not cause leak --- .../src/com/intellij/diff/impl/DiffRequestProcessor.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java b/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java index 0c6669125855..eace4af9f1ee 100644 --- a/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java +++ b/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java @@ -34,6 +34,7 @@ import com.intellij.diff.util.DiffUserDataKeys; import com.intellij.diff.util.DiffUserDataKeysEx; import com.intellij.diff.util.DiffUserDataKeysEx.ScrollToPolicy; import com.intellij.diff.util.DiffUtil; +import com.intellij.ide.DataManager; import com.intellij.ide.impl.DataManagerImpl; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; @@ -429,7 +430,9 @@ public abstract class DiffRequestProcessor implements Disposable { protected void buildToolbar(@Nullable List viewerActions) { ActionGroup group = collectToolbarActions(viewerActions); ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.DIFF_TOOLBAR, group, true); - toolbar.setTargetComponent(myMainPanel); + + DataManager.registerDataProvider(toolbar.getComponent(), myMainPanel); + toolbar.setTargetComponent(toolbar.getComponent()); myToolbarPanel.setContent(toolbar.getComponent()); for (AnAction action : group.getChildren(null)) { From dab125d640b54e8013fc69a87afb530cd042651c Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 20 Mar 2015 17:15:23 +0100 Subject: [PATCH 05/67] diff: default project used to fix NPE --- .../src/com/intellij/diff/applications/DiffApplication.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java b/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java index 8de2d02f1c07..0bbc064b3cab 100644 --- a/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java +++ b/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java @@ -21,6 +21,8 @@ import com.intellij.diff.DiffRequestFactory; import com.intellij.diff.requests.DiffRequest; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.diff.DiffBundle; +import com.intellij.openapi.project.DefaultProjectFactory; +import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -59,6 +61,7 @@ public class DiffApplication extends ApplicationStarterBase { file2.refresh(false, true); DiffRequest request = DiffRequestFactory.getInstance().createFromFiles(null, file1, file2); - DiffManagerEx.getInstance().showDiffBuiltin(null, request, DiffDialogHints.MODAL); + Project project = DefaultProjectFactory.getInstance().getDefaultProject(); + DiffManagerEx.getInstance().showDiffBuiltin(project, request, DiffDialogHints.MODAL); } } From 524d0278fb7ec5575402de4c3e1bf244d8854c23 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Fri, 20 Mar 2015 17:28:07 +0300 Subject: [PATCH 06/67] put ConsoleView actions back in language console --- .../com/intellij/execution/console/LanguageConsoleImpl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java index 23366fb404f1..0a87853657dc 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java @@ -466,7 +466,11 @@ public class LanguageConsoleImpl extends ConsoleViewImpl implements LanguageCons @Nullable @Override public Object getData(@NonNls String dataId) { - if (OpenFileDescriptor.NAVIGATE_IN_EDITOR.is(dataId)) { + Object data = super.getData(dataId); + if (data != null) { + return data; + } + else if (OpenFileDescriptor.NAVIGATE_IN_EDITOR.is(dataId)) { return myConsoleEditor; } else if (getProject().isInitialized()) { From e9e28e97879c15da35e9c80c9b1b3405c27ebcf0 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Fri, 20 Mar 2015 19:32:32 +0300 Subject: [PATCH 07/67] EA-66474: diff: Project should be NotNull --- .../src/com/intellij/diff/tools/dir/DirDiffViewer.java | 8 +++++++- .../intellij/openapi/diff/impl/dir/DirDiffTableModel.java | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffViewer.java index 75f496f570c9..a4dd1e76416f 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffViewer.java @@ -38,6 +38,8 @@ import com.intellij.openapi.diff.impl.dir.DirDiffFrame; import com.intellij.openapi.diff.impl.dir.DirDiffPanel; import com.intellij.openapi.diff.impl.dir.DirDiffTableModel; import com.intellij.openapi.diff.impl.dir.DirDiffWindow; +import com.intellij.openapi.project.DefaultProjectFactory; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -63,7 +65,11 @@ class DirDiffViewer implements FrameDiffTool.DiffViewer { List contents = request.getContents(); DiffElement element1 = createDiffElement(contents.get(0)); DiffElement element2 = createDiffElement(contents.get(1)); - DirDiffTableModel model = new DirDiffTableModel(context.getProject(), element1, element2, new DirDiffSettings()); + + Project project = context.getProject(); + if (project == null) project = DefaultProjectFactory.getInstance().getDefaultProject(); + + DirDiffTableModel model = new DirDiffTableModel(project, element1, element2, new DirDiffSettings()); myDirDiffPanel = new DirDiffPanel(model, new DirDiffWindow((DirDiffFrame)null) { @Override diff --git a/platform/diff-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffTableModel.java b/platform/diff-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffTableModel.java index 8b799509a1fd..573dbd7a4345 100644 --- a/platform/diff-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffTableModel.java +++ b/platform/diff-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffTableModel.java @@ -82,7 +82,7 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode public static final String EMPTY_STRING = " "; private DirDiffPanel myPanel; - public DirDiffTableModel(Project project, DiffElement src, DiffElement trg, DirDiffSettings settings) { + public DirDiffTableModel(@NotNull Project project, DiffElement src, DiffElement trg, DirDiffSettings settings) { myProject = project; mySettings = settings; mySrc = src; From 30eba5a9e176caeef9ed7517d9bfd864baf83fac Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 4 Mar 2015 20:23:19 +0300 Subject: [PATCH 08/67] [git] IDEA-103211 Support urls of different nature for a single remote * GitHandler: set up both SSH and HTTP authentication environments for any remote command without analyzing urls. * Let specify several urls to the GitHandler, and do it for pull, push, fetch, and ls-remote commands * Modify Git interface for some commands to accept GitRemote instead of remoteName + remoteUrl, but still keep the previous signature in some cases where GitRemote object doesn't exist yet (e.g. in clone). --- .../util/CloudGitDeploymentRuntime.java | 2 +- .../src/git4idea/actions/GitPull.java | 10 +- .../GitDeleteRemoteBranchOperation.java | 12 +- .../git4idea/src/git4idea/commands/Git.java | 16 +-- .../src/git4idea/commands/GitHandler.java | 126 ++++++++++-------- .../git4idea/commands/GitHttpAuthService.java | 6 +- .../commands/GitHttpAuthServiceImpl.java | 6 +- .../commands/GitHttpGuiAuthenticator.java | 32 +++-- .../src/git4idea/commands/GitImpl.java | 98 +++++++------- .../git4idea/commands/GitRemoteProtocol.java | 43 ------ .../src/git4idea/merge/GitPullDialog.java | 4 +- .../src/git4idea/push/GitPushOperation.java | 4 +- .../src/git4idea/update/GitFetcher.java | 41 ++---- .../push/GitPushOperationMultiRepoTest.java | 15 +-- .../git4idea/test/GitHttpAuthTestService.java | 10 +- .../GithubCreatePullRequestTestBase.java | 2 +- 16 files changed, 187 insertions(+), 240 deletions(-) delete mode 100644 plugins/git4idea/src/git4idea/commands/GitRemoteProtocol.java diff --git a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java index 3ac118fe6b7f..3c7c0c76e03f 100644 --- a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java +++ b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java @@ -402,7 +402,7 @@ public class CloudGitDeploymentRuntime extends CloudDeploymentRuntime { protected void push(@NotNull CloudGitApplication application, @NotNull GitRepository repository, @NotNull String remote) throws ServerRuntimeException { GitCommandResult gitPushResult - = getGit().push(repository, remote, application.getGitUrl(), "master:master", createGitLineHandlerListener()); + = getGit().push(repository, remote, application.getGitUrl(), "master:master", false, createGitLineHandlerListener()); checkGitResult(gitPushResult); } diff --git a/plugins/git4idea/src/git4idea/actions/GitPull.java b/plugins/git4idea/src/git4idea/actions/GitPull.java index 3ed4c84e504d..93877f11c5f2 100644 --- a/plugins/git4idea/src/git4idea/actions/GitPull.java +++ b/plugins/git4idea/src/git4idea/actions/GitPull.java @@ -27,6 +27,7 @@ import git4idea.repo.GitRepository; import git4idea.repo.GitRepositoryManager; import org.jetbrains.annotations.NotNull; +import java.util.Collections; import java.util.List; public class GitPull extends GitMergeAction { @@ -49,17 +50,16 @@ public class GitPull extends GitMergeAction { GitRepository repository = repositoryManager.getRepositoryForRoot(dialog.gitRoot()); assert repository != null : "Repository can't be null for root " + dialog.gitRoot(); String remoteOrUrl = dialog.getRemote(); - - GitRemote remote = GitUtil.findRemoteByName(repository, remoteOrUrl); - final String url = (remote == null) ? remoteOrUrl : remote.getFirstUrl(); - if (url == null) { + if (remoteOrUrl == null) { return null; } + GitRemote remote = GitUtil.findRemoteByName(repository, remoteOrUrl); + final List urls = remote == null ? Collections.singletonList(remoteOrUrl) : remote.getUrls(); Computable handlerProvider = new Computable() { @Override public GitLineHandler compute() { - return dialog.makeHandler(url); + return dialog.makeHandler(urls); } }; return new DialogState(dialog.gitRoot(), GitBundle.message("pulling.title", dialog.getRemote()), handlerProvider); diff --git a/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java b/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java index 8aa308623dbd..2bec81e5ef3b 100644 --- a/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java +++ b/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java @@ -157,18 +157,12 @@ class GitDeleteRemoteBranchOperation extends GitBranchOperation { return GitCommandResult.error(error); } - String remoteUrl = remote.getFirstUrl(); - if (remoteUrl == null) { - LOG.warn("No urls are defined for remote: " + remote); - return GitCommandResult.error("There is no urls defined for remote " + remote.getName()); - } - return pushDeletionNatively(repository, remoteName, remoteUrl, branchName); + return pushDeletionNatively(repository, remote, branchName); } @NotNull - private GitCommandResult pushDeletionNatively(@NotNull GitRepository repository, @NotNull String remoteName, @NotNull String url, - @NotNull String branchName) { - return myGit.push(repository, remoteName, url,":" + branchName); + private GitCommandResult pushDeletionNatively(@NotNull GitRepository repository, @NotNull GitRemote remote, @NotNull String branchName) { + return myGit.push(repository, remote, ":" + branchName, false, false, null); } @Nullable diff --git a/plugins/git4idea/src/git4idea/commands/Git.java b/plugins/git4idea/src/git4idea/commands/Git.java index 836a6a7d8b79..58035e609e6a 100644 --- a/plugins/git4idea/src/git4idea/commands/Git.java +++ b/plugins/git4idea/src/git4idea/commands/Git.java @@ -20,8 +20,6 @@ import com.intellij.openapi.util.Computable; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import git4idea.GitCommit; -import git4idea.GitLocalBranch; -import git4idea.GitRemoteBranch; import git4idea.repo.GitRemote; import git4idea.repo.GitRepository; import git4idea.reset.GitResetMode; @@ -106,14 +104,10 @@ public interface Git { GitCommandResult push(@NotNull GitRepository repository, @NotNull String remote, @Nullable String url, @NotNull String spec, boolean updateTracking, @NotNull GitLineHandlerListener... listeners); - @NotNull - GitCommandResult push(@NotNull GitRepository repository, @NotNull String remote, @Nullable String url, @NotNull String spec, - @NotNull GitLineHandlerListener... listeners); - @NotNull GitCommandResult push(@NotNull GitRepository repository, - @NotNull GitLocalBranch source, - @NotNull GitRemoteBranch target, + @NotNull GitRemote remote, + @NotNull String spec, boolean force, boolean updateTracking, @Nullable String tagMode, @@ -143,8 +137,10 @@ public interface Git { List history(@NotNull GitRepository repository, @NotNull String range); @NotNull - GitCommandResult fetch(@NotNull GitRepository repository, @NotNull String url, @NotNull String remote, - @NotNull List listeners, String... params); + GitCommandResult fetch(@NotNull GitRepository repository, + @NotNull GitRemote remote, + @NotNull List listeners, + String... params); @NotNull GitCommandResult addRemote(@NotNull GitRepository repository, @NotNull String name, @NotNull String url); diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java index 5bee0181b257..6b9e6f315663 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java @@ -22,6 +22,7 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; @@ -36,6 +37,7 @@ import com.intellij.util.EnvironmentUtil; import com.intellij.util.EventDispatcher; import com.intellij.util.ObjectUtils; import com.intellij.util.Processor; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.URLUtil; import com.intellij.util.net.HttpConfigurable; import com.intellij.util.net.IdeaWideProxySelector; @@ -52,11 +54,14 @@ import org.jetbrains.git4idea.ssh.GitSSHHandler; import org.jetbrains.git4idea.ssh.GitXmlRpcSshService; import java.io.File; +import java.io.IOException; import java.io.OutputStream; import java.nio.charset.Charset; import java.util.*; import java.util.concurrent.LinkedBlockingQueue; +import static java.util.Collections.singletonList; + /** * A handler for git commands */ @@ -81,7 +86,8 @@ public abstract class GitHandler { private final File myWorkingDirectory; private boolean myEnvironmentCleanedUp = true; // the flag indicating that environment has been cleaned up, by default is true because there is nothing to clean - private int myHandlerNo; + private int mySshHandler; + private int myHttpHandler; private Processor myInputProcessor; // The processor for stdin // if true process might be cancelled @@ -110,7 +116,7 @@ public abstract class GitHandler { private long myStartTime; // git execution start timestamp private static final long LONG_TIME = 10 * 1000; - @Nullable private String myUrl; + @Nullable private Collection myUrls; private boolean myHttpAuthFailed; @@ -234,13 +240,16 @@ public abstract class GitHandler { return file; } - @SuppressWarnings("NullableProblems") public void setUrl(@NotNull String url) { - myUrl = url; + setUrls(singletonList(url)); + } + + public void setUrls(@NotNull Collection urls) { + myUrls = urls; } protected boolean isRemote() { - return myUrl != null; + return myUrls != null; } /** @@ -435,46 +444,12 @@ public abstract class GitHandler { } // setup environment - GitRemoteProtocol remoteProtocol = GitRemoteProtocol.fromUrl(myUrl); - if (remoteProtocol == GitRemoteProtocol.SSH && myProjectSettings.isIdeaSsh()) { - GitXmlRpcSshService ssh = ServiceManager.getService(GitXmlRpcSshService.class); - myEnv.put(GitSSHHandler.GIT_SSH_ENV, ssh.getScriptPath().getPath()); - myHandlerNo = ssh.registerHandler(new GitSSHGUIHandler(myProject)); - myEnvironmentCleanedUp = false; - myEnv.put(GitSSHHandler.SSH_HANDLER_ENV, Integer.toString(myHandlerNo)); - int port = ssh.getXmlRcpPort(); - myEnv.put(GitSSHHandler.SSH_PORT_ENV, Integer.toString(port)); - LOG.debug(String.format("handler=%s, port=%s", myHandlerNo, port)); - - final HttpConfigurable httpConfigurable = HttpConfigurable.getInstance(); - boolean useHttpProxy = httpConfigurable.USE_HTTP_PROXY && !isSshUrlExcluded(httpConfigurable, myUrl); - myEnv.put(GitSSHHandler.SSH_USE_PROXY_ENV, String.valueOf(useHttpProxy)); - - if (useHttpProxy) { - myEnv.put(GitSSHHandler.SSH_PROXY_HOST_ENV, StringUtil.notNullize(httpConfigurable.PROXY_HOST)); - myEnv.put(GitSSHHandler.SSH_PROXY_PORT_ENV, String.valueOf(httpConfigurable.PROXY_PORT)); - boolean proxyAuthentication = httpConfigurable.PROXY_AUTHENTICATION; - myEnv.put(GitSSHHandler.SSH_PROXY_AUTHENTICATION_ENV, String.valueOf(proxyAuthentication)); - - if (proxyAuthentication) { - myEnv.put(GitSSHHandler.SSH_PROXY_USER_ENV, StringUtil.notNullize(httpConfigurable.PROXY_LOGIN)); - myEnv.put(GitSSHHandler.SSH_PROXY_PASSWORD_ENV, StringUtil.notNullize(httpConfigurable.getPlainProxyPassword())); - } + if (isRemote()) { + setupHttpAuthenticator(); + if (myProjectSettings.isIdeaSsh()) { + setupSshAuthenticator(); } } - else if (remoteProtocol == GitRemoteProtocol.HTTP) { - GitHttpAuthService service = ServiceManager.getService(GitHttpAuthService.class); - myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_ENV, service.getScriptPath().getPath()); - assert myUrl != null : "myUrl can't be null here"; - GitHttpAuthenticator httpAuthenticator = service.createAuthenticator(myProject, myCommand, myUrl); - myHandlerNo = service.registerHandler(httpAuthenticator); - myEnvironmentCleanedUp = false; - myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_HANDLER_ENV, Integer.toString(myHandlerNo)); - int port = service.getXmlRcpPort(); - myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_PORT_ENV, Integer.toString(port)); - LOG.debug(String.format("handler=%s, port=%s", myHandlerNo, port)); - addAuthListener(httpAuthenticator); - } myCommandLine.getEnvironment().clear(); myCommandLine.getEnvironment().putAll(myEnv); // start process @@ -493,9 +468,54 @@ public abstract class GitHandler { } } - protected static boolean isSshUrlExcluded(@NotNull HttpConfigurable httpConfigurable, @NotNull String url) { - String host = URLUtil.parseHostFromSshUrl(url); - return ((IdeaWideProxySelector)httpConfigurable.getOnlyBySettingsSelector()).isProxyException(host); + private void setupHttpAuthenticator() throws IOException { + GitHttpAuthService service = ServiceManager.getService(GitHttpAuthService.class); + myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_ENV, service.getScriptPath().getPath()); + GitHttpAuthenticator httpAuthenticator = service.createAuthenticator(myProject, myCommand, ObjectUtils.assertNotNull(myUrls)); + myHttpHandler = service.registerHandler(httpAuthenticator); + myEnvironmentCleanedUp = false; + myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_HANDLER_ENV, Integer.toString(myHttpHandler)); + int port = service.getXmlRcpPort(); + myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_PORT_ENV, Integer.toString(port)); + LOG.debug(String.format("handler=%s, port=%s", myHttpHandler, port)); + addAuthListener(httpAuthenticator); + } + + private void setupSshAuthenticator() throws IOException { + GitXmlRpcSshService ssh = ServiceManager.getService(GitXmlRpcSshService.class); + myEnv.put(GitSSHHandler.GIT_SSH_ENV, ssh.getScriptPath().getPath()); + mySshHandler = ssh.registerHandler(new GitSSHGUIHandler(myProject)); + myEnvironmentCleanedUp = false; + myEnv.put(GitSSHHandler.SSH_HANDLER_ENV, Integer.toString(mySshHandler)); + int port = ssh.getXmlRcpPort(); + myEnv.put(GitSSHHandler.SSH_PORT_ENV, Integer.toString(port)); + LOG.debug(String.format("handler=%s, port=%s", mySshHandler, port)); + + final HttpConfigurable httpConfigurable = HttpConfigurable.getInstance(); + boolean useHttpProxy = httpConfigurable.USE_HTTP_PROXY && !isSshUrlExcluded(httpConfigurable, ObjectUtils.assertNotNull(myUrls)); + myEnv.put(GitSSHHandler.SSH_USE_PROXY_ENV, String.valueOf(useHttpProxy)); + + if (useHttpProxy) { + myEnv.put(GitSSHHandler.SSH_PROXY_HOST_ENV, StringUtil.notNullize(httpConfigurable.PROXY_HOST)); + myEnv.put(GitSSHHandler.SSH_PROXY_PORT_ENV, String.valueOf(httpConfigurable.PROXY_PORT)); + boolean proxyAuthentication = httpConfigurable.PROXY_AUTHENTICATION; + myEnv.put(GitSSHHandler.SSH_PROXY_AUTHENTICATION_ENV, String.valueOf(proxyAuthentication)); + + if (proxyAuthentication) { + myEnv.put(GitSSHHandler.SSH_PROXY_USER_ENV, StringUtil.notNullize(httpConfigurable.PROXY_LOGIN)); + myEnv.put(GitSSHHandler.SSH_PROXY_PASSWORD_ENV, StringUtil.notNullize(httpConfigurable.getPlainProxyPassword())); + } + } + } + + protected static boolean isSshUrlExcluded(@NotNull final HttpConfigurable httpConfigurable, @NotNull Collection urls) { + return ContainerUtil.exists(urls, new Condition() { + @Override + public boolean value(String url) { + String host = URLUtil.parseHostFromSshUrl(url); + return ((IdeaWideProxySelector)httpConfigurable.getOnlyBySettingsSelector()).isProxyException(host); + } + }); } private void addAuthListener(@NotNull final GitHttpAuthenticator authenticator) { @@ -586,17 +606,11 @@ public abstract class GitHandler { if (myEnvironmentCleanedUp) { return; } - GitRemoteProtocol remoteProtocol = GitRemoteProtocol.fromUrl(myUrl); - if (remoteProtocol == GitRemoteProtocol.SSH) { - GitXmlRpcSshService ssh = ServiceManager.getService(GitXmlRpcSshService.class); - myEnvironmentCleanedUp = true; - ssh.unregisterHandler(myHandlerNo); - } - else if (remoteProtocol == GitRemoteProtocol.HTTP) { - GitHttpAuthService service = ServiceManager.getService(GitHttpAuthService.class); - myEnvironmentCleanedUp = true; - service.unregisterHandler(myHandlerNo); + if (isRemote()) { + ServiceManager.getService(GitXmlRpcSshService.class).unregisterHandler(mySshHandler); + ServiceManager.getService(GitHttpAuthService.class).unregisterHandler(myHttpHandler); } + myEnvironmentCleanedUp = true; } /** diff --git a/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java b/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java index 712582339405..6ddbcab22147 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java +++ b/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java @@ -22,6 +22,8 @@ import org.jetbrains.git4idea.http.GitAskPassXmlRpcHandler; import org.jetbrains.git4idea.ssh.GitXmlRpcHandlerService; import org.jetbrains.git4idea.util.ScriptGenerator; +import java.util.Collection; + /** * Provides the authentication mechanism for Git HTTP connections. */ @@ -45,7 +47,9 @@ public abstract class GitHttpAuthService extends GitXmlRpcHandlerService urls); /** * Internal handler implementation class, it is made public to be accessible via XML RPC. diff --git a/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java b/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java index cda188d64e4b..0d7b56dc8f9a 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java +++ b/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java @@ -18,6 +18,8 @@ package git4idea.commands; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; +import java.util.Collection; + /** * @author Kirill Likhodedov */ @@ -25,8 +27,8 @@ class GitHttpAuthServiceImpl extends GitHttpAuthService { @Override @NotNull - public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull String url) { - return new GitHttpGuiAuthenticator(project, command, url); + public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull Collection urls) { + return new GitHttpGuiAuthenticator(project, command, urls); } } diff --git a/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java b/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java index cf6b81c36cd6..9e4777be5174 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java +++ b/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java @@ -39,6 +39,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Arrays; +import java.util.Collection; import java.util.List; /** @@ -57,9 +58,9 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator { private static final Logger LOG = Logger.getInstance(GitHttpGuiAuthenticator.class); private static final Class PASS_REQUESTER = GitHttpAuthenticator.class; - @NotNull private final Project myProject; - @NotNull private final String myTitle; - @NotNull private final String myUrlFromCommand; + @NotNull private final Project myProject; + @NotNull private final String myTitle; + @NotNull private final Collection myUrlsFromCommand; @Nullable private String myPassword; @Nullable private String myPasswordKey; @@ -69,10 +70,10 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator { @Nullable private GitHttpAuthDataProvider myDataProvider; private boolean myWasCancelled; - GitHttpGuiAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull String url) { + GitHttpGuiAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull Collection url) { myProject = project; myTitle = "Git " + StringUtil.capitalize(command.name()); - myUrlFromCommand = url; + myUrlsFromCommand = url; } @Override @@ -195,18 +196,25 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator { if (StringUtil.isEmptyOrSpaces(url)) { // if Git doesn't specify the URL in the username/password query, we use the url from the Git command // We only take the host, to avoid entering the same password for different repositories on the same host. - return adjustHttpUrl(getHost(myUrlFromCommand)); + return adjustHttpUrl(getHost(myUrlsFromCommand)); } return adjustHttpUrl(url); } @NotNull - private static String getHost(@NotNull String url) { - Couple split = UriUtil.splitScheme(url); - String scheme = split.getFirst(); - String urlItself = split.getSecond(); - int pathStart = urlItself.indexOf("/"); - return scheme + URLUtil.SCHEME_SEPARATOR + urlItself.substring(0, pathStart); + private static String getHost(@NotNull Collection urls) { + String host = "unknown"; + for (String url : urls) { + Couple split = UriUtil.splitScheme(url); + String scheme = split.getFirst(); + String urlItself = split.getSecond(); + int pathStart = urlItself.indexOf("/"); + host = scheme + URLUtil.SCHEME_SEPARATOR + urlItself.substring(0, pathStart); + if (scheme.startsWith("http")) { + return host; + } + } + return host; } /** diff --git a/plugins/git4idea/src/git4idea/commands/GitImpl.java b/plugins/git4idea/src/git4idea/commands/GitImpl.java index 695ea348bc76..9a4cba14b543 100644 --- a/plugins/git4idea/src/git4idea/commands/GitImpl.java +++ b/plugins/git4idea/src/git4idea/commands/GitImpl.java @@ -39,6 +39,8 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; +import static java.util.Collections.singleton; + /** * Easy-to-use wrapper of common native Git commands. * Most of them return result as {@link GitCommandResult}. @@ -374,29 +376,47 @@ public class GitImpl implements Git { @Override @NotNull - public GitCommandResult push(@NotNull GitRepository repository, @NotNull String remote, @Nullable String url, @NotNull String spec, - boolean updateTracking, @NotNull GitLineHandlerListener... listeners) { - return doPush(repository, remote, url, spec, false, updateTracking, null, listeners); + public GitCommandResult push(@NotNull GitRepository repository, + @NotNull String remote, + @Nullable String url, + @NotNull String spec, + boolean updateTracking, + @NotNull GitLineHandlerListener... listeners) { + return doPush(repository, remote, singleton(url), spec, false, updateTracking, null, listeners); + } + + @Override + @NotNull + public GitCommandResult push(@NotNull GitRepository repository, + @NotNull GitRemote remote, + @NotNull String spec, + boolean force, + boolean updateTracking, + @Nullable String tagMode, + GitLineHandlerListener... listeners) { + return doPush(repository, remote.getName(), remote.getPushUrls(), spec, force, updateTracking, tagMode, listeners); } @NotNull - private GitCommandResult doPush(@NotNull final GitRepository repository, @NotNull final String remote, @Nullable final String url, - @NotNull final String spec, final boolean force, final boolean updateTracking, - @Nullable final String tagMode, - @NotNull final GitLineHandlerListener... listeners) { + private GitCommandResult doPush(@NotNull final GitRepository repository, + @NotNull final String remoteName, + @NotNull final Collection remoteUrls, + @NotNull final String spec, + final boolean force, + final boolean updateTracking, + @Nullable final String tagMode, + @NotNull final GitLineHandlerListener... listeners) { return runCommand(new Computable() { @Override public GitLineHandler compute() { final GitLineHandler h = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.PUSH); - if (url != null) { - h.setUrl(url); - } + h.setUrls(remoteUrls); h.setSilent(false); h.setStdoutSuppressed(false); addListeners(h, listeners); h.addProgressParameter(); h.addParameters("--porcelain"); - h.addParameters(remote); + h.addParameters(remoteName); h.addParameters(spec); if (updateTracking) { h.addParameters("--set-upstream"); @@ -412,31 +432,6 @@ public class GitImpl implements Git { }); } - @Override - @NotNull - public GitCommandResult push(@NotNull GitRepository repository, @NotNull String remote, @Nullable String url, @NotNull String spec, - @NotNull GitLineHandlerListener... listeners) { - return push(repository, remote, url, spec, false, listeners); - } - - @Override - @NotNull - public GitCommandResult push(@NotNull GitRepository repository, @NotNull GitLocalBranch source, @NotNull GitRemoteBranch target, - boolean force, boolean updateTracking, @Nullable String tagMode, GitLineHandlerListener... listeners) { - GitRemote remote = target.getRemote(); - Collection pushUrls = remote.getPushUrls(); // TODO handle the case with multiple pushurls with different protocols - String url; - if (pushUrls.isEmpty()) { - LOG.error("No urls or pushUrls are defined for " + remote); - url = null; - } - else { - url = pushUrls.iterator().next(); - } - String spec = source.getFullName() + ":" + target.getNameForRemoteOperations(); - return doPush(repository, remote.getName(), url, spec, force, updateTracking, tagMode, listeners); - } - @NotNull @Override public GitCommandResult show(@NotNull GitRepository repository, @NotNull String... params) { @@ -476,16 +471,18 @@ public class GitImpl implements Git { */ @Override @NotNull - public GitCommandResult fetch(@NotNull final GitRepository repository, @NotNull final String url, @NotNull final String remote, - @NotNull final List listeners, final String... params) { + public GitCommandResult fetch(@NotNull final GitRepository repository, + @NotNull final GitRemote remote, + @NotNull final List listeners, + final String... params) { return runCommand(new Computable() { @Override public GitLineHandler compute() { final GitLineHandler h = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.FETCH); h.setSilent(false); h.setStdoutSuppressed(false); - h.setUrl(url); - h.addParameters(remote); + h.setUrls(remote.getUrls()); + h.addParameters(remote.getName()); h.addParameters(params); h.addProgressParameter(); GitVcs vcs = GitVcs.getInstance(repository.getProject()); @@ -511,7 +508,7 @@ public class GitImpl implements Git { public GitCommandResult lsRemote(@NotNull final Project project, @NotNull final File workingDir, @NotNull final String url) { - return doLsRemote(project, workingDir, url, url); + return doLsRemote(project, workingDir, url, singleton(url)); } @NotNull @@ -520,27 +517,22 @@ public class GitImpl implements Git { @NotNull VirtualFile workingDir, @NotNull GitRemote remote, String... additionalParameters) { - return doLsRemote(project, VfsUtilCore.virtualToIoFile(workingDir), remote.getName(), remote.getFirstUrl(), additionalParameters); + return doLsRemote(project, VfsUtilCore.virtualToIoFile(workingDir), remote.getName(), remote.getUrls(), additionalParameters); } @NotNull - private GitCommandResult doLsRemote(@NotNull final Project project, - @NotNull final File workingDir, - @NotNull final String remoteId, - @Nullable final String authenticationUrl, - final String... additionalParameters) { + private static GitCommandResult doLsRemote(@NotNull final Project project, + @NotNull final File workingDir, + @NotNull final String remoteId, + @NotNull final Collection authenticationUrls, + final String... additionalParameters) { return run(new Computable() { @Override public GitLineHandler compute() { GitLineHandler h = new GitLineHandler(project, workingDir, GitCommand.LS_REMOTE); h.addParameters(additionalParameters); h.addParameters(remoteId); - if (authenticationUrl != null) { - h.setUrl(authenticationUrl); - } - else { - LOG.error("No valid URLs for remote " + remoteId); - } + h.setUrls(authenticationUrls); return h; } }); diff --git a/plugins/git4idea/src/git4idea/commands/GitRemoteProtocol.java b/plugins/git4idea/src/git4idea/commands/GitRemoteProtocol.java deleted file mode 100644 index be1da0262662..000000000000 --- a/plugins/git4idea/src/git4idea/commands/GitRemoteProtocol.java +++ /dev/null @@ -1,43 +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 git4idea.commands; - -import org.jetbrains.annotations.Nullable; - -/** -* @author Kirill Likhodedov -*/ -public enum GitRemoteProtocol { - GIT, - SSH, - HTTP; - - @Nullable - public static GitRemoteProtocol fromUrl(@Nullable String url) { - if (url == null) { - return null; - } - url = url.toLowerCase(); - if (url.startsWith("http")) { - return HTTP; - } - if (url.startsWith("git://")) { // "://" are there not to mix with scp-like syntax used for SSH: git@host.com/path/to.git - return GIT; - } - return SSH; - } - -} diff --git a/plugins/git4idea/src/git4idea/merge/GitPullDialog.java b/plugins/git4idea/src/git4idea/merge/GitPullDialog.java index f01a2083980e..21a7d2fb05da 100644 --- a/plugins/git4idea/src/git4idea/merge/GitPullDialog.java +++ b/plugins/git4idea/src/git4idea/merge/GitPullDialog.java @@ -178,11 +178,11 @@ public class GitPullDialog extends DialogWrapper { setOKActionEnabled(myBranchChooser.getMarkedElements().size() != 0); } - public GitLineHandler makeHandler(@NotNull String url) { + public GitLineHandler makeHandler(@NotNull List urls) { GitLineHandler h = new GitLineHandler(myProject, gitRoot(), GitCommand.PULL); // ignore merge failure for the pull h.ignoreErrorCode(1); - h.setUrl(url); + h.setUrls(urls); h.addProgressParameter(); h.addParameters("--no-stat"); if (myNoCommitCheckBox.isSelected()) { diff --git a/plugins/git4idea/src/git4idea/push/GitPushOperation.java b/plugins/git4idea/src/git4idea/push/GitPushOperation.java index 8973cd2b7b4b..545023aadfcc 100644 --- a/plugins/git4idea/src/git4idea/push/GitPushOperation.java +++ b/plugins/git4idea/src/git4idea/push/GitPushOperation.java @@ -368,7 +368,9 @@ public class GitPushOperation { GitLineHandlerListener progressListener = GitStandardProgressAnalyzer.createListener(myProgressIndicator); boolean setUpstream = pushSpec.getTarget().isNewBranchCreated() && !branchTrackingInfoIsSet(repository, sourceBranch); String tagMode = myTagMode == null ? null : myTagMode.getArgument(); - GitCommandResult res = myGit.push(repository, sourceBranch, targetBranch, myForce, setUpstream, tagMode, progressListener); + + String spec = sourceBranch.getFullName() + ":" + targetBranch.getNameForRemoteOperations(); + GitCommandResult res = myGit.push(repository, targetBranch.getRemote(), spec, myForce, setUpstream, tagMode, progressListener); return new ResultWithOutput(res); } diff --git a/plugins/git4idea/src/git4idea/update/GitFetcher.java b/plugins/git4idea/src/git4idea/update/GitFetcher.java index 0d01aaf30786..c9d70532db12 100644 --- a/plugins/git4idea/src/git4idea/update/GitFetcher.java +++ b/plugins/git4idea/src/git4idea/update/GitFetcher.java @@ -102,11 +102,7 @@ public class GitFetcher { if (remote == null) { return logError("Couldn't find remote with the name " + remoteName, null); } - String url = remote.getFirstUrl(); - if (url == null) { - return logError("URL is null for remote " + remote.getName(), null); - } - return fetchRemote(repository, remote, url, branch); + return fetchRemote(repository, remote, branch); } private static GitFetchResult logError(@NotNull String message, @Nullable String additionalInfo) { @@ -123,16 +119,14 @@ public class GitFetcher { } GitRemote remote = fetchParams.getRemote(); - String url = fetchParams.getUrl(); - return fetchRemote(repository, remote, url, null); + return fetchRemote(repository, remote, null); } @NotNull private GitFetchResult fetchRemote(@NotNull GitRepository repository, @NotNull GitRemote remote, - @NotNull String url, @Nullable String branch) { - return fetchNatively(repository, remote, url, branch); + return fetchNatively(repository, remote, branch); } // leaving this unused method, because the wanted behavior can change again @@ -146,8 +140,7 @@ public class GitFetcher { GitRemote remote = fetchParams.getRemote(); String remoteBranch = fetchParams.getRemoteBranch().getNameForRemoteOperations(); - String url = fetchParams.getUrl(); - return fetchNatively(repository, remote, url, remoteBranch); + return fetchNatively(repository, remote, remoteBranch); } @NotNull @@ -167,14 +160,7 @@ public class GitFetcher { } GitRemote remote = trackInfo.getRemote(); - String url = remote.getFirstUrl(); - if (url == null) { - String message = "URL is null for remote " + remote.getName(); - LOG.error(message); - return new FetchParams(GitFetchResult.error(new Exception(message))); - } - - return new FetchParams(remote, trackInfo.getRemoteBranch(), url); + return new FetchParams(remote, trackInfo.getRemoteBranch()); } @NotNull @@ -185,7 +171,7 @@ public class GitFetcher { LOG.error("URL is null for remote " + remote.getName()); continue; } - GitFetchResult res = fetchNatively(repository, remote, url, null); + GitFetchResult res = fetchNatively(repository, remote, null); res.addPruneInfo(fetchResult.getPrunedRefs()); fetchResult = res; if (!fetchResult.isSuccess()) { @@ -196,16 +182,15 @@ public class GitFetcher { } @NotNull - private static GitFetchResult fetchNatively(@NotNull GitRepository repository, @NotNull GitRemote remote, @NotNull String url, - @Nullable String branch) { + private static GitFetchResult fetchNatively(@NotNull GitRepository repository, @NotNull GitRemote remote, @Nullable String branch) { Git git = ServiceManager.getService(Git.class); String[] additionalParams = branch != null ? new String[]{ getFetchSpecForBranch(branch, remote.getName()) } : ArrayUtil.EMPTY_STRING_ARRAY; GitFetchPruneDetector pruneDetector = new GitFetchPruneDetector(); - GitCommandResult result = - git.fetch(repository, url, remote.getName(), Collections.singletonList(pruneDetector), additionalParams); + GitCommandResult result = git.fetch(repository, remote, + Collections.singletonList(pruneDetector), additionalParams); GitFetchResult fetchResult; if (result.success()) { @@ -347,16 +332,14 @@ public class GitFetcher { private GitRemote myRemote; private GitRemoteBranch myRemoteBranch; private GitFetchResult myError; - private String myUrl; FetchParams(GitFetchResult error) { myError = error; } - FetchParams(GitRemote remote, GitRemoteBranch remoteBranch, String url) { + FetchParams(GitRemote remote, GitRemoteBranch remoteBranch) { myRemote = remote; myRemoteBranch = remoteBranch; - myUrl = url; } boolean isError() { @@ -374,9 +357,5 @@ public class GitFetcher { public GitRemoteBranch getRemoteBranch() { return myRemoteBranch; } - - public String getUrl() { - return myUrl; - } } } diff --git a/plugins/git4idea/tests/git4idea/push/GitPushOperationMultiRepoTest.java b/plugins/git4idea/tests/git4idea/push/GitPushOperationMultiRepoTest.java index a053be8e9f6e..d069bd7db5fe 100644 --- a/plugins/git4idea/tests/git4idea/push/GitPushOperationMultiRepoTest.java +++ b/plugins/git4idea/tests/git4idea/push/GitPushOperationMultiRepoTest.java @@ -19,12 +19,11 @@ import com.intellij.dvcs.push.PushSpec; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Trinity; import com.intellij.util.containers.ContainerUtil; -import git4idea.GitLocalBranch; -import git4idea.GitRemoteBranch; import git4idea.commands.Git; import git4idea.commands.GitCommandResult; import git4idea.commands.GitImpl; import git4idea.commands.GitLineHandlerListener; +import git4idea.repo.GitRemote; import git4idea.repo.GitRepository; import git4idea.test.GitTestUtil; import git4idea.update.GitUpdateResult; @@ -80,20 +79,20 @@ public class GitPushOperationMultiRepoTest extends GitPushOperationBaseTest { private static class FailingPushGit extends GitImpl { private Condition myPushShouldFail; - @NotNull @Override + @NotNull public GitCommandResult push(@NotNull GitRepository repository, - @NotNull GitLocalBranch source, - @NotNull GitRemoteBranch target, + @NotNull GitRemote remote, + @NotNull String spec, boolean force, boolean updateTracking, @Nullable String tagMode, GitLineHandlerListener... listeners) { if (myPushShouldFail.value(repository)) { - return new GitCommandResult(false, 128, Collections.singletonList("Failed to push to " + target.getName()), + return new GitCommandResult(false, 128, Collections.singletonList("Failed to push to " + remote.getName()), Collections.emptyList(), null); } - return super.push(repository, source, target, force, updateTracking, tagMode, listeners); + return super.push(repository, remote, spec, force, updateTracking, tagMode, listeners); } } @@ -123,7 +122,7 @@ public class GitPushOperationMultiRepoTest extends GitPushOperationBaseTest { GitPushRepoResult result2 = result.getResults().get(myCommunity); assertResult(GitPushRepoResult.Type.ERROR, -1, "master", "origin/master", null, result1); - assertEquals("Error text is incorrect", "Failed to push to origin/master", result1.getError()); + assertEquals("Error text is incorrect", "Failed to push to origin", result1.getError()); assertResult(GitPushRepoResult.Type.SUCCESS, 1, "master", "origin/master", null, result2); } diff --git a/plugins/git4idea/tests/git4idea/test/GitHttpAuthTestService.java b/plugins/git4idea/tests/git4idea/test/GitHttpAuthTestService.java index 8723ce280269..cc5c9c5e22bf 100644 --- a/plugins/git4idea/tests/git4idea/test/GitHttpAuthTestService.java +++ b/plugins/git4idea/tests/git4idea/test/GitHttpAuthTestService.java @@ -21,6 +21,8 @@ import git4idea.commands.GitHttpAuthService; import git4idea.commands.GitHttpAuthenticator; import org.jetbrains.annotations.NotNull; +import java.util.Collection; + /** * @author Kirill Likhodedov */ @@ -30,23 +32,21 @@ public class GitHttpAuthTestService extends GitHttpAuthService { @NotNull @Override public String askPassword(@NotNull String url) { - throw new IllegalStateException("Authenticator was not registered"); + return ""; } @NotNull @Override public String askUsername(@NotNull String url) { - throw new IllegalStateException("Authenticator was not registered"); + return ""; } @Override public void saveAuthData() { - throw new IllegalStateException("Authenticator was not registered"); } @Override public void forgetPassword() { - throw new IllegalStateException("Authenticator was not registered"); } @Override @@ -59,7 +59,7 @@ public class GitHttpAuthTestService extends GitHttpAuthService { @NotNull @Override - public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull String url) { + public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull Collection urls) { return myAuthenticator; } diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTestBase.java b/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTestBase.java index b6a2058cd24f..1c0404be9280 100644 --- a/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTestBase.java +++ b/plugins/github/test/org/jetbrains/plugins/github/GithubCreatePullRequestTestBase.java @@ -67,7 +67,7 @@ public abstract class GithubCreatePullRequestTestBase extends GithubTest { protected void deleteRemoteBranch() { GitRepository repository = GithubUtil.getGitRepository(myProject, myProjectRoot); if (repository != null) { - ServiceManager.getService(Git.class).push(repository, "origin", PROJECT_URL, ":" + BRANCH_NAME); + ServiceManager.getService(Git.class).push(repository, "origin", PROJECT_URL, ":" + BRANCH_NAME, false); } } From 0493e76f3a788ebe3f1d0339cd7591ec03f56edd Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 4 Mar 2015 20:59:25 +0300 Subject: [PATCH 09/67] [git] IDEA-96402 Prune obsolete remote refs on branch delete --- .../GitDeleteRemoteBranchOperation.java | 41 +++++++++++-------- .../git4idea/src/git4idea/commands/Git.java | 3 ++ .../src/git4idea/commands/GitCommand.java | 5 +++ .../src/git4idea/commands/GitImpl.java | 16 ++++++++ 4 files changed, 47 insertions(+), 18 deletions(-) diff --git a/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java b/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java index 2bec81e5ef3b..82b7580cd6fa 100644 --- a/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java +++ b/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java @@ -121,22 +121,39 @@ class GitDeleteRemoteBranchOperation extends GitBranchOperation { } private boolean doDeleteRemote(@NotNull String branchName, @NotNull Collection repositories) { + Couple pair = splitNameOfRemoteBranch(branchName); + String remoteName = pair.getFirst(); + String branch = pair.getSecond(); + GitCompoundResult result = new GitCompoundResult(myProject); for (GitRepository repository : repositories) { - Couple pair = splitNameOfRemoteBranch(branchName); - String remote = pair.getFirst(); - String branch = pair.getSecond(); - GitCommandResult res = pushDeletion(repository, remote, branch); + GitCommandResult res; + GitRemote remote = getRemoteByName(repository, remoteName); + if (remote == null) { + String error = "Couldn't find remote by name: " + remoteName; + LOG.error(error); + res = GitCommandResult.error(error); + } + else { + res = pushDeletion(repository, remote, branch); + if (!res.success() && isAlreadyDeletedError(res.getErrorOutputAsJoinedString())) { + res = myGit.remotePrune(repository, remote); + } + } result.append(repository, res); repository.update(); } if (!result.totalSuccess()) { VcsNotifier.getInstance(myProject).notifyError("Failed to delete remote branch " + branchName, - result.getErrorOutputWithReposIndication()); + result.getErrorOutputWithReposIndication()); } return result.totalSuccess(); } + private static boolean isAlreadyDeletedError(@NotNull String errorOutput) { + return errorOutput.contains("remote ref does not exist"); + } + /** * Returns the remote and the "local" name of a remote branch. * Expects branch in format "origin/master", i.e. remote/branch @@ -149,19 +166,7 @@ class GitDeleteRemoteBranchOperation extends GitBranchOperation { } @NotNull - private GitCommandResult pushDeletion(@NotNull GitRepository repository, @NotNull String remoteName, @NotNull String branchName) { - GitRemote remote = getRemoteByName(repository, remoteName); - if (remote == null) { - String error = "Couldn't find remote by name: " + remoteName; - LOG.error(error); - return GitCommandResult.error(error); - } - - return pushDeletionNatively(repository, remote, branchName); - } - - @NotNull - private GitCommandResult pushDeletionNatively(@NotNull GitRepository repository, @NotNull GitRemote remote, @NotNull String branchName) { + private GitCommandResult pushDeletion(@NotNull GitRepository repository, @NotNull GitRemote remote, @NotNull String branchName) { return myGit.push(repository, remote, ":" + branchName, false, false, null); } diff --git a/plugins/git4idea/src/git4idea/commands/Git.java b/plugins/git4idea/src/git4idea/commands/Git.java index 58035e609e6a..c56a3d729fe0 100644 --- a/plugins/git4idea/src/git4idea/commands/Git.java +++ b/plugins/git4idea/src/git4idea/commands/Git.java @@ -153,4 +153,7 @@ public interface Git { @NotNull VirtualFile workingDir, @NotNull GitRemote remote, String... additionalParameters); + + @NotNull + GitCommandResult remotePrune(@NotNull GitRepository repository, @NotNull GitRemote remote); } diff --git a/plugins/git4idea/src/git4idea/commands/GitCommand.java b/plugins/git4idea/src/git4idea/commands/GitCommand.java index 32e367f84a35..d544ab54a48e 100644 --- a/plugins/git4idea/src/git4idea/commands/GitCommand.java +++ b/plugins/git4idea/src/git4idea/commands/GitCommand.java @@ -106,6 +106,11 @@ public class GitCommand { return new GitCommand(this, LockingPolicy.READ); } + @NotNull + public GitCommand writeLockingCommand() { + return new GitCommand(this, LockingPolicy.WRITE); + } + @NotNull private static GitCommand read(@NotNull String name) { return new GitCommand(name, LockingPolicy.READ); diff --git a/plugins/git4idea/src/git4idea/commands/GitImpl.java b/plugins/git4idea/src/git4idea/commands/GitImpl.java index 9a4cba14b543..a658879a9ed1 100644 --- a/plugins/git4idea/src/git4idea/commands/GitImpl.java +++ b/plugins/git4idea/src/git4idea/commands/GitImpl.java @@ -520,6 +520,22 @@ public class GitImpl implements Git { return doLsRemote(project, VfsUtilCore.virtualToIoFile(workingDir), remote.getName(), remote.getUrls(), additionalParameters); } + @NotNull + @Override + public GitCommandResult remotePrune(@NotNull final GitRepository repository, @NotNull final GitRemote remote) { + return run(new Computable() { + @Override + public GitLineHandler compute() { + GitLineHandler h = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.REMOTE.writeLockingCommand()); + h.setStdoutSuppressed(false); + h.addParameters("prune"); + h.addParameters(remote.getName()); + h.setUrls(remote.getUrls()); + return h; + } + }); + } + @NotNull private static GitCommandResult doLsRemote(@NotNull final Project project, @NotNull final File workingDir, From 22e0e70882d2b3440cc30b7e639a30bfab012a69 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 20 Mar 2015 15:27:37 +0100 Subject: [PATCH 10/67] no setText2 during "Scanning scope" inspection stage (IDEA-137831) --- .../src/com/intellij/analysis/AnalysisScope.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java b/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java index 73257051db51..5fedccd155be 100644 --- a/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java +++ b/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java @@ -177,6 +177,9 @@ public class AnalysisScope { protected PsiElementVisitor createFileSearcher() { final FileIndex fileIndex = getFileIndex(); final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); + if (indicator != null) { + indicator.setText(AnalysisScopeBundle.message("scanning.scope.progress.title")); + } return new PsiElementVisitor() { @Override @@ -191,12 +194,6 @@ public class AnalysisScope { } if (!shouldHighlightFile(file)) return; myFilesSet.add(virtualFile); - if (indicator != null) { - indicator.setText(AnalysisScopeBundle.message("scanning.scope.progress.title")); - Project project = file.getProject(); - String text = displayProjectRelativePath(virtualFile, project); - indicator.setText2(text); - } } } }; From 95a8299e196ca96ee6fe5c1dd53d17aba0e71fc5 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 20 Mar 2015 15:49:41 +0100 Subject: [PATCH 11/67] no clearResolveCache during "Scanning scope" inspection stage (IDEA-137831) --- .../com/intellij/analysis/AnalysisScope.java | 72 +++++++------------ 1 file changed, 27 insertions(+), 45 deletions(-) diff --git a/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java b/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java index 5fedccd155be..b70622ae2d0d 100644 --- a/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java +++ b/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java @@ -19,9 +19,7 @@ package com.intellij.analysis; import com.intellij.codeInsight.FileModificationService; import com.intellij.codeInsight.daemon.ProblemHighlightFilter; import com.intellij.lang.injection.InjectedLanguageManager; -import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; @@ -244,7 +242,7 @@ public class AnalysisScope { } else if (myType == DIRECTORY || myType == PROJECT || myType == MODULES || myType == MODULE || myType == CUSTOM) { myFilesSet = new HashSet(); - accept(createFileSearcher()); + accept(createFileSearcher(), false); } else if (myType == VIRTUAL_FILES) { myFilesSet = new HashSet(); @@ -272,16 +270,23 @@ public class AnalysisScope { public void accept(@NotNull final PsiElementVisitor visitor) { - accept(visitor, !ApplicationManager.getApplication().isReadAccessAllowed()); + accept(visitor, true); } - protected void accept(@NotNull final PsiElementVisitor visitor, final boolean needReadAction) { + private void accept(@NotNull final PsiElementVisitor visitor, final boolean clearResolveCache) { + final boolean needReadAction = !ApplicationManager.getApplication().isReadAccessAllowed(); final PsiManager psiManager = PsiManager.getInstance(myProject); final FileIndex fileIndex = getFileIndex(); accept(new Processor() { @Override public boolean process(VirtualFile file) { - return processFile(file, visitor, fileIndex, psiManager, needReadAction); + if (file.isDirectory()) return true; + if (ProjectCoreUtil.isProjectOrWorkspaceFile(file)) return true; + if (fileIndex.isInContent(file) && (myIncludeTestSource || !fileIndex.isInTestSourceContent(file)) + && !isInGeneratedSources(file, myProject)) { + return processFile(file, visitor, psiManager, needReadAction, clearResolveCache); + } + return true; } }); } @@ -372,20 +377,6 @@ public class AnalysisScope { }); } - private boolean processFile(@NotNull final VirtualFile fileOrDir, - @NotNull final PsiElementVisitor visitor, - @NotNull final FileIndex fileIndex, - @NotNull final PsiManager psiManager, - final boolean needReadAction) { - if (fileOrDir.isDirectory()) return true; - if (ProjectCoreUtil.isProjectOrWorkspaceFile(fileOrDir)) return true; - if (fileIndex.isInContent(fileOrDir) && (myIncludeTestSource || !fileIndex.isInTestSourceContent(fileOrDir)) - && !isInGeneratedSources(fileOrDir, psiManager.getProject())) { - return processFile(fileOrDir, visitor, psiManager, needReadAction); - } - return true; - } - private static boolean isInGeneratedSources(@NotNull VirtualFile file, @NotNull Project project) { for (GeneratedSourcesFilter filter : GeneratedSourcesFilter.EP_NAME.getExtensions()) { if (filter.isGeneratedSource(file, project)) { @@ -395,32 +386,15 @@ public class AnalysisScope { return false; } - private static boolean processFile(@NotNull final VirtualFile fileOrDir, + private static boolean processFile(@NotNull final VirtualFile vFile, @NotNull final PsiElementVisitor visitor, @NotNull final PsiManager psiManager, - final boolean needReadAction) { - final PsiFile file; - - AccessToken accessToken = ReadAction.start(); - try { - if (!fileOrDir.isValid()) return false; - - file = psiManager.findFile(fileOrDir); - if (file == null) { - //skip .class files under src directory - return true; - } - - if (!shouldHighlightFile(file)) return true; - } - finally { - accessToken.finish(); - } - + final boolean needReadAction, + final boolean clearResolveCache) { final Runnable runnable = new Runnable() { @Override public void run() { - doProcessFile(visitor, psiManager, file); + doProcessFile(visitor, psiManager, vFile, clearResolveCache); } }; if (needReadAction && !ApplicationManager.getApplication().isDispatchThread()) { @@ -468,10 +442,18 @@ public class AnalysisScope { } } - private static void doProcessFile(@NotNull PsiElementVisitor visitor, @NotNull PsiManager psiManager, @NotNull PsiFile file) { - file.accept(visitor); - psiManager.dropResolveCaches(); - InjectedLanguageManager.getInstance(file.getProject()).dropFileCaches(file); + private static void doProcessFile(@NotNull PsiElementVisitor visitor, @NotNull PsiManager psiManager, @NotNull VirtualFile vFile, + boolean clearResolveCache) { + if (!vFile.isValid()) return; + + PsiFile psiFile = psiManager.findFile(vFile); + if (psiFile == null || !shouldHighlightFile(psiFile)) return; + + psiFile.accept(visitor); + if (clearResolveCache) { + psiManager.dropResolveCaches(); + InjectedLanguageManager.getInstance(psiManager.getProject()).dropFileCaches(psiFile); + } } protected boolean accept(@NotNull final PsiDirectory dir, @NotNull final Processor processor) { From 755787e44253684cea6193c3931f075fcabbb8b6 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 20 Mar 2015 15:51:57 +0100 Subject: [PATCH 12/67] a bit faster ConcurrentHashMap.clear --- .../src/com/intellij/util/containers/ConcurrentHashMap.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentHashMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentHashMap.java index e511d3f4c2d6..1da7b756ea88 100644 --- a/platform/util/src/com/intellij/util/containers/ConcurrentHashMap.java +++ b/platform/util/src/com/intellij/util/containers/ConcurrentHashMap.java @@ -1210,6 +1210,8 @@ public final class ConcurrentHashMap extends AbstractMap */ @Override public void clear() { + if (isEmpty()) return; + long delta = 0L; // negative number of deletions int i = 0; Node[] tab = table; From 0e0e1b07fc8c39c55a4e9a4d3923387d4094a14e Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Fri, 20 Mar 2015 19:53:06 +0300 Subject: [PATCH 13/67] diff: cleanup --- .../src/com/intellij/diff/impl/DiffWindowBase.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java b/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java index f7b4dd7d1a56..8d9cff475107 100644 --- a/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java +++ b/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java @@ -19,8 +19,7 @@ import com.intellij.diff.DiffDialogHints; import com.intellij.diff.util.DiffUserDataKeys; import com.intellij.diff.util.DiffUtil; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CustomShortcutSet; -import com.intellij.openapi.keymap.KeymapManager; +import com.intellij.openapi.actionSystem.CommonShortcuts; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.WindowWrapper; @@ -73,8 +72,7 @@ public abstract class DiffWindowBase { public void actionPerformed(final AnActionEvent e) { myWrapper.close(); } - }.registerCustomShortcutSet(new CustomShortcutSet(KeymapManager.getInstance().getActiveKeymap().getShortcuts("CloseContent")), - myProcessor.getComponent()); + }.registerCustomShortcutSet(CommonShortcuts.getCloseActiveWindow(), myProcessor.getComponent()); } public void show() { From f15e70aa5eca8569a189a949b6dbc11a43f363ed Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Fri, 20 Mar 2015 20:08:34 +0300 Subject: [PATCH 14/67] IDEA-137726 File replace is not updating file name in title bar --- .../openapi/fileEditor/impl/FileEditorManagerImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java index 1cf6b6fe5682..ada2456c782e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java @@ -114,7 +114,8 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec private final List> mySelectionHistory = new ArrayList>(); private Reference myLastSelectedComposite = new WeakReference(null); - private final MergingUpdateQueue myQueue = new MergingUpdateQueue("FileEditorManagerUpdateQueue", 50, true, null); + private final MergingUpdateQueue myQueue = new MergingUpdateQueue("FileEditorManagerUpdateQueue", 50, true, + MergingUpdateQueue.ANY_COMPONENT); private final BusyObject.Impl.Simple myBusyObject = new BusyObject.Impl.Simple(); From 2d63e30ec1d6ec739282628139097104ce0924c3 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 20 Mar 2015 20:25:19 +0300 Subject: [PATCH 15/67] debugger: reuse monitor slot on exit from synchronized block --- .../ui/impl/watch/ArgumentValueDescriptorImpl.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java index 2e3653afaf02..545517903000 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -161,9 +161,15 @@ public class ArgumentValueDescriptorImpl extends ValueDescriptorImpl{ } public void visitSynchronizedStatement(PsiSynchronizedStatement statement) { - appendName(""); - myCurrentSlotIndex++; - super.visitSynchronizedStatement(statement); + myIndexStack.push(myCurrentSlotIndex); + try { + appendName(""); + myCurrentSlotIndex++; + super.visitSynchronizedStatement(statement); + } + finally { + myCurrentSlotIndex = myIndexStack.pop(); + } } private void appendName(String varName) { From b66000da0cf46727b6702ce077b6ef841f436ba2 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 20 Mar 2015 20:26:10 +0300 Subject: [PATCH 16/67] debugger: instruction parser should stop on code offset, not instruction index --- .../intellij/debugger/jdi/InstructionParser.java | 15 +++++---------- .../debugger/ui/impl/FrameVariablesTree.java | 3 +-- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/jdi/InstructionParser.java b/java/debugger/impl/src/com/intellij/debugger/jdi/InstructionParser.java index 78bf10fe7e40..2cfa649b10dc 100644 --- a/java/debugger/impl/src/com/intellij/debugger/jdi/InstructionParser.java +++ b/java/debugger/impl/src/com/intellij/debugger/jdi/InstructionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,21 +22,16 @@ import org.jetbrains.annotations.Nullable; */ public class InstructionParser { private final byte[] myCode; - private final long myCurrentInstructionIndex; + private final long myStopOffset; - public InstructionParser(byte[] code, long instructionIndex) { + public InstructionParser(byte[] code, long stopOffset) { myCode = code; - myCurrentInstructionIndex = instructionIndex; + myStopOffset = stopOffset; } public void parse() { - final int codeEnd = myCode.length; int v = 0; - int instructionIndex = 0; - while (v < codeEnd) { - if (instructionIndex++ >= myCurrentInstructionIndex) { - break; - } + while (v < myStopOffset) { int opcode = myCode[v] & 0xFF; final byte opcodeType = opcode == Bytecodes.IMPDEP1 || opcode == Bytecodes.IMPDEP2? Bytecodes.NOARG_INSN : Bytecodes.TYPE[opcode]; switch (opcodeType) { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java index c4c6201f0ee6..5bf55df20844 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java @@ -242,9 +242,8 @@ public class FrameVariablesTree extends DebuggerTree { final byte[] bytecodes = method.bytecodes(); if (bytecodes != null && bytecodes.length > 0) { final int firstLocalVariableSlot = ArgumentValueDescriptorImpl.getFirstLocalsSlot(method); - final long instructionIndex = location.codeIndex(); final TIntObjectHashMap usedVars = new TIntObjectHashMap(); - new InstructionParser(bytecodes, instructionIndex) { + new InstructionParser(bytecodes, location.codeIndex()) { @Override protected void localVariableInstructionFound(int opcode, int slot, String typeSignature) { if (slot >= firstLocalVariableSlot) { From b4774980e735f8a3fb91e346db2739090fdf7964 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Fri, 20 Mar 2015 19:44:47 +0400 Subject: [PATCH 17/67] cleanUp: remove code duplication --- .../com/intellij/dvcs/push/ui/PushLog.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java index d8b492b5630f..d5877d6ac55d 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java @@ -261,11 +261,7 @@ public class PushLog extends JPanel implements DataProvider { @Override public void linkSelected(LinkLabel aSource, String aLinkData) { if (linkLabel.isEnabled()) { - mySyncStrategy = true; - DefaultMutableTreeNode nodeToEdit = getFirstNodeToEdit(); - if (nodeToEdit != null) { - myTree.startEditingAtPath(TreeUtil.getPathFromRoot(nodeToEdit)); - } + startSyncEditing(); } } }, null); @@ -282,6 +278,13 @@ public class PushLog extends JPanel implements DataProvider { return labelPanel; } + private void startSyncEditing() { + mySyncStrategy = true; + DefaultMutableTreeNode nodeToEdit = getFirstNodeToEdit(); + if (nodeToEdit != null) { + myTree.startEditingAtPath(TreeUtil.getPathFromRoot(nodeToEdit)); + } + } @NotNull private static List collectAllChanges(@NotNull List commitNodes) { @@ -418,11 +421,7 @@ public class PushLog extends JPanel implements DataProvider { return true; } if (myAllowSyncStrategy && e.getKeyCode() == KeyEvent.VK_F2 && e.getModifiers() == InputEvent.ALT_MASK && pressed) { - mySyncStrategy = true; - DefaultMutableTreeNode node = getFirstNodeToEdit(); - if (node != null) { - myTree.startEditingAtPath(TreeUtil.getPathFromRoot(node)); - } + startSyncEditing(); return true; } return super.processKeyBinding(ks, e, condition, pressed); From 10eb161df8f4c79cf3cfbbcce27fe47b369175fd Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Fri, 20 Mar 2015 20:18:49 +0400 Subject: [PATCH 18/67] style: optimize return statement --- plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java index a8fc310347f9..d8838104e17c 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java @@ -47,11 +47,7 @@ public final class HgErrorUtil { } public static boolean isAbort(@Nullable HgCommandResult result) { - if (result == null) { - return true; - } - if (getAbortLine(result) != null) return true; - return false; + return result == null || getAbortLine(result) != null; } @Nullable From f4cf2a934c2ab5406ae9a23f22e64924b67bc460 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Fri, 20 Mar 2015 21:01:57 +0300 Subject: [PATCH 19/67] fix random incorrect foreground for selected cells --- .../com/intellij/ui/EditorTextFieldCellRenderer.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java b/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java index cd82980af2d8..4fdd374d4bca 100644 --- a/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java +++ b/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java @@ -101,10 +101,8 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer, editor.getColorsScheme().setEditorFontSize(table.getFont().getSize()); String text = getText(table, value, row, column); TextAttributes textAttributes = getTextAttributes(table, value, selected, focused, row, column); - panel.setText(text, textAttributes); + panel.setText(text, textAttributes, selected); - ((EditorImpl)editor).setPaintSelection(selected); - editor.getSelectionModel().setSelection(0, selected ? editor.getDocument().getTextLength() : 0); editor.getColorsScheme().setColor(EditorColors.SELECTION_BACKGROUND_COLOR, table.getSelectionBackground()); editor.getColorsScheme().setColor(EditorColors.SELECTION_FOREGROUND_COLOR, table.getSelectionForeground()); editor.setBackgroundColor(getCellBackground(table, value, selected, focused, row, column)); @@ -165,6 +163,7 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer, private Dimension myPreferredSize; private String myRawText; private TextAttributes myTextAttributes; + private boolean mySelected; public MyPanel(EditorEx editor) { add(editor.getContentComponent()); @@ -178,9 +177,10 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer, } } - public void setText(String text, @Nullable TextAttributes textAttributes) { + public void setText(String text, @Nullable TextAttributes textAttributes, boolean selected) { myRawText = text; myTextAttributes = textAttributes; + mySelected = selected; recalculatePreferredSize(); } @@ -277,8 +277,9 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer, ((EditorImpl)myEditor).resetSizes(); + ((EditorImpl)myEditor).setPaintSelection(mySelected); SelectionModel selectionModel = myEditor.getSelectionModel(); - selectionModel.setSelection(0, selectionModel.hasSelection() ? myEditor.getDocument().getTextLength() : 0); + selectionModel.setSelection(0, mySelected ? myEditor.getDocument().getTextLength() : 0); } private static void appendAbbreviated(StringBuilder to, String text, int start, int end, From 858119b77567f2d3edc300dd3ec9595cfa352ed9 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 20 Mar 2015 18:38:30 +0100 Subject: [PATCH 20/67] new overload resolution: remember candidate when argument type is to be calculated (IDEA-137921) --- .../psi/infos/MethodCandidateInfo.java | 65 ++++++++++++------- .../JavaMethodsConflictResolver.java | 24 ++----- .../MultipleOverloadsWithNestedGeneric.java | 9 +++ .../daemon/lambda/OverloadResolutionTest.java | 4 ++ 4 files changed, 60 insertions(+), 42 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/overloadResolution/MultipleOverloadsWithNestedGeneric.java diff --git a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java index 9b57ab5d4aa4..78a58fc8b70b 100644 --- a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java +++ b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java @@ -115,34 +115,23 @@ public class MethodCandidateInfo extends CandidateInfo{ if (myArgumentList == null || !PsiUtil.isLanguageLevel8OrHigher(myArgumentList)) { return getApplicabilityLevel(); } - @ApplicabilityLevelConstant int level; final PsiSubstitutor substitutor = getSubstitutor(false); - Map map = CURRENT_CANDIDATE.get(); - if (map == null) { - map = ContainerUtil.createConcurrentWeakMap(); - CURRENT_CANDIDATE.set(map); - } final PsiMethod method = getElement(); - final CurrentCandidateProperties properties = new CurrentCandidateProperties(method, substitutor, isVarargs(), true); - final CurrentCandidateProperties alreadyThere = map.put(getMarkerList(), properties); - try { - PsiType[] argumentTypes = getArgumentTypes(); - if (argumentTypes == null) { - return ApplicabilityLevel.NOT_APPLICABLE; - } + @ApplicabilityLevelConstant int level = computeForOverloadedCandidate(new Computable() { + @Override + public Integer compute() { + PsiType[] argumentTypes = getArgumentTypes(); + if (argumentTypes == null) { + return ApplicabilityLevel.NOT_APPLICABLE; + } - level = PsiUtil.getApplicabilityLevel(method, substitutor, argumentTypes, myLanguageLevel); - if (!isVarargs() && level < ApplicabilityLevel.FIXED_ARITY) { - return ApplicabilityLevel.NOT_APPLICABLE; + int level = PsiUtil.getApplicabilityLevel(method, substitutor, argumentTypes, myLanguageLevel); + if (!isVarargs() && level < ApplicabilityLevel.FIXED_ARITY) { + return ApplicabilityLevel.NOT_APPLICABLE; + } + return level; } - } - finally { - if (alreadyThere == null) { - map.remove(getMarkerList()); - } else { - map.put(getMarkerList(), alreadyThere); - } - } + }, substitutor); if (level > ApplicabilityLevel.NOT_APPLICABLE && !isTypeArgumentsApplicable(new Computable() { @Override public PsiSubstitutor compute() { @@ -154,6 +143,34 @@ public class MethodCandidateInfo extends CandidateInfo{ return level; } + public PsiType[] getPertinentArgumentTypes() { + return computeForOverloadedCandidate(new Computable() { + public PsiType[] compute() { + return getArgumentTypes(); + } + }, getSubstitutor(false)); + } + + private T computeForOverloadedCandidate(final Computable computable, final PsiSubstitutor substitutor) { + Map map = CURRENT_CANDIDATE.get(); + if (map == null) { + map = ContainerUtil.createConcurrentWeakMap(); + CURRENT_CANDIDATE.set(map); + } + final CurrentCandidateProperties alreadyThere = map.put(getMarkerList(), + new CurrentCandidateProperties(getElement(), substitutor, isVarargs(), true)); + try { + return computable.compute(); + } + finally { + if (alreadyThere == null) { + map.remove(getMarkerList()); + } else { + map.put(getMarkerList(), alreadyThere); + } + } + } + @NotNull public PsiSubstitutor getSiteSubstitutor() { PsiSubstitutor incompleteSubstitutor = super.getSubstitutor(); diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java index 4ffc804573ae..5755a53c69ef 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java @@ -422,16 +422,6 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ (method.getCurrentFileResolveScope() instanceof PsiImportStaticStatement ? 0 : 1); } - @NotNull - private PsiType[] getActualParameterTypes() { - PsiType[] types = myActualParameterTypes; - if (types == null) { - LOG.assertTrue(myArgumentsList instanceof PsiExpressionList, myArgumentsList); - myActualParameterTypes = types = getArgumentTypes(); - } - return types; - } - private int getActualParametersLength() { if (myActualParameterTypes == null) { LOG.assertTrue(myArgumentsList instanceof PsiExpressionList, myArgumentsList); @@ -440,11 +430,6 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ return myActualParameterTypes.length; } - @NotNull - protected PsiType[] getArgumentTypes() { - return ((PsiExpressionList)myArgumentsList).getExpressionTypes(); - } - private enum Specifics { FIRST, SECOND, @@ -509,20 +494,23 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ boolean sameBoxing = true; int[] boxingHappened = new int[2]; + final PsiType[] argTypes1 = myActualParameterTypes != null ? myActualParameterTypes : info1.getPertinentArgumentTypes(); + final PsiType[] argTypes2 = myActualParameterTypes != null ? myActualParameterTypes : info2.getPertinentArgumentTypes(); for (int i = 0; i < types1.length; i++) { ProgressManager.checkCanceled(); PsiType type1 = classSubstitutor1.substitute(types1[i]); PsiType type2 = classSubstitutor2.substitute(types2[i]); - PsiType argType = i < getActualParameterTypes().length ? getActualParameterTypes()[i] : null; + final PsiType argType1 = i < getActualParametersLength() ? argTypes1[i] : null; + final PsiType argType2 = i < getActualParametersLength() ? argTypes2[i] : null; boolean boxingInFirst = false; - if (isBoxingHappened(argType, type1, languageLevel)) { + if (isBoxingHappened(argType1, type1, languageLevel)) { boxingHappened[0] += 1; boxingInFirst = true; } boolean boxingInSecond = false; - if (isBoxingHappened(argType, type2, languageLevel)) { + if (isBoxingHappened(argType2, type2, languageLevel)) { boxingHappened[1] += 1; boxingInSecond = true; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/overloadResolution/MultipleOverloadsWithNestedGeneric.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/overloadResolution/MultipleOverloadsWithNestedGeneric.java new file mode 100644 index 000000000000..14316e0154a9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/overloadResolution/MultipleOverloadsWithNestedGeneric.java @@ -0,0 +1,9 @@ +import java.lang.String; + +abstract class Test { + abstract T get(); + + void foo() { + String.valueOf(get()); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/OverloadResolutionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/OverloadResolutionTest.java index 5ec359058511..d2ff3ce3ae6f 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/OverloadResolutionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/OverloadResolutionTest.java @@ -98,6 +98,10 @@ public class OverloadResolutionTest extends LightDaemonAnalyzerTestCase { }).assertTiming(); } + public void testMultipleOverloadsWithNestedGeneric() throws Exception { + doTest(false); + } + private void doTest() { doTest(true); } From 1f506406711581657a84d8edc6195721891b6f4d Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 20 Mar 2015 19:02:26 +0100 Subject: [PATCH 21/67] lambda isValueCompatible: ensure that normal completion is impossible for infinite loops (IDEA-137848) --- .../intellij/psi/controlFlow/ControlFlowUtil.java | 7 ++++++- .../InfiniteLoopAndValueCompatibility.java | 14 ++++++++++++++ .../daemon/lambda/NewLambdaHighlightingTest.java | 4 ++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/InfiniteLoopAndValueCompatibility.java diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java index 64169e127a6c..228e97f116aa 100644 --- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java @@ -735,7 +735,12 @@ public class ControlFlowUtil { if (lastInstruction instanceof GoToInstruction && ((GoToInstruction)lastInstruction).role == BranchingInstruction.Role.END && !((GoToInstruction)lastInstruction).isReturn) { - lastOffset--; + if (((GoToInstruction)lastInstruction).offset == startOffset) { + lastOffset = -1; + } + else { + lastOffset--; + } } if (lastOffset >= 0) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/InfiniteLoopAndValueCompatibility.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/InfiniteLoopAndValueCompatibility.java new file mode 100644 index 000000000000..d81a7a47e68f --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/InfiniteLoopAndValueCompatibility.java @@ -0,0 +1,14 @@ +import java.io.Reader; +import java.io.StringReader; +import java.util.concurrent.Callable; + +class Test { + public static final void main(String[] args) throws Exception { + Reader r = new StringReader("Elvis lives!"); + Callable c1 = () -> { + while (true) { + r.read(); + } + }; + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java index 696da0e64078..6a76895714b4 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java @@ -185,6 +185,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testInfiniteLoopAndValueCompatibility() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } From 9dc0d5048c91389ca4c8152dbba8078defcca74c Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 20 Mar 2015 22:39:29 +0300 Subject: [PATCH 22/67] do not use layered pane for expansion hints --- .../intellij/ui/AbstractExpandableItemsHandler.java | 13 +++++-------- .../src/com/intellij/ui/popup/MovablePopup.java | 12 ++++++++++++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java index c191bd2af3eb..b7b0638185bf 100644 --- a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java +++ b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java @@ -304,12 +304,9 @@ public abstract class AbstractExpandableItemsHandler= other.getX() && bounds.intersects(other.getBounds())) { return false; } } diff --git a/platform/platform-impl/src/com/intellij/ui/popup/MovablePopup.java b/platform/platform-impl/src/com/intellij/ui/popup/MovablePopup.java index 3bf745f229ca..cc731d6d61a7 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/MovablePopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/MovablePopup.java @@ -93,6 +93,10 @@ public class MovablePopup { } } + public void setBounds(@NotNull Rectangle bounds) { + setBounds(bounds.x, bounds.y, bounds.width, bounds.height); + } + public void setBounds(int x, int y, int width, int height) { if (myViewBounds != null) { myViewBounds.setBounds(x, y, width, height); @@ -102,6 +106,10 @@ public class MovablePopup { } } + public void setLocation(@NotNull Point location) { + setLocation(location.x, location.y); + } + public void setLocation(int x, int y) { if (myViewBounds != null) { myViewBounds.setLocation(x, y); @@ -111,6 +119,10 @@ public class MovablePopup { } } + public void setSize(@NotNull Dimension size) { + setSize(size.width, size.height); + } + public void setSize(int width, int height) { if (myViewBounds != null) { myViewBounds.setSize(width, height); From b79bf470cf12d378a8d34ef9586297dc6295833c Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Fri, 20 Mar 2015 22:36:04 +0300 Subject: [PATCH 23/67] IDEA-57472 Floating tool windows should be more like native windows, with maximize/minimize/close buttons --- .../intellij/openapi/wm/ToolWindowType.java | 2 +- .../com/intellij/openapi/wm/WindowInfo.java | 2 + .../intellij/designer/LightToolWindow.java | 7 +- .../ide/actions/HideAllToolWindowsAction.java | 6 +- .../ide/actions/ResizeToolWindowAction.java | 2 +- .../ide/actions/ToggleDockModeAction.java | 4 +- .../ide/actions/ToggleWindowedModeAction.java | 76 +++++++++++ .../openapi/wm/impl/FloatingDecorator.java | 3 +- .../openapi/wm/impl/InternalDecorator.java | 31 +++++ .../wm/impl/ToolWindowManagerImpl.java | 128 +++++++++++++++++- .../openapi/wm/impl/WindowInfoImpl.java | 10 +- .../openapi/wm/impl/WindowedDecorator.java | 39 ++++++ .../src/messages/ActionsBundle.properties | 2 + .../src/idea/PlatformActions.xml | 1 + .../enter/Performance.properties | 4 + xml/dom-tests/testData/performance.xml | 1 + 16 files changed, 308 insertions(+), 10 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/ide/actions/ToggleWindowedModeAction.java create mode 100644 platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowedDecorator.java diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowType.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowType.java index d33dc93e070d..aea21320f433 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowType.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowType.java @@ -16,5 +16,5 @@ package com.intellij.openapi.wm; public enum ToolWindowType { - DOCKED, FLOATING, SLIDING + DOCKED, FLOATING, SLIDING, WINDOWED } diff --git a/platform/platform-api/src/com/intellij/openapi/wm/WindowInfo.java b/platform/platform-api/src/com/intellij/openapi/wm/WindowInfo.java index 836c15ef66c3..370c789437d6 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/WindowInfo.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/WindowInfo.java @@ -38,6 +38,8 @@ public interface WindowInfo { boolean isFloating(); + boolean isWindowed(); + boolean isSliding(); ToolWindowContentUiType getContentUiType(); diff --git a/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java b/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java index ce3cb33deb90..c0953e4c06c0 100644 --- a/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java +++ b/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java @@ -16,6 +16,7 @@ package com.intellij.designer; import com.intellij.icons.AllIcons; +import com.intellij.ide.actions.ToggleWindowedModeAction; import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.impl.ActionManagerImpl; @@ -69,6 +70,7 @@ public class LightToolWindow extends JPanel { private final TogglePinnedModeAction myToggleAutoHideModeAction = new TogglePinnedModeAction(); private final ToggleDockModeAction myToggleDockModeAction = new ToggleDockModeAction(); private final ToggleFloatingModeAction myToggleFloatingModeAction = new ToggleFloatingModeAction(); + private final ToggleWindowedModeAction myToggleWindowedModeAction = new ToggleWindowedModeAction(); private final ToggleSideModeAction myToggleSideModeAction = new ToggleSideModeAction(); private final ComponentListener myWidthListener = new ComponentAdapter() { @@ -331,15 +333,18 @@ public class LightToolWindow extends JPanel { group.add(myToggleAutoHideModeAction); group.add(myToggleDockModeAction); group.add(myToggleFloatingModeAction); + group.add(myToggleWindowedModeAction); group.add(myToggleSideModeAction); } - else if (type == ToolWindowType.FLOATING) { + else if (type == ToolWindowType.FLOATING || type == ToolWindowType.WINDOWED) { group.add(myToggleAutoHideModeAction); group.add(myToggleFloatingModeAction); + group.add(myToggleWindowedModeAction); } else if (type == ToolWindowType.SLIDING) { group.add(myToggleDockModeAction); group.add(myToggleFloatingModeAction); + group.add(myToggleWindowedModeAction); } return group; diff --git a/platform/platform-impl/src/com/intellij/ide/actions/HideAllToolWindowsAction.java b/platform/platform-impl/src/com/intellij/ide/actions/HideAllToolWindowsAction.java index 99fb583fd864..8e4bd27579ed 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/HideAllToolWindowsAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/HideAllToolWindowsAction.java @@ -23,6 +23,7 @@ import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowType; import com.intellij.openapi.wm.ex.ToolWindowManagerEx; import com.intellij.openapi.wm.impl.DesktopLayout; @@ -51,7 +52,7 @@ public class HideAllToolWindowsAction extends AnAction implements DumbAware { boolean hasVisible = false; for (String id : ids) { ToolWindow toolWindow = toolWindowManager.getToolWindow(id); - if (toolWindow.isVisible()) { + if (toolWindow.isVisible() && toolWindow.getType() != ToolWindowType.WINDOWED) { toolWindow.hide(null); hasVisible = true; } @@ -81,7 +82,8 @@ public class HideAllToolWindowsAction extends AnAction implements DumbAware { ToolWindowManagerEx toolWindowManager = ToolWindowManagerEx.getInstanceEx(project); String[] ids = toolWindowManager.getToolWindowIds(); for (String id : ids) { - if (toolWindowManager.getToolWindow(id).isVisible()) { + ToolWindow toolWindow = toolWindowManager.getToolWindow(id); + if (toolWindow.isVisible() && toolWindow.getType() != ToolWindowType.WINDOWED) { presentation.setEnabled(true); presentation.setText(IdeBundle.message("action.hide.all.windows"), true); return; diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ResizeToolWindowAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ResizeToolWindowAction.java index 9f8d104ebdd2..f0b43e3737ae 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ResizeToolWindowAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ResizeToolWindowAction.java @@ -99,7 +99,7 @@ public abstract class ResizeToolWindowAction extends AnAction implements DumbAwa window = mgr.getToolWindow(mgr.getActiveToolWindowId()); } - if (window == null || !window.isAvailable() || !window.isVisible() || window.getType() == ToolWindowType.FLOATING || !window.isActive()) { + if (window == null || !window.isAvailable() || !window.isVisible() || window.getType() == ToolWindowType.FLOATING || window.getType() == ToolWindowType.WINDOWED || !window.isActive()) { setDisabled(e); return; } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ToggleDockModeAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ToggleDockModeAction.java index 9c41674642e9..75b646bd3e72 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ToggleDockModeAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ToggleDockModeAction.java @@ -74,6 +74,8 @@ public class ToggleDockModeAction extends ToggleAction implements DumbAware { return; } ToolWindow toolWindow=mgr.getToolWindow(id); - presentation.setEnabled(toolWindow.isAvailable()&&ToolWindowType.FLOATING!=toolWindow.getType()); + presentation.setEnabled(toolWindow.isAvailable() + && toolWindow.getType() != ToolWindowType.FLOATING + && toolWindow.getType() != ToolWindowType.WINDOWED); } } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ToggleWindowedModeAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ToggleWindowedModeAction.java new file mode 100644 index 000000000000..6d18de9024f4 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/actions/ToggleWindowedModeAction.java @@ -0,0 +1,76 @@ +/* + * Copyright 2000-2009 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.ide.actions; + +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.actionSystem.Presentation; +import com.intellij.openapi.actionSystem.ToggleAction; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.wm.ToolWindowManager; +import com.intellij.openapi.wm.ToolWindowType; +import com.intellij.openapi.wm.ex.ToolWindowEx; +import com.intellij.openapi.wm.ex.ToolWindowManagerEx; + +public class ToggleWindowedModeAction extends ToggleAction implements DumbAware { + + public boolean isSelected(AnActionEvent event) { + Project project = CommonDataKeys.PROJECT.getData(event.getDataContext()); + if (project == null) { + return false; + } + ToolWindowManager windowManager = ToolWindowManager.getInstance(project); + String id = windowManager.getActiveToolWindowId(); + if (id == null) { + return false; + } + return ToolWindowType.WINDOWED == windowManager.getToolWindow(id).getType(); + } + + public void setSelected(AnActionEvent event, boolean flag) { + Project project = CommonDataKeys.PROJECT.getData(event.getDataContext()); + if (project == null) { + return; + } + String id = ToolWindowManager.getInstance(project).getActiveToolWindowId(); + if (id == null) { + return; + } + ToolWindowManagerEx mgr = ToolWindowManagerEx.getInstanceEx(project); + ToolWindowEx toolWindow = (ToolWindowEx)mgr.getToolWindow(id); + ToolWindowType type = toolWindow.getType(); + if (ToolWindowType.WINDOWED == type) { + toolWindow.setType(toolWindow.getInternalType(), null); + } + else { + toolWindow.setType(ToolWindowType.WINDOWED, null); + } + } + + public void update(AnActionEvent event) { + super.update(event); + Presentation presentation = event.getPresentation(); + Project project = CommonDataKeys.PROJECT.getData(event.getDataContext()); + if (project == null) { + presentation.setEnabled(false); + return; + } + ToolWindowManager mgr = ToolWindowManager.getInstance(project); + String id = mgr.getActiveToolWindowId(); + presentation.setEnabled(id != null && mgr.getToolWindow(id).isAvailable()); + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java index 5a0a20351c29..4a05faa4a8f0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java @@ -43,6 +43,8 @@ import java.awt.event.WindowEvent; public final class FloatingDecorator extends JDialog { private static final Logger LOG=Logger.getInstance("#com.intellij.openapi.wm.impl.FloatingDecorator"); + static final int DIVIDER_WIDTH = 3; + private static final int ANCHOR_TOP=1; private static final int ANCHOR_LEFT=2; private static final int ANCHOR_BOTTOM=4; @@ -201,7 +203,6 @@ public final class FloatingDecorator extends JDialog { } private final class BorderItem extends JPanel{ - private static final int DIVIDER_WIDTH=3; private static final int RESIZER_WIDTH=10; private final int myAnchor; diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java index 876d4e8c5886..fd33c767533d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java @@ -65,6 +65,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr private final TogglePinnedModeAction myToggleAutoHideModeAction; private final ToggleDockModeAction myToggleDockModeAction; private final ToggleFloatingModeAction myToggleFloatingModeAction; + private final ToggleWindowedModeAction myToggleWindowedModeAction; private final ToggleSideModeAction myToggleSideModeAction; private final ToggleContentUiTypeAction myToggleContentUiTypeAction; @@ -76,6 +77,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr @NonNls public static final String TOGGLE_PINNED_MODE_ACTION_ID = "TogglePinnedMode"; @NonNls public static final String TOGGLE_DOCK_MODE_ACTION_ID = "ToggleDockMode"; @NonNls public static final String TOGGLE_FLOATING_MODE_ACTION_ID = "ToggleFloatingMode"; + @NonNls public static final String TOGGLE_WINDOWED_MODE_ACTION_ID = "ToggleWindowedMode"; @NonNls public static final String TOGGLE_SIDE_MODE_ACTION_ID = "ToggleSideMode"; @NonNls private static final String TOGGLE_CONTENT_UI_TYPE_ACTION_ID = "ToggleContentUiTypeMode"; @@ -90,6 +92,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr myDivider = new MyDivider(); myToggleFloatingModeAction = new ToggleFloatingModeAction(); + myToggleWindowedModeAction = new ToggleWindowedModeAction(); myToggleSideModeAction = new ToggleSideModeAction(); myToggleDockModeAction = new ToggleDockModeAction(); myToggleAutoHideModeAction = new TogglePinnedModeAction(); @@ -428,17 +431,24 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr group.add(myToggleAutoHideModeAction); group.add(myToggleDockModeAction); group.add(myToggleFloatingModeAction); + group.add(myToggleWindowedModeAction); group.add(myToggleSideModeAction); } else if (myInfo.isFloating()) { group.add(myToggleAutoHideModeAction); group.add(myToggleFloatingModeAction); + group.add(myToggleWindowedModeAction); + } + else if (myInfo.isWindowed()) { + group.add(myToggleFloatingModeAction); + group.add(myToggleWindowedModeAction); } else if (myInfo.isSliding()) { if (!ToolWindowId.PREVIEW.equals(myInfo.getId())) { group.add(myToggleDockModeAction); } group.add(myToggleFloatingModeAction); + group.add(myToggleWindowedModeAction); group.add(myToggleSideModeAction); } return group; @@ -567,6 +577,27 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr } } + private final class ToggleWindowedModeAction extends ToggleAction implements DumbAware { + public ToggleWindowedModeAction() { + copyFrom(ActionManager.getInstance().getAction(TOGGLE_WINDOWED_MODE_ACTION_ID)); + } + + @Override + public final boolean isSelected(final AnActionEvent event) { + return myInfo.isWindowed(); + } + + @Override + public final void setSelected(final AnActionEvent event, final boolean flag) { + if (myInfo.isWindowed()) { + fireTypeChanged(myInfo.getInternalType()); + } + else { + fireTypeChanged(ToolWindowType.WINDOWED); + } + } + } + private final class ToggleSideModeAction extends ToggleAction implements DumbAware { public ToggleSideModeAction() { copyFrom(ActionManager.getInstance().getAction(TOGGLE_SIDE_MODE_ACTION_ID)); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java index e7240a66a5b2..2d727abfdc3e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java @@ -77,6 +77,8 @@ import java.beans.PropertyChangeListener; import java.util.*; import java.util.List; +import static com.intellij.openapi.wm.impl.FloatingDecorator.DIVIDER_WIDTH; + /** * @author Anton Katilin * @author Vladimir Kondratyev @@ -90,6 +92,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private final DesktopLayout myLayout; private final Map myId2InternalDecorator; private final Map myId2FloatingDecorator; + private final Map myId2WindowedDecorator; private final Map myId2StripeButton; private final Map myId2FocusWatcher; private final Set myDumbAwareIds = Collections.synchronizedSet(ContainerUtil.newTroveSet()); @@ -186,6 +189,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements myId2InternalDecorator = new HashMap(); myId2FloatingDecorator = new HashMap(); + myId2WindowedDecorator = new HashMap(); myId2StripeButton = new HashMap(); myId2FocusWatcher = new HashMap(); @@ -702,7 +706,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } private boolean isToHide(final WindowInfoImpl info) { - return (info.isAutoHide() || info.isSliding()) && !(info.isFloating() && hasModalChild(info)); + return (info.isAutoHide() || info.isSliding()) && !(info.isFloating() && hasModalChild(info)) && !info.isWindowed(); } /** @@ -808,6 +812,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements if (info.isFloating()) { appendRemoveFloatingDecoratorCmd(info, commandsList); } + else if (info.isWindowed()) { + appendRemoveWindowedDecoratorCmd(info, commandsList); + } else { // docked and sliding windows appendRemoveDecoratorCmd(id, false, commandsList); } @@ -863,7 +870,12 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private FloatingDecorator getFloatingDecorator(final String id) { return myId2FloatingDecorator.get(id); } - + /** + * @return windowed decorator for the tool window with specified ID. + */ + private WindowedDecorator getWindowedDecorator(String id) { + return myId2WindowedDecorator.get(id); + } /** * @return internal decorator for the tool window with specified ID. */ @@ -1037,6 +1049,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements if (toBeShownInfo.isFloating()) { commandsList.add(new AddFloatingDecoratorCmd(decorator, toBeShownInfo)); } + else if (toBeShownInfo.isWindowed()) { + commandsList.add(new AddWindowedDecoratorCmd(decorator, toBeShownInfo)); + } else { // docked and sliding windows // If there is tool window on the same side then we have to hide it, i.e. @@ -1260,6 +1275,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements if (info.isFloating()) { appendRemoveFloatingDecoratorCmd(info, commandsList); } + else if (info.isWindowed()) { + appendRemoveWindowedDecoratorCmd(info, commandsList); + } else { // floating and sliding windows appendRemoveDecoratorCmd(id, false, commandsList); } @@ -1744,6 +1762,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements if (info.isFloating()) { appendRemoveFloatingDecoratorCmd(info, commandsList); } + else if (info.isWindowed()) { + appendRemoveWindowedDecoratorCmd(info, commandsList); + } else { // docked and sliding windows appendRemoveDecoratorCmd(id, dirtyMode, commandsList); } @@ -1790,6 +1811,11 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements commandsList.add(command); } + private void appendRemoveWindowedDecoratorCmd(final WindowInfoImpl info, final List commandsList) { + final RemoveWindowedDecoratorCmd command = new RemoveWindowedDecoratorCmd(info); + commandsList.add(command); + } + /** * @see com.intellij.openapi.wm.impl.ToolWindowsPane#createAddButtonCmd */ @@ -2108,6 +2134,104 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return ApplicationManager.getApplication().getDisposed(); } } + + /** + * This command creates and shows WindowedDecorator. + */ + private final class AddWindowedDecoratorCmd extends FinalizableCommand { + private final WindowedDecorator myWindowedDecorator; + + /** + * Creates floating decorator for specified floating decorator. + */ + private AddWindowedDecoratorCmd(final InternalDecorator decorator, final WindowInfoImpl info) { + super(myWindowManager.getCommandProcessor()); + myWindowedDecorator = new WindowedDecorator(myProject, info.copy(), decorator); + Window window = myWindowedDecorator.getFrame(); + final Rectangle bounds = info.getFloatingBounds(); + if (bounds != null) { + bounds.setBounds(bounds.x + DIVIDER_WIDTH, bounds.y + DIVIDER_WIDTH, bounds.width - 2 * DIVIDER_WIDTH, bounds.height - 2 * DIVIDER_WIDTH); + } + if (bounds != null && + bounds.width > 0 && + bounds.height > 0 && + myWindowManager.isInsideScreenBounds(bounds.x, bounds.y, bounds.width)) { + window.setBounds(bounds); + } + else { // place new frame at the center of main frame if there are no floating bounds + Dimension size = decorator.getSize(); + if (size.width == 0 || size.height == 0) { + size = decorator.getPreferredSize(); + } + window.setSize(size); + window.setLocationRelativeTo(myFrame); + } + myId2WindowedDecorator.put(info.getId(), myWindowedDecorator); + myWindowedDecorator.addDisposable(new Disposable() { + @Override + public void dispose() { + if (myId2WindowedDecorator.get(info.getId()) != null) { + hideToolWindow(info.getId(), false); + } + } + }); + } + + @Override + public void run() { + try { + myWindowedDecorator.show(false); + Window window = myWindowedDecorator.getFrame(); + JRootPane rootPane = ((RootPaneContainer)window).getRootPane(); + Rectangle rootPaneBounds = rootPane.getBounds(); + Point point = rootPane.getLocationOnScreen(); + Rectangle windowBounds = window.getBounds(); + //Point windowLocation = windowBounds.getLocation(); + //windowLocation.translate(windowLocation.x - point.x, windowLocation.y - point.y); + window.setLocation(2 * windowBounds.x - point.x, 2 * windowBounds.y - point.y); + window.setSize(2 * windowBounds.width - rootPaneBounds.width, 2 * windowBounds.height - rootPaneBounds.height); + } + finally { + finish(); + } + } + } + + /** + * This command hides and destroys floating decorator for tool window + * with specified ID. + */ + private final class RemoveWindowedDecoratorCmd extends FinalizableCommand { + private final WindowedDecorator myWindowedDecorator; + + private RemoveWindowedDecoratorCmd(final WindowInfoImpl info) { + super(myWindowManager.getCommandProcessor()); + myWindowedDecorator = getWindowedDecorator(info.getId()); + myId2WindowedDecorator.remove(info.getId()); + + JRootPane rootPane = ((RootPaneContainer)myWindowedDecorator.getFrame()).getRootPane(); + Rectangle bounds = rootPane.getBounds(); + Point location = rootPane.getLocationOnScreen(); + bounds.setBounds(location.x - DIVIDER_WIDTH, location.y - DIVIDER_WIDTH, bounds.width + 2 * DIVIDER_WIDTH, bounds.height + 2 * DIVIDER_WIDTH); + info.setFloatingBounds(bounds); + } + + @Override + public void run() { + try { + Disposer.dispose(myWindowedDecorator); + } + finally { + finish(); + } + } + + @Override + @Nullable + public Condition getExpireCondition() { + return ApplicationManager.getApplication().getDisposed(); + } + } private final class EditorComponentFocusWatcher extends FocusWatcher { @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java index 8fc9b55d609c..aa7c3657e18b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java @@ -157,7 +157,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo */ @Override public Rectangle getFloatingBounds(){ - return myFloatingBounds; + return new Rectangle(myFloatingBounds); } /** @@ -229,6 +229,11 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo return ToolWindowType.FLOATING==myType; } + @Override + public boolean isWindowed(){ + return ToolWindowType.WINDOWED==myType; + } + @Override public boolean isSliding(){ return ToolWindowType.SLIDING==myType; @@ -251,6 +256,9 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo if (ToolWindowType.DOCKED.toString().equalsIgnoreCase(text)) { return ToolWindowType.DOCKED; } + if (ToolWindowType.WINDOWED.toString().equalsIgnoreCase(text)) { + return ToolWindowType.WINDOWED; + } if (ToolWindowType.FLOATING.toString().equalsIgnoreCase(text)) { return ToolWindowType.FLOATING; } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowedDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowedDecorator.java new file mode 100644 index 000000000000..53e29a1a8749 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowedDecorator.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.openapi.wm.impl; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.FrameWrapper; +import org.jetbrains.annotations.NotNull; + +public final class WindowedDecorator extends FrameWrapper { + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.WindowedDecorator"); + + private final Project myProject; + + WindowedDecorator(@NotNull Project project, @NotNull WindowInfoImpl info, @NotNull InternalDecorator internalDecorator) { + super(project); + myProject = project; + setTitle(info.getId() + " - " + myProject.getName()); + setProject(project); + setComponent(internalDecorator); + } + + public Project getProject() { + return myProject; + } +} \ No newline at end of file diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 89f48f1340cc..430b5b608017 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -843,6 +843,8 @@ action.ToggleDockMode.text=Dock_ed Mode action.ToggleDockMode.description=Dock/undock active tool window action.ToggleFloatingMode.text=Floating _Mode action.ToggleFloatingMode.description=Float/unfloat active tool window +action.ToggleWindowedMode.text=_Windowed Mode +action.ToggleWindowedMode.description=Window/unwindow active tool window action.ToggleSideMode.text=Split Mode action.ToggleSideMode.description=Tool windows split mode on/off action.ToggleContentUiTypeMode.text=Show Views as Tabs diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index 05c267a7b065..d1f98e7d62ae 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -374,6 +374,7 @@ + diff --git a/plugins/properties/testData/propertiesFile/enter/Performance.properties b/plugins/properties/testData/propertiesFile/enter/Performance.properties index 7ea7f2a6db40..a0384241cf5c 100644 --- a/plugins/properties/testData/propertiesFile/enter/Performance.properties +++ b/plugins/properties/testData/propertiesFile/enter/Performance.properties @@ -5045,6 +5045,8 @@ action.ToggleDockMode.text=Dock_ed Mode action.ToggleDockMode.description=Dock/undock active tool window action.ToggleFloatingMode.text=Floating _Mode action.ToggleFloatingMode.description=Float/unfloat active tool window +action.ToggleWindowedMode.text=_Windowed Mode +action.ToggleWindowedMode.description=Window/unwindow active tool window action.ToggleSideMode.text=Split Mode action.ToggleSideMode.description=Tool windows split mode on/off action.ToggleContentUiTypeMode.text=Show Views as Tabs @@ -20533,6 +20535,8 @@ action.ToggleDockMode.text=Dock_ed Mode action.ToggleDockMode.description=Dock/undock active tool window action.ToggleFloatingMode.text=Floating _Mode action.ToggleFloatingMode.description=Float/unfloat active tool window +action.ToggleWindowedMode.text=_Windowed Mode +action.ToggleWindowedMode.description=Window/unwindow active tool window action.ToggleSideMode.text=Split Mode action.ToggleSideMode.description=Tool windows split mode on/off action.ToggleContentUiTypeMode.text=Show Views as Tabs diff --git a/xml/dom-tests/testData/performance.xml b/xml/dom-tests/testData/performance.xml index 49f57b15fcd9..f962b120e584 100644 --- a/xml/dom-tests/testData/performance.xml +++ b/xml/dom-tests/testData/performance.xml @@ -591,6 +591,7 @@ + From 0504e11398b51394ef946ba723488334381c928c Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 20 Mar 2015 20:55:51 +0100 Subject: [PATCH 24/67] method refs and invokeDynamic bytecode parsing to register corresponding dependencies correctly (IDEA-137568) --- .../changeLambdaSAMMethodSignature.log | 16 +++ .../src/ppp/Client.java | 8 ++ .../src/ppp/Client.java.new | 8 ++ .../src/ppp/DataProvider.java | 7 + .../src/ppp/DataProvider.java.new | 7 + .../src/ppp/Main.java | 9 ++ .../src/ppp/Repository.java | 10 ++ .../src/ppp/Repository.java.new | 10 ++ .../changeLambdaTargetReturnType.log | 12 ++ .../src/ppp/Client.java | 8 ++ .../src/ppp/DataProvider.java | 7 + .../src/ppp/Main.java | 9 ++ .../src/ppp/Repository.java | 10 ++ .../src/ppp/Repository.java.new | 10 ++ .../changeMethodRefReturnType.log | 12 ++ .../src/ppp/Client.java | 8 ++ .../src/ppp/DataProvider.java | 7 + .../src/ppp/Main.java | 9 ++ .../src/ppp/Repository.java | 10 ++ .../src/ppp/Repository.java.new | 10 ++ .../changeSAMMethodSignature.log | 16 +++ .../src/ppp/Client.java | 8 ++ .../src/ppp/Client.java.new | 8 ++ .../src/ppp/DataProvider.java | 7 + .../src/ppp/DataProvider.java.new | 7 + .../src/ppp/Main.java | 9 ++ .../src/ppp/Repository.java | 10 ++ .../src/ppp/Repository.java.new | 10 ++ .../dependencyView/ClassfileAnalyzer.java | 135 +++++++++++++++--- .../jetbrains/ether/IncrementalTestCase.java | 18 ++- .../jetbrains/ether/MethodPropertyTest.java | 36 +++++ 31 files changed, 428 insertions(+), 23 deletions(-) create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature.log create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java.new create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java.new create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Main.java create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java.new create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType.log create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Client.java create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/DataProvider.java create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Main.java create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java.new create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType.log create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Client.java create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/DataProvider.java create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Main.java create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java.new create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature.log create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java.new create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java.new create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Main.java create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java create mode 100644 java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java.new diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature.log b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature.log new file mode 100644 index 000000000000..98d7347e73f2 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature.log @@ -0,0 +1,16 @@ +Cleaning output files: +out/production/ChangeLambdaSAMMethodSignature/ppp/Client.class +out/production/ChangeLambdaSAMMethodSignature/ppp/DataProvider.class +out/production/ChangeLambdaSAMMethodSignature/ppp/Repository.class +End of files +Compiling files: +src/ppp/Client.java +src/ppp/DataProvider.java +src/ppp/Repository.java +End of files +Cleaning output files: +out/production/ChangeLambdaSAMMethodSignature/ppp/Main.class +End of files +Compiling files: +src/ppp/Main.java +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java new file mode 100644 index 000000000000..463efb86e87a --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData()) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java.new new file mode 100644 index 000000000000..bcef65b859f9 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java.new @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData(10)) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java new file mode 100644 index 000000000000..867c0ec1b227 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java.new new file mode 100644 index 000000000000..48cad7204add --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java.new @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(int param); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Main.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Main.java new file mode 100644 index 000000000000..83badb8b4311 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Main.java @@ -0,0 +1,9 @@ +package ppp; + +public class Main { + public static void main(String[] args) { + Repository repo = new Repository(); + Client client = new Client(); + client.execute(()-> repo.getStorages()); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java new file mode 100644 index 000000000000..ff7c586d6b38 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java.new new file mode 100644 index 000000000000..29625a07d866 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java.new @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages(int param) { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType.log b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType.log new file mode 100644 index 000000000000..74c5f74e7cc3 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType.log @@ -0,0 +1,12 @@ +Cleaning output files: +out/production/ChangeLambdaTargetReturnType/ppp/Repository.class +End of files +Compiling files: +src/ppp/Repository.java +End of files +Cleaning output files: +out/production/ChangeLambdaTargetReturnType/ppp/Main.class +End of files +Compiling files: +src/ppp/Main.java +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Client.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Client.java new file mode 100644 index 000000000000..463efb86e87a --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Client.java @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData()) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/DataProvider.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/DataProvider.java new file mode 100644 index 000000000000..867c0ec1b227 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/DataProvider.java @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Main.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Main.java new file mode 100644 index 000000000000..83badb8b4311 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Main.java @@ -0,0 +1,9 @@ +package ppp; + +public class Main { + public static void main(String[] args) { + Repository repo = new Repository(); + Client client = new Client(); + client.execute(()-> repo.getStorages()); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java new file mode 100644 index 000000000000..ff7c586d6b38 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java.new new file mode 100644 index 000000000000..f70ad61f7ea8 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java.new @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.Collection; + +public class Repository { + public Collection getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType.log b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType.log new file mode 100644 index 000000000000..19e7ce03cf1f --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType.log @@ -0,0 +1,12 @@ +Cleaning output files: +out/production/ChangeMethodRefReturnType/ppp/Repository.class +End of files +Compiling files: +src/ppp/Repository.java +End of files +Cleaning output files: +out/production/ChangeMethodRefReturnType/ppp/Main.class +End of files +Compiling files: +src/ppp/Main.java +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Client.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Client.java new file mode 100644 index 000000000000..463efb86e87a --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Client.java @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData()) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/DataProvider.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/DataProvider.java new file mode 100644 index 000000000000..867c0ec1b227 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/DataProvider.java @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Main.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Main.java new file mode 100644 index 000000000000..3f1e0382a832 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Main.java @@ -0,0 +1,9 @@ +package ppp; + +public class Main { + public static void main(String[] args) { + Repository repo = new Repository(); + Client client = new Client(); + client.execute(repo::getStorages); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java new file mode 100644 index 000000000000..ff7c586d6b38 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java.new new file mode 100644 index 000000000000..f70ad61f7ea8 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java.new @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.Collection; + +public class Repository { + public Collection getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature.log b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature.log new file mode 100644 index 000000000000..4b61261611d1 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature.log @@ -0,0 +1,16 @@ +Cleaning output files: +out/production/ChangeSAMMethodSignature/ppp/Client.class +out/production/ChangeSAMMethodSignature/ppp/DataProvider.class +out/production/ChangeSAMMethodSignature/ppp/Repository.class +End of files +Compiling files: +src/ppp/Client.java +src/ppp/DataProvider.java +src/ppp/Repository.java +End of files +Cleaning output files: +out/production/ChangeSAMMethodSignature/ppp/Main.class +End of files +Compiling files: +src/ppp/Main.java +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java new file mode 100644 index 000000000000..463efb86e87a --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData()) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java.new new file mode 100644 index 000000000000..bcef65b859f9 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java.new @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData(10)) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java new file mode 100644 index 000000000000..867c0ec1b227 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java.new new file mode 100644 index 000000000000..48cad7204add --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java.new @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(int param); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Main.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Main.java new file mode 100644 index 000000000000..3f1e0382a832 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Main.java @@ -0,0 +1,9 @@ +package ppp; + +public class Main { + public static void main(String[] args) { + Repository repo = new Repository(); + Client client = new Client(); + client.execute(repo::getStorages); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java new file mode 100644 index 000000000000..ff7c586d6b38 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java.new new file mode 100644 index 000000000000..29625a07d866 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java.new @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages(int param) { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java index 137f4527b5a8..a67fa2563769 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java @@ -19,6 +19,7 @@ import com.intellij.openapi.util.Pair; import gnu.trove.THashMap; import gnu.trove.THashSet; import gnu.trove.TIntHashSet; +import org.jetbrains.annotations.Nullable; import org.jetbrains.org.objectweb.asm.*; import org.jetbrains.org.objectweb.asm.signature.SignatureReader; import org.jetbrains.org.objectweb.asm.signature.SignatureVisitor; @@ -34,6 +35,7 @@ import java.util.Set; */ class ClassfileAnalyzer { + public static final String LAMBDA_FACTORY_CLASS = "java/lang/invoke/LambdaMetafactory"; private final DependencyContext myContext; ClassfileAnalyzer(DependencyContext context) { @@ -390,11 +392,11 @@ class ClassfileAnalyzer { } @Override - public FieldVisitor visitField(int access, String n, String desc, String signature, Object value) { + public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { processSignature(signature); if ((access & Opcodes.ACC_SYNTHETIC) == 0) { - myFields.add(new FieldRepr(myContext, access, myContext.get(n), myContext.get(desc), myContext.get(signature), value)); + myFields.add(new FieldRepr(myContext, access, myContext.get(name), myContext.get(desc), myContext.get(signature), value)); } return new FieldVisitor(Opcodes.ASM5) { @@ -504,34 +506,118 @@ class ClassfileAnalyzer { @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { - final int fieldName = myContext.get(name); - final int fieldOwner = myContext.get(owner); - final int descr = myContext.get(desc); - - if (opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC) { - myUsages.add(UsageRepr.createFieldAssignUsage(myContext, fieldName, fieldOwner, descr)); - } - - if (opcode == Opcodes.GETFIELD || opcode == Opcodes.GETSTATIC) { - addClassUsage(TypeRepr.getType(myContext, descr)); - } - - myUsages.add(UsageRepr.createFieldUsage(myContext, fieldName, fieldOwner, descr)); + registerFieldUsage(opcode, owner, name, desc); super.visitFieldInsn(opcode, owner, name, desc); } @Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { - final int methodName = myContext.get(name); - final int methodOwner = myContext.get(owner); - - myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, methodOwner, desc)); - myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, methodOwner)); - addClassUsage(TypeRepr.getType(myContext, Type.getReturnType(desc))); - + registerMethodUsage(owner, name, desc); super.visitMethodInsn(opcode, owner, name, desc, itf); } + @Override + public void visitInvokeDynamicInsn(String methodName, String desc, Handle bsm, Object... bsmArgs) { + final Type returnType = Type.getReturnType(desc); + addClassUsage(TypeRepr.getType(myContext, returnType)); + + // common args processing + for (Object arg : bsmArgs) { + if (arg instanceof Type) { + final Type type = (Type)arg; + if (type.getSort() == Type.METHOD) { + for (Type argType : type.getArgumentTypes()) { + addClassUsage(TypeRepr.getType(myContext, argType)); + } + addClassUsage(TypeRepr.getType(myContext, type.getReturnType())); + } + else { + addClassUsage(TypeRepr.getType(myContext, type)); + } + } + else if (arg instanceof Handle) { + processMethodHandle((Handle)arg); + } + } + + if (LAMBDA_FACTORY_CLASS.equals(bsm.getOwner())) { + // This invokeDynamic implements a lambda or method reference usage. + // Need to register method usage for the corresponding SAM-type. + // First three arguments to the bootstrap methods are provided automatically by VM. + // Arguments in args array are expected to be as following: + // [0]: Type: Signature and return type of method to be implemented by the function object. + // [1]: Handle: implementation method handle + // [2]: Type: The signature and return type that should be enforced dynamically at invocation time. May be the same as samMethodType, or may be a specialization of it + // [...]: optional additional arguments + + if (returnType.getSort() == Type.OBJECT && bsmArgs.length >= 3) { + if (bsmArgs[0] instanceof Type) { + final Type samMethodType = (Type)bsmArgs[0]; + if (samMethodType.getSort() == Type.METHOD) { + registerMethodUsage(returnType.getInternalName(), methodName, samMethodType.getDescriptor()); + } + } + } + } + + super.visitInvokeDynamicInsn(methodName, desc, bsm, bsmArgs); + } + + private void processMethodHandle(Handle handle) { + final String memberOwner = handle.getOwner(); + if (myContext.get(memberOwner) != myName) { + // do not register access to own class members + final String memberName = handle.getName(); + final String memberDescriptor = handle.getDesc(); + if (isFieldAccessHandle(handle)) { + final int tag = handle.getTag(); + int opCode; + if (tag == Opcodes.H_GETFIELD) { + opCode = Opcodes.GETFIELD; + } + else if (tag == Opcodes.H_GETSTATIC) { + opCode = Opcodes.GETSTATIC; + } + else if (tag == Opcodes.H_PUTFIELD) { + opCode = Opcodes.PUTFIELD; + } + else if (tag == Opcodes.H_PUTSTATIC) { + opCode = Opcodes.PUTSTATIC; + } + else { + opCode = Opcodes.H_GETFIELD; + } + registerFieldUsage(opCode, memberOwner, memberName, memberDescriptor); + } + else { + registerMethodUsage(memberOwner, memberName, memberDescriptor); + } + } + } + + private void registerFieldUsage(int opcode, String owner, String fName, String desc) { + final int fieldName = myContext.get(fName); + final int fieldOwner = myContext.get(owner); + final int descr = myContext.get(desc); + if (opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC) { + myUsages.add(UsageRepr.createFieldAssignUsage(myContext, fieldName, fieldOwner, descr)); + } + if (opcode == Opcodes.GETFIELD || opcode == Opcodes.GETSTATIC) { + addClassUsage(TypeRepr.getType(myContext, descr)); + } + myUsages.add(UsageRepr.createFieldUsage(myContext, fieldName, fieldOwner, descr)); + } + + private void registerMethodUsage(String owner, String name, @Nullable String desc) { + final int methodOwner = myContext.get(owner); + final int methodName = myContext.get(name); + myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, methodOwner)); + if (desc != null) { + myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, methodOwner, desc)); + addClassUsage(TypeRepr.getType(myContext, Type.getReturnType(desc))); + } + } + private void addClassUsage(final TypeRepr.AbstractType type) { TypeRepr.ClassType classType = null; if (type instanceof TypeRepr.ClassType) { @@ -551,6 +637,11 @@ class ClassfileAnalyzer { }; } + private boolean isFieldAccessHandle(Handle handle) { + final int tag = handle.getTag(); + return tag == Opcodes.H_GETFIELD || tag == Opcodes.H_GETSTATIC || tag == Opcodes.H_PUTFIELD || tag == Opcodes.H_PUTSTATIC; + } + @Override public void visitInnerClass(String name, String outerName, String innerName, int access) { if (outerName != null) { diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java index 4525aa74bd4d..f8b4e51ccd52 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java @@ -37,7 +37,9 @@ import org.jetbrains.jps.model.module.JpsModule; import org.jetbrains.jps.model.serialization.PathMacroUtil; import org.jetbrains.jps.util.JpsPathUtil; -import java.io.*; +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; /** * @author db @@ -212,6 +214,20 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { module.addSourceRoot(getUrl(testRootRelativePath), JavaSourceRootType.TEST_SOURCE); } + protected static boolean isRunningOnAtLeastJava(int javaVersion) { + final String versionString = System.getProperty("java.version"); + final String prefix = "1."; + final int startIndex = versionString.startsWith(prefix) ? prefix.length() : 0; + final int dotIndex = versionString.indexOf('.', startIndex); + try { + int version = Integer.parseInt(versionString.substring(startIndex, dotIndex > startIndex? dotIndex : versionString.length())); + return version >= javaVersion; + } + catch (NumberFormatException ignored) { + } + return false; + } + private static class StringProjectBuilderLogger extends ProjectBuilderLoggerBase { private final String myRoot; private StringBuilder myLog; diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/MethodPropertyTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/MethodPropertyTest.java index 28093d91f8b8..839effbe7ac8 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/MethodPropertyTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/MethodPropertyTest.java @@ -32,6 +32,42 @@ public class MethodPropertyTest extends IncrementalTestCase { doTest(); } + public void testChangeMethodRefReturnType() throws Exception { + if (isRunningOnAtLeastJava(8)) { + doTest(); + } + else { + System.err.println("Skipping test " + getTestName(true) + ": java version 8 or higher required to run it"); + } + } + + public void testChangeLambdaTargetReturnType() throws Exception { + if (isRunningOnAtLeastJava(8)) { + doTest(); + } + else { + System.err.println("Skipping test " + getTestName(true) + ": java version 8 or higher required to run it"); + } + } + + public void testChangeSAMMethodSignature() throws Exception { + if (isRunningOnAtLeastJava(8)) { + doTest(); + } + else { + System.err.println("Skipping test " + getTestName(true) + ": java version 8 or higher required to run it"); + } + } + + public void testChangeLambdaSAMMethodSignature() throws Exception { + if (isRunningOnAtLeastJava(8)) { + doTest(); + } + else { + System.err.println("Skipping test " + getTestName(true) + ": java version 8 or higher required to run it"); + } + } + public void testChangeReturnType1() throws Exception { doTest(); } From 4597494195c07134517e646496536293dd3086fa Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 20 Mar 2015 21:02:29 +0100 Subject: [PATCH 25/67] import of inner classes through should get raw substitutor from outr class if applicable (IDEA-121166) --- .../psi/impl/source/PsiJavaFileBaseImpl.java | 31 +++++++++++++++++-- .../advHighlighting7/raw/p/Class1.java | 9 ++++++ .../advHighlighting7/raw/p/Class2.java | 10 ++++++ .../advHighlighting7/raw/p2/GenericClass.java | 6 ++++ .../rawOnDemand/p/Class1.java | 9 ++++++ .../rawOnDemand/p/Class2.java | 10 ++++++ .../rawOnDemand/p2/GenericClass.java | 6 ++++ .../daemon/AdvHighlightingJdk7Test.java | 8 +++++ 8 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p/Class1.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p/Class2.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p2/GenericClass.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p/Class1.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p/Class2.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p2/GenericClass.java diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java index a825e7cd7281..d0a665a9e2e4 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java @@ -50,6 +50,7 @@ import com.intellij.util.containers.MostlySingularMultiMap; import com.intellij.util.indexing.IndexingDataKeys; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; @@ -314,7 +315,12 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava final PsiElement resolved = statement.resolve(); if (resolved instanceof PsiClass) { processor.handleEvent(JavaScopeProcessorEvent.SET_CURRENT_FILE_CONTEXT, statement); - if (!processor.execute(resolved, state)) return false; + final PsiClass containingClass = ((PsiClass)resolved).getContainingClass(); + if (containingClass != null && containingClass.hasTypeParameters()) { + if (!processor.execute(resolved, state.put(PsiSubstitutor.KEY, + createRawSubstitutor(containingClass)))) return false; + } + else if (!processor.execute(resolved, state)) return false; } } } @@ -385,6 +391,11 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava return true; } + @NotNull + private static PsiSubstitutor createRawSubstitutor(PsiClass containingClass) { + return JavaPsiFacade.getElementFactory(containingClass.getProject()).createRawSubstitutor(containingClass); + } + private static boolean processOnDemandTarget(PsiElement target, PsiScopeProcessor processor, ResolveState substitutor, PsiElement place) { if (target instanceof PsiPackage) { if (!target.processDeclarations(processor, substitutor, null, place)) { @@ -393,6 +404,10 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava } else if (target instanceof PsiClass) { PsiClass[] inners = ((PsiClass)target).getInnerClasses(); + if (((PsiClass)target).hasTypeParameters()) { + substitutor = substitutor.put(PsiSubstitutor.KEY, createRawSubstitutor((PsiClass)target)); + } + for (PsiClass inner : inners) { if (!processor.execute(inner, substitutor)) return false; } @@ -494,8 +509,18 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava @Override public boolean process(SymbolCollectingProcessor.ResultWithContext result) { - myProcessor.handleEvent(JavaScopeProcessorEvent.SET_CURRENT_FILE_CONTEXT, result.getFileContext()); - return myProcessor.execute(result.getElement(), myState); + final PsiElement context = result.getFileContext(); + myProcessor.handleEvent(JavaScopeProcessorEvent.SET_CURRENT_FILE_CONTEXT, context); + final PsiNamedElement element = result.getElement(); + + if (element instanceof PsiClass && context instanceof PsiImportStatement) { + final PsiClass containingClass = ((PsiClass)element).getContainingClass(); + if (containingClass != null && containingClass.hasTypeParameters()) { + return myProcessor.execute(element, myState.put(PsiSubstitutor.KEY, createRawSubstitutor(containingClass))); + } + } + + return myProcessor.execute(element, myState); } } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p/Class1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p/Class1.java new file mode 100644 index 000000000000..71f2a5e58a71 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p/Class1.java @@ -0,0 +1,9 @@ +package p; + +import p2.GenericClass; + +public class Class1 extends GenericClass { + public void map(InnerClass context) { + Class2.test(context); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p/Class2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p/Class2.java new file mode 100644 index 000000000000..10506b456976 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p/Class2.java @@ -0,0 +1,10 @@ +package p; + +import p2.GenericClass.InnerClass; + +public class Class2 { + + public static boolean test(InnerClass context) { + return true; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p2/GenericClass.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p2/GenericClass.java new file mode 100644 index 000000000000..21c284bbd1b0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p2/GenericClass.java @@ -0,0 +1,6 @@ +package p2; + +public class GenericClass { + public class InnerClass { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p/Class1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p/Class1.java new file mode 100644 index 000000000000..71f2a5e58a71 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p/Class1.java @@ -0,0 +1,9 @@ +package p; + +import p2.GenericClass; + +public class Class1 extends GenericClass { + public void map(InnerClass context) { + Class2.test(context); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p/Class2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p/Class2.java new file mode 100644 index 000000000000..55941a9b084f --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p/Class2.java @@ -0,0 +1,10 @@ +package p; + +import p2.GenericClass.*; + +public class Class2 { + + public static boolean test(InnerClass context) { + return true; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p2/GenericClass.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p2/GenericClass.java new file mode 100644 index 000000000000..21c284bbd1b0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p2/GenericClass.java @@ -0,0 +1,6 @@ +package p2; + +public class GenericClass { + public class InnerClass { + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingJdk7Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingJdk7Test.java index dcac1068a631..19e3b245fa89 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingJdk7Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingJdk7Test.java @@ -63,6 +63,14 @@ public class AdvHighlightingJdk7Test extends DaemonAnalyzerTestCase { doTest(BASE_PATH + "staticImportConflict/UsageMixed.java", BASE_PATH + "/staticImportConflict", false, false); } + public void testRawInnerClassImport() throws Exception { + doTest(BASE_PATH + "raw/p/Class1.java", BASE_PATH + "/raw", false, false); + } + + public void testRawInnerClassImportOnDemand() throws Exception { + doTest(BASE_PATH + "rawOnDemand/p/Class1.java", BASE_PATH + "/rawOnDemand", false, false); + } + //ambiguous method calls private void doTestAmbiguous() throws Exception { doTestAmbiguous(JavaSdkVersion.JDK_1_7); From 33df60b18a9f1c0cfbac03ab806c324c14aff339 Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Sat, 21 Mar 2015 00:18:39 +0300 Subject: [PATCH 26/67] 1px editor splitters --- .../openapi/fileEditor/impl/EditorWindow.java | 118 +----------------- .../fileEditor/impl/EditorsSplitters.java | 5 +- 2 files changed, 6 insertions(+), 117 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java index 36dcd15efdc0..5b0beefd98d5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,6 +44,7 @@ import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.ui.JBColor; import com.intellij.ui.LayeredIcon; +import com.intellij.ui.OnePixelSplitter; import com.intellij.util.IconUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Stack; @@ -54,7 +55,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.border.Border; import java.awt.*; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; @@ -114,7 +114,6 @@ public class EditorWindow { protected EditorWindow(final EditorsSplitters owner) { myOwner = owner; myPanel = new JPanel(new BorderLayout()); - myPanel.setBorder(new AdaptiveBorder()); myPanel.setOpaque(false); myTabbedPane = null; @@ -156,115 +155,6 @@ public class EditorWindow { } } - private static class AdaptiveBorder implements Border { - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - Insets insets = ((JComponent)c).getInsets(); - g.setColor(UIUtil.getPanelBackground()); - paintBorder(g, x, y, width, height, insets); - g.setColor(new Color(0, 0, 0, 90)); - paintBorder(g, x, y, width, height, insets); - } - - private static void paintBorder(Graphics g, int x, int y, int width, int height, Insets insets) { - if (insets.left == 1) { - g.drawLine(x, y, x, y + height); - } - - if (insets.right == 1) { - g.drawLine(x + width - 1, y, x + width - 1, y + height); - } - - if (insets.bottom == 1) { - g.drawLine(x, y + height - 1, x + width, y + height - 1); - } - } - - @Override - public Insets getBorderInsets(Component c) { - Container parent = c.getParent(); - if (parent instanceof Splitter) { - boolean editorToTheLeft = false; - boolean editorToTheRight = false; - boolean editorToTheDown = false; - - Splitter splitter = (Splitter)parent; - - boolean vertical = splitter.getOrientation(); - if (vertical && splitter.getFirstComponent() == c) { - editorToTheDown = true; - } else if (!vertical) { - if (splitter.getFirstComponent() == c) { - editorToTheRight = true; - } - if (splitter.getSecondComponent() == c) editorToTheLeft = true; - } - - - //Frame frame = (Frame) SwingUtilities.getAncestorOfClass(Frame.class, c); - //if (frame instanceof IdeFrame) { - // Project project = ((IdeFrame)frame).getProject(); - // ToolWindowManagerEx toolWindowManager = ToolWindowManagerEx.getInstanceEx(project); - // if (!editorToTheLeft) { - // List left = toolWindowManager.getIdsOn(ToolWindowAnchor.LEFT); - // if (left.size() > 0) { - // for (String lid : left) { - // ToolWindow window = toolWindowManager.getToolWindow(lid); - // editorToTheLeft = window != null && window.isVisible() && window.getType() == ToolWindowType.DOCKED; - // if (editorToTheLeft) break; - // } - // } - // } - // - // if (!editorToTheRight) { - // List right = toolWindowManager.getIdsOn(ToolWindowAnchor.RIGHT); - // if (right.size() > 0) { - // for (String lid : right) { - // ToolWindow window = toolWindowManager.getToolWindow(lid); - // editorToTheRight = window != null && window.isVisible() && window.getType() == ToolWindowType.DOCKED; - // if (editorToTheRight) break; - // } - // } - // } - //} - - Splitter outer = nextOuterSplitter(splitter); - if (outer != null) { - boolean outerVertical = outer.getOrientation(); - if (!outerVertical) { - if (splitter.getParent() == outer.getFirstComponent()) editorToTheRight = true; - if (splitter.getParent() == outer.getSecondComponent()) editorToTheLeft = true; - } else { - if (splitter.getParent() == outer.getFirstComponent()) { - editorToTheDown = true; - } - } - } - - int left = editorToTheLeft ? 1 : 0; - int right = editorToTheRight ? 1 : 0; - int bottom = editorToTheDown ? 1 : 0; - return new Insets(0, left, bottom, right); - } - - return new Insets(0, 0, 0, 0); - } - - @Nullable - private static Splitter nextOuterSplitter(Component c) { - Container parent = c.getParent(); - if (parent == null) return null; - Container grandParent = parent.getParent(); - if (grandParent instanceof Splitter) return (Splitter)grandParent; - return null; - } - - @Override - public boolean isBorderOpaque() { - return true; - } - } - void dispose() { try { disposeTabs(); @@ -798,10 +688,8 @@ public class EditorWindow { final EditorWithProviderComposite firstEC = getEditorAt(0); myPanel = new JPanel(new BorderLayout()); myPanel.setOpaque(false); - myPanel.setBorder(new AdaptiveBorder()); - myPanel.setOpaque(false); - final Splitter splitter = new Splitter(orientation == JSplitPane.VERTICAL_SPLIT, 0.5f, 0.1f, 0.9f); + final Splitter splitter = new OnePixelSplitter(orientation == JSplitPane.VERTICAL_SPLIT, 0.5f, 0.1f, 0.9f); final EditorWindow res = new EditorWindow(myOwner); if (myTabbedPane != null) { final EditorWithProviderComposite selectedEditor = getSelectedEditor(); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java index 78068f695d5b..95653ec576ce 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,6 +43,7 @@ import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.openapi.wm.impl.FrameTitleBuilder; import com.intellij.openapi.wm.impl.IdePanePanel; import com.intellij.ui.JBColor; +import com.intellij.ui.OnePixelSplitter; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.docking.DockManager; import com.intellij.ui.tabs.JBTabs; @@ -893,7 +894,7 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener public void run() { JPanel panel = new JPanel(new BorderLayout()); panel.setOpaque(false); - Splitter splitter = new Splitter(orientation, proportion, 0.1f, 0.9f); + Splitter splitter = new OnePixelSplitter(orientation, proportion, 0.1f, 0.9f); panel.add(splitter, BorderLayout.CENTER); splitter.setFirstComponent(firstComponent); splitter.setSecondComponent(secondComponent); From 45363cd41bb02b87398cd4ec13836726418cbe5b Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Sat, 21 Mar 2015 13:52:38 +0300 Subject: [PATCH 27/67] IDEA-57472 Floating tool windows should be more like native windows, with maximize/minimize/close buttons (disable under Mac OS X) --- .../intellij/ide/actions/ToggleWindowedModeAction.java | 5 +++++ .../com/intellij/openapi/wm/impl/InternalDecorator.java | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ToggleWindowedModeAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ToggleWindowedModeAction.java index 6d18de9024f4..b346f88c99a0 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ToggleWindowedModeAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ToggleWindowedModeAction.java @@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.actionSystem.ToggleAction; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.openapi.wm.ToolWindowType; import com.intellij.openapi.wm.ex.ToolWindowEx; @@ -64,6 +65,10 @@ public class ToggleWindowedModeAction extends ToggleAction implements DumbAware public void update(AnActionEvent event) { super.update(event); Presentation presentation = event.getPresentation(); + if (SystemInfo.isMac) { + presentation.setEnabledAndVisible(false); + return; + } Project project = CommonDataKeys.PROJECT.getData(event.getDataContext()); if (project == null) { presentation.setEnabled(false); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java index fd33c767533d..037bb45a7e6d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java @@ -596,6 +596,14 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr fireTypeChanged(ToolWindowType.WINDOWED); } } + + @Override + public void update(@NotNull AnActionEvent e) { + super.update(e); + if (SystemInfo.isMac) { + e.getPresentation().setEnabledAndVisible(false); + } + } } private final class ToggleSideModeAction extends ToggleAction implements DumbAware { From 6918396409faf7d318f3f2a61dc77663ca517089 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Sat, 21 Mar 2015 23:46:52 +0300 Subject: [PATCH 28/67] RUBY-16353: Fix invisible prompt in consoles in Darcula --- .../platform-resources/src/DefaultColorSchemesManager.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/platform-resources/src/DefaultColorSchemesManager.xml b/platform/platform-resources/src/DefaultColorSchemesManager.xml index 10f717aa29d8..c916a5b8649c 100644 --- a/platform/platform-resources/src/DefaultColorSchemesManager.xml +++ b/platform/platform-resources/src/DefaultColorSchemesManager.xml @@ -1335,6 +1335,12 @@ + +