From 7c98f4a7e33770f09a9d697694751c962cdc76ef Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 8 Dec 2010 16:58:19 +0300 Subject: [PATCH 01/38] EA-24567 GitPushActiveBranchesDialog: 1. remember push exception to show it after overall failure; 2. fake content in Notication in case content is empty. --- .../checkin/GitPushActiveBranchesDialog.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/plugins/git4idea/src/git4idea/checkin/GitPushActiveBranchesDialog.java b/plugins/git4idea/src/git4idea/checkin/GitPushActiveBranchesDialog.java index 2d85d6b95e87..c7c33029829c 100644 --- a/plugins/git4idea/src/git4idea/checkin/GitPushActiveBranchesDialog.java +++ b/plugins/git4idea/src/git4idea/checkin/GitPushActiveBranchesDialog.java @@ -21,6 +21,7 @@ import com.intellij.notification.NotificationType; import com.intellij.notification.Notifications; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; @@ -101,6 +102,7 @@ public class GitPushActiveBranchesDialog extends DialogWrapper { private JRadioButton myStashRadioButton; // Save files policy option private JRadioButton myShelveRadioButton; private GitVcs myVcs; + private static final Logger LOG = Logger.getInstance(GitPushActiveBranchesDialog.class.getName()); /** * A modification of Runnable with the roots-parameter. @@ -232,6 +234,7 @@ public class GitPushActiveBranchesDialog extends DialogWrapper { final Task.Backgroundable rebaseAndPushTask = new Task.Backgroundable(myProject, GitBundle.getString("push.active.fetching")) { public void run(@NotNull ProgressIndicator indicator) { List exceptions = new ArrayList(); + List pushExceptions = new ArrayList(); for (int i = 0; i < 3; i++) { final RebaseInfo rebaseInfo = collectRebaseInfo(); @@ -251,6 +254,7 @@ public class GitPushActiveBranchesDialog extends DialogWrapper { "Pushed " + commitsNum + " " + StringUtil.pluralize("commit", commitsNum) + "."); return; } + pushExceptions = new ArrayList(exceptions); exceptions.clear(); } @@ -270,7 +274,7 @@ public class GitPushActiveBranchesDialog extends DialogWrapper { GitUtil.refreshFiles(myProject, rebaseInfo.roots); } } - notifyException("Failed to push", exceptions); + notifyException("Failed to push", pushExceptions); } }; myVcs.runInBackground(rebaseAndPushTask); @@ -280,11 +284,15 @@ public class GitPushActiveBranchesDialog extends DialogWrapper { * Notifies about errors during background rebase & push tasks. */ private void notifyException(String title, Collection exceptions) { - final String content = StringUtil.join(exceptions, new Function() { + String content = StringUtil.join(exceptions, new Function() { @Override public String fun(VcsException e) { return e.getLocalizedMessage(); } }, "
"); + if (StringUtil.isEmptyOrSpaces(content)) { + content = title; + } + LOG.info(title + " || " + content); Notifications.Bus.notify(new Notification(GitVcs.IMPORTANT_ERROR_NOTIFICATION, title, content, NotificationType.ERROR), NotificationDisplayType.STICKY_BALLOON, myProject); } From b5620626cfc8ca7a7dbb7f5ffe6a0e6b3c3d621a Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Thu, 9 Dec 2010 12:22:26 +0300 Subject: [PATCH 02/38] GitChangeProvider: added a comment about possible exception that should be monitored. --- .../git4idea/changes/GitChangeProvider.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/plugins/git4idea/src/git4idea/changes/GitChangeProvider.java b/plugins/git4idea/src/git4idea/changes/GitChangeProvider.java index c1c4d1e5cdbb..3ab1a0fbf050 100644 --- a/plugins/git4idea/src/git4idea/changes/GitChangeProvider.java +++ b/plugins/git4idea/src/git4idea/changes/GitChangeProvider.java @@ -19,8 +19,20 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.*; -import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.FilePathImpl; +import com.intellij.openapi.vcs.FileStatus; +import com.intellij.openapi.vcs.ProjectLevelVcsManager; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.VcsKey; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.ChangeListManager; +import com.intellij.openapi.vcs.changes.ChangeListManagerGate; +import com.intellij.openapi.vcs.changes.ChangeProvider; +import com.intellij.openapi.vcs.changes.ChangelistBuilder; +import com.intellij.openapi.vcs.changes.ChangesUtil; +import com.intellij.openapi.vcs.changes.VcsDirtyScope; +import com.intellij.openapi.vcs.changes.VcsModifiableDirtyScope; import com.intellij.openapi.vfs.VirtualFile; import git4idea.GitContentRevision; import git4idea.GitRevisionNumber; @@ -125,6 +137,10 @@ public class GitChangeProvider implements ChangeProvider { } public void unversioned(final VirtualFile vf) { + // NB: There was an exception that happened several times: vf == null. + // Populating myUnversioned in the ChangeCollector makes nulls not possible in myUnversioned, + // so proposing that the exception was fixed. + // More detailed analysis will be needed in case the exception appears again. 2010-12-09. myDirty.remove(new FilePathImpl(vf)); } From d02ce956a9c802eead4599b39260fe821cb5f400 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Thu, 9 Dec 2010 12:52:29 +0300 Subject: [PATCH 03/38] GitVcs.getInstance(): returning null in case of already disposed project. Should check for null in callers. --- plugins/git4idea/src/git4idea/GitVcs.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/git4idea/src/git4idea/GitVcs.java b/plugins/git4idea/src/git4idea/GitVcs.java index 98d0f8df9e8c..de15bef42bc3 100644 --- a/plugins/git4idea/src/git4idea/GitVcs.java +++ b/plugins/git4idea/src/git4idea/GitVcs.java @@ -147,8 +147,12 @@ public class GitVcs extends AbstractVcs { private RepositoryChangeListener myIndexChangeListener; private GitCurrentBranchWidget myCurrentBranchWidget; - public static GitVcs getInstance(@NotNull Project project) { - return (GitVcs)ProjectLevelVcsManager.getInstance(project).findVcsByName(NAME); + @Nullable + public static GitVcs getInstance(Project project) { + if (project == null || project.isDisposed()) { + return null; + } + return (GitVcs) ProjectLevelVcsManager.getInstance(project).findVcsByName(NAME); } public GitVcs(@NotNull Project project, From 99dbfad0f64ac99b3b4bbbfc3afaf6b69f74499b Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Thu, 9 Dec 2010 13:55:59 +0300 Subject: [PATCH 04/38] Git: logging GitBaseRebaseProcess. --- .../git4idea/update/GitBaseRebaseProcess.java | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/plugins/git4idea/src/git4idea/update/GitBaseRebaseProcess.java b/plugins/git4idea/src/git4idea/update/GitBaseRebaseProcess.java index a59f0cccec03..f0cfef7ca9d1 100644 --- a/plugins/git4idea/src/git4idea/update/GitBaseRebaseProcess.java +++ b/plugins/git4idea/src/git4idea/update/GitBaseRebaseProcess.java @@ -26,7 +26,12 @@ import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.AbstractVcsHelper; import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.ChangeListManagerEx; +import com.intellij.openapi.vcs.changes.ContentRevision; +import com.intellij.openapi.vcs.changes.InvokeAfterUpdateMode; +import com.intellij.openapi.vcs.changes.LocalChangeList; +import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager; import com.intellij.openapi.vcs.changes.shelf.ShelvedChangeList; import com.intellij.openapi.vfs.LocalFileSystem; @@ -47,7 +52,16 @@ import git4idea.ui.GitConvertFilesDialog; import git4idea.ui.GitUIUtil; import java.io.File; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.TreeSet; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -126,6 +140,7 @@ public abstract class GitBaseRebaseProcess { * @param roots the vcs roots */ public void doUpdate(ProgressIndicator progressIndicator, Set roots) { + LOG.info("GitBaseRebaseProcess.doUpdate started"); ProjectManagerEx projectManager = ProjectManagerEx.getInstanceEx(); projectManager.blockReloadingProjectOnExternalChanges(); this.myProgressIndicator = progressIndicator; @@ -244,6 +259,7 @@ public abstract class GitBaseRebaseProcess { * Restore project changes after update */ private void restoreProjectChangesAfterUpdate() { + LOG.info("GitBaseRebaseProcess.restoreProjectChangesAfterUpdate update policy: " + getUpdatePolicy()); if (mySkippedCommits.size() > 0) { GitSkippedCommits.showSkipped(myProject, mySkippedCommits); } @@ -259,6 +275,7 @@ public abstract class GitBaseRebaseProcess { final boolean isStash = getUpdatePolicy() == GitVcsSettings.UpdateChangesPolicy.STASH; HashSet filesToRefresh = isStash ? new HashSet() : null; for (LocalChangeList changeList : myListsCopy) { + LOG.info("GitBaseRebaseProcess.restoreProjectChangesAfterUpdate refreshing files from changelist " + changeList); for (Change c : changeList.getChanges()) { ContentRevision after = c.getAfterRevision(); if (after != null) { @@ -285,6 +302,7 @@ public abstract class GitBaseRebaseProcess { public void run() { for (LocalChangeList changeList : myListsCopy) { final Collection changes = changeList.getChanges(); + LOG.debug("restoreProjectChangesAfterUpdate.invokeAfterUpdate changeList: " + changeList.getName() + " changes: " + changes.size()); if (!changes.isEmpty()) { LOG.debug("After restoring files: moving " + changes.size() + " changes to '" + changeList.getName() + "'"); myChangeManager.moveChangesTo(changeList, changes.toArray(new Change[changes.size()])); @@ -351,12 +369,13 @@ public abstract class GitBaseRebaseProcess { * @return false, if update process needs to be aborted */ private boolean saveProjectChangesBeforeUpdate() { + LOG.info("GitBaseRebaseProcess.saveProjectChangesBeforeUpdate update policy: " + getUpdatePolicy()); if (getUpdatePolicy() == GitVcsSettings.UpdateChangesPolicy.STASH || getUpdatePolicy() == GitVcsSettings.UpdateChangesPolicy.SHELVE) { myStashMessage = makeStashMessage(); myListsCopy = myChangeManager.getChangeListsCopy(); for (LocalChangeList l : myListsCopy) { final Collection changeCollection = l.getChanges(); - LOG.debug("Stashing " + changeCollection.size() + " changes from '" + l.getName() + "'"); + LOG.info("Stashing " + changeCollection.size() + " changes from '" + l.getName() + "'"); for (Change c : changeCollection) { ContentRevision after = c.getAfterRevision(); if (after != null) { @@ -405,7 +424,9 @@ public abstract class GitBaseRebaseProcess { } if (changes.size() > 0) { myProgressIndicator.setText(GitBundle.getString("update.shelving.changes")); + LOG.info("GitBaseRebaseProcess.saveProjectChangesBeforeUpdate shelving changes"); myShelvedChangeList = GitStashUtils.shelveChanges(myProject, myShelveManager, changes, myStashMessage, myExceptions); + LOG.info("GitBaseRebaseProcess.saveProjectChangesBeforeUpdate shelved changes to " + myShelvedChangeList); if (myShelvedChangeList == null) { return false; } From 74a3ab5ff07290257544024aa3483119ef71d44a Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Thu, 9 Dec 2010 16:08:37 +0300 Subject: [PATCH 05/38] GitVcs: made runInBackground static. If project is already disposed, the task won't be added to the queue. --- plugins/git4idea/src/git4idea/GitVcs.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/plugins/git4idea/src/git4idea/GitVcs.java b/plugins/git4idea/src/git4idea/GitVcs.java index de15bef42bc3..53bc07f9c4de 100644 --- a/plugins/git4idea/src/git4idea/GitVcs.java +++ b/plugins/git4idea/src/git4idea/GitVcs.java @@ -64,6 +64,7 @@ import git4idea.changes.GitCommittedChangeListProvider; import git4idea.changes.GitOutgoingChangesProvider; import git4idea.checkin.GitCheckinEnvironment; import git4idea.checkin.GitCommitAndPushExecutor; +import git4idea.checkout.branches.GitBranches; import git4idea.checkout.branches.GitCurrentBranchWidget; import git4idea.commands.GitCommand; import git4idea.commands.GitSimpleHandler; @@ -146,6 +147,7 @@ public class GitVcs extends AbstractVcs { private GitExecutableValidator myExecutableValidator; private RepositoryChangeListener myIndexChangeListener; private GitCurrentBranchWidget myCurrentBranchWidget; + private GitBranches myBranches; @Nullable public static GitVcs getInstance(Project project) { @@ -186,6 +188,7 @@ public class GitVcs extends AbstractVcs { myReferenceTracker = new GitReferenceTracker(myProject, this, myReferenceListeners.getMulticaster()); myTaskQueue = new BackgroundTaskQueue(myProject, GitBundle.getString("task.queue.title")); myIndexChangeListener = new RepositoryChangeListener(myProject, ".git/index"); + myBranches = new GitBranches(myProject); } /** @@ -207,8 +210,11 @@ public class GitVcs extends AbstractVcs { * * @param task the task to run */ - public void runInBackground(Task.Backgroundable task) { - myTaskQueue.run(task); + public static void runInBackground(Task.Backgroundable task) { + GitVcs vcs = getInstance(task.getProject()); + if (vcs != null) { + vcs.myTaskQueue.run(task); + } } /** @@ -460,11 +466,11 @@ public class GitVcs extends AbstractVcs { NewGitUsersComponent.getInstance(myProject).activate(); GitProjectLogManager.getInstance(myProject).activate(); + addGitReferenceListener(myBranches); StatusBar statusBar = WindowManager.getInstance().getStatusBar(myProject); if (statusBar != null) { - myCurrentBranchWidget = new GitCurrentBranchWidget(myProject); + myCurrentBranchWidget = new GitCurrentBranchWidget(myProject, myBranches); statusBar.addWidget(myCurrentBranchWidget, "after " + (SystemInfo.isMac ? "Encoding" : "InsertOverwrite"), myProject); - addGitReferenceListener(myCurrentBranchWidget); } } @@ -495,10 +501,10 @@ public class GitVcs extends AbstractVcs { NewGitUsersComponent.getInstance(myProject).deactivate(); GitProjectLogManager.getInstance(myProject).deactivate(); + removeGitReferenceListener(myBranches); StatusBar statusBar = WindowManager.getInstance().getStatusBar(myProject); if (statusBar != null && myCurrentBranchWidget != null) { statusBar.removeWidget(myCurrentBranchWidget.ID()); - removeGitReferenceListener(myCurrentBranchWidget); myCurrentBranchWidget = null; } } From b4dbc115dc303e87eb44fa8a868926b5ed69da7e Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Thu, 9 Dec 2010 18:03:34 +0300 Subject: [PATCH 06/38] GitBranchWidget refactoring. Introduced GitBranches project service to keep and track branch information (for now only current branch per root). Introduced GitBranchesListener interface to listen to changes in branch configuration. Renamed GitCurrentBranchWidget to GitBranchWidget. Moved all 3 classes to git4idea.branch. Also fixed: if current file is unversioned, show nothing in the widget. --- plugins/git4idea/src/META-INF/plugin.xml | 4 + plugins/git4idea/src/git4idea/GitVcs.java | 28 +-- .../src/git4idea/branch/GitBranchWidget.java | 141 +++++++++++++ .../src/git4idea/branch/GitBranches.java | 172 +++++++++++++++ .../git4idea/branch/GitBranchesListener.java | 27 +++ .../branches/GitCurrentBranchWidget.java | 196 ------------------ 6 files changed, 354 insertions(+), 214 deletions(-) create mode 100644 plugins/git4idea/src/git4idea/branch/GitBranchWidget.java create mode 100644 plugins/git4idea/src/git4idea/branch/GitBranches.java create mode 100644 plugins/git4idea/src/git4idea/branch/GitBranchesListener.java delete mode 100644 plugins/git4idea/src/git4idea/checkout/branches/GitCurrentBranchWidget.java diff --git a/plugins/git4idea/src/META-INF/plugin.xml b/plugins/git4idea/src/META-INF/plugin.xml index 318a2eb588e8..5a69476e65c8 100644 --- a/plugins/git4idea/src/META-INF/plugin.xml +++ b/plugins/git4idea/src/META-INF/plugin.xml @@ -104,6 +104,10 @@ + + diff --git a/plugins/git4idea/src/git4idea/GitVcs.java b/plugins/git4idea/src/git4idea/GitVcs.java index 53bc07f9c4de..661c18cf1f55 100644 --- a/plugins/git4idea/src/git4idea/GitVcs.java +++ b/plugins/git4idea/src/git4idea/GitVcs.java @@ -58,14 +58,14 @@ import com.intellij.util.containers.ComparatorDelegate; import com.intellij.util.containers.Convertor; import com.intellij.util.ui.UIUtil; import git4idea.annotate.GitAnnotationProvider; +import git4idea.branch.GitBranchWidget; +import git4idea.branch.GitBranches; import git4idea.changes.GitChangeProvider; import git4idea.changes.GitChangeUtils; import git4idea.changes.GitCommittedChangeListProvider; import git4idea.changes.GitOutgoingChangesProvider; import git4idea.checkin.GitCheckinEnvironment; import git4idea.checkin.GitCommitAndPushExecutor; -import git4idea.checkout.branches.GitBranches; -import git4idea.checkout.branches.GitCurrentBranchWidget; import git4idea.commands.GitCommand; import git4idea.commands.GitSimpleHandler; import git4idea.config.GitExecutableValidator; @@ -146,8 +146,7 @@ public class GitVcs extends AbstractVcs { private boolean isActivated; // If true, the vcs was activated private GitExecutableValidator myExecutableValidator; private RepositoryChangeListener myIndexChangeListener; - private GitCurrentBranchWidget myCurrentBranchWidget; - private GitBranches myBranches; + private GitBranchWidget myBranchWidget; @Nullable public static GitVcs getInstance(Project project) { @@ -188,7 +187,6 @@ public class GitVcs extends AbstractVcs { myReferenceTracker = new GitReferenceTracker(myProject, this, myReferenceListeners.getMulticaster()); myTaskQueue = new BackgroundTaskQueue(myProject, GitBundle.getString("task.queue.title")); myIndexChangeListener = new RepositoryChangeListener(myProject, ".git/index"); - myBranches = new GitBranches(myProject); } /** @@ -441,9 +439,6 @@ public class GitVcs extends AbstractVcs { protected void shutdown() throws VcsException { } - /** - * {@inheritDoc} - */ @Override protected void activate() { isActivated = true; @@ -466,17 +461,14 @@ public class GitVcs extends AbstractVcs { NewGitUsersComponent.getInstance(myProject).activate(); GitProjectLogManager.getInstance(myProject).activate(); - addGitReferenceListener(myBranches); + GitBranches.getInstance(myProject).activate(this); StatusBar statusBar = WindowManager.getInstance().getStatusBar(myProject); if (statusBar != null) { - myCurrentBranchWidget = new GitCurrentBranchWidget(myProject, myBranches); - statusBar.addWidget(myCurrentBranchWidget, "after " + (SystemInfo.isMac ? "Encoding" : "InsertOverwrite"), myProject); + myBranchWidget = new GitBranchWidget(myProject); + statusBar.addWidget(myBranchWidget, "after " + (SystemInfo.isMac ? "Encoding" : "InsertOverwrite"), myProject); } } - /** - * {@inheritDoc} - */ @Override protected void deactivate() { isActivated = false; @@ -501,11 +493,11 @@ public class GitVcs extends AbstractVcs { NewGitUsersComponent.getInstance(myProject).deactivate(); GitProjectLogManager.getInstance(myProject).deactivate(); - removeGitReferenceListener(myBranches); + GitBranches.getInstance(myProject).deactivate(); StatusBar statusBar = WindowManager.getInstance().getStatusBar(myProject); - if (statusBar != null && myCurrentBranchWidget != null) { - statusBar.removeWidget(myCurrentBranchWidget.ID()); - myCurrentBranchWidget = null; + if (statusBar != null && myBranchWidget != null) { + statusBar.removeWidget(myBranchWidget.ID()); + myBranchWidget = null; } } diff --git a/plugins/git4idea/src/git4idea/branch/GitBranchWidget.java b/plugins/git4idea/src/git4idea/branch/GitBranchWidget.java new file mode 100644 index 000000000000..734e8d44b7d9 --- /dev/null +++ b/plugins/git4idea/src/git4idea/branch/GitBranchWidget.java @@ -0,0 +1,141 @@ +/* + * Copyright 2000-2010 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.branch; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileEditor.FileEditorManagerEvent; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.StatusBarWidget; +import com.intellij.openapi.wm.impl.status.EditorBasedWidget; +import com.intellij.util.Consumer; +import git4idea.GitBranch; +import org.jetbrains.annotations.NotNull; + +import java.awt.event.MouseEvent; + +/** + * Status bar widget which displays the current branch for the file currently open in the editor. + * @author Kirill Likhodedov + */ +public class GitBranchWidget extends EditorBasedWidget implements StatusBarWidget.TextPresentation, StatusBarWidget.Multiframe, + GitBranchesListener { + + private volatile String myCurrentBranchName = ""; + private final GitBranches myBranches; + + public GitBranchWidget(Project project) { + super(project); + myBranches = GitBranches.getInstance(project); + myBranches.addListener(this); + } + + @Override + public StatusBarWidget copy() { + return new GitBranchWidget(getProject()); + } + + @NotNull + @Override + public String ID() { + return GitBranchWidget.class.getName(); + } + + @Override + public WidgetPresentation getPresentation(@NotNull PlatformType type) { + return this; + } + + @Override + public void selectionChanged(FileEditorManagerEvent event) { + update(); + } + + @Override + public void fileOpened(FileEditorManager source, VirtualFile file) { + update(); + } + + @Override + public void fileClosed(FileEditorManager source, VirtualFile file) { + update(); + } + + @NotNull + @Override + public String getText() { + final String text = myCurrentBranchName; + return StringUtil.isEmpty(text) ? "" : "Git: " + text; + } + + @NotNull + @Override + public String getMaxPossibleText() { + return "Git: abcdefghij"; + } + + @Override + public float getAlignment() { + return 0; + } + + @Override + public String getTooltipText() { + return "Current Git branch"; + } + + @Override + // Updates branch information on click + public Consumer getClickConsumer() { + return new Consumer() { + public void consume(MouseEvent mouseEvent) { + update(); + } + }; + } + + @Override + public void branchConfigurationChanged() { + update(); + } + + @Override + public void dispose() { + myBranches.removeListener(this); + } + + private void update() { + ApplicationManager.getApplication().invokeLater(new Runnable() { + public void run() { + final GitBranch currentBranch = myBranches.getCurrentBranch(getSelectedFile()); + String currentBranchName = currentBranch != null ? currentBranch.getName() : null; + if (currentBranchName == null) { + currentBranchName = ""; + } + myCurrentBranchName = currentBranchName; + myStatusBar.updateWidget(ID()); + } + }, new Condition() { + public boolean value(Object o) { + Project project = getProject(); + return isDisposed() || (project != null) && ((!project.isOpen()) || project.isDisposed()) || myStatusBar == null; + } + }); + } +} diff --git a/plugins/git4idea/src/git4idea/branch/GitBranches.java b/plugins/git4idea/src/git4idea/branch/GitBranches.java new file mode 100644 index 000000000000..8b3cd9c6b140 --- /dev/null +++ b/plugins/git4idea/src/git4idea/branch/GitBranches.java @@ -0,0 +1,172 @@ +/* + * Copyright 2000-2010 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.branch; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.AbstractVcs; +import com.intellij.openapi.vcs.ProjectLevelVcsManager; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.VcsRoot; +import com.intellij.openapi.vcs.changes.ChangeListManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.EventDispatcher; +import git4idea.GitBranch; +import git4idea.GitVcs; +import git4idea.vfs.GitReferenceListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * Container and tracker of git branches information. + * Listens to branch change and updates information here. + * Subscribe a {@link GitBranchesListener} to get notified for current branch and other branch configuration changes. + * @author Kirill Likhodedov + */ +public class GitBranches implements GitReferenceListener { + private static final Logger LOG = Logger.getInstance(GitBranches.class.getName()); + private final Project myProject; + private final ProjectLevelVcsManager myVcsManager; + + private final EventDispatcher myListeners = EventDispatcher.create(GitBranchesListener.class); + private Map myCurrentBranches = new HashMap(); + private final Object myCurrentBranchesLock = new Object(); + private ChangeListManager myChangeListManager; + private GitVcs myVcs; + + public GitBranches(Project project, ChangeListManager changeListManager, ProjectLevelVcsManager vcsManager) { + myProject = project; + myChangeListManager = changeListManager; + myVcsManager = vcsManager; + } + + public static GitBranches getInstance(Project project) { + return ServiceManager.getService(project, GitBranches.class); + } + + @Override + public void referencesChanged(VirtualFile root) { + updateBranchesInfo(root); + } + + public void activate(GitVcs vcs) { + myVcs = vcs; + myVcs.addGitReferenceListener(this); + } + + public void deactivate() { + if (myVcs != null) { + myVcs.removeGitReferenceListener(this); + } + } + + /** + * Returns branch that is active (current) in the repository in which the given file resides. + * @param file file to determine branch. + * @return current branch or null if the file is null, not under git vcs, unversioned, or branch information is not available for it. + */ + @Nullable + public GitBranch getCurrentBranch(VirtualFile file) { + if (file == null) { return null; } + final AbstractVcs vcs = myVcsManager.getVcsFor(file); + if (vcs == null || !(vcs instanceof GitVcs)) { return null; } + final VirtualFile vcsRoot = myVcsManager.getVcsRootFor(file); + if (vcsRoot == null) { return null; } + if (myChangeListManager.isUnversioned(file)) { return null; } + + synchronized (myCurrentBranchesLock) { + return myCurrentBranches.get(vcsRoot); + } + } + + public void addListener(GitBranchesListener listener) { + myListeners.addListener(listener); + } + + public void removeListener(GitBranchesListener listener) { + myListeners.removeListener(listener); + } + + /** + * Updates branch information for the given root. + * If root is null, updates branch information for all Git roots in the project. + * @see #fullyUpdateBranchesInfo(java.util.Collection) + */ + private void updateBranchesInfo(final VirtualFile root) { + if (root == null) { // all roots may be affected + Collection roots = new ArrayList(1); + for (VcsRoot vcsRoot : myVcsManager.getAllVcsRoots()) { + if (vcsRoot.vcs != null && vcsRoot.vcs instanceof GitVcs && vcsRoot.path != null) { + roots.add(vcsRoot.path); + } + } + fullyUpdateBranchesInfo(roots); + return; + } + + final Task.Backgroundable task = new Task.Backgroundable(myProject, "") { + @Override public void run(@NotNull ProgressIndicator indicator) { + try { + GitBranch currentBranch = GitBranch.current(myProject, root); + synchronized (myCurrentBranchesLock) { + myCurrentBranches.put(root, currentBranch); + } + notifyListeners(); + } catch (VcsException e) { + LOG.info("Exception while trying to get current branch for root " + root, e); + // doing nothing - null will be set to myCurrentBranchName + } + } + }; + GitVcs.runInBackground(task); + } + + private void fullyUpdateBranchesInfo(final Collection roots) { + if (roots == null) { return; } + final Task.Backgroundable task = new Task.Backgroundable(myProject, "") { + @Override public void run(@NotNull ProgressIndicator indicator) { + Map currentBranches = new HashMap(); + for (VirtualFile root : roots) { + try { + GitBranch currentBranch = GitBranch.current(myProject, root); + currentBranches.put(root, currentBranch); + notifyListeners(); + } catch (VcsException e) { + LOG.info("Exception while trying to get current branch for root " + root, e); + // doing nothing - null will be set to myCurrentBranchName + } + } + synchronized (myCurrentBranchesLock) { + myCurrentBranches = currentBranches; + } + } + }; + GitVcs.runInBackground(task); + } + + private void notifyListeners() { + myListeners.getMulticaster().branchConfigurationChanged(); + } + +} diff --git a/plugins/git4idea/src/git4idea/branch/GitBranchesListener.java b/plugins/git4idea/src/git4idea/branch/GitBranchesListener.java new file mode 100644 index 000000000000..cc4cec12092a --- /dev/null +++ b/plugins/git4idea/src/git4idea/branch/GitBranchesListener.java @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2010 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.branch; + +import java.util.EventListener; + +/** + * GitBranchesListener listens to events related to Git branches. + * Change of active branch, branch creation, etc. + * @author Kirill Likhodedov + */ +public interface GitBranchesListener extends EventListener { + void branchConfigurationChanged(); +} diff --git a/plugins/git4idea/src/git4idea/checkout/branches/GitCurrentBranchWidget.java b/plugins/git4idea/src/git4idea/checkout/branches/GitCurrentBranchWidget.java deleted file mode 100644 index ebca1eec9e8f..000000000000 --- a/plugins/git4idea/src/git4idea/checkout/branches/GitCurrentBranchWidget.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2000-2010 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.checkout.branches; - -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.fileEditor.FileEditorManager; -import com.intellij.openapi.fileEditor.FileEditorManagerEvent; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.Task; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vcs.AbstractVcs; -import com.intellij.openapi.vcs.CalledInAwt; -import com.intellij.openapi.vcs.ProjectLevelVcsManager; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.VcsRoot; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.wm.StatusBarWidget; -import com.intellij.openapi.wm.impl.status.EditorBasedWidget; -import com.intellij.util.Consumer; -import git4idea.GitBranch; -import git4idea.GitVcs; -import git4idea.vfs.GitReferenceListener; -import org.jetbrains.annotations.NotNull; - -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; - -/** - * Status bar widget which displays the current branch. - * @author Kirill Likhodedov - */ -public class GitCurrentBranchWidget extends EditorBasedWidget implements StatusBarWidget.TextPresentation, GitReferenceListener, StatusBarWidget.Multiframe { - - private ProjectLevelVcsManager myVcsManager; - private AtomicReference myCurrentBranchName = new AtomicReference(""); - private static final Logger LOG = Logger.getInstance(GitCurrentBranchWidget.class.getName()); - private final Map myCurrentBranches = new HashMap(); - - public GitCurrentBranchWidget(Project project) { - super(project); - myVcsManager = ProjectLevelVcsManager.getInstance(project); - updateBranchInfo(null); - } - - @Override - public StatusBarWidget copy() { - return new GitCurrentBranchWidget(getProject()); - } - - @NotNull - @Override - public String ID() { - return "git4idea.GitCurrentBranchWidget"; - } - - @Override - public WidgetPresentation getPresentation(@NotNull PlatformType type) { - return this; - } - - @Override - public void selectionChanged(FileEditorManagerEvent event) { - updateUI(); - } - - @Override - public void fileOpened(FileEditorManager source, VirtualFile file) { - updateUI(); - } - - @Override - public void fileClosed(FileEditorManager source, VirtualFile file) { - updateUI(); - } - - @Override - public void referencesChanged(VirtualFile root) { - updateBranchInfo(root); - } - - @NotNull - @Override - public String getText() { - final String text = myCurrentBranchName.get(); - return StringUtil.isEmpty(text) ? "" : "Git: " + text; - } - - @NotNull - @Override - public String getMaxPossibleText() { - return "Git: abcdefghij"; - } - - @Override - public float getAlignment() { - return 0; - } - - @Override - public String getTooltipText() { - return "Current Git branch"; - } - - @Override - // Updates branch information on click - public Consumer getClickConsumer() { - return new Consumer() { - public void consume(MouseEvent mouseEvent) { - updateUI(); - } - }; - } - - @CalledInAwt - private void updateUI() { - final VirtualFile file = getSelectedFile(); - final Project project = getProject(); - if (file == null || project == null || isDisposed() || !project.isOpen() || project.isDisposed() || myStatusBar == null) { - return; - } - - String currentBranchName = null; - final AbstractVcs vcs = myVcsManager.getVcsFor(file); - if (vcs != null && vcs instanceof GitVcs) { - final VirtualFile root = myVcsManager.getVcsRootFor(file); - if (root != null) { - final GitBranch currentBranch = myCurrentBranches.get(root); - if (currentBranch != null) { - currentBranchName = currentBranch.getName(); - } - } - } - if (currentBranchName == null) { - currentBranchName = ""; - } - myCurrentBranchName.set(currentBranchName); - myStatusBar.updateWidget(ID()); - } - - private void updateBranchInfo(VirtualFile root) { - final Collection roots = new ArrayList(1); - if (root == null) { // all roots may be affected - for (VcsRoot vcsRoot : myVcsManager.getAllVcsRoots()) { - if (vcsRoot.vcs != null && vcsRoot.vcs instanceof GitVcs && vcsRoot.path != null) { - roots.add(vcsRoot.path); - } - } - } else { - roots.add(root); - } - - final Project project = getProject(); - final Task.Backgroundable task = new Task.Backgroundable(project, "Loading Git branch info") { - @Override public void run(@NotNull ProgressIndicator indicator) { - for (VirtualFile root : roots) { - try { - GitBranch currentBranch = GitBranch.current(project, root); - synchronized (myCurrentBranches) { - myCurrentBranches.put(root, currentBranch); - } - } catch (VcsException e) { - LOG.info("Exception while trying to get current branch for root " + root, e); - } - } - ApplicationManager.getApplication().invokeLater(new Runnable() { - public void run() { - updateUI(); - } - }); - } - }; - if (project != null) { - GitVcs.getInstance(project).runInBackground(task); - } - } - -} From e27d671a8dbaa831e7abaca31f23b1c9f507e441 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Thu, 9 Dec 2010 18:09:05 +0300 Subject: [PATCH 07/38] Git: more logging in update and unshelve. --- .../src/git4idea/update/GitBaseRebaseProcess.java | 2 +- .../git4idea/src/git4idea/update/GitStashUtils.java | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/plugins/git4idea/src/git4idea/update/GitBaseRebaseProcess.java b/plugins/git4idea/src/git4idea/update/GitBaseRebaseProcess.java index f0cfef7ca9d1..ea9d0d7de72d 100644 --- a/plugins/git4idea/src/git4idea/update/GitBaseRebaseProcess.java +++ b/plugins/git4idea/src/git4idea/update/GitBaseRebaseProcess.java @@ -259,7 +259,7 @@ public abstract class GitBaseRebaseProcess { * Restore project changes after update */ private void restoreProjectChangesAfterUpdate() { - LOG.info("GitBaseRebaseProcess.restoreProjectChangesAfterUpdate update policy: " + getUpdatePolicy()); + LOG.info("GitBaseRebaseProcess.restoreProjectChangesAfterUpdate update policy: " + getUpdatePolicy() + " myShelvedChangeList: " + myShelvedChangeList); if (mySkippedCommits.size() > 0) { GitSkippedCommits.showSkipped(myProject, mySkippedCommits); } diff --git a/plugins/git4idea/src/git4idea/update/GitStashUtils.java b/plugins/git4idea/src/git4idea/update/GitStashUtils.java index 14e13b582b7c..1b66b0b66a4a 100644 --- a/plugins/git4idea/src/git4idea/update/GitStashUtils.java +++ b/plugins/git4idea/src/git4idea/update/GitStashUtils.java @@ -15,6 +15,7 @@ */ package git4idea.update; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.FileStatus; @@ -42,7 +43,11 @@ import org.jetbrains.annotations.Nullable; import javax.swing.event.ChangeEvent; import java.io.File; import java.io.IOException; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; /** * The class contains utilities for creating and removing stashes. @@ -52,6 +57,7 @@ public class GitStashUtils { * The version when quiet stash supported */ private final static GitVersion QUIET_STASH_SUPPORTED = new GitVersion(1, 6, 4, 0); + private static final Logger LOG = Logger.getInstance(GitStashUtils.class.getName()); private GitStashUtils() { } @@ -103,6 +109,7 @@ public class GitStashUtils { final ShelveChangesManager shelveManager, final ChangeListManagerEx changeManager, List exceptions) { + LOG.info("doSystemUnshelve "); // The changes are temporary copied to the first local change list, the next operation will restore them back VirtualFile baseDir = project.getBaseDir(); assert baseDir != null; @@ -126,15 +133,18 @@ public class GitStashUtils { } } LocalFileSystem.getInstance().refreshIoFiles(filesToRefresh); + LOG.info("doSystemUnshelve files refreshed. unshelving in AWT thread."); // Do unshevle UIUtil.invokeAndWaitIfNeeded(new Runnable() { public void run() { GitVFSListener l = GitVcs.getInstance(project).getVFSListener(); l.setEventsSuppressed(true); try { + LOG.info("Unshelving in UI thread. shelvedChangeList: " + shelvedChangeList); shelveManager .unshelveChangeList(shelvedChangeList, shelvedChangeList.getChanges(), shelvedChangeList.getBinaryFiles(), changeManager.getDefaultChangeList(), false); + LOG.info("Deleting change list"); shelveManager.deleteChangeList(shelvedChangeList); } finally { From a31ca728008f06ff346989228918684ce7e12268 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 10 Dec 2010 15:40:16 +0300 Subject: [PATCH 08/38] Check if IdeFrame has project (EA-24673) --- .../src/com/intellij/unscramble/UnscrambleListener.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/unscramble/UnscrambleListener.java b/java/java-impl/src/com/intellij/unscramble/UnscrambleListener.java index 120e3d83c4ef..6c44fad99e3a 100644 --- a/java/java-impl/src/com/intellij/unscramble/UnscrambleListener.java +++ b/java/java-impl/src/com/intellij/unscramble/UnscrambleListener.java @@ -16,6 +16,7 @@ package com.intellij.unscramble; import com.intellij.openapi.application.ApplicationAdapter; +import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.IdeFrame; import java.util.regex.Pattern; @@ -32,8 +33,9 @@ public class UnscrambleListener extends ApplicationAdapter { final String clipboard = AnalyzeStacktraceUtil.getTextInClipboard(); if (clipboard != null && clipboard.length() < MAX_STACKTRACE_SIZE && !clipboard.equals(stacktrace)) { stacktrace = clipboard; - if (isStacktrace(stacktrace)) { - final UnscrambleDialog dialog = new UnscrambleDialog(ideFrame.getProject()); + final Project project = ideFrame.getProject(); + if (project != null && isStacktrace(stacktrace)) { + final UnscrambleDialog dialog = new UnscrambleDialog(project); dialog.createNormalizeTextAction().actionPerformed(null); dialog.doOKAction(); } From 16b871e607c76bfdb4f441c0e43428fe0f5b4292 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Thu, 9 Dec 2010 13:36:12 +0300 Subject: [PATCH 09/38] cleanup && diagnostics for EA-24385 - NPE: FileReferenceSet. --- .../resolve/reference/impl/providers/FileReferenceSet.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceSet.java b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceSet.java index 6de47a442bf5..af780a7e4535 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceSet.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceSet.java @@ -139,8 +139,7 @@ public class FileReferenceSet { public FileReferenceSet(final @NotNull PsiElement element) { myElement = element; - final ElementManipulator manipulator = ElementManipulators.getManipulator(element); - final TextRange range = manipulator.getRangeInElement(element); + TextRange range = ElementManipulators.getValueTextRange(element); myStartInElement = range.getStartOffset(); final String s = range.substring(element.getText()); myPathString = s.trim(); From d12dd083b1f694a83e497fee15112571c60aae41 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 10 Dec 2010 15:57:41 +0300 Subject: [PATCH 10/38] EA-24189 - OOME: FileChannelImpl.map recovery [rev. by jeka] --- .../intellij/util/io/MappedBufferWrapper.java | 5 +- .../intellij/util/io/PagedFileStorage.java | 70 ++++++++++++++++--- .../util/io/ReadOnlyMappedBufferWrapper.java | 21 ++---- .../util/io/ReadWriteMappedBufferWrapper.java | 50 ++++--------- 4 files changed, 84 insertions(+), 62 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/MappedBufferWrapper.java b/platform/util/src/com/intellij/util/io/MappedBufferWrapper.java index 8114f53e3a3b..0cf5923e87d5 100644 --- a/platform/util/src/com/intellij/util/io/MappedBufferWrapper.java +++ b/platform/util/src/com/intellij/util/io/MappedBufferWrapper.java @@ -24,6 +24,7 @@ import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NonNls; import java.io.File; +import java.io.IOException; import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; @@ -48,7 +49,7 @@ public abstract class MappedBufferWrapper { myLength = length; } - protected abstract MappedByteBuffer map(); + protected abstract MappedByteBuffer map() throws IOException; private static final int MAX_FORCE_ATTEMPTS = 10; @@ -63,7 +64,7 @@ public abstract class MappedBufferWrapper { return myBuffer; } - public ByteBuffer buf() { + public ByteBuffer buf() throws IOException { if (myBuffer == null) { myBuffer = map(); } diff --git a/platform/util/src/com/intellij/util/io/PagedFileStorage.java b/platform/util/src/com/intellij/util/io/PagedFileStorage.java index 5a985cceabf7..a3954c1b16ce 100644 --- a/platform/util/src/com/intellij/util/io/PagedFileStorage.java +++ b/platform/util/src/com/intellij/util/io/PagedFileStorage.java @@ -16,6 +16,7 @@ package com.intellij.util.io; import com.intellij.openapi.Forceable; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.util.containers.hash.LinkedHashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -33,7 +34,12 @@ import java.util.Set; * @author max */ public class PagedFileStorage implements Forceable { - private final static int BUFFER_SIZE = 10 * 1024 * 1024; // 10M + + protected static final Logger LOG = Logger.getInstance("#com.intellij.util.io.PagedFileStorage"); + private static final int MEGABYTE = 1024 * 1024; + private final static int BUFFER_SIZE = 10 * MEGABYTE; + private final static int UPPER_LIMIT = 200 * MEGABYTE; + private final static int LOWER_LIMIT = 100 * MEGABYTE; private final StorageLock myLock; @@ -51,8 +57,9 @@ public class PagedFileStorage implements Forceable { final BuffersCache myBuffersCache = new BuffersCache(); private class BuffersCache extends MyCache { + public BuffersCache() { - super(20 * BUFFER_SIZE); + super(UPPER_LIMIT); } @NotNull @@ -65,7 +72,40 @@ public class PagedFileStorage implements Forceable { if (off > key.owner.length()) { throw new IndexOutOfBoundsException("off=" + off + " key.owner.length()=" + key.owner.length()); } - return new ReadWriteMappedBufferWrapper(key.owner.myFile, off, Math.min((int)(key.owner.length() - off), BUFFER_SIZE)); + ReadWriteMappedBufferWrapper wrapper = + new ReadWriteMappedBufferWrapper(key.owner.myFile, off, Math.min((int)(key.owner.length() - off), BUFFER_SIZE)); + IOException oome = null; + while (true) { + try { + // ensure it's allocated + wrapper.buf(); + if (oome != null) { + LOG.error("Successfully recovered OOME in memory mapping: -Xmx=" + Runtime.getRuntime().maxMemory() / MEGABYTE + "MB " + + "new size limit: " + mySizeLimit / MEGABYTE + "MB " + + "trying to allocate " + wrapper.myLength + " block"); + } + return wrapper; + } + catch (IOException e) { + if (e.getCause() instanceof OutOfMemoryError) { + oome = e; + if (mySizeLimit > LOWER_LIMIT) { + mySizeLimit -= BUFFER_SIZE; + } + long newSize = getSize() - BUFFER_SIZE; + if (newSize >= 0) { + ensureSize(newSize); + continue; // next try + } + else { + throw new MappingFailedException("Cannot recover from OOME in memory mapping: -Xmx=" + Runtime.getRuntime().maxMemory() / MEGABYTE + "MB " + + "new size limit: " + mySizeLimit / MEGABYTE + "MB " + + "trying to allocate " + wrapper.myLength + " block", e); + } + } + throw new MappingFailedException("Cannot map buffer", e); + } + } } public void onDropFromCache(PageKey key, MappedBufferWrapper buf) { @@ -106,7 +146,7 @@ public class PagedFileStorage implements Forceable { private final byte[] myTypedIOBuffer = new byte[8]; private boolean isDirty = false; private final File myFile; - private long mySize = -1; + protected long mySize = -1; @NonNls private static final String RW = "rw"; public PagedFileStorage(File file, StorageLock lock) throws IOException { @@ -133,6 +173,7 @@ public class PagedFileStorage implements Forceable { put(addr, myTypedIOBuffer, 0, 8); } + @SuppressWarnings({"UnusedDeclaration"}) public void putByte(final int addr, final byte b) { myTypedIOBuffer[0] = b; put(addr, myTypedIOBuffer, 0, 1); @@ -277,7 +318,12 @@ public class PagedFileStorage implements Forceable { } private ByteBuffer getBuffer(int page) { - return myLock.myBuffersCache.get(new PageKey(this, page)).buf(); + try { + return myLock.myBuffersCache.get(new PageKey(this, page)).buf(); + } + catch (IOException e) { + throw new MappingFailedException("Cannot map buffer", e); + } } public void force() { @@ -296,7 +342,7 @@ public class PagedFileStorage implements Forceable { private static abstract class MyCache { private final LinkedHashMap myMap; - private final long mySizeLimit; + protected long mySizeLimit; private long mySize; protected MyCache(long sizeLimit) { @@ -329,11 +375,19 @@ public class PagedFileStorage implements Forceable { wrapper = createValue(key); mySize += wrapper.myLength; myMap.put(key, wrapper); - while (mySize > mySizeLimit) { + ensureSize(mySizeLimit); + return wrapper; + } + + protected void ensureSize(long sizeLimit) { + while (mySize > sizeLimit) { // we still have to drop something myMap.doRemoveEldestEntry(); } - return wrapper; + } + + public long getSize() { + return mySize; } public Set> entrySet() { diff --git a/platform/util/src/com/intellij/util/io/ReadOnlyMappedBufferWrapper.java b/platform/util/src/com/intellij/util/io/ReadOnlyMappedBufferWrapper.java index f025447395be..9280bcaab5e4 100644 --- a/platform/util/src/com/intellij/util/io/ReadOnlyMappedBufferWrapper.java +++ b/platform/util/src/com/intellij/util/io/ReadOnlyMappedBufferWrapper.java @@ -30,22 +30,15 @@ public class ReadOnlyMappedBufferWrapper extends MappedBufferWrapper { super(file, pos, file.length() - pos); } - public MappedByteBuffer map() { + public MappedByteBuffer map() throws IOException { + FileInputStream stream = new FileInputStream(myFile); + FileChannel channel = stream.getChannel(); try { - FileInputStream stream = new FileInputStream(myFile); - FileChannel channel = stream.getChannel(); - try { - return channel.map(FileChannel.MapMode.READ_ONLY, myPosition, myLength); - } - finally { - channel.close(); - stream.close(); - } + return channel.map(FileChannel.MapMode.READ_ONLY, myPosition, myLength); } - catch (IOException e) { - final MappingFailedException mapFailed = new MappingFailedException("Mapping failed for: " + myFile.getPath(), e); - LOG.error(mapFailed); - throw mapFailed; + finally { + channel.close(); + stream.close(); } } } diff --git a/platform/util/src/com/intellij/util/io/ReadWriteMappedBufferWrapper.java b/platform/util/src/com/intellij/util/io/ReadWriteMappedBufferWrapper.java index 1e91397015e3..68367ac0f112 100644 --- a/platform/util/src/com/intellij/util/io/ReadWriteMappedBufferWrapper.java +++ b/platform/util/src/com/intellij/util/io/ReadWriteMappedBufferWrapper.java @@ -30,51 +30,25 @@ import java.nio.channels.FileChannel; public class ReadWriteMappedBufferWrapper extends MappedBufferWrapper { @NonNls private static final String RW = "rw"; - public ReadWriteMappedBufferWrapper(final File file) { - super(file, 0, file.length()); - } - public ReadWriteMappedBufferWrapper(final File file, int offset, int len) { super(file, offset, len); } - public MappedByteBuffer map() { - MappedByteBuffer buf; + public MappedByteBuffer map() throws IOException { + RandomAccessFile raf = null; + FileChannel channel = null; try { - buf = null; - RandomAccessFile raf = null; - FileChannel channel = null; - try { - raf = new RandomAccessFile(myFile, RW); - channel = raf.getChannel(); - buf = channel.map(FileChannel.MapMode.READ_WRITE, myPosition, myLength); + raf = new RandomAccessFile(myFile, RW); + channel = raf.getChannel(); + return channel.map(FileChannel.MapMode.READ_WRITE, myPosition, myLength); + } + finally { + if (channel != null) { + channel.close(); } - catch (IOException e) { - final MappingFailedException mapFailed = - new MappingFailedException("Mapping failed: " + myFile.getAbsolutePath() + ", position=" + myPosition + ", length=" + myLength, e); - LOG.error(mapFailed); - throw mapFailed; - } - finally { - if (channel != null) { - channel.close(); - } - if (raf != null) { - raf.close(); - } + if (raf != null) { + raf.close(); } } - catch (IOException e) { - buf = null; - } - - if (buf == null) { - final MappingFailedException mapFailed = - new MappingFailedException("Mapping failed: " + myFile.getAbsolutePath() + ", position=" + myPosition + ", length=" + myLength); - LOG.error(mapFailed); - throw mapFailed; - } - - return buf; } } \ No newline at end of file From ee553e9690d2208ae36083493e2c98f8d24ecfae Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 10 Dec 2010 15:58:16 +0300 Subject: [PATCH 11/38] cleanup --- .../util/io/ByteBufferIntObjectMap.java | 147 -------- .../com/intellij/util/io/ByteBufferMap.java | 199 ---------- .../util/io/ByteBufferMapWriteHandler.java | 112 ------ .../util/io/ByteBufferRADataInput.java | 110 ------ .../com/intellij/util/io/FileKeyProvider.java | 61 --- .../util/io/IntArrayValueProvider.java | 99 ----- .../intellij/util/io/IntValueProvider.java | 42 --- .../intellij/util/io/IntegerKeyProvider.java | 54 --- .../intellij/util/io/StringKeyProvider.java | 92 ----- .../intellij/util/io/WriteableMapAdapter.java | 54 --- .../src/com/intellij/util/io/MappedFile.java | 355 ------------------ 11 files changed, 1325 deletions(-) delete mode 100644 platform/platform-impl/src/com/intellij/util/io/ByteBufferIntObjectMap.java delete mode 100644 platform/platform-impl/src/com/intellij/util/io/ByteBufferMap.java delete mode 100644 platform/platform-impl/src/com/intellij/util/io/ByteBufferMapWriteHandler.java delete mode 100644 platform/platform-impl/src/com/intellij/util/io/ByteBufferRADataInput.java delete mode 100644 platform/platform-impl/src/com/intellij/util/io/FileKeyProvider.java delete mode 100644 platform/platform-impl/src/com/intellij/util/io/IntArrayValueProvider.java delete mode 100644 platform/platform-impl/src/com/intellij/util/io/IntValueProvider.java delete mode 100644 platform/platform-impl/src/com/intellij/util/io/IntegerKeyProvider.java delete mode 100644 platform/platform-impl/src/com/intellij/util/io/StringKeyProvider.java delete mode 100644 platform/platform-impl/src/com/intellij/util/io/WriteableMapAdapter.java delete mode 100644 platform/util/src/com/intellij/util/io/MappedFile.java diff --git a/platform/platform-impl/src/com/intellij/util/io/ByteBufferIntObjectMap.java b/platform/platform-impl/src/com/intellij/util/io/ByteBufferIntObjectMap.java deleted file mode 100644 index 1b5a16bf6f82..000000000000 --- a/platform/platform-impl/src/com/intellij/util/io/ByteBufferIntObjectMap.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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.util.io; - -import com.intellij.openapi.diagnostic.Logger; -import gnu.trove.TIntArrayList; -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; - -public class ByteBufferIntObjectMap { - private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.ByteBufferMap"); - - private final RandomAccessDataInput myBuffer; - private final int myStartOffset; - private final ByteBufferMap.ValueProvider myValueProvider; - private int myMod; - private final int myEndOffset; - - public ByteBufferIntObjectMap(@NotNull MappedBufferWrapper buffer, - int startOffset, - int endOffset, - @NotNull ByteBufferMap.ValueProvider valueProvider) { - assert startOffset < endOffset; - - myBuffer = new ByteBufferRADataInput(buffer); - myStartOffset = startOffset; - myEndOffset = endOffset; - myValueProvider = valueProvider; - - myBuffer.setPosition(startOffset); - try { - myMod = myBuffer.readInt(); - } - catch (IOException e) { - LOG.error(e); - } - } - - public V get(int key) { - int hash = hash(key); - int keyGroupOffset = readKeyGroupOffset(hash); - if (keyGroupOffset == -1) return null; - if (!(myStartOffset < keyGroupOffset && keyGroupOffset < myEndOffset)){ - LOG.error("keyGroupOffset = " + keyGroupOffset + " myStartOffset = " + myStartOffset + " myEndOffset = " + myEndOffset); - } - - try { - myBuffer.setPosition(keyGroupOffset); - int keyGroupSize = myBuffer.readInt(); - assert (keyGroupSize > 0); - for (int i = 0; i < keyGroupSize; i++) { - if (key == myBuffer.readInt()) { - int valueOffset = myBuffer.readInt(); - assert (valueOffset > 0); - - myBuffer.setPosition(myStartOffset + valueOffset); - return myValueProvider.get(myBuffer); - } - else { - myBuffer.readInt(); //read offset; - } - } - } - catch (IOException e) { - LOG.error(e); - } - - return null; - } - - public TIntArrayList getKeys() { - TIntArrayList result = new TIntArrayList(); - getKeys(result); - return result; - } - - public void getKeys(TIntArrayList dst) { - try { - myBuffer.setPosition(myStartOffset + 4 /* mod */); - - int firstKeyGroupOffset = -1; - int lastKeyGroupOffset = -1; - for (int i = 0; i < myMod; i++) { - int value = myBuffer.readInt(); - if (value != -1) { - int offset = value + myStartOffset; - if (firstKeyGroupOffset == -1) firstKeyGroupOffset = offset; - lastKeyGroupOffset = offset; - } - } - if (firstKeyGroupOffset == -1) { - return; - } - assert (firstKeyGroupOffset > myStartOffset); - assert (lastKeyGroupOffset > myStartOffset); - assert (lastKeyGroupOffset >= firstKeyGroupOffset); - - int firstValueOffset = -1; - - myBuffer.setPosition(firstKeyGroupOffset); - while (myBuffer.getPosition() <= lastKeyGroupOffset) { - int groupSize = myBuffer.readInt(); - for (int i = 0; i < groupSize; i++) { - dst.add(myBuffer.readInt()); - - int valueOffset = myBuffer.readInt(); /* value offset */ - if( firstValueOffset == -1 ) firstValueOffset = valueOffset + myStartOffset; - } - } - assert myBuffer.getPosition() == firstValueOffset; - } - catch (IOException e) { - LOG.error(e); - } - } - - private int readKeyGroupOffset(int hash) { - myBuffer.setPosition(myStartOffset + 4 /* mod */ + 4 * hash); - int offset = -1; - try { - offset = myBuffer.readInt(); - } - catch (IOException e) { - LOG.error(e); - } - if (offset == -1) return -1; - return offset + myStartOffset; - } - - private int hash(int hashCode) { - return Math.abs(hashCode) % myMod; - } -} diff --git a/platform/platform-impl/src/com/intellij/util/io/ByteBufferMap.java b/platform/platform-impl/src/com/intellij/util/io/ByteBufferMap.java deleted file mode 100644 index 1068e8d78c85..000000000000 --- a/platform/platform-impl/src/com/intellij/util/io/ByteBufferMap.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * 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.util.io; - -import com.intellij.openapi.diagnostic.Logger; -import org.jetbrains.annotations.NotNull; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.Collection; - -public class ByteBufferMap { - private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.ByteBufferMap"); - - private final RandomAccessDataInput myBuffer; - private final int myStartOffset; - private final KeyProvider myKeyProvider; - private final ValueProvider myValueProvider; - private int myMod; - private final int myEndOffset; - - public static interface KeyProvider { - int hashCode(K key); - - void write(DataOutput out, K key) throws IOException; - - int length(K key); - - K get(DataInput in) throws IOException; - - /** - * Should move the buffer pointer to the key end. - */ - boolean equals(DataInput in, K key) throws IOException; - } - - public static interface ValueProvider { - void write(DataOutput out, V value) throws IOException; - - int length(V value); - - V get(DataInput in) throws IOException; - } - - public static void writeMap(DataOutput stream, - ValueProvider valueProvider, - WriteableMap map, - double searchFactor) throws IOException { - new ByteBufferMapWriteHandler(stream, valueProvider, map, searchFactor).execute(); - } - - public static int calcMapLength(ValueProvider valueProvider, - WriteableMap map, - double searchFactor) throws IOException { - return new ByteBufferMapWriteHandler(null, valueProvider, map, searchFactor).calcLength(); - } - - public ByteBufferMap(@NotNull MappedBufferWrapper holder, - int startOffset, - int endOffset, - @NotNull KeyProvider keyProvider, - @NotNull ValueProvider valueProvider) { - this(new ByteBufferRADataInput(holder), startOffset, endOffset, keyProvider, valueProvider); - } - - public ByteBufferMap(@NotNull RandomAccessDataInput buffer, - int startOffset, - int endOffset, - @NotNull KeyProvider keyProvider, - @NotNull ValueProvider valueProvider) { - assert startOffset < endOffset; - - myBuffer = buffer; - myStartOffset = startOffset; - myEndOffset = endOffset; - myKeyProvider = keyProvider; - myValueProvider = valueProvider; - - buffer.setPosition(startOffset); - try { - myMod = buffer.readInt(); - } - catch (IOException e) { - LOG.error(e); - } - } - - public V get(K key) { - int hash = hash(myKeyProvider.hashCode(key)); - int keyGroupOffset = readKeyGroupOffset(hash); - if (keyGroupOffset == -1) return null; - if (!(myStartOffset < keyGroupOffset && keyGroupOffset < myEndOffset)){ - LOG.error("keyGroupOffset = " + keyGroupOffset + " myStartOffset = " + myStartOffset + " myEndOffset = " + myEndOffset); - } - - try { - myBuffer.setPosition(keyGroupOffset); - int keyGroupSize = myBuffer.readInt(); - assert (keyGroupSize > 0); - for (int i = 0; i < keyGroupSize; i++) { - if (myKeyProvider.equals(myBuffer, key)) { - int valueOffset = myBuffer.readInt(); - assert (valueOffset > 0); - - myBuffer.setPosition(myStartOffset + valueOffset); - return myValueProvider.get(myBuffer); - } - else { - myBuffer.readInt(); //read offset; - } - } - } - catch (IOException e) { - LOG.error(e); - } - - return null; - } - - @SuppressWarnings({"unchecked"}) - public K[] getKeys(Class keyClass) { - ArrayList result = new ArrayList(); - getKeys(keyClass, result); - return result.toArray((K[])Array.newInstance(keyClass, result.size())); - } - - public void getKeys(Class keyClass, Collection dst) { - try { - myBuffer.setPosition(myStartOffset + 4 /* mod */); - - int firstKeyGroupOffset = -1; - int lastKeyGroupOffset = -1; - for (int i = 0; i < myMod; i++) { - int value = myBuffer.readInt(); - if (value != -1) { - int offset = value + myStartOffset; - if (firstKeyGroupOffset == -1) firstKeyGroupOffset = offset; - lastKeyGroupOffset = offset; - } - } - if (firstKeyGroupOffset == -1) { - return; - } - assert (firstKeyGroupOffset > myStartOffset); - assert (lastKeyGroupOffset > myStartOffset); - assert (lastKeyGroupOffset >= firstKeyGroupOffset); - - int firstValueOffset = -1; - - myBuffer.setPosition(firstKeyGroupOffset); - while (myBuffer.getPosition() <= lastKeyGroupOffset) { - int groupSize = myBuffer.readInt(); - for (int i = 0; i < groupSize; i++) { - dst.add(myKeyProvider.get(myBuffer)); - - int valueOffset = myBuffer.readInt(); /* value offset */ - if( firstValueOffset == -1 ) firstValueOffset = valueOffset + myStartOffset; - } - } - assert myBuffer.getPosition() == firstValueOffset; - } - catch (IOException e) { - LOG.error(e); - } - } - - private int readKeyGroupOffset(int hash) { - myBuffer.setPosition(myStartOffset + 4 /* mod */ + 4 * hash); - int offset = -1; - try { - offset = myBuffer.readInt(); - } - catch (IOException e) { - LOG.error(e); - } - if (offset == -1) return -1; - return offset + myStartOffset; - } - - private int hash(int hashCode) { - return Math.abs(hashCode) % myMod; - } -} diff --git a/platform/platform-impl/src/com/intellij/util/io/ByteBufferMapWriteHandler.java b/platform/platform-impl/src/com/intellij/util/io/ByteBufferMapWriteHandler.java deleted file mode 100644 index 3987c02cb676..000000000000 --- a/platform/platform-impl/src/com/intellij/util/io/ByteBufferMapWriteHandler.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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.util.io; - -import com.intellij.openapi.diagnostic.Logger; - -import java.io.DataOutput; -import java.io.IOException; -import java.util.Arrays; - -class ByteBufferMapWriteHandler { - private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.ByteBufferMapWriteHandler"); - - private final ByteBufferMap.ValueProvider myValueProvider; - private final WriteableMap myMap; - - private final int[] myKeyHashes; - private final int myMod; - private final DataOutput myOut; - - public ByteBufferMapWriteHandler(DataOutput stream, /*ByteBufferMap.KeyProvider keyProvider, */ByteBufferMap.ValueProvider valueProvider, WriteableMap map, double searchFactor) { - myValueProvider = valueProvider; - myMap = map; - - myKeyHashes = myMap.getHashCodesArray(); - int mod = (int)(myKeyHashes.length / searchFactor); - myMod = mod != 0 ? mod : 1; - myOut = stream; - } - - public void execute() throws IOException { - - executeImpl( true ); - } - - public int calcLength() throws IOException { - return executeImpl( false ); - } - - public int executeImpl( boolean write ) throws IOException { - if( write ) myOut.writeInt(myMod); - int offset = 4; - - int[] overflowList = new int[myKeyHashes.length]; - int[] firstOverflowElem = new int[myMod]; - int[] occurs = new int[myMod]; - Arrays.fill(firstOverflowElem, -1); - - // Creating hash table and overflow lists - for( int i = myKeyHashes.length-1; i >= 0; i-- ) { - int hashhash = hash(myKeyHashes[i]); - overflowList[i] = firstOverflowElem[hashhash]; - firstOverflowElem[hashhash] = i; - occurs[hashhash]++; - } - - offset += 4 * myMod; // hash table size - // writing hash table - for( int i = 0; i < myMod; i++ ) { - if( write ) myOut.writeInt( occurs[i] != 0 ? offset : -1 ); - if( occurs[i] != 0 ) offset += 4; // key group size, if key group present - int occurs_i = 0; - for( int j = firstOverflowElem[i]; j != -1; j = overflowList[j] ) { - offset += myMap.getKeyLength( j ) + 4 /* value offset */; - occurs_i++; - } - LOG.assertTrue( occurs_i == occurs[i] ); - } - - // writing key table - for( int i = 0; i < myMod; i++ ) { - if( occurs[i] == 0 ) continue; - - if( write ) myOut.writeInt( occurs[i] ); - for( int j = firstOverflowElem[i]; j != -1; j = overflowList[j] ) { - if( write ) { - myMap.writeKey( myOut, j ); - myOut.writeInt( offset ); - } - V value = myMap.getValue(j); - offset += myValueProvider.length(value); - } - } - - // writing value table - for( int i = 0; i < myMod; i++ ) { - for( int j = firstOverflowElem[i]; j != -1; j = overflowList[j] ) { - V value = myMap.getValue(j); - if( write ) myValueProvider.write( myOut, value ); - } - } - - return offset; // total resulting length - } - - private int hash(int hashCode){ - return Math.abs(hashCode) % myMod; - } -} diff --git a/platform/platform-impl/src/com/intellij/util/io/ByteBufferRADataInput.java b/platform/platform-impl/src/com/intellij/util/io/ByteBufferRADataInput.java deleted file mode 100644 index 65d5474a3c23..000000000000 --- a/platform/platform-impl/src/com/intellij/util/io/ByteBufferRADataInput.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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.util.io; - -import com.intellij.openapi.diagnostic.Logger; - -import java.io.DataInputStream; -import java.io.IOException; -import java.nio.ByteBuffer; - -/** - * @author max - */ -public class ByteBufferRADataInput implements RandomAccessDataInput { - private static final Logger LOG = Logger.getInstance("com.intellij.util.io.ByteBufferRADataInput"); - - private final MappedBufferWrapper myBuffer; - - public ByteBufferRADataInput(MappedBufferWrapper buffer) { - myBuffer = buffer; - } - - public void setPosition(int pos) { - getBuffer().position(pos); - } - - public int getPosition() { - return getBuffer().position(); - } - - public void readFully(byte[] b) throws IOException { - getBuffer().get(b); - } - - public void readFully(byte[] b, int off, int len) throws IOException { - getBuffer().get(b, off, len); - } - - public int skipBytes(int n) throws IOException { - int newPos = getPosition() + n; - setPosition(newPos); - return newPos; - } - - public boolean readBoolean() throws IOException { - return getBuffer().get() == 1; - } - - public byte readByte() throws IOException { - return getBuffer().get(); - } - - public int readUnsignedByte() throws IOException { - return 0xFF & ((int)getBuffer().get()); - } - - public short readShort() throws IOException { - return getBuffer().getShort(); - } - - public int readUnsignedShort() throws IOException { - return 0xFFFF & ((int)getBuffer().getShort()); - } - - public char readChar() throws IOException { - return getBuffer().getChar(); - } - - public int readInt() throws IOException { - return getBuffer().getInt(); - } - - public long readLong() throws IOException { - return getBuffer().getLong(); - } - - public float readFloat() throws IOException { - return getBuffer().getFloat(); - } - - public double readDouble() throws IOException { - return getBuffer().getDouble(); - } - - public String readLine() throws IOException { - LOG.error("Not implemented"); - return null; - } - - public String readUTF() throws IOException { - return DataInputStream.readUTF(this); - } - - public ByteBuffer getBuffer() { - return myBuffer.buf(); - } -} diff --git a/platform/platform-impl/src/com/intellij/util/io/FileKeyProvider.java b/platform/platform-impl/src/com/intellij/util/io/FileKeyProvider.java deleted file mode 100644 index 5bffe1b1d568..000000000000 --- a/platform/platform-impl/src/com/intellij/util/io/FileKeyProvider.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.util.io; - -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.vfs.VirtualFile; -import gnu.trove.TObjectIntHashMap; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -public class FileKeyProvider implements ByteBufferMap.KeyProvider{ - private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.FileKeyProvider"); - - private final VirtualFile[] myFileIndex; - private final TObjectIntHashMap myFileToIndexMap; - - public FileKeyProvider(VirtualFile[] fileIndex, TObjectIntHashMap fileToIndexMap) { - myFileIndex = fileIndex; - myFileToIndexMap = fileToIndexMap; - } - - public int hashCode(VirtualFile key) { - int index = myFileToIndexMap.get(key) - 1; - return index; - } - - public void write(DataOutput out, VirtualFile key) throws IOException { - int index = myFileToIndexMap.get(key) - 1; - LOG.assertTrue(index >= 0); - out.writeInt(index); - } - - public int length(VirtualFile key) { - return 4; - } - - public VirtualFile get(DataInput in) throws IOException { - int index = in.readInt(); - return myFileIndex[index]; - } - - public boolean equals(DataInput in, VirtualFile key) throws IOException { - int index = in.readInt(); - return key.equals(myFileIndex[index]); - } -} diff --git a/platform/platform-impl/src/com/intellij/util/io/IntArrayValueProvider.java b/platform/platform-impl/src/com/intellij/util/io/IntArrayValueProvider.java deleted file mode 100644 index 1a395c0d08ee..000000000000 --- a/platform/platform-impl/src/com/intellij/util/io/IntArrayValueProvider.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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.util.io; - -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.util.ArrayUtil; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -public class IntArrayValueProvider implements ByteBufferMap.ValueProvider { - private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.IntArrayValueProvider"); - public static final IntArrayValueProvider INSTANCE = new IntArrayValueProvider(-1); - - private final int myArraySize; - - public IntArrayValueProvider(int arraySize) { - myArraySize = arraySize; - } - - public void write(DataOutput out, int[] value) throws IOException { - //if (value instanceof IntArrayList) { - // IntArrayList list = (IntArrayList) value; - // LOG.assertTrue(myArraySize == -1 || list.size() == myArraySize); - // if (myArraySize == -1) out.writeInt(list.size()); - // for (int i = 0; i < list.size(); i++) { - // out.writeInt(list.get(i)); - // } - //} else if (value instanceof TIntArrayList) { - // TIntArrayList list = (TIntArrayList) value; - // LOG.assertTrue(myArraySize == -1 || list.size() == myArraySize); - // if (myArraySize == -1) out.writeInt(list.size()); - // for (int i = 0; i < list.size(); i++) { - // out.writeInt(list.get(i)); - // } - //} else { - int[] array = (int[])value; - LOG.assertTrue(myArraySize == -1 || array.length == myArraySize); - if (myArraySize == -1) out.writeInt(array.length); - for(int i = 0; i < array.length; i++){ - out.writeInt(array[i]); - } - //} - } - - public int length(int[] value) { - //if (value instanceof IntArrayList) { - // IntArrayList list = (IntArrayList) value; - // LOG.assertTrue(myArraySize == -1 || list.size() == myArraySize); - // - // if (myArraySize == -1) return 4 * (list.size() + 1); - // - // return 4 * myArraySize; - //} else if (value instanceof TIntArrayList) { - // TIntArrayList list = (TIntArrayList) value; - // LOG.assertTrue(myArraySize == -1 || list.size() == myArraySize); - // - // if (myArraySize == -1) return 4 * (list.size() + 1); - // - // return 4 * myArraySize; - //} else { - int[] array = (int[])value; - LOG.assertTrue(myArraySize == -1 || array.length == myArraySize); - - if (myArraySize == -1) return 4 * (array.length + 1); - - return 4 * myArraySize; - //} - } - - public int[] get(DataInput in) throws IOException { - final int[] result; - - if (myArraySize >= 0) { - result = ArrayUtil.newIntArray(myArraySize); - } else { - result = ArrayUtil.newIntArray(in.readInt()); - } - - for(int i = 0; i < result.length; i++){ - result[i] = in.readInt(); - } - return result; - } -} diff --git a/platform/platform-impl/src/com/intellij/util/io/IntValueProvider.java b/platform/platform-impl/src/com/intellij/util/io/IntValueProvider.java deleted file mode 100644 index 8c30fd88a055..000000000000 --- a/platform/platform-impl/src/com/intellij/util/io/IntValueProvider.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.util.io; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -/** - * @author max - */ -public class IntValueProvider implements ByteBufferMap.ValueProvider { - public static IntValueProvider INSTANCE = new IntValueProvider(); - - private IntValueProvider() { - } - - public void write(DataOutput out, Integer value) throws IOException { - out.writeInt(((Integer)value).intValue()); - } - - public int length(Integer value) { - return 4; - } - - public Integer get(DataInput in) throws IOException { - return new Integer(in.readInt()); - } -} diff --git a/platform/platform-impl/src/com/intellij/util/io/IntegerKeyProvider.java b/platform/platform-impl/src/com/intellij/util/io/IntegerKeyProvider.java deleted file mode 100644 index ff10086a1b74..000000000000 --- a/platform/platform-impl/src/com/intellij/util/io/IntegerKeyProvider.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.util.io; - -import com.intellij.openapi.diagnostic.Logger; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -/** - * @deprecated use {@link ByteBufferIntObjectMap} instead - */ -public class IntegerKeyProvider implements ByteBufferMap.KeyProvider { - private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.StringKeyProvider"); - - public static final IntegerKeyProvider INSTANCE = new IntegerKeyProvider(); - - private IntegerKeyProvider() { - } - - public int hashCode(Integer key) { - return key.hashCode(); - } - - public void write(DataOutput out, Integer key) throws IOException { - out.writeInt(key.intValue()); - } - - public int length(Integer key) { - return 4; - } - - public Integer get(DataInput in) throws IOException { - return new Integer(in.readInt()); - } - - public boolean equals(DataInput in, Integer key) throws IOException { - return key.intValue() == in.readInt(); - } -} diff --git a/platform/platform-impl/src/com/intellij/util/io/StringKeyProvider.java b/platform/platform-impl/src/com/intellij/util/io/StringKeyProvider.java deleted file mode 100644 index f3a7e643aa1e..000000000000 --- a/platform/platform-impl/src/com/intellij/util/io/StringKeyProvider.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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.util.io; - -import com.intellij.openapi.diagnostic.Logger; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.io.UnsupportedEncodingException; - -import org.jetbrains.annotations.NonNls; - -public class StringKeyProvider implements ByteBufferMap.KeyProvider{ - private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.StringKeyProvider"); - - public static final StringKeyProvider INSTANCE = new StringKeyProvider(); - @NonNls public static final String UTF_8_CHARSET_NAME = "UTF-8"; - - private StringKeyProvider() { - } - - public int hashCode(String key) { - return key.hashCode(); - } - - public void write(DataOutput out, String key) throws IOException { - String keyString = (String)key; - byte[] keyBytes = keyString.getBytes(UTF_8_CHARSET_NAME); - out.writeInt(keyBytes.length); - out.write(keyBytes); - } - - public int length(String key) { - try{ - String keyString = (String)key; - byte[] keyBytes = keyString.getBytes(UTF_8_CHARSET_NAME); - return 4 + keyBytes.length; - } - catch(UnsupportedEncodingException e){ - LOG.error(e); - return 0; - } - } - - public String get(DataInput in) throws IOException { - int length = in.readInt(); - byte[] bytes = new byte[length]; - in.readFully(bytes); - try { - return new String(bytes, UTF_8_CHARSET_NAME); - } - catch (UnsupportedEncodingException e) { - LOG.error(e); - return null; - } - } - - public boolean equals(DataInput in, String key) throws IOException { - try { - String keyString = (String)key; - byte[] keyBytes = keyString.getBytes(UTF_8_CHARSET_NAME); - - int length = in.readInt(); - byte[] inputBytes = new byte[length]; - in.readFully(inputBytes); - if (length != keyBytes.length) return false; - for (int i = 0; i < length; i++) { - if (keyBytes[i] != inputBytes[i]) return false; - } - - return true; - } - catch (UnsupportedEncodingException e) { - LOG.error(e); - return false; - } - } -} diff --git a/platform/platform-impl/src/com/intellij/util/io/WriteableMapAdapter.java b/platform/platform-impl/src/com/intellij/util/io/WriteableMapAdapter.java deleted file mode 100644 index 2375d37232e9..000000000000 --- a/platform/platform-impl/src/com/intellij/util/io/WriteableMapAdapter.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.util.io; - -import java.io.DataOutput; -import java.io.IOException; -import java.util.Map; - -/** - * @author max - */ -public class WriteableMapAdapter implements WriteableMap { - private final Map myMap; - private final ByteBufferMap.KeyProvider myKeyProvider; - private final K[] myKeys; - - public WriteableMapAdapter(Map map, ByteBufferMap.KeyProvider provider) { - myMap = map; - myKeyProvider = provider; - myKeys = (K[]) myMap.keySet().toArray(); - } - - public int[] getHashCodesArray() { - int[] keyHashCodes = new int[ myKeys.length ]; - for( int i = 0; i < myKeys.length; i++ ) - keyHashCodes[i] = myKeyProvider.hashCode(myKeys[i]); - return keyHashCodes; - } - - public V getValue( int n ) { - return myMap.get( myKeys[n] ); - } - - public int getKeyLength( int n ) { - return myKeyProvider.length( myKeys[n] ); - } - - public void writeKey( DataOutput out, int n ) throws IOException { - myKeyProvider.write( out, myKeys[n] ); - } -} diff --git a/platform/util/src/com/intellij/util/io/MappedFile.java b/platform/util/src/com/intellij/util/io/MappedFile.java deleted file mode 100644 index 494ffe9fa206..000000000000 --- a/platform/util/src/com/intellij/util/io/MappedFile.java +++ /dev/null @@ -1,355 +0,0 @@ -/* - * 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.util.io; - -import com.intellij.openapi.Forceable; -import com.intellij.openapi.diagnostic.Logger; -import org.jetbrains.annotations.NonNls; - -import java.io.*; -import java.nio.ByteBuffer; -import java.nio.MappedByteBuffer; - -/** - * @author max - */ -public class MappedFile implements Forceable { - private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.MappedFile"); - - private MappedBufferWrapper myHolder; - private final File myFile; - - private long myRealSize; - private long mySize; - private long myPosition; - private boolean myIsDirty = false; - - @NonNls private static final String UTF_8_CHARSET_NAME = "UTF-8"; - @NonNls private static final String RW = "rw"; - private final byte[] buffer = new byte[8]; - - public MappedFile(File file, int initialSize) throws IOException { - myFile = file; - if (!file.exists() || file.length() == 0) { - writeLength(0); - } - - myPosition = 0; - map(); - - mySize = readLength(); - if (mySize == 0) { - resize(initialSize); - } - } - - private long readLength() { - File lengthFile = getLengthFile(); - DataInputStream stream = null; - try { - stream = new DataInputStream(new FileInputStream(lengthFile)); - return stream.readLong(); - } - catch (IOException e) { - writeLength(myRealSize); - return myRealSize; - } - finally { - if (stream != null) { - try { - stream.close(); - } - catch (IOException e) { - LOG.error(e); - } - } - } - } - - private File getLengthFile() { - return new File(myFile.getPath() + ".len"); - } - - private void writeLength(final long len) { - File lengthFile = getLengthFile(); - DataOutputStream stream = null; - try { - stream = new DataOutputStream(new FileOutputStream(lengthFile)); - stream.writeLong(len); - } - catch (FileNotFoundException e) { - LOG.error(e); - } - catch (IOException e) { - LOG.error(e); - } - finally { - if (stream != null) { - try { - stream.close(); - } - catch (IOException e) { - LOG.error(e); - } - } - } - } - - private void map() { - myHolder = new ReadWriteMappedBufferWrapper(myFile); - myRealSize = myFile.length(); - if (LOG.isDebugEnabled()) { - LOG.assertTrue(myPosition > 0L && myPosition < myRealSize || myPosition == 0 && myRealSize == 0, "myPosition=" + myPosition + ", myRealSize=" + myRealSize); - } - myHolder.buf().position((int)myPosition); - } - - public short getShort(int index) throws IOException { - seek(index); - return readShort(); - } - - public short readShort() throws IOException { - get(buffer, 0, 2); - - return Bits.getShort(buffer, 0); - } - - public void putShort(int index, short value) throws IOException { - seek(index); - writeShort(value); - } - - public void writeShort(int value) throws IOException { - Bits.putShort(buffer, 0, (short)value); - put(buffer, 0, 2); - } - - public int getInt(int index) throws IOException { - seek(index); - return readInt(); - } - - public long getLong(final int index) throws IOException { - seek(index); - return readLong(); - } - - public void putInt(int index, int value) throws IOException { - seek(index); - writeInt(value); - } - - public void putLong(final int index, final long value) throws IOException { - seek(index); - writeLong(value); - } - - public byte get(int index) throws IOException { - seek(index); - return readByte(); - } - - public void put(int index, byte value) throws IOException { - seek(index); - writeByte(value); - } - - public void get(int index, byte[] dst, int offset, int length) throws IOException { - seek(index); - get(dst, offset, length); - } - - public void get(final byte[] dst, final int offset, final int length) throws IOException { - if (myPosition + length > mySize) { - throw new EOFException(); - } - - buf().get(dst, offset, length); - myPosition += length; - } - - public void put(int index, byte[] src, int offset, int length) throws IOException { - seek(index); - put(src, offset, length); - } - - public void seek(long pos) throws IOException { - ensureSize(pos); - buf().position((int)pos); - myPosition = pos; - if (pos > mySize) { - mySize = pos; - } - } - - private ByteBuffer buf() { - if (!isMapped()) { - map(); - } - - return myHolder.buf(); - } - - private void ensureSize(final long pos) throws IOException { - while (pos >= myRealSize) { - expand(); - } - } - - private void expand() throws IOException { - resize((int)((myRealSize + 1) * 13) >> 3); - } - - public void put(final byte[] src, final int offset, final int length) throws IOException { - ensureSize(myPosition + length); - myIsDirty = true; - buf().put(src, offset, length); - myPosition += length; - if (myPosition > mySize) { - mySize = myPosition; - } - } - - public void flush() { - if (myIsDirty) { - writeLength(mySize); - final ByteBuffer buf = buf(); - if (buf instanceof MappedByteBuffer) { - MappedBufferWrapper.tryForce(buf); - } - myIsDirty = false; - } - } - - public void force() { - flush(); - } - - public boolean isDirty() { - return myIsDirty; - } - - public void close() { - if (myIsDirty) { - writeLength(mySize); - } - unmap(); - } - - public void resize(int size) throws IOException { - final int current = (int)myRealSize; - if (current == size) return; - unmap(); - RandomAccessFile raf = new RandomAccessFile(myFile, RW); - try { - raf.setLength(size); - } - finally { - raf.close(); - } - map(); - } - - public final long length() { - return mySize; - } - - public long getFilePointer() { - return myPosition; - } - - public int readInt() throws IOException { - get(buffer, 0, 4); - return Bits.getInt(buffer, 0); - } - - public long readLong() throws IOException { - get(buffer, 0, 8); - return Bits.getLong(buffer, 0); - } - - public void writeInt(int value) throws IOException { - Bits.putInt(buffer, 0, value); - put(buffer, 0, 4); - } - - public void writeLong(long value) throws IOException { - Bits.putLong(buffer, 0, value); - put(buffer, 0, 8); - } - - public String readUTF() throws IOException { - try { - int len = readInt(); - byte[] bytes = new byte[ len ]; - get(bytes, 0, len); - return new String(bytes, UTF_8_CHARSET_NAME); - } - catch (UnsupportedEncodingException e) { - // Can't be - return ""; - } - } - - public void writeUTF(String value) throws IOException { - try { - final byte[] bytes = value.getBytes(UTF_8_CHARSET_NAME); - writeInt(bytes.length); - put(bytes, 0, bytes.length); - } - catch (UnsupportedEncodingException e) { - // Can't be - } - } - - public int readUnsignedShort() throws IOException { - get(buffer, 0, 2); - - int ch1 = buffer[0] & 0xff; - int ch2 = buffer[1] & 0xff; - return (ch1 << 8) + ch2; - } - - public char readChar() throws IOException { - return (char)readUnsignedShort(); - } - - public void writeChar(char value) throws IOException { - writeShort(value); - } - - public byte readByte() throws IOException { - get(buffer, 0, 1); - return buffer[0]; - } - - public void writeByte(byte value) throws IOException { - buffer[0] = value; - put(buffer, 0, 1); - } - - private void unmap() { - if (myHolder != null) { - /* flush(); TODO: Don't commit... */ - myHolder.unmap(); - } - } - - public boolean isMapped() { - return myHolder.isMapped(); - } -} From a8ff806528f5b6a1412c355eb2b12fb10294354b Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 3 Dec 2010 13:25:18 +0300 Subject: [PATCH 12/38] Git cancellable tasks. GitTextHandler is started via RunnerMediator and CustomDestroyProcessHandler is attached to the process. GitTextHandler.destroyProcess() now kills the git process tree. GitBinaryHandler is started as it used to. --- .../git4idea/commands/GitBinaryHandler.java | 7 +- .../src/git4idea/commands/GitHandler.java | 9 ++- .../src/git4idea/commands/GitTextHandler.java | 69 ++++++++----------- 3 files changed, 39 insertions(+), 46 deletions(-) diff --git a/plugins/git4idea/src/git4idea/commands/GitBinaryHandler.java b/plugins/git4idea/src/git4idea/commands/GitBinaryHandler.java index a86dbc02ccad..fbd0aa75443f 100644 --- a/plugins/git4idea/src/git4idea/commands/GitBinaryHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitBinaryHandler.java @@ -15,6 +15,7 @@ */ package git4idea.commands; +import com.intellij.execution.ExecutionException; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.VcsException; @@ -82,6 +83,10 @@ public class GitBinaryHandler extends GitHandler { super(project, vcsRoot, command); } + @Override + protected Process startProcess() throws ExecutionException { + return myCommandLine.createProcess(); + } /** * {@inheritDoc} @@ -132,7 +137,7 @@ public class GitBinaryHandler extends GitHandler { * {@inheritDoc} */ @Override - protected void destroyProcess() { + public void destroyProcess() { myProcess.destroy(); } diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java index 900e9d2cb4b5..fa7f28ede7c0 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java @@ -15,6 +15,7 @@ */ package git4idea.commands; +import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; @@ -397,7 +398,7 @@ public abstract class GitHandler { } myCommandLine.setEnvParams(myEnv); // start process - myProcess = myCommandLine.createProcess(); + myProcess = startProcess(); startHandlingStreams(); } catch (Throwable t) { @@ -410,8 +411,10 @@ public abstract class GitHandler { } } + protected abstract Process startProcess() throws ExecutionException; + /** - * Start handling streams for the handler + * Start handling process output streams for the handler. */ protected abstract void startHandlingStreams(); @@ -438,7 +441,7 @@ public abstract class GitHandler { /** * Destroy process */ - protected abstract void destroyProcess(); + public abstract void destroyProcess(); /** * @return exit code for process if it is available diff --git a/plugins/git4idea/src/git4idea/commands/GitTextHandler.java b/plugins/git4idea/src/git4idea/commands/GitTextHandler.java index 8a21b78c5570..9e2c0313d766 100644 --- a/plugins/git4idea/src/git4idea/commands/GitTextHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitTextHandler.java @@ -15,10 +15,13 @@ */ package git4idea.commands; +import com.intellij.execution.ExecutionException; +import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.process.OSProcessHandler; import com.intellij.execution.process.ProcessEvent; +import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.process.ProcessListener; -import com.intellij.openapi.diagnostic.Logger; +import com.intellij.execution.process.RunnerMediator; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; @@ -31,44 +34,29 @@ import java.nio.charset.Charset; * The handler for git commands with text outputs */ public abstract class GitTextHandler extends GitHandler { - /** - * the logger - */ - private static final Logger log = Logger.getInstance(GitTextHandler.class.getName()); - /** * wrapped process handler */ // note that access is safe because it accessed in unsynchronized block only after process is started, and it does not change after that @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) private OSProcessHandler myHandler; - /** - * The constructor from super - * - * @param project the project - * @param directory the command directory - * @param command the command - */ protected GitTextHandler(@NotNull Project project, @NotNull File directory, @NotNull GitCommand command) { super(project, directory, command); } - /** - * The constructor - * - * @param project the project - * @param vcsRoot the vcs root - * @param command the command to run - */ protected GitTextHandler(final Project project, final VirtualFile vcsRoot, final GitCommand command) { super(project, vcsRoot, command); } - /** - * {@inheritDoc} - */ + @Override + protected Process startProcess() throws ExecutionException { + final ProcessHandler processHandler = new MyRunnerMediator().createProcess(myCommandLine); + assert processHandler instanceof MyOSProcessHandler; + myHandler = (MyOSProcessHandler)processHandler; + return myHandler.getProcess(); + } + protected void startHandlingStreams() { - myHandler = new MyOSProcessHandler(myProcess, myCommandLine.getCommandLineString(), getCharset()); myHandler.addProcessListener(new ProcessListener() { public void startNotified(final ProcessEvent event) { // do nothing @@ -108,31 +96,28 @@ public abstract class GitTextHandler extends GitHandler { */ protected abstract void onTextAvailable(final String text, final Key outputType); - /** - * {@inheritDoc} - */ - protected void destroyProcess() { - try { - myHandler.destroyProcess(); - } - catch (Exception e) { - log.warn("Exception during cancel", e); - } + public void destroyProcess() { + myHandler.destroyProcess(); } - /** - * {@inheritDoc} - */ protected void waitForProcess() { - OSProcessHandler handler = myHandler; - myHandler = null; - handler.waitFor(); + myHandler.waitFor(); } - private static class MyOSProcessHandler extends OSProcessHandler { + /** + * RunnerMediator that attaches our MyProcessHandler to the process instead of the standard CustomDestroyProcessHandler. + */ + private class MyRunnerMediator extends RunnerMediator { + @Override + protected ProcessHandler createProcessHandler(@NotNull Process process, @NotNull GeneralCommandLine commandLine) { + return new MyOSProcessHandler(process, commandLine, getCharset()); + } + } + + private static class MyOSProcessHandler extends RunnerMediator.CustomDestroyProcessHandler { private final Charset myCharset; - public MyOSProcessHandler(Process process, String commandLine, Charset charset) { + public MyOSProcessHandler(Process process, GeneralCommandLine commandLine, Charset charset) { super(process, commandLine); myCharset = charset; } From cac0e2bf4135cf68898b1d37a8124b328e6c0c09 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 3 Dec 2010 13:26:51 +0300 Subject: [PATCH 13/38] Git cancellable tasks. Introduced class GitTask which handles the native git tasking for GitHandler and stops it when progress indicator is cancelled by user (checks the indicator with a java.util.Timer). GitTaskResult - basic enum to handler results. --- .../src/git4idea/commands/GitTask.java | 260 ++++++++++++++++++ .../src/git4idea/commands/GitTaskResult.java | 27 ++ 2 files changed, 287 insertions(+) create mode 100644 plugins/git4idea/src/git4idea/commands/GitTask.java create mode 100644 plugins/git4idea/src/git4idea/commands/GitTaskResult.java diff --git a/plugins/git4idea/src/git4idea/commands/GitTask.java b/plugins/git4idea/src/git4idea/commands/GitTask.java new file mode 100644 index 000000000000..85a288f11983 --- /dev/null +++ b/plugins/git4idea/src/git4idea/commands/GitTask.java @@ -0,0 +1,260 @@ +/* + * Copyright 2000-2010 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 com.intellij.openapi.Disposable; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.vcs.VcsException; +import git4idea.GitVcs; +import git4idea.i18n.GitBundle; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.atomic.AtomicReference; + +/** + * A Task to run the given GitHandler with ability to cancel it. + * Cancellation is implemented with a {@link java.util.Timer} which checks whether the ProgressIndicator was cancelled and kills + * the GitHandler in that case. + * + * A GitTask may be executed synchronously ({@link #execute()} or asynchronously ({@link #executeAsync(GitTask.ResultHandler)}. + * Result of the execution is encapsulated in {@link GitTaskResult}. + * + * @see {@link git4idea.commands.GitHandler#kill()} + * @author Kirill Likhodedov + */ +public class GitTask { + + private final Project myProject; + private final GitHandler myHandler; + private final String myTitle; + private final AtomicReference myResult = new AtomicReference(GitTaskResult.INITIAL); + + public interface ResultHandler { + void run(GitTaskResult result); + } + + public GitTask(Project project, GitHandler handler, String title) { + myProject = project; + myHandler = handler; + myTitle = title; + } + + /** + * Executes this task synchronously, with a modal progress dialog. + * @return Result of the task execution. + */ + public GitTaskResult execute() { + ModalTask task = new ModalTask(myProject, myHandler, myTitle) { + public void execute(ProgressIndicator indicator) { + GitHandlerUtil.runInCurrentThread(myHandler, indicator, true, myTitle); + } + + @Override + public void onSuccess() { + if (!myHandler.errors().isEmpty()) { + myResult.set(GitTaskResult.GIT_ERROR); + } else { + myResult.set(GitTaskResult.OK); + } + } + + @Override + public void onCancel() { + myResult.set(GitTaskResult.CANCELLED); + } + }; + + addListeners(task); + ProgressManager.getInstance().run(task); + return myResult.get(); + } + + /** + * Executes this task asynchronously, in backgrond. Calls the resultHandler when finished. + * @param resultHandler callback called after the task has finished or was cancelled by user or automatically. + */ + public void executeAsync(final ResultHandler resultHandler) { + BackgroundableTask task = new BackgroundableTask(myProject, myHandler, myTitle) { + public void execute(ProgressIndicator indicator) { + GitHandlerUtil.runInCurrentThread(myHandler, indicator, true, myTitle); + } + + @Override + public void onSuccess() { + if (!myHandler.errors().isEmpty()) { // TODO: handle errors smarter: an error may be not a complete failure. + myResult.set(GitTaskResult.GIT_ERROR); + } else { + myResult.set(GitTaskResult.OK); + } + resultHandler.run(myResult.get()); + } + + @Override + public void onCancel() { + myResult.set(GitTaskResult.CANCELLED); + resultHandler.run(GitTaskResult.CANCELLED); + } + }; + + addListeners(task); + GitVcs.getInstance(myProject).runInBackground(task); + } + + private void addListeners(final TaskExecution task) { + // When receives an error line, adds a VcsException to the GitHandler. + final GitLineHandlerListener errorListener = new GitLineHandlerListener() { + @Override + public void processTerminated(int exitCode) { + if (exitCode != 0 && !myHandler.isIgnoredErrorCode(exitCode)) { + if (myHandler.errors().isEmpty()) { + myHandler.addError(new VcsException(GitBundle.message("git.error.exit", exitCode))); + } + } + } + + @Override + public void startFailed(Throwable exception) { + myHandler.addError(new VcsException("Git start failed: " + exception.getMessage(), exception)); + } + + @Override + public void onLineAvailable(String line, Key outputType) { + if (GitHandlerUtil.isErrorLine(line.trim())) { + myHandler.addError(new VcsException(line)); + } + } + }; + + myHandler.addListener(errorListener); + if (myHandler instanceof GitLineHandler) { + ((GitLineHandler)myHandler).addLineListener(errorListener); + } + + // disposes the timer + myHandler.addListener(new GitHandlerListener() { + @Override + public void processTerminated(int exitCode) { + task.dispose(); + } + + @Override + public void startFailed(Throwable exception) { + task.dispose(); + } + }); + } + + /** + * We're using this interface here to work with Task, because standard {@link Task#run(com.intellij.openapi.progress.ProgressIndicator)} + * is busy with timers. + */ + private interface TaskExecution { + void execute(ProgressIndicator indicator); + void dispose(); + } + + // To add to {@link com.intellij.openapi.progress.BackgroundTaskQueue} a task must be {@link Task.Backgroundable}, + // so we can't have a single class representing a task: we have BackgroundableTask and ModalTask. + // To minimize code duplication we use GitTaskDelegate. + + private abstract class BackgroundableTask extends Task.Backgroundable implements TaskExecution { + private GitTaskDelegate myDelegate; + + public BackgroundableTask(@Nullable final Project project, @NotNull GitHandler handler, @NotNull final String processTitle) { + super(project, processTitle, true); + myDelegate = new GitTaskDelegate(myProject, handler, this); + } + + @Override + public final void run(@NotNull ProgressIndicator indicator) { + myDelegate.run(indicator); + } + + @Override + public void dispose() { + Disposer.dispose(myDelegate); + } + } + + private abstract class ModalTask extends Task.Modal implements TaskExecution { + private GitTaskDelegate myDelegate; + + public ModalTask(@Nullable final Project project, @NotNull GitHandler handler, @NotNull final String processTitle) { + super(project, processTitle, true); + myDelegate = new GitTaskDelegate(myProject, handler, this); + } + + @Override + public final void run(@NotNull ProgressIndicator indicator) { + myDelegate.run(indicator); + } + + @Override + public void dispose() { + Disposer.dispose(myDelegate); + } + } + + /** + * Does the work which is common for BackgrounableTask and ModalTask. + * Actually - starts a timer which checks if current progress indicator is cancelled. + * If yes, kills the GitHandler. + */ + private static class GitTaskDelegate implements Disposable { + private GitHandler myHandler; + private ProgressIndicator myIndicator; + private TaskExecution myTask; + private Timer myTimer; + private Project myProject; + + public GitTaskDelegate(Project project, GitHandler handler, TaskExecution task) { + myProject = project; + myHandler = handler; + myTask = task; + Disposer.register(myProject, this); + } + + public void run(ProgressIndicator indicator) { + myIndicator = indicator; + myTimer = new Timer(); + myTimer.schedule(new TimerTask() { + @Override + public void run() { + if (myIndicator != null && myIndicator.isCanceled()) { + if (myHandler != null) { + myHandler.destroyProcess(); + } + Disposer.dispose(GitTaskDelegate.this); + } + } + }, 0, 200); + myTask.execute(indicator); + } + + public void dispose() { + myTimer.cancel(); + } + } + +} diff --git a/plugins/git4idea/src/git4idea/commands/GitTaskResult.java b/plugins/git4idea/src/git4idea/commands/GitTaskResult.java new file mode 100644 index 000000000000..864a7b739d36 --- /dev/null +++ b/plugins/git4idea/src/git4idea/commands/GitTaskResult.java @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2010 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; + +/** +* @author Kirill Likhodedov +*/ +public enum GitTaskResult { + INITIAL, WORKING, OK, EXCEPTION, GIT_ERROR, TIMEOUT, CANCELLED, TERMINATED; + + public boolean isOK() { + return this == OK; + } +} From f38aa2e48243dafe5672e138860b27621fc3e958 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 3 Dec 2010 13:27:29 +0300 Subject: [PATCH 14/38] Git cancellable tasks: using it in testing remote repository (in GitCloneDialog) and checkouting from git. --- .../checkout/GitCheckoutProvider.java | 36 +++++++++---------- .../src/git4idea/checkout/GitCloneDialog.java | 27 +++++++++----- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java b/plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java index cd97d1bf84f2..db814e08ebf9 100644 --- a/plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java +++ b/plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java @@ -15,9 +15,7 @@ */ package git4idea.checkout; -import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.CheckoutProvider; import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; @@ -28,6 +26,8 @@ import git4idea.actions.BasicAction; import git4idea.commands.GitCommand; import git4idea.commands.GitHandlerUtil; import git4idea.commands.GitLineHandler; +import git4idea.commands.GitTask; +import git4idea.commands.GitTaskResult; import git4idea.config.GitVersion; import git4idea.i18n.GitBundle; import org.jetbrains.annotations.NotNull; @@ -74,26 +74,26 @@ public class GitCheckoutProvider implements CheckoutProvider { final String originName, final String parentDirectory) { final GitLineHandler handler = clone(project, sourceRepositoryURL, new File(parentDirectory), directoryName, originName); - handler.addLineListener(new GitHandlerUtil.GitLineHandlerListenerProgress(ProgressManager.getInstance().getProgressIndicator(), handler, "git clone", true)); - new Task.Backgroundable(project, GitBundle.message("cloning.repository", sourceRepositoryURL), true) { - @Override public void run(@NotNull ProgressIndicator indicator) { - GitHandlerUtil.runInCurrentThread(handler, indicator, true, "git clone"); - } - @Override public void onSuccess() { - destinationParent.refresh(true, true, new Runnable() { - public void run() { - if (project.isOpen() && (! project.isDisposed()) && (! project.isDefault())) { - final VcsDirtyScopeManager mgr = VcsDirtyScopeManager.getInstance(project); - mgr.fileDirty(destinationParent); + GitTask task = new GitTask(project, handler, GitBundle.message("cloning.repository", sourceRepositoryURL)); + task.executeAsync(new GitTask.ResultHandler() { + @Override + public void run(GitTaskResult result) { + if (result == GitTaskResult.OK) { + destinationParent.refresh(true, true, new Runnable() { + public void run() { + if (project.isOpen() && (!project.isDisposed()) && (!project.isDefault())) { + final VcsDirtyScopeManager mgr = VcsDirtyScopeManager.getInstance(project); + mgr.fileDirty(destinationParent); + } } - } - }); - listener.directoryCheckedOut(new File(parentDirectory, directoryName)); - listener.checkoutCompleted(); + }); + listener.directoryCheckedOut(new File(parentDirectory, directoryName)); + listener.checkoutCompleted(); + } } - }.queue(); + }); } /** diff --git a/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java b/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java index fbbe62c3045c..2b5b3f48a31f 100644 --- a/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java +++ b/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java @@ -17,16 +17,24 @@ package git4idea.checkout; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.*; +import com.intellij.openapi.ui.ComponentWithBrowseButton; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.ui.TextComponentAccessor; +import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.vfs.VirtualFile; import git4idea.commands.GitCommand; -import git4idea.commands.GitHandlerUtil; import git4idea.commands.GitSimpleHandler; +import git4idea.commands.GitTask; +import git4idea.commands.GitTaskResult; import git4idea.i18n.GitBundle; import git4idea.validators.GitBranchNameValidator; import org.jetbrains.annotations.NonNls; -import javax.swing.*; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JTextField; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import java.awt.event.ActionEvent; @@ -163,14 +171,17 @@ public class GitCloneDialog extends DialogWrapper { myTestButton.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { myTestURL = myRepositoryURL.getText(); - String output = GitHandlerUtil - .doSynchronously(checkRepository(myProject, myTestURL), GitBundle.message("clone.testing", myTestURL), "connection test"); - if (output != null) { + GitSimpleHandler handler = new GitSimpleHandler(myProject, new File("."), GitCommand.LS_REMOTE); + handler.addParameters(myTestURL, "master"); + + GitTask task = new GitTask(myProject, handler, GitBundle.message("clone.testing", myTestURL)); + GitTaskResult result = task.execute(); + + if (result.isOK()) { Messages.showInfoMessage(myTestButton, GitBundle.message("clone.test.success.message", myTestURL), GitBundle.getString("clone.test.success")); myTestResult = Boolean.TRUE; - } - else { + } else { myTestResult = Boolean.FALSE; } updateOkButton(); From f29f249265e49ed9ea44bf5b65a17d04a0328f44 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Thu, 9 Dec 2010 18:28:51 +0300 Subject: [PATCH 15/38] GitTextHandler: no need in assert. --- plugins/git4idea/src/git4idea/commands/GitTextHandler.java | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/git4idea/src/git4idea/commands/GitTextHandler.java b/plugins/git4idea/src/git4idea/commands/GitTextHandler.java index 9e2c0313d766..89f61e383390 100644 --- a/plugins/git4idea/src/git4idea/commands/GitTextHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitTextHandler.java @@ -51,7 +51,6 @@ public abstract class GitTextHandler extends GitHandler { @Override protected Process startProcess() throws ExecutionException { final ProcessHandler processHandler = new MyRunnerMediator().createProcess(myCommandLine); - assert processHandler instanceof MyOSProcessHandler; myHandler = (MyOSProcessHandler)processHandler; return myHandler.getProcess(); } From aac4ec7851d9ff1ce32ac594ecf45f6d9244a6be Mon Sep 17 00:00:00 2001 From: Oleg Shpynov Date: Fri, 10 Dec 2010 16:01:47 +0300 Subject: [PATCH 16/38] Remove limitation on the master branch --- .../plugins/github/GithubRebaseAction.java | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java index fe1c677fc9e6..6796a0f969ec 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java @@ -26,7 +26,6 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; -import git4idea.GitBranch; import git4idea.GitRemote; import git4idea.GitUtil; import git4idea.actions.BasicAction; @@ -76,18 +75,6 @@ public class GithubRebaseAction extends DumbAwareAction { } try { - // Check current branch - final GitBranch currentBranch = GitBranch.current(project, root); - if (currentBranch == null) { - Messages.showErrorDialog(project, "Cannot find current branch", "Cannot perform github rebase"); - return; - } - if (!"master".equals(currentBranch.getName())) { - Messages.showErrorDialog(project, "Cannot perform rebase with '" + currentBranch.getName() + "' branch.\nPlease switch to master", - "Cannot perform github rebase"); - return; - } - // Check that given repository is properly configured git repository GitRemote githubRemote = null; final List gitRemotes = GitRemote.list(project, root); From a8ecdbf807c7441f361e667f6de3e8d6aa55f667 Mon Sep 17 00:00:00 2001 From: Oleg Shpynov Date: Fri, 10 Dec 2010 17:06:32 +0300 Subject: [PATCH 17/38] DRY --- .../plugins/github/GithubRebaseAction.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java index 6796a0f969ec..449ef30de2c8 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java @@ -44,6 +44,7 @@ import java.util.List; public class GithubRebaseAction extends DumbAwareAction { public static final Icon ICON = IconLoader.getIcon("/icons/github.png"); private static final Logger LOG = Logger.getInstance(GithubRebaseAction.class.getName()); + private static final String CANNOT_PERFORM_GITHUB_REBASE = "Cannot perform github rebase"; public GithubRebaseAction() { super("Rebase my fork", "Rebase your forked repository relative to the origin", ICON); @@ -63,14 +64,14 @@ public class GithubRebaseAction extends DumbAwareAction { final Project project = e.getData(PlatformDataKeys.PROJECT); final VirtualFile[] roots = ProjectRootManager.getInstance(project).getContentRoots(); if (roots.length == 0) { - Messages.showErrorDialog(project, "Project doesn't have any project roots", "Cannot create new GitHub repository"); + Messages.showErrorDialog(project, "Project doesn't have any project roots", CANNOT_PERFORM_GITHUB_REBASE); return; } final VirtualFile root = roots[0]; // Check if git is already initialized and presence of remote branch final boolean gitDetected = GitUtil.isUnderGit(root); if (!gitDetected) { - Messages.showErrorDialog(project, "Cannot find any git repository configured for the project", "Cannot perform github rebase"); + Messages.showErrorDialog(project, "Cannot find any git repository configured for the project", CANNOT_PERFORM_GITHUB_REBASE); return; } @@ -79,7 +80,7 @@ public class GithubRebaseAction extends DumbAwareAction { GitRemote githubRemote = null; final List gitRemotes = GitRemote.list(project, root); if (gitRemotes.isEmpty()) { - Messages.showErrorDialog(project, "Git repository doesn't have any remotes configured", "Cannot perform github rebase"); + Messages.showErrorDialog(project, "Git repository doesn't have any remotes configured", CANNOT_PERFORM_GITHUB_REBASE); return; } for (GitRemote gitRemote : gitRemotes) { @@ -89,7 +90,7 @@ public class GithubRebaseAction extends DumbAwareAction { } } if (githubRemote == null) { - Messages.showErrorDialog(project, "Configured own github repository is not found", "Cannot perform github rebase"); + Messages.showErrorDialog(project, "Configured own github repository is not found", CANNOT_PERFORM_GITHUB_REBASE); return; } @@ -98,7 +99,7 @@ public class GithubRebaseAction extends DumbAwareAction { final int index = pushUrl.lastIndexOf(login); if (index == -1) { Messages.showErrorDialog(project, "Github remote repository doesn't seem to be your own repository: " + pushUrl, - "Cannot perform github rebase"); + CANNOT_PERFORM_GITHUB_REBASE); return; } String repoName = pushUrl.substring(index + login.length() + 1); @@ -109,12 +110,12 @@ public class GithubRebaseAction extends DumbAwareAction { final RepositoryInfo repositoryInfo = GithubUtil.getDetailedRepositoryInfo(project, repoName); if (repositoryInfo == null) { Messages - .showErrorDialog(project, "Github repository doesn't seem to be your own repository: " + pushUrl, "Cannot perform github rebase"); + .showErrorDialog(project, "Github repository doesn't seem to be your own repository: " + pushUrl, CANNOT_PERFORM_GITHUB_REBASE); return; } if (!repositoryInfo.isFork()) { - Messages.showErrorDialog(project, "Github repository '" + repoName + "' is not a forked one", "Cannot perform github rebase"); + Messages.showErrorDialog(project, "Github repository '" + repoName + "' is not a forked one", CANNOT_PERFORM_GITHUB_REBASE); return; } @@ -148,7 +149,7 @@ public class GithubRebaseAction extends DumbAwareAction { addRemoteHandler.addParameters("add", repoName, parentRepoUrl); addRemoteHandler.run(); if (addRemoteHandler.getExitCode() != 0) { - Messages.showErrorDialog("Failed to add GitHub remote: '" + parentRepoUrl + "'", "Failed to add GitHub remote"); + Messages.showErrorDialog("Failed to add GitHub remote: '" + parentRepoUrl + "'", CANNOT_PERFORM_GITHUB_REBASE); return; } @@ -162,7 +163,7 @@ public class GithubRebaseAction extends DumbAwareAction { action.actionPerformed(actionEvent); } catch (VcsException e1) { - Messages.showErrorDialog(project, "Error happened during git operation: " + e1.getMessage(), "Cannot perform github rebase"); + Messages.showErrorDialog(project, "Error happened during git operation: " + e1.getMessage(), CANNOT_PERFORM_GITHUB_REBASE); return; } } From 71fe23e0db7e494b58db17dfb73d5cc7c236fff6 Mon Sep 17 00:00:00 2001 From: Oleg Shpynov Date: Fri, 10 Dec 2010 17:37:04 +0300 Subject: [PATCH 18/38] Open in browser action --- plugins/github/src/META-INF/plugin.xml | 3 + .../github/GithubOpenInBrowserAction.java | 132 ++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java diff --git a/plugins/github/src/META-INF/plugin.xml b/plugins/github/src/META-INF/plugin.xml index c001c3a27454..fef2a86bae91 100644 --- a/plugins/github/src/META-INF/plugin.xml +++ b/plugins/github/src/META-INF/plugin.xml @@ -23,6 +23,9 @@ + + + \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java new file mode 100644 index 000000000000..4e028514198b --- /dev/null +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java @@ -0,0 +1,132 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.github; + +import com.intellij.ide.BrowserUtil; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.DumbAwareAction; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vfs.VirtualFile; +import git4idea.GitRemote; +import git4idea.GitUtil; + +import javax.swing.*; +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * + * @author oleg + * @date 12/10/10 + */ +public class GithubOpenInBrowserAction extends DumbAwareAction { + public static final Icon ICON = IconLoader.getIcon("/icons/github.png"); + private static final Logger LOG = Logger.getInstance(GithubOpenInBrowserAction.class.getName()); + private static final String CANNOT_OPEN_IN_BROWSER = "Cannot open in browser"; + + protected GithubOpenInBrowserAction() { + super("Open in browser", "Open corresponding GitHub link in browser", ICON); + } + + @Override + public void update(final AnActionEvent e) { + final Project project = e.getData(PlatformDataKeys.PROJECT); + final VirtualFile virtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE); + if (project == null || project.isDefault() || virtualFile == null) { + e.getPresentation().setEnabled(false); + return; + } + e.getPresentation().setEnabled(true); + } + + @Override + public void actionPerformed(final AnActionEvent e) { + final Project project = e.getData(PlatformDataKeys.PROJECT); + + final VirtualFile[] roots = ProjectRootManager.getInstance(project).getContentRoots(); + if (roots.length == 0) { + Messages.showErrorDialog(project, "Project doesn't have any project roots", CANNOT_OPEN_IN_BROWSER); + return; + } + final VirtualFile root = roots[0]; + // Check if git is already initialized and presence of remote branch + final boolean gitDetected = GitUtil.isUnderGit(root); + if (!gitDetected) { + Messages.showErrorDialog(project, "Cannot find any git repository configured for the project", CANNOT_OPEN_IN_BROWSER); + return; + } + final VirtualFile virtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE); + final String rootPath = root.getPath(); + final String path = virtualFile.getPath(); + if (!path.startsWith(rootPath)){ + Messages.showErrorDialog(project, "File is not under project root", CANNOT_OPEN_IN_BROWSER); + return; + } + + + try { + // Check that given repository is properly configured git repository + GitRemote githubRemote = null; + final List gitRemotes = GitRemote.list(project, root); + if (gitRemotes.isEmpty()) { + Messages.showErrorDialog(project, "Git repository doesn't have any remotes configured", CANNOT_OPEN_IN_BROWSER); + return; + } + for (GitRemote gitRemote : gitRemotes) { + if (gitRemote.pushUrl().contains("git@github.com")) { + githubRemote = gitRemote; + break; + } + } + if (githubRemote == null) { + Messages.showErrorDialog(project, "Configured own github repository is not found", CANNOT_OPEN_IN_BROWSER); + return; + } + + final String pushUrl = githubRemote.pushUrl(); + final String login = GithubSettings.getInstance().getLogin(); + final int index = pushUrl.lastIndexOf(login); + if (index == -1) { + Messages.showErrorDialog(project, "Github remote repository doesn't seem to be your own repository: " + pushUrl, + CANNOT_OPEN_IN_BROWSER); + return; + } + String repoName = pushUrl.substring(index + login.length() + 1); + if (repoName.endsWith(".git")) { + repoName = repoName.substring(0, repoName.length() - 4); + } + final RepositoryInfo repositoryInfo = GithubUtil.getDetailedRepositoryInfo(project, repoName); + if (repositoryInfo == null) { + Messages + .showErrorDialog(project, "Github repository doesn't seem to be your own repository: " + pushUrl, CANNOT_OPEN_IN_BROWSER); + return; + } + // TODO[oleg] support custom branches here + BrowserUtil.launchBrowser("https://github.com/" + login + "/" + repoName + "/blob/master" + path.substring(rootPath.length())); + + } catch (VcsException e1){ + Messages.showErrorDialog(project, "Error happened during git operation: " + e1.getMessage(), CANNOT_OPEN_IN_BROWSER); + return; + } + + } +} From 1503b4ce9d7c015e000add555da7612e6e175e9e Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 10 Dec 2010 15:57:51 +0300 Subject: [PATCH 19/38] version number and JDK requirements updated --- bin/win/idea.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/win/idea.bat b/bin/win/idea.bat index 632ae9142b2d..b849c97c2729 100644 --- a/bin/win/idea.bat +++ b/bin/win/idea.bat @@ -6,7 +6,7 @@ :: --------------------------------------------------------------------- :: Before you run IntelliJ IDEA specify the location of the -:: JDK 1.5 installation directory which will be used for running IDEA +:: JDK 1.6 installation directory which will be used for running IDEA :: --------------------------------------------------------------------- IF "%IDEA_JDK%" == "" SET IDEA_JDK=%JDK_HOME% IF "%IDEA_JDK%" == "" goto error From c7f838f2004b1358a3b5114d5b3c93135b099af4 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 10 Dec 2010 16:01:03 +0300 Subject: [PATCH 20/38] move Linux installation instructions to CE --- build/Install-Linux-tar.txt | 51 +++++++++++++++++++++++++++++++++++++ build/scripts/dist.gant | 1 + 2 files changed, 52 insertions(+) create mode 100644 build/Install-Linux-tar.txt diff --git a/build/Install-Linux-tar.txt b/build/Install-Linux-tar.txt new file mode 100644 index 000000000000..d51b005ba33d --- /dev/null +++ b/build/Install-Linux-tar.txt @@ -0,0 +1,51 @@ +IntelliJ IDEA + +INSTALLATION INSTRUCTIONS +=============================================================================== + + Linux Installation Instructions + ------------------------------------------------------------------------------ + 1. Unpack the IntelliJ IDEA distribution file that you downloaded to + where you wish to install the program. We will refer to this destination + location as your {installation home} below. + + 2. Open a console and cd into "{installation home}/bin" and type: + + ./idea.sh + + to start the application. + + 3. [OPTIONAL] Add the "{installation home}/bin" to your PATH environmental + variable so that you may start IntelliJ IDEA from any directory. + + 4. [OPTIONAL] To adjust the value of JVM heap size open idea.vmoptions and + modify the -Xms and -Xmx parameters. + + + [OPTIONAL] Changing location of "config" and "system" directory + ------------------------------------------------------------------------------ + By default IDEA stores all your settings under ~/.IntelliJIdea10/config directory + and stores data cache under ~/.IntelliJIdea10/system directory. + If you want to change these settings, + + 1. Open a console and cd into "{installation home}/bin" + + 2. Open file "idea.properties" in an editor. You should find strings like + + idea.system.path=~/.IntelliJIdea10/system + + and + + idea.config.path=~/.IntelliJIdea10/config + + and change them. + + 3. Note that we recommend to store data cache ("system" directory) at a disk + with at least 1G bytes free space + + + + +Enjoy! + +-IntelliJ IDEA Development Team diff --git a/build/scripts/dist.gant b/build/scripts/dist.gant index d2635baf3b05..bd8d82c0364d 100644 --- a/build/scripts/dist.gant +++ b/build/scripts/dist.gant @@ -198,6 +198,7 @@ def layoutLinux(Map args, String home, Paths paths) { fileset(dir: "$home/bin/nix") fileset(dir: "$home/build/images") } + fileset(dir: "$home/build", includes: "Install-Linux-tar.txt") } patchPropertiesFile(paths.distUnix) From 423d9b1fc1973fbfd251e98ca762a2b235154d8d Mon Sep 17 00:00:00 2001 From: Oleg Shpynov Date: Fri, 10 Dec 2010 18:01:10 +0300 Subject: [PATCH 21/38] Disable github share and option actions in non github bound project --- .../github/GithubOpenInBrowserAction.java | 4 +++ .../plugins/github/GithubRebaseAction.java | 21 ++++--------- .../jetbrains/plugins/github/GithubUtil.java | 31 +++++++++++++++++++ 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java index 4e028514198b..872557ced4ac 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java @@ -55,6 +55,10 @@ public class GithubOpenInBrowserAction extends DumbAwareAction { e.getPresentation().setEnabled(false); return; } + if (GithubUtil.getGithubBoundRepository(project) == null){ + e.getPresentation().setEnabled(false); + return; + } e.getPresentation().setEnabled(true); } diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java index 449ef30de2c8..89defbbbe16e 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java @@ -56,6 +56,10 @@ public class GithubRebaseAction extends DumbAwareAction { e.getPresentation().setEnabled(false); return; } + if (GithubUtil.getGithubBoundRepository(project) == null){ + e.getPresentation().setEnabled(false); + return; + } e.getPresentation().setEnabled(true); } @@ -77,22 +81,9 @@ public class GithubRebaseAction extends DumbAwareAction { try { // Check that given repository is properly configured git repository - GitRemote githubRemote = null; + final GitRemote githubRemote = GithubUtil.getGithubBoundRepository(project); final List gitRemotes = GitRemote.list(project, root); - if (gitRemotes.isEmpty()) { - Messages.showErrorDialog(project, "Git repository doesn't have any remotes configured", CANNOT_PERFORM_GITHUB_REBASE); - return; - } - for (GitRemote gitRemote : gitRemotes) { - if (gitRemote.pushUrl().contains("git@github.com")) { - githubRemote = gitRemote; - break; - } - } - if (githubRemote == null) { - Messages.showErrorDialog(project, "Configured own github repository is not found", CANNOT_PERFORM_GITHUB_REBASE); - return; - } + LOG.assertTrue(githubRemote != null); final String pushUrl = githubRemote.pushUrl(); final String login = GithubSettings.getInstance().getLogin(); diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java index b9bda80682de..45c2e8585af4 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java @@ -5,9 +5,14 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vfs.VirtualFile; +import git4idea.GitRemote; +import git4idea.GitUtil; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.UsernamePasswordCredentials; @@ -236,4 +241,30 @@ public class GithubUtil { return null; } } + + @Nullable + public static GitRemote getGithubBoundRepository(final Project project){ + final VirtualFile[] roots = ProjectRootManager.getInstance(project).getContentRoots(); + if (roots.length == 0) { + return null; + } + final VirtualFile root = roots[0]; + // Check if git is already initialized and presence of remote branch + final boolean gitDetected = GitUtil.isUnderGit(root); + if (!gitDetected) { + return null; + } + try { + // Check that given repository is properly configured git repository + final List gitRemotes = GitRemote.list(project, root); + for (GitRemote gitRemote : gitRemotes) { + if (gitRemote.pushUrl().contains("git@github.com")) { + return gitRemote; + } + } + } catch (VcsException e){ + // ignore + } + return null; + } } From 5f90138e33226d7b1e4d65e3fbef334abb56a7f6 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 10 Dec 2010 18:09:01 +0300 Subject: [PATCH 22/38] update keymap URL (IDEA-62851) --- community-resources/src/idea/IdeaApplicationInfo.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/community-resources/src/idea/IdeaApplicationInfo.xml b/community-resources/src/idea/IdeaApplicationInfo.xml index 1bcdca8d3b40..3ab6ac4dd875 100644 --- a/community-resources/src/idea/IdeaApplicationInfo.xml +++ b/community-resources/src/idea/IdeaApplicationInfo.xml @@ -18,8 +18,8 @@ - + From b455facd0b4753411783b6da9d7d2c00332e685c Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Fri, 10 Dec 2010 18:30:08 +0300 Subject: [PATCH 23/38] IDEA-62762 increase default ddms timeout [rev=nnmatveev] --- plugins/android/src/org/jetbrains/android/sdk/AndroidSdk.java | 2 ++ .../android/src/org/jetbrains/android/util/AndroidUtils.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/android/src/org/jetbrains/android/sdk/AndroidSdk.java b/plugins/android/src/org/jetbrains/android/sdk/AndroidSdk.java index 6ccea9c53dda..079fdfc678d1 100644 --- a/plugins/android/src/org/jetbrains/android/sdk/AndroidSdk.java +++ b/plugins/android/src/org/jetbrains/android/sdk/AndroidSdk.java @@ -17,6 +17,7 @@ package org.jetbrains.android.sdk; import com.android.ddmlib.AndroidDebugBridge; +import com.android.ddmlib.DdmPreferences; import com.android.sdklib.IAndroidTarget; import com.android.sdklib.ISdkLog; import com.android.sdklib.SdkConstants; @@ -145,6 +146,7 @@ public abstract class AndroidSdk { String adbPath = getAdbPath(); if (!myDdmLibInitialized) { myDdmLibInitialized = true; + DdmPreferences.setTimeOut(AndroidUtils.TIMEOUT); AndroidDebugBridge.init(AndroidEnableDdmsAction.isDdmsEnabled()); AndroidDebugBridge.createBridge(adbPath, true); } diff --git a/plugins/android/src/org/jetbrains/android/util/AndroidUtils.java b/plugins/android/src/org/jetbrains/android/util/AndroidUtils.java index 38eda83180d4..282462bf5874 100644 --- a/plugins/android/src/org/jetbrains/android/util/AndroidUtils.java +++ b/plugins/android/src/org/jetbrains/android/util/AndroidUtils.java @@ -119,7 +119,7 @@ public class AndroidUtils { public static final String EXT_NATIVE_LIB = "so"; @NonNls public static final String RES_OVERLAY_DIR_NAME = "res-overlay"; - private static final int TIMEOUT = 30000; + public static final int TIMEOUT = 30000; private AndroidUtils() { } From f09dd6762657a78e30d99c876bce8168d454e040 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Fri, 10 Dec 2010 18:31:56 +0300 Subject: [PATCH 24/38] smart error messages after uploading; user should be able to stop uploading; remove uninstall-install workaround, because it doesn't work [rev=nnmatveev] --- .../android/run/AndroidRunningState.java | 82 +++++++++++++++++-- 1 file changed, 75 insertions(+), 7 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/run/AndroidRunningState.java b/plugins/android/src/org/jetbrains/android/run/AndroidRunningState.java index a583f1ebb399..38b51eaaa21e 100644 --- a/plugins/android/src/org/jetbrains/android/run/AndroidRunningState.java +++ b/plugins/android/src/org/jetbrains/android/run/AndroidRunningState.java @@ -613,6 +613,29 @@ public abstract class AndroidRunningState implements RunProfileState, AndroidDeb return true; } + private class MyISyncProgressMonitor implements SyncService.ISyncProgressMonitor { + @Override + public void start(int totalWork) { + } + + @Override + public void stop() { + } + + @Override + public boolean isCanceled() { + return myStopped; + } + + @Override + public void startSubTask(String name) { + } + + @Override + public void advance(int work) { + } + } + private boolean uploadApp(IDevice device, String remotePath, String localPath) throws IOException { if (myStopped) return false; getProcessHandler().notifyTextAvailable("Uploading file\n\tlocal path: " + localPath + "\n\tremote path: " + remotePath + '\n', STDOUT); @@ -621,12 +644,57 @@ public abstract class AndroidRunningState implements RunProfileState, AndroidDeb getProcessHandler().notifyTextAvailable("Can't upload file: device is not available.\n", STDERR); return false; } - SyncService.SyncResult result = service.pushFile(localPath, remotePath, SyncService.getNullProgressMonitor()); - if (result.getCode() != SyncService.RESULT_OK) { - getProcessHandler().notifyTextAvailable("Can't upload file: " + result.getMessage() + ".\n", STDERR); - return false; + SyncService.SyncResult result = service.pushFile(localPath, remotePath, new MyISyncProgressMonitor()); + int code = result.getCode(); + String errorMessage; + switch (code) { + case SyncService.RESULT_OK: + return true; + case SyncService.RESULT_CANCELED: + errorMessage = "Command canceled"; + break; + case SyncService.RESULT_CONNECTION_ERROR: + errorMessage = "Connection error"; + break; + case SyncService.RESULT_CONNECTION_TIMEOUT: + errorMessage = "Connection timeout"; + break; + case SyncService.RESULT_FILE_READ_ERROR: + errorMessage = "Cannot read the file"; + break; + case SyncService.RESULT_FILE_WRITE_ERROR: + errorMessage = "Cannot write the file"; + break; + case SyncService.RESULT_LOCAL_IS_DIRECTORY: + errorMessage = "Local is directory"; + break; + case SyncService.RESULT_NO_DIR_TARGET: + errorMessage = "Target directory not found"; + break; + case SyncService.RESULT_NO_LOCAL_FILE: + errorMessage = "Local file not found"; + break; + case SyncService.RESULT_NO_REMOTE_OBJECT: + errorMessage = "No remote object"; + break; + case SyncService.RESULT_REMOTE_IS_FILE: + errorMessage = "Remote is a file"; + break; + case SyncService.RESULT_REMOTE_PATH_ENCODING: + errorMessage = "Incorrect remote path encoding"; + break; + case SyncService.RESULT_REMOTE_PATH_LENGTH: + errorMessage = "Incorrect remote path length"; + break; + case SyncService.RESULT_TARGET_IS_FILE: + errorMessage = "Target is a file"; + break; + default: + errorMessage = "Can't upload file"; } - return true; + getProcessHandler() + .notifyTextAvailable(errorMessage + (result.getMessage() != null ? "\n" + result.getMessage() + "\n" : "\n"), STDERR); + return false; } @SuppressWarnings({"DuplicateThrows"}) @@ -676,13 +744,13 @@ public abstract class AndroidRunningState implements RunProfileState, AndroidDeb executeDeviceCommandAndWriteToConsole(device, "pm install -r \"" + remotePath + '\"', receiver); if (myStopped) return false; }*/ - if (!isSuccess(receiver)) { + /*if (!isSuccess(receiver)) { getProcessHandler().notifyTextAvailable("Can't reinstall application. Installing from scratch.\n", STDOUT); executeDeviceCommandAndWriteToConsole(device, "pm uninstall \"" + remotePath + '\"', receiver); if (myStopped) return false; executeDeviceCommandAndWriteToConsole(device, "pm install \"" + remotePath + '\"', receiver); if (myStopped) return false; - } + }*/ boolean success = isSuccess(receiver); getProcessHandler().notifyTextAvailable(receiver.output.toString(), success ? STDOUT : STDERR); return success; From b94400a66a5e5ceab13c6710cd524085af043163 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Fri, 10 Dec 2010 18:37:31 +0300 Subject: [PATCH 25/38] IDEA-62715 Automatic indentation doesn't work if you don't use braces 1. Providing correct indentation for incomplete brace-less 'if', 'for' and 'while' statements; 2. Corresponding test is added; --- .../java/BlockContainingJavaBlock.java | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/BlockContainingJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/BlockContainingJavaBlock.java index c8b11d1f9f08..b5c7822cbb01 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/BlockContainingJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/BlockContainingJavaBlock.java @@ -17,12 +17,15 @@ package com.intellij.psi.formatter.java; import com.intellij.formatting.*; import com.intellij.lang.ASTNode; +import com.intellij.psi.JavaTokenType; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.impl.source.tree.ElementType; import com.intellij.psi.impl.source.tree.JavaDocElementType; +import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.impl.source.tree.StdTokenSets; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -30,6 +33,10 @@ import java.util.List; public class BlockContainingJavaBlock extends AbstractJavaBlock{ + private static final TokenSet TYPES_OF_STATEMENTS_WITH_OPTIONAL_BRACES = TokenSet.create( + JavaElementType.IF_STATEMENT, JavaElementType.WHILE_STATEMENT, JavaElementType.FOR_STATEMENT + ); + private final static int BEFORE_FIRST = 0; private final static int BEFORE_BLOCK = 1; private final static int AFTER_ELSE = 2; @@ -207,12 +214,37 @@ public class BlockContainingJavaBlock extends AbstractJavaBlock{ return new ChildAttributes(getCodeBlockExternalIndent(), null); } + boolean useExternalIndent = false; if (newChildIndex == getSubBlocks().size()) { + useExternalIndent = true; + } + else if (TYPES_OF_STATEMENTS_WITH_OPTIONAL_BRACES.contains(myNode.getElementType())) { + // There is a possible case that we have situation like below: + // if (true) + // + // System.out.println(); + // We would like to indent current caret position then because there is a high probability that the user starts + // typing there (populating statement body). So, we perform dedicated check for that here and use 'external indent' + // if necessary. + Block prevBlock = getSubBlocks().get(newChildIndex - 1); + Block nextBlock = getSubBlocks().get(newChildIndex); + if (prevBlock instanceof ASTBlock && nextBlock instanceof ASTBlock) { + ASTNode prevNode = ((ASTBlock)prevBlock).getNode(); + ASTNode nextNode = ((ASTBlock)nextBlock).getNode(); + if (prevNode != null && nextNode != null && prevNode.getElementType() == JavaTokenType.RPARENTH + && nextNode.getElementType() != JavaTokenType.LBRACE) + { + useExternalIndent = true; + } + } + } + + if (useExternalIndent) { return new ChildAttributes(getCodeBlockChildExternalIndent(newChildIndex), null); } - - return new ChildAttributes(myIndentsBefore.get(newChildIndex), null); - + else { + return new ChildAttributes(myIndentsBefore.get(newChildIndex), null); + } } private boolean isInsideForParens(final int newChildIndex) { From 8c0ad53b149fcd24d1ebec69ffc4736da4445f91 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 10 Dec 2010 18:42:33 +0300 Subject: [PATCH 26/38] Avoid grand VFS refresh in tests (fixed) --- .../src/com/intellij/codeInsight/CodeInsightTestCase.java | 3 +-- .../src/com/intellij/testFramework/PlatformTestCase.java | 7 ------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java b/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java index 4cbcebdc186a..6028e2bfb1c3 100644 --- a/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java @@ -240,8 +240,7 @@ public abstract class CodeInsightTestCase extends PsiTestCase { } })); - // grand VFS refresh significantly slows down local tests and generally not needed - //VirtualFileManager.getInstance().refresh(false); + toDir.refresh(false, true); } else { editorInfos = new LinkedHashMap(); diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java index 118d3202931d..a47d2d76d7e6 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java @@ -595,13 +595,6 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro public static File createTempDir(@NonNls final String prefix) throws IOException { final File tempDirectory = FileUtil.createTempDirectory(TEST_DIR_PREFIX + prefix, null); myFilesToDelete.add(tempDirectory); - // grand VFS refresh significantly slows down local tests and generally not needed - //ApplicationManager.getApplication().runWriteAction(new Runnable() { - // @Override - // public void run() { - // VirtualFileManager.getInstance().refresh(false); - // } - //}); return tempDirectory; } From a6cf1e04a66fee89878f4284f3b6021fae9e4baf Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Fri, 10 Dec 2010 20:07:35 +0300 Subject: [PATCH 27/38] some fixes in editor showing for remote debug files --- .../src/com/intellij/xdebugger/XDebugSession.java | 9 +++++---- .../com/intellij/xdebugger/impl/XDebugSessionImpl.java | 6 ++++++ .../intellij/xdebugger/impl/XDebuggerManagerImpl.java | 1 - 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java index f924a5fb70a4..f8010f52b2a1 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java @@ -16,16 +16,15 @@ package com.intellij.xdebugger; -import com.intellij.execution.ExecutionException; -import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.execution.configurations.RunProfile; +import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.openapi.project.Project; import com.intellij.xdebugger.breakpoints.XBreakpoint; import com.intellij.xdebugger.breakpoints.XLineBreakpoint; -import com.intellij.xdebugger.frame.XSuspendContext; import com.intellij.xdebugger.frame.XStackFrame; -import com.intellij.xdebugger.stepping.XSmartStepIntoVariant; +import com.intellij.xdebugger.frame.XSuspendContext; import com.intellij.xdebugger.stepping.XSmartStepIntoHandler; +import com.intellij.xdebugger.stepping.XSmartStepIntoVariant; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -64,6 +63,8 @@ public interface XDebugSession extends AbstractDebuggerSession { void pause(); void resume(); + void showExecutionPoint(XSourcePosition sourcePosition); + void showExecutionPoint(); void setCurrentStackFrame(@NotNull XStackFrame frame); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java index b4765e42e86e..8d66f86e78ee 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java @@ -344,6 +344,12 @@ public class XDebugSessionImpl implements XDebugSession { myDispatcher.getMulticaster().sessionResumed(); } + public void showExecutionPoint(XSourcePosition sourcePosition) { + XExecutionStack activeExecutionStack = mySuspendContext.getActiveExecutionStack(); + boolean isTopFrame = activeExecutionStack != null && activeExecutionStack.getTopFrame() == myCurrentStackFrame; + myDebuggerManager.setActiveSession(this, sourcePosition, !isTopFrame); + } + public void showExecutionPoint() { if (mySuspendContext != null) { XExecutionStack executionStack = mySuspendContext.getActiveExecutionStack(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java index 3dc3c8af5c73..2b410768f79b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java @@ -68,7 +68,6 @@ public class XDebuggerManagerImpl extends XDebuggerManager implements ProjectCom private final ExecutionPointHighlighter myExecutionPointHighlighter; private XDebugSessionImpl myActiveSession; - public XDebuggerManagerImpl(final Project project, final StartupManager startupManager, MessageBus messageBus) { myProject = project; myBreakpointManager = new XBreakpointManagerImpl(project, this, startupManager); From a4bee5779085c2e836d4203af832a609fc857adc Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 10 Dec 2010 19:09:41 +0300 Subject: [PATCH 28/38] list all colors and provide full preview in regexp color settings page; remove color which is very unlikely to be usefully highlighted --- .../lang/regexp/RegExpColorsPage.java | 20 ++++++++++++------- .../lang/regexp/RegExpHighlighter.java | 5 ----- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpColorsPage.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpColorsPage.java index 8afcb738c59e..1c175c978094 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpColorsPage.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpColorsPage.java @@ -15,7 +15,6 @@ */ package org.intellij.lang.regexp; -import com.intellij.application.options.colors.InspectionColorSettingsPage; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.fileTypes.SyntaxHighlighter; import com.intellij.openapi.options.colors.AttributesDescriptor; @@ -31,13 +30,20 @@ import java.util.Map; /** * @author traff */ -public class RegExpColorsPage implements ColorSettingsPage, InspectionColorSettingsPage { +public class RegExpColorsPage implements ColorSettingsPage { private static final AttributesDescriptor[] ATTRS = new AttributesDescriptor[] { - new AttributesDescriptor("Keywords", RegExpHighlighter.META), - new AttributesDescriptor("Escaped characters", RegExpHighlighter.ESC_CHARACTER), - new AttributesDescriptor("Braces", RegExpHighlighter.BRACES), - new AttributesDescriptor("Brackets", RegExpHighlighter.BRACKETS), + new AttributesDescriptor("Keyword", RegExpHighlighter.META), + new AttributesDescriptor("Escaped character", RegExpHighlighter.ESC_CHARACTER), + new AttributesDescriptor("Invalid escape sequence", RegExpHighlighter.INVALID_CHARACTER_ESCAPE), + new AttributesDescriptor("Redundant escape sequence", RegExpHighlighter.REDUNDANT_ESCAPE), + new AttributesDescriptor("Brace", RegExpHighlighter.BRACES), + new AttributesDescriptor("Bracket", RegExpHighlighter.BRACKETS), new AttributesDescriptor("Parenthesis", RegExpHighlighter.PARENTHS), + new AttributesDescriptor("Comma", RegExpHighlighter.COMMA), + new AttributesDescriptor("Bad character", RegExpHighlighter.BAD_CHARACTER), + new AttributesDescriptor("Character class", RegExpHighlighter.CHAR_CLASS), + new AttributesDescriptor("Quote character", RegExpHighlighter.QUOTE_CHARACTER), + new AttributesDescriptor("Comment", RegExpHighlighter.COMMENT) }; @NonNls private static final HashMap ourTagToDescriptorMap = new HashMap(); @@ -71,7 +77,7 @@ public class RegExpColorsPage implements ColorSettingsPage, InspectionColorSetti @NotNull public String getDemoText() { return - "^[\\w\\.-]+@([\\w\\-]+\\.)+[A-Z]{2,4}$"; + "^[\\w\\.-]+@([\\w\\-]+\\.)+[A-Z]{2,4}\\x0g\\#\\p{alpha}\\Q\\E$"; } diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpHighlighter.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpHighlighter.java index 141391a7cbeb..17da2ae193b4 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpHighlighter.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpHighlighter.java @@ -78,10 +78,6 @@ class RegExpHighlighter extends SyntaxHighlighterBase { "REGEXP.QUOTE_CHARACTER", SyntaxHighlighterColors.VALID_STRING_ESCAPE.getDefaultAttributes() ); - static final TextAttributesKey CTRL_CHARACTER = TextAttributesKey.createTextAttributesKey( - "REGEXP.CTRL_CHARACTER", - SyntaxHighlighterColors.VALID_STRING_ESCAPE.getDefaultAttributes() - ); static final TextAttributesKey COMMENT = TextAttributesKey.createTextAttributesKey( "REGEXP.COMMENT", SyntaxHighlighterColors.LINE_COMMENT.getDefaultAttributes() @@ -108,7 +104,6 @@ class RegExpHighlighter extends SyntaxHighlighterBase { keys1.put(RegExpTT.BAD_HEX_VALUE, INVALID_CHARACTER_ESCAPE); keys1.put(RegExpTT.BAD_OCT_VALUE, INVALID_CHARACTER_ESCAPE); - keys1.put(RegExpTT.CTRL_CHARACTER, CTRL_CHARACTER); keys1.put(RegExpTT.PROPERTY, CHAR_CLASS); keys1.put(RegExpTT.ESC_CHARACTER, ESC_CHARACTER); From fe30364a511f1540c145f73ba80f364ff7b44898 Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 10 Dec 2010 21:45:55 +0300 Subject: [PATCH 29/38] junit: speed up start - send objects first; do not send through err and out --- .../junit/segments/OutputObjectRegistry.java | 35 +++++++++++-------- .../rt/execution/junit/segments/Packet.java | 5 +++ .../junit/segments/PoolOfDelimiters.java | 1 + .../intellij/junit3/JUnit3IdeaTestRunner.java | 4 +-- .../junit3/JUnit3OutputObjectRegistry.java | 8 ++--- .../intellij/junit3/TestResultsSender.java | 6 +--- .../src/com/intellij/junit3/TreeSender.java | 15 ++++---- .../intellij/junit4/JUnit4IdeaTestRunner.java | 21 ++++++----- .../junit4/JUnit4OutputObjectRegistry.java | 4 +-- .../junit4/JUnit4TestResultsSender.java | 5 +-- 10 files changed, 55 insertions(+), 49 deletions(-) diff --git a/java/java-runtime/src/com/intellij/rt/execution/junit/segments/OutputObjectRegistry.java b/java/java-runtime/src/com/intellij/rt/execution/junit/segments/OutputObjectRegistry.java index c23c9c520ee4..8b7132d6bd37 100644 --- a/java/java-runtime/src/com/intellij/rt/execution/junit/segments/OutputObjectRegistry.java +++ b/java/java-runtime/src/com/intellij/rt/execution/junit/segments/OutputObjectRegistry.java @@ -15,29 +15,42 @@ */ package com.intellij.rt.execution.junit.segments; +import java.util.Collection; import java.util.Hashtable; public abstract class OutputObjectRegistry { private final Hashtable myKnownKeys = new Hashtable(); private int myLastIndex = 0; private PacketProcessor myMainTransport; - private PacketProcessor myAuxilaryTransport; public OutputObjectRegistry(PacketProcessor transport) { myMainTransport = transport; } - public OutputObjectRegistry(PacketProcessor mainTransport, PacketProcessor auxilaryTransport) { - this(mainTransport); - myAuxilaryTransport = auxilaryTransport; - } - public String referenceTo(Object test) { if (myKnownKeys.containsKey(test)) return (String) myKnownKeys.get(test); return sendObject(test); } + public String referenceTo(Object test, Collection packets) { + if (myKnownKeys.containsKey(test)) + return (String) myKnownKeys.get(test); + return sendObject(test, packets); + } + + private String sendObject(Object test, Collection packets) { + String key = String.valueOf(myLastIndex++); + myKnownKeys.put(test, key); + final Packet packet = createPacket(); + packet.addString(PoolOfDelimiters.OBJECT_PREFIX).addReference(key); + addStringRepresentation(test, packet); + packet.addLong(getTestCont(test)); + packet.addString(PoolOfDelimiters.REFERENCE_END_STR); + packets.add(packet); + return key; + } + public Packet createPacket() { return new Packet(myMainTransport, this); } @@ -48,21 +61,13 @@ public abstract class OutputObjectRegistry { Packet packet = createPacket().addString(PoolOfDelimiters.OBJECT_PREFIX).addReference(key); addStringRepresentation(test, packet); packet.addLong(getTestCont(test)); - sendViaAllTransports(packet); + packet.send(); return key; } protected abstract int getTestCont(Object test); protected abstract void addStringRepresentation(Object test, Packet packet); - private void sendViaAllTransports(Packet packet) { - packet.send(); - if (myAuxilaryTransport != null) - packet.sendThrough(myAuxilaryTransport); - } - - - protected static void addTestClass(Packet packet, String className) { packet. addLimitedString(PoolOfTestTypes.TEST_CLASS). diff --git a/java/java-runtime/src/com/intellij/rt/execution/junit/segments/Packet.java b/java/java-runtime/src/com/intellij/rt/execution/junit/segments/Packet.java index b1970a947b6f..8e72223bfa35 100644 --- a/java/java-runtime/src/com/intellij/rt/execution/junit/segments/Packet.java +++ b/java/java-runtime/src/com/intellij/rt/execution/junit/segments/Packet.java @@ -18,6 +18,7 @@ package com.intellij.rt.execution.junit.segments; import junit.runner.BaseTestRunner; import java.io.*; +import java.util.Collection; import java.util.Vector; public class Packet extends PacketWriter { @@ -36,6 +37,10 @@ public class Packet extends PacketWriter { return addReference(myRegistry.referenceTo(test)); } + public Packet addObject(Object test, Collection packet) { + return addReference(myRegistry.referenceTo(test, packet)); + } + public Packet addReference(String reference) { appendString(reference + PoolOfDelimiters.REFERENCE_END); return this; diff --git a/java/java-runtime/src/com/intellij/rt/execution/junit/segments/PoolOfDelimiters.java b/java/java-runtime/src/com/intellij/rt/execution/junit/segments/PoolOfDelimiters.java index 21f115f1038f..6f87e8c788b1 100644 --- a/java/java-runtime/src/com/intellij/rt/execution/junit/segments/PoolOfDelimiters.java +++ b/java/java-runtime/src/com/intellij/rt/execution/junit/segments/PoolOfDelimiters.java @@ -20,6 +20,7 @@ package com.intellij.rt.execution.junit.segments; */ public interface PoolOfDelimiters { char REFERENCE_END = ':'; + String REFERENCE_END_STR = ":"; char INTEGER_DELIMITER = ' '; String OBJECT_PREFIX = "O"; diff --git a/plugins/junit_rt/src/com/intellij/junit3/JUnit3IdeaTestRunner.java b/plugins/junit_rt/src/com/intellij/junit3/JUnit3IdeaTestRunner.java index 8b87d1aa369c..a9cf05ee5cd9 100644 --- a/plugins/junit_rt/src/com/intellij/junit3/JUnit3IdeaTestRunner.java +++ b/plugins/junit_rt/src/com/intellij/junit3/JUnit3IdeaTestRunner.java @@ -62,8 +62,8 @@ public class JUnit3IdeaTestRunner extends TestRunner implements IdeaTestRunner { public void setStreams(SegmentedOutputStream segmentedOut, SegmentedOutputStream segmentedErr) { setPrinter(new TimeSender()); - myRegistry = new JUnit3OutputObjectRegistry(segmentedOut, segmentedErr); - myTestsListener = new TestResultsSender(myRegistry, segmentedErr); + myRegistry = new JUnit3OutputObjectRegistry(segmentedOut); + myTestsListener = new TestResultsSender(myRegistry); } protected TestResult createTestResult() { diff --git a/plugins/junit_rt/src/com/intellij/junit3/JUnit3OutputObjectRegistry.java b/plugins/junit_rt/src/com/intellij/junit3/JUnit3OutputObjectRegistry.java index 0edf7adca7ff..87deb5857916 100644 --- a/plugins/junit_rt/src/com/intellij/junit3/JUnit3OutputObjectRegistry.java +++ b/plugins/junit_rt/src/com/intellij/junit3/JUnit3OutputObjectRegistry.java @@ -28,12 +28,8 @@ import junit.framework.TestCase; import junit.framework.TestSuite; public class JUnit3OutputObjectRegistry extends OutputObjectRegistry { - public JUnit3OutputObjectRegistry(PacketProcessor mainTransport, PacketProcessor auxilaryTransport) { - super(mainTransport, auxilaryTransport); - } - - public JUnit3OutputObjectRegistry(PacketProcessor out) { - super(out); + public JUnit3OutputObjectRegistry(PacketProcessor mainTransport) { + super(mainTransport); } protected int getTestCont(Object test) { diff --git a/plugins/junit_rt/src/com/intellij/junit3/TestResultsSender.java b/plugins/junit_rt/src/com/intellij/junit3/TestResultsSender.java index da85d0d8ddc5..e573a93067c8 100644 --- a/plugins/junit_rt/src/com/intellij/junit3/TestResultsSender.java +++ b/plugins/junit_rt/src/com/intellij/junit3/TestResultsSender.java @@ -18,7 +18,6 @@ package com.intellij.junit3; import com.intellij.rt.execution.junit.*; import com.intellij.rt.execution.junit.segments.OutputObjectRegistry; import com.intellij.rt.execution.junit.segments.Packet; -import com.intellij.rt.execution.junit.segments.PacketProcessor; import com.intellij.rt.execution.junit.states.PoolOfTestStates; import junit.framework.AssertionFailedError; import junit.framework.ComparisonFailure; @@ -27,13 +26,11 @@ import junit.framework.TestListener; public class TestResultsSender implements TestListener { private final OutputObjectRegistry myRegistry; - private final PacketProcessor myErr; private TestMeter myCurrentTestMeter; private Test myCurrentTest; - public TestResultsSender(OutputObjectRegistry packetFactory, PacketProcessor segmentedErr) { + public TestResultsSender(OutputObjectRegistry packetFactory) { myRegistry = packetFactory; - myErr = segmentedErr; } public synchronized void addError(Test test, Throwable throwable) { @@ -93,7 +90,6 @@ public class TestResultsSender implements TestListener { private void switchOutput(Packet switchPacket) { switchPacket.send(); - switchPacket.sendThrough(myErr); } public synchronized void startTest(Test test) { diff --git a/plugins/junit_rt/src/com/intellij/junit3/TreeSender.java b/plugins/junit_rt/src/com/intellij/junit3/TreeSender.java index ba0a54cdb163..caf4791548c9 100644 --- a/plugins/junit_rt/src/com/intellij/junit3/TreeSender.java +++ b/plugins/junit_rt/src/com/intellij/junit3/TreeSender.java @@ -21,16 +21,15 @@ import com.intellij.rt.execution.junit.segments.Packet; import junit.framework.Test; import junit.framework.TestSuite; -import java.util.Enumeration; -import java.util.Vector; +import java.util.*; public class TreeSender { - private static void sendNode(Test test, Packet packet) { + private static void sendNode(Test test, Packet packet, Collection objects) { Vector testCases = getTestCasesOf(test); - packet.addObject(test).addLong(testCases.size()); + packet.addObject(test, objects).addLong(testCases.size()); for (int i = 0; i < testCases.size(); i++) { Test nextTest = (Test)testCases.get(i); - sendNode(nextTest, packet); + sendNode(nextTest, packet, objects); } } @@ -54,7 +53,11 @@ public class TreeSender { public static void sendSuite(OutputObjectRegistry registry, Test suite) { Packet packet = registry.createPacket(); packet.addString(PoolOfDelimiters.TREE_PREFIX); - sendNode(suite, packet); + Collection objects = new ArrayList(); + sendNode(suite, packet, objects); + for (Iterator iterator = objects.iterator(); iterator.hasNext();) { + ((Packet)iterator.next()).send(); + } packet.addString("\n"); packet.send(); } diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java index 7b74dd6413b6..905d43be072d 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java @@ -30,26 +30,29 @@ import org.junit.runner.manipulation.Filter; import org.junit.runner.notification.RunListener; import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Iterator; +import java.util.*; /** @noinspection UnusedDeclaration*/ public class JUnit4IdeaTestRunner implements IdeaTestRunner { private RunListener myTestsListener; private OutputObjectRegistry myRegistry; - private static void sendNode(Description test, Packet packet) { + private static void sendNode(Description test, Packet packet, Collection objectPackets) { final ArrayList children = test.getChildren(); - packet.addObject(test).addLong(children.size()); + packet.addObject(test, objectPackets).addLong(children.size()); for (int i = 0; i < children.size(); i++) { - sendNode((Description)children.get(i), packet); + sendNode((Description)children.get(i), packet, objectPackets); } } - public static void sendTree(OutputObjectRegistry registry, Description suite) { + public void sendTree(OutputObjectRegistry registry, Description suite) { Packet packet = registry.createPacket(); packet.addString(PoolOfDelimiters.TREE_PREFIX); - sendNode(suite, packet); + Set objects = new HashSet(); + sendNode(suite, packet, objects); + for (Iterator iterator = objects.iterator(); iterator.hasNext();) { + ((Packet)iterator.next()).send(); + } packet.addString("\n"); packet.send(); } @@ -150,8 +153,8 @@ public class JUnit4IdeaTestRunner implements IdeaTestRunner { public void setStreams(SegmentedOutputStream segmentedOut, SegmentedOutputStream segmentedErr) { - myRegistry = new JUnit4OutputObjectRegistry(segmentedOut, segmentedErr); - myTestsListener = new JUnit4TestResultsSender(myRegistry, segmentedErr); + myRegistry = new JUnit4OutputObjectRegistry(segmentedOut); + myTestsListener = new JUnit4TestResultsSender(myRegistry); } private class TimeSender extends ResultPrinter { diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4OutputObjectRegistry.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4OutputObjectRegistry.java index 5a1fd67f7efc..d628da9a062b 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4OutputObjectRegistry.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4OutputObjectRegistry.java @@ -27,8 +27,8 @@ import org.junit.runner.Description; public class JUnit4OutputObjectRegistry extends OutputObjectRegistry { - public JUnit4OutputObjectRegistry(PacketProcessor mainTransport, PacketProcessor auxilaryTransport) { - super(mainTransport, auxilaryTransport); + public JUnit4OutputObjectRegistry(PacketProcessor mainTransport) { + super(mainTransport); } protected int getTestCont(Object test) { diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java index 989136a78c7c..af994c2069a4 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java @@ -35,13 +35,11 @@ import java.util.regex.Pattern; public class JUnit4TestResultsSender extends RunListener { private final OutputObjectRegistry myRegistry; - private final PacketProcessor myErr; private Map myCurrentTestMeters = new HashMap(); private Set myCurrentTests = new HashSet(); - public JUnit4TestResultsSender(OutputObjectRegistry packetFactory, PacketProcessor segmentedErr) { + public JUnit4TestResultsSender(OutputObjectRegistry packetFactory) { myRegistry = packetFactory; - myErr = segmentedErr; } public synchronized void testFailure(Failure failure) throws Exception { @@ -139,7 +137,6 @@ public class JUnit4TestResultsSender extends RunListener { private void switchOutput(Packet switchPacket) { switchPacket.send(); - switchPacket.sendThrough(myErr); } From bb39a079957d18a4a3aaa64da8c6cbedda360a67 Mon Sep 17 00:00:00 2001 From: Oleg Shpynov Date: Sat, 11 Dec 2010 00:13:22 +0300 Subject: [PATCH 30/38] IDEA-62869 Github fails to save settings --- .../src/org/jetbrains/plugins/github/GithubSettings.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubSettings.java b/plugins/github/src/org/jetbrains/plugins/github/GithubSettings.java index 41342b27ba52..80ccdc2542ea 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubSettings.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubSettings.java @@ -40,9 +40,9 @@ public class GithubSettings implements PersistentStateComponent { return null; } final Element element = new Element(GITHUB_SETTINGS_TAG); - element.setAttribute(LOGIN, myLogin); + element.setAttribute(LOGIN, getLogin()); element.setAttribute(PASSWORD, getEncodedPassword()); - element.setAttribute(CLONE_PATH, myClonePath); + element.setAttribute(CLONE_PATH, getClonePath()); return element; } From 93c16006aad4f58e92e2171ce6ef0c5098ccd41f Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Sat, 11 Dec 2010 14:24:07 +0100 Subject: [PATCH 31/38] IDEA-62872 ("Multiple variables in one declaration" should (optionally) warn about multiple variables in for-loop declarations) --- .../siyeh/InspectionGadgetsBundle.properties | 3 +- .../ig/fixes/NormalizeDeclarationFix.java | 93 +++++++++++++++++-- .../style/MultipleDeclarationInspection.java | 41 ++++++-- 3 files changed, 122 insertions(+), 15 deletions(-) diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index 106bef988a7a..fe755a04d8e2 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -1817,4 +1817,5 @@ cast.conflicts.with.instanceof.quickfix2=Replace instanceof ''{0}'' with ''{1}'' double.checked.locking.quickfix=Make ''{0}'' volatile double.literal.may.be.float.literal.display.name=double literal cast to long could be float literal double.literal.may.be.float.literal.problem.descriptor=#ref could be replaced with ''{0}'' #loc -double.literal.may.be.float.literal.quickfix=Replace with ''{0}'' \ No newline at end of file +double.literal.may.be.float.literal.quickfix=Replace with ''{0}'' +multiple.declaration.option=Ignore for loop declarations \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/NormalizeDeclarationFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/NormalizeDeclarationFix.java index 2808d4d99a74..5d4f37354bfe 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/NormalizeDeclarationFix.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/NormalizeDeclarationFix.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2005 Dave Griffith + * Copyright 2003-2010 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,24 +17,105 @@ package com.siyeh.ig.fixes; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiVariable; +import com.intellij.psi.*; import com.intellij.util.IncorrectOperationException; import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.InspectionGadgetsBundle; import org.jetbrains.annotations.NotNull; public class NormalizeDeclarationFix extends InspectionGadgetsFix{ + @NotNull public String getName(){ return InspectionGadgetsBundle.message("normalize.declaration.quickfix"); } + @Override public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException{ final PsiElement variableNameElement = descriptor.getPsiElement(); - final PsiVariable var = (PsiVariable) variableNameElement.getParent(); - assert var != null; - var.normalizeDeclaration(); + final PsiVariable parent = + (PsiVariable) variableNameElement.getParent(); + if (parent == null) { + return; + } + final PsiElement grandParent = parent.getParent(); + if (!(grandParent instanceof PsiDeclarationStatement)) { + return; + } + final PsiElement greatGrandParent = grandParent.getParent(); + if (greatGrandParent instanceof PsiForStatement) { + final PsiForStatement forStatement = + (PsiForStatement) greatGrandParent; + final PsiStatement initialization = + forStatement.getInitialization(); + if (grandParent.equals(initialization)) { + final PsiDeclarationStatement declarationStatement = + (PsiDeclarationStatement) grandParent; + splitMultipleDeclarationInForStatementInitializer( + declarationStatement); + return; + } + } + parent.normalizeDeclaration(); + } + + private static void splitMultipleDeclarationInForStatementInitializer( + PsiDeclarationStatement declarationStatement) { + final PsiElement forStatement = declarationStatement.getParent(); + final PsiElement[] declaredElements = + declarationStatement.getDeclaredElements(); + final Project project = forStatement.getProject(); + final PsiElementFactory factory = + JavaPsiFacade.getElementFactory(project); + final PsiElement greatGreatGrandParent = forStatement.getParent(); + final PsiBlockStatement blockStatement; + final PsiCodeBlock codeBlock; + if (!(greatGreatGrandParent instanceof PsiCodeBlock)) { + blockStatement = (PsiBlockStatement) + factory.createStatementFromText("{}", forStatement); + codeBlock = blockStatement.getCodeBlock(); + } else { + blockStatement = null; + codeBlock = null; + } + for (int i = 1; i < declaredElements.length; i++) { + final PsiElement declaredElement = declaredElements[i]; + if (!(declaredElement instanceof PsiVariable)) { + continue; + } + final PsiVariable variable = (PsiVariable) declaredElement; + final PsiType type = variable.getType(); + final String typeText = type.getCanonicalText(); + final StringBuilder newStatementText = + new StringBuilder(typeText); + newStatementText.append(' '); + newStatementText.append(variable.getName()); + final PsiExpression initializer = variable.getInitializer(); + if (initializer != null) { + newStatementText.append('='); + newStatementText.append(initializer.getText()); + } + newStatementText.append(';'); + final PsiStatement newStatement = + factory.createStatementFromText( + newStatementText.toString(), forStatement); + if (codeBlock == null) { + greatGreatGrandParent.addBefore(newStatement, forStatement); + } else { + codeBlock.add(newStatement); + } + } + for (int i = 1; i < declaredElements.length; i++) { + final PsiElement declaredElement = declaredElements[i]; + if (!(declaredElement instanceof PsiVariable)) { + continue; + } + declaredElement.delete(); + } + if (codeBlock != null) { + codeBlock.add(forStatement); + forStatement.replace(blockStatement); + } } } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/MultipleDeclarationInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/MultipleDeclarationInspection.java index b5121ed5cd55..ef54fce822c3 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/MultipleDeclarationInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/MultipleDeclarationInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2010 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ package com.siyeh.ig.style; +import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; import com.intellij.psi.*; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; @@ -23,34 +24,51 @@ import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.fixes.NormalizeDeclarationFix; import org.jetbrains.annotations.NotNull; +import javax.swing.*; + public class MultipleDeclarationInspection extends BaseInspection { + @SuppressWarnings({"PublicField"}) + public boolean ignoreForLoopDeclarations = true; + + @Override @NotNull public String getDisplayName() { return InspectionGadgetsBundle.message( "multiple.declaration.display.name"); } + @Override @NotNull public String getID() { return "MultipleVariablesInDeclaration"; } + @Override @NotNull protected String buildErrorString(Object... infos) { return InspectionGadgetsBundle.message( "multiple.declaration.problem.descriptor"); } + @Override + public JComponent createOptionsPanel() { + return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message( + "multiple.declaration.option"), + this, "ignoreForLoopDeclarations"); + } + + @Override public InspectionGadgetsFix buildFix(Object... infos) { return new NormalizeDeclarationFix(); } + @Override public BaseInspectionVisitor buildVisitor() { return new MultipleDeclarationVisitor(); } - private static class MultipleDeclarationVisitor + private class MultipleDeclarationVisitor extends BaseInspectionVisitor { @Override public void visitDeclarationStatement( @@ -60,7 +78,8 @@ public class MultipleDeclarationInspection extends BaseInspection { return; } final PsiElement parent = statement.getParent(); - if (parent instanceof PsiForStatement) { + if (ignoreForLoopDeclarations && + parent instanceof PsiForStatement) { final PsiForStatement forStatement = (PsiForStatement)parent; final PsiStatement initialization = forStatement.getInitialization(); @@ -68,11 +87,17 @@ public class MultipleDeclarationInspection extends BaseInspection { return; } } - final PsiElement[] declaredVars = statement.getDeclaredElements(); - for (int i = 1; i < declaredVars.length; i++) { + final PsiElement[] declaredElements = + statement.getDeclaredElements(); + for (int i = 1; i < declaredElements.length; i++) { //skip the first one; - final PsiLocalVariable var = (PsiLocalVariable)declaredVars[i]; - registerVariableError(var); + final PsiElement declaredElement = declaredElements[i]; + if (!(declaredElement instanceof PsiVariable)) { + continue; + } + final PsiVariable variable = + (PsiVariable) declaredElement; + registerVariableError(variable); } } @@ -87,7 +112,7 @@ public class MultipleDeclarationInspection extends BaseInspection { registerFieldError(field); } - public static boolean childrenContainTypeElement(PsiElement field) { + public boolean childrenContainTypeElement(PsiElement field) { final PsiElement[] children = field.getChildren(); for (PsiElement aChildren : children) { if (aChildren instanceof PsiTypeElement) { From 1e2aec73825898b83da71b7f74e98dc5bbbc2ccf Mon Sep 17 00:00:00 2001 From: "Kirill.Safonov" Date: Sun, 12 Dec 2010 18:31:11 +0300 Subject: [PATCH 32/38] JS/AS goto super/goto implementation popups: show classes names when searching for implemented methods (IDEA-62786), consistent style and title, i18n [r=Maxim.Mossienko] --- .../daemon/impl/PsiElementListNavigator.java | 62 +++++++++++-------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java index 7e147ae691c6..ac32823613be 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java @@ -18,11 +18,14 @@ package com.intellij.codeInsight.daemon.impl; import com.intellij.ide.util.PsiElementListCellRenderer; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.PopupChooserBuilder; import com.intellij.psi.NavigatablePsiElement; import com.intellij.psi.PsiElement; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.components.JBList; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.event.MouseEvent; @@ -34,35 +37,44 @@ public class PsiElementListNavigator { } public static void openTargets(MouseEvent e, NavigatablePsiElement[] targets, String title, ListCellRenderer listRenderer) { - if (targets.length == 0) return; - if (targets.length == 1){ + JBPopup popup = navigateOrCreatePopup(targets, title, listRenderer); + if (popup != null) popup.show(new RelativePoint(e)); + } + + public static void openTargets(Editor e, NavigatablePsiElement[] targets, String title, ListCellRenderer listRenderer) { + JBPopup popup = navigateOrCreatePopup(targets, title, listRenderer); + if (popup != null) popup.showInBestPositionFor(e); + } + + @Nullable + private static JBPopup navigateOrCreatePopup(NavigatablePsiElement[] targets, String title, ListCellRenderer listRenderer) { + if (targets.length == 0) return null; + if (targets.length == 1) { targets[0].navigate(true); + return null; } - else{ - final JList list = new JBList(targets); - list.setCellRenderer(listRenderer); + final JList list = new JBList(targets); + list.setCellRenderer(listRenderer); - final PopupChooserBuilder builder = new PopupChooserBuilder(list); - if (listRenderer instanceof PsiElementListCellRenderer) { - ((PsiElementListCellRenderer)listRenderer).installSpeedSearch(builder); - } + final PopupChooserBuilder builder = new PopupChooserBuilder(list); + if (listRenderer instanceof PsiElementListCellRenderer) { + ((PsiElementListCellRenderer)listRenderer).installSpeedSearch(builder); + } - builder. - setTitle(title). - setMovable(true). - setItemChoosenCallback(new Runnable() { - public void run() { - int[] ids = list.getSelectedIndices(); - if (ids == null || ids.length == 0) return; - Object [] selectedElements = list.getSelectedValues(); - for (Object element : selectedElements) { - PsiElement selected = (PsiElement) element; - LOG.assertTrue(selected.isValid()); - ((NavigatablePsiElement)selected).navigate(true); - } + return builder. + setTitle(title). + setMovable(true). + setItemChoosenCallback(new Runnable() { + public void run() { + int[] ids = list.getSelectedIndices(); + if (ids == null || ids.length == 0) return; + Object[] selectedElements = list.getSelectedValues(); + for (Object element : selectedElements) { + PsiElement selected = (PsiElement)element; + LOG.assertTrue(selected.isValid()); + ((NavigatablePsiElement)selected).navigate(true); } - }).createPopup(). - show(new RelativePoint(e)); - } + } + }).createPopup(); } } From 8504aed3767f0544db46c44fed8fb6f76730108d Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Sun, 12 Dec 2010 22:11:42 +0100 Subject: [PATCH 33/38] remove tiny bit of unneeded code --- .../ig/fixes/NormalizeDeclarationFix.java | 18 ++++++------------ .../style/MultipleDeclarationInspection.java | 7 +------ 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/NormalizeDeclarationFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/NormalizeDeclarationFix.java index 5d4f37354bfe..5f5393c7f4e8 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/NormalizeDeclarationFix.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/NormalizeDeclarationFix.java @@ -45,22 +45,16 @@ public class NormalizeDeclarationFix extends InspectionGadgetsFix{ } final PsiElement greatGrandParent = grandParent.getParent(); if (greatGrandParent instanceof PsiForStatement) { - final PsiForStatement forStatement = - (PsiForStatement) greatGrandParent; - final PsiStatement initialization = - forStatement.getInitialization(); - if (grandParent.equals(initialization)) { - final PsiDeclarationStatement declarationStatement = - (PsiDeclarationStatement) grandParent; - splitMultipleDeclarationInForStatementInitializer( - declarationStatement); - return; - } + final PsiDeclarationStatement declarationStatement = + (PsiDeclarationStatement) grandParent; + splitMultipleDeclarationInForStatementInitialization( + declarationStatement); + return; } parent.normalizeDeclaration(); } - private static void splitMultipleDeclarationInForStatementInitializer( + private static void splitMultipleDeclarationInForStatementInitialization( PsiDeclarationStatement declarationStatement) { final PsiElement forStatement = declarationStatement.getParent(); final PsiElement[] declaredElements = diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/MultipleDeclarationInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/MultipleDeclarationInspection.java index ef54fce822c3..080785bb0b75 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/MultipleDeclarationInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/MultipleDeclarationInspection.java @@ -80,12 +80,7 @@ public class MultipleDeclarationInspection extends BaseInspection { final PsiElement parent = statement.getParent(); if (ignoreForLoopDeclarations && parent instanceof PsiForStatement) { - final PsiForStatement forStatement = (PsiForStatement)parent; - final PsiStatement initialization = - forStatement.getInitialization(); - if (statement.equals(initialization)) { - return; - } + return; } final PsiElement[] declaredElements = statement.getDeclaredElements(); From a3bb303a7a4f9abe87340e0f9f4f230a73aad1ae Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Sun, 12 Dec 2010 22:12:46 +0100 Subject: [PATCH 34/38] IDEA-24662 (Inspection to find+fix simplifiable @SomeAnnotation(value = "foo") declarations) --- .../siyeh/InspectionGadgetsBundle.properties | 8 +- .../com/siyeh/ig/InspectionGadgetsPlugin.java | 2 +- .../SimplifiableAnnotationInspection.java | 137 ++++++++++++++++++ ...essaryAnnotationParenthesesInspection.java | 122 ---------------- .../SimplifiableAnnotation.html | 8 + .../SimplifiableAnnotation.java | 10 ++ .../simplifiable_annotation/expected.xml | 16 ++ .../UnnecessaryAnnotationParentheses.java | 14 -- .../expected.xml | 9 -- .../SimplifiableAnnotationInspectionTest.java | 11 ++ ...ryAnnotationParenthesesInspectionTest.java | 11 -- 11 files changed, 187 insertions(+), 161 deletions(-) create mode 100644 plugins/InspectionGadgets/src/com/siyeh/ig/style/SimplifiableAnnotationInspection.java delete mode 100644 plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryAnnotationParenthesesInspection.java create mode 100644 plugins/InspectionGadgets/src/inspectionDescriptions/SimplifiableAnnotation.html create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/style/simplifiable_annotation/SimplifiableAnnotation.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/style/simplifiable_annotation/expected.xml delete mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_annotation_parentheses/UnnecessaryAnnotationParentheses.java delete mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_annotation_parentheses/expected.xml create mode 100644 plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/SimplifiableAnnotationInspectionTest.java delete mode 100644 plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryAnnotationParenthesesInspectionTest.java diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index fe755a04d8e2..56df1c6e604b 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -1722,9 +1722,6 @@ junit4.test.method.in.class.extending.junit3.testcase.problem.descriptor=@Test a equals.called.on.enum.constant.display.name='equals()' called on Enum value equals.called.on.enum.constant.problem.descriptor=#ref called on Enum value #loc equals.called.on.enum.constant.quickfix=Replace 'equals()' with '==' -unnecessary.annotation.parentheses.display.name=Unnecessary annotation parentheses -unnecessary.annotation.parentheses.problem.descriptor=#ref has unnecessary parentheses #loc -unnecessary.annotation.parameter.quickfix=Remove parentheses int.literal.may.be.long.literal.display.name=int literal cast to long could be long literal int.literal.may.be.long.literal.problem.descriptor=#ref could be replaced with ''{0}'' #loc int.literal.may.be.long.literal.quickfix=Replace with ''{0}'' @@ -1818,4 +1815,7 @@ double.checked.locking.quickfix=Make ''{0}'' volatile double.literal.may.be.float.literal.display.name=double literal cast to long could be float literal double.literal.may.be.float.literal.problem.descriptor=#ref could be replaced with ''{0}'' #loc double.literal.may.be.float.literal.quickfix=Replace with ''{0}'' -multiple.declaration.option=Ignore for loop declarations \ No newline at end of file +multiple.declaration.option=Ignore for loop declarations +simplifiable.annotation.display.name=Simplifiable annotation +simplifiable.annotation.problem.descriptor=Annotation #ref may be replaced with ''{0}'' +simplifiable.annotation.quickfix=Simplify annotation diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java b/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java index 1cdf74d1f5bb..666994a0303b 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java @@ -729,10 +729,10 @@ public class InspectionGadgetsPlugin implements ApplicationComponent, m_inspectionClasses.add(RedundantFieldInitializationInspection.class); m_inspectionClasses.add(RedundantImplementsInspection.class); m_inspectionClasses.add(ReturnThisInspection.class); + m_inspectionClasses.add(SimplifiableAnnotationInspection.class); m_inspectionClasses.add(TypeParameterExtendsObjectInspection.class); m_inspectionClasses.add(UnnecessarilyQualifiedInnerClassAccessInspection.class); m_inspectionClasses.add(UnnecessarilyQualifiedStaticUsageInspection.class); - m_inspectionClasses.add(UnnecessaryAnnotationParenthesesInspection.class); m_inspectionClasses.add(UnnecessaryBlockStatementInspection.class); m_inspectionClasses.add(UnnecessaryCallToStringValueOfInspection.class); m_inspectionClasses.add(UnnecessaryConstructorInspection.class); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/SimplifiableAnnotationInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/SimplifiableAnnotationInspection.java new file mode 100644 index 000000000000..699fe826fc82 --- /dev/null +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/SimplifiableAnnotationInspection.java @@ -0,0 +1,137 @@ +/* + * Copyright 2010 Bas Leijdekkers + * + * 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.siyeh.ig.style; + +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.util.IncorrectOperationException; +import com.siyeh.InspectionGadgetsBundle; +import com.siyeh.ig.BaseInspection; +import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.InspectionGadgetsFix; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +public class SimplifiableAnnotationInspection extends BaseInspection { + + @Nls + @NotNull + @Override + public String getDisplayName() { + return InspectionGadgetsBundle.message( + "simplifiable.annotation.display.name"); + } + + @NotNull + @Override + protected String buildErrorString(Object... infos) { + final String replacement = (String) infos[0]; + return InspectionGadgetsBundle.message( + "simplifiable.annotation.problem.descriptor", replacement); + } + + @Override + protected InspectionGadgetsFix buildFix(Object... infos) { + final String replacement = (String) infos[0]; + return new SimplifiableAnnotationFix(replacement); + } + + private static class SimplifiableAnnotationFix + extends InspectionGadgetsFix { + + private final String replacement; + + public SimplifiableAnnotationFix(String replacement) { + super(); + this.replacement = replacement; + } + + @NotNull + public String getName() { + return InspectionGadgetsBundle.message( + "simplifiable.annotation.quickfix"); + } + + @Override + protected void doFix(Project project, ProblemDescriptor descriptor) + throws IncorrectOperationException { + final PsiElement element = descriptor.getPsiElement(); + if (!(element instanceof PsiAnnotation)) { + return; + } + final PsiElementFactory factory = + JavaPsiFacade.getElementFactory(project); + final PsiAnnotation annotation = + factory.createAnnotationFromText(replacement, element); + element.replace(annotation); + } + } + + @Override + public BaseInspectionVisitor buildVisitor() { + return new SimplifiableAnnotationVisitor(); + } + + private static class SimplifiableAnnotationVisitor + extends BaseInspectionVisitor { + + @Override + public void visitAnnotation(PsiAnnotation annotation) { + super.visitAnnotation(annotation); + final PsiAnnotationParameterList parameterList = + annotation.getParameterList(); + final PsiJavaCodeReferenceElement nameReferenceElement = + annotation.getNameReferenceElement(); + if (nameReferenceElement == null) { + return; + } + final PsiNameValuePair[] attributes = parameterList.getAttributes(); + + final PsiElement[] annotationChildren = annotation.getChildren(); + if (annotationChildren.length >= 2) { + final PsiElement child = annotationChildren[1]; + if (child instanceof PsiWhiteSpace) { + final String replacementText; + if (attributes.length > 0) { + replacementText = '@' + nameReferenceElement.getText() + + parameterList.getText(); + } else { + replacementText = '@' + nameReferenceElement.getText(); + } + registerError(annotation, replacementText); + return; + } + } + if (attributes.length == 0) { + final PsiElement[] children = parameterList.getChildren(); + if (children.length <= 0) { + return; + } + registerError(annotation, '@' + nameReferenceElement.getText()); + } else if (attributes.length == 1) { + final PsiNameValuePair attribute = attributes[0]; + @NonNls final String name = attribute.getName(); + if (!"value".equals(name)) { + return; + } + registerError(annotation, '@' + nameReferenceElement.getText() + + '(' + attribute.getValue().getText() + ')'); + } + } + } +} diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryAnnotationParenthesesInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryAnnotationParenthesesInspection.java deleted file mode 100644 index e1a8badcb493..000000000000 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryAnnotationParenthesesInspection.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2009 Bas Leijdekkers - * - * 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.siyeh.ig.style; - -import com.intellij.codeInspection.ProblemDescriptor; -import com.intellij.openapi.project.Project; -import com.intellij.psi.*; -import com.intellij.util.IncorrectOperationException; -import com.siyeh.InspectionGadgetsBundle; -import com.siyeh.ig.BaseInspection; -import com.siyeh.ig.BaseInspectionVisitor; -import com.siyeh.ig.InspectionGadgetsFix; -import org.jetbrains.annotations.Nls; -import org.jetbrains.annotations.NotNull; - -public class UnnecessaryAnnotationParenthesesInspection extends BaseInspection { - - @Override - @Nls - @NotNull() - public String getDisplayName() { - return InspectionGadgetsBundle.message( - "unnecessary.annotation.parentheses.display.name"); - } - - @Override - @NotNull - protected String buildErrorString(Object... infos) { - return InspectionGadgetsBundle.message( - "unnecessary.annotation.parentheses.problem.descriptor"); - } - - @Override - protected InspectionGadgetsFix buildFix(Object... infos) { - return new UnnecessaryAnnotationParenthesesFix(); - } - - private static class UnnecessaryAnnotationParenthesesFix - extends InspectionGadgetsFix { - - @NotNull - public String getName() { - return InspectionGadgetsBundle.message( - "unnecessary.annotation.parameter.quickfix"); - } - - @Override - protected void doFix(Project project, ProblemDescriptor descriptor) - throws IncorrectOperationException { - final PsiElement element = descriptor.getPsiElement(); - if (!(element instanceof PsiAnnotationParameterList)) { - return; - } - final PsiElement[] children = element.getChildren(); - for (PsiElement child : children) { - child.delete(); - } - } - } - - @Override - public BaseInspectionVisitor buildVisitor() { - return new UnnecessaryAnnotatinoParenthesesVisitor(); - } - - private static class UnnecessaryAnnotatinoParenthesesVisitor - extends BaseInspectionVisitor { - - @Override - public void visitAnnotation(PsiAnnotation annotation) { - super.visitAnnotation(annotation); - final PsiJavaCodeReferenceElement reference = - annotation.getNameReferenceElement(); - if (reference == null) { - return; - } - final PsiAnnotationParameterList parameterList = - annotation.getParameterList(); - final PsiElement[] children = parameterList.getChildren(); - if (children.length == 0) { - return; - } - final PsiNameValuePair[] nameValuePairs = - parameterList.getAttributes(); - if (nameValuePairs.length > 0) { - return; - } - final PsiElement target = reference.resolve(); - if (!(target instanceof PsiClass)) { - return; - } - final PsiClass annotationClass = (PsiClass) target; - final PsiMethod[] methods = annotationClass.getMethods(); - for (PsiMethod method : methods) { - if (!(method instanceof PsiAnnotationMethod)) { - continue; - } - final PsiAnnotationMethod annotationMethod = - (PsiAnnotationMethod) method; - final PsiAnnotationMemberValue defaultValue = - annotationMethod.getDefaultValue(); - if (defaultValue == null) { - return; - } - } - registerError(parameterList); - } - } -} diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/SimplifiableAnnotation.html b/plugins/InspectionGadgets/src/inspectionDescriptions/SimplifiableAnnotation.html new file mode 100644 index 000000000000..45847f410cfb --- /dev/null +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/SimplifiableAnnotation.html @@ -0,0 +1,8 @@ + +
+ +This inspection reports annotations which can be simplified to their 'single element' +or 'marker' shorthand form. Annotation that contain whitespace between the @-sign and the name +of the annotation are also reported. +
New in 10.1, Powered by InspectionGadgets
+ \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/simplifiable_annotation/SimplifiableAnnotation.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/simplifiable_annotation/SimplifiableAnnotation.java new file mode 100644 index 000000000000..8a3eb8a8c2e4 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/simplifiable_annotation/SimplifiableAnnotation.java @@ -0,0 +1,10 @@ +package com.siyeh.igtest.style.simplifiable_annotation; + +public class SimplifiableAnnotation { + + @ SuppressWarnings(value = "blabla") + @ Deprecated() + Object foo() { + return null; + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/simplifiable_annotation/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/simplifiable_annotation/expected.xml new file mode 100644 index 000000000000..cebedfafc00b --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/simplifiable_annotation/expected.xml @@ -0,0 +1,16 @@ + + + + SimplifiableAnnotation.java + 5 + Simplifiable annotation + Annotation <code>@ SuppressWarnings(value = "blabla")</code> may be replaced with '@SuppressWarnings(value = "blabla")' + + + + SimplifiableAnnotation.java + 6 + Simplifiable annotation + Annotation <code>@ Deprecated()</code> may be replaced with '@Deprecated' + + \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_annotation_parentheses/UnnecessaryAnnotationParentheses.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_annotation_parentheses/UnnecessaryAnnotationParentheses.java deleted file mode 100644 index 435f3ef55143..000000000000 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_annotation_parentheses/UnnecessaryAnnotationParentheses.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.siyeh.igtest.style.unnecessary_annotation_parentheses; - -import org.jetbrains.annotations.NotNull; - -public class UnnecessaryAnnotationParentheses { - - @Deprecated() - Object foo() { - return null; - } - - @SuppressWarnings() - String s; -} diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_annotation_parentheses/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_annotation_parentheses/expected.xml deleted file mode 100644 index 405af641dfec..000000000000 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_annotation_parentheses/expected.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - UnnecessaryAnnotationParentheses.java - 7 - Unnecessary annotation parentheses - <code>()</code> has unnecessary parentheses #loc - - \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/SimplifiableAnnotationInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/SimplifiableAnnotationInspectionTest.java new file mode 100644 index 000000000000..646cf7ec830e --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/SimplifiableAnnotationInspectionTest.java @@ -0,0 +1,11 @@ +package com.siyeh.ig.style; + +import com.IGInspectionTestCase; + +public class SimplifiableAnnotationInspectionTest extends IGInspectionTestCase { + + public void test() throws Exception { + doTest("com/siyeh/igtest/style/simplifiable_annotation", + new SimplifiableAnnotationInspection()); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryAnnotationParenthesesInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryAnnotationParenthesesInspectionTest.java deleted file mode 100644 index 9a41f42962d1..000000000000 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryAnnotationParenthesesInspectionTest.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.siyeh.ig.style; - -import com.IGInspectionTestCase; - -public class UnnecessaryAnnotationParenthesesInspectionTest extends IGInspectionTestCase { - - public void test() throws Exception { - doTest("com/siyeh/igtest/style/unnecessary_annotation_parentheses", - new UnnecessaryAnnotationParenthesesInspection()); - } -} \ No newline at end of file From d5cd85891ecbf0c7ab076f3cad32d1bbd0e8488c Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Mon, 13 Dec 2010 11:01:13 +0300 Subject: [PATCH 35/38] IDEA-62629 Switching soft wraps On and Off from a console toolbar does not update another opened console properly Soft wraps implied command line folding is applied to inactive console when soft wraps usage is toggled from the active one --- .../execution/impl/ConsoleViewImpl.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java index e08c4a7d677e..0bc22bbeea7c 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java @@ -1668,11 +1668,28 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo nextAction.getTemplatePresentation().setText(getNextOccurenceActionName()); final AnAction switchSoftWrapsAction = new ToggleUseSoftWrapsToolbarAction(SoftWrapAppliancePlaces.CONSOLE) { + + /** + * There is a possible case that more than console is open and user toggles soft wraps mode at one of them. We want + * to update another console(s) representation as well when they are switched on after that. Hence, we remember last + * used soft wraps mode and perform update if we see that the current value differs from the stored. + */ + private boolean myLastIsSelected; + @Override protected Editor getEditor(AnActionEvent e) { return myEditor; } + @Override + public boolean isSelected(AnActionEvent e) { + boolean result = super.isSelected(e); + if (result ^ myLastIsSelected) { + setSelected(null, result); + } + return myLastIsSelected = result; + } + @Override public void setSelected(AnActionEvent e, final boolean state) { super.setSelected(e, state); From e5d4d1a4a18f211869a20ea37977b9aaf5a67d5f Mon Sep 17 00:00:00 2001 From: nik Date: Mon, 13 Dec 2010 11:23:08 +0300 Subject: [PATCH 36/38] IDEA-62874: Unable to create a Module Library containing Jar Directories [rev by Pegov] --- .../intellij/openapi/roots/ui/configuration/ModuleEditor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModuleEditor.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModuleEditor.java index 59e25af14f35..6816f8112021 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModuleEditor.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModuleEditor.java @@ -30,6 +30,7 @@ import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ModuleRootModel; import com.intellij.openapi.roots.OrderEntry; import com.intellij.openapi.roots.impl.ModuleRootManagerImpl; +import com.intellij.openapi.roots.impl.libraries.LibraryTableBase; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.util.ActionCallback; @@ -427,7 +428,7 @@ public abstract class ModuleEditor implements Place.Navigator, Disposable { new LibraryInvocationHandler((Library)result)); } else if (result instanceof LibraryTable.ModifiableModel) { - return Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{LibraryTable.ModifiableModel.class}, + return Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{LibraryTableBase.ModifiableModelEx.class}, new LibraryTableModelInvocationHandler((LibraryTable.ModifiableModel)result)); } if (result instanceof Library[]) { From 2933526e62e69d8feacf78463712671fe953d2ab Mon Sep 17 00:00:00 2001 From: nik Date: Mon, 13 Dec 2010 11:23:35 +0300 Subject: [PATCH 37/38] fixed minimum size for library chooser dialog [rev by Pegov] --- .../intellij/util/ui/classpath/ChooseLibrariesDialogBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/util/ui/classpath/ChooseLibrariesDialogBase.java b/platform/lang-impl/src/com/intellij/util/ui/classpath/ChooseLibrariesDialogBase.java index cd06228cc62b..ad5ab6fdfc0e 100644 --- a/platform/lang-impl/src/com/intellij/util/ui/classpath/ChooseLibrariesDialogBase.java +++ b/platform/lang-impl/src/com/intellij/util/ui/classpath/ChooseLibrariesDialogBase.java @@ -173,7 +173,7 @@ public abstract class ChooseLibrariesDialogBase extends DialogWrapper { myTree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "ENTER"); myTree.getActionMap().put("ENTER", getOKAction()); final JScrollPane pane = ScrollPaneFactory.createScrollPane(myTree); - pane.setMinimumSize(new Dimension(300, 80)); + pane.setPreferredSize(new Dimension(300, 80)); return pane; } From e7cb7f66ced7106044bc8b8294f5104ff05d0c34 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Mon, 13 Dec 2010 12:07:17 +0300 Subject: [PATCH 38/38] IDEA-62830 AE at com.intellij.openapi.editor.impl.softwrap.mapping.SoftWrapApplianceManager.a 1. Ensuring that collapsed fold region may be soft wrapped all the time; 2. Corresponding test is added; --- .../mapping/SoftWrapApplianceManager.java | 22 ++++++++++++++----- ...apApplianceOnDocumentModificationTest.java | 15 +++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java index 1e1f076c5044..6c6da2a5a619 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java @@ -249,9 +249,14 @@ public class SoftWrapApplianceManager implements FoldingListener, DocumentListen myContext.logicalLineData.update(foldRegion.getStartOffset()); SoftWrap softWrap = registerSoftWrap( - myContext.softWrapStartOffset, myContext.tokenStartOffset, myContext.tokenStartOffset, myContext.getSpaceWidth(), myContext.logicalLineData + myContext.softWrapStartOffset, myContext.tokenStartOffset, myContext.tokenStartOffset, myContext.getSpaceWidth(), + myContext.logicalLineData ); - assert softWrap != null; // We expect that it's always possible to wrap collapsed fold region placeholder text + if (softWrap == null) { + // If we're here that means that we can't find appropriate soft wrap offset before the fold region. + // However, we expect that it's always possible to wrap collapsed fold region placeholder text + softWrap = registerSoftWrap(myContext.tokenStartOffset, myContext.getSpaceWidth(), myContext.logicalLineData); + } myContext.softWrapStartOffset = softWrap.getStart(); if (softWrap.getStart() < myContext.tokenStartOffset) { revertListeners(softWrap.getStart(), myContext.currentPosition.visualLine); @@ -524,19 +529,24 @@ public class SoftWrapApplianceManager implements FoldingListener, DocumentListen return null; } + return registerSoftWrap(softWrapOffset, spaceSize, lineData); + } + + @NotNull + private SoftWrap registerSoftWrap(int offset, int spaceSize, LogicalLineData lineData) { int indentInColumns = 0; int indentInPixels = myPainter.getMinDrawingWidth(SoftWrapDrawingType.AFTER_SOFT_WRAP); if (myCustomIndentUsedLastTime) { indentInColumns = myCustomIndentValueUsedLastTime + lineData.indentInColumns; indentInPixels += lineData.indentInPixels + (myCustomIndentValueUsedLastTime * spaceSize); } - SoftWrapImpl softWrap = new SoftWrapImpl( - new TextChangeImpl("\n" + StringUtil.repeatSymbol(' ', indentInColumns), softWrapOffset, softWrapOffset), + SoftWrapImpl result = new SoftWrapImpl( + new TextChangeImpl("\n" + StringUtil.repeatSymbol(' ', indentInColumns), offset, offset), indentInColumns + 1/* for 'after soft wrap' drawing */, indentInPixels ); - myStorage.storeOrReplace(softWrap, true); - return softWrap; + myStorage.storeOrReplace(result, true); + return result; } /** diff --git a/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java b/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java index 3f1faa390fbb..f051b7849536 100644 --- a/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java +++ b/platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java @@ -420,6 +420,21 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP assertEquals(startOffset, myEditor.logicalPositionToOffset(myEditor.visualToLogicalPosition(new VisualPosition(2, 0)))); } + public void testFoldRegionThatStartsAtLineEnd() throws IOException { + String text = + "line1\n" + + "line2\n" + + "line3\n" + + "line4\n" + + "line5"; + + init(30, text); + int start = text.indexOf("line3") - 1; + addCollapsedFoldRegion(start, text.length(), "..."); + assertEquals(1, getSoftWrapModel().getRegisteredSoftWraps().size()); + assertEquals(start, getSoftWrapModel().getRegisteredSoftWraps().get(0).getStart()); + } + public void testHomeProcessing() throws IOException { String text = "class Test {\n" +