From b4bbca203f5e603fede630bb3f6a8d7a0b7753f0 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 3 Feb 2012 12:13:55 +0400 Subject: [PATCH 01/35] EA-33013 Not clear were NPE could be here. Added @NotNull --- .../openapi/vcs/merge/MultipleFileMergeDialog.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java index c64484a612f4..4c0eb90ef6f8 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/merge/MultipleFileMergeDialog.java @@ -17,7 +17,6 @@ package com.intellij.openapi.vcs.merge; import com.intellij.CommonBundle; -import com.intellij.ide.impl.ProjectUtil; import com.intellij.ide.presentation.VirtualFilePresentation; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diff.ActionButtonPresentation; @@ -26,7 +25,6 @@ import com.intellij.openapi.diff.DiffRequestFactory; import com.intellij.openapi.diff.MergeRequest; import com.intellij.openapi.diff.impl.mergeTool.MergeVersion; import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ex.ProjectManagerEx; import com.intellij.openapi.ui.DialogWrapper; @@ -37,10 +35,9 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.VcsBundle; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; -import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vcs.history.VcsRevisionNumber; +import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.projectImport.ProjectOpenProcessor; import com.intellij.ui.ColoredTableCellRenderer; import com.intellij.ui.SimpleTextAttributes; import com.intellij.ui.components.JBLabel; @@ -49,6 +46,7 @@ import com.intellij.util.ui.ColumnInfo; import com.intellij.util.ui.ListTableModel; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -112,7 +110,8 @@ public class MultipleFileMergeDialog extends DialogWrapper { } }; - public MultipleFileMergeDialog(Project project, final List files, final MergeProvider provider, MergeDialogCustomizer mergeDialogCustomizer) { + public MultipleFileMergeDialog(@NotNull Project project, @NotNull final List files, @NotNull final MergeProvider provider, + @NotNull MergeDialogCustomizer mergeDialogCustomizer) { super(project, false); myProject = project; myProjectManager = ProjectManagerEx.getInstanceEx(); From 430e515799587e8650afdfd24cbd642a442b1350 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 3 Feb 2012 12:22:05 +0400 Subject: [PATCH 02/35] EA-32991 Better assertion to capture the NPE --- plugins/hg4idea/src/org/zmlx/hg4idea/HgFileStatusEnum.java | 5 ++++- .../src/org/zmlx/hg4idea/command/HgStatusCommand.java | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgFileStatusEnum.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgFileStatusEnum.java index 96674e4609a2..ba389c688d2d 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgFileStatusEnum.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgFileStatusEnum.java @@ -12,6 +12,8 @@ // limitations under the License. package org.zmlx.hg4idea; +import org.jetbrains.annotations.Nullable; + public enum HgFileStatusEnum { ADDED('A'), @@ -29,7 +31,8 @@ public enum HgFileStatusEnum { this.id = id; } - public static HgFileStatusEnum valueOf(char c) { + @Nullable + public static HgFileStatusEnum parse(char c) { for (HgFileStatusEnum status : HgFileStatusEnum.values()) { if (status.id == c) { return status; diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java index 25c336e26b36..ab65d753b4fd 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java @@ -160,7 +160,12 @@ public class HgStatusCommand { LOG.warn("Unexpected line in status '" + line + '\''); continue; } - HgFileStatusEnum status = HgFileStatusEnum.valueOf(line.charAt(STATUS_INDEX)); + char statusChar = line.charAt(STATUS_INDEX); + HgFileStatusEnum status = HgFileStatusEnum.parse(statusChar); + if (status == null) { + LOG.error("Unknown status [" + statusChar + "] in line [" + line + "]"); + continue; + } File ioFile = new File(repo.getPath(), line.substring(2)); if (HgFileStatusEnum.COPY == status && previous != null && previous.getStatus() == HgFileStatusEnum.ADDED) { From 329fcc54b722c43ada601b9b412c5cb23e2dca27 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 3 Feb 2012 14:19:50 +0400 Subject: [PATCH 03/35] Move the Notification extension to a static class. Not to hold the whole project in the case of memleak like IDEA-80753 --- .../src/git4idea/push/GitPushResult.java | 57 ++++++++++++------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/plugins/git4idea/src/git4idea/push/GitPushResult.java b/plugins/git4idea/src/git4idea/push/GitPushResult.java index 3d327d591431..68f9ee0380e3 100644 --- a/plugins/git4idea/src/git4idea/push/GitPushResult.java +++ b/plugins/git4idea/src/git4idea/push/GitPushResult.java @@ -280,30 +280,10 @@ class GitPushResult { sb.append("View files updated during the push"); } - NotificationListener viewUpdateFilesListener = new NotificationListener() { - @Override - public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { - if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { - if (event.getDescription().equals("UpdatedFiles")) { - ProjectLevelVcsManagerEx vcsManager = ProjectLevelVcsManagerEx.getInstanceEx(myProject); - UpdateInfoTree tree = vcsManager.showUpdateProjectInfo(updatedFiles, "Update", ActionInfo.UPDATE, false); - tree.setBefore(myBeforeUpdateLabel); - tree.setAfter(LocalHistory.getInstance().putSystemLabel(myProject, "After push")); - } - else { - BrowserUtil.launchBrowser(event.getDescription()); - } - } - } - }; + NotificationListener viewUpdateFilesListener = new ViewUpdatedFilesNotificationListener(updatedFiles); if (onlySuccess) { - // display tool window balloon - return new Notification(GitVcs.NOTIFICATION_GROUP_ID.getDisplayId(), title, sb.toString(), notificationType, viewUpdateFilesListener) { - @Override public boolean isImportant() { - return false; // don't highlight event log if push was totally successful - } - }; + return new MySuccessfulNotification(title, sb.toString(), notificationType, viewUpdateFilesListener); } return new Notification(GitVcs.IMPORTANT_ERROR_NOTIFICATION.getDisplayId(), title, sb.toString(), notificationType, viewUpdateFilesListener); @@ -380,4 +360,37 @@ class GitPushResult { return commitNum + " " + StringUtil.pluralize("commit", commitNum); } + private static class MySuccessfulNotification extends Notification { + public MySuccessfulNotification(@NotNull String title, @NotNull String message, @NotNull NotificationType notificationType, + @NotNull NotificationListener listener) { + super(GitVcs.NOTIFICATION_GROUP_ID.getDisplayId(), title, message, notificationType, listener); + } + + @Override public boolean isImportant() { + return false; // don't highlight event log if push was totally successful + } + } + + private class ViewUpdatedFilesNotificationListener implements NotificationListener { + private final UpdatedFiles myUpdatedFiles; + + public ViewUpdatedFilesNotificationListener(UpdatedFiles updatedFiles) { + myUpdatedFiles = updatedFiles; + } + + @Override + public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { + if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { + if (event.getDescription().equals("UpdatedFiles")) { + ProjectLevelVcsManagerEx vcsManager = ProjectLevelVcsManagerEx.getInstanceEx(myProject); + UpdateInfoTree tree = vcsManager.showUpdateProjectInfo(myUpdatedFiles, "Update", ActionInfo.UPDATE, false); + tree.setBefore(myBeforeUpdateLabel); + tree.setAfter(LocalHistory.getInstance().putSystemLabel(myProject, "After push")); + } + else { + BrowserUtil.launchBrowser(event.getDescription()); + } + } + } + } } From 1333d1206ec811b5852358f50dfd8c30de09b482 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 3 Feb 2012 16:33:58 +0400 Subject: [PATCH 04/35] GitBranchPopup UI enhancements: current branch and diverge warning 1. AbstractPopup#setWarning to display a warning message just below the title. 2. Remove fake actions "Current branch". Show current branch in the popup footer. 3. Remove fake action "Branches have diverged". Use AbstractPopup#setWarning instead. 4. Change wording a bit. 5. Remove redundant code & warnings, some extract method refactorings in GitBranchPopup(). --- .../com/intellij/ui/popup/AbstractPopup.java | 10 ++ .../git4idea/ui/branch/GitBranchPopup.java | 123 +++++++++--------- .../ui/branch/GitBranchPopupActions.java | 35 +++-- 3 files changed, 85 insertions(+), 83 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index 70e663cdfc5f..6b5792b4c262 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java @@ -38,6 +38,7 @@ import com.intellij.openapi.wm.impl.IdeFrameImpl; import com.intellij.openapi.wm.impl.IdeGlassPaneImpl; import com.intellij.ui.*; import com.intellij.ui.awt.RelativePoint; +import com.intellij.ui.components.JBLabel; import com.intellij.ui.speedSearch.SpeedSearch; import com.intellij.util.ImageLoader; import com.intellij.util.Processor; @@ -1494,6 +1495,15 @@ public class AbstractPopup implements JBPopup { if (doRevalidate) myContent.revalidate(); } + + public void setWarning(@NotNull String text) { + JBLabel label = new JBLabel(text, UIUtil.getBalloonWarningIcon(), SwingConstants.CENTER); + Color color = HintUtil.INFORMATION_COLOR; + label.setOpaque(true); + label.setBackground(color); + label.setBorder(BorderFactory.createLineBorder(color, 3)); + myHeaderPanel.add(label, BorderLayout.SOUTH); + } public void addListener(final JBPopupListener listener) { myListeners.add(listener); diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopup.java b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopup.java index c31352bbd3a2..f28fb4f950ce 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopup.java +++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopup.java @@ -23,13 +23,12 @@ import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.actionSystem.impl.SimpleDataContext; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.ShowSettingsUtil; -import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.ListPopup; import com.intellij.openapi.util.IconLoader; +import com.intellij.ui.popup.list.ListPopupImpl; import git4idea.GitVcs; import git4idea.config.GitVcsSettings; import git4idea.repo.GitRepository; @@ -38,6 +37,7 @@ import git4idea.util.GitUIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import javax.swing.event.HyperlinkEvent; import java.util.List; @@ -53,12 +53,14 @@ import java.util.List; */ class GitBranchPopup { - private static final Logger LOG = Logger.getInstance(GitBranchPopup.class); - private final Project myProject; + private final GitRepositoryManager myRepositoryManager; + private final GitVcsSettings myVcsSettings; + private final GitVcs myVcs; + private final GitMultiRootBranchConfig myMultiRootBranchConfig; + private final GitRepository myCurrentRepository; - private final ListPopup myPopup; - private GitMultiRootBranchConfig myMultiRootBranchConfig; + private final ListPopupImpl myPopup; ListPopup asListPopup() { return myPopup; @@ -76,31 +78,63 @@ class GitBranchPopup { private GitBranchPopup(@NotNull Project project, @NotNull GitRepository currentRepository) { myProject = project; myCurrentRepository = currentRepository; + myRepositoryManager = GitRepositoryManager.getInstance(project); + myVcs = GitVcs.getInstance(project); + myVcsSettings = GitVcsSettings.getInstance(myProject); - GitRepositoryManager repositoryManager = GitRepositoryManager.getInstance(project); - myMultiRootBranchConfig = new GitMultiRootBranchConfig(repositoryManager.getRepositories()); - - String title = "Git Branches"; - if (repositoryManager.moreThanOneRoot() && (myMultiRootBranchConfig.diverged() || getSyncSetting() == GitBranchSyncSetting.DONT)) { - title += " on [" + GitUIUtil.getShortRepositoryName(currentRepository) + "]"; - } + myMultiRootBranchConfig = new GitMultiRootBranchConfig(myRepositoryManager.getRepositories()); - myPopup = JBPopupFactory.getInstance().createActionGroupPopup( + String title = createPopupTitle(currentRepository); + + myPopup = (ListPopupImpl) JBPopupFactory.getInstance().createActionGroupPopup( title, createActions(), SimpleDataContext.getProjectContext(project), JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, true); - if (repositoryManager.moreThanOneRoot() && getSyncSetting() == GitBranchSyncSetting.NOT_DECIDED) { + initBranchSyncPolicyIfNotInitialized(); + setCurrentBranchInfo(); + warnThatBranchesDivergedIfNeeded(); + } + + private void initBranchSyncPolicyIfNotInitialized() { + if (myRepositoryManager.moreThanOneRoot() && myVcsSettings.getSyncSetting() == GitBranchSyncSetting.NOT_DECIDED) { if (!myMultiRootBranchConfig.diverged()) { notifyAboutSyncedBranches(); - GitVcsSettings.getInstance(project).setSyncSetting(GitBranchSyncSetting.SYNC); + myVcsSettings.setSyncSetting(GitBranchSyncSetting.SYNC); } else { - GitVcsSettings.getInstance(project).setSyncSetting(GitBranchSyncSetting.DONT); + myVcsSettings.setSyncSetting(GitBranchSyncSetting.DONT); } } } + @NotNull + private String createPopupTitle(@NotNull GitRepository currentRepository) { + String title = "Git Branches"; + if (myRepositoryManager.moreThanOneRoot() && + (myMultiRootBranchConfig.diverged() || myVcsSettings.getSyncSetting() == GitBranchSyncSetting.DONT)) { + title += " in " + GitUIUtil.getShortRepositoryName(currentRepository); + } + return title; + } + + private void setCurrentBranchInfo() { + String currentBranchText = "Current branch"; + if (myRepositoryManager.moreThanOneRoot()) { + if (myMultiRootBranchConfig.diverged()) { + currentBranchText += " in " + GitUIUtil.getShortRepositoryName(myCurrentRepository) + ": " + + GitBranchUiUtil.getDisplayableBranchText(myCurrentRepository); + } + else { + currentBranchText += ": " + myMultiRootBranchConfig.getCurrentBranch(); + } + } + else { + currentBranchText += ": " + GitBranchUiUtil.getDisplayableBranchText(myCurrentRepository); + } + myPopup.setAdText(currentBranchText, SwingConstants.CENTER); + } + private void notifyAboutSyncedBranches() { GitVcs.IMPORTANT_ERROR_NOTIFICATION.createNotification("Synchronous branch control enabled", "You have several Git roots in the project and they all are checked out at the same branch. " + @@ -109,8 +143,8 @@ class GitBranchPopup { NotificationType.INFORMATION, new NotificationListener() { @Override public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - ShowSettingsUtil.getInstance().showSettingsDialog(myProject, GitVcs.getInstance(myProject).getConfigurable().getDisplayName()); - if (getSyncSetting() == GitBranchSyncSetting.DONT) { + ShowSettingsUtil.getInstance().showSettingsDialog(myProject, myVcs.getConfigurable().getDisplayName()); + if (myVcsSettings.getSyncSetting() == GitBranchSyncSetting.DONT) { notification.expire(); } } @@ -118,11 +152,6 @@ class GitBranchPopup { }).notify(myProject); } - @NotNull - private GitBranchSyncSetting getSyncSetting() { - return GitVcsSettings.getInstance(myProject).getSyncSetting(); - } - private ActionGroup createActions() { DefaultActionGroup popupGroup = new DefaultActionGroup(null, false); @@ -133,10 +162,6 @@ class GitBranchPopup { fillWithCommonRepositoryActions(popupGroup, repositoryManager); } else { - if (myMultiRootBranchConfig.diverged() && userWantsSyncControl()) { - warnThatBranchesDiverged(popupGroup); - } - fillPopupWithCurrentRepositoryActions(popupGroup, createRepositoriesActions()); } } @@ -145,19 +170,17 @@ class GitBranchPopup { } popupGroup.addSeparator(); - //popupGroup.addAction(new ConfigureAction()); return popupGroup; } private boolean userWantsSyncControl() { - return (getSyncSetting() != GitBranchSyncSetting.DONT); + return (myVcsSettings.getSyncSetting() != GitBranchSyncSetting.DONT); } private void fillWithCommonRepositoryActions(DefaultActionGroup popupGroup, GitRepositoryManager repositoryManager) { List repositories = repositoryManager.getRepositories(); String currentBranch = myMultiRootBranchConfig.getCurrentBranch(); assert currentBranch != null : "Current branch can't be null if branches have not diverged"; - popupGroup.add(new GitBranchPopupActions.CurrentBranchAction(currentBranch, " in all roots")); popupGroup.add(new GitBranchPopupActions.NewBranchAction(myProject, repositories, myCurrentRepository)); popupGroup.addAll(createRepositoriesActions()); @@ -175,9 +198,10 @@ class GitBranchPopup { } } - private void warnThatBranchesDiverged(@NotNull DefaultActionGroup popupGroup) { - popupGroup.add(new BranchesHaveDivergedMessage(myCurrentRepository)); - popupGroup.addSeparator(); + private void warnThatBranchesDivergedIfNeeded() { + if (myMultiRootBranchConfig.diverged() && userWantsSyncControl()) { + myPopup.setWarning("Branches have diverged"); + } } private DefaultActionGroup createRepositoriesActions() { @@ -218,38 +242,7 @@ class GitBranchPopup { ActionGroup group = new GitBranchPopupActions(myRepository.getProject(), myRepository).createActions(null); return group.getChildren(e); } - } - private static class BranchesHaveDivergedMessage extends DumbAwareAction { - - BranchesHaveDivergedMessage(GitRepository currentRepository) { - super("Branches have diverged, showing current root " + GitUIUtil.getShortRepositoryName(currentRepository), "", IconLoader.getIcon("/general/ideFatalError.png")); - } - - @Override - public void actionPerformed(AnActionEvent e) { - } - - @Override public void update(AnActionEvent e) { - e.getPresentation().setEnabled(false); // this action works as a label - } - } - - /** - * "Configure" opens a dialog to configure branches in the repository, i.e. set up tracked branches, fetch/push branches, etc. - */ - private static class ConfigureAction extends DumbAwareAction { - public ConfigureAction() { - super("Configure", null, IconLoader.getIcon("/general/ideOptions.png")); // TODO description - } - - @Override public void actionPerformed(AnActionEvent e) { - } - - @Override - public void update(AnActionEvent e) { - //e.getPresentation().setVisible(false); - } } } diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java index e1dda0d03b4e..efdd34f94929 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java +++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java @@ -27,7 +27,6 @@ import com.intellij.openapi.util.IconLoader; import git4idea.GitBranch; import git4idea.branch.GitBranchOperationsProcessor; import git4idea.repo.GitRepository; -import git4idea.util.GitUIUtil; import git4idea.validators.GitNewBranchNameValidator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -54,7 +53,7 @@ class GitBranchPopupActions { ActionGroup createActions(@Nullable DefaultActionGroup toInsert) { DefaultActionGroup popupGroup = new DefaultActionGroup(null, false); - popupGroup.addAction(new CurrentBranchAction(GitBranchUiUtil.getDisplayableBranchText(myRepository), "in root " + GitUIUtil.getShortRepositoryName(myRepository))); + //popupGroup.addAction(new CurrentBranchAction(GitBranchUiUtil.getDisplayableBranchText(myRepository), "in root " + GitUIUtil.getShortRepositoryName(myRepository))); popupGroup.addAction(new NewBranchAction(myProject, Collections.singletonList(myRepository), myRepository)); popupGroup.addAction(new CheckoutRevisionActions(myProject, myRepository)); @@ -81,22 +80,22 @@ class GitBranchPopupActions { return popupGroup; } - /** - * "Current branch:" item which is disabled and is just a label to display the current branch. - */ - static class CurrentBranchAction extends DumbAwareAction { - CurrentBranchAction(@NotNull String currentBranchName, @Nullable String rootName) { - super("", String.format("Current branch is %s %s", currentBranchName, rootName), null); - getTemplatePresentation().setText("Current Branch: " + currentBranchName, false); // no mnemonics - } - - @Override public void actionPerformed(AnActionEvent e) { - } - - @Override public void update(AnActionEvent e) { - e.getPresentation().setEnabled(false); // this action works as a label - } - } + ///** + // * "Current branch:" item which is disabled and is just a label to display the current branch. + // */ + //static class CurrentBranchAction extends DumbAwareAction { + // CurrentBranchAction(@NotNull String currentBranchName, @Nullable String rootName) { + // super("", String.format("Current branch is %s %s", currentBranchName, rootName), null); + // getTemplatePresentation().setText("Current Branch: " + currentBranchName, false); // no mnemonics + // } + // + // @Override public void actionPerformed(AnActionEvent e) { + // } + // + // @Override public void update(AnActionEvent e) { + // e.getPresentation().setEnabled(false); // this action works as a label + // } + //} static class NewBranchAction extends DumbAwareAction { private final Project myProject; From 381a435b99dca5e468b36a5462768fa1129dd4ba Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 3 Feb 2012 17:04:49 +0400 Subject: [PATCH 05/35] GitFetcher: successful notification should be INFO --- plugins/git4idea/src/git4idea/update/GitFetcher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/git4idea/src/git4idea/update/GitFetcher.java b/plugins/git4idea/src/git4idea/update/GitFetcher.java index 6073c2d1bfe2..b27459f8d91a 100644 --- a/plugins/git4idea/src/git4idea/update/GitFetcher.java +++ b/plugins/git4idea/src/git4idea/update/GitFetcher.java @@ -132,7 +132,7 @@ public class GitFetcher { @NotNull GitFetchResult result, @Nullable String errorNotificationTitle, @NotNull Collection errors) { if (result.isSuccess()) { - GitVcs.NOTIFICATION_GROUP_ID.createNotification("Fetched successfully", NotificationType.WARNING).notify(project); + GitVcs.NOTIFICATION_GROUP_ID.createNotification("Fetched successfully", NotificationType.INFORMATION).notify(project); } else if (result.isCancelled()) { GitVcs.NOTIFICATION_GROUP_ID.createNotification("Fetch cancelled by user", NotificationType.WARNING).notify(project); } else if (result.isNotAuthorized()) { From 5ba1cf4144cb3ff785bffc259012c94358d207df Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 3 Feb 2012 17:06:11 +0400 Subject: [PATCH 06/35] Sort CheckoutProviders by name correctly - including mnemonics DRY: move the common comparator to CheckoutProvider --- .../src/com/intellij/openapi/vcs/CheckoutProvider.java | 9 +++++++++ .../openapi/vcs/checkout/CheckoutActionGroup.java | 8 +------- .../openapi/wm/impl/welcomeScreen/GetFromVcsAction.java | 8 +------- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/CheckoutProvider.java b/platform/vcs-api/src/com/intellij/openapi/vcs/CheckoutProvider.java index 653ffbd70cdc..cda70a244b76 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/CheckoutProvider.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/CheckoutProvider.java @@ -22,6 +22,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.util.Comparator; + +import static com.intellij.ui.GuiUtils.getTextWithoutMnemonicEscaping; /** * Implement this interface and register it as extension to checkoutProvider extension point in order to provide checkout @@ -37,4 +40,10 @@ public interface CheckoutProvider { void directoryCheckedOut(File directory, VcsKey vcs); void checkoutCompleted(); } + + class CheckoutProviderComparator implements Comparator { + public int compare(final CheckoutProvider o1, final CheckoutProvider o2) { + return getTextWithoutMnemonicEscaping(o1.getVcsName()).compareTo(getTextWithoutMnemonicEscaping(o2.getVcsName())); + } + } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/CheckoutActionGroup.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/CheckoutActionGroup.java index cd043d408b28..5fbf2bccad7d 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/CheckoutActionGroup.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/CheckoutActionGroup.java @@ -24,7 +24,6 @@ import com.intellij.openapi.vcs.CheckoutProvider; import org.jetbrains.annotations.Nullable; import java.util.Arrays; -import java.util.Comparator; public class CheckoutActionGroup extends ActionGroup implements DumbAware { @@ -41,12 +40,7 @@ public class CheckoutActionGroup extends ActionGroup implements DumbAware { public AnAction[] getChildren(@Nullable AnActionEvent e) { if (myChildren == null) { final CheckoutProvider[] providers = Extensions.getExtensions(CheckoutProvider.EXTENSION_POINT_NAME); - Arrays.sort(providers, new Comparator() { - public int compare(final CheckoutProvider o1, final CheckoutProvider o2) { - // not strict but will do - return o1.getVcsName().compareTo(o2.getVcsName()); - } - }); + Arrays.sort(providers, new CheckoutProvider.CheckoutProviderComparator()); myChildren = new AnAction[providers.length]; for (int i = 0; i < providers.length; i++) { CheckoutProvider provider = providers[i]; diff --git a/platform/vcs-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/GetFromVcsAction.java b/platform/vcs-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/GetFromVcsAction.java index 966a58abfc8b..07e0ed737d48 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/GetFromVcsAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/GetFromVcsAction.java @@ -22,18 +22,12 @@ import com.intellij.openapi.vcs.checkout.CheckoutAction; import com.intellij.ui.UIBundle; import java.util.Arrays; -import java.util.Comparator; public class GetFromVcsAction extends WelcomePopupAction{ protected void fillActions(DefaultActionGroup group) { final CheckoutProvider[] providers = Extensions.getExtensions(CheckoutProvider.EXTENSION_POINT_NAME); - Arrays.sort(providers, new Comparator() { - public int compare(final CheckoutProvider o1, final CheckoutProvider o2) { - // not strict but will do - return o1.getVcsName().compareTo(o2.getVcsName()); - } - }); + Arrays.sort(providers, new CheckoutProvider.CheckoutProviderComparator()); for (CheckoutProvider provider : providers) { group.add(new CheckoutAction(provider)); } From adf83b92e7d771410461f582c75b4408754f732c Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Fri, 3 Feb 2012 17:24:12 +0400 Subject: [PATCH 07/35] IDEA-80828 --- .../src/com/intellij/uiDesigner/actions/CreateFormAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/CreateFormAction.java b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/CreateFormAction.java index 7f762f65bb6c..04a9fd8bb513 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/CreateFormAction.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/CreateFormAction.java @@ -86,7 +86,7 @@ public class CreateFormAction extends AbstractCreateFormAction { final String packageName = aPackage.getQualifiedName(); String fqClassName = null; if (myLastClassName != null) { - fqClassName = packageName.length() == 0 ? newName : packageName + "." + myLastClassName; + fqClassName = packageName.length() == 0 ? myLastClassName : packageName + "." + myLastClassName; } final String formBody = createFormBody(fqClassName, "/com/intellij/uiDesigner/NewForm.xml", From f1f6eba38576a792ebf73e98c4cb1df3290f0253 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 3 Feb 2012 18:12:27 +0400 Subject: [PATCH 08/35] missed return --- platform/platform-impl/src/com/intellij/idea/RareLogger.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-impl/src/com/intellij/idea/RareLogger.java b/platform/platform-impl/src/com/intellij/idea/RareLogger.java index a18948341a24..88bddb4743af 100644 --- a/platform/platform-impl/src/com/intellij/idea/RareLogger.java +++ b/platform/platform-impl/src/com/intellij/idea/RareLogger.java @@ -52,6 +52,7 @@ public class RareLogger extends Logger { if (fairSynch) { synchronized (lock) { super.put(key, value); + return; } } super.put(key, value); From acb8c78d971013d5ae88744c2a1dfb6eec6d3064 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Thu, 2 Feb 2012 17:23:28 +0400 Subject: [PATCH 09/35] IDEA-79943 restart daemon code analyzer after switching html language level --- .../codeInspection/htmlInspections/SwitchToHtml5Action.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xml/impl/src/com/intellij/codeInspection/htmlInspections/SwitchToHtml5Action.java b/xml/impl/src/com/intellij/codeInspection/htmlInspections/SwitchToHtml5Action.java index 9d411f5d2d63..cf6bee3dc81b 100644 --- a/xml/impl/src/com/intellij/codeInspection/htmlInspections/SwitchToHtml5Action.java +++ b/xml/impl/src/com/intellij/codeInspection/htmlInspections/SwitchToHtml5Action.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInspection.htmlInspections; +import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; import com.intellij.codeInsight.daemon.XmlErrorMessages; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.LocalQuickFix; @@ -72,5 +73,6 @@ public class SwitchToHtml5Action implements LocalQuickFix, IntentionAction { private static void applyFix(Project project) { ExternalResourceManagerEx.getInstanceEx().setDefaultHtmlDoctype(Html5SchemaProvider.HTML5_SCHEMA_LOCATION, project); + DaemonCodeAnalyzer.getInstance(project).restart(); } } From 913119762943639e50d46b04f708e0ddac78f072 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Thu, 2 Feb 2012 20:01:28 +0400 Subject: [PATCH 10/35] android: source autogenerating queue per module --- .../AndroidRegenerateRJavaFileAction.java | 1 + .../android/compiler/AndroidCompileUtil.java | 60 ++++++++++++------- .../jetbrains/android/facet/AndroidFacet.java | 11 ++++ .../android/facet/AndroidFacetEditorTab.java | 26 ++++---- 4 files changed, 59 insertions(+), 39 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/actions/AndroidRegenerateRJavaFileAction.java b/plugins/android/src/org/jetbrains/android/actions/AndroidRegenerateRJavaFileAction.java index 4b89bcdf5c41..43597a15b8b3 100644 --- a/plugins/android/src/org/jetbrains/android/actions/AndroidRegenerateRJavaFileAction.java +++ b/plugins/android/src/org/jetbrains/android/actions/AndroidRegenerateRJavaFileAction.java @@ -95,6 +95,7 @@ public class AndroidRegenerateRJavaFileAction extends AnAction { CompilerManager.getInstance(project).executeTask(new CompileTask() { @Override public boolean execute(CompileContext context) { + // todo: compatibility with background autogenerating AndroidCompileUtil.generate(new AndroidAptCompiler(), context); return true; } diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidCompileUtil.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidCompileUtil.java index 726a42a95bc2..e3f16dc3d50c 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidCompileUtil.java +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidCompileUtil.java @@ -47,6 +47,7 @@ import com.intellij.psi.search.FileTypeIndex; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.HashSet; +import com.intellij.util.ui.update.Update; import org.jetbrains.android.AndroidProjectComponent; import org.jetbrains.android.dom.resources.Attr; import org.jetbrains.android.dom.resources.DeclareStyleable; @@ -352,13 +353,26 @@ public class AndroidCompileUtil { } public static void generate(final Module module, final GeneratingCompiler compiler) { + final AndroidFacet facet = AndroidFacet.getInstance(module); + + if (facet != null) { + facet.scheduleGeneratingActivity(new Update(Pair.create(module, compiler.getClass())) { + @Override + public void run() { + doGenerate(module, compiler); + } + }); + } + } + + private static void doGenerate(final Module module, final GeneratingCompiler compiler) { final Project project = module.getProject(); final AndroidProjectComponent component = ApplicationManager.getApplication().runReadAction(new Computable() { @Nullable @Override public AndroidProjectComponent compute() { return !project.isDisposed() ? project.getComponent(AndroidProjectComponent.class) : null; - } + } }); if (component == null) { return; @@ -693,33 +707,33 @@ public class AndroidCompileUtil { } for (final Resources resources : manager.getResourceElements()) { - waitForSmartMode(project); + waitForSmartMode(project); - ApplicationManager.getApplication().runReadAction(new Runnable() { - @Override - public void run() { - if (!resources.isValid() || facet.getModule().isDisposed() || project.isDisposed()) { - return; - } + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + if (!resources.isValid() || facet.getModule().isDisposed() || project.isDisposed()) { + return; + } - for (final Attr attr : resources.getAttrs()) { - final String name = attr.getName().getValue(); + for (final Attr attr : resources.getAttrs()) { + final String name = attr.getName().getValue(); - if (name != null) { - resourceSet.add(new ResourceEntry(ResourceType.ATTR.getName(), name)); + if (name != null) { + resourceSet.add(new ResourceEntry(ResourceType.ATTR.getName(), name)); + } + } + + for (final DeclareStyleable styleable : resources.getDeclareStyleables()) { + final String name = styleable.getName().getValue(); + + if (name != null) { + resourceSet.add(new ResourceEntry(ResourceType.DECLARE_STYLEABLE.getName(), name)); + } } } - - for (final DeclareStyleable styleable : resources.getDeclareStyleables()) { - final String name = styleable.getName().getValue(); - - if (name != null) { - resourceSet.add(new ResourceEntry(ResourceType.DECLARE_STYLEABLE.getName(), name)); - } - } - } - }); - } + }); + } waitForSmartMode(project); diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacet.java b/plugins/android/src/org/jetbrains/android/facet/AndroidFacet.java index 371077fede8e..97911b325410 100644 --- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacet.java +++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacet.java @@ -69,6 +69,8 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.Processor; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.HashSet; +import com.intellij.util.ui.update.MergingUpdateQueue; +import com.intellij.util.ui.update.Update; import com.intellij.util.xml.ConvertContext; import com.intellij.util.xml.DomElement; import org.jetbrains.android.compiler.*; @@ -107,10 +109,14 @@ public class AndroidFacet extends Facet { private final Map> myClassMaps = new HashMap>(); private final Object myClassMapLock = new Object(); + + private final MergingUpdateQueue mySourcesAutogeneratingQueue; public AndroidFacet(@NotNull Module module, String name, @NotNull AndroidFacetConfiguration configuration) { super(getFacetType(), module, name, configuration, null); configuration.setFacet(this); + + mySourcesAutogeneratingQueue = new MergingUpdateQueue("AndroidSourcesAutogeneratingQueue", 300, true, null, this, null, false); } @Nullable @@ -710,4 +716,9 @@ public class AndroidFacet extends Facet { String moduleDirPath = getModuleDirPath(); return moduleDirPath != null ? FileUtil.toSystemDependentName(moduleDirPath + path) : null; } + + public void scheduleGeneratingActivity(@NotNull Update update) { + mySourcesAutogeneratingQueue.flush(); + mySourcesAutogeneratingQueue.queue(update); + } } diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java index 658462b9787c..26cf05e4d4c8 100644 --- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java +++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java @@ -18,7 +18,6 @@ package org.jetbrains.android.facet; import com.android.sdklib.SdkConstants; import com.intellij.facet.ui.FacetEditorContext; import com.intellij.facet.ui.FacetEditorTab; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; @@ -432,22 +431,17 @@ public class AndroidFacetEditorTab extends FacetEditorTab { runApt = runApt && myConfiguration.REGENERATE_R_JAVA && AndroidAptCompiler.isToCompileModule(myContext.getModule(), myConfiguration); runIdl = runIdl && myConfiguration.REGENERATE_JAVA_BY_AIDL; + if (runApt || runIdl) { - final boolean finalRunApt = runApt; - final boolean finalRunIdl = runIdl; - ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { - @Override - public void run() { - Module module = myContext.getModule(); - Project project = module.getProject(); - if (finalRunApt) { - AndroidCompileUtil.generate(module, new AndroidAptCompiler(), true); - } - if (finalRunIdl) { - AndroidCompileUtil.generate(module, new AndroidIdlCompiler(project)); - } - } - }); + final Module module = myContext.getModule(); + final Project project = module.getProject(); + + if (runApt) { + AndroidCompileUtil.generate(module, new AndroidAptCompiler(), true); + } + if (runIdl) { + AndroidCompileUtil.generate(module, new AndroidIdlCompiler(project)); + } } } From 46eba1dce8e48faa902dd2118295228d32f2379d Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Fri, 3 Feb 2012 16:00:01 +0400 Subject: [PATCH 11/35] android autogenerating: separate queue for every generating compiler --- .../android/compiler/AndroidCompileUtil.java | 10 +---- .../jetbrains/android/facet/AndroidFacet.java | 42 ++++++++++++++++--- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidCompileUtil.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidCompileUtil.java index e3f16dc3d50c..90a34eef8812 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidCompileUtil.java +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidCompileUtil.java @@ -47,7 +47,6 @@ import com.intellij.psi.search.FileTypeIndex; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.HashSet; -import com.intellij.util.ui.update.Update; import org.jetbrains.android.AndroidProjectComponent; import org.jetbrains.android.dom.resources.Attr; import org.jetbrains.android.dom.resources.DeclareStyleable; @@ -356,16 +355,11 @@ public class AndroidCompileUtil { final AndroidFacet facet = AndroidFacet.getInstance(module); if (facet != null) { - facet.scheduleGeneratingActivity(new Update(Pair.create(module, compiler.getClass())) { - @Override - public void run() { - doGenerate(module, compiler); - } - }); + facet.scheduleSourceRegenerating(compiler); } } - private static void doGenerate(final Module module, final GeneratingCompiler compiler) { + public static void doGenerate(final Module module, final GeneratingCompiler compiler) { final Project project = module.getProject(); final AndroidProjectComponent component = ApplicationManager.getApplication().runReadAction(new Computable() { @Nullable diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacet.java b/plugins/android/src/org/jetbrains/android/facet/AndroidFacet.java index 97911b325410..93b5d88c5c62 100644 --- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacet.java +++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacet.java @@ -37,6 +37,7 @@ import com.intellij.facet.FacetTypeRegistry; import com.intellij.lang.properties.IProperty; import com.intellij.lang.properties.psi.PropertiesFile; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.compiler.GeneratingCompiler; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; @@ -73,7 +74,10 @@ import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.Update; import com.intellij.util.xml.ConvertContext; import com.intellij.util.xml.DomElement; -import org.jetbrains.android.compiler.*; +import org.jetbrains.android.compiler.AndroidAptCompiler; +import org.jetbrains.android.compiler.AndroidCompileUtil; +import org.jetbrains.android.compiler.AndroidIdlCompiler; +import org.jetbrains.android.compiler.AndroidRenderscriptCompiler; import org.jetbrains.android.dom.manifest.Manifest; import org.jetbrains.android.importDependencies.ImportDependenciesUtil; import org.jetbrains.android.resourceManagers.LocalResourceManager; @@ -110,13 +114,26 @@ public class AndroidFacet extends Facet { private final Object myClassMapLock = new Object(); - private final MergingUpdateQueue mySourcesAutogeneratingQueue; + private final Map, MergingUpdateQueue> mySourcesAutogeneratingQueueMap = new HashMap, MergingUpdateQueue>(); public AndroidFacet(@NotNull Module module, String name, @NotNull AndroidFacetConfiguration configuration) { super(getFacetType(), module, name, configuration, null); configuration.setFacet(this); - mySourcesAutogeneratingQueue = new MergingUpdateQueue("AndroidSourcesAutogeneratingQueue", 300, true, null, this, null, false); + mySourcesAutogeneratingQueueMap.put(AndroidAptCompiler.class, createSourceGeneratingQueue("AndroidAptAutogeneratingQueue")); + mySourcesAutogeneratingQueueMap.put(AndroidIdlCompiler.class, createSourceGeneratingQueue("AndroidIdlAutogeneratingQueue")); + mySourcesAutogeneratingQueueMap + .put(AndroidRenderscriptCompiler.class, createSourceGeneratingQueue("AndroidRenderscriptAutogeneratingQueue")); + } + + private MergingUpdateQueue createSourceGeneratingQueue(@NotNull String name) { + return new MergingUpdateQueue(name, 1000, false, null, this, null, false); + } + + private void activateSourceAutogenerating() { + for (MergingUpdateQueue queue : mySourcesAutogeneratingQueueMap.values()) { + queue.activate(); + } } @Nullable @@ -372,6 +389,8 @@ public class AndroidFacet extends Facet { AndroidCompileUtil.generate(module, new AndroidIdlCompiler(project)); } AndroidCompileUtil.generate(module, new AndroidRenderscriptCompiler()); + + activateSourceAutogenerating(); } }); } @@ -717,8 +736,19 @@ public class AndroidFacet extends Facet { return moduleDirPath != null ? FileUtil.toSystemDependentName(moduleDirPath + path) : null; } - public void scheduleGeneratingActivity(@NotNull Update update) { - mySourcesAutogeneratingQueue.flush(); - mySourcesAutogeneratingQueue.queue(update); + public void scheduleSourceRegenerating(@NotNull final GeneratingCompiler compiler) { + final MergingUpdateQueue queue = mySourcesAutogeneratingQueueMap.get(compiler.getClass()); + + if (queue == null) { + LOG.error("Autogenerating is not supported for compiler " + compiler.getClass().getCanonicalName()); + } + else { + queue.queue(new Update(Pair.create(compiler.getClass(), getModule())) { + @Override + public void run() { + AndroidCompileUtil.doGenerate(getModule(), compiler); + } + }); + } } } From afb8a6f7b4a86b40148b10f69ac4c83909bf1527 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Fri, 3 Feb 2012 18:10:16 +0400 Subject: [PATCH 12/35] compiler is unique for one queue --- .../android/src/org/jetbrains/android/facet/AndroidFacet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacet.java b/plugins/android/src/org/jetbrains/android/facet/AndroidFacet.java index 93b5d88c5c62..7b03bcc7f15c 100644 --- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacet.java +++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacet.java @@ -743,7 +743,7 @@ public class AndroidFacet extends Facet { LOG.error("Autogenerating is not supported for compiler " + compiler.getClass().getCanonicalName()); } else { - queue.queue(new Update(Pair.create(compiler.getClass(), getModule())) { + queue.queue(new Update(this) { @Override public void run() { AndroidCompileUtil.doGenerate(getModule(), compiler); From b5ec833ebf4be9696f2ac1b546c5a34c77afbe73 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Fri, 3 Feb 2012 18:14:49 +0400 Subject: [PATCH 13/35] create stub resource field to resolve resource reference immediately after extracting --- .../AndroidAddStringResourceAction.java | 54 ++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java b/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java index 08e641d87637..0ba132425390 100644 --- a/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java +++ b/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java @@ -39,8 +39,10 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlAttributeValue; import com.intellij.psi.xml.XmlFile; @@ -218,7 +220,7 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction impl } if (file instanceof PsiJavaFile) { - createJavaResourceReference(project, editor, file, element, aPackage, resName, ResourceType.STRING.getName()); + createJavaResourceReference(facet.getModule(), editor, file, element, aPackage, resName, ResourceType.STRING.getName()); } else { final XmlAttribute attribute = PsiTreeUtil.getParentOfType(element, XmlAttribute.class); @@ -237,19 +239,28 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction impl }); } - private static void createJavaResourceReference(final Project project, + private static void createJavaResourceReference(final Module module, final Editor editor, final PsiFile file, final PsiElement element, - String aPackage, - String resName, - String resType) { + final String aPackage, + final String resName, + final String resType) { final boolean extendsContext = getContainingInheritorOf(element, CONTEXT) != null; - final String field = aPackage + ".R." + resType + '.' + AndroidResourceUtil.getRJavaFieldName(resName); + final String rJavaFieldName = AndroidResourceUtil.getRJavaFieldName(resName); + final String field = aPackage + ".R." + resType + '.' + rJavaFieldName; final String methodName = getGetterNameForResourceType(resType); assert methodName != null; final TemplateImpl template; final boolean inStaticContext = RefactoringUtil.isInStaticContext(element, null); + final Project project = module.getProject(); + + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + createStubResourceField(module, aPackage, resType, rJavaFieldName); + } + }); if (extendsContext && !inStaticContext) { if (ResourceType.STRING.getName().equals(resType)) { @@ -295,6 +306,37 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction impl }); } + private static void createStubResourceField(final Module module, + final String aPackage, + final String resType, + final String fieldName) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + final Project project = module.getProject(); + final PsiClass[] classes = + JavaPsiFacade.getInstance(project).findClasses(aPackage + ".R", GlobalSearchScope.moduleScope(module)); + if (classes.length == 1) { + final PsiClass aClass = classes[0]; + final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + + PsiClass resTypeClass = aClass.findInnerClassByName(resType, false); + + if (resTypeClass == null) { + resTypeClass = (PsiClass)aClass.add(factory.createClass(resType)); + } + else if (resTypeClass.findFieldByName(fieldName, false) != null) { + return; + } + final PsiField psiField = (PsiField)resTypeClass.add(factory.createField(fieldName, PsiType.INT)); + PsiUtil.setModifierProperty(psiField, PsiModifier.PUBLIC, true); + PsiUtil.setModifierProperty(psiField, PsiModifier.STATIC, true); + PsiUtil.setModifierProperty(psiField, PsiModifier.FINAL, true); + } + } + }); + } + @Nullable private static String getPackage(@NotNull AndroidFacet facet) { Manifest manifest = facet.getManifest(); From 2095da8179343b45586b5e1ca9200fbaa5991c37 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 3 Feb 2012 18:44:41 +0400 Subject: [PATCH 14/35] junit: prevent run suite method when another method is selected --- .../src/com/intellij/junit4/JUnit4TestRunnerUtil.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java index 75a4d4d32af7..864e51a87373 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java @@ -17,6 +17,7 @@ package com.intellij.junit4; import org.junit.Ignore; import org.junit.internal.AssumptionViolatedException; +import org.junit.internal.builders.JUnit3Builder; import org.junit.internal.requests.ClassRequest; import org.junit.internal.runners.model.EachTestNotifier; import org.junit.runner.Description; @@ -148,6 +149,14 @@ public class JUnit4TestRunnerUtil { } } } + try { + if (clazz.getMethod("suite", new Class[0]) != null && !methodName.equals("suite")) { + return Request.runner(new JUnit3Builder().runnerForClass(clazz)).filterWith(Description.createTestDescription(clazz, methodName)); + } + } + catch (Throwable e) { + //ignore + } return Request.method(clazz, methodName); } appendTestClass(result, suiteClassName); From ceba74a079d9b79f115811ba10afe3091188e964 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 3 Feb 2012 16:15:48 +0100 Subject: [PATCH 15/35] allow to use compile server options in internal mode as well --- .../src/com/intellij/compiler/CompileServerManager.java | 2 +- .../intellij/compiler/options/CompilerUIConfigurable.java | 7 ++++--- .../intellij/compiler/CompilerWorkspaceConfiguration.java | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java b/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java index 2e5f1dff1219..b207b8d4a5e2 100644 --- a/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java @@ -268,7 +268,7 @@ public class CompileServerManager implements ApplicationComponent{ continue; } final CompilerWorkspaceConfiguration config = CompilerWorkspaceConfiguration.getInstance(project); - if (!config.USE_COMPILE_SERVER || !config.MAKE_PROJECT_ON_SAVE) { + if (!config.useCompileServer() || !config.MAKE_PROJECT_ON_SAVE) { continue; } final RequestFuture future = submitCompilationTask( diff --git a/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java b/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java index e4ed0b2665e8..783925920601 100644 --- a/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java +++ b/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java @@ -17,6 +17,7 @@ package com.intellij.compiler.options; import com.intellij.compiler.*; import com.intellij.compiler.impl.TranslatingCompilerFilesMonitor; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.compiler.CompilerBundle; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; @@ -47,9 +48,9 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura public CompilerUIConfigurable(final Project project) { myProject = project; - final boolean isEnabled = Registry.is("compiler.server.enabled"); - myCbUseCompileServer.setVisible(isEnabled); - myCbMakeProjectOnSave.setVisible(isEnabled); + final boolean isServerOptionEnabled = Registry.is("compiler.server.enabled") || ApplicationManager.getApplication().isInternal(); + myCbUseCompileServer.setVisible(isServerOptionEnabled); + myCbMakeProjectOnSave.setVisible(isServerOptionEnabled); myPatternLegendLabel.setText("" + "Use ; to separate patterns and ! to negate a pattern. " + diff --git a/java/compiler/openapi/src/com/intellij/compiler/CompilerWorkspaceConfiguration.java b/java/compiler/openapi/src/com/intellij/compiler/CompilerWorkspaceConfiguration.java index e0b3ed1d2fce..503af79d0e41 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/CompilerWorkspaceConfiguration.java +++ b/java/compiler/openapi/src/com/intellij/compiler/CompilerWorkspaceConfiguration.java @@ -19,6 +19,7 @@ */ package com.intellij.compiler; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.State; @@ -57,6 +58,6 @@ public class CompilerWorkspaceConfiguration implements PersistentStateComponent< } public boolean useCompileServer() { - return USE_COMPILE_SERVER && Registry.is("compiler.server.enabled"); + return USE_COMPILE_SERVER && (Registry.is("compiler.server.enabled") || ApplicationManager.getApplication().isInternal()); } } From f4c1497e23c5525cc7b2b4d6c63c8c5effe0d34c Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 3 Feb 2012 16:27:00 +0100 Subject: [PATCH 16/35] possible ReadLock assertion fix --- .../intellij/ide/util/FileStructurePopup.java | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java index d438f5388335..1d6b184ad403 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java +++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java @@ -296,15 +296,21 @@ public class FileStructurePopup implements Disposable { if (!filter.equals(prefix)) { filter = prefix; - myAbstractTreeBuilder.refilter(null, false, false).doWhenProcessed(new Runnable() { - @Override - public void run() { - myTree.repaint(); - //if (mySpeedSearch.isPopupActive()) { - // mySpeedSearch.refreshSelection(); - //} - } - }); + final AccessToken token = ApplicationManager.getApplication().acquireReadActionLock(); + try { + myAbstractTreeBuilder.refilter(null, false, false).doWhenProcessed(new Runnable() { + @Override + public void run() { + myTree.repaint(); + //if (mySpeedSearch.isPopupActive()) { + // mySpeedSearch.refreshSelection(); + //} + } + }); + } + finally { + token.finish(); + } } alarm.addRequest(this, 300); } @@ -575,14 +581,20 @@ public class FileStructurePopup implements Disposable { myFilteringStructure.rebuild(); final Object sel = selection; - myAbstractTreeBuilder.refilter(sel, true, false).doWhenProcessed(new Runnable() { - @Override - public void run() { - if (mySpeedSearch.isPopupActive()) { - mySpeedSearch.refreshSelection(); + final AccessToken token = ApplicationManager.getApplication().acquireReadActionLock(); + try { + myAbstractTreeBuilder.refilter(sel, true, false).doWhenProcessed(new Runnable() { + @Override + public void run() { + if (mySpeedSearch.isPopupActive()) { + mySpeedSearch.refreshSelection(); + } } - } - }); + }); + } + finally { + token.finish(); + } } }); chkFilter.setFocusable(false); From aba25e382ffdb9a01887f2235ea16fb49d592e58 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 3 Feb 2012 15:39:55 +0400 Subject: [PATCH 17/35] Long-deprecated methods dropped --- .../openapi/fileChooser/FileSystemTree.java | 15 +--- .../fileChooser/ex/FileChooserDialogImpl.java | 8 +- .../fileChooser/ex/FileSystemTreeImpl.java | 79 ++++++------------- 3 files changed, 30 insertions(+), 72 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileSystemTree.java b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileSystemTree.java index 3ef5a393b30d..db03e497bdc3 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileSystemTree.java +++ b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileSystemTree.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -36,21 +36,10 @@ public interface FileSystemTree extends Disposable { @Nullable VirtualFile getNewFileParent(); - /** - * @deprecated since tree updating is an asynchronous operation - */ - boolean select(VirtualFile file); - void select(VirtualFile file, @Nullable Runnable onDone); void select(VirtualFile[] files, @Nullable Runnable onDone); - - /** - * @deprecated since tree updating is an asynchronous operation - */ - boolean expand(VirtualFile file); - void expand(VirtualFile file, @Nullable Runnable onDone); void addListener(Listener listener, Disposable parent); @@ -63,7 +52,7 @@ public interface FileSystemTree extends Disposable { boolean areHiddensShown(); - void showHiddens(boolean showHiddens); + void showHiddens(boolean showHidden); interface Listener { void selectionChanged(List selection); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java index 1b39da39afaf..a9e673168515 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -126,7 +126,9 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD myFileSystemTree.select(parent, null); } } - else if (file.isDirectory()) myFileSystemTree.expand(file); + else if (file.isDirectory()) { + myFileSystemTree.expand(file, null); + } } }); } @@ -336,7 +338,7 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD } protected VirtualFile[] getSelectedFiles() { - return myFileSystemTree.getChoosenFiles(); + return myFileSystemTree.getChosenFiles(); } private final Map myRequests = new HashMap(); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileSystemTreeImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileSystemTreeImpl.java index 6a00226b34a4..eed66d66c8bf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileSystemTreeImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileSystemTreeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -18,13 +18,13 @@ package com.intellij.openapi.fileChooser.ex; import com.intellij.ide.util.treeView.AbstractTreeBuilder; import com.intellij.ide.util.treeView.AbstractTreeStructure; import com.intellij.ide.util.treeView.NodeDescriptor; +import com.intellij.ide.util.treeView.NodeRenderer; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileElement; import com.intellij.openapi.fileChooser.FileSystemTree; @@ -37,6 +37,7 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.newvfs.NewVirtualFile; import com.intellij.openapi.vfs.newvfs.RefreshQueue; @@ -44,7 +45,6 @@ import com.intellij.ui.PopupHandler; import com.intellij.ui.SimpleTextAttributes; import com.intellij.ui.TreeSpeedSearch; import com.intellij.ui.UIBundle; -import com.intellij.ui.treeStructure.SimpleNodeRenderer; import com.intellij.ui.treeStructure.Tree; import com.intellij.util.containers.ConvertingIterator; import com.intellij.util.containers.Convertor; @@ -62,8 +62,6 @@ import java.io.IOException; import java.util.*; public class FileSystemTreeImpl implements FileSystemTree { - private static final Logger LOG = Logger.getInstance("#com.intellij.chooser.FileSystemTreeImpl"); - private final Tree myTree; private final FileTreeStructure myTreeStructure; private final AbstractTreeBuilder myTreeBuilder; @@ -76,15 +74,18 @@ public class FileSystemTreeImpl implements FileSystemTree { private Map myEverExpanded = new WeakHashMap(); - public FileSystemTreeImpl(@Nullable Project project, FileChooserDescriptor descriptor) { + public FileSystemTreeImpl(@Nullable final Project project, final FileChooserDescriptor descriptor) { this(project, descriptor, new Tree(), null, null, null); myTree.setRootVisible(descriptor.isTreeRootVisible()); myTree.setShowsRootHandles(true); } - public FileSystemTreeImpl(@Nullable Project project, FileChooserDescriptor descriptor, Tree tree, TreeCellRenderer renderer, - final Runnable onInitialized, - Convertor speedSearchConvertor) { + public FileSystemTreeImpl(@Nullable final Project project, + final FileChooserDescriptor descriptor, + final Tree tree, + @Nullable TreeCellRenderer renderer, + @Nullable final Runnable onInitialized, + @Nullable final Convertor speedSearchConverter) { myProject = project; myTreeStructure = new FileTreeStructure(project, descriptor); myDescriptor = descriptor; @@ -119,8 +120,8 @@ public class FileSystemTreeImpl implements FileSystemTree { } }); - if (speedSearchConvertor != null) { - new TreeSpeedSearch(myTree, speedSearchConvertor); + if (speedSearchConverter != null) { + new TreeSpeedSearch(myTree, speedSearchConverter); } else { new TreeSpeedSearch(myTree); } @@ -135,8 +136,7 @@ public class FileSystemTreeImpl implements FileSystemTree { registerTreeActions(); if (renderer == null) { - renderer = new SimpleNodeRenderer() { - + renderer = new NodeRenderer() { public void customizeCellRenderer(JTree tree, Object value, boolean selected, @@ -214,13 +214,13 @@ public class FileSystemTreeImpl implements FileSystemTree { return myTreeStructure.areHiddensShown(); } - public void showHiddens(boolean showHiddens) { - myTreeStructure.showHiddens(showHiddens); + public void showHiddens(boolean showHidden) { + myTreeStructure.showHiddens(showHidden); updateTree(); } public void updateTree() { - myTreeBuilder.updateFromRoot(); + myTreeBuilder.queueUpdate(); } public void dispose() { @@ -235,20 +235,8 @@ public class FileSystemTreeImpl implements FileSystemTree { return myTreeBuilder; } - /** - * @deprecated since tree updating is an asynchronous operation - */ - public boolean select(final VirtualFile file) { - DefaultMutableTreeNode node = getNodeForFile(file); - if (node == null) return false; - else { - TreeUtil.selectPath(myTree, new TreePath(node.getPath())); - return true; - } - } - public void select(VirtualFile file, @Nullable final Runnable onDone) { - select(new VirtualFile[] {file}, onDone); + select(new VirtualFile[]{file}, onDone); } public void select(VirtualFile[] file, @Nullable final Runnable onDone) { @@ -282,23 +270,6 @@ public class FileSystemTreeImpl implements FileSystemTree { return new FileElement(selectFile, selectFile.getName()); } - public boolean expand(VirtualFile directory) { - if (!directory.isDirectory()) return false; - DefaultMutableTreeNode node = getNodeForFile(directory); - if (node == null) return false; - myTree.expandPath(new TreePath(node.getPath())); - return true; - } - - @Nullable - private DefaultMutableTreeNode getNodeForFile(VirtualFile file) { - FileElement descriptor = getFileElementFor(file); - if (descriptor == null) return null; - - myTreeBuilder.buildNodeForElement(descriptor); - return myTreeBuilder.getNodeForElement(descriptor); - } - public Exception createNewFolder(final VirtualFile parentDirectory, final String newFolderName) { final Exception[] failReason = new Exception[] { null }; CommandProcessor.getInstance().executeCommand( @@ -370,19 +341,15 @@ public class FileSystemTreeImpl implements FileSystemTree { public VirtualFile getNewFileParent() { if (getSelectedFile() != null) return getSelectedFile(); - List roots = myDescriptor.getRoots(); - for (VirtualFile each : roots) { - return each; - } - - return null; + final List roots = myDescriptor.getRoots(); + return roots.size() > 0 ? roots.get(0) : null; } public VirtualFile[] getSelectedFiles() { return collectSelectedFiles(new ConvertingIterator.IdConvertor()); } - public VirtualFile[] getChoosenFiles() { + public VirtualFile[] getChosenFiles() { return collectSelectedFiles(new Convertor() { @Nullable public VirtualFile convert(VirtualFile file) { @@ -392,7 +359,7 @@ public class FileSystemTreeImpl implements FileSystemTree { }); } - private VirtualFile[] collectSelectedFiles(Convertor fileConvertor) { + private VirtualFile[] collectSelectedFiles(Convertor fileConverter) { TreePath[] paths = myTree.getSelectionPaths(); if (paths == null) return VirtualFile.EMPTY_ARRAY; ArrayList files = new ArrayList(paths.length); @@ -401,7 +368,7 @@ public class FileSystemTreeImpl implements FileSystemTree { DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); if (!(node.getUserObject() instanceof FileNodeDescriptor)) return VirtualFile.EMPTY_ARRAY; FileNodeDescriptor descriptor = (FileNodeDescriptor)node.getUserObject(); - VirtualFile file = fileConvertor.convert(descriptor.getElement().getFile()); + VirtualFile file = fileConverter.convert(descriptor.getElement().getFile()); if (file != null && file.isValid()) files.add(file); } return VfsUtil.toVirtualFileArray(files); @@ -419,7 +386,7 @@ public class FileSystemTreeImpl implements FileSystemTree { } for (VirtualFile root : roots) { if (root == null) continue; - if (VfsUtil.isAncestor(root, file, false)) { + if (VfsUtilCore.isAncestor(root, file, false)) { return true; } } From a4051b843bd4ca86593e4be6b858dd5ba95cfca3 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 3 Feb 2012 19:34:57 +0400 Subject: [PATCH 18/35] Test cleanup --- .../intellij/lang/PsiBuilderQuickTest.java | 28 ++++++------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java b/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java index ab3fb6a76552..8cdac98782a9 100644 --- a/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java +++ b/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -27,6 +27,7 @@ import com.intellij.psi.impl.DebugUtil; import com.intellij.psi.impl.source.tree.ASTStructure; import com.intellij.psi.tree.*; import com.intellij.testFramework.LightPlatformTestCase; +import com.intellij.testFramework.PlatformTestCase; import com.intellij.util.ThreeState; import com.intellij.util.diff.DiffTree; import com.intellij.util.diff.DiffTreeChangeBuilder; @@ -34,14 +35,12 @@ import com.intellij.util.diff.FlyweightCapableTreeStructure; import com.intellij.util.diff.ShallowNodeComparator; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import org.junit.Test; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.util.List; - public class PsiBuilderQuickTest extends LightPlatformTestCase { private static final IFileElementType ROOT = new IFileElementType("ROOT", Language.ANY); @@ -58,7 +57,11 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase { private static final TokenSet WHITESPACE_SET = TokenSet.create(TokenType.WHITE_SPACE); private static final TokenSet COMMENT_SET = TokenSet.create(COMMENT); - @Test + @SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors") + public PsiBuilderQuickTest() { + PlatformTestCase.initPlatformLangPrefix(); + } + public void testPlain() { doTest("a<>b", new Parser() { @@ -146,7 +147,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase { ); } - @Test public void testDoneAndError() { doTest("a2b", new Parser() { @@ -169,7 +169,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase { " PsiElement(LETTER)('b')\n"); } - @Test public void testPrecedeAndDoneBefore() { doTest("ab", new Parser() { @@ -195,7 +194,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase { " PsiElement(LETTER)('b')\n"); } - @Test public void testErrorBefore() { doTest("a1", new Parser() { @@ -219,7 +217,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase { " PsiElement(DIGIT)('1')\n"); } - @Test public void testValidityChecksOnDone() { doFailTest("a", new Parser() { @@ -234,7 +231,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase { "Another not done marker added after this one. Must be done before this."); } - @Test public void testValidityChecksOnDoneBefore1() { doFailTest("a", new Parser() { @@ -250,7 +246,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase { "Another not done marker added after this one. Must be done before this."); } - @Test public void testValidityChecksOnDoneBefore2() { doFailTest("a", new Parser() { @@ -265,7 +260,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase { "'Before' marker precedes this one."); } - @Test public void testValidityChecksOnTreeBuild1() { doFailTest("aa", new Parser() { @@ -277,7 +271,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase { "Assertion failed: Parser produced no markers. Text:\naa"); } - @Test public void testValidityChecksOnTreeBuild2() { doFailTest("aa", new Parser() { @@ -291,7 +284,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase { "Tokens [LETTER] were not inserted into the tree. Text:\naa"); } - @Test public void testValidityChecksOnTreeBuild3() { doFailTest("a ", new Parser() { @@ -306,7 +298,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase { "Tokens [WHITE_SPACE] are outside of root element \"LETTER\". Text:\na "); } - @Test public void testWhitespaceTrimming() { doTest(" a b ", new Parser() { @@ -331,7 +322,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase { " PsiWhiteSpace(' ')\n"); } - @Test public void testWhitespaceBalancingByErrors() { doTest("a b c", new Parser() { @@ -365,7 +355,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase { " PsiElement(LETTER)('c')\n"); } - @Test public void testWhitespaceBalancingByEmptyComposites() { doTest("a b c", new Parser() { @@ -396,7 +385,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase { " PsiElement(LETTER)('c')\n"); } - @Test public void testCustomEdgeProcessors() { final WhitespacesAndCommentsBinder leftEdgeProcessor = new WhitespacesAndCommentsBinder() { @Override @@ -446,7 +434,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase { } } - @Test public void testLightChameleon() { final IElementType CHAMELEON_2 = new MyLazyElementType("CHAMELEON_2") { @Override @@ -554,6 +541,7 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase { " PsiElement(OTHER)('}')\n"); } + @SuppressWarnings("ConstantConditions") private static PsiBuilderImpl createBuilder(CharSequence text) { ParserDefinition parserDefinition = new ParserDefinition() { @NotNull From 5d1f4266237d5aff1438131886f2bad160511896 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Fri, 3 Feb 2012 19:35:37 +0400 Subject: [PATCH 19/35] IDEA-78960 (Filtered Resources: @ delimeter and custom delimeters are not supported) Implementing custom delimiter support! --- .../maven/compiler/MavenResourceCompiler.java | 15 +- .../idea/maven/dom/MavenPropertyResolver.java | 203 +++++++++++------- ...nFilteredPropertyPsiReferenceProvider.java | 102 ++++++++- .../idea/maven/project/MavenProject.java | 24 +++ .../maven/compiler/ResourceFilteringTest.java | 41 ++++ .../idea/maven/dom/MavenDomTestCase.java | 36 +++- ...PropertiesCompletionAndResolutionTest.java | 75 +++++++ .../maven/dom/MavenPropertyResolverTest.java | 37 +++- 8 files changed, 429 insertions(+), 104 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/compiler/MavenResourceCompiler.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/compiler/MavenResourceCompiler.java index dd4d16884e68..cf4e4e77c138 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/compiler/MavenResourceCompiler.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/compiler/MavenResourceCompiler.java @@ -409,13 +409,20 @@ public class MavenResourceCompiler implements ClassPostProcessingCompiler { if (shouldFilter) { String charset = sourceVirtualFile.getCharset().name(); String text = new String(FileUtil.loadFileBytes(sourceFile), charset); - String escapedCharacters = "properties".equals(sourceVirtualFile.getExtension()) ? "\\" : null; - text = MavenPropertyResolver.resolve(eachItem.getModule(), + String escapedCharacters = sourceVirtualFile.getName().endsWith(".properties") ? "\\" : null; + + PrintWriter printWriter = new PrintWriter(outputFile, charset); + try { + MavenPropertyResolver.doFilterText(eachItem.getModule(), text, eachItem.getProperties(), eachItem.getEscapeString(), - escapedCharacters); - FileUtil.writeToFile(outputFile, text.getBytes(charset)); + escapedCharacters, + printWriter); + } + finally { + printWriter.close(); + } } else { FileUtil.copy(sourceFile, outputFile); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java index c116575803c5..d3dc45492512 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java @@ -16,39 +16,144 @@ package org.jetbrains.idea.maven.dom; import com.intellij.openapi.module.Module; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.xml.XmlTag; +import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.dom.model.MavenDomProfile; import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel; import org.jetbrains.idea.maven.dom.model.MavenDomProperties; +import org.jetbrains.idea.maven.dom.references.MavenFilteredPropertyPsiReferenceProvider; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.server.MavenServerUtil; -import java.util.Collection; -import java.util.Properties; -import java.util.Stack; +import java.io.IOException; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class MavenPropertyResolver { - public static final Pattern PATTERN = Pattern.compile("\\$\\{([^\\}]+?)\\}|@([^@]+?)@"); + public static final Pattern PATTERN = Pattern.compile("\\$\\{(.+?)\\}|@(.+?)@"); - public static String resolve(Module module, - String text, - Properties additionalProperties, - String propertyEscapeString, - String escapedCharacters) { + public static void doFilterText(Module module, + String text, + Properties additionalProperties, + String propertyEscapeString, + String escapedCharacters, + Appendable out) throws IOException { MavenProjectsManager manager = MavenProjectsManager.getInstance(module.getProject()); MavenProject mavenProject = manager.findProject(module); - if (mavenProject == null) return text; - return doResolve(text, mavenProject, additionalProperties, propertyEscapeString, escapedCharacters, new Stack()); + if (mavenProject == null) { + out.append(text); + return; + } + + doFilterText(MavenFilteredPropertyPsiReferenceProvider.getDelimitersPattern(mavenProject), + mavenProject, + text, + additionalProperties, + propertyEscapeString, + escapedCharacters, + null, + out); + } + + private static void doFilterText(Pattern pattern, + MavenProject mavenProject, + String text, + Properties additionalProperties, + @Nullable String escapeString, + @Nullable String escapedCharacters, + @Nullable Map resolvedPropertiesParam, + Appendable out) throws IOException { + Map resolvedProperties = resolvedPropertiesParam; + + Matcher matcher = pattern.matcher(text); + int groupCount = matcher.groupCount(); + + int last = 0; + while (matcher.find()) { + if (escapeString != null) { + int escapeStringStartIndex = matcher.start() - escapeString.length(); + if (escapeStringStartIndex >= last) { + if (text.startsWith(escapeString, escapeStringStartIndex)) { + out.append(text, last, escapeStringStartIndex); + out.append(matcher.group()); + last = matcher.end(); + continue; + } + } + } + + out.append(text, last, matcher.start()); + last = matcher.end(); + + String propertyName = null; + + for (int i = 0; i < groupCount; i++) { + propertyName = matcher.group(i + 1); + if (propertyName != null) { + break; + } + } + + assert propertyName != null; + + if (resolvedProperties == null) { + resolvedProperties = new HashMap(); + } + + String propertyValue = resolvedProperties.get(propertyName); + if (propertyValue == null) { + if (resolvedProperties.containsKey(propertyName)) { // if cyclic property dependencies + out.append(matcher.group()); + continue; + } + + String resolved = doResolveProperty(propertyName, mavenProject, additionalProperties); + if (resolved == null) { + out.append(matcher.group()); + continue; + } + + resolvedProperties.put(propertyName, null); + + StringBuilder sb = new StringBuilder(); + doFilterText(pattern, mavenProject, resolved, additionalProperties, null, null, resolvedProperties, sb); + propertyValue = sb.toString(); + + resolvedProperties.put(propertyName, propertyValue); + } + + if (escapedCharacters == null) { + out.append(propertyValue); + } + else { + for (int i = 0; i < propertyValue.length(); i++) { + char ch = propertyValue.charAt(i); + if (escapedCharacters.indexOf(ch) != -1) { + out.append('\\'); + } + out.append(ch); + } + } + } + + out.append(text, last, text.length()); } public static String resolve(String text, MavenDomProjectModel projectDom) { MavenProject mavenProject = MavenDomUtil.findProject(projectDom); if (mavenProject == null) return text; - return doResolve(text, mavenProject, collectPropertiesFromDOM(mavenProject, projectDom), null, null, new Stack()); + + StringBuilder res = new StringBuilder(); + try { + doFilterText(PATTERN, mavenProject, text, collectPropertiesFromDOM(mavenProject, projectDom), null, null, null, res); + } + catch (IOException e) { + throw new RuntimeException(e); // never thrown + } + + return res.toString(); } private static Properties collectPropertiesFromDOM(MavenProject project, MavenDomProjectModel projectDom) { @@ -75,78 +180,18 @@ public class MavenPropertyResolver { } } - private static String doResolve(String text, - MavenProject project, - Properties additionalProperties, - String escapeString, - String escapedCharacters, - Stack resolutionStack) { - Matcher matcher = PATTERN.matcher(text); - - StringBuffer buff = new StringBuffer(); - StringBuffer dummy = new StringBuffer(); - int last = 0; - while (matcher.find()) { - String propText = matcher.group(); - String propName = matcher.group(1); - if (propName == null) { - propName = matcher.group(2); - } - - int tempLast = last; - last = matcher.start() + propText.length(); - - if (escapeString != null) { - int pos = matcher.start(); - if (pos > escapeString.length() && text.substring(pos - escapeString.length(), pos).equals(escapeString)) { - buff.append(text.substring(tempLast, pos - escapeString.length())); - buff.append(propText); - matcher.appendReplacement(dummy, ""); - continue; - } - } - - String resolved = doResolveProperty(propName, project, additionalProperties); - if (resolved == null) resolved = propText; - if (!resolved.equals(propText) && !resolutionStack.contains(propName)) { - resolutionStack.push(propName); - resolved = doResolve(resolved, project, additionalProperties, escapeString, escapedCharacters, resolutionStack); - resolutionStack.pop(); - } - matcher.appendReplacement(buff, Matcher.quoteReplacement(escapeCharacters(resolved, escapedCharacters))); - } - matcher.appendTail(buff); - - return buff.toString(); - } - - private static String escapeCharacters(String text, String escapedCharacters) { - if (StringUtil.isEmpty(escapedCharacters)) return text; - - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < text.length(); i++) { - char ch = text.charAt(i); - if (escapedCharacters.indexOf(ch) != -1) { - builder.append('\\'); - } - builder.append(ch); - } - return builder.toString(); - } - + @Nullable private static String doResolveProperty(String propName, MavenProject project, Properties additionalProperties) { String result; result = MavenServerUtil.collectSystemProperties().getProperty(propName); if (result != null) return result; - if (propName.startsWith("project.") || propName.startsWith("pom.")) { - if (propName.startsWith("pom.")) { - propName = propName.substring("pom.".length()); - } - else { - propName = propName.substring("project.".length()); - } + if (propName.startsWith("pom.")) { + propName = propName.substring("pom.".length()); + } + else if (propName.startsWith("project.")) { + propName = propName.substring("project.".length()); } if (propName.equals("basedir")) return project.getDirectory(); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenFilteredPropertyPsiReferenceProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenFilteredPropertyPsiReferenceProvider.java index c95ea6a923de..501f7f40beb8 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenFilteredPropertyPsiReferenceProvider.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenFilteredPropertyPsiReferenceProvider.java @@ -15,23 +15,90 @@ */ package org.jetbrains.idea.maven.dom.references; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; import com.intellij.psi.PsiReferenceProvider; import com.intellij.util.ProcessingContext; +import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.maven.dom.MavenDomUtil; import org.jetbrains.idea.maven.dom.MavenPropertyResolver; import org.jetbrains.idea.maven.project.MavenProject; +import org.jetbrains.idea.maven.utils.MavenJDOMUtil; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; +import java.util.regex.Pattern; public class MavenFilteredPropertyPsiReferenceProvider extends PsiReferenceProvider { + private static final Key KEY = Key.create("MavenFilteredPropertyPsiReferenceProvider:delimitersKey"); + + public static final Pattern DEFAULT_DELIMITERS = MavenPropertyResolver.PATTERN; + + @NotNull + public static Pattern getDelimitersPattern(MavenProject mavenProject) { + Pattern res = mavenProject.getCachedValue(KEY); + if (res == null) { + Element cfg = mavenProject.getPluginConfiguration("org.apache.maven.plugins", "maven-resources-plugin"); + if (cfg == null) { + res = DEFAULT_DELIMITERS; + } + else { + List delimiters = MavenJDOMUtil.findChildrenValuesByPath(cfg, "delimiters", "delimiter"); + if (delimiters.isEmpty() || delimiters.size() > 10) { + res = DEFAULT_DELIMITERS; + } + else { + StringBuilder patternBuilder = new StringBuilder(); + + for (String delimiter : delimiters) { + delimiter = delimiter.trim(); + if (delimiter.isEmpty()) continue; + + int ind = delimiter.indexOf('*'); + if (ind >= 0) { + appendDelimiter(patternBuilder, delimiter.substring(0, ind), delimiter.substring(ind + 1)); + } + else { + appendDelimiter(patternBuilder, delimiter, delimiter); + } + } + + // is not used if custom delimiters are not present. + boolean useDefaultDelimiters = true; + + String useDefaultDelimitersText = cfg.getChildText("useDefaultDelimiters"); + if (StringUtil.isNotEmpty(useDefaultDelimitersText)) { + useDefaultDelimiters = Boolean.parseBoolean(useDefaultDelimitersText); + } + + if (useDefaultDelimiters) { + appendDelimiter(patternBuilder, "${", "}"); + appendDelimiter(patternBuilder, "@", "@"); + } + + res = Pattern.compile(patternBuilder.toString()); + } + } + + res = mavenProject.putCachedValue(KEY, res); + } + + return res; + } + + private static void appendDelimiter(StringBuilder pattern, String prefix, String suffix) { + if (pattern.length() > 0) { + pattern.append('|'); + } + pattern.append(Pattern.quote(prefix)).append("(.+?)").append(Pattern.quote(suffix)); + } + @NotNull @Override public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { @@ -43,25 +110,38 @@ public class MavenFilteredPropertyPsiReferenceProvider extends PsiReferenceProvi MavenProject mavenProject = MavenDomUtil.findContainingProject(element); if (mavenProject == null) return PsiReference.EMPTY_ARRAY; - List result = new ArrayList(); + List res = null; + + Pattern pattern = getDelimitersPattern(mavenProject); - Matcher matcher = MavenPropertyResolver.PATTERN.matcher(text); + Matcher matcher = pattern.matcher(text); + + int groupCount = matcher.groupCount(); + while (matcher.find()) { - String propertyName = matcher.group(1); - int from; - if (propertyName == null) { - propertyName = matcher.group(2); - from = matcher.start(2); + String propertyName = null; + int from = 0; + + for (int i = 0; i < groupCount; i++) { + propertyName = matcher.group(i + 1); + if (propertyName != null) { + from = matcher.start(i + 1); + break; + } } - else { - from = matcher.start(1); + + assert propertyName != null; + + if (res == null) { + res = new ArrayList(); } TextRange range = TextRange.from(from, propertyName.length()); - result.add(new MavenFilteredPropertyPsiReference(mavenProject, element, propertyName, range, MavenPropertyPsiReferenceProvider.SOFT_DEFAULT)); + res.add( + new MavenFilteredPropertyPsiReference(mavenProject, element, propertyName, range, MavenPropertyPsiReferenceProvider.SOFT_DEFAULT)); } - return result.toArray(new PsiReference[result.size()]); + return res == null ? PsiReference.EMPTY_ARRAY : res.toArray(new PsiReference[res.size()]); } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java index 93afbfdd96d9..f6dbfa657089 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java @@ -20,6 +20,7 @@ import com.intellij.openapi.module.StdModuleTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream; import com.intellij.openapi.util.io.FileUtil; @@ -42,6 +43,7 @@ import org.jetbrains.idea.maven.utils.*; import java.io.*; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; public class MavenProject { @NotNull private final VirtualFile myFile; @@ -822,6 +824,23 @@ public class MavenProject { return Pair.create(type.getDefaultClassifier(), type.getDefaultExtension()); } + @Nullable + public V getCachedValue(Key key) { + //noinspection unchecked + return (V)myState.myCache.get(key); + } + + @NotNull + public V putCachedValue(Key key, @NotNull V value) { + ConcurrentHashMap map = myState.myCache; + Object oldValue = map.putIfAbsent(key, value); + if (oldValue != null) { + return (V)oldValue; + } + + return value; + } + @Override public String toString() { return getMavenId().toString(); @@ -872,10 +891,13 @@ public class MavenProject { volatile List myUnresolvedPluginsCache; volatile List myUnresolvedExtensionsCache; + ConcurrentHashMap myCache = new ConcurrentHashMap(); + @Override public State clone() { try { State result = (State)super.clone(); + myCache = new ConcurrentHashMap(); result.resetCache(); return result; } @@ -889,6 +911,8 @@ public class MavenProject { myUnresolvedDependenciesCache = null; myUnresolvedPluginsCache = null; myUnresolvedExtensionsCache = null; + + myCache.clear(); } public MavenProjectChanges getChanges(State other) { diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java index 779fbad371e4..18fbd2010960 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java @@ -63,6 +63,47 @@ public class ResourceFilteringTest extends MavenImportingTestCase { "value2=1"); } + public void testCustomDelimiter() throws Exception { + createProjectSubFile("resources/file.properties", "value1=${project.version}\n" + + "value2=@project.version@\n" + + "valueX=|\n" + + "value3=|project.version|\n" + + "value4=(project.version]"); + + importProject("test" + + "project" + + "1" + + + "" + + " " + + " " + + " resources" + + " true" + + " " + + " " + + " " + + " " + + " org.apache.maven.plugins" + + " maven-resources-plugin" + + " " + + " " + + " |" + + " (*]" + + " " + + " " + + " " + + " " + + ""); + + compileModules("project"); + + assertResult("target/classes/file.properties", "value1=1\n" + + "value2=1\n" + + "valueX=|\n" + + "value3=1\n" + + "value4=1"); + } + public void testPomArtifactId() throws Exception { createProjectSubFile("resources/file.properties", "value=${pom.artifactId}"); diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java index 9955e761e784..97af461e12a6 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java @@ -30,6 +30,7 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -54,6 +55,8 @@ import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.MavenImportingTestCase; import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel; import org.jetbrains.idea.maven.dom.references.MavenPsiElementWrapper; @@ -110,6 +113,11 @@ public abstract class MavenDomTestCase extends MavenImportingTestCase { return findPsiFile(f).findReferenceAt(getEditorOffset(f)); } + protected PsiReference getReferenceAt(VirtualFile f, int offset) throws IOException { + configTest(f); + return findPsiFile(f).findReferenceAt(offset); + } + protected PsiElement getElementAtCaret(VirtualFile f) throws IOException { configTest(f); return findPsiFile(f).findElementAt(getEditorOffset(f)); @@ -177,11 +185,35 @@ public abstract class MavenDomTestCase extends MavenImportingTestCase { assertEquals(expectedText, ref.getCanonicalText()); } - protected void assertResolved(VirtualFile file, PsiElement expected) throws IOException { + protected void assertResolved(VirtualFile file, @NotNull PsiElement expected) throws IOException { doAssertResolved(file, expected); } - protected void assertResolved(VirtualFile file, PsiElement expected, String expectedText) throws IOException { + @Nullable + protected PsiReference getReference(VirtualFile file, @NotNull String referenceText) throws IOException { + String text = VfsUtilCore.loadText(file); + int index = text.indexOf(referenceText); + assert index >= 0; + + assert text.indexOf(referenceText, index + referenceText.length()) == -1 : "Reference text '" + referenceText + "' occurs more than one times"; + + return getReferenceAt(file, index); + } + + @Nullable + protected PsiElement resolveReference(VirtualFile file, @NotNull String referenceText) throws IOException { + PsiReference ref = getReference(file, referenceText); + assertNotNull(ref); + + PsiElement resolved = ref.resolve(); + if (resolved instanceof MavenPsiElementWrapper) { + resolved = ((MavenPsiElementWrapper)resolved).getWrappee(); + } + + return resolved; + } + + protected void assertResolved(VirtualFile file, @NotNull PsiElement expected, String expectedText) throws IOException { PsiReference ref = doAssertResolved(file, expected); assertEquals(expectedText, ref.getCanonicalText()); } diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenFilteredPropertiesCompletionAndResolutionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenFilteredPropertiesCompletionAndResolutionTest.java index 2f8729d12784..8abc1192fb12 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenFilteredPropertiesCompletionAndResolutionTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenFilteredPropertiesCompletionAndResolutionTest.java @@ -457,4 +457,79 @@ public class MavenFilteredPropertiesCompletionAndResolutionTest extends MavenDom assertEquals("foo=abc${bar}abc", findPsiFile(f).getText()); assertEquals("bar=1", findPsiFile(filter).getText()); } + + public void testCustomDelimiters() throws Exception { + createProjectSubDir("res"); + + importProject("test" + + "project" + + "1" + + "" + + " " + + " " + + " res" + + " true" + + " " + + " " + + " " + + " " + + " org.apache.maven.plugins" + + " maven-resources-plugin" + + " 2.5" + + " " + + " " + + " |" + + " (*]" + + " " + + " " + + " " + + " " + + ""); + + VirtualFile f = createProjectSubFile("res/foo1.properties", + "foo1=${basedir}\n" + + "foo2=|baseUri|\n" + + "foo3=a(ve|rsion]"); + + assertNotNull(resolveReference(f, "basedir")); + assertNotNull(resolveReference(f, "baseUri")); + assertNotNull(getReference(f, "ve|rsion")); + } + + public void testDontUseDefaultDelimiter1() throws Exception { + createProjectSubDir("res"); + + importProject("test" + + "project" + + "1" + + "" + + " " + + " " + + " res" + + " true" + + " " + + " " + + " " + + " " + + " org.apache.maven.plugins" + + " maven-resources-plugin" + + " 2.5" + + " " + + " " + + " |" + + " " + + " false" + + " " + + " " + + " " + + ""); + + VirtualFile f = createProjectSubFile("res/foo1.properties", + "foo1=${basedir}\n" + + "foo2=|baseUri|"); + + assert !(getReference(f, "basedir") instanceof MavenPropertyPsiReference); + assertNotNull(resolveReference(f, "baseUri")); + } + } diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyResolverTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyResolverTest.java index 4886d24e33bd..378866fdd985 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyResolverTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyResolverTest.java @@ -18,14 +18,35 @@ package org.jetbrains.idea.maven.dom; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.module.Module; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDocumentManager; import org.jetbrains.idea.maven.MavenImportingTestCase; import java.io.File; +import java.io.IOException; import java.util.Properties; public class MavenPropertyResolverTest extends MavenImportingTestCase { + + private static String resolve(Module module, + String text, + Properties additionalProperties, + String propertyEscapeString, + String escapedCharacters) { + StringBuilder sb = new StringBuilder(); + + try { + MavenPropertyResolver.doFilterText(module, text, additionalProperties, propertyEscapeString, escapedCharacters, sb); + } + catch (IOException e) { + throw new RuntimeException(e); + } + + return sb.toString(); + } + + public void testResolvingProjectAttributes() throws Exception { importProject("test" + "project" + @@ -145,8 +166,8 @@ public class MavenPropertyResolverTest extends MavenImportingTestCase { importProject(); assertEquals("${prop1}", resolve("${prop1}", myProjectPom)); - assertEquals("${prop3}", resolve("${prop2}", myProjectPom)); - assertEquals("${prop5}", resolve("${prop4}", myProjectPom)); + assertEquals("${prop3}", resolve("${prop3}", myProjectPom)); + assertEquals("${prop5}", resolve("${prop5}", myProjectPom)); } public void testSophisticatedPropertyNameDoesNotBreakResolver() throws Exception { @@ -262,13 +283,13 @@ public class MavenPropertyResolverTest extends MavenImportingTestCase { "1"); assertEquals("foo ^project bar", - MavenPropertyResolver.resolve(getModule("project"), "foo ^${project.artifactId} bar", new Properties(), "/", null)); + resolve(getModule("project"), "foo ^${project.artifactId} bar", new Properties(), "/", null)); assertEquals("foo ${project.artifactId} bar", - MavenPropertyResolver.resolve(getModule("project"), "foo ^^${project.artifactId} bar", new Properties(), "^^", null)); + resolve(getModule("project"), "foo ^^${project.artifactId} bar", new Properties(), "^^", null)); assertEquals("project ${project.artifactId} project ${project.artifactId}", - MavenPropertyResolver.resolve(getModule("project"), - "${project.artifactId} ^${project.artifactId} ${project.artifactId} ^${project.artifactId}", - new Properties(), "^", null)); + resolve(getModule("project"), + "${project.artifactId} ^${project.artifactId} ${project.artifactId} ^${project.artifactId}", + new Properties(), "^", null)); } public void testEscapingCharacters() throws Exception { @@ -280,7 +301,7 @@ public class MavenPropertyResolverTest extends MavenImportingTestCase { " abc:def\\ghi" + ""); - assertEquals("abc\\:def\\\\ghi", MavenPropertyResolver.resolve(getModule("project"), "${foo}", new Properties(), null, ":\\")); + assertEquals("abc\\:def\\\\ghi", resolve(getModule("project"), "${foo}", new Properties(), null, ":\\")); } private String resolve(String text, VirtualFile f) { From db7990d13ef86d624dd40fa1694b865c6bfb8d86 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 3 Feb 2012 19:42:12 +0400 Subject: [PATCH 20/35] fixed NPE when running test --- .../src/com/intellij/openapi/editor/XmlHighlighterColors.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xml/openapi/src/com/intellij/openapi/editor/XmlHighlighterColors.java b/xml/openapi/src/com/intellij/openapi/editor/XmlHighlighterColors.java index 43f0da56674b..a6fb98685228 100644 --- a/xml/openapi/src/com/intellij/openapi/editor/XmlHighlighterColors.java +++ b/xml/openapi/src/com/intellij/openapi/editor/XmlHighlighterColors.java @@ -41,5 +41,5 @@ public class XmlHighlighterColors { public static final TextAttributesKey HTML_ENTITY_REFERENCE = TextAttributesKey.createTextAttributesKey("HTML_ENTITY_REFERENCE"); public static final TextAttributesKey HTML_CODE = - TextAttributesKey.createTextAttributesKey("HTML_CODE", HighlighterColors.TEXT.getDefaultAttributes().clone()); + TextAttributesKey.createTextAttributesKey("HTML_CODE", HighlighterColors.TEXT.getDefaultAttributes()); } From a34e7094879544faf274ca72793db489bb70e0be Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 3 Feb 2012 19:57:10 +0400 Subject: [PATCH 21/35] fix tests (getPsiRoots() and getLanguages have the same order) --- .../intellij/psi/impl/source/PsiFileImpl.java | 19 ++++++++++--------- .../daemon/impl/HectorComponent.java | 17 +++++++++-------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java index dd202dd57883..553de3e50cb9 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java @@ -519,17 +519,18 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF } roots[i++] = psi; } - if (roots.length > 1) { - Arrays.sort(roots, FILE_BY_LANGUAGE_ID); - } + // getPsiRoots() returns languages in the same order + //if (roots.length > 1) { + // Arrays.sort(roots, FILE_BY_LANGUAGE_ID); + //} return roots; } - private static final Comparator FILE_BY_LANGUAGE_ID = new Comparator() { - @Override - public int compare(PsiFile o1, PsiFile o2) { - return o1.getLanguage().getID().compareTo(o2.getLanguage().getID()); - } - }; + //private static final Comparator FILE_BY_LANGUAGE_ID = new Comparator() { + // @Override + // public int compare(PsiFile o1, PsiFile o2) { + // return o1.getLanguage().getID().compareTo(o2.getLanguage().getID()); + // } + //}; @Override public boolean isPhysical() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HectorComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HectorComponent.java index 226c00f56381..f43f4e7ad6ce 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HectorComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HectorComponent.java @@ -55,7 +55,6 @@ import javax.swing.plaf.basic.BasicSliderUI; import java.awt.*; import java.lang.ref.WeakReference; import java.util.*; -import java.util.List; /** * User: anna @@ -84,13 +83,15 @@ public class HectorComponent extends JPanel { final boolean notInLibrary = !fileIndex.isInLibrarySource(virtualFile) && !fileIndex.isInLibraryClasses(virtualFile) || fileIndex.isInContent(virtualFile); final FileViewProvider viewProvider = myFile.getViewProvider(); - List languages = new ArrayList(viewProvider.getLanguages()); - Collections.sort(languages, new Comparator() { - @Override - public int compare(Language o1, Language o2) { - return o1.getID().compareTo(o2.getID()); - } - }); + //List languages = new ArrayList(viewProvider.getLanguages()); + //Collections.sort(languages, new Comparator() { + // @Override + // public int compare(Language o1, Language o2) { + // return o1.getID().compareTo(o2.getID()); + // } + //}); + Collection languages = viewProvider.getLanguages(); + for (Language language : languages) { @SuppressWarnings("UseOfObsoleteCollectionType") final Hashtable sliderLabels = new Hashtable(); From be58e5117ef99d911ba6f2e15a9c4dcc2772f536 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 3 Feb 2012 19:41:30 +0400 Subject: [PATCH 22/35] expand our macros recursively in program params (IDEA-80593) --- .../src/com/intellij/execution/util/ProgramParametersUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/execution/util/ProgramParametersUtil.java b/platform/lang-impl/src/com/intellij/execution/util/ProgramParametersUtil.java index 2f7adf63a796..df0c41facec0 100644 --- a/platform/lang-impl/src/com/intellij/execution/util/ProgramParametersUtil.java +++ b/platform/lang-impl/src/com/intellij/execution/util/ProgramParametersUtil.java @@ -36,7 +36,7 @@ public class ProgramParametersUtil { Project project = configuration.getProject(); Module module = getModule(configuration); - parameters.getProgramParametersList().addParametersString(configuration.getProgramParameters()); + parameters.getProgramParametersList().addParametersString(expandPath(configuration.getProgramParameters(), module, project)); parameters.setWorkingDirectory(getWorkingDir(configuration, project, module)); From b984133d9255819ca70dcbc6d9b9362b54ee0f87 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Fri, 3 Feb 2012 20:26:16 +0400 Subject: [PATCH 23/35] Maven: show more information in error message. --- .../maven/execution/MavenExternalParameters.java | 12 +++++++++--- .../maven/src/main/resources/RunnerBundle.properties | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java index 210d2554a0b6..4ca1f9fd8173 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java @@ -55,7 +55,7 @@ public class MavenExternalParameters { params.setWorkingDirectory(parameters.getWorkingDirFile()); - params.setJdk(getJdk(runnerSettings.getJreName())); + params.setJdk(getJdk(runnerSettings, project != null && MavenRunner.getInstance(project).getState() == runnerSettings)); final String mavenHome = resolveMavenHome(coreSettings); @@ -83,7 +83,8 @@ public class MavenExternalParameters { } @NotNull - private static Sdk getJdk(final String name) throws ExecutionException { + private static Sdk getJdk(MavenRunnerSettings runnerSettings, boolean isGlobalRunnerSettings) throws ExecutionException { + String name = runnerSettings.getJreName(); if (name.equals(MavenRunnerSettings.USE_INTERNAL_JAVA)) { return JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk(); } @@ -106,7 +107,12 @@ public class MavenExternalParameters { } } - throw new ExecutionException(RunnerBundle.message("maven.java.not.found", name)); + if (isGlobalRunnerSettings) { + throw new ExecutionException(RunnerBundle.message("maven.java.not.found.default.config", name)); + } + else { + throw new ExecutionException(RunnerBundle.message("maven.java.not.found", name)); + } } public static List createVMParameters(final List list, final String mavenHome, final MavenRunnerSettings runnerSettings) { diff --git a/plugins/maven/src/main/resources/RunnerBundle.properties b/plugins/maven/src/main/resources/RunnerBundle.properties index 00b4bced8aeb..f5d127c52a84 100644 --- a/plugins/maven/src/main/resources/RunnerBundle.properties +++ b/plugins/maven/src/main/resources/RunnerBundle.properties @@ -28,6 +28,7 @@ maven.java.home.env=Use JAVA_HOME maven.java.home.undefined=JAVA_HOME environment variable not defined maven.java.home.invalid=JAVA_HOME environment vairable does not point to valid JRE ({0}) maven.java.not.found=Cannot find JRE ''{0}'' +maven.java.not.found.default.config=Cannot find JRE ''{0}''. You can specify JRE to run maven goals in Settings -> Maver -> Runner maven.run.configuration.name=Maven maven.run.configuration.description=Maven build From 2b6ca14d7ef0aa8de426f4f91d8b673243526bdc Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Fri, 3 Feb 2012 20:41:47 +0400 Subject: [PATCH 24/35] Maven: Show unexisting JDK in Maven Runner configuration dialog. --- .../execution/MavenRunnerConfigurable.java | 19 ++++++++++--------- .../maven/execution/MavenRunnerSettings.java | 10 +++++----- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerConfigurable.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerConfigurable.java index 7f97fe601051..085fc93e248c 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerConfigurable.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerConfigurable.java @@ -187,20 +187,21 @@ public abstract class MavenRunnerConfigurable implements SearchableConfigurable, } - private void fillComboboxJdk(MavenRunnerSettings data) { - myJdkComboModel.removeAllElements(); - for (Pair jdk : data.collectJdkNamesAndDescriptions()) { - ComboBoxUtil.addToModel(myJdkComboModel, jdk.getFirst(), jdk.getSecond()); - } - myJdkCombo.setModel(myJdkComboModel); - } - void getData(MavenRunnerSettings data) { myRunInBackgroundCheckbox.setSelected(data.isRunMavenInBackground()); myVMParametersEditor.setText(data.getVmOptions()); mySkipTestsCheckBox.setSelected(data.isSkipTests()); - fillComboboxJdk(data); + Map jdkMap = data.collectJdkNamesAndDescriptions(); + if (!jdkMap.containsKey(data.getJreName())) { + jdkMap.put(data.getJreName(), data.getJreName()); + } + + myJdkComboModel.removeAllElements(); + for (Map.Entry entry : jdkMap.entrySet()) { + ComboBoxUtil.addToModel(myJdkComboModel, entry.getKey(), entry.getValue()); + } + myJdkCombo.setModel(myJdkComboModel); ComboBoxUtil.select(myJdkComboModel, data.getJreName()); myPropertiesPanel.setDataFromMap(data.getMavenProperties()); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerSettings.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerSettings.java index 87046b1b1e23..4cf38fec00e4 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerSettings.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerSettings.java @@ -98,16 +98,16 @@ public class MavenRunnerSettings implements Cloneable { this.mavenProperties = mavenProperties; } - public List> collectJdkNamesAndDescriptions() { - List> result = new ArrayList>(); + public Map collectJdkNamesAndDescriptions() { + Map result = new LinkedHashMap(); for (Sdk projectJdk : ProjectJdkTable.getInstance().getSdksOfType(getSdkType())) { String name = projectJdk.getName(); - result.add(new Pair(name, name)); + result.put(name, name); } - result.add(new Pair(USE_INTERNAL_JAVA, RunnerBundle.message("maven.java.internal"))); - result.add(new Pair(USE_JAVA_HOME, RunnerBundle.message("maven.java.home.env"))); + result.put(USE_INTERNAL_JAVA, RunnerBundle.message("maven.java.internal")); + result.put(USE_JAVA_HOME, RunnerBundle.message("maven.java.home.env")); return result; } From ee2eab7b4b387272bf8cabaa90e22fdb1ff09736 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 3 Feb 2012 20:41:24 +0400 Subject: [PATCH 25/35] Restore log factory after JPS tests --- .../jetbrains/ether/IncrementalTestCase.java | 121 ++++++++++-------- 1 file changed, 65 insertions(+), 56 deletions(-) diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java index 9b9bf010e319..697b8da8654e 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java @@ -82,59 +82,61 @@ public abstract class IncrementalTestCase extends TestCase { } } } - + + private static class MyFactory implements Logger.Factory { + @Override + public Logger getLoggerInstance(String category) { + final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(category); + + final boolean affectedLogger = category.equals("#org.jetbrains.jps.incremental.java.JavaBuilder") || + category.equals("#org.jetbrains.jps.incremental.IncProjectBuilder"); + + return new Logger() { + @Override + public boolean isDebugEnabled() { + return affectedLogger; + } + + @Override + public void debug(@NonNls String message) { + } + + @Override + public void debug(@Nullable Throwable t) { + } + + @Override + public void debug(@NonNls String message, @Nullable Throwable t) { + } + + @Override + public void error(@NonNls String message, @Nullable Throwable t, @NonNls String... details) { + } + + @Override + public void info(@NonNls String message) { + if (affectedLogger) { + logger.info(stripper.strip(message)); + } + } + + @Override + public void info(@NonNls String message, @Nullable Throwable t) { + } + + @Override + public void warn(@NonNls String message, @Nullable Throwable t) { + } + + @Override + public void setLevel(Level level) { + } + }; + } + } + static { - Logger.setFactory(new Logger.Factory() { - @Override - public Logger getLoggerInstance(String category) { - final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(category); - - final boolean affectedLogger = category.equals("#org.jetbrains.jps.incremental.java.JavaBuilder") || - category.equals("#org.jetbrains.jps.incremental.IncProjectBuilder"); - - return new Logger() { - @Override - public boolean isDebugEnabled() { - return affectedLogger; - } - - @Override - public void debug(@NonNls String message) { - } - - @Override - public void debug(@Nullable Throwable t) { - } - - @Override - public void debug(@NonNls String message, @Nullable Throwable t) { - } - - @Override - public void error(@NonNls String message, @Nullable Throwable t, @NonNls String... details) { - } - - @Override - public void info(@NonNls String message) { - if (affectedLogger) { - logger.info(stripper.strip(message)); - } - } - - @Override - public void info(@NonNls String message, @Nullable Throwable t) { - } - - @Override - public void warn(@NonNls String message, @Nullable Throwable t) { - } - - @Override - public void setLevel(Level level) { - } - }; - } - }); + Logger.setFactory(new MyFactory()); } private static RootStripper stripper = new RootStripper(); @@ -142,6 +144,7 @@ public abstract class IncrementalTestCase extends TestCase { private final String groupName; private final String tempDir = FileUtil.toSystemDependentName(new File(System.getProperty("java.io.tmpdir")).getCanonicalPath()); + private Logger.Factory oldFactory; private String baseDir; private String workDir; @@ -152,6 +155,9 @@ public abstract class IncrementalTestCase extends TestCase { @Override protected void setUp() throws Exception { + oldFactory = Logger.ourFactory; + Logger.setFactory(new MyFactory()); + super.setUp(); baseDir = PathManagerEx.getTestDataPath() + File.separator + "compileServer" + File.separator + "incremental" + File.separator; @@ -175,8 +181,13 @@ public abstract class IncrementalTestCase extends TestCase { super.tearDown(); } finally { - closeAppender(); - delete(new File(workDir)); + try { + closeAppender(); + delete(new File(workDir)); + } + finally { + Logger.setFactory(oldFactory); + } } } @@ -342,7 +353,5 @@ public abstract class IncrementalTestCase extends TestCase { finally { projectDescriptor.release(); } - - } } From aaaf310ef63b231cdf8224fc38eef7708be86e66 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 3 Feb 2012 21:02:52 +0400 Subject: [PATCH 26/35] Restore log factory after JPS tests (cleanup) --- .../org/jetbrains/ether/IncrementalTestCase.java | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java index 697b8da8654e..31e596cef0b7 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java @@ -43,11 +43,8 @@ import java.util.List; import java.util.Properties; /** - * Created by IntelliJ IDEA. - * User: db - * Date: 26.07.11 - * Time: 0:34 - * To change this template use File | Settings | File Templates. + * @author db + * @since 26.07.11 */ public abstract class IncrementalTestCase extends TestCase { private static class RootStripper { @@ -135,10 +132,6 @@ public abstract class IncrementalTestCase extends TestCase { } } - static { - Logger.setFactory(new MyFactory()); - } - private static RootStripper stripper = new RootStripper(); private final String groupName; @@ -148,6 +141,7 @@ public abstract class IncrementalTestCase extends TestCase { private String baseDir; private String workDir; + @SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors") protected IncrementalTestCase(final String name) throws Exception { super(name); groupName = name; From 76f44f17a2f970e9d1a045cde6f81186d0eb03a3 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Fri, 3 Feb 2012 20:38:09 +0400 Subject: [PATCH 27/35] minor optimization (don't use regexp) --- jps/model/src/org/jetbrains/ether/dependencyView/TypeRepr.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/TypeRepr.java b/jps/model/src/org/jetbrains/ether/dependencyView/TypeRepr.java index d551f914a432..eb3857668df3 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/TypeRepr.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/TypeRepr.java @@ -1,5 +1,6 @@ package org.jetbrains.ether.dependencyView; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.io.DataExternalizer; import org.jetbrains.ether.RW; import org.objectweb.asm.Type; @@ -238,7 +239,7 @@ class TypeRepr { switch (t.getSort()) { case Type.OBJECT: - return context.getType(new ClassType(context.get(t.getClassName().replaceAll("\\.", "/")))); + return context.getType(new ClassType(context.get(StringUtil.replaceChar(t.getClassName(), '.', '/')))); case Type.ARRAY: return context.getType(new ArrayType(getType(context, t.getElementType()))); From c6f61c44d6447f267da696711ebf949aa5b4879c Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Fri, 3 Feb 2012 21:13:45 +0400 Subject: [PATCH 28/35] Do not check for recompile dependent files if no structural changes have been detected --- .../ether/dependencyView/Mappings.java | 125 +++++++++--------- 1 file changed, 59 insertions(+), 66 deletions(-) diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java index 58e482b45da1..bd27bb4fb361 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java @@ -237,18 +237,12 @@ public class Mappings { this.myDelta = delta; } - void appendDependents(final Set classes, final Set result) { - if (classes == null) { - return; - } + void appendDependents(final ClassRepr c, final Set result) { + final Collection depClasses = myDelta.myClassToClassDependency.get(c.name); - for (ClassRepr c : classes) { - final Collection depClasses = myDelta.myClassToClassDependency.get(c.name); - - if (depClasses != null) { - for (DependencyContext.S className : depClasses) { - result.add(className); - } + if (depClasses != null) { + for (DependencyContext.S className : depClasses) { + result.add(className); } } } @@ -813,8 +807,6 @@ public class Mappings { final Set pastClasses = (Set)mySourceFileToClasses.get(fileName); final Set dependants = new HashSet(); - self.appendDependents(pastClasses, dependants); - final Set affectedUsages = new HashSet(); final Set annotationQuery = new HashSet(); final Map usageConstraints = new HashMap(); @@ -826,6 +818,8 @@ public class Mappings { final ClassRepr it = changed.first; final ClassRepr.Diff diff = (ClassRepr.Diff)changed.second; + self.appendDependents(it, dependants); + debug("Changed: ", it.name); final int addedModifiers = diff.addedModifiers(); @@ -1388,6 +1382,7 @@ public class Mappings { debug("Processing removed classes:"); for (ClassRepr c : classDiff.removed()) { + self.appendDependents(c, dependants); debug("Adding usages of class ", c.name); affectedUsages.add(c.createUsage()); } @@ -1412,71 +1407,69 @@ public class Mappings { debug("End of added classes processing."); debug("Checking dependent files:"); - if (dependants != null) { - final Set dependentFiles = new HashSet(); + final Set dependentFiles = new HashSet(); - for (DependencyContext.S depClass : dependants) { - final DependencyContext.S file = myClassToSourceFile.get(depClass); + for (DependencyContext.S depClass : dependants) { + final DependencyContext.S file = myClassToSourceFile.get(depClass); - if (file != null) { - dependentFiles.add(file); - } + if (file != null) { + dependentFiles.add(file); + } + } + + filewise: + for (DependencyContext.S depFile : dependentFiles) { + final File theFile = new File(myContext.getValue(depFile)); + + if (affectedFiles.contains(theFile) || compiledFiles.contains(theFile)) { + continue filewise; } - filewise: - for (DependencyContext.S depFile : dependentFiles) { - final File theFile = new File(myContext.getValue(depFile)); + debug("Dependent file: ", depFile); + final Collection depClusters = mySourceFileToUsages.get(depFile); + if (depClusters != null) { + for (UsageRepr.Cluster depCluster : depClusters) { + final Set depUsages = depCluster.getUsages(); + if (depUsages == null) { + continue; + } + final Set usages = new HashSet(depUsages); - if (affectedFiles.contains(theFile) || compiledFiles.contains(theFile)) { - continue filewise; - } + usages.retainAll(affectedUsages); - debug("Dependent file: ", depFile); - final Collection depClusters = mySourceFileToUsages.get(depFile); - if (depClusters != null) { - for (UsageRepr.Cluster depCluster : depClusters) { - final Set depUsages = depCluster.getUsages(); - if (depUsages == null) { - continue; - } - final Set usages = new HashSet(depUsages); + if (!usages.isEmpty()) { + for (UsageRepr.Usage usage : usages) { + final Util.UsageConstraint constraint = usageConstraints.get(usage); - usages.retainAll(affectedUsages); - - if (!usages.isEmpty()) { - for (UsageRepr.Usage usage : usages) { - final Util.UsageConstraint constraint = usageConstraints.get(usage); - - if (constraint == null) { - debug("Added file with no constraints"); - affectedFiles.add(theFile); - continue filewise; - } - else { - final Set residenceClasses = depCluster.getResidence(usage); - for (DependencyContext.S residentName : residenceClasses) { - if (constraint.checkResidence(residentName)) { - debug("Added file with satisfied constraint"); - affectedFiles.add(theFile); - continue filewise; - } - } - - } + if (constraint == null) { + debug("Added file with no constraints"); + affectedFiles.add(theFile); + continue filewise; } - } - - if (annotationQuery.size() > 0) { - final Collection annotationUsages = mySourceFileToAnnotationUsages.get(depFile); - - for (UsageRepr.Usage usage : annotationUsages) { - for (UsageRepr.AnnotationUsage query : annotationQuery) { - if (query.satisfies(usage)) { - debug("Added file due to annotation query"); + else { + final Set residenceClasses = depCluster.getResidence(usage); + for (DependencyContext.S residentName : residenceClasses) { + if (constraint.checkResidence(residentName)) { + debug("Added file with satisfied constraint"); affectedFiles.add(theFile); continue filewise; } } + + } + } + } + + if (annotationQuery.size() > 0) { + final Collection annotationUsages = mySourceFileToAnnotationUsages.get(depFile); + + for (UsageRepr.Usage usage : annotationUsages) { + for (UsageRepr.AnnotationUsage query : annotationQuery) { + if (query.satisfies(usage)) { + debug("Added file due to annotation query"); + affectedFiles.add(theFile); + continue filewise; + } } } } From 582924a2464c957633b6e39787d0b3bde18d9ead Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 3 Feb 2012 16:34:36 +0100 Subject: [PATCH 29/35] kill NotificationModel and leaks altogether (IDEA-80753) --- .../com/intellij/notification/LogModel.java | 2 - .../impl/IdeNotificationArea.java | 22 ++- .../notification/impl/NotificationModel.java | 128 ------------------ .../impl/NotificationsManagerImpl.java | 69 +--------- .../impl/ProjectNotificationsComponent.java | 16 +-- 5 files changed, 28 insertions(+), 209 deletions(-) delete mode 100644 platform/platform-impl/src/com/intellij/notification/impl/NotificationModel.java diff --git a/platform/platform-impl/src/com/intellij/notification/LogModel.java b/platform/platform-impl/src/com/intellij/notification/LogModel.java index b70604b82c65..0134bdaf9925 100644 --- a/platform/platform-impl/src/com/intellij/notification/LogModel.java +++ b/platform/platform-impl/src/com/intellij/notification/LogModel.java @@ -16,7 +16,6 @@ package com.intellij.notification; import com.intellij.notification.impl.NotificationsConfigurationImpl; -import com.intellij.notification.impl.NotificationsManagerImpl; import com.intellij.openapi.Disposable; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; @@ -105,7 +104,6 @@ public class LogModel implements Disposable { } void removeNotification(Notification notification) { - NotificationsManagerImpl.getNotificationsManagerImpl().remove(notification); synchronized (myNotifications) { myNotifications.remove(notification); } diff --git a/platform/platform-impl/src/com/intellij/notification/impl/IdeNotificationArea.java b/platform/platform-impl/src/com/intellij/notification/impl/IdeNotificationArea.java index d77090c27e84..982eca49d6f5 100644 --- a/platform/platform-impl/src/com/intellij/notification/impl/IdeNotificationArea.java +++ b/platform/platform-impl/src/com/intellij/notification/impl/IdeNotificationArea.java @@ -18,6 +18,7 @@ package com.intellij.notification.impl; import com.intellij.ide.DataManager; import com.intellij.notification.EventLog; import com.intellij.notification.LogModel; +import com.intellij.notification.Notification; import com.intellij.notification.NotificationType; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.project.Project; @@ -34,6 +35,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; +import java.util.List; /** * @author spleaner @@ -113,7 +115,7 @@ public class IdeNotificationArea implements StatusBarWidget, StatusBarWidget.Ico } private void updateStatus(final LogModel model) { - myCurrentIcon = getPendingNotificationsIcon(EMPTY_ICON, NotificationModel.getMaximumType(model.getNotifications())); + myCurrentIcon = getPendingNotificationsIcon(EMPTY_ICON, getMaximumType(model.getNotifications())); myStatusBar.updateWidget(ID()); } @@ -128,4 +130,22 @@ public class IdeNotificationArea implements StatusBarWidget, StatusBarWidget.Ico return defIcon; } + @Nullable + public static NotificationType getMaximumType(List notifications) { + NotificationType result = null; + for (Notification notification : notifications) { + if (NotificationType.ERROR == notification.getType()) { + return NotificationType.ERROR; + } + + if (NotificationType.WARNING == notification.getType()) { + result = NotificationType.WARNING; + } + else if (result == null && NotificationType.INFORMATION == notification.getType()) { + result = NotificationType.INFORMATION; + } + } + + return result; + } } diff --git a/platform/platform-impl/src/com/intellij/notification/impl/NotificationModel.java b/platform/platform-impl/src/com/intellij/notification/impl/NotificationModel.java deleted file mode 100644 index d83a4f834a7e..000000000000 --- a/platform/platform-impl/src/com/intellij/notification/impl/NotificationModel.java +++ /dev/null @@ -1,128 +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.notification.impl; - -import com.intellij.notification.Notification; -import com.intellij.notification.NotificationType; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Pair; -import com.intellij.util.PairFunction; -import com.intellij.util.concurrency.ReentrantLock2; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.*; - -/** - * @author spleaner - */ -public class NotificationModel { - - private final Map> myNotifications = new LinkedHashMap>(); - - private final ReentrantLock2 myLock = new ReentrantLock2(); - - public void add(@NotNull final Notification notification, final @Nullable Project project) { - try { - myLock.acquire(); - myNotifications.put(notification, Pair.create(project, false)); - } - finally { - myLock.release(); - } - } - - @Nullable - public Notification remove(@NotNull final Notification notification) { - try { - myLock.acquire(); - myNotifications.remove(notification); - } - finally { - myLock.release(); - } - - return notification; - } - - public void remove(@NotNull final Notification... notifications) { - try { - myLock.acquire(); - for (final Notification notification : notifications) { - myNotifications.remove(notification); - } - } - finally { - myLock.release(); - } - } - - private List filterNotifications(@NotNull PairFunction filter) { - LinkedList result; - if (myNotifications.isEmpty()) return Collections.emptyList(); - - result = new LinkedList(); - for (final Map.Entry> entry : myNotifications.entrySet()) { - //noinspection ConstantConditions - if (filter.fun(entry.getKey(), entry.getValue().first)) { - result.addFirst(entry.getKey()); - } - } - - return result; - } - - public void clear(@NotNull PairFunction filter) { - List result; - try { - myLock.acquire(); - result = filterNotifications(filter); - myNotifications.keySet().removeAll(result); - } - finally { - myLock.release(); - } - } - - public List getFilteredNotifications(@NotNull PairFunction filter) { - try { - myLock.acquire(); - return Collections.unmodifiableList(filterNotifications(filter)); - } - finally { - myLock.release(); - } - } - - @Nullable - public static NotificationType getMaximumType(List notifications) { - NotificationType result = null; - for (Notification notification : notifications) { - if (NotificationType.ERROR == notification.getType()) { - return NotificationType.ERROR; - } - - if (NotificationType.WARNING == notification.getType()) { - result = NotificationType.WARNING; - } - else if (result == null && NotificationType.INFORMATION == notification.getType()) { - result = NotificationType.INFORMATION; - } - } - - return result; - } -} diff --git a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java index 6d41095bf51b..ee1ef9c1bd9f 100644 --- a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java @@ -34,7 +34,6 @@ import com.intellij.openapi.wm.impl.IdeFrameImpl; import com.intellij.ui.BalloonImpl; import com.intellij.ui.components.panels.NonOpaquePanel; import com.intellij.util.ArrayUtil; -import com.intellij.util.PairFunction; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -46,7 +45,6 @@ import javax.swing.event.HyperlinkListener; import java.awt.*; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.List; /** @@ -54,8 +52,6 @@ import java.util.List; */ public class NotificationsManagerImpl extends NotificationsManager implements Notifications, ApplicationComponent { - private final NotificationModel myModel = new NotificationModel(); - @NotNull public String getComponentName() { return "NotificationsManager"; @@ -70,7 +66,7 @@ public class NotificationsManagerImpl extends NotificationsManager implements No } public void notify(@NotNull Notification notification) { - doNotify(notification, NotificationDisplayType.BALLOON); + doNotify(notification, NotificationDisplayType.BALLOON, null); } @Override @@ -86,50 +82,27 @@ public class NotificationsManagerImpl extends NotificationsManager implements No @Override public void expire(@NotNull Notification notification) { EventLog.expire(notification); - remove(notification); } @Override public T[] getNotificationsOfType(Class klass, @Nullable final Project project) { - final List notifications = myModel.getFilteredNotifications(createFilter(project, false)); final List result = new ArrayList(); - for (final Notification notification : notifications) { + for (Notification notification : EventLog.getLogModel(project).getNotifications()) { if (klass.isInstance(notification)) { //noinspection unchecked result.add((T) notification); } } - + return ArrayUtil.toObjectArray(result, klass); } - private static final PairFunction ALL = new PairFunction() { - @NotNull - public Boolean fun(final Notification notification, final Project project) { - return true; - } - }; - - private static final PairFunction APPLICATION = new PairFunction() { - @NotNull - public Boolean fun(final Notification notification, final Project project) { - return project == null; - } - }; - - public void clear(@Nullable Project project) { - myModel.clear(createFilter(project, true)); - } - public void disposeComponent() { - myModel.clear(ALL); } - protected void doNotify(@NotNull Notification notification, @Nullable final NotificationDisplayType displayType) { - doNotify(notification, displayType, null); - } - - public void doNotify(@NotNull final Notification notification, @Nullable NotificationDisplayType displayType, @Nullable final Project project) { + public static void doNotify(@NotNull final Notification notification, + @Nullable NotificationDisplayType displayType, + @Nullable final Project project) { final NotificationsConfigurationImpl configuration = NotificationsConfigurationImpl.getNotificationsConfigurationImpl(); if (!configuration.isRegistered(notification.getGroupId())) { configuration.register(notification.getGroupId(), displayType == null ? NotificationDisplayType.BALLOON : displayType); @@ -138,9 +111,6 @@ public class NotificationsManagerImpl extends NotificationsManager implements No final NotificationSettings settings = NotificationsConfigurationImpl.getSettings(notification.getGroupId()); boolean shouldLog = settings.isShouldLog(); boolean displayable = settings.getDisplayType() != NotificationDisplayType.NONE; - if (shouldLog && displayable) { - myModel.add(notification, project); - } boolean willBeShown = displayable && NotificationsConfigurationImpl.getNotificationsConfigurationImpl().SHOW_BALLOONS; if (!shouldLog && !willBeShown) { @@ -318,31 +288,4 @@ public class NotificationsManagerImpl extends NotificationsManager implements No return balloon; } - private static PairFunction createFilter(@Nullable final Project project, final boolean strict) { - return project == null ? APPLICATION : new ProjectFilter(project, strict); - } - - @Nullable - public Notification remove(Notification notification) { - return myModel.remove(notification); - } - - public Collection getAllNotifications(@Nullable final Project project) { - return myModel.getFilteredNotifications(createFilter(project, false)); - } - - private static class ProjectFilter implements PairFunction { - private final Project myProject; - private final boolean myStrict; - - private ProjectFilter(@NotNull final Project project, final boolean strict) { - myProject = project; - myStrict = strict; - } - - @NotNull - public Boolean fun(final Notification notification, final Project project) { - return myStrict ? project == myProject : project == null || project == myProject; - } - } } diff --git a/platform/platform-impl/src/com/intellij/notification/impl/ProjectNotificationsComponent.java b/platform/platform-impl/src/com/intellij/notification/impl/ProjectNotificationsComponent.java index 3056a2b4b95f..937225e51309 100644 --- a/platform/platform-impl/src/com/intellij/notification/impl/ProjectNotificationsComponent.java +++ b/platform/platform-impl/src/com/intellij/notification/impl/ProjectNotificationsComponent.java @@ -18,12 +18,10 @@ package com.intellij.notification.impl; import com.intellij.notification.Notification; import com.intellij.notification.NotificationDisplayType; import com.intellij.notification.Notifications; -import com.intellij.openapi.Disposable; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Disposer; import org.jetbrains.annotations.NotNull; /** @@ -40,18 +38,13 @@ public class ProjectNotificationsComponent implements Notifications, ProjectComp } myProject.getMessageBus().connect().subscribe(TOPIC, this); - Disposer.register(myProject, new Disposable() { - public void dispose() { - NotificationsManagerImpl.getNotificationsManagerImpl().clear(myProject); - } - }); } public void projectOpened() { } public void notify(@NotNull Notification notification) { - NotificationsManagerImpl.getNotificationsManagerImpl().doNotify(notification, null, myProject); + NotificationsManagerImpl.doNotify(notification, null, myProject); } @Override @@ -64,14 +57,7 @@ public class ProjectNotificationsComponent implements Notifications, ProjectComp boolean shouldLog) { } - public void notify(@NotNull Notification notification, @NotNull NotificationDisplayType defaultDisplayType) { - NotificationsManagerImpl.getNotificationsManagerImpl().doNotify(notification, defaultDisplayType, myProject); - } - public void projectClosed() { - for (final Notification notification : NotificationsManagerImpl.getNotificationsManagerImpl().getAllNotifications(myProject)) { - notification.expire(); - } } private static boolean isDummyEnvironment() { From 8238aa13619a01f891df19b14f129c2083fc804b Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 3 Feb 2012 16:48:08 +0100 Subject: [PATCH 30/35] checkCanceled during stub index queries --- .../lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java index d6586755473c..44234f494e30 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java @@ -25,6 +25,7 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -201,6 +202,7 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe container.forEach(new ValueContainer.ContainerAction() { @Override public void perform(final int id, final TIntArrayList value) { + ProgressManager.checkCanceled(); final VirtualFile file = IndexInfrastructure.findFileByIdIfCached(fs, id); if (file == null || scope != null && !scope.contains(file)) { return; From 8f62167ff113f3e11da2fd33deb6344fe1437146 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 3 Feb 2012 17:38:03 +0100 Subject: [PATCH 31/35] IDEA-77916 Event Log: two icons to open Event Log panel --- .../impl/IdeNotificationArea.java | 111 +++++++++++++----- 1 file changed, 83 insertions(+), 28 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/notification/impl/IdeNotificationArea.java b/platform/platform-impl/src/com/intellij/notification/impl/IdeNotificationArea.java index 982eca49d6f5..72ca65f0f01c 100644 --- a/platform/platform-impl/src/com/intellij/notification/impl/IdeNotificationArea.java +++ b/platform/platform-impl/src/com/intellij/notification/impl/IdeNotificationArea.java @@ -16,6 +16,8 @@ package com.intellij.notification.impl; import com.intellij.ide.DataManager; +import com.intellij.ide.ui.UISettings; +import com.intellij.ide.ui.UISettingsListener; import com.intellij.notification.EventLog; import com.intellij.notification.LogModel; import com.intellij.notification.Notification; @@ -24,9 +26,11 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.wm.CustomStatusBarWidget; +import com.intellij.openapi.wm.IconLikeCustomStatusBarWidget; import com.intellij.openapi.wm.StatusBar; -import com.intellij.openapi.wm.StatusBarWidget; import com.intellij.openapi.wm.ToolWindow; +import com.intellij.ui.RowIcon; import com.intellij.util.Alarm; import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; @@ -35,29 +39,34 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; +import java.util.ArrayList; import java.util.List; /** * @author spleaner */ -public class IdeNotificationArea implements StatusBarWidget, StatusBarWidget.IconPresentation { +public class IdeNotificationArea extends JLabel implements CustomStatusBarWidget, IconLikeCustomStatusBarWidget { private static final Icon EMPTY_ICON = IconLoader.getIcon("/ide/notifications.png"); private static final Icon ERROR_ICON = IconLoader.getIcon("/ide/error_notifications.png"); private static final Icon WARNING_ICON = IconLoader.getIcon("/ide/warning_notifications.png"); private static final Icon INFO_ICON = IconLoader.getIcon("/ide/info_notifications.png"); public static final String WIDGET_ID = "Notifications"; - private Icon myCurrentIcon = EMPTY_ICON; private StatusBar myStatusBar; private final Alarm myLogAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); public IdeNotificationArea() { Disposer.register(this, myLogAlarm); - + UISettings.getInstance().addUISettingsListener(new UISettingsListener() { + @Override + public void uiSettingsChanged(UISettings source) { + updateStatus(); + } + }, this); } public WidgetPresentation getPresentation(@NotNull PlatformType type) { - return this; + return null; } public void dispose() { @@ -69,13 +78,7 @@ public class IdeNotificationArea implements StatusBarWidget, StatusBarWidget.Ico new Runnable() { @Override public void run() { - final Project project = getProject(); - LogModel logModel = EventLog.getLogModel(project); - ToolWindow eventLog = EventLog.getEventLog(project); - if (eventLog != null && eventLog.isVisible()) { - logModel.logShown(); - } - updateStatus(logModel); + updateStatus(); myLogAlarm.addRequest(this, 100); } }.run(); @@ -95,30 +98,42 @@ public class IdeNotificationArea implements StatusBarWidget, StatusBarWidget.Ico }; } - @NotNull - public Icon getIcon() { - return myCurrentIcon; - } - - public String getTooltipText() { - int count = EventLog.getLogModel(getProject()).getNotifications().size(); - if (count > 0) { - return String.format("%s notification%s pending", count, count == 1 ? "" : "s"); - } - - return "No new notifications"; - } - @NotNull public String ID() { return WIDGET_ID; } - private void updateStatus(final LogModel model) { - myCurrentIcon = getPendingNotificationsIcon(EMPTY_ICON, getMaximumType(model.getNotifications())); + private void updateStatus() { + final Project project = getProject(); + LogModel logModel = EventLog.getLogModel(project); + ToolWindow eventLog = EventLog.getEventLog(project); + if (eventLog != null && eventLog.isVisible()) { + logModel.logShown(); + } + boolean stripesVisible = !UISettings.getInstance().HIDE_TOOL_STRIPES; + ArrayList notifications = logModel.getNotifications(); + RowIcon icon = new RowIcon(2); + icon.setIcon(getPendingNotificationsIcon(EMPTY_ICON, getMaximumType(notifications)), 0); + final int count = notifications.size(); + if (count > 0) { + icon.setIcon(new TextIcon(this, String.valueOf(count)), 1); + } + if (stripesVisible && eventLog != null) { + eventLog.setIcon(icon); + setIcon(null); + } else { + setIcon(icon); + } + setToolTipText(count > 0 ? String.format("%s notification%s pending", count, count == 1 ? "" : "s") : "No new notifications"); + myStatusBar.updateWidget(ID()); } + @Override + public JComponent getComponent() { + return this; + } + private static Icon getPendingNotificationsIcon(Icon defIcon, final NotificationType maximumType) { if (maximumType != null) { switch (maximumType) { @@ -148,4 +163,44 @@ public class IdeNotificationArea implements StatusBarWidget, StatusBarWidget.Ico return result; } + + private static class TextIcon implements Icon { + private final String myStr; + private final JComponent myComponent; + private final int myWidth; + + public TextIcon(IdeNotificationArea component, String str) { + myStr = str; + myComponent = component; + myWidth = myComponent.getFontMetrics(calcFont()).stringWidth(myStr) + 2; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + Font originalFont = g.getFont(); + Color originalColor = g.getColor(); + g.setFont(calcFont()); + y += getIconHeight() - g.getFontMetrics().getDescent(); + + g.setColor(Color.BLACK); + g.drawString(myStr, x + 1, y); + + g.setFont(originalFont); + g.setColor(originalColor); + } + + private Font calcFont() { + return myComponent.getFont().deriveFont(Font.BOLD).deriveFont((float) getIconHeight() * 2 / 3); + } + + @Override + public int getIconWidth() { + return myWidth; + } + + @Override + public int getIconHeight() { + return EMPTY_ICON.getIconHeight(); + } + } } From 8c335051f1fa5fadc0f0c9449fba3ff1611e9230 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 3 Feb 2012 20:58:20 +0400 Subject: [PATCH 32/35] test for injection problems in presence of xml entities --- .../lang/xpath/xslt/XsltHighlightingTest.java | 8 ++++++++ .../testData/xslt/highlighting/XsltFreeze.xsl | 11 +++++++++++ 2 files changed, 19 insertions(+) create mode 100644 plugins/xpath/xpath-lang/testData/xslt/highlighting/XsltFreeze.xsl diff --git a/plugins/xpath/xpath-lang/test/org/intellij/lang/xpath/xslt/XsltHighlightingTest.java b/plugins/xpath/xpath-lang/test/org/intellij/lang/xpath/xslt/XsltHighlightingTest.java index 0797b78d4811..6d7a84ea9166 100644 --- a/plugins/xpath/xpath-lang/test/org/intellij/lang/xpath/xslt/XsltHighlightingTest.java +++ b/plugins/xpath/xpath-lang/test/org/intellij/lang/xpath/xslt/XsltHighlightingTest.java @@ -16,6 +16,7 @@ package org.intellij.lang.xpath.xslt; import com.intellij.codeInsight.daemon.impl.analysis.XmlUnusedNamespaceInspection; +import com.intellij.idea.Bombed; import com.intellij.javaee.ExternalResourceManagerEx; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; @@ -26,6 +27,8 @@ import com.intellij.util.ArrayUtil; import org.intellij.lang.xpath.TestBase; import org.intellij.lang.xpath.xslt.impl.XsltStuffProvider; +import java.util.Calendar; + /* * Created by IntelliJ IDEA. * User: sweinreuter @@ -127,6 +130,11 @@ public class XsltHighlightingTest extends TestBase { doXsltHighlighting(); } + @Bombed(user = "Maxim.Mossienko", month = Calendar.FEBRUARY, day = 15) + public void testXsltFreeze() throws Throwable { + doXsltHighlighting(); + } + public void testTemplateWithPrefix() throws Throwable { myFixture.enableInspections(XmlUnusedNamespaceInspection.class); doXsltHighlighting(); diff --git a/plugins/xpath/xpath-lang/testData/xslt/highlighting/XsltFreeze.xsl b/plugins/xpath/xpath-lang/testData/xslt/highlighting/XsltFreeze.xsl new file mode 100644 index 000000000000..9f9d0b462b9c --- /dev/null +++ b/plugins/xpath/xpath-lang/testData/xslt/highlighting/XsltFreeze.xsl @@ -0,0 +1,11 @@ + + + + ]> + + + + + + \ No newline at end of file From 53864ceb73b10696ed6a49f43760b1a08519b59d Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 3 Feb 2012 21:00:20 +0400 Subject: [PATCH 33/35] proper parsing entities in attribute value context --- .../psi/impl/source/parsing/xml/OldXmlParsing.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/OldXmlParsing.java b/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/OldXmlParsing.java index bec64b7d958c..57093fb7ac98 100644 --- a/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/OldXmlParsing.java +++ b/xml/impl/src/com/intellij/psi/impl/source/parsing/xml/OldXmlParsing.java @@ -922,7 +922,12 @@ public class OldXmlParsing implements XmlElementType { public void parseAttrValue(CompositeElement element, Lexer lexer) { while(lexer.getTokenType() != null) { - addToken(element, lexer); + if (lexer.getTokenType() == XML_ENTITY_REF_TOKEN) { + final TreeElement children = parseEntityRef(lexer); + element.rawAddChildren(children); + } else { + addToken(element, lexer); + } } } From 31c3c5068929a982cfae2466f18f9550b16d06d2 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 3 Feb 2012 19:20:35 +0100 Subject: [PATCH 34/35] restore showing event log by clicking on the notification widget --- .../notification/impl/IdeNotificationArea.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/notification/impl/IdeNotificationArea.java b/platform/platform-impl/src/com/intellij/notification/impl/IdeNotificationArea.java index 72ca65f0f01c..ae7d7140ab17 100644 --- a/platform/platform-impl/src/com/intellij/notification/impl/IdeNotificationArea.java +++ b/platform/platform-impl/src/com/intellij/notification/impl/IdeNotificationArea.java @@ -32,12 +32,12 @@ import com.intellij.openapi.wm.StatusBar; import com.intellij.openapi.wm.ToolWindow; import com.intellij.ui.RowIcon; import com.intellij.util.Alarm; -import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; +import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; @@ -63,6 +63,12 @@ public class IdeNotificationArea extends JLabel implements CustomStatusBarWidget updateStatus(); } }, this); + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + EventLog.toggleLog(getProject()); + } + }); } public WidgetPresentation getPresentation(@NotNull PlatformType type) { @@ -90,14 +96,6 @@ public class IdeNotificationArea extends JLabel implements CustomStatusBarWidget return PlatformDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext((Component) myStatusBar)); } - public Consumer getClickConsumer() { - return new Consumer() { - public void consume(MouseEvent mouseEvent) { - EventLog.toggleLog(getProject()); - } - }; - } - @NotNull public String ID() { return WIDGET_ID; @@ -146,7 +144,7 @@ public class IdeNotificationArea extends JLabel implements CustomStatusBarWidget } @Nullable - public static NotificationType getMaximumType(List notifications) { + private static NotificationType getMaximumType(List notifications) { NotificationType result = null; for (Notification notification : notifications) { if (NotificationType.ERROR == notification.getType()) { From 6bff0f5277b5cafd42ac82369ccbcc73b5fd0c65 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 3 Feb 2012 19:34:57 +0100 Subject: [PATCH 35/35] don't show expired notifications in status bar --- .../src/com/intellij/openapi/wm/impl/status/StatusPanel.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java index 19c90bce2eb6..504d6195c875 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java @@ -125,9 +125,11 @@ class StatusPanel extends JPanel { final Alarm alarm = getAlarm(); myLogMode = logAllowed && StringUtil.isEmpty(nonLogText) && statusMessage != null && alarm != null; - if (myLogMode) { + if (alarm != null) { alarm.cancelAllRequests(); + } + if (myLogMode) { myTextPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); new Runnable() { @Override