From ff7976e413685ee97a2f7ce10de14527c52dc046 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 20 Mar 2012 11:44:48 +0400 Subject: [PATCH 001/106] Better handle invalid Git executable on "Enable Git Integration" Git#init() - transform to the common format returning GitCommandResult. --- .../git4idea/src/git4idea/actions/GitInit.java | 15 +++++++-------- plugins/git4idea/src/git4idea/commands/Git.java | 2 +- .../git4idea/src/git4idea/commands/GitImpl.java | 14 ++++++-------- .../src/git4idea/roots/GitIntegrationEnabler.java | 12 ++++++------ .../git4idea/tests/git4idea/test/MockGit.groovy | 4 +++- 5 files changed, 23 insertions(+), 24 deletions(-) diff --git a/plugins/git4idea/src/git4idea/actions/GitInit.java b/plugins/git4idea/src/git4idea/actions/GitInit.java index 78291cd44878..685cb743a30f 100644 --- a/plugins/git4idea/src/git4idea/actions/GitInit.java +++ b/plugins/git4idea/src/git4idea/actions/GitInit.java @@ -15,6 +15,7 @@ */ package git4idea.actions; +import com.intellij.notification.NotificationType; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.components.ServiceManager; @@ -30,12 +31,12 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.VcsDirectoryMapping; -import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.vcsUtil.VcsFileUtil; import git4idea.GitUtil; import git4idea.GitVcs; import git4idea.commands.Git; +import git4idea.commands.GitCommandResult; import git4idea.i18n.GitBundle; import git4idea.util.GitUIUtil; import org.jetbrains.annotations.NotNull; @@ -78,14 +79,12 @@ public class GitInit extends DumbAwareAction { } } - GitVcs vcs = GitVcs.getInstance(project); Git git = ServiceManager.getService(Git.class); - try { - git.init(project, root); - } catch (VcsException ex) { - if (vcs == null || vcs.getExecutableValidator().isExecutableValid()) { - GitUIUtil.showOperationErrors(project, Collections.singleton(ex), "git init"); - } + + GitCommandResult result = git.init(project, root); + if (!result.success()) { + GitUIUtil.notify(GitVcs.IMPORTANT_ERROR_NOTIFICATION, project, "Git init failed", result.getErrorOutputAsHtmlString(), + NotificationType.ERROR, null); return; } diff --git a/plugins/git4idea/src/git4idea/commands/Git.java b/plugins/git4idea/src/git4idea/commands/Git.java index b0e303723376..a4dfbb727e37 100644 --- a/plugins/git4idea/src/git4idea/commands/Git.java +++ b/plugins/git4idea/src/git4idea/commands/Git.java @@ -33,7 +33,7 @@ import java.util.Set; */ public interface Git { - void init(Project project, VirtualFile root) throws VcsException; + GitCommandResult init(@NotNull Project project, @NotNull VirtualFile root, @NotNull GitLineHandlerListener... listeners); @NotNull Set untrackedFiles(@NotNull Project project, diff --git a/plugins/git4idea/src/git4idea/commands/GitImpl.java b/plugins/git4idea/src/git4idea/commands/GitImpl.java index 56dfb31eb1d6..f610113b1cbe 100644 --- a/plugins/git4idea/src/git4idea/commands/GitImpl.java +++ b/plugins/git4idea/src/git4idea/commands/GitImpl.java @@ -50,17 +50,15 @@ public class GitImpl implements Git { /** * Calls 'git init' on the specified directory. - * // TODO use common format */ @Override - public void init(Project project, VirtualFile root) throws VcsException { - GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.INIT); - h.setSilent(false); - h.setNoSSH(true); - h.run(); - if (!h.errors().isEmpty()) { - throw h.errors().get(0); + public GitCommandResult init(@NotNull Project project, @NotNull VirtualFile root, @NotNull GitLineHandlerListener... listeners) { + GitLineHandler h = new GitLineHandler(project, root, GitCommand.INIT); + for (GitLineHandlerListener listener : listeners) { + h.addLineListener(listener); } + h.setSilent(false); + return run(h); } /** diff --git a/plugins/git4idea/src/git4idea/roots/GitIntegrationEnabler.java b/plugins/git4idea/src/git4idea/roots/GitIntegrationEnabler.java index ae1765dc4aaa..145ea231095a 100644 --- a/plugins/git4idea/src/git4idea/roots/GitIntegrationEnabler.java +++ b/plugins/git4idea/src/git4idea/roots/GitIntegrationEnabler.java @@ -20,13 +20,13 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.VcsDirectoryMapping; -import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ui.UIUtil; import git4idea.Notificator; import git4idea.PlatformFacade; import git4idea.commands.Git; +import git4idea.commands.GitCommandResult; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -77,15 +77,15 @@ public class GitIntegrationEnabler { } private boolean gitInitOrNotifyError(@NotNull Notificator notificator, @NotNull final VirtualFile projectDir) { - try { - myGit.init(myProject, projectDir); + GitCommandResult result = myGit.init(myProject, projectDir); + if (result.success()) { refreshGitDir(projectDir); notificator.notifySuccess("", "Created Git repository in \n" + projectDir.getPresentableUrl()); return true; } - catch (VcsException e) { - notificator.notifyError("Couldn't git init " + projectDir.getPresentableUrl(), e.getMessage()); - LOG.error(e); + else { + notificator.notifyError("Couldn't git init " + projectDir.getPresentableUrl(), result.getErrorOutputAsHtmlString()); + LOG.info(result.getErrorOutputAsHtmlString()); return false; } } diff --git a/plugins/git4idea/tests/git4idea/test/MockGit.groovy b/plugins/git4idea/tests/git4idea/test/MockGit.groovy index a90770008384..fb6497932119 100644 --- a/plugins/git4idea/tests/git4idea/test/MockGit.groovy +++ b/plugins/git4idea/tests/git4idea/test/MockGit.groovy @@ -22,6 +22,7 @@ import git4idea.commands.GitCommandResult import git4idea.commands.GitLineHandlerListener import git4idea.push.GitPushSpec import git4idea.repo.GitRepository +import org.jetbrains.annotations.NotNull /** * @@ -30,8 +31,9 @@ import git4idea.repo.GitRepository class MockGit implements Git { @Override - void init(Project project, VirtualFile root) { + GitCommandResult init(@NotNull Project project, @NotNull VirtualFile root, @NotNull GitLineHandlerListener... listeners) { new File(root.path, ".git").mkdir() + new GitCommandResult(true, 0, Collections.emptyList(), Collections.emptyList()) } @Override From e3f5d7e587e3e60aa1af9e0e330a6e40b6395d97 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 20 Mar 2012 11:54:57 +0400 Subject: [PATCH 002/106] IDEA-80457 Git Compare With Branch is disabled when invoked from main menu Set action presentation, if everything is ok. --- .../src/git4idea/actions/GitCompareWithBranchAction.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/git4idea/src/git4idea/actions/GitCompareWithBranchAction.java b/plugins/git4idea/src/git4idea/actions/GitCompareWithBranchAction.java index 45c32dbddf20..925cd756b38d 100644 --- a/plugins/git4idea/src/git4idea/actions/GitCompareWithBranchAction.java +++ b/plugins/git4idea/src/git4idea/actions/GitCompareWithBranchAction.java @@ -142,7 +142,11 @@ public class GitCompareWithBranchAction extends DumbAwareAction { if (repository == null || repository.isFresh() || noBranchesToCompare(repository)) { presentation.setEnabled(false); presentation.setVisible(true); + return; } + + presentation.setEnabled(true); + presentation.setVisible(true); } private static boolean noBranchesToCompare(@NotNull GitRepository repository) { From 1ee8f72da2f2299ca3175b984ceeb419e4324234 Mon Sep 17 00:00:00 2001 From: irengrig Date: Tue, 20 Mar 2012 12:23:14 +0400 Subject: [PATCH 003/106] VCS: already disposed from incoming changes --- .../src/com/intellij/openapi/progress/ProgressManagerQueue.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/platform-api/src/com/intellij/openapi/progress/ProgressManagerQueue.java b/platform/platform-api/src/com/intellij/openapi/progress/ProgressManagerQueue.java index 18beef5fcedc..6e86c7bd2d74 100644 --- a/platform/platform-api/src/com/intellij/openapi/progress/ProgressManagerQueue.java +++ b/platform/platform-api/src/com/intellij/openapi/progress/ProgressManagerQueue.java @@ -37,11 +37,13 @@ public class ProgressManagerQueue extends AbstractTaskQueue { protected void runMe() { final Application app = ApplicationManager.getApplication(); if (app.isDispatchThread()) { + if (myTask.myProject != null && myTask.myProject.isDisposed()) return; myProgressManager.run(myTask); } else { ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { + if (myTask.myProject != null && myTask.myProject.isDisposed()) return; myProgressManager.run(myTask); } }); From 8a0b1d6a84283f878f63192ae14f0271c9d0d517 Mon Sep 17 00:00:00 2001 From: peter Date: Sat, 17 Mar 2012 00:09:01 +0400 Subject: [PATCH 004/106] remove attribute fix not to hold a hard ref to psi --- .../analysis/RemoveAttributeIntentionFix.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/RemoveAttributeIntentionFix.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/RemoveAttributeIntentionFix.java index 8dfa7660095d..4814d65af145 100644 --- a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/RemoveAttributeIntentionFix.java +++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/RemoveAttributeIntentionFix.java @@ -17,25 +17,24 @@ package com.intellij.codeInsight.daemon.impl.analysis; import com.intellij.codeInsight.CodeInsightUtilBase; import com.intellij.codeInsight.daemon.XmlErrorMessages; -import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.xml.XmlAttribute; -import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author Maxim.Mossienko */ -public class RemoveAttributeIntentionFix implements IntentionAction { +public class RemoveAttributeIntentionFix extends LocalQuickFixAndIntentionActionOnPsiElement { private final String myLocalName; - private final XmlAttribute myAttribute; public RemoveAttributeIntentionFix(final String localName, final @NotNull XmlAttribute attribute) { + super(attribute); myLocalName = localName; - myAttribute = attribute; } @NotNull @@ -48,20 +47,22 @@ public class RemoveAttributeIntentionFix implements IntentionAction { return XmlErrorMessages.message("remove.attribute.quickfix.family"); } - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return myAttribute.isValid(); - } - - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + @Override + public void invoke(@NotNull Project project, + @NotNull PsiFile file, + @Nullable("is null when called from inspection") Editor editor, + @NotNull PsiElement startElement, + @NotNull PsiElement endElement) { if (!CodeInsightUtilBase.prepareFileForWrite(file)) return; - PsiElement next = findNextAttribute(myAttribute); - myAttribute.delete(); + PsiElement next = findNextAttribute((XmlAttribute)startElement); + startElement.delete(); - if (next != null) { + if (next != null && editor != null) { editor.getCaretModel().moveToOffset(next.getTextRange().getStartOffset()); } } + @Nullable private static PsiElement findNextAttribute(final XmlAttribute attribute) { PsiElement nextSibling = attribute.getNextSibling(); while (nextSibling != null) { From 779cda730276f99187c1e27e4a9d3d030a26dc62 Mon Sep 17 00:00:00 2001 From: irengrig Date: Tue, 20 Mar 2012 12:53:20 +0400 Subject: [PATCH 005/106] AbstractRefreshablePanel - if exception doesnt have a message.. --- .../openapi/vcs/changes/AbstractRefreshablePanel.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/AbstractRefreshablePanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/AbstractRefreshablePanel.java index af635d50dbe2..32a8085acedd 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/AbstractRefreshablePanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/AbstractRefreshablePanel.java @@ -135,7 +135,9 @@ public abstract class AbstractRefreshablePanel implements RefreshablePanel { cause = e; } LOG.info(e); - VcsBalloonProblemNotifier.showOverChangesView(myProject, cause.getMessage() == null ? e.getMessage() : cause.getMessage(), MessageType.ERROR); + String message = cause.getMessage() == null ? e.getMessage() : cause.getMessage(); + message = message == null ? "Unknown error" : message; + VcsBalloonProblemNotifier.showOverChangesView(myProject, message, MessageType.ERROR); } @Override From 2897f098620436c7fe72990ef072c782f89a7c8b Mon Sep 17 00:00:00 2001 From: irengrig Date: Tue, 20 Mar 2012 13:06:20 +0400 Subject: [PATCH 006/106] SVN: indicator to say abt cleanup only if cleanup --- .../src/org/jetbrains/idea/svn/dialogs/SvnFormatWorker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnFormatWorker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnFormatWorker.java index 972bab503239..2e7acdecdb05 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnFormatWorker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnFormatWorker.java @@ -136,9 +136,9 @@ public class SvnFormatWorker extends Task.Backgroundable { if (! wcInfo.isIsWcRoot()) { path = SvnUtil.getWorkingCopyRoot(path); } - indicator.setText(SvnBundle.message("action.Subversion.cleanup.progress.text", path.getAbsolutePath())); try { if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(myNewFormat)) { + indicator.setText(SvnBundle.message("action.Subversion.cleanup.progress.text", path.getAbsolutePath())); wcClient.doCleanup(path); } indicator.setText(SvnBundle.message("action.change.wcopy.format.task.progress.text", path.getAbsolutePath(), From 8f2cad78bcb4ebbc5e18005f7d0ab67ec13f2f46 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 20 Mar 2012 13:27:12 +0400 Subject: [PATCH 007/106] IDEA-82453 PHPStorm commits w/o asking first when sharing repository on Github Don't commit if the repository is not fresh (i.e. has history). Check this via GitRepository. Don't proceed with bindToGithub if initial commit fails with error. --- .../plugins/github/GithubShareAction.java | 47 ++++++++++++------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java index 1903933b61e2..6365f187a447 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java @@ -7,6 +7,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ex.ApplicationInfoEx; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; @@ -32,11 +33,13 @@ import git4idea.GitUtil; import git4idea.GitVcs; import git4idea.actions.BasicAction; import git4idea.actions.GitInit; -import git4idea.push.GitPushUtils; import git4idea.commands.*; import git4idea.i18n.GitBundle; -import git4idea.util.GitUIUtil; +import git4idea.push.GitPushUtils; +import git4idea.repo.GitRepository; +import git4idea.repo.GitRepositoryManager; import git4idea.util.GitFileUtils; +import git4idea.util.GitUIUtil; import org.jetbrains.plugins.github.ui.GithubShareDialog; import java.io.IOException; @@ -129,12 +132,13 @@ public class GithubShareAction extends DumbAwareAction { Messages.showErrorDialog(e1.getMessage(), "Failed to create new GitHub repository"); return; } - bindToGithub(project, root, gitDetected, settings.getLogin(), name); - Notifications.Bus.notify(new Notification("github", "Success", "Successfully created project ''" + name + "'' on github", - NotificationType.INFORMATION)); + if (bindToGithub(project, root, gitDetected, settings.getLogin(), name)) { + Notifications.Bus.notify(new Notification("github", "Success", "Successfully created project ''" + name + "'' on github", + NotificationType.INFORMATION)); + } } - private void bindToGithub(final Project project, final VirtualFile root, final boolean gitDetected, final String login, final String name) { + private boolean bindToGithub(final Project project, final VirtualFile root, final boolean gitDetected, final String login, String name) { LOG.info("Binding local project with GitHub"); // creating empty git repo if git isnot initialized if (!gitDetected) { @@ -145,7 +149,7 @@ public class GithubShareAction extends DumbAwareAction { if (!h.errors().isEmpty()) { GitUIUtil.showOperationErrors(project, h.errors(), "git init"); LOG.info("Failed to create empty git repo: " + h.errors()); - return; + return false; } final ProgressManager manager = ProgressManager.getInstance(); manager.runProcessWithProgressSynchronously(new Runnable() { @@ -157,7 +161,9 @@ public class GithubShareAction extends DumbAwareAction { } // In this case we should create sample commit for binding project - performFirstCommitIfRequired(project, root); + if (!performFirstCommitIfRequired(project, root)) { + return false; + } //git remote add origin git@github.com:login/name.git LOG.info("Adding GitHub as a remote host"); @@ -169,13 +175,13 @@ public class GithubShareAction extends DumbAwareAction { addRemoteHandler.run(); if (addRemoteHandler.getExitCode() != 0) { Messages.showErrorDialog("Failed to add GitHub repository as remote", "Failed to add GitHub repository as remote"); - return; + return false; } } catch (VcsException e) { Messages.showErrorDialog(e.getMessage(), "Failed to add GitHub repository as remote"); LOG.info("Failed to add GitHub as remote: " + e.getMessage()); - return; + return false; } //git push origin master @@ -198,6 +204,7 @@ public class GithubShareAction extends DumbAwareAction { } // refresh vcs manually RefreshAction.doRefresh(project); + return true; } private boolean performFirstCommitIfRequired(final Project project, final VirtualFile root) { @@ -211,15 +218,21 @@ public class GithubShareAction extends DumbAwareAction { Messages.showErrorDialog(project, "Cannot find git initialized", "Failed to share"); return false; } - try { - if (!provider.getOutgoingChanges(root, false).getSecond().isEmpty()){ - return true; - } - } - catch (VcsException e) { - Messages.showErrorDialog(project, e.getMessage(), "Failed to share"); + + GitRepositoryManager repositoryManager = ServiceManager.getService(project, GitRepositoryManager.class); + Git git = ServiceManager.getService(Git.class); + if (repositoryManager == null || git == null) { return false; } + GitRepository repository = repositoryManager.getRepositoryForRoot(root); + if (repository == null) { + Messages.showErrorDialog(project, "Cannot find git repository for root " + root, "Failed to share"); + return false; + } + if (!repository.isFresh()) { + return true; + } + final Ref exceptionRef = new Ref(); // Creating or modifying readme file LOG.info("Touching file 'README' for initial commit"); From ae6e4fd188dc56604c9c07e29b4e83ae1fcc88b5 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Mar 2012 10:32:37 +0100 Subject: [PATCH 008/106] exception tolerance (http://youtrack.jetbrains.com/issue/IDEA-83060) --- .../highlighter/EditorHighlighterFactoryImpl.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/highlighter/EditorHighlighterFactoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/highlighter/EditorHighlighterFactoryImpl.java index e53742e1e2f4..4c32efd347a6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/highlighter/EditorHighlighterFactoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/highlighter/EditorHighlighterFactoryImpl.java @@ -16,6 +16,7 @@ package com.intellij.openapi.editor.highlighter; import com.intellij.lang.Language; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.ex.util.LexerEditorHighlighter; @@ -32,6 +33,8 @@ import org.jetbrains.annotations.Nullable; * @author yole */ public class EditorHighlighterFactoryImpl extends EditorHighlighterFactory { + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.highlighter.EditorHighlighterFactoryImpl"); + @Override public EditorHighlighter createEditorHighlighter(SyntaxHighlighter highlighter, final EditorColorsScheme colors) { if (highlighter == null) highlighter = new PlainSyntaxHighlighter(); @@ -74,8 +77,16 @@ public class EditorHighlighterFactoryImpl extends EditorHighlighterFactory { final ContentBasedFileSubstitutor[] processors = Extensions.getExtensions(ContentBasedFileSubstitutor.EP_NAME); SyntaxHighlighter highlighter = null; for (ContentBasedFileSubstitutor processor : processors) { - if (processor.isApplicable(project, vFile) && processor instanceof ContentBasedClassFileProcessor) { - highlighter = ((ContentBasedClassFileProcessor) processor).createHighlighter(project, vFile); + boolean applicable; + try { + applicable = processor.isApplicable(project, vFile); + } + catch (Exception e) { + LOG.error(e); + continue; + } + if (applicable && processor instanceof ContentBasedClassFileProcessor) { + highlighter = ((ContentBasedClassFileProcessor)processor).createHighlighter(project, vFile); } } if (highlighter == null) { From 22502328e0bc7b97d596ee0a7f1ad1949894230b Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 20 Mar 2012 13:33:50 +0400 Subject: [PATCH 009/106] IDEA-83017 Exception while cherry-picking Correct InvokeAfterUpdateMode --- .../git4idea/src/git4idea/history/browser/CherryPicker.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java b/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java index c2a2213a141d..23decfea9335 100644 --- a/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java +++ b/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java @@ -103,11 +103,11 @@ public class CherryPicker { public void run() { moveToCorrectLists(); } - }, InvokeAfterUpdateMode.SYNCHRONOUS_CANCELLABLE, "", new Consumer() { + }, InvokeAfterUpdateMode.SILENT, "", new Consumer() { public void consume(VcsDirtyScopeManager vcsDirtyScopeManager) { vcsDirtyScopeManager.filePathsDirty(getAllChangedFiles(), null); } - }, ModalityState.defaultModalityState()); + }, ModalityState.NON_MODAL); } private void showResults() { From e6776d9ff5d8db0f79f7a4e774fea394a2c791fe Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Tue, 20 Mar 2012 12:51:24 +0400 Subject: [PATCH 010/106] EA-34784 --- .../com/intellij/execution/ui/layout/impl/GridCellImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java index fc6488f989db..ae9624772796 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java @@ -363,7 +363,9 @@ public class GridCellImpl implements GridCell { service.setSize(getDimensionKey(), size, myContext.getProject()); if (myContext.getWindow() != 0) { final Window frame = SwingUtilities.getWindowAncestor(myPlaceholder); - service.setLocation(getDimensionKey(), frame.getLocationOnScreen()); + if (frame != null) { + service.setLocation(getDimensionKey(), frame.getLocationOnScreen()); + } } } From 32670877a42fa4c22ee7e6f2f0b0089ee6194a16 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Tue, 20 Mar 2012 13:32:06 +0400 Subject: [PATCH 011/106] EA-33725 --- .../src/com/intellij/ui/tabs/impl/JBTabsImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index 45c466bf66e9..53ec6dcc98ab 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -337,7 +337,9 @@ public class JBTabsImpl extends JComponent BufferedImage img; if (cmp.isShowing()) { - img = new BufferedImage(cmp.getWidth(), cmp.getHeight(), BufferedImage.TYPE_INT_ARGB); + final int width = cmp.getWidth(); + final int height = cmp.getHeight(); + img = new BufferedImage(width > 0 ? width : 500, height > 0 ? height : 500, BufferedImage.TYPE_INT_ARGB); Graphics2D g = img.createGraphics(); cmp.paint(g); } else { From 68542ff716f5bdc0cd3decccd6481c5636362c2f Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Mar 2012 12:54:39 +0400 Subject: [PATCH 012/106] optimisation: do not queue document for commit during bulk update --- .../editor/ex/DocumentBulkUpdateListener.java | 2 +- .../psi/impl/PsiDocumentManagerImpl.java | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/platform/core-impl/src/com/intellij/openapi/editor/ex/DocumentBulkUpdateListener.java b/platform/core-impl/src/com/intellij/openapi/editor/ex/DocumentBulkUpdateListener.java index b85db01dc00b..999482c517df 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/ex/DocumentBulkUpdateListener.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/ex/DocumentBulkUpdateListener.java @@ -24,7 +24,7 @@ import com.intellij.util.messages.Topic; import org.jetbrains.annotations.NotNull; public interface DocumentBulkUpdateListener { - Topic TOPIC = Topic.create("Bulk document change notifcation like reformat, etc.", DocumentBulkUpdateListener.class); + Topic TOPIC = Topic.create("Bulk document change notification like reformat, etc.", DocumentBulkUpdateListener.class); void updateStarted(@NotNull Document doc); void updateFinished(@NotNull Document doc); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java index 84e455f565d3..2d97fc4052a7 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java @@ -31,6 +31,7 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.event.DocumentListener; +import com.intellij.openapi.editor.ex.DocumentBulkUpdateListener; import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.FileDocumentManagerAdapter; @@ -79,7 +80,7 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec private final List myListeners = ContainerUtil.createEmptyCOWList(); private final SmartPointerManagerImpl mySmartPointerManager; - public PsiDocumentManagerImpl(@NotNull Project project, + public PsiDocumentManagerImpl(@NotNull final Project project, @NotNull PsiManager psiManager, @NotNull SmartPointerManager smartPointerManager, @NotNull EditorFactory editorFactory, @@ -105,6 +106,12 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec fireDocumentCreated(document, psiFile); } }); + bus.connect().subscribe(DocumentBulkUpdateListener.TOPIC, new DocumentBulkUpdateListener.Adapter() { + @Override + public void updateFinished(@NotNull Document doc) { + documentCommitThread.queueCommit(project, doc, "Bulk update finished"); + } + }); ApplicationManager.getApplication().addApplicationListener(new ApplicationAdapter() { @Override public void beforeWriteActionStart(Object action) { @@ -668,12 +675,13 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec commitNecessary = true; } + boolean fromRefresh = ApplicationManager.getApplication().hasWriteAction(ExternalChangeAction.class); if (commitNecessary) { myUncommittedDocuments.add(document); - myDocumentCommitThread.log("PDI: added to uncommitted", null, false, document, event, myUncommittedDocuments); - - myDocumentCommitThread.queueCommit(myProject, document, event); + if (!fromRefresh && !((DocumentEx)document).isInBulkUpdate()) { + myDocumentCommitThread.queueCommit(myProject, document, event); + } } // Consider that it's worth to perform complete re-parse instead of merge if the whole document text is replaced and @@ -683,7 +691,7 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec document.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, Boolean.TRUE); } - if (commitNecessary && ApplicationManager.getApplication().hasWriteAction(ExternalChangeAction.class)){ + if (commitNecessary && fromRefresh){ commitDocument(document); } // avoid documents piling up during batch processing From 5d7dacca34446e917a1e99d90f1651cc6205893e Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Mar 2012 12:55:09 +0400 Subject: [PATCH 013/106] cleanup --- .../src/com/intellij/lang/folding/CustomFoldingBuilder.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/lang-api/src/com/intellij/lang/folding/CustomFoldingBuilder.java b/platform/lang-api/src/com/intellij/lang/folding/CustomFoldingBuilder.java index cc6c34625ef8..689ad61035da 100644 --- a/platform/lang-api/src/com/intellij/lang/folding/CustomFoldingBuilder.java +++ b/platform/lang-api/src/com/intellij/lang/folding/CustomFoldingBuilder.java @@ -58,7 +58,7 @@ public abstract class CustomFoldingBuilder extends FoldingBuilderEx implements D private void addCustomFoldingRegionsRecursively(@Nullable FoldingStack foldingStack, @NotNull ASTNode node, - List descriptors, + @NotNull List descriptors, int currDepth) { FoldingStack localFoldingStack = isCustomFoldingRoot(node) || foldingStack == null ? new FoldingStack(node) : foldingStack; for (ASTNode child = node.getFirstChildNode(); child != null; child = child.getTreeNext()) { @@ -196,7 +196,7 @@ public abstract class CustomFoldingBuilder extends FoldingBuilderEx implements D } private static class FoldingStack extends Stack { - private ASTNode owner; + private final ASTNode owner; public FoldingStack(@NotNull ASTNode owner) { super(1); @@ -205,7 +205,7 @@ public abstract class CustomFoldingBuilder extends FoldingBuilderEx implements D @NotNull public ASTNode getOwner() { - return this.owner; + return owner; } } } From a2493cd3918043813f870809ea0fca726f65c032 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Mar 2012 12:55:36 +0400 Subject: [PATCH 014/106] do not start external ann pass on no change --- .../codeInsight/daemon/impl/ExternalToolPassFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPassFactory.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPassFactory.java index 4dec3b2a23b6..d1717395c5c5 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPassFactory.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPassFactory.java @@ -54,7 +54,7 @@ public class ExternalToolPassFactory extends AbstractProjectComponent implements @Override @Nullable public TextEditorHighlightingPass createHighlightingPass(@NotNull PsiFile file, @NotNull final Editor editor) { - TextRange textRange = file.getTextRange(); + TextRange textRange = FileStatusMap.getDirtyTextRange(editor, Pass.EXTERNAL_TOOLS) == null ? null : file.getTextRange(); if (textRange == null || !externalAnnotatorsDefined(file)) { return null; } From d67cbcc81b0538c9be0b258eecb75d1e53a57149 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Mar 2012 12:58:49 +0400 Subject: [PATCH 015/106] double dispose --- .../impl/ConfigFileContainerImpl.java | 5 +- .../util/descriptors/impl/ConfigFileImpl.java | 55 +++++++++---------- .../daemon/DaemonAnalyzerTestCase.java | 1 - .../vfs/impl/VirtualFilePointerImpl.java | 10 ++-- .../impl/VirtualFilePointerManagerImpl.java | 9 +-- .../openapi/vfs/VirtualFilePointerTest.java | 33 +++++++++++ .../testFramework/PlatformTestCase.java | 6 -- 7 files changed, 70 insertions(+), 49 deletions(-) diff --git a/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileContainerImpl.java b/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileContainerImpl.java index 6299468b345b..331db279750b 100644 --- a/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileContainerImpl.java +++ b/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileContainerImpl.java @@ -16,10 +16,11 @@ package com.intellij.util.descriptors.impl; +import com.intellij.openapi.Disposable; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.MultiValuesMap; import com.intellij.openapi.vfs.*; -import com.intellij.openapi.Disposable; import com.intellij.util.EventDispatcher; import com.intellij.util.descriptors.*; import org.jetbrains.annotations.Nullable; @@ -135,6 +136,7 @@ public class ConfigFileContainerImpl implements ConfigFileContainer { } for (ConfigFileInfo configuration : newDescriptors) { final ConfigFileImpl configFile = new ConfigFileImpl(this, configuration); + Disposer.register(this, configFile); myConfigFiles.put(metaData, configFile); added.add(configFile); } @@ -142,6 +144,7 @@ public class ConfigFileContainerImpl implements ConfigFileContainer { for (ConfigFile descriptor : toDelete) { myConfigFiles.remove(descriptor.getMetaData(), descriptor); + Disposer.dispose(descriptor); } myCachedConfigFiles = null; diff --git a/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileImpl.java b/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileImpl.java index fcee66b35973..a64cc6c8a313 100644 --- a/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileImpl.java +++ b/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileImpl.java @@ -1,4 +1,3 @@ - package com.intellij.util.descriptors.impl; import com.intellij.openapi.project.Project; @@ -22,43 +21,38 @@ import org.jetbrains.annotations.Nullable; */ public class ConfigFileImpl implements ConfigFile { @NotNull private ConfigFileInfo myInfo; - private VirtualFilePointer myFilePointer; - private PsiFile myPsiFile; + private final VirtualFilePointer myFilePointer; + private volatile PsiFile myPsiFile; private final ConfigFileContainerImpl myContainer; private final Project myProject; private long myModificationCount; - private final Object myPsiFileLock = new Object(); - private final VirtualFilePointerListener myListener = new VirtualFilePointerListener() { - public void beforeValidityChanged(final VirtualFilePointer[] pointers) { - } - - public void validityChanged(final VirtualFilePointer[] pointers) { - synchronized (myPsiFileLock) { - myPsiFile = null; - } - onChange(); - } - }; public ConfigFileImpl(@NotNull final ConfigFileContainerImpl container, @NotNull final ConfigFileInfo configuration) { myContainer = container; myInfo = configuration; - setUrl(configuration.getUrl()); + final VirtualFilePointerManager pointerManager = VirtualFilePointerManager.getInstance(); + myFilePointer = pointerManager.create(configuration.getUrl(), this, new VirtualFilePointerListener() { + @Override + public void beforeValidityChanged(final VirtualFilePointer[] pointers) { + } + + @Override + public void validityChanged(final VirtualFilePointer[] pointers) { + myPsiFile = null; + onChange(); + } + }); + onChange(); Disposer.register(container, this); myProject = myContainer.getProject(); } - private void setUrl(String url) { - final VirtualFilePointerManager pointerManager = VirtualFilePointerManager.getInstance(); - myFilePointer = pointerManager.create(url, this, myListener); - onChange(); - } - private void onChange() { myModificationCount++; myContainer.fireDescriptorChanged(this); } + @Override public String getUrl() { return myFilePointer.getUrl(); } @@ -67,17 +61,16 @@ public class ConfigFileImpl implements ConfigFile { myInfo = info; } + @Override @Nullable public VirtualFile getVirtualFile() { return myFilePointer.getFile(); } + @Override @Nullable public PsiFile getPsiFile() { - PsiFile psiFile; - synchronized (myPsiFileLock) { - psiFile = myPsiFile; - } + PsiFile psiFile = myPsiFile; if (psiFile != null && psiFile.isValid()) { return psiFile; @@ -88,27 +81,29 @@ public class ConfigFileImpl implements ConfigFile { psiFile = PsiManager.getInstance(myProject).findFile(virtualFile); - synchronized (myPsiFileLock) { - myPsiFile = psiFile; - } + myPsiFile = psiFile; return psiFile; } + @Override @Nullable public XmlFile getXmlFile() { final PsiFile file = getPsiFile(); return file instanceof XmlFile ? (XmlFile)file : null; } + @Override public void dispose() { } + @Override @NotNull public ConfigFileInfo getInfo() { return myInfo; } + @Override public boolean isValid() { final PsiFile psiFile = getPsiFile(); if (psiFile == null || !psiFile.isValid()) { @@ -122,12 +117,14 @@ public class ConfigFileImpl implements ConfigFile { } + @Override @NotNull public ConfigFileMetaData getMetaData() { return myInfo.getMetaData(); } + @Override public long getModificationCount() { return myModificationCount; } diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java index 53f1c6b6583e..b3dc24ace4ae 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java @@ -109,7 +109,6 @@ public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase { @Override protected void setUp() throws Exception { super.setUp(); - ((VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance()).cleanupForNextTest(); final LocalInspectionTool[] tools = configureLocalInspectionTools(); for (LocalInspectionTool tool : tools) { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerImpl.java index c1b580603cbd..fa98c84c896e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerImpl.java @@ -219,11 +219,13 @@ public class VirtualFilePointerImpl extends UserDataHolderBase implements Virtua disposed = true; final Pair pair = myFileAndUrl; - if (pair.first != null) { - ((VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance()).clearPointerCaches(pair.first.getUrl(), myListener); + VirtualFile file = pair.first; + if (file != null) { + ((VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance()).clearPointerCaches(file.getUrl(), myListener); } - if (pair.second != null) { - ((VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance()).clearPointerCaches(pair.second, myListener); + String url = pair.second; + if (url != null && (file == null || !url.equals(file.getUrl()))) { + ((VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance()).clearPointerCaches(url, myListener); } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java index 15ec1b998201..6b9ac8d5ab93 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java @@ -72,7 +72,6 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp synchronized void clearPointerCaches(String url, VirtualFilePointerListener listener) { TreeMap urlToPointer = myUrlToPointerMaps.get(listener); - if (urlToPointer == null && ApplicationManager.getApplication().isUnitTestMode()) return; assert urlToPointer != null; urlToPointer.remove(VfsUtil.urlToPath(url)); if (urlToPointer.isEmpty()) { @@ -148,12 +147,6 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp return url.substring(separatorIndex + JarFileSystem.JAR_SEPARATOR.length()); } - @TestOnly - public synchronized void cleanupForNextTest() { - myUrlToPointerMaps.clear(); - myContainers.clear(); - } - /** * @see #create(String, com.intellij.openapi.Disposable, com.intellij.openapi.vfs.pointers.VirtualFilePointerListener) */ @@ -339,7 +332,7 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp VirtualFilePointerListener listener = entry.getKey(); TreeMap map = entry.getValue(); for (VirtualFilePointerImpl pointer : map.values()) { - myUrlToPointerMaps.clear(); + //myUrlToPointerMaps.clear(); pointer.throwNotDisposedError("Not disposed pointer: listener="+listener); } } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VirtualFilePointerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VirtualFilePointerTest.java index 116a6c59557c..ec9f7b074671 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VirtualFilePointerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VirtualFilePointerTest.java @@ -424,6 +424,39 @@ public class VirtualFilePointerTest extends PlatformLangTestCase { }); } + public void testDoubleDispose() throws IOException { + final File tempDir = createTempDirectory(); + final File file = new File(tempDir, "f1"); + boolean created = file.createNewFile(); + assertTrue(created); + + final VirtualFile[] vFile = new VirtualFile[1]; + final String url = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, file.getCanonicalPath().replace(File.separatorChar, '/')); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + vFile[0] = VirtualFileManager.getInstance().refreshAndFindFileByUrl(url); + } + }); + + Disposable disposable = Disposer.newDisposable(); + final VirtualFilePointer pointer = myVirtualFilePointerManager.create(vFile[0], disposable, new VirtualFilePointerListener() { + @Override + public void beforeValidityChanged(VirtualFilePointer[] pointers) { + } + + @Override + public void validityChanged(VirtualFilePointer[] pointers) { + } + }); + + + assertTrue(pointer.isValid()); + + Disposer.dispose(disposable); + assertFalse(pointer.isValid()); + } + public void testThreads() throws IOException, InterruptedException { final File ioTempDir = createTempDirectory(); final File ioPtrBase = new File(ioTempDir, "parent"); diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java index 2a853d4ea32f..6eaef6b87234 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java @@ -53,11 +53,9 @@ import com.intellij.openapi.util.EmptyRunnable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.impl.VirtualFilePointerManagerImpl; import com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl; import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl; import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS; -import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; @@ -339,10 +337,6 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro LocalHistoryImpl.getInstanceImpl().cleanupForNextTest(); - VirtualFilePointerManagerImpl virtualFilePointerManager = (VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance(); - if (virtualFilePointerManager != null) { - virtualFilePointerManager.cleanupForNextTest(); - } PatchedWeakReference.clearAll(); } From ec31fd8946473d543867db53cb54d06607cfd76c Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 20 Mar 2012 13:48:02 +0400 Subject: [PATCH 016/106] IDEA-81085 (UI unresponsive during maven artifact downloads) --- .../project/MavenArtifactDownloader.java | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactDownloader.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactDownloader.java index ced430176ea0..0aee05f9e8dc 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactDownloader.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactDownloader.java @@ -90,23 +90,8 @@ public class MavenArtifactDownloader { return download(artifacts, downloadedFiles); } finally { - scheduleFilesRefresh(downloadedFiles); - } - } - - private void scheduleFilesRefresh(final List downloadedFiles) { - Runnable refreshTask = new Runnable() { - public void run() { - LocalFileSystem.getInstance().refreshIoFiles(downloadedFiles); - } - }; - - if (ApplicationManager.getApplication().isUnitTestMode() - || ApplicationManager.getApplication().isDispatchThread()) { - refreshTask.run(); - } - else { - ApplicationManager.getApplication().invokeLater(refreshTask); + boolean isAsync = !ApplicationManager.getApplication().isUnitTestMode(); + LocalFileSystem.getInstance().refreshIoFiles(downloadedFiles, isAsync, false, null); } } From 216447ce8c0c52426e41338198800f631dfc3bf4 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 20 Mar 2012 14:19:15 +0400 Subject: [PATCH 017/106] IDEA-83059 (Maven plugin exception) --- .../intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java index fb4c6759109a..e56a68e89719 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java @@ -1647,6 +1647,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec if (newFilePair == null) continue; VirtualFile newFile = newFilePair.first; + if (newFile == null) continue; // already open if (eachWindow.findFileIndex(newFile) != -1) continue; From 910bfcdbfa381bf604024619d0630f982dca4673 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Mar 2012 11:19:35 +0100 Subject: [PATCH 018/106] remove redundant commit in wrong thread (EA-34768 - assert: PsiDocumentManagerImpl.commitAllDocuments) --- .../src/com/intellij/codeEditor/printing/TextPainter.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeEditor/printing/TextPainter.java b/platform/lang-impl/src/com/intellij/codeEditor/printing/TextPainter.java index e36efc870d41..b57def2b36be 100644 --- a/platform/lang-impl/src/com/intellij/codeEditor/printing/TextPainter.java +++ b/platform/lang-impl/src/com/intellij/codeEditor/printing/TextPainter.java @@ -27,7 +27,6 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; @@ -93,8 +92,6 @@ public class TextPainter implements Printable { myFileName = fileName; mySegmentEnd = myDocument.getTextLength(); - PsiDocumentManager.getInstance(project).commitAllDocuments(); - myFileType = psiFile.getFileType(); From a1c1f09f0f96dffbb53cef8aebb44d8ee24750bf Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 20 Mar 2012 14:46:22 +0400 Subject: [PATCH 019/106] IDEA-83008 (Maven treats goal specific required parameters as required when missing from default plugin configuration section) --- .../MavenPluginConfigurationDomExtender.java | 27 ++++++++++++------- .../idea/maven/dom/MavenPluginDomUtil.java | 3 +++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPluginConfigurationDomExtender.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPluginConfigurationDomExtender.java index 44cb3dff60bd..eebd3737476a 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPluginConfigurationDomExtender.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPluginConfigurationDomExtender.java @@ -17,7 +17,9 @@ package org.jetbrains.idea.maven.dom; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiElement; import com.intellij.psi.codeStyle.NameUtil; +import com.intellij.psi.xml.XmlElement; import com.intellij.psi.xml.XmlTag; import com.intellij.util.xml.DomElement; import com.intellij.util.xml.GenericDomValue; @@ -34,13 +36,15 @@ import org.jetbrains.idea.maven.dom.converters.MavenPluginCustomParameterValueCo import org.jetbrains.idea.maven.dom.model.MavenDomConfiguration; import org.jetbrains.idea.maven.dom.model.MavenDomConfigurationParameter; import org.jetbrains.idea.maven.dom.model.MavenDomPluginExecution; -import org.jetbrains.idea.maven.dom.model.MavenDomPluginManagement; import org.jetbrains.idea.maven.dom.plugin.MavenDomMojo; import org.jetbrains.idea.maven.dom.plugin.MavenDomParameter; import org.jetbrains.idea.maven.dom.plugin.MavenDomPluginModel; import java.lang.annotation.Annotation; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; public class MavenPluginConfigurationDomExtender extends DomExtender { public static final Key PLUGIN_PARAMETER_KEY = Key.create("MavenPluginConfigurationDomExtender.PLUGIN_PARAMETER_KEY"); @@ -53,21 +57,26 @@ public class MavenPluginConfigurationDomExtender extends DomExtender collectParameters(MavenDomPluginModel pluginModel, MavenDomConfiguration config) { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPluginDomUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPluginDomUtil.java index 7cbcfa2e51de..63bcc9862a2b 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPluginDomUtil.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPluginDomUtil.java @@ -20,6 +20,7 @@ import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.xml.DomElement; +import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.dom.model.MavenDomPlugin; import org.jetbrains.idea.maven.dom.plugin.MavenDomPluginModel; import org.jetbrains.idea.maven.project.MavenProjectsManager; @@ -28,6 +29,7 @@ import org.jetbrains.idea.maven.utils.MavenArtifactUtil; import java.io.File; public class MavenPluginDomUtil { + @Nullable public static MavenDomPluginModel getMavenPluginModel(DomElement element) { Project p = element.getXmlElement().getProject(); @@ -40,6 +42,7 @@ public class MavenPluginDomUtil { return MavenDomUtil.getMavenDomModel(p, pluginXmlFile, MavenDomPluginModel.class); } + @Nullable private static VirtualFile getPluginXmlFile(Project p, MavenDomPlugin pluginElement) { String groupId = pluginElement.getGroupId().getStringValue(); String artifactId = pluginElement.getArtifactId().getStringValue(); From a2326502420ed275fa23d7d31dae50ec3fdefc9f Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Mar 2012 11:48:43 +0100 Subject: [PATCH 020/106] EA-33950 - NPE: MasterDetailsComponent$.customizeCellRenderer --- .../openapi/ui/MasterDetailsComponent.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java index 62c78bbb0f6c..c7d0dcbacf19 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java @@ -462,7 +462,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom boolean hasFocus) { if (value instanceof MyNode) { final MyNode node = ((MyNode)value); - setIcon(node.getConfigurable().getIcon(expanded)); + setIcon(node.getIcon(expanded)); final Font font = UIUtil.getTreeFont(); if (node.isDisplayInBold()) { setFont(font.deriveFont(Font.BOLD)); @@ -699,8 +699,8 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom throw new ConfigurationException("Name should contain non-space characters"); } if (names.contains(name)) { - final NamedConfigurable selectedConfugurable = getSelectedConfugurable(); - if (selectedConfugurable == null || !Comparing.strEqual(selectedConfugurable.getDisplayName(), name)) { + final NamedConfigurable selectedConfigurable = getSelectedConfugurable(); + if (selectedConfigurable == null || !Comparing.strEqual(selectedConfigurable.getDisplayName(), name)) { selectNodeInTree(node); } throw new ConfigurationException(CommonBundle.message("smth.already.exist.error.message", prefix, name), title); @@ -836,6 +836,16 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom public void setDisplayInBold(boolean displayInBold) { myDisplayInBold = displayInBold; } + + @Nullable + public Icon getIcon(boolean expanded) { + // thanks to invokeLater() in TreeUtil.showAndSelect(), we can get calls to getIcon() after the tree has been disposed + final NamedConfigurable configurable = getConfigurable(); + if (configurable != null) { + return configurable.getIcon(expanded); + } + return null; + } } @SuppressWarnings({"ConstantConditions"}) From eddd0173dfe49b0816c65dc219dc045dc0de478c Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Tue, 20 Mar 2012 14:47:21 +0400 Subject: [PATCH 021/106] WI-10360 A gray line under the project view header --- .../src/com/intellij/ide/projectView/impl/ProjectViewImpl.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java index 08d9c320118f..9b63a06d17bc 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java @@ -253,8 +253,6 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo myViewContentPanel = new JPanel(); myPanel = new SimpleToolWindowPanel(true).setProvideQuickActions(false); myPanel.setContent(myViewContentPanel); - - myPanel.setBorder(new ToolWindow.Border(true, false, false, false)); } public String getName() { From 1a33b8db2512783fda0a37ea9a9c57434e6d2e6e Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Mar 2012 12:23:43 +0100 Subject: [PATCH 022/106] EA-31802 - assert: DialogBuilder.showImpl --- .../src/com/intellij/ui/RawCommandLineEditor.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/platform/platform-api/src/com/intellij/ui/RawCommandLineEditor.java b/platform/platform-api/src/com/intellij/ui/RawCommandLineEditor.java index f2af238df062..5b0296ecfd54 100644 --- a/platform/platform-api/src/com/intellij/ui/RawCommandLineEditor.java +++ b/platform/platform-api/src/com/intellij/ui/RawCommandLineEditor.java @@ -15,7 +15,9 @@ */ package com.intellij.ui; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileChooser.FileChooserDescriptor; +import com.intellij.openapi.ui.LabeledComponent; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.IconLoader; @@ -27,6 +29,8 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class RawCommandLineEditor extends JPanel { + private static final Logger LOG = Logger.getInstance("#com.intellij.ui.RawCommandLineEditor"); + private final TextFieldWithBrowseButton myTextField; private String myDialogCaption = ""; @@ -34,6 +38,14 @@ public class RawCommandLineEditor extends JPanel { super(new BorderLayout()); myTextField = new TextFieldWithBrowseButton(new ActionListener() { public void actionPerformed(ActionEvent e) { + if (myDialogCaption == null) { + Container parent = getParent(); + if (parent instanceof LabeledComponent) { + parent = parent.getParent(); + } + LOG.error("Did not call RawCommandLineEditor.setDialogCaption() in " + parent); + myDialogCaption = "Parameters"; + } Messages.showTextAreaDialog(myTextField.getTextField(), myDialogCaption, "EditParametersPopupWindow"); } }); From a6d23dabe933fb9b9ae1b869d947b2d855e03b0b Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Mar 2012 12:38:02 +0100 Subject: [PATCH 023/106] EA-34181 - NPE: EditorImpl$MyTransferHandler$$.run --- .../src/com/intellij/openapi/editor/impl/EditorImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index fb2f5a32ae26..b44e8d539581 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -5803,7 +5803,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (last != null && !(last instanceof EditorComponentImpl)) return; final Editor editor = getEditor(source); - if (action == MOVE && !editor.isViewer()) { + if (action == MOVE && !editor.isViewer() && myDraggedRange != null) { if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), editor.getProject())) { return; } From 5b1f1345f74f2d31eec158021aa22936827f1ffc Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Mar 2012 12:45:38 +0100 Subject: [PATCH 024/106] EA-34735 - assert: DirectoryBasedStorage.; fix python new project validation --- .../src/com/intellij/platform/NewDirectoryProjectDialog.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/platform/NewDirectoryProjectDialog.java b/platform/platform-impl/src/com/intellij/platform/NewDirectoryProjectDialog.java index b40e9ca29530..d902cbe95204 100644 --- a/platform/platform-impl/src/com/intellij/platform/NewDirectoryProjectDialog.java +++ b/platform/platform-impl/src/com/intellij/platform/NewDirectoryProjectDialog.java @@ -103,6 +103,11 @@ public class NewDirectoryProjectDialog extends DialogWrapper { setErrorText("Project name can't be empty"); return; } + if (myLocationField.getText().indexOf('$') >= 0) { + setOKActionEnabled(false); + setErrorText("Project directory name must not contain the $ character"); + return; + } DirectoryProjectGenerator generator = getProjectGenerator(); if (generator != null) { String baseDirPath = myLocationField.getTextField().getText(); From abade7efaee9bb5977daf2151bb839860534a32b Mon Sep 17 00:00:00 2001 From: irengrig Date: Tue, 20 Mar 2012 15:49:44 +0400 Subject: [PATCH 025/106] IDEA-82608 AE at org.jetbrains.idea.svn.RootsToWorkingCopies.getMatchingCopy --- .../committed/CommittedChangesCache.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java index c850c88d6820..c06b21fb42bd 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java @@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.changes.committed; import com.intellij.concurrency.JobScheduler; import com.intellij.lifecycle.PeriodicalTasksCloser; import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.components.PersistentStateComponent; @@ -743,8 +744,24 @@ public class CommittedChangesCache implements PersistentStateComponent receivedChanges) { final Collection changes = receivedChanges == null ? myCachedIncomingChangeLists : receivedChanges; if (changes == null) { - final List lists = loadIncomingChanges(false); - myBus.syncPublisher(COMMITTED_TOPIC).incomingChangesUpdated(new ArrayList(lists)); + final Application application = ApplicationManager.getApplication(); + final Runnable runnable = new Runnable() { + @Override + public void run() { + final List lists = loadIncomingChanges(false); + application.invokeLater(new Runnable() { + @Override + public void run() { + myBus.syncPublisher(COMMITTED_TOPIC).incomingChangesUpdated(new ArrayList(lists)); + } + }); + } + }; + if (application.isDispatchThread()) { + application.executeOnPooledThread(runnable); + } else { + runnable.run(); + } return; } final ArrayList listCopy = new ArrayList(changes); From 725746d5366c21885a0333c5322fe71d24c960c5 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 20 Mar 2012 16:05:37 +0400 Subject: [PATCH 026/106] show ADB logs in console and when ADB crashed (cherry picked from commit d7e15e7) --- .../messages/AndroidBundle.properties | 3 +- plugins/android/src/META-INF/plugin.xml | 2 +- .../jetbrains/android/logcat/AdbErrors.java | 37 +++++++++ .../AndroidLogcatToolWindowFactory.java | 79 +++++++++++++++++-- .../jetbrains/android/sdk/AndroidSdkData.java | 47 ++++++++--- 5 files changed, 150 insertions(+), 18 deletions(-) create mode 100644 plugins/android/src/org/jetbrains/android/logcat/AdbErrors.java diff --git a/plugins/android/resources/messages/AndroidBundle.properties b/plugins/android/resources/messages/AndroidBundle.properties index ba66305c6f68..a5203a77da24 100644 --- a/plugins/android/resources/messages/AndroidBundle.properties +++ b/plugins/android/resources/messages/AndroidBundle.properties @@ -36,7 +36,8 @@ activity.class.not.specified.error=Activity class not specified not.activity.subclass.error={0} is not an Activity subclass no.facet.error=No Android facet found for {0} android.logcat.tab.title=Logcat -android.logcat.title=Android Logcat +android.adb.logs.tab.title=ADB logs +android.logcat.title=Android android.logcat.error.dialog.title=Android Logcat Error android.logcat.color.page.name=Android Logcat warning.level.title=Warning diff --git a/plugins/android/src/META-INF/plugin.xml b/plugins/android/src/META-INF/plugin.xml index 1cfc42b1a4fd..008774bdaad1 100644 --- a/plugins/android/src/META-INF/plugin.xml +++ b/plugins/android/src/META-INF/plugin.xml @@ -181,7 +181,7 @@ - ourAdbErrorList; + + @NotNull + public static synchronized String[] getErrors() { + return ourAdbErrorList != null ? ArrayUtil.toStringArray(ourAdbErrorList) : ArrayUtil.EMPTY_STRING_ARRAY; + } + + public static synchronized void clear() { + if (ourAdbErrorList != null) { + ourAdbErrorList.clear(); + } + } + + public static synchronized void reportError(@NotNull String message, @Nullable String tag) { + final String fullMessage = tag != null ? tag + ": " + message : message; + if (ourAdbErrorList == null) { + ourAdbErrorList = new ArrayList(); + } + ourAdbErrorList.add(fullMessage); + } +} diff --git a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowFactory.java b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowFactory.java index 82f5a22cdd84..389f0f05b1a6 100644 --- a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowFactory.java +++ b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowFactory.java @@ -16,8 +16,10 @@ package org.jetbrains.android.logcat; +import com.android.ddmlib.Log; import com.intellij.ProjectTopics; import com.intellij.execution.filters.HyperlinkInfo; +import com.intellij.execution.impl.ConsoleViewImpl; import com.intellij.execution.ui.ConsoleView; import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.facet.ProjectFacetManager; @@ -34,6 +36,7 @@ import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter; import com.intellij.openapi.wm.ex.ToolWindowManagerEx; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentManager; +import com.intellij.ui.content.impl.ContentImpl; import com.intellij.util.messages.MessageBusConnection; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.maven.AndroidMavenUtil; @@ -90,12 +93,34 @@ public class AndroidLogcatToolWindowFactory implements ToolWindowFactory { JPanel contentPanel = view.getContentPanel(); final ContentManager contentManager = toolWindow.getContentManager(); - final Content content = contentManager.getFactory().createContent(contentPanel, null, false); - content.setDisposer(view); - content.setCloseable(false); - content.setPreferredFocusableComponent(contentPanel); - contentManager.addContent(content); - contentManager.setSelectedContent(content, true); + + final Content logcatContent = + contentManager.getFactory().createContent(contentPanel, AndroidBundle.message("android.logcat.tab.title"), false); + logcatContent.setDisposer(view); + logcatContent.setCloseable(false); + logcatContent.setPreferredFocusableComponent(contentPanel); + contentManager.addContent(logcatContent); + contentManager.setSelectedContent(logcatContent, true); + + final ConsoleView console = new ConsoleViewImpl(project, false); + final Content adbLogsContent = new ContentImpl(console.getComponent(), AndroidBundle.message("android.adb.logs.tab.title"), false); + adbLogsContent.setCloseable(false); + contentManager.addContent(adbLogsContent); + + //noinspection UnnecessaryFullyQualifiedName + com.android.ddmlib.Log.setLogOutput(new Log.ILogOutput() { + @Override + public void printLog(Log.LogLevel logLevel, String tag, String message) { + reportAdbLogMessage(logLevel, tag, message, console); + } + + @Override + public void printAndPromptLog(Log.LogLevel logLevel, String tag, String message) { + // todo: should we show dialog? + reportAdbLogMessage(logLevel, tag, message, console); + } + }); + ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { view.activate(); @@ -107,6 +132,48 @@ public class AndroidLogcatToolWindowFactory implements ToolWindowFactory { }); } + private static void reportAdbLogMessage(Log.LogLevel logLevel, String tag, String message, @NotNull ConsoleView consoleView) { + if (message == null) { + return; + } + if (logLevel == null) { + logLevel = Log.LogLevel.INFO; + } + + if (logLevel == Log.LogLevel.ERROR || logLevel == Log.LogLevel.ASSERT) { + AdbErrors.reportError(message, tag); + } + + final ConsoleViewContentType contentType = toConsoleViewContentType(logLevel); + if (contentType == null) { + return; + } + + final String fullMessage = tag != null ? tag + ": " + message : message; + consoleView.print(fullMessage + '\n', contentType); + } + + @Nullable + private static ConsoleViewContentType toConsoleViewContentType(@NotNull Log.LogLevel logLevel) { + switch (logLevel) { + case VERBOSE: + return null; + case DEBUG: + return null; + case INFO: + return ConsoleViewContentType.getConsoleViewType(AndroidLogcatConstants.INFO); + case WARN: + return ConsoleViewContentType.getConsoleViewType(AndroidLogcatConstants.WARNING); + case ERROR: + return ConsoleViewContentType.getConsoleViewType(AndroidLogcatConstants.ERROR); + case ASSERT: + return ConsoleViewContentType.getConsoleViewType(AndroidLogcatConstants.ASSERT); + default: + assert false : "Unknown log level " + logLevel; + } + return null; + } + private static void checkFacetAndSdk(Project project, AndroidLogcatToolWindowView view) { final List facets = ProjectFacetManager.getInstance(project).getFacets(AndroidFacet.ID); final ConsoleView console = view.getLogConsole().getConsole(); diff --git a/plugins/android/src/org/jetbrains/android/sdk/AndroidSdkData.java b/plugins/android/src/org/jetbrains/android/sdk/AndroidSdkData.java index c63650b914fb..616a78281a17 100644 --- a/plugins/android/src/org/jetbrains/android/sdk/AndroidSdkData.java +++ b/plugins/android/src/org/jetbrains/android/sdk/AndroidSdkData.java @@ -18,6 +18,7 @@ package org.jetbrains.android.sdk; import com.android.ddmlib.AndroidDebugBridge; import com.android.ddmlib.DdmPreferences; +import com.android.ddmlib.Log; import com.android.sdklib.*; import com.android.sdklib.internal.project.ProjectProperties; import com.intellij.CommonBundle; @@ -33,6 +34,7 @@ import com.intellij.reference.SoftReference; import com.intellij.util.containers.HashMap; import gnu.trove.TIntObjectHashMap; import org.jetbrains.android.actions.AndroidEnableAdbServiceAction; +import org.jetbrains.android.logcat.AdbErrors; import org.jetbrains.android.util.AndroidCommonUtils; import org.jetbrains.android.util.AndroidUtils; import org.jetbrains.android.util.BufferingFileWrapper; @@ -182,12 +184,15 @@ public class AndroidSdkData { return getLocation().hashCode(); } + @SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod") private boolean initializeDdmlib(@NotNull Project project) { ApplicationManager.getApplication().assertIsDispatchThread(); while (true) { final MyInitializeDdmlibTask task = new MyInitializeDdmlibTask(project); + AdbErrors.clear(); + Thread t = new Thread(new Runnable() { @Override public void run() { @@ -205,25 +210,33 @@ public class AndroidSdkData { boolean finished = task.isFinished(); - //noinspection AssignmentToStaticFieldFromInstanceMethod - myAdbCrashed = !finished; - if (task.isCanceled()) { + myAdbCrashed = !finished; forceInterrupt(t); return false; } - if (!finished) { - int result = Messages - .showOkCancelDialog(project, - "ADB not responding. Please, kill \"" + SdkConstants.FN_ADB + "\" process manually and click 'Retry'", - CommonBundle.getErrorTitle(), "&Retry", "&Cancel", Messages.getErrorIcon()); + myAdbCrashed = false; - if (result == 1) { + if (!finished) { + final String adbErrorString = combine(AdbErrors.getErrors()); + final int result = Messages.showDialog(project, "ADB not responding. You can wait more, or kill \"" + + SdkConstants.FN_ADB + + "\" process manually and click 'Restart'" + + (adbErrorString.length() > 0 ? "\nErrors from ADB:\n" + adbErrorString : ""), + CommonBundle.getErrorTitle(), new String[]{"&Wait more", "&Restart", "&Cancel"}, 0, + Messages.getErrorIcon()); + if (result == 2) { + // cancel + myAdbCrashed = true; forceInterrupt(t); return false; } - retryWas = true; + else if (result == 1) { + // restart + myAdbCrashed = true; + retryWas = true; + } } } @@ -236,6 +249,19 @@ public class AndroidSdkData { return true; } + @NotNull + private static String combine(@NotNull String[] strs) { + final StringBuilder builder = new StringBuilder(); + + for (String str : strs) { + if (builder.length() > 0) { + builder.append('\n'); + } + builder.append(str); + } + return builder.toString(); + } + @SuppressWarnings({"BusyWait"}) private static void forceInterrupt(Thread thread) { /* @@ -262,6 +288,7 @@ public class AndroidSdkData { synchronized (myDdmsLock) { if (!myDdmLibInitialized) { myDdmLibInitialized = true; + DdmPreferences.setLogLevel(Log.LogLevel.INFO.getStringValue()); DdmPreferences.setTimeOut(AndroidUtils.TIMEOUT); AndroidDebugBridge.init(AndroidEnableAdbServiceAction.isAdbServiceEnabled()); LOG.info("DDMLib initialized"); From 919a38f52ea4ba88d0ab1b8732c4be3c5ce550ab Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 20 Mar 2012 16:08:06 +0400 Subject: [PATCH 027/106] EA-34609 fix assertion (cherry picked from commit 3e3694c) --- .../src/org/jetbrains/android/dom/AndroidDomExtender.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/android/src/org/jetbrains/android/dom/AndroidDomExtender.java b/plugins/android/src/org/jetbrains/android/dom/AndroidDomExtender.java index 1db4a5146102..ac16ab465ef8 100644 --- a/plugins/android/src/org/jetbrains/android/dom/AndroidDomExtender.java +++ b/plugins/android/src/org/jetbrains/android/dom/AndroidDomExtender.java @@ -249,7 +249,7 @@ public class AndroidDomExtender extends DomExtender { return ApplicationManager.getApplication().runReadAction(new Computable() { @Nullable public PsiClass compute() { - return c.getSuperClass(); + return c.isValid() ? c.getSuperClass() : null; } }); } From 0c83e2d2b3275f3734570afc174cbf33f0303e64 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 20 Mar 2012 16:08:59 +0400 Subject: [PATCH 028/106] EA-33751 fix assertion (cherry picked from commit 8ebcdd236c437aca1391d5497c7cf2442c3fed58) --- .../android/dom/manifest/ManifestDomFileDescription.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/android/src/org/jetbrains/android/dom/manifest/ManifestDomFileDescription.java b/plugins/android/src/org/jetbrains/android/dom/manifest/ManifestDomFileDescription.java index acea0d6bb5f5..641838ee575c 100644 --- a/plugins/android/src/org/jetbrains/android/dom/manifest/ManifestDomFileDescription.java +++ b/plugins/android/src/org/jetbrains/android/dom/manifest/ManifestDomFileDescription.java @@ -42,7 +42,7 @@ public class ManifestDomFileDescription extends DomFileDescription { return false; } final Module module = ModuleUtil.findModuleForPsiElement(file); - return module == null || AndroidFacet.getInstance(module) != null; + return module == null || !module.isDisposed() && AndroidFacet.getInstance(module) != null; } protected void initializeFileDescription() { From 557b6ad60448d91a2c772ce81bbbd1c430992746 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 20 Mar 2012 16:11:15 +0400 Subject: [PATCH 029/106] EA-34581 fix IVFAE (cherry picked from commit dc55325) --- .../android/compiler/ClassesAndJarsValidityState.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/android/src/org/jetbrains/android/compiler/ClassesAndJarsValidityState.java b/plugins/android/src/org/jetbrains/android/compiler/ClassesAndJarsValidityState.java index 626d41af239d..41ba37422358 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/ClassesAndJarsValidityState.java +++ b/plugins/android/src/org/jetbrains/android/compiler/ClassesAndJarsValidityState.java @@ -29,7 +29,9 @@ class ClassesAndJarsValidityState implements ValidityState { } } else if (StdFileTypes.CLASS.equals(file.getFileType()) || file.getFileType() instanceof ArchiveFileType) { - myFiles.put(file.getPath(), file.getTimeStamp()); + if (file.isValid()) { + myFiles.put(file.getPath(), file.getTimeStamp()); + } } } From 6a29b35840a9217a9847ab106bce5a00fc09d54b Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Mar 2012 13:14:41 +0100 Subject: [PATCH 030/106] EA-33948 - NPE: PositionPanel.caretPositionChanged --- .../com/intellij/openapi/wm/impl/status/PositionPanel.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PositionPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PositionPanel.java index cc6e397f8e86..e1f9760bb1f8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PositionPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/PositionPanel.java @@ -128,8 +128,11 @@ public class PositionPanel extends EditorBasedWidget implements StatusBarWidget. public void caretPositionChanged(final CaretEvent e) { final Editor editor = e.getEditor(); Project project = editor.getProject(); - if (project != null && !project.isDisposed() && FileEditorManager.getInstance(project).getSelectedTextEditor() == e.getEditor()) { - updatePosition(editor); + if (project != null && !project.isDisposed()) { + final FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); // returns null for default project + if (fileEditorManager != null && fileEditorManager.getSelectedTextEditor() == e.getEditor()) { + updatePosition(editor); + } } } From 0b89cf0b7ca6cd0520bb4c5604576420abfc0a47 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Mar 2012 13:35:47 +0100 Subject: [PATCH 031/106] EA-32136 - assert: ComponentManagerImpl.getComponent --- .../src/com/intellij/ide/palette/impl/PaletteWindow.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/java/idea-ui/src/com/intellij/ide/palette/impl/PaletteWindow.java b/java/idea-ui/src/com/intellij/ide/palette/impl/PaletteWindow.java index f14a38242e12..18a485dc18e3 100644 --- a/java/idea-ui/src/com/intellij/ide/palette/impl/PaletteWindow.java +++ b/java/idea-ui/src/com/intellij/ide/palette/impl/PaletteWindow.java @@ -55,9 +55,11 @@ public class PaletteWindow extends JPanel implements DataProvider { private PaletteGroupHeader myLastFocusedGroup; @NonNls private static final String ourHelpID = "guiDesigner.uiTour.palette"; + private PaletteManager myPaletteManager; public PaletteWindow(Project project) { myProject = project; + myPaletteManager = PaletteManager.getInstance(myProject); myProviders = Extensions.getExtensions(PaletteItemProvider.EP_NAME, project); for(PaletteItemProvider provider: myProviders) { provider.addListener(myPropertyChangeListener); @@ -180,7 +182,7 @@ public class PaletteWindow extends JPanel implements DataProvider { group.getComponentList().clearSelection(); } ListSelectionEvent event = new ListSelectionEvent(this, -1, -1, false); - PaletteManager.getInstance(myProject).notifySelectionChanged(event); + myPaletteManager.notifySelectionChanged(event); } @Nullable public PaletteItem getActiveItem() { @@ -252,7 +254,7 @@ public class PaletteWindow extends JPanel implements DataProvider { break; } } - PaletteManager.getInstance(myProject).notifySelectionChanged(e); + myPaletteManager.notifySelectionChanged(e); } } From 909c966137f54588e1bcdfc6b4550cfc69a8ac60 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 20 Mar 2012 16:39:37 +0400 Subject: [PATCH 032/106] remove unused code --- .../org/jetbrains/plugins/github/GithubShareAction.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java index 6365f187a447..d306f0b6e297 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java @@ -18,12 +18,10 @@ import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Ref; import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.VcsOutgoingChangesProvider; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.ChangeListManagerImpl; import com.intellij.openapi.vcs.changes.InvokeAfterUpdateMode; import com.intellij.openapi.vcs.changes.actions.RefreshAction; -import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.concurrency.Semaphore; @@ -213,11 +211,6 @@ public class GithubShareAction extends DumbAwareAction { Messages.showErrorDialog(project, "Cannot find git initialized", "Failed to share"); return false; } - final VcsOutgoingChangesProvider provider = gitVcs.getOutgoingChangesProvider(); - if (provider == null) { - Messages.showErrorDialog(project, "Cannot find git initialized", "Failed to share"); - return false; - } GitRepositoryManager repositoryManager = ServiceManager.getService(project, GitRepositoryManager.class); Git git = ServiceManager.getService(Git.class); From e90e4b6ce298fd7bda19e2d43e37720da997e985 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Mar 2012 13:43:59 +0100 Subject: [PATCH 033/106] EA-32835 - assert: ContributorsBasedGotoByModel$.process --- .../util/gotoByName/ContributorsBasedGotoByModel.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java index db21ded54762..b02c3272bc89 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java @@ -16,10 +16,13 @@ package com.intellij.ide.util.gotoByName; import com.intellij.concurrency.JobUtil; +import com.intellij.diagnostic.PluginException; +import com.intellij.ide.plugins.PluginManager; import com.intellij.ide.util.NavigationItemListCellRenderer; import com.intellij.navigation.ChooseByNameContributor; import com.intellij.navigation.NavigationItem; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbService; @@ -109,7 +112,13 @@ public abstract class ContributorsBasedGotoByModel implements ChooseByNameModel try { for (NavigationItem item : contributor.getItemsByName(name, pattern, myProject, checkBoxState)) { if (item == null) { - LOG.error("null item from contributor " + contributor + " for name " + name); + final PluginId pluginId = PluginManager.getPluginByClassName(contributor.getClass().getName()); + if (pluginId != null) { + LOG.error(new PluginException("null item from contributor " + contributor + " for name " + name, pluginId)); + } + else { + LOG.error("null item from contributor " + contributor + " for name " + name); + } continue; } From 4f4053c86f3d913c1e1455a43ea6b1fdce885fc0 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 20 Mar 2012 16:45:09 +0400 Subject: [PATCH 034/106] IDEA-70202 Spring Integration fails to recognize existing constructor sort arguments by type --- platform/util/src/com/intellij/openapi/util/Comparing.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/util/src/com/intellij/openapi/util/Comparing.java b/platform/util/src/com/intellij/openapi/util/Comparing.java index 95f5f8ab166a..4860c7ab53f7 100644 --- a/platform/util/src/com/intellij/openapi/util/Comparing.java +++ b/platform/util/src/com/intellij/openapi/util/Comparing.java @@ -140,6 +140,10 @@ public class Comparing { return o1 < o2 ? -1 : o1 == o2 ? 0 : 1; } + public static int compare(boolean o1, boolean o2) { + return o1 == o2 ? 0 : o1 ? 1 : -1; + } + public static int compare(int o1, int o2) { return o1 < o2 ? -1 : o1 == o2 ? 0 : 1; } From 661c34b2b45156fda3168d327d78126e61ef2555 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Mon, 19 Mar 2012 13:01:30 +0400 Subject: [PATCH 035/106] remove duplicating token sets --- .../jetbrains/plugins/groovy/lang/lexer/TokenSets.java | 10 ---------- .../expressions/arithmetic/PostfixExpression.java | 2 +- .../expressions/arithmetic/UnaryExpression.java | 2 +- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java index b04214d900aa..d09ec7ff336d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java @@ -201,14 +201,4 @@ public abstract class TokenSets { ); public static final TokenSet SHIFT_SIGNS = TokenSet.create(COMPOSITE_LSHIFT_SIGN, COMPOSITE_RSHIFT_SIGN, COMPOSITE_TRIPLE_SHIFT_SIGN); - - public static final TokenSet POSTFIXES = TokenSet.create(mINC,mDEC); - public static final TokenSet PREFIXES = TokenSet.create( - mPLUS, - mMINUS, - mINC, - mDEC, - mBNOT, - mLNOT - ); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/PostfixExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/PostfixExpression.java index e8edbafc9d0b..2d96ffa9b118 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/PostfixExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/PostfixExpression.java @@ -40,7 +40,7 @@ public class PostfixExpression implements GroovyElementTypes { } private static void subParse(PsiBuilder builder, PsiBuilder.Marker marker) { - if (ParserUtils.getToken(builder, TokenSets.POSTFIXES)) { + if (ParserUtils.getToken(builder, TokenSets.POSTFIX_UNARY_OP_SET)) { PsiBuilder.Marker newMarker = marker.precede(); marker.done(POSTFIX_EXPRESSION); subParse(builder, newMarker); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/UnaryExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/UnaryExpression.java index 64d4a3c3c515..d215334597f7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/UnaryExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/UnaryExpression.java @@ -30,7 +30,7 @@ public class UnaryExpression implements GroovyElementTypes { public static boolean parse(PsiBuilder builder, GroovyParser parser) { PsiBuilder.Marker marker = builder.mark(); - if (ParserUtils.getToken(builder, TokenSets.PREFIXES)) { + if (ParserUtils.getToken(builder, TokenSets.UNARY_OP_SET)) { ParserUtils.getToken(builder, mNLS); parse(builder, parser); marker.done(UNARY_EXPRESSION); From a0780033a5c1a884516286f843f01858d98b72a0 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Mon, 19 Mar 2012 14:34:30 +0400 Subject: [PATCH 036/106] correct control flow for prefix and postfix ++, --. --- .../controlFlow/impl/ControlFlowBuilder.java | 21 ++++++++----------- .../testdata/groovy/controlFlow/for1.test | 7 +++---- .../testdata/groovy/controlFlow/while1.test | 7 +++---- .../groovy/controlFlow/whileNonConstant.test | 9 ++++---- 4 files changed, 19 insertions(+), 25 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java index 2e4f31e52201..16b9c5ea7317 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java @@ -413,17 +413,13 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { if (name == null) return; if (ControlFlowUtils.isIncOrDecOperand(refExpr) && !myAssertionsOnly) { - final ReadWriteVariableInstruction i = new ReadWriteVariableInstruction(name, refExpr, myInstructionNumber++, false); + final InstructionImpl i = new ReadWriteVariableInstruction(name, refExpr, myInstructionNumber++, false); addNode(i); addNode(new ReadWriteVariableInstruction(name, refExpr, myInstructionNumber++, true)); - if (refExpr.getParent() instanceof GrUnaryExpression) { - addNode(new ReadWriteVariableInstruction(name, refExpr, myInstructionNumber++, false)); - } checkPending(i); } else { - final ReadWriteVariableInstruction i = - new ReadWriteVariableInstruction(name, refExpr, myInstructionNumber++, !myAssertionsOnly && PsiUtil.isLValue(refExpr)); + final InstructionImpl i = new ReadWriteVariableInstruction(name, refExpr, myInstructionNumber++, !myAssertionsOnly && PsiUtil.isLValue(refExpr)); addNode(i); checkPending(i); } @@ -563,10 +559,10 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { } GrVariable variable = clause.getDeclaredVariable(); if (variable != null) { - ReadWriteVariableInstruction writeInsn = + ReadWriteVariableInstruction writeInst = new ReadWriteVariableInstruction(variable.getName(), variable, myInstructionNumber++, true); - checkPending(writeInsn); - addNode(writeInsn); + checkPending(writeInst); + addNode(writeInst); } } @@ -755,6 +751,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { Set> pendingAfterTry = new LinkedHashSet>(myPending); + @SuppressWarnings("unchecked") List[] throwers = new List[catchClauses.length]; for (int i = 0; i < catchClauses.length; i++) { @@ -877,9 +874,9 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { super.visitVariable(variable); if (variable.getInitializerGroovy() != null || variable.getParent() instanceof GrTupleDeclaration && ((GrTupleDeclaration)variable.getParent()).getInitializerGroovy() != null) { - ReadWriteVariableInstruction writeInsn = new ReadWriteVariableInstruction(variable.getName(), variable, myInstructionNumber++, true); - checkPending(writeInsn); - addNode(writeInsn); + ReadWriteVariableInstruction writeInst = new ReadWriteVariableInstruction(variable.getName(), variable, myInstructionNumber++, true); + checkPending(writeInst); + addNode(writeInst); } } diff --git a/plugins/groovy/testdata/groovy/controlFlow/for1.test b/plugins/groovy/testdata/groovy/controlFlow/for1.test index 0f0ebbd84c66..cefbd1ce77bf 100644 --- a/plugins/groovy/testdata/groovy/controlFlow/for1.test +++ b/plugins/groovy/testdata/groovy/controlFlow/for1.test @@ -3,8 +3,7 @@ for(int i = 0; i < 10; i++); 0(1) element: null 1(2) WRITE i 2(3) element: For statement -3(4,7) READ i +3(4,6) READ i 4(5) READ i -5(6) WRITE i -6(2) READ i -7() element: null \ No newline at end of file +5(2) WRITE i +6() element: null \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/controlFlow/while1.test b/plugins/groovy/testdata/groovy/controlFlow/while1.test index 3b7578eb1411..493df467f932 100644 --- a/plugins/groovy/testdata/groovy/controlFlow/while1.test +++ b/plugins/groovy/testdata/groovy/controlFlow/while1.test @@ -8,9 +8,8 @@ while (true) { 1(2) WRITE i 2(3) element: WHILE statement 3(4,5) element: IF statement -4(9) READ i +4(8) READ i 5(6) element: IF statement 6(7) READ i -7(8) WRITE i -8(2) READ i -9() element: null \ No newline at end of file +7(2) WRITE i +8() element: null \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/controlFlow/whileNonConstant.test b/plugins/groovy/testdata/groovy/controlFlow/whileNonConstant.test index a54fd3bee520..f1206ab03412 100644 --- a/plugins/groovy/testdata/groovy/controlFlow/whileNonConstant.test +++ b/plugins/groovy/testdata/groovy/controlFlow/whileNonConstant.test @@ -7,11 +7,10 @@ while (condition()) { 0(1) element: null 1(2) WRITE i 2(3) element: WHILE statement -3(4,10) READ condition +3(4,9) READ condition 4(5,6) element: IF statement -5(10) READ i +5(9) READ i 6(7) element: IF statement 7(8) READ i -8(9) WRITE i -9(2) READ i -10() element: null \ No newline at end of file +8(2) WRITE i +9() element: null \ No newline at end of file From 38e526de06009b2e5101b4d9d98bf60841262824 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Mon, 19 Mar 2012 14:43:43 +0400 Subject: [PATCH 037/106] get rid of GrPostfixExpression. use GrUnaryExpression.isPostfix() --- .../groovy/annotator/GroovyAnnotator.java | 3 +- ...GroovyWhileLoopSpinsOnFieldInspection.java | 10 +++-- .../unusedDef/UnusedDefInspection.java | 24 +++++++---- .../utils/ControlFlowUtils.java | 2 - .../utils/EquivalenceChecker.java | 15 +++---- .../utils/SideEffectChecker.java | 18 ++------- .../processors/GroovySpacingProcessor.java | 13 +----- .../intentions/utils/ParenthesesUtils.java | 7 +--- .../lang/parser/GroovyElementTypes.java | 1 - .../groovy/lang/parser/GroovyPsiCreator.java | 6 ++- .../arithmetic/PostfixExpression.java | 2 +- .../groovy/lang/psi/GroovyElementVisitor.java | 4 -- .../expressions/GrPostfixExpression.java | 23 ----------- .../expressions/GrUnaryExpression.java | 2 + .../groovy/lang/psi/impl/PsiImplUtil.java | 9 ++--- .../arithmetic/GrPostfixExprImpl.java | 40 ------------------- .../arithmetic/GrUnaryExpressionImpl.java | 5 +++ .../convertToJava/ExpressionGenerator.java | 8 ++-- .../groovy/expressions/arithmetic/post1.test | 4 +- .../parsing/groovy/statements/for/for10.test | 2 +- .../parsing/groovy/statements/for/for6.test | 2 +- .../parsing/groovy/statements/for/for9.test | 2 +- 22 files changed, 63 insertions(+), 139 deletions(-) delete mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrPostfixExpression.java delete mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrPostfixExprImpl.java diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index 4858ab7eae7a..3a81c5db8a1d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -290,7 +290,8 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { for (PsiReference reference : ReferencesSearch.search(var, new LocalSearchScope(scope)).findAll()) { if (reference instanceof GrReferenceExpression && (PsiUtil.isLValue((GrReferenceExpression)reference) || - ((GrReferenceExpression)reference).getParent() instanceof GrPostfixExpression)) { + ((GrReferenceExpression)reference).getParent() instanceof GrUnaryExpression && + ((GrUnaryExpression)((GrReferenceExpression)reference).getParent()).isPostfix())) { if (hasAssignment) { return true; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWhileLoopSpinsOnFieldInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWhileLoopSpinsOnFieldInspection.java index 01548294a59b..a7429db7e476 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWhileLoopSpinsOnFieldInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWhileLoopSpinsOnFieldInspection.java @@ -30,7 +30,10 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrBlockStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrWhileStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnaryExpression; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import javax.swing.*; @@ -94,9 +97,8 @@ public class GroovyWhileLoopSpinsOnFieldInspection extends BaseInspection { return true; } - if (condition instanceof GrPostfixExpression) { - final GrPostfixExpression postfixExpression = - (GrPostfixExpression) condition; + if (condition instanceof GrUnaryExpression && ((GrUnaryExpression)condition).isPostfix()) { + final GrUnaryExpression postfixExpression = (GrUnaryExpression) condition; final GrExpression operand = postfixExpression.getOperand(); return isSimpleFieldComparison(operand); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java index fb8e2f0e6c12..cbb719736507 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java @@ -24,6 +24,7 @@ import com.intellij.psi.PsiReference; import com.intellij.psi.impl.DebugUtil; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.Processor; import gnu.trove.TIntHashSet; @@ -36,6 +37,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle; import org.jetbrains.plugins.groovy.codeInspection.GroovyLocalInspectionBase; +import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; @@ -44,8 +46,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrPostfixExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnaryExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction; @@ -97,9 +99,9 @@ public class UnusedDefInspection extends GroovyLocalInspectionBase { for (int i = 0; i < dfaResult.size(); i++) { final Instruction instruction = flow[i]; if (instruction instanceof ReadWriteVariableInstruction) { - final ReadWriteVariableInstruction varInsn = (ReadWriteVariableInstruction) instruction; - if (!varInsn.isWrite()) { - final String varName = varInsn.getVariableName(); + final ReadWriteVariableInstruction varInst = (ReadWriteVariableInstruction) instruction; + if (!varInst.isWrite()) { + final String varName = varInst.getVariableName(); TIntObjectHashMap e = dfaResult.get(i); e.forEachValue(new TObjectProcedure() { public boolean execute(TIntHashSet reaching) { @@ -125,13 +127,13 @@ public class UnusedDefInspection extends GroovyLocalInspectionBase { final PsiElement element = instruction.getElement(); if (element == null) return true; PsiElement toHighlight = null; - if (isLocalAssignment(element) && isUsedInToplevelFlowOnly(element)) { + if (isLocalAssignment(element) && isUsedInTopLevelFlowOnly(element) && !isIncOrDec(element)) { if (element instanceof GrReferenceExpression) { PsiElement parent = element.getParent(); if (parent instanceof GrAssignmentExpression) { toHighlight = ((GrAssignmentExpression)parent).getLValue(); } - if (parent instanceof GrPostfixExpression) { + if (parent instanceof GrUnaryExpression && ((GrUnaryExpression)parent).isPostfix()) { toHighlight = parent; } } @@ -147,7 +149,15 @@ public class UnusedDefInspection extends GroovyLocalInspectionBase { }); } - private static boolean isUsedInToplevelFlowOnly(PsiElement element) { + private static boolean isIncOrDec(PsiElement element) { + PsiElement parent = element.getParent(); + if (!(parent instanceof GrUnaryExpression)) return false; + + IElementType type = ((GrUnaryExpression)parent).getOperationTokenType(); + return type == GroovyTokenTypes.mINC || type == GroovyTokenTypes.mDEC; + } + + private static boolean isUsedInTopLevelFlowOnly(PsiElement element) { GrVariable var = null; if (element instanceof GrVariable) { var = (GrVariable) element; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java index 36583cf8bba0..4103c4f5ddc8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java @@ -40,7 +40,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnState import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrThrowStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrCaseSection; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrPostfixExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnaryExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; @@ -499,7 +498,6 @@ public class ControlFlowUtils { public static boolean isIncOrDecOperand(GrReferenceExpression referenceExpression) { final PsiElement parent = referenceExpression.getParent(); - if (parent instanceof GrPostfixExpression) return true; if (parent instanceof GrUnaryExpression) { final IElementType opType = ((GrUnaryExpression)parent).getOperationTokenType(); return opType == GroovyTokenTypes.mDEC || opType == GroovyTokenTypes.mINC; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/EquivalenceChecker.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/EquivalenceChecker.java index fdde5dd99efd..c67351f4dced 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/EquivalenceChecker.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/EquivalenceChecker.java @@ -445,8 +445,8 @@ public class EquivalenceChecker { return prefixExpressionsAreEquivalent((GrUnaryExpression) expToCompare1, (GrUnaryExpression) expToCompare2); case POSTFIX_EXPRESSION: - return postfixExpressionsAreEquivalent((GrPostfixExpression) expToCompare1, - (GrPostfixExpression) expToCompare2); + return postfixExpressionsAreEquivalent((GrUnaryExpression) expToCompare1, + (GrUnaryExpression) expToCompare2); case BINARY_EXPRESSION: return binaryExpressionsAreEquivalent((GrBinaryExpression) expToCompare1, (GrBinaryExpression) expToCompare2); @@ -674,8 +674,8 @@ public class EquivalenceChecker { return expressionsAreEquivalent(operand1, operand2); } - private static boolean postfixExpressionsAreEquivalent(@NotNull GrPostfixExpression postfixExp1, - @NotNull GrPostfixExpression postfixExp2) { + private static boolean postfixExpressionsAreEquivalent(@NotNull GrUnaryExpression postfixExp1, + @NotNull GrUnaryExpression postfixExp2) { final IElementType sign1 = postfixExp1.getOperationTokenType(); final IElementType sign2 = postfixExp2.getOperationTokenType(); if (!sign1.equals(sign2)) { @@ -690,7 +690,7 @@ public class EquivalenceChecker { @NotNull GrBinaryExpression binaryExp2) { final IElementType sign1 = binaryExp1.getOperationTokenType(); final IElementType sign2 = binaryExp2.getOperationTokenType(); - if (sign1 == null || sign2 == null || !sign1.equals(sign2)) { + if (!sign1.equals(sign2)) { return false; } final GrExpression lhs1 = binaryExp1.getLeftOperand(); @@ -834,11 +834,8 @@ public class EquivalenceChecker { if (exp instanceof GrMethodCall) { return CALL_EXPRESSION; } - if (exp instanceof GrPostfixExpression) { - return POSTFIX_EXPRESSION; - } if (exp instanceof GrUnaryExpression) { - return PREFIX_EXPRESSION; + return ((GrUnaryExpression)exp).isPostfix() ? POSTFIX_EXPRESSION : PREFIX_EXPRESSION; } if (exp instanceof GrAssignmentExpression) { return ASSIGNMENT_EXPRESSION; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/SideEffectChecker.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/SideEffectChecker.java index 13cc60aaf959..6f4946169677 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/SideEffectChecker.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/SideEffectChecker.java @@ -20,7 +20,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnaryExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; public class SideEffectChecker { @@ -71,19 +74,6 @@ public class SideEffectChecker { mayHaveSideEffects = true; } - public void visitPostfixExpression( - @NotNull GrPostfixExpression expression) { - if (mayHaveSideEffects) { - return; - } - super.visitPostfixExpression(expression); - final IElementType tokenType = expression.getOperationTokenType(); - if (tokenType.equals(GroovyTokenTypes.mINC) || - tokenType.equals(GroovyTokenTypes.mDEC)) { - mayHaveSideEffects = true; - } - } - public void visitUnaryExpression( @NotNull GrUnaryExpression expression) { if (mayHaveSideEffects) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java index 18c08d51d08a..970d869780a1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java @@ -484,17 +484,8 @@ public class GroovySpacingProcessor extends GroovyElementVisitor { @Override public void visitUnaryExpression(GrUnaryExpression expression) { - //prefix only - LOG.assertTrue(!(expression instanceof GrPostfixExpression)); - - if (expression.getOperationToken() == myChild1) { - createSpaceInCode(mySettings.SPACE_AROUND_UNARY_OPERATOR); - } - } - - @Override - public void visitPostfixExpression(GrPostfixExpression expression) { - if (expression.getOperationToken() == myChild2) { + if (!expression.isPostfix() && expression.getOperationToken() == myChild1 || + expression.isPostfix() && expression.getOperationToken() == myChild2) { createSpaceInCode(mySettings.SPACE_AROUND_UNARY_OPERATOR); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/utils/ParenthesesUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/utils/ParenthesesUtils.java index cf87e09df314..4c354de1c83a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/utils/ParenthesesUtils.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/utils/ParenthesesUtils.java @@ -104,17 +104,14 @@ public class ParenthesesUtils { expression instanceof GrNewExpression) { return TYPE_CAST_PRECEDENCE; } - if (expression instanceof GrPostfixExpression) { - return POSTFIX_PRECEDENCE; - } if (expression instanceof GrUnaryExpression) { - return PREFIX_PRECEDENCE; + return ((GrUnaryExpression)expression).isPostfix()?POSTFIX_PRECEDENCE:PREFIX_PRECEDENCE; } if (expression instanceof GrBinaryExpression) { final GrBinaryExpression binaryExpression = (GrBinaryExpression) expression; final IElementType sign = binaryExpression.getOperationTokenType(); - if (sign != null) return precedenceForBinaryOperator(sign); + return precedenceForBinaryOperator(sign); } if (expression instanceof GrConditionalExpression) { return CONDITIONAL_PRECEDENCE; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java index e1d73e4cc191..0ecc5f9e99f6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java @@ -222,7 +222,6 @@ public interface GroovyElementTypes extends GroovyTokenTypes, GroovyDocElementTy GroovyElementType CAST_EXPRESSION = new GroovyElementType("cast expression"); GroovyElementType SAFE_CAST_EXPRESSION = new GroovyElementType("safe cast expression"); GroovyElementType INSTANCEOF_EXPRESSION = new GroovyElementType("instanceof expression"); - GroovyElementType POSTFIX_EXPRESSION = new GroovyElementType("Postfix expression"); GroovyElementType PATH_PROPERTY_REFERENCE = new GroovyElementType("Property reference"); GroovyElementType PATH_METHOD_CALL = new GroovyElementType("Method call"); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyPsiCreator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyPsiCreator.java index 30c697c579a0..6f5d0be5057f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyPsiCreator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyPsiCreator.java @@ -28,7 +28,10 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyASTPsiElementImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.GrLabelImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.GrListOrMapImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.GrThrowsClauseImpl; -import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.*; +import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationArgumentListImpl; +import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationArrrayInitializerImpl; +import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationImpl; +import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationNameValuePairImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.modifiers.GrModifierListImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.*; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.arguments.GrArgumentLabelImpl; @@ -218,7 +221,6 @@ public class GroovyPsiCreator implements GroovyElementTypes { if (elem == POWER_EXPRESSION) return new GrPowerExpressionImpl(node); if (elem == POWER_EXPRESSION_SIMPLE) return new GrPowerExpressionImpl(node); if (elem == UNARY_EXPRESSION) return new GrUnaryExpressionImpl(node); - if (elem == POSTFIX_EXPRESSION) return new GrPostfixExprImpl(node); if (elem == CAST_EXPRESSION) return new GrTypeCastExpressionImpl(node); if (elem == SAFE_CAST_EXPRESSION) return new GrSafeCastExpressionImpl(node); if (elem == INSTANCEOF_EXPRESSION) return new GrInstanceofExpressionImpl(node); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/PostfixExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/PostfixExpression.java index 2d96ffa9b118..5ab5c9efd0a9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/PostfixExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/PostfixExpression.java @@ -42,7 +42,7 @@ public class PostfixExpression implements GroovyElementTypes { private static void subParse(PsiBuilder builder, PsiBuilder.Marker marker) { if (ParserUtils.getToken(builder, TokenSets.POSTFIX_UNARY_OP_SET)) { PsiBuilder.Marker newMarker = marker.precede(); - marker.done(POSTFIX_EXPRESSION); + marker.done(UNARY_EXPRESSION); subParse(builder, newMarker); } else { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java index cdd57b7486ec..7dbdd4007022 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java @@ -168,10 +168,6 @@ public abstract class GroovyElementVisitor { visitExpression(expression); } - public void visitPostfixExpression(GrPostfixExpression expression) { - visitUnaryExpression(expression); - } - public void visitRegexExpression(GrRegex expression) { visitGStringExpression(expression); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrPostfixExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrPostfixExpression.java deleted file mode 100644 index de2bb73e0d4d..000000000000 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrPostfixExpression.java +++ /dev/null @@ -1,23 +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 org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions; - -/** - * @author ilyas - */ -public interface GrPostfixExpression extends GrUnaryExpression { -} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrUnaryExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrUnaryExpression.java index ef4a8b6b5b85..03900c94f287 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrUnaryExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrUnaryExpression.java @@ -35,4 +35,6 @@ public interface GrUnaryExpression extends GrExpression, PsiPolyVariantReference @NotNull @Override GroovyResolveResult[] multiResolve(final boolean incompleteCode); + + boolean isPostfix(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java index f837f3687ec3..22d5d9ad691d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java @@ -39,7 +39,6 @@ import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.formatter.GeeseUtil; -import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.lexer.TokenSets; import org.jetbrains.plugins.groovy.lang.psi.GrNamedElement; import org.jetbrains.plugins.groovy.lang.psi.GrQualifiedReference; @@ -317,15 +316,13 @@ public class PsiImplUtil { private static int getExprPriorityLevel(GrExpression expr) { int priority = 0; //if (expr instanceof GrNewExpression) priority = 1; - if (expr instanceof GrPostfixExpression) priority = 5; - else if (expr instanceof GrUnaryExpression || - expr instanceof GrTypeCastExpression) priority = 6; + if (expr instanceof GrUnaryExpression) priority = ((GrUnaryExpression)expr).isPostfix() ? 5 : 6; + else if (expr instanceof GrTypeCastExpression) priority = 6; else if (expr instanceof GrRangeExpressionImpl) priority = 11; else if (expr instanceof GrBinaryExpression) { final IElementType opToken = ((GrBinaryExpression)expr).getOperationTokenType(); - LOG.assertTrue(opToken != null, expr.getText()); if (opToken == mSTAR_STAR) priority = 7; else if (opToken == mSTAR || opToken == mDIV) priority = 8; @@ -507,7 +504,7 @@ public class PsiImplUtil { } else { if (oldQualifier == null) { if (refNameElement != null) { - node.addLeaf(GroovyTokenTypes.mDOT, ".", refNameElement.getNode()); + node.addLeaf(mDOT, ".", refNameElement.getNode()); ref.addBefore(newQualifier, refNameElement.getPrevSibling()); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrPostfixExprImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrPostfixExprImpl.java deleted file mode 100644 index f5f2092ad9be..000000000000 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrPostfixExprImpl.java +++ /dev/null @@ -1,40 +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 org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic; - -import com.intellij.lang.ASTNode; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrPostfixExpression; - -/** - * @author ilyas - */ -public class GrPostfixExprImpl extends GrUnaryExpressionImpl implements GrPostfixExpression { - - public GrPostfixExprImpl(@NotNull ASTNode node) { - super(node); - } - - public String toString() { - return "Postfix expression"; - } - - public void accept(GroovyElementVisitor visitor) { - visitor.visitPostfixExpression(this); - } -} \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrUnaryExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrUnaryExpressionImpl.java index 2b95343cbaef..3ae033a3a647 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrUnaryExpressionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrUnaryExpressionImpl.java @@ -125,6 +125,11 @@ public class GrUnaryExpressionImpl extends GrExpressionImpl implements GrUnaryEx return (GroovyResolveResult[])ResolveCache.getInstance(getProject()).resolveWithCaching(this, OUR_RESOLVER, false, incompleteCode); } + @Override + public boolean isPostfix() { + return getFirstChild() instanceof GrExpression; + } + @Override public PsiElement getElement() { return this; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java index b55c62da66d4..2a60c5494208 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java @@ -669,7 +669,7 @@ public class ExpressionGenerator extends Generator { @Override public void visitUnaryExpression(GrUnaryExpression expression) { - final boolean postfix = expression instanceof GrPostfixExpression; + final boolean postfix = expression.isPostfix(); final GroovyResolveResult resolveResult = PsiImplUtil.extractUniqueResult(expression.multiResolve(false)); final PsiElement resolved = resolveResult.getElement(); @@ -816,12 +816,12 @@ public class ExpressionGenerator extends Generator { private static void writeSimpleUnary(GrExpression operand, GrUnaryExpression unary, ExpressionGenerator generator) { String opTokenText = unary.getOperationToken().getText(); - boolean isPrefix = !(unary instanceof GrPostfixExpression); - if (isPrefix) { + boolean isPostfix = unary.isPostfix(); + if (!isPostfix) { generator.getBuilder().append(opTokenText); } operand.accept(generator); - if (!isPrefix) { + if (isPostfix) { generator.getBuilder().append(opTokenText); } } diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/arithmetic/post1.test b/plugins/groovy/testdata/parsing/groovy/expressions/arithmetic/post1.test index 65d287aed2d6..e51d2abf5bda 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/arithmetic/post1.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/arithmetic/post1.test @@ -3,8 +3,8 @@ Groovy script Unary expression PsiElement(!)('!') - Postfix expression - Postfix expression + Unary expression + Unary expression Literal PsiElement(Integer)('3') PsiElement(++)('++') diff --git a/plugins/groovy/testdata/parsing/groovy/statements/for/for10.test b/plugins/groovy/testdata/parsing/groovy/statements/for/for10.test index 24de169dd13b..bec24b69f0a0 100644 --- a/plugins/groovy/testdata/parsing/groovy/statements/for/for10.test +++ b/plugins/groovy/testdata/parsing/groovy/statements/for/for10.test @@ -31,7 +31,7 @@ Groovy script PsiWhiteSpace(' ') PsiElement(;)(';') PsiWhiteSpace(' ') - Postfix expression + Unary expression Reference expression PsiElement(identifier)('i') PsiElement(++)('++') diff --git a/plugins/groovy/testdata/parsing/groovy/statements/for/for6.test b/plugins/groovy/testdata/parsing/groovy/statements/for/for6.test index 8cea9c0925fb..42f99b3dda73 100644 --- a/plugins/groovy/testdata/parsing/groovy/statements/for/for6.test +++ b/plugins/groovy/testdata/parsing/groovy/statements/for/for6.test @@ -26,7 +26,7 @@ Groovy script PsiElement(Integer)('5') PsiElement(;)(';') PsiWhiteSpace(' ') - Postfix expression + Unary expression Reference expression PsiElement(identifier)('i') PsiElement(++)('++') diff --git a/plugins/groovy/testdata/parsing/groovy/statements/for/for9.test b/plugins/groovy/testdata/parsing/groovy/statements/for/for9.test index 24de169dd13b..bec24b69f0a0 100644 --- a/plugins/groovy/testdata/parsing/groovy/statements/for/for9.test +++ b/plugins/groovy/testdata/parsing/groovy/statements/for/for9.test @@ -31,7 +31,7 @@ Groovy script PsiWhiteSpace(' ') PsiElement(;)(';') PsiWhiteSpace(' ') - Postfix expression + Unary expression Reference expression PsiElement(identifier)('i') PsiElement(++)('++') From d004c25e541f36997f873e7216671dbb9e1eaf4c Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Mon, 19 Mar 2012 17:22:39 +0400 Subject: [PATCH 038/106] check control flow issues in class initializers --- .../groovy/codeInspection/GroovyLocalInspectionBase.java | 7 ++++++- .../plugins/groovy/lang/psi/GroovyElementVisitor.java | 4 ++++ .../lang/psi/impl/statements/GrClassInitializerImpl.java | 6 ++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyLocalInspectionBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyLocalInspectionBase.java index d22a439132a4..c46ea77c0c87 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyLocalInspectionBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyLocalInspectionBase.java @@ -22,6 +22,7 @@ import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementVisitor; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrClassInitializer; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; @@ -42,7 +43,6 @@ public abstract class GroovyLocalInspectionBase extends GroovySuppressableInspec return new GroovyPsiElementVisitor(new GroovyElementVisitor() { public void visitClosure(GrClosableBlock closure) { check(closure, problemsHolder); - } public void visitMethod(GrMethod method) { @@ -55,6 +55,11 @@ public abstract class GroovyLocalInspectionBase extends GroovySuppressableInspec public void visitFile(GroovyFileBase file) { check(file, problemsHolder); } + + @Override + public void visitClassInitializer(GrClassInitializer initializer) { + check(initializer.getBlock(), problemsHolder); + } }); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java index 7dbdd4007022..872546b7894a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java @@ -439,4 +439,8 @@ public abstract class GroovyElementVisitor { public void visitTypeParameterList(GrTypeParameterList list) { visitElement(list); } + + public void visitClassInitializer(GrClassInitializer initializer) { + visitElement(initializer); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrClassInitializerImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrClassInitializerImpl.java index ab2d9984d740..623daf3e780f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrClassInitializerImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrClassInitializerImpl.java @@ -25,6 +25,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; +import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrClassInitializer; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; @@ -42,6 +43,11 @@ public class GrClassInitializerImpl extends GroovyPsiElementImpl implements GrCl super(node); } + @Override + public void accept(GroovyElementVisitor visitor) { + visitor.visitClassInitializer(this); + } + public String toString() { return "Class initializer"; } From 4fa74c4b8917020d53df67b345a5fbbbb1926712 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Mon, 19 Mar 2012 17:51:19 +0400 Subject: [PATCH 039/106] unused ++, -- --- .../GroovyUnusedAssignment.html | 2 +- .../GroovyUnusedIncOrDec.html | 6 + plugins/groovy/src/META-INF/plugin.xml | 3 + .../GroovyInspectionBundle.properties | 6 + .../confusing/GrUnusedIncDecInspection.java | 217 ++++++++++++++++++ .../utils/ControlFlowUtils.java | 3 +- .../groovy/lang/GroovyHighlightingTest.groovy | 5 +- .../highlighting/IfIncrementElseReturn.groovy | 2 +- .../highlighting/PrefixIncrementCfa.groovy | 2 +- 9 files changed, 239 insertions(+), 7 deletions(-) create mode 100644 plugins/groovy/resources/inspectionDescriptions/GroovyUnusedIncOrDec.html create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrUnusedIncDecInspection.java diff --git a/plugins/groovy/resources/inspectionDescriptions/GroovyUnusedAssignment.html b/plugins/groovy/resources/inspectionDescriptions/GroovyUnusedAssignment.html index f10ac59f3c47..d093014e3eab 100644 --- a/plugins/groovy/resources/inspectionDescriptions/GroovyUnusedAssignment.html +++ b/plugins/groovy/resources/inspectionDescriptions/GroovyUnusedAssignment.html @@ -2,6 +2,6 @@ This inspection reports on unnecessary Groovy assignment statement -
Powered by InspectorGroovy +
diff --git a/plugins/groovy/resources/inspectionDescriptions/GroovyUnusedIncOrDec.html b/plugins/groovy/resources/inspectionDescriptions/GroovyUnusedIncOrDec.html new file mode 100644 index 000000000000..13ba5a2d65e5 --- /dev/null +++ b/plugins/groovy/resources/inspectionDescriptions/GroovyUnusedIncOrDec.html @@ -0,0 +1,6 @@ + + +This inspection reports on unnecessary Groovy incrementing and decrementing expressions +
+ + diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index f16a34ca5f0c..956a30ddf366 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -408,6 +408,9 @@ + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties index b650ca7468de..28f439a39a95 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties @@ -35,6 +35,8 @@ groovy.dfa.issues=Data Flow Issues unused.assignment=Unused Assignment unused.assignment.tooltip=Assignment is not used +unused.inc.dec=Unused Incrementing or Decrementing + unassigned.access=Variable Not Assigned unassigned.access.short.name=VariableNotAssigned unassigned.access.tooltip=Variable ''{0}'' might not be assigned @@ -77,3 +79,7 @@ rtype.cannot.contain.ltype=''{1}'' cannot contain ''{0}'' new.instance.of.singleton=New instance of class annotated with @groovy.lang.Singleton replace.new.expression.with.0.instance=Replace with ''{0}.instance'' getter.0.clashes.with.getter.1={0} clashes with {1} +unused.0=Unused {0} +remove.0=Remove {0} +replace.postfix.0.with.prefix.0=Replace postfix {0} with prefix {0} +replace.0.with.1=Replace {0} with binary {1} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrUnusedIncDecInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrUnusedIncDecInspection.java new file mode 100644 index 000000000000..8f8ec88a5cec --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrUnusedIncDecInspection.java @@ -0,0 +1,217 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.codeInspection.confusing; + +import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.codeInspection.BaseInspection; +import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor; +import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle; +import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; +import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnaryExpression; +import org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction; +import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; + +import java.util.List; + +/** + * @author Max Medvedev + */ +public class GrUnusedIncDecInspection extends BaseInspection { + @Override + protected BaseInspectionVisitor buildVisitor() { + return new GrUnusedIncDecInspectionVisitor(); + } + + @Override + public boolean isEnabledByDefault() { + return true; + } + + @Nls + @NotNull + public String getGroupDisplayName() { + return GroovyInspectionBundle.message("groovy.dfa.issues"); + } + + @Nls + @NotNull + public String getDisplayName() { + return GroovyInspectionBundle.message("unused.inc.dec"); + } + + @NonNls + @NotNull + public String getShortName() { + return "GroovyUnusedIncOrDec"; + } + + private static class GrUnusedIncDecInspectionVisitor extends BaseInspectionVisitor { + @Override + public void visitUnaryExpression(GrUnaryExpression expression) { + super.visitUnaryExpression(expression); + + IElementType opType = expression.getOperationTokenType(); + if (opType != GroovyTokenTypes.mINC && opType != GroovyTokenTypes.mDEC) return; + + GrExpression operand = expression.getOperand(); + if (!(operand instanceof GrReferenceExpression)) return; + + PsiElement resolved = ((GrReferenceExpression)operand).resolve(); + if (!(resolved instanceof GrVariable) || resolved instanceof GrField) return; + + List accesses = ControlFlowUtils.findAccess((GrVariable)resolved, expression.getOperand(), true, false); + boolean allAreWrite = true; + for (ReadWriteVariableInstruction access : accesses) { + if (!access.isWrite()) { + allAreWrite = false; + break; + } + } + + + if (allAreWrite) { + if (expression.isPostfix() && PsiUtil.isExpressionUsed(expression)) { + registerError(expression.getOperationToken(), + GroovyInspectionBundle.message("unused.0", expression.getOperationToken().getText()), + new LocalQuickFix[]{new ReplacePostfixIncWithPrefixFix(expression), new RemoveIncOrDecFix(expression)}, + ProblemHighlightType.LIKE_UNUSED_SYMBOL); + } + else if (!PsiUtil.isExpressionUsed(expression)) { + registerError(expression.getOperationToken(), + GroovyInspectionBundle.message("unused.0", expression.getOperationToken().getText()), LocalQuickFix.EMPTY_ARRAY, + ProblemHighlightType.LIKE_UNUSED_SYMBOL); + } + } + } + + private static class RemoveIncOrDecFix implements LocalQuickFix { + private final String myMessage; + + public RemoveIncOrDecFix(GrUnaryExpression expression) { + myMessage = GroovyInspectionBundle.message("remove.0", expression.getOperationToken().getText()); + } + + @NotNull + @Override + public String getName() { + return myMessage; + } + + @NotNull + @Override + public String getFamilyName() { + return myMessage; + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + GrUnaryExpression expr = findUnaryExpression(descriptor); + if (expr == null) return; + + expr.replaceWithExpression(expr.getOperand(), true); + } + } + + private static class ReplacePostfixIncWithPrefixFix implements LocalQuickFix { + private final String myMessage; + + public ReplacePostfixIncWithPrefixFix(GrUnaryExpression expression) { + myMessage = GroovyInspectionBundle.message("replace.postfix.0.with.prefix.0", expression.getOperationToken().getText()); + } + + @NotNull + @Override + public String getName() { + return myMessage; + } + + @NotNull + @Override + public String getFamilyName() { + return myMessage; + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + GrUnaryExpression expr = findUnaryExpression(descriptor); + if (expr == null) return; + + GrExpression prefix = GroovyPsiElementFactory.getInstance(project) + .createExpressionFromText(expr.getOperationToken().getText() + expr.getOperand().getText()); + + expr.replaceWithExpression(prefix, true); + } + } + + private static class ReplaceIncDecWithBinary implements LocalQuickFix { + private final String myMessage; + + public ReplaceIncDecWithBinary(GrUnaryExpression expression) { + String opToken = expression.getOperationToken().getText(); + myMessage = GroovyInspectionBundle.message("replace.0.with.1", opToken, opToken.substring(0, 1)); + } + + @NotNull + @Override + public String getName() { + return myMessage; + } + + @NotNull + @Override + public String getFamilyName() { + return myMessage; + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + GrUnaryExpression expr = findUnaryExpression(descriptor); + GrExpression newExpr = GroovyPsiElementFactory.getInstance(project) + .createExpressionFromText(expr.getOperand().getText() + expr.getOperationToken().getText().substring(0, 1) + "1"); + expr.replaceWithExpression(newExpr, true); + } + } + } + + @Nullable + private static GrUnaryExpression findUnaryExpression(ProblemDescriptor descriptor) { + GrUnaryExpression expr; + PsiElement element = descriptor.getPsiElement(); + if (element == null) return null; + PsiElement parent = element.getParent(); + IElementType opType = element.getNode().getElementType(); + if (opType != GroovyTokenTypes.mINC && opType != GroovyTokenTypes.mDEC) return null; + if (!(parent instanceof GrUnaryExpression)) return null; + expr = (GrUnaryExpression)parent; + return expr; + } +} + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java index 4103c4f5ddc8..84ce78bb2550 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java @@ -53,7 +53,6 @@ import org.jetbrains.plugins.groovy.lang.psi.dataFlow.DFAEngine; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.DfaInstance; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.Semilattice; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; -import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; import java.util.*; @@ -673,7 +672,7 @@ public class ControlFlowUtils { } public static List findAccess(GrVariable local, final PsiElement place, boolean ahead, boolean writeAccessOnly) { - LOG.assertTrue(GroovyRefactoringUtil.isLocalVariable(local), local.getClass()); + LOG.assertTrue(!(local instanceof GrField), local.getClass()); final GrControlFlowOwner owner = findControlFlowOwner(local); assert owner != null; diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy index d4f6fe10a871..6a241766c841 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy @@ -37,6 +37,7 @@ import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilit import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyResultOfAssignmentUsedInspection import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyUncheckedAssignmentOfMemberOfRawTypeInspection import org.jetbrains.plugins.groovy.codeInspection.confusing.ClashingGettersInspection +import org.jetbrains.plugins.groovy.codeInspection.confusing.GrUnusedIncDecInspection import org.jetbrains.plugins.groovy.codeInspection.confusing.GroovyOctalIntegerInspection import org.jetbrains.plugins.groovy.codeInspection.confusing.GroovyResultOfIncrementOrDecrementUsedInspection import org.jetbrains.plugins.groovy.codeInspection.control.GroovyTrivialConditionalInspection @@ -248,8 +249,8 @@ class A { public void testByteArrayArgument() throws Exception {doTest(new GroovyAssignabilityCheckInspection());} public void testForLoopWithNestedEndlessLoop() throws Exception {doTest(new UnassignedVariableAccessInspection());} - public void testPrefixIncrementCfa() throws Exception {doTest(new UnusedDefInspection());} - public void testIfIncrementElseReturn() throws Exception {doTest(new UnusedDefInspection()); } + public void testPrefixIncrementCfa() throws Exception {doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection());} + public void testIfIncrementElseReturn() throws Exception {doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection()); } public void testArrayLikeAccess() throws Exception {doTest();} diff --git a/plugins/groovy/testdata/highlighting/IfIncrementElseReturn.groovy b/plugins/groovy/testdata/highlighting/IfIncrementElseReturn.groovy index 04e1d86bc2e5..3eb7602a44a8 100644 --- a/plugins/groovy/testdata/highlighting/IfIncrementElseReturn.groovy +++ b/plugins/groovy/testdata/highlighting/IfIncrementElseReturn.groovy @@ -1,7 +1,7 @@ int numPermutationsPrinted = 1; for ( int pos_right = 2; pos_right <= n; pos_right++ ) { - if (numPermutationsPrinted++ < 30) + if (numPermutationsPrinted++ < 30) { println "a" } diff --git a/plugins/groovy/testdata/highlighting/PrefixIncrementCfa.groovy b/plugins/groovy/testdata/highlighting/PrefixIncrementCfa.groovy index 711bb7b8c062..e886f8664bdf 100644 --- a/plugins/groovy/testdata/highlighting/PrefixIncrementCfa.groovy +++ b/plugins/groovy/testdata/highlighting/PrefixIncrementCfa.groovy @@ -1,7 +1,7 @@ int idx idx = 2 idx = 3 -if (++idx == 8) { //Assignment is used here +if (++idx == 8) { idx = 33 } print idx \ No newline at end of file From 186cd45d86b5c073733c954f903cf268c6bf11a3 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Tue, 20 Mar 2012 10:42:02 +0400 Subject: [PATCH 040/106] 'dump groovy control flow' prints text of control flow owner --- .../plugins/groovy/actions/DumpGroovyControlFlowAction.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/DumpGroovyControlFlowAction.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/DumpGroovyControlFlowAction.java index 856b586a76c6..46f6694f41fd 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/DumpGroovyControlFlowAction.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/DumpGroovyControlFlowAction.java @@ -82,6 +82,7 @@ public class DumpGroovyControlFlowAction extends AnAction implements DumbAware { } private static void passInner(GrControlFlowOwner owner) { + System.out.println(owner.getText()); System.out.println(ControlFlowUtils.dumpControlFlow(owner.getControlFlow())); } } From bdee83fec856a8c6e1b1def85e1750d8a3f788f0 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Tue, 20 Mar 2012 10:50:02 +0400 Subject: [PATCH 041/106] more demonstrative constructor for ReadWriteVariableInstruction --- .../ReadWriteVariableInstruction.java | 7 ++++-- .../controlFlow/impl/ControlFlowBuilder.java | 24 +++++++++++-------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/ReadWriteVariableInstruction.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/ReadWriteVariableInstruction.java index 247cdd929346..e68eddd8fa56 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/ReadWriteVariableInstruction.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/ReadWriteVariableInstruction.java @@ -23,13 +23,16 @@ import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.InstructionImpl; * @author ven */ public class ReadWriteVariableInstruction extends InstructionImpl { + public static final int WRITE = -1; + public static final int READ = 1; + private final boolean myIsWrite; private final String myName; - public ReadWriteVariableInstruction(@NotNull String varName, PsiElement element, int num, boolean isWrite) { + public ReadWriteVariableInstruction(@NotNull String varName, PsiElement element, int num, int accessType) { super(element, num); myName = varName; - myIsWrite = isWrite; + myIsWrite = accessType == WRITE; } @NotNull public String getVariableName() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java index 16b9c5ea7317..1b5caea2116b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java @@ -51,6 +51,9 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import java.util.*; +import static org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction.READ; +import static org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction.WRITE; + /** * @author ven */ @@ -107,7 +110,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { final PsiElement lbrace = block.getLBrace(); if (lbrace != null && parent instanceof GrMethod) { for (GrParameter parameter : ((GrMethod)parent).getParameters()) { - addNode(new ReadWriteVariableInstruction(parameter.getName(), parameter, myInstructionNumber++, true)); + addNode(new ReadWriteVariableInstruction(parameter.getName(), parameter, myInstructionNumber++, WRITE)); } } super.visitOpenBlock(block); @@ -185,7 +188,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { private void buildFlowForClosure(final GrClosableBlock closure) { for (GrParameter parameter : closure.getAllParameters()) { - addNode(new ReadWriteVariableInstruction(parameter.getName(), parameter, myInstructionNumber++, true)); + addNode(new ReadWriteVariableInstruction(parameter.getName(), parameter, myInstructionNumber++, WRITE)); } final Set names = new LinkedHashSet(); @@ -207,7 +210,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { names.add("owner"); for (String name : names) { - addNode(new ReadWriteVariableInstruction(name, closure.getLBrace(), myInstructionNumber++, true)); + addNode(new ReadWriteVariableInstruction(name, closure.getLBrace(), myInstructionNumber++, WRITE)); } PsiElement child = closure.getFirstChild(); @@ -364,7 +367,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { if (lValue instanceof GrReferenceExpression) { String referenceName = ((GrReferenceExpression)lValue).getReferenceName(); if (referenceName != null) { - ReadWriteVariableInstruction instruction = new ReadWriteVariableInstruction(referenceName, lValue, myInstructionNumber++, false); + ReadWriteVariableInstruction instruction = new ReadWriteVariableInstruction(referenceName, lValue, myInstructionNumber++, READ); addNode(instruction); checkPending(instruction); } @@ -413,13 +416,14 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { if (name == null) return; if (ControlFlowUtils.isIncOrDecOperand(refExpr) && !myAssertionsOnly) { - final InstructionImpl i = new ReadWriteVariableInstruction(name, refExpr, myInstructionNumber++, false); + final InstructionImpl i = new ReadWriteVariableInstruction(name, refExpr, myInstructionNumber++, READ); addNode(i); - addNode(new ReadWriteVariableInstruction(name, refExpr, myInstructionNumber++, true)); + addNode(new ReadWriteVariableInstruction(name, refExpr, myInstructionNumber++, WRITE)); checkPending(i); } else { - final InstructionImpl i = new ReadWriteVariableInstruction(name, refExpr, myInstructionNumber++, !myAssertionsOnly && PsiUtil.isLValue(refExpr)); + boolean isWrite = !myAssertionsOnly && PsiUtil.isLValue(refExpr); + final InstructionImpl i = new ReadWriteVariableInstruction(name, refExpr, myInstructionNumber++, isWrite ? WRITE : READ); addNode(i); checkPending(i); } @@ -560,7 +564,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { GrVariable variable = clause.getDeclaredVariable(); if (variable != null) { ReadWriteVariableInstruction writeInst = - new ReadWriteVariableInstruction(variable.getName(), variable, myInstructionNumber++, true); + new ReadWriteVariableInstruction(variable.getName(), variable, myInstructionNumber++, WRITE); checkPending(writeInst); addNode(writeInst); } @@ -769,7 +773,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { final GrParameter parameter = catchClauses[i].getParameter(); if (parameter != null) { - addNode(new ReadWriteVariableInstruction(parameter.getName(), parameter, myInstructionNumber++, true)); + addNode(new ReadWriteVariableInstruction(parameter.getName(), parameter, myInstructionNumber++, WRITE)); } catchClauses[i].accept(this); catches[i] = myHead; @@ -874,7 +878,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { super.visitVariable(variable); if (variable.getInitializerGroovy() != null || variable.getParent() instanceof GrTupleDeclaration && ((GrTupleDeclaration)variable.getParent()).getInitializerGroovy() != null) { - ReadWriteVariableInstruction writeInst = new ReadWriteVariableInstruction(variable.getName(), variable, myInstructionNumber++, true); + ReadWriteVariableInstruction writeInst = new ReadWriteVariableInstruction(variable.getName(), variable, myInstructionNumber++, WRITE); checkPending(writeInst); addNode(writeInst); } From 4dc61f8ec4f9c8956320032894dda97cd4592268 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Tue, 20 Mar 2012 12:09:09 +0400 Subject: [PATCH 042/106] correct GrUnusedIncDecInpection --- .../confusing/GrUnusedIncDecInspection.java | 26 ++++++++++++++++++- .../utils/ControlFlowUtils.java | 26 ++++++++++++------- .../groovy/lang/GroovyHighlightingTest.groovy | 24 ++++++++++------- .../highlighting/IfIncrementElseReturn.groovy | 2 +- .../testdata/highlighting/UnusedInc.groovy | 7 +++++ 5 files changed, 63 insertions(+), 22 deletions(-) create mode 100644 plugins/groovy/testdata/highlighting/UnusedInc.groovy diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrUnusedIncDecInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrUnusedIncDecInspection.java index 8f8ec88a5cec..fadb994f0ec0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrUnusedIncDecInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrUnusedIncDecInspection.java @@ -18,6 +18,7 @@ package org.jetbrains.plugins.groovy.codeInspection.confusing; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; @@ -30,21 +31,25 @@ import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor; import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle; import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; +import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnaryExpression; +import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; +import java.util.Iterator; import java.util.List; /** * @author Max Medvedev */ public class GrUnusedIncDecInspection extends BaseInspection { + private static final Logger LOG = Logger.getInstance(GrUnusedIncDecInspection.class); @Override protected BaseInspectionVisitor buildVisitor() { return new GrUnusedIncDecInspectionVisitor(); @@ -87,7 +92,26 @@ public class GrUnusedIncDecInspection extends BaseInspection { PsiElement resolved = ((GrReferenceExpression)operand).resolve(); if (!(resolved instanceof GrVariable) || resolved instanceof GrField) return; - List accesses = ControlFlowUtils.findAccess((GrVariable)resolved, expression.getOperand(), true, false); + final GrControlFlowOwner owner = ControlFlowUtils.findControlFlowOwner(expression); + assert owner != null; + GrControlFlowOwner ownerOfDeclaration = ControlFlowUtils.findControlFlowOwner(resolved); + if (ownerOfDeclaration != owner) return; + + final Instruction cur = ControlFlowUtils.findInstruction(operand, owner.getControlFlow()); + + if (cur == null) { + LOG.error("no instruction found in flow." + "operand: " + operand.getText() + " cfo: " + owner.getText()); + } + + //get write access for inc or dec + Iterable successors = cur.allSuccessors(); + Iterator iterator = successors.iterator(); + LOG.assertTrue(iterator.hasNext()); + Instruction writeAccess = iterator.next(); + LOG.assertTrue(!iterator.hasNext()); + + List accesses = ControlFlowUtils.findAccess((GrVariable)resolved, true, false, writeAccess); + boolean allAreWrite = true; for (ReadWriteVariableInstruction access : accesses) { if (!access.isWrite()) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java index 84ce78bb2550..9acf0f2512e3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java @@ -679,15 +679,21 @@ public class ControlFlowUtils { final Instruction cur = findInstruction(place, owner.getControlFlow()); - if (cur == null) throw new IllegalArgumentException("place is not in the flow"); + if (cur == null) { + throw new IllegalArgumentException("place is not in the flow"); + } + return findAccess(local, ahead, writeAccessOnly, cur); + } + + public static List findAccess(GrVariable local, boolean ahead, boolean writeAccessOnly, Instruction cur) { String name = local.getName(); - + final ArrayList result = new ArrayList(); final HashSet visited = new HashSet(); - + visited.add(cur); - + Queue queue = new ArrayDeque(); for (Instruction i : ahead ? cur.allSuccessors() : cur.allPredecessors()) { @@ -695,11 +701,11 @@ public class ControlFlowUtils { queue.add(i); } } - + while (true) { Instruction instruction = queue.poll(); if (instruction == null) break; - + if (instruction instanceof ReadWriteVariableInstruction) { ReadWriteVariableInstruction rw = (ReadWriteVariableInstruction)instruction; if (name.equals(rw.getVariableName())) { @@ -707,13 +713,13 @@ public class ControlFlowUtils { result.add(rw); continue; } - + if (!writeAccessOnly) { result.add(rw); } } } - + for (Instruction i : ahead ? instruction.allSuccessors() : instruction.allPredecessors()) { if (visited.add(i)) { queue.add(i); @@ -723,9 +729,9 @@ public class ControlFlowUtils { return result; } - + @Nullable - private static Instruction findInstruction(final PsiElement place, Instruction[] controlFlow) { + public static Instruction findInstruction(final PsiElement place, Instruction[] controlFlow) { return ContainerUtil.find(controlFlow, new Condition() { @Override public boolean value(Instruction instruction) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy index 6a241766c841..e0ba3cd80dad 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy @@ -189,10 +189,10 @@ public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase { public void testUnassigned3() throws Exception { doTest(new UnassignedVariableAccessInspection()); } public void testUnassignedTryFinally() throws Exception { doTest(new UnassignedVariableAccessInspection()); } - public void testUnusedVariable() throws Exception { doTest(new UnusedDefInspection()); } - public void testDefinitionUsedInClosure() throws Exception { doTest(new UnusedDefInspection()); } - public void testDefinitionUsedInClosure2() throws Exception { doTest(new UnusedDefInspection()); } - public void testDefinitionUsedInSwitchCase() throws Exception { doTest(new UnusedDefInspection()); } + public void testUnusedVariable() throws Exception { doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection()); } + public void testDefinitionUsedInClosure() throws Exception { doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection()); } + public void testDefinitionUsedInClosure2() throws Exception { doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection()); } + public void testDefinitionUsedInSwitchCase() throws Exception { doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection()); } public void testDuplicateInnerClass() throws Throwable{doTest();} public void testThisInStaticContext() throws Throwable {doTest();} @@ -316,7 +316,7 @@ class A { public void testBuiltInTypeInstantiation() {doTest();} - public void testSwitchControlFlow() {doTest(new UnusedDefInspection(), new GroovyResultOfAssignmentUsedInspection());} + public void testSwitchControlFlow() {doTest(new UnusedDefInspection(), new GroovyResultOfAssignmentUsedInspection(), new GrUnusedIncDecInspection());} public void testRawTypeInAssignment() {doTest(new GroovyAssignabilityCheckInspection());} @@ -326,7 +326,7 @@ class A { IdeaTestUtil.assertTiming("", 10000, 1, new Runnable() { @Override public void run() { - doTest(new GroovyAssignabilityCheckInspection(), new UnusedDefInspection()); + doTest(new GroovyAssignabilityCheckInspection(), new UnusedDefInspection(), new GrUnusedIncDecInspection()); } }); } @@ -398,7 +398,7 @@ class A { doTest(new GroovyUnresolvedAccessInspection(), new GroovyUntypedAccessInspection()); } - public void testUsageInInjection() { doTest(new UnusedDefInspection()); } + public void testUsageInInjection() { doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection()); } public void testDuplicatedNamedArgs() {doTest();} @@ -420,15 +420,19 @@ class A { } public void testUnusedDefsForArgs() { - doTest(new UnusedDefInspection()); + doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection()); } public void testUsedDefBeforeTry1() { - doTest(new UnusedDefInspection()); + doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection()); } public void testUsedDefBeforeTry2() { - doTest(new UnusedDefInspection()); + doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection()); + } + + public void testUnusedInc() { + doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection()) } public void testStringAssignableToChar() { diff --git a/plugins/groovy/testdata/highlighting/IfIncrementElseReturn.groovy b/plugins/groovy/testdata/highlighting/IfIncrementElseReturn.groovy index 3eb7602a44a8..04e1d86bc2e5 100644 --- a/plugins/groovy/testdata/highlighting/IfIncrementElseReturn.groovy +++ b/plugins/groovy/testdata/highlighting/IfIncrementElseReturn.groovy @@ -1,7 +1,7 @@ int numPermutationsPrinted = 1; for ( int pos_right = 2; pos_right <= n; pos_right++ ) { - if (numPermutationsPrinted++ < 30) + if (numPermutationsPrinted++ < 30) { println "a" } diff --git a/plugins/groovy/testdata/highlighting/UnusedInc.groovy b/plugins/groovy/testdata/highlighting/UnusedInc.groovy new file mode 100644 index 000000000000..3483ac2f7b68 --- /dev/null +++ b/plugins/groovy/testdata/highlighting/UnusedInc.groovy @@ -0,0 +1,7 @@ +def a = 4 +print (++a) +print (a++) + +def b = 3 +b++ +b = 3 \ No newline at end of file From c348738fd0fd306cd24f69247ac34e149c9c6912 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Tue, 20 Mar 2012 13:36:20 +0400 Subject: [PATCH 043/106] refactor UnusedDefInspection --- .../unusedDef/UnusedDefInspection.java | 72 +++++++++---------- .../utils/ControlFlowUtils.java | 4 +- 2 files changed, 37 insertions(+), 39 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java index cbb719736507..da1bd028bac2 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java @@ -25,7 +25,6 @@ import com.intellij.psi.impl.DebugUtil; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.Processor; import gnu.trove.TIntHashSet; import gnu.trove.TIntObjectHashMap; @@ -34,29 +33,25 @@ import gnu.trove.TObjectProcedure; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle; import org.jetbrains.plugins.groovy.codeInspection.GroovyLocalInspectionBase; +import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner; -import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrClassInitializer; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnaryExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.DFAEngine; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.ReachingDefinitionsDfaInstance; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.ReachingDefinitionsSemilattice; -import java.util.ArrayList; +import java.util.List; /** & @author ven @@ -88,7 +83,7 @@ public class UnusedDefInspection extends GroovyLocalInspectionBase { final ReachingDefinitionsDfaInstance dfaInstance = new ReachingDefinitionsDfaInstance(flow); final ReachingDefinitionsSemilattice lattice = new ReachingDefinitionsSemilattice(); final DFAEngine> engine = new DFAEngine>(flow, dfaInstance, lattice); - final ArrayList> dfaResult = engine.performDFA(); + final List> dfaResult = engine.performDFA(); final TIntHashSet unusedDefs = new TIntHashSet(); for (Instruction instruction : flow) { if (instruction instanceof ReadWriteVariableInstruction && ((ReadWriteVariableInstruction) instruction).isWrite()) { @@ -126,21 +121,8 @@ public class UnusedDefInspection extends GroovyLocalInspectionBase { final ReadWriteVariableInstruction instruction = (ReadWriteVariableInstruction)flow[num]; final PsiElement element = instruction.getElement(); if (element == null) return true; - PsiElement toHighlight = null; if (isLocalAssignment(element) && isUsedInTopLevelFlowOnly(element) && !isIncOrDec(element)) { - if (element instanceof GrReferenceExpression) { - PsiElement parent = element.getParent(); - if (parent instanceof GrAssignmentExpression) { - toHighlight = ((GrAssignmentExpression)parent).getLValue(); - } - if (parent instanceof GrUnaryExpression && ((GrUnaryExpression)parent).isPostfix()) { - toHighlight = parent; - } - } - else if (element instanceof GrVariable) { - toHighlight = ((GrVariable)element).getNameIdentifierGroovy(); - } - if (toHighlight == null) toHighlight = element; + PsiElement toHighlight = getHighlightElement(element); problemsHolder.registerProblem(toHighlight, GroovyInspectionBundle.message("unused.assignment.tooltip"), ProblemHighlightType.LIKE_UNUSED_SYMBOL); } @@ -149,6 +131,24 @@ public class UnusedDefInspection extends GroovyLocalInspectionBase { }); } + private static PsiElement getHighlightElement(PsiElement element) { + PsiElement toHighlight = null; + if (element instanceof GrReferenceExpression) { + PsiElement parent = element.getParent(); + if (parent instanceof GrAssignmentExpression) { + toHighlight = ((GrAssignmentExpression)parent).getLValue(); + } + if (parent instanceof GrUnaryExpression && ((GrUnaryExpression)parent).isPostfix()) { + toHighlight = parent; + } + } + else if (element instanceof GrVariable) { + toHighlight = ((GrVariable)element).getNameIdentifierGroovy(); + } + if (toHighlight == null) toHighlight = element; + return toHighlight; + } + private static boolean isIncOrDec(PsiElement element) { PsiElement parent = element.getParent(); if (!(parent instanceof GrUnaryExpression)) return false; @@ -160,22 +160,23 @@ public class UnusedDefInspection extends GroovyLocalInspectionBase { private static boolean isUsedInTopLevelFlowOnly(PsiElement element) { GrVariable var = null; if (element instanceof GrVariable) { - var = (GrVariable) element; - } else if (element instanceof GrReferenceExpression) { - final PsiElement resolved = ((GrReferenceExpression) element).resolve(); - if (resolved instanceof GrVariable) var = (GrVariable) resolved; + var = (GrVariable)element; + } + else if (element instanceof GrReferenceExpression) { + final PsiElement resolved = ((GrReferenceExpression)element).resolve(); + if (resolved instanceof GrVariable) var = (GrVariable)resolved; } if (var != null) { - final GroovyPsiElement scope = getScope(var); + final GroovyPsiElement scope = ControlFlowUtils.findControlFlowOwner(var); if (scope == null) { PsiFile file = var.getContainingFile(); - LOG.error(file == null ? "no file??? var of type"+ var.getClass().getCanonicalName() : DebugUtil.psiToString(file, true, false)); + LOG.error(file == null ? "no file??? var of type" + var.getClass().getCanonicalName() : DebugUtil.psiToString(file, true, false)); } return ReferencesSearch.search(var, new LocalSearchScope(scope)).forEach(new Processor() { public boolean process(PsiReference ref) { - return getScope(ref.getElement()) == scope; + return ControlFlowUtils.findControlFlowOwner(ref.getElement()) == scope; } }); } @@ -183,17 +184,14 @@ public class UnusedDefInspection extends GroovyLocalInspectionBase { return true; } - @Nullable - private static GroovyPsiElement getScope(PsiElement var) { - return PsiTreeUtil.getContextOfType(var, GrClosableBlock.class, GrMethod.class, GrClassInitializer.class, GroovyFileBase.class); - } private static boolean isLocalAssignment(PsiElement element) { if (element instanceof GrVariable) { - return isLocalVariable((GrVariable) element, false); - } else if (element instanceof GrReferenceExpression) { - final PsiElement resolved = ((GrReferenceExpression) element).resolve(); - return resolved instanceof GrVariable && isLocalVariable((GrVariable) resolved, true); + return isLocalVariable((GrVariable)element, false); + } + else if (element instanceof GrReferenceExpression) { + final PsiElement resolved = ((GrReferenceExpression)element).resolve(); + return resolved instanceof GrVariable && isLocalVariable((GrVariable)resolved, true); } return false; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java index 9acf0f2512e3..18fb9b913a0c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java @@ -647,10 +647,10 @@ public class ControlFlowUtils { @Nullable public static GrControlFlowOwner findControlFlowOwner(PsiElement place) { if (place instanceof GrCodeBlock) { - place = place.getParent(); + place = place.getContext(); } while (true) { - place = place.getParent(); + place = place.getContext(); if (place == null) return null; if (place instanceof GrClosableBlock) return (GrClosableBlock)place; if (place instanceof GrMethod) return ((GrMethod)place).getBlock(); From 757529b442661697fd2c6d79799b4c7f35026b55 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Tue, 20 Mar 2012 16:41:10 +0400 Subject: [PATCH 044/106] refactor UnusedDefInspection --- .../controlFlow/impl/ControlFlowBuilder.java | 81 +++++++++++++++++-- .../groovy/lang/resolve/ResolveUtil.java | 11 ++- .../lang/controlFlow/ControlFlowTest.java | 2 + .../extract/method/ExtractMethodTest.groovy | 3 + .../groovy/controlFlow/anonymous.test | 17 ++++ .../testdata/groovy/controlFlow/closure.test | 15 ++++ .../argsUsedOnlyInAnonymousClass.test | 19 +++++ .../extractMethod/argsUsedOnlyInClosure.test | 15 ++++ .../refactoring/extractMethod/output1.test | 4 +- 9 files changed, 153 insertions(+), 14 deletions(-) create mode 100644 plugins/groovy/testdata/groovy/controlFlow/anonymous.test create mode 100644 plugins/groovy/testdata/groovy/controlFlow/closure.test create mode 100644 plugins/groovy/testdata/groovy/refactoring/extractMethod/argsUsedOnlyInAnonymousClass.test create mode 100644 plugins/groovy/testdata/groovy/refactoring/extractMethod/argsUsedOnlyInClosure.test diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java index 1b5caea2116b..1fea9d257838 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java @@ -20,6 +20,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.containers.hash.HashSet; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; @@ -244,12 +245,26 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { //do not go inside closures except gstring injections if (closure.getParent() instanceof GrStringInjection) { super.visitClosure(closure); + return; } - else { - //create instruction for closure to use it in inline local refactoring - final InstructionImpl i = new InstructionImpl(closure, myInstructionNumber++); + + Set names = new HashSet(); + + ReadWriteVariableInstruction[] reads = ControlFlowBuilderUtil.getReadsWithoutPriorWrites(closure.getControlFlow()); + for (ReadWriteVariableInstruction read : reads) { + names.add(read.getVariableName()); + } + + for (String name : names) { + ReadWriteVariableInstruction i = new ReadWriteVariableInstruction(name, closure, myInstructionNumber++, READ); addNode(i); + checkPending(i); } + + + InstructionImpl i = new InstructionImpl(closure, myInstructionNumber++); + addNode(i); + checkPending(i); } public void visitBreakStatement(GrBreakStatement breakStatement) { @@ -868,10 +883,64 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { public void visitMethod(GrMethod method) { } - public void visitTypeDefinition(GrTypeDefinition typeDefinition) { - if (typeDefinition instanceof GrAnonymousClassDefinition) { - super.visitTypeDefinition(typeDefinition); + @Override + public void visitClassInitializer(GrClassInitializer initializer) { + } + + public void visitTypeDefinition(final GrTypeDefinition typeDefinition) { + if (!(typeDefinition instanceof GrAnonymousClassDefinition)) return; + + final Set vars = new HashSet(); + typeDefinition.acceptChildren(new GroovyRecursiveElementVisitor() { + private void collectVars(Instruction[] flow) { + ReadWriteVariableInstruction[] reads = ControlFlowBuilderUtil.getReadsWithoutPriorWrites(flow); + for (ReadWriteVariableInstruction instruction : reads) { + vars.add(instruction.getVariableName()); + } + } + + @Override + public void visitField(GrField field) { + GrExpression initializer = field.getInitializerGroovy(); + if (initializer != null) { + Instruction[] flow = new ControlFlowBuilder(field.getProject()).buildControlFlow(initializer); + collectVars(flow); + } + } + + @Override + public void visitMethod(GrMethod method) { + GrOpenBlock block = method.getBlock(); + if (block != null) { + collectVars(block.getControlFlow()); + } + } + + @Override + public void visitClassInitializer(GrClassInitializer initializer) { + GrOpenBlock block = initializer.getBlock(); + collectVars(block.getControlFlow()); + } + + @Override + public void visitTypeDefinition(GrTypeDefinition typeDefinition) { + typeDefinition.acceptChildren(this); + } + }); + + PsiField[] fields = typeDefinition.getAllFields(); + for (PsiField field : fields) { + vars.remove(field.getName()); } + + for (String var : vars) { + ReadWriteVariableInstruction i = new ReadWriteVariableInstruction(var, typeDefinition, myInstructionNumber++, READ); + addNode(i); + checkPending(i); + } + InstructionImpl i = new InstructionImpl(typeDefinition, myInstructionNumber++); + addNode(i); + checkPending(i); } public void visitVariable(GrVariable variable) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java index 239574da80c1..ce38cea5b7cd 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java @@ -78,9 +78,9 @@ public class ResolveUtil { } /** - * + * * @param place - place to start tree walk up - * @param processor + * @param processor * @param processNonCodeMethods - this parameter tells us if we need non code members. But non code members are started to process only after we walk up any code block or script * @return */ @@ -95,10 +95,6 @@ public class ResolveUtil { while (run != null) { if (!run.processDeclarations(processor, ResolveState.initial(), lastParent, place)) return false; - if (run instanceof GrClosableBlock) { - PsiClass superClass = getLiteralSuperClass((GrClosableBlock)run); - if (superClass != null && !superClass.processDeclarations(processor, ResolveState.initial(), null, place)) return false; - } if (processNonCodeMethods) { if (!doProcessNonCodeMembers) { if (run instanceof GrCodeBlock) doProcessNonCodeMembers = true; @@ -115,6 +111,9 @@ public class ResolveUtil { } } else if (run instanceof GrClosableBlock) { + PsiClass superClass = getLiteralSuperClass((GrClosableBlock)run); + if (superClass != null && !superClass.processDeclarations(processor, ResolveState.initial(), null, place)) return false; + if (!GdkMethodUtil.categoryIteration((GrClosableBlock)run, processor)) return false; if (!GdkMethodUtil.withIteration((GrClosableBlock)run, processor, place)) return false; } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java index a6790d48e8d5..ff34da2ea32e 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.java @@ -55,6 +55,8 @@ public class ControlFlowTest extends LightCodeInsightFixtureTestCase { public void testIfInstanceofElse() throws Throwable { doTest(); } public void testReturnMapFromClosure() {doTest();} public void testSwitchInTryWithThrows() {doTest();} + public void testClosure() {doTest();} + public void testAnonymous() {doTest();} public void doTest() { final List input = TestUtils.readInput(getTestDataPath() + getTestName(true) + ".test"); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.groovy index 04fee16b1f12..729e0d436827 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.groovy @@ -114,4 +114,7 @@ public class ExtractMethodTest extends LightGroovyTestCase { public void testParamChangedInsideExtractedMethod() {doTest();} public void testTerribleAppStatement() {doTest()} + + public void testArgsUsedOnlyInClosure() {doTest()} + public void testArgsUsedOnlyInAnonymousClass() {doTest()} } \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/controlFlow/anonymous.test b/plugins/groovy/testdata/groovy/controlFlow/anonymous.test new file mode 100644 index 000000000000..79b93ac0c3fd --- /dev/null +++ b/plugins/groovy/testdata/groovy/controlFlow/anonymous.test @@ -0,0 +1,17 @@ +int x = 0 +[1, 2, 3].each (new Closure(this, this) { + void call() { + x++ + } +}) + +print x +----- +0(1) element: null +1(2) WRITE x +2(3) READ x +3(4) element: Anonymous class +4(5) READ print +5(6) READ x +6(7) element: Call expression MAYBE_RETURN +7() element: null \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/controlFlow/closure.test b/plugins/groovy/testdata/groovy/controlFlow/closure.test new file mode 100644 index 000000000000..ed94fc177ee3 --- /dev/null +++ b/plugins/groovy/testdata/groovy/controlFlow/closure.test @@ -0,0 +1,15 @@ +int x = 0 +[1, 2, 3].each { + x++ +} + +print x +----- +0(1) element: null +1(2) WRITE x +2(3) READ x +3(4) element: Closable block +4(5) READ print +5(6) READ x +6(7) element: Call expression MAYBE_RETURN +7() element: null \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/argsUsedOnlyInAnonymousClass.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/argsUsedOnlyInAnonymousClass.test new file mode 100644 index 000000000000..0857daf5c4db --- /dev/null +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/argsUsedOnlyInAnonymousClass.test @@ -0,0 +1,19 @@ +def foo(b, c) { + [].each (new Closure(this, this) { + void call() { + b.plus(c) + } + }) +} +----- +def foo(b, c) { + testMethod(b, c) +} + +private testMethod(b, c) { + [].each(new Closure(this, this) { + void call() { + b.plus(c) + } + }) +} \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/argsUsedOnlyInClosure.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/argsUsedOnlyInClosure.test new file mode 100644 index 000000000000..7ff5598dbdff --- /dev/null +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/argsUsedOnlyInClosure.test @@ -0,0 +1,15 @@ +def foo(b, c) { + [].each { + b.plus(c) + } +} +----- +def foo(b, c) { + testMethod(b, c) +} + +private testMethod(b, c) { + [].each { + b.plus(c) + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/output1.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/output1.test index d77f380f9410..e1738a81d52c 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/output1.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/output1.test @@ -12,7 +12,7 @@ class S { ----- class S { def r() { - Closure sin = testMethod() + Closure sin = testMethod() 10.times { @@ -21,7 +21,7 @@ class S { } - private Closure testMethod() { + private Closure testMethod() { Closure sin = {x -> Math.sin(x)} return sin } From 976c6ca6248ccb6cbb60042bd0e703dbef8569e7 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Mar 2012 13:49:24 +0100 Subject: [PATCH 045/106] EA-33002 - NPE: ModuleAttachProcessor.attachToProject --- .../intellij/platform/ModuleAttachProcessor.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/platform/ModuleAttachProcessor.java b/platform/lang-impl/src/com/intellij/platform/ModuleAttachProcessor.java index 90bd69e50224..e1768278e035 100644 --- a/platform/lang-impl/src/com/intellij/platform/ModuleAttachProcessor.java +++ b/platform/lang-impl/src/com/intellij/platform/ModuleAttachProcessor.java @@ -70,12 +70,15 @@ public class ModuleAttachProcessor extends ProjectAttachProcessor { token.finish(); } } - for(String file: projectDir.list()) { - if (FileUtil.getExtension(file).equals("iml")) { - VirtualFile imlFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(projectDir, file)); - if (imlFile != null) { - attachModule(project, imlFile, callback); - return true; + final String[] files = projectDir.list(); + if (files != null) { + for(String file: files) { + if (FileUtil.getExtension(file).equals("iml")) { + VirtualFile imlFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(projectDir, file)); + if (imlFile != null) { + attachModule(project, imlFile, callback); + return true; + } } } } From 9f3d0e8ac113452da2ef37ba8122f7a67ea63596 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 20 Mar 2012 16:52:26 +0400 Subject: [PATCH 046/106] GitInit: don't show the error if executable is not valid. It is notified separately from GitHandler.start(). --- plugins/git4idea/src/git4idea/actions/GitInit.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/git4idea/src/git4idea/actions/GitInit.java b/plugins/git4idea/src/git4idea/actions/GitInit.java index 685cb743a30f..43aa23976177 100644 --- a/plugins/git4idea/src/git4idea/actions/GitInit.java +++ b/plugins/git4idea/src/git4idea/actions/GitInit.java @@ -80,11 +80,13 @@ public class GitInit extends DumbAwareAction { } Git git = ServiceManager.getService(Git.class); - + GitVcs vcs = GitVcs.getInstance(project); GitCommandResult result = git.init(project, root); if (!result.success()) { - GitUIUtil.notify(GitVcs.IMPORTANT_ERROR_NOTIFICATION, project, "Git init failed", result.getErrorOutputAsHtmlString(), - NotificationType.ERROR, null); + if (vcs != null && vcs.getExecutableValidator().isExecutableValid()) { + GitUIUtil.notify(GitVcs.IMPORTANT_ERROR_NOTIFICATION, project, "Git init failed", result.getErrorOutputAsHtmlString(), + NotificationType.ERROR, null); + } return; } From 083dbf648455a8f943fce4246c9f816ef9e671ba Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 20 Mar 2012 16:57:47 +0400 Subject: [PATCH 047/106] IDEA-81997 IDEA does not recognize taglibs defined in dependent module additional search scope based on artifacts (cherry picked from commit 2ee640a) --- .../xml/index/IndexedRelevantResource.java | 15 +++++---------- .../com/intellij/xml/index/ResourceRelevance.java | 7 +++++-- .../com/intellij/xml/index/XmlNamespaceIndex.java | 3 ++- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/xml/impl/src/com/intellij/xml/index/IndexedRelevantResource.java b/xml/impl/src/com/intellij/xml/index/IndexedRelevantResource.java index 17ba1da98290..075b32d8bdf2 100644 --- a/xml/impl/src/com/intellij/xml/index/IndexedRelevantResource.java +++ b/xml/impl/src/com/intellij/xml/index/IndexedRelevantResource.java @@ -21,7 +21,6 @@ import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.util.Function; import com.intellij.util.NullableFunction; import com.intellij.util.indexing.AdditionalIndexedRootsScope; import com.intellij.util.indexing.FileBasedIndex; @@ -38,22 +37,17 @@ import java.util.List; */ public class IndexedRelevantResource implements Comparable> { - public static final Function,VirtualFile> MAPPING = new Function, VirtualFile>() { - public VirtualFile fun(IndexedRelevantResource resource) { - return resource.getFile(); - } - }; - public static List> getResources(ID indexId, final K key, @Nullable final Module module, - @NotNull Project project) { + @NotNull Project project, + @Nullable final GlobalSearchScope additionalScope) { final ArrayList> resources = new ArrayList>(); final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); FileBasedIndex.getInstance().processValues(indexId, key, null, new FileBasedIndex.ValueProcessor() { public boolean process(VirtualFile file, V value) { - ResourceRelevance relevance = ResourceRelevance.getRelevance(file, module, fileIndex); + ResourceRelevance relevance = ResourceRelevance.getRelevance(file, module, fileIndex, additionalScope); if (relevance != ResourceRelevance.NONE) { resources.add(new IndexedRelevantResource(file, key, value, relevance)); } @@ -69,7 +63,8 @@ public class IndexedRelevantResource implements Compara ArrayList> all = new ArrayList>(); Collection allKeys = FileBasedIndex.getInstance().getAllKeys(indexId, module.getProject()); for (K key : allKeys) { - List> resources = getResources(indexId, key, module, module.getProject()); + List> resources = getResources(indexId, key, module, module.getProject(), + null); if (!resources.isEmpty()) { if (chooser == null) { all.add(resources.get(0)); diff --git a/xml/impl/src/com/intellij/xml/index/ResourceRelevance.java b/xml/impl/src/com/intellij/xml/index/ResourceRelevance.java index 411ebc65af19..834478dd78bd 100644 --- a/xml/impl/src/com/intellij/xml/index/ResourceRelevance.java +++ b/xml/impl/src/com/intellij/xml/index/ResourceRelevance.java @@ -34,14 +34,17 @@ public enum ResourceRelevance { SOURCE, MAPPED; - public static ResourceRelevance getRelevance(VirtualFile resource, @Nullable Module module, ProjectFileIndex fileIndex) { + public static ResourceRelevance getRelevance(VirtualFile resource, + @Nullable Module module, + ProjectFileIndex fileIndex, + @Nullable GlobalSearchScope additionalScope) { boolean inTest = fileIndex.isInTestSourceContent(resource); if (module != null) { GlobalSearchScope scope = module.getModuleRuntimeScope(inTest); Module resourceModule = fileIndex.getModuleForFile(resource); if (resourceModule != null && (resourceModule == module || scope.isSearchInModuleContent(resourceModule)) || - scope.contains(resource)) { + scope.contains(resource) || (additionalScope != null && additionalScope.contains(resource))) { return inTest || fileIndex.isInSource(resource) ? SOURCE : LIBRARY; } } diff --git a/xml/impl/src/com/intellij/xml/index/XmlNamespaceIndex.java b/xml/impl/src/com/intellij/xml/index/XmlNamespaceIndex.java index 071ea9df83b9..51f584c0ead8 100644 --- a/xml/impl/src/com/intellij/xml/index/XmlNamespaceIndex.java +++ b/xml/impl/src/com/intellij/xml/index/XmlNamespaceIndex.java @@ -45,7 +45,8 @@ public class XmlNamespaceIndex extends XmlIndex { } public static List> getResourcesByNamespace(String namespace, final Project project, Module module) { - List> resources = IndexedRelevantResource.getResources(NAME, namespace, module, project); + List> resources = IndexedRelevantResource.getResources(NAME, namespace, module, project, + null); Collections.sort(resources); return resources; } From 0f6ea234fd1acd67f22df471e4b5ad9df3303d95 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 20 Mar 2012 16:58:01 +0400 Subject: [PATCH 048/106] IDEA-79322 YouTRACK integration stops working if network connection was temporary lost: diagnostics (cherry picked from commit 0a70f8f) --- .../tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java index ab2bba3438e0..a3b5c5e6ab15 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java @@ -735,6 +735,7 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe ContainerUtil.addAll(issues, tasks); } catch (Exception e) { + LOG.warn("Cannot connect to " + repository, e); myBadRepositories.add(repository); if (forceRequest) { notifyAboutConnectionFailure(repository); From 6f1b010496bf47e1438cf236d6960b5c685b57a8 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 20 Mar 2012 16:59:21 +0400 Subject: [PATCH 049/106] toString() (cherry picked from commit 402ee93) --- .../src/com/intellij/xml/util/ColorSampleLookupValue.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xml/impl/src/com/intellij/xml/util/ColorSampleLookupValue.java b/xml/impl/src/com/intellij/xml/util/ColorSampleLookupValue.java index ea5d0e6a52d8..0f564d2bf0ec 100644 --- a/xml/impl/src/com/intellij/xml/util/ColorSampleLookupValue.java +++ b/xml/impl/src/com/intellij/xml/util/ColorSampleLookupValue.java @@ -460,4 +460,9 @@ public class ColorSampleLookupValue implements LookupValueWithUIHint, DeferredUs } return null; } + + @Override + public String toString() { + return myName == null ? myValue : myValue + " " + myName; + } } From cf87dbcbb4de6c71665a48f7703e31cc58bc419d Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 20 Mar 2012 17:00:16 +0400 Subject: [PATCH 050/106] avoid key duplication (cherry picked from commit 5849a15) --- .../intellij/lang/properties/xml/XmlPropertiesFile.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesFile.java b/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesFile.java index 48c21e52d951..ba9f2a9f7424 100644 --- a/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesFile.java +++ b/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesFile.java @@ -31,6 +31,7 @@ import java.util.*; */ public class XmlPropertiesFile implements PropertiesFile { + private static final Key> KEY = Key.create("xml properties file"); private final XmlFile myFile; private final List myProperties = new ArrayList(); private final MultiMap myPropertiesMap = new MultiMap(); @@ -42,7 +43,7 @@ public class XmlPropertiesFile implements PropertiesFile { public static PropertiesFile getPropertiesFile(final XmlFile file) { CachedValuesManager manager = CachedValuesManager.getManager(file.getProject()); - return manager.getCachedValue(file, Key.>create("xml properties file"), + return manager.getCachedValue(file, KEY, new CachedValueProvider() { @Override public Result compute() { @@ -104,13 +105,13 @@ public class XmlPropertiesFile implements PropertiesFile { @NotNull @Override public PsiElement addProperty(@NotNull IProperty property) throws IncorrectOperationException { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } @NotNull @Override public PsiElement addPropertyAfter(@NotNull Property property, @Nullable Property anchor) throws IncorrectOperationException { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } @Override From 652a3d6b7273ae0ab46c126528d8ed058d3d5a5a Mon Sep 17 00:00:00 2001 From: "kirill.safonov" Date: Tue, 20 Mar 2012 17:39:37 +0400 Subject: [PATCH 051/106] Flex build configurations presentation - step 1 --- .../ProjectStructureElementRenderer.java | 10 ++++++++-- .../daemon/ProjectStructureElement.java | 5 +++++ platform/icons/src/actions/checked_16x16.png | Bin 0 -> 259 bytes .../icons/src/actions/checked_16x16_selected.png | Bin 0 -> 262 bytes .../com/intellij/ui/ColoredTreeCellRenderer.java | 8 ++++++-- .../src/com/intellij/ui/HtmlListCellRenderer.java | 9 +++++++++ .../src/com/intellij/ui/SimpleColoredText.java | 11 +++++++++++ 7 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 platform/icons/src/actions/checked_16x16.png create mode 100644 platform/icons/src/actions/checked_16x16_selected.png diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ProjectStructureElementRenderer.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ProjectStructureElementRenderer.java index 06bb5ec7731b..54037ea58236 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ProjectStructureElementRenderer.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ProjectStructureElementRenderer.java @@ -53,8 +53,7 @@ class ProjectStructureElementRenderer extends ColoredTreeCellRenderer { setToolTipText(null); setFont(UIUtil.getTreeFont()); - SimpleTextAttributes textAttributes = - selected && hasFocus ? SimpleTextAttributes.SELECTED_SIMPLE_CELL_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES; + SimpleTextAttributes textAttributes = SimpleTextAttributes.REGULAR_ATTRIBUTES; if (node.isDisplayInBold()) { textAttributes = SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES; } @@ -74,6 +73,13 @@ class ProjectStructureElementRenderer extends ColoredTreeCellRenderer { textAttributes = textAttributes.derive(style, foreground, null, waveColor); setToolTipText(problemsHolder.composeTooltipMessage()); } + + append(displayName, textAttributes); + String description = projectStructureElement.getDescription(); + if (description != null) { + append(" (" + description + ")", SimpleTextAttributes.GRAY_ATTRIBUTES, false); + } + return; } } append(displayName, textAttributes); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureElement.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureElement.java index f9e866962e79..fed82781265d 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureElement.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureElement.java @@ -18,6 +18,11 @@ public abstract class ProjectStructureElement { public abstract String getPresentableName(); + @Nullable + public String getDescription() { + return null; + } + public abstract String getTypeName(); public abstract String getId(); diff --git a/platform/icons/src/actions/checked_16x16.png b/platform/icons/src/actions/checked_16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..d55c1fc133c906ecd2bc7abdf4b73a00e8dd1683 GIT binary patch literal 259 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85p>QL70(Y)*K0-AbW|YuPgf)y_Zq^AohUlv6UZK#A5=V>{x$j?=R7ag#Oek>2rdV&37crzWaRT yMz9R?zN4IzLmxGs-F|G}Sv$kSjO*>|C-J|@7Jd-r-&p~44uhwwpUXO@geCwCqh6i> literal 0 HcmV?d00001 diff --git a/platform/icons/src/actions/checked_16x16_selected.png b/platform/icons/src/actions/checked_16x16_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..2dfa1eda3c128d47ebb667b95770c88316789635 GIT binary patch literal 262 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85p>QL70(Y)*K0-AbW|YuPgfexUz}HLIPz_Kc=?>djt*}Z6V)$s*Y~X`KI?qv>lw?oa;X#|(54gQu&X%Q~loCIBBz BVQv5b literal 0 HcmV?d00001 diff --git a/platform/platform-api/src/com/intellij/ui/ColoredTreeCellRenderer.java b/platform/platform-api/src/com/intellij/ui/ColoredTreeCellRenderer.java index 9a7a047a812b..98757ca2ff8f 100644 --- a/platform/platform-api/src/com/intellij/ui/ColoredTreeCellRenderer.java +++ b/platform/platform-api/src/com/intellij/ui/ColoredTreeCellRenderer.java @@ -56,7 +56,7 @@ public abstract class ColoredTreeCellRenderer extends SimpleColoredComponent imp clear(); mySelected = selected; - myFocused = tree.hasFocus(); + myFocused = isFocused(); // We paint background if and only if tree path is selected and tree has focus. // If path is selected and tree is not focused then we just paint focused border. @@ -104,7 +104,7 @@ public abstract class ColoredTreeCellRenderer extends SimpleColoredComponent imp super.setIconOpaque(false); } else { - super.setOpaque(myOpaque || selected && hasFocus || selected && tree.hasFocus()); // draw selection background even for non-opaque tree + super.setOpaque(myOpaque || selected && hasFocus || selected && isFocused()); // draw selection background even for non-opaque tree } if (tree.getUI() instanceof UIUtil.MacTreeUI) { @@ -121,6 +121,10 @@ public abstract class ColoredTreeCellRenderer extends SimpleColoredComponent imp return this; } + protected boolean isFocused() { + return myTree.hasFocus(); + } + public void setOpaque(boolean isOpaque) { myOpaque = isOpaque; super.setOpaque(isOpaque); diff --git a/platform/platform-api/src/com/intellij/ui/HtmlListCellRenderer.java b/platform/platform-api/src/com/intellij/ui/HtmlListCellRenderer.java index 179e6418c92d..f383b18eb0b6 100644 --- a/platform/platform-api/src/com/intellij/ui/HtmlListCellRenderer.java +++ b/platform/platform-api/src/com/intellij/ui/HtmlListCellRenderer.java @@ -90,6 +90,15 @@ public abstract class HtmlListCellRenderer extends ListCellRendererWrapper } } + public void append(SimpleColoredText text) { + int length = text.getTexts().size(); + for (int i = 0; i < length; i++) { + String fragment = text.getTexts().get(i); + SimpleTextAttributes attributes = text.getAttributes().get(i); + append(fragment, attributes); + } + } + private static void formatStyle(final StringBuilder builder, final SimpleTextAttributes attributes) { final Color fgColor = attributes.getFgColor(); final Color bgColor = attributes.getBgColor(); diff --git a/platform/platform-api/src/com/intellij/ui/SimpleColoredText.java b/platform/platform-api/src/com/intellij/ui/SimpleColoredText.java index d568198030c0..a267e62a87d8 100644 --- a/platform/platform-api/src/com/intellij/ui/SimpleColoredText.java +++ b/platform/platform-api/src/com/intellij/ui/SimpleColoredText.java @@ -81,4 +81,15 @@ public class SimpleColoredText { public ArrayList getAttributes() { return myAttributes; } + + public SimpleColoredText derive(SimpleTextAttributes attributes, boolean override) { + SimpleColoredText result = new SimpleColoredText(); + for (int i = 0; i < myTexts.size(); i++) { + SimpleTextAttributes overridden = override + ? SimpleTextAttributes.merge(myAttributes.get(i), attributes) + : SimpleTextAttributes.merge(attributes, myAttributes.get(i)); + result.append(myTexts.get(i), overridden); + } + return result; + } } From cf75e76e930a9c238e5c91d787cf71b20b13a571 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 20 Mar 2012 14:21:11 +0100 Subject: [PATCH 052/106] do not perform initial vfs lookup of output roots in compile-server mode --- .../intellij/compiler/impl/CompileDriver.java | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java index 0d7a54633fec..54efeb29a62a 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java @@ -154,23 +154,25 @@ public class CompileDriver { myGenerationCompilerModuleToOutputDirMap = new HashMap, Pair>(); - final LocalFileSystem lfs = LocalFileSystem.getInstance(); - final IntermediateOutputCompiler[] generatingCompilers = CompilerManager.getInstance(myProject).getCompilers(IntermediateOutputCompiler.class, myCompilerFilter); - final Module[] allModules = ModuleManager.getInstance(myProject).getModules(); - final CompilerConfiguration config = CompilerConfiguration.getInstance(project); - for (Module module : allModules) { - for (IntermediateOutputCompiler compiler : generatingCompilers) { - final VirtualFile productionOutput = lookupVFile(lfs, CompilerPaths.getGenerationOutputPath(compiler, module, false)); - final VirtualFile testOutput = lookupVFile(lfs, CompilerPaths.getGenerationOutputPath(compiler, module, true)); - final Pair pair = new Pair(compiler, module); - final Pair outputs = new Pair(productionOutput, testOutput); - myGenerationCompilerModuleToOutputDirMap.put(pair, outputs); - } - if (config.isAnnotationProcessorsEnabled()) { - if (config.isAnnotationProcessingEnabled(module)) { - final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module); - if (path != null) { - lookupVFile(lfs, path); // ensure the file is created and added to VFS + if (!useCompileServer()) { + final LocalFileSystem lfs = LocalFileSystem.getInstance(); + final IntermediateOutputCompiler[] generatingCompilers = CompilerManager.getInstance(myProject).getCompilers(IntermediateOutputCompiler.class, myCompilerFilter); + final Module[] allModules = ModuleManager.getInstance(myProject).getModules(); + final CompilerConfiguration config = CompilerConfiguration.getInstance(project); + for (Module module : allModules) { + for (IntermediateOutputCompiler compiler : generatingCompilers) { + final VirtualFile productionOutput = lookupVFile(lfs, CompilerPaths.getGenerationOutputPath(compiler, module, false)); + final VirtualFile testOutput = lookupVFile(lfs, CompilerPaths.getGenerationOutputPath(compiler, module, true)); + final Pair pair = new Pair(compiler, module); + final Pair outputs = new Pair(productionOutput, testOutput); + myGenerationCompilerModuleToOutputDirMap.put(pair, outputs); + } + if (config.isAnnotationProcessorsEnabled()) { + if (config.isAnnotationProcessingEnabled(module)) { + final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module); + if (path != null) { + lookupVFile(lfs, path); // ensure the file is created and added to VFS + } } } } From 6eab78118ab6c18c0a5c7c89fe932132263aa54f Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 20 Mar 2012 15:02:23 +0100 Subject: [PATCH 053/106] don't LOG.error problems caused by invalid templates (EA-31899 - assert: JavaParserUtil.parseFragment) --- .../jetbrains/generate/tostring/GenerateToStringUtils.java | 7 ++----- .../generate/tostring/GenerateToStringWorker.java | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/plugins/generate-tostring/src/org/jetbrains/generate/tostring/GenerateToStringUtils.java b/plugins/generate-tostring/src/org/jetbrains/generate/tostring/GenerateToStringUtils.java index e582eb2c336c..c74798537cb2 100644 --- a/plugins/generate-tostring/src/org/jetbrains/generate/tostring/GenerateToStringUtils.java +++ b/plugins/generate-tostring/src/org/jetbrains/generate/tostring/GenerateToStringUtils.java @@ -18,7 +18,6 @@ package org.jetbrains.generate.tostring; import com.intellij.codeInsight.generation.PsiElementClassMember; import com.intellij.codeInsight.generation.PsiFieldMember; import com.intellij.codeInsight.generation.PsiMethodMember; -import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; @@ -31,7 +30,6 @@ import org.jetbrains.generate.tostring.exception.GenerateCodeException; import org.jetbrains.generate.tostring.exception.PluginException; import org.jetbrains.generate.tostring.psi.PsiAdapter; -import java.io.File; import java.util.ArrayList; import java.util.List; @@ -142,9 +140,8 @@ public class GenerateToStringUtils { * @param e the caused exception. * @throws RuntimeException is thrown for severe exceptions */ - public static void handleExeption(Project project, Exception e) throws RuntimeException { - e.printStackTrace(); // must print stacktrace to see caused in IDEA log / console - log.error(e); + public static void handleException(Project project, Exception e) throws RuntimeException { + log.info(e); if (e instanceof GenerateCodeException) { // code generation error - display velocity errror in error dialog so user can identify problem quicker diff --git a/plugins/generate-tostring/src/org/jetbrains/generate/tostring/GenerateToStringWorker.java b/plugins/generate-tostring/src/org/jetbrains/generate/tostring/GenerateToStringWorker.java index 0eb91c0fd2a8..d2dd14f394ef 100644 --- a/plugins/generate-tostring/src/org/jetbrains/generate/tostring/GenerateToStringWorker.java +++ b/plugins/generate-tostring/src/org/jetbrains/generate/tostring/GenerateToStringWorker.java @@ -382,7 +382,7 @@ public class GenerateToStringWorker { new GenerateToStringWorker(clazz, editor, insertAtOverride).execute(selectedMemebers, template); } catch (Exception e) { - GenerateToStringUtils.handleExeption(clazz.getProject(), e); + GenerateToStringUtils.handleException(clazz.getProject(), e); } } }); From f813ec1a2ffef01b1e26824b8870fc3feb30078e Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Tue, 20 Mar 2012 17:40:36 +0400 Subject: [PATCH 054/106] indeterminate progress for updates checking --- .../openapi/updateSettings/impl/CheckForUpdateAction.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java index 719dd5276cd4..ce5ad9dacc10 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java @@ -50,6 +50,7 @@ public class CheckForUpdateAction extends AnAction implements DumbAware { ProgressManager.getInstance().run(new Task.Modal(project, "Checking for updates", false) { @Override public void run(@NotNull ProgressIndicator indicator) { + indicator.setIndeterminate(true); final CheckForUpdateResult result = UpdateChecker.checkForUpdates(instance, PropertiesComponent.getInstance(), true ); From 12c304a12571eccaf9e51f48e5c496dc90080070 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 20 Mar 2012 16:31:41 +0100 Subject: [PATCH 055/106] compile-server: when marking dependent files in some package for recompilation, accept only the files belonging to the module chunk being compiled or to modules that depend on the chunk --- .../jps/incremental/ModuleLevelBuilder.java | 78 +++++++++++-------- .../ether/dependencyView/Mappings.java | 33 ++++++-- .../org/jetbrains/ether/ProjectWrapper.java | 3 +- 3 files changed, 72 insertions(+), 42 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java index 4c4a3e7f78f4..099eb993c267 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java @@ -77,8 +77,9 @@ public abstract class ModuleLevelBuilder extends Builder { final HashSet affectedBeforeDif = new HashSet(allAffectedFiles); + final ModulesBasedFileFilter moduleBasedFilter = new ModulesBasedFileFilter(context, chunk); final boolean incremental = globalMappings.differentiate( - delta, removedPaths, filesToCompile, allCompiledFiles, allAffectedFiles + delta, removedPaths, filesToCompile, allCompiledFiles, allAffectedFiles, moduleBasedFilter ); if (LOG.isDebugEnabled()) { @@ -103,13 +104,13 @@ public abstract class ModuleLevelBuilder extends Builder { if (!newlyAffectedFiles.isEmpty()) { - if (LOG.isDebugEnabled()) { - final List> wrongFiles = checkAffectedFilesInCorrectModules(context, chunk, newlyAffectedFiles); + final List> wrongFiles = checkAffectedFilesInCorrectModules(context, newlyAffectedFiles, moduleBasedFilter); if (!wrongFiles.isEmpty()) { LOG.debug("Wrong affected files for module chunk " + chunk.getName() + ": "); for (Pair pair : wrongFiles) { - LOG.debug("\t[" + pair.second.getName() + "] " + pair.first.getPath()); + final String name = pair.second != null? pair.second.getName() : "null"; + LOG.debug("\t[" + name + "] " + pair.first.getPath()); } } } @@ -146,45 +147,20 @@ public abstract class ModuleLevelBuilder extends Builder { } } - - private static List> checkAffectedFilesInCorrectModules(CompileContext context, ModuleChunk currentChunk, Collection affected) { + private static List> checkAffectedFilesInCorrectModules(CompileContext context, Collection affected, ModulesBasedFileFilter moduleBasedFilter) { if (affected.isEmpty()) { return Collections.emptyList(); } - - final Set chunkModules = currentChunk.getModules(); - final Map> cache = new HashMap>(); final List> result = new ArrayList>(); - for (File file : affected) { - final RootDescriptor moduleAndRoot = context.getModuleAndRoot(file); - if (moduleAndRoot == null) { - continue; + if (!moduleBasedFilter.accept(file)) { + final RootDescriptor moduleAndRoot = context.getModuleAndRoot(file); + result.add(Pair.create(file, moduleAndRoot != null? moduleAndRoot.module : null)); } - final Module moduleOfFile = moduleAndRoot.module; - if (chunkModules.contains(moduleOfFile)) { - continue; - } - Set moduleOfFileWithDependencies = cache.get(moduleOfFile); - if (moduleOfFileWithDependencies == null) { - moduleOfFileWithDependencies = ProjectPaths.getModulesWithDependentsRecursively(moduleOfFile, true); - cache.put(moduleOfFile, moduleOfFileWithDependencies); - } - if (intersects(moduleOfFileWithDependencies, chunkModules)) { - continue; - } - result.add(Pair.create(file, moduleOfFile)); } return result; } - private static boolean intersects(Set set1, Set set2) { - if (set1.size() < set2.size()) { - return new HashSet(set1).removeAll(set2); - } - return new HashSet(set2).removeAll(set1); - } - private static boolean chunkContainsAffectedFiles(CompileContext context, ModuleChunk chunk, final Set affected) throws IOException { final Set chunkModules = new HashSet(chunk.getModules()); if (!chunkModules.isEmpty()) { @@ -221,4 +197,40 @@ public abstract class ModuleLevelBuilder extends Builder { return removed != null? removed : Collections.emptySet(); } + private static class ModulesBasedFileFilter implements Mappings.DependentFilesFilter{ + private final CompileContext myContext; + private final Set myChunkModules; + private final Map> myCache = new HashMap>(); + + private ModulesBasedFileFilter(CompileContext context, ModuleChunk chunk) { + myContext = context; + myChunkModules = chunk.getModules(); + } + + @Override + public boolean accept(File file) { + final RootDescriptor moduleAndRoot = myContext.getModuleAndRoot(file); + if (moduleAndRoot == null) { + return true; + } + final Module moduleOfFile = moduleAndRoot.module; + if (myChunkModules.contains(moduleOfFile)) { + return true; + } + Set moduleOfFileWithDependencies = myCache.get(moduleOfFile); + if (moduleOfFileWithDependencies == null) { + moduleOfFileWithDependencies = ProjectPaths.getModulesWithDependentsRecursively(moduleOfFile, true); + myCache.put(moduleOfFile, moduleOfFileWithDependencies); + } + return intersects(moduleOfFileWithDependencies, myChunkModules); + } + + private static boolean intersects(Set set1, Set set2) { + if (set1.size() < set2.size()) { + return new HashSet(set1).removeAll(set2); + } + return new HashSet(set2).removeAll(set1); + } + } + } diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java index d6190d61d815..71918d2578b9 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java @@ -806,7 +806,10 @@ public class Mappings { } } - private boolean incrementalDecision(final DependencyContext.S owner, final Proto member, final Collection affectedFiles) { + private boolean incrementalDecision(final DependencyContext.S owner, + final Proto member, + final Collection affectedFiles, + DependentFilesFilter filter) { final boolean isField = member instanceof FieldRepr; final Util self = new Util(this); @@ -842,19 +845,33 @@ public class Mappings { if (ClassRepr.getPackageName(myContext.getValue(className)).equals(packageName)) { final String f = myContext.getValue(fileName); - debug("Adding: ", f); - affectedFiles.add(new File(f)); + final File file = new File(f); + if (filter.accept(file)) { + debug("Adding: ", f); + affectedFiles.add(file); + } } } return true; } + public interface DependentFilesFilter { + DependentFilesFilter ALL_FILES = new DependentFilesFilter() { + @Override + public boolean accept(File file) { + return true; + } + }; + + boolean accept(File file); + } + public boolean differentiate(final Mappings delta, final Collection removed, final Collection filesToCompile, final Collection compiledFiles, - final Collection affectedFiles) { + final Collection affectedFiles, DependentFilesFilter filter) { synchronized (myLock) { debug("Begin of Differentiate:"); @@ -926,7 +943,7 @@ public class Mappings { if (it.isAnnotation() && it.policy == RetentionPolicy.SOURCE) { debug("Annotation, retention policy = SOURCE => a switch to non-incremental mode requested"); - if (!incrementalDecision(it.outerClassName, it, affectedFiles)) { + if (!incrementalDecision(it.outerClassName, it, affectedFiles, filter)) { debug("End of Differentiate, returning false"); return false; } @@ -970,7 +987,7 @@ public class Mappings { if (removedtargets.contains(ElementType.LOCAL_VARIABLE)) { debug("Removed target contains LOCAL_VARIABLE => a switch to non-incremental mode requested"); - if (!incrementalDecision(it.outerClassName, it, affectedFiles)) { + if (!incrementalDecision(it.outerClassName, it, affectedFiles, filter)) { debug("End of Differentiate, returning false"); return false; } @@ -1396,7 +1413,7 @@ public class Mappings { if ((f.access & Opcodes.ACC_PRIVATE) == 0 && (f.access & mask) == mask && f.hasValue()) { debug("Field had value and was (non-private) final static => a switch to non-incremental mode requested"); - if (!incrementalDecision(it.name, f, affectedFiles)) { + if (!incrementalDecision(it.name, f, affectedFiles, filter)) { debug("End of Differentiate, returning false"); return false; } @@ -1417,7 +1434,7 @@ public class Mappings { if ((field.access & Opcodes.ACC_PRIVATE) == 0 && (field.access & mask) == mask) { if ((d.base() & Difference.ACCESS) > 0 || (d.base() & Difference.VALUE) > 0) { debug("Inline field changed it's access or value => a switch to non-incremental mode requested"); - if (!incrementalDecision(it.name, field, affectedFiles)) { + if (!incrementalDecision(it.name, field, affectedFiles, filter)) { debug("End of Differentiate, returning false"); return false; } diff --git a/jps/src/org/jetbrains/ether/ProjectWrapper.java b/jps/src/org/jetbrains/ether/ProjectWrapper.java index 01811ee5a439..05c22f89ada4 100644 --- a/jps/src/org/jetbrains/ether/ProjectWrapper.java +++ b/jps/src/org/jetbrains/ether/ProjectWrapper.java @@ -1163,7 +1163,8 @@ public class ProjectWrapper { final Collection affected = new HashSet(); - final boolean incremental = dependencyMapping.differentiate(delta, removed, files, compiled, affected); + final boolean incremental = dependencyMapping.differentiate(delta, removed, files, compiled, affected, + Mappings.DependentFilesFilter.ALL_FILES); for (File a : affected) { affectedFiles.add(FileUtil.toSystemIndependentName(a.getAbsolutePath())); From 9c33c655a9e822b6424f5d88eda0297a6773a00d Mon Sep 17 00:00:00 2001 From: irengrig Date: Tue, 20 Mar 2012 19:34:03 +0400 Subject: [PATCH 056/106] SVN: set tunnel provider for connections pool --- plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java index e05f70a8b0b1..ca76ab2915f8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java @@ -562,7 +562,7 @@ public class SvnVcs extends AbstractVcs { } else { keep = Boolean.getBoolean(KEEP_CONNECTIONS_KEY); } - myPool = new DefaultSVNRepositoryPool(myConfiguration.getAuthenticationManager(this), null, 60*1000, keep); + myPool = new DefaultSVNRepositoryPool(myConfiguration.getAuthenticationManager(this), myConfiguration.getOptions(myProject), 60*1000, keep); } private ISVNRepositoryPool getPool() { From 4dd76d0b8d88bd3105dbfe6150f795aeca457dc6 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 20 Mar 2012 19:44:29 +0400 Subject: [PATCH 057/106] "Local History -> Show History For Selection" menu item in context menu of project tree confuses user. --- .../ui/actions/ShowSelectionHistoryAction.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/ui/actions/ShowSelectionHistoryAction.java b/platform/lvcs-impl/src/com/intellij/history/integration/ui/actions/ShowSelectionHistoryAction.java index 90bafa107ef6..843795e24455 100644 --- a/platform/lvcs-impl/src/com/intellij/history/integration/ui/actions/ShowSelectionHistoryAction.java +++ b/platform/lvcs-impl/src/com/intellij/history/integration/ui/actions/ShowSelectionHistoryAction.java @@ -20,12 +20,14 @@ import com.intellij.history.core.LocalHistoryFacade; import com.intellij.history.integration.IdeaGateway; import com.intellij.history.integration.ui.views.SelectionHistoryDialog; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.actions.VcsContext; import com.intellij.openapi.vcs.actions.VcsContextWrapper; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.vcsUtil.VcsSelection; import com.intellij.vcsUtil.VcsSelectionUtil; +import org.jetbrains.annotations.Nullable; public class ShowSelectionHistoryAction extends ShowHistoryAction { @Override @@ -44,12 +46,23 @@ public class ShowSelectionHistoryAction extends ShowHistoryAction { return sel == null ? super.getText(e) : sel.getActionName(); } + @Override + public void update(AnActionEvent e) { + if (e.getData(PlatformDataKeys.EDITOR) == null) { + e.getPresentation().setVisible(false); + } + else { + super.update(e); + } + } + @Override protected boolean isEnabled(LocalHistoryFacade vcs, IdeaGateway gw, VirtualFile f, AnActionEvent e) { return super.isEnabled(vcs, gw, f, e) && !f.isDirectory() && getSelection(e) != null; } - private VcsSelection getSelection(AnActionEvent e) { + @Nullable + private static VcsSelection getSelection(AnActionEvent e) { VcsContext c = VcsContextWrapper.createCachedInstanceOn(e); return VcsSelectionUtil.getSelection(c); } From fab119c28505b7d9d88a121bfc6ed4f3468d3627 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 20 Mar 2012 20:12:57 +0400 Subject: [PATCH 058/106] IDEA-83033 external annotators: do not perform more than one annotating sessions in the same time [rev=rustam.vishnyakov] --- .../daemon/impl/ExternalToolPass.java | 8 ++++++-- .../daemon/impl/ExternalToolPassFactory.java | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPass.java index 16e61e3fa520..df0cea32c0c2 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPass.java @@ -50,6 +50,8 @@ public class ExternalToolPass extends TextEditorHighlightingPass { private final Map myAnnotator2DataMap; + private final ExternalToolPassFactory myExternalToolPassFactory; + private static class MyData { final PsiFile myPsiRoot; final Object myCollectedInfo; @@ -61,7 +63,8 @@ public class ExternalToolPass extends TextEditorHighlightingPass { } } - public ExternalToolPass(@NotNull PsiFile file, + public ExternalToolPass(@NotNull ExternalToolPassFactory externalToolPassFactory, + @NotNull PsiFile file, @NotNull Editor editor, int startOffset, int endOffset) { @@ -72,6 +75,7 @@ public class ExternalToolPass extends TextEditorHighlightingPass { myAnnotationHolder = new AnnotationHolderImpl(new AnnotationSession(file)); myAnnotator2DataMap = new HashMap(); + myExternalToolPassFactory = externalToolPassFactory; } @Override @@ -159,7 +163,7 @@ public class ExternalToolPass extends TextEditorHighlightingPass { r.run(); } else { - ApplicationManager.getApplication().executeOnPooledThread(r); + myExternalToolPassFactory.scheduleExternalActivity(myFile, r); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPassFactory.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPassFactory.java index d1717395c5c5..f719f5e89cf4 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPassFactory.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPassFactory.java @@ -28,6 +28,8 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiFile; +import com.intellij.util.ui.update.MergingUpdateQueue; +import com.intellij.util.ui.update.Update; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -38,10 +40,15 @@ import java.util.List; * @author cdr */ public class ExternalToolPassFactory extends AbstractProjectComponent implements TextEditorHighlightingPassFactory { + private final MergingUpdateQueue myExternalActivitiesQueue; + public ExternalToolPassFactory(Project project, TextEditorHighlightingPassRegistrar highlightingPassRegistrar) { super(project); // start after PostHighlightingPass completion since it could report errors that can prevent us to run highlightingPassRegistrar.registerTextEditorHighlightingPass(this, new int[]{Pass.POST_UPDATE_ALL}, null, true, Pass.EXTERNAL_TOOLS); + + myExternalActivitiesQueue = new MergingUpdateQueue("ExternalActivitiesQueue", 300, true, MergingUpdateQueue.ANY_COMPONENT, project, + null, false); } @Override @@ -58,7 +65,7 @@ public class ExternalToolPassFactory extends AbstractProjectComponent implements if (textRange == null || !externalAnnotatorsDefined(file)) { return null; } - return new ExternalToolPass(file, editor, textRange.getStartOffset(), textRange.getEndOffset()); + return new ExternalToolPass(this, file, editor, textRange.getStartOffset(), textRange.getEndOffset()); } private static boolean externalAnnotatorsDefined(PsiFile file) { @@ -70,4 +77,13 @@ public class ExternalToolPassFactory extends AbstractProjectComponent implements } return false; } + + void scheduleExternalActivity(@NotNull PsiFile file, @NotNull final Runnable r) { + myExternalActivitiesQueue.queue(new Update(file) { + @Override + public void run() { + r.run(); + } + }); + } } From d51d821e9b1a68a05177dc66bd4cf4ff91e59c6f Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Mar 2012 12:16:58 +0100 Subject: [PATCH 059/106] more diagnostics (EA-34727, EA-34803) --- .../src/com/intellij/util/xml/impl/DomInvocationHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/DomInvocationHandler.java b/xml/dom-impl/src/com/intellij/util/xml/impl/DomInvocationHandler.java index b7480910ed49..61b1bab28c3c 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/impl/DomInvocationHandler.java +++ b/xml/dom-impl/src/com/intellij/util/xml/impl/DomInvocationHandler.java @@ -80,7 +80,7 @@ public abstract class DomInvocationHandler" + parameter.getName() + "; method=" + method); + throw new AssertionError("No converter specified: String<->" + parameter.getName() + "; method=" + method + "; place=" + myChildDescription); } return converter; } From 665025f19416044b02e8fa9fd2c7e5afe470a7e5 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Mar 2012 12:40:06 +0100 Subject: [PATCH 060/106] a more gentle error reporting (EA-34679) --- .../groovy/compiler/GroovyCompilerBase.java | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java index 9c0ee98046b6..e044b6054b1d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java @@ -165,38 +165,40 @@ public abstract class GroovyCompilerBase implements TranslatingCompiler { parameters.setMainClass(GroovycRunner.class.getName()); - try { - final VirtualFile finalOutputDir = getMainOutput(compileContext, module, tests); - LOG.assertTrue(finalOutputDir != null, "No output directory for module " + module.getName() + (tests ? " tests" : " production")); - final Charset ideCharset = EncodingProjectManager.getInstance(myProject).getDefaultCharset(); - String encoding = ideCharset != null && !Comparing.equal(CharsetToolkit.getDefaultSystemCharset(), ideCharset) ? ideCharset.name() : null; - Set paths2Compile = ContainerUtil.map2Set(toCompile, new Function() { - @Override - public String fun(VirtualFile file) { - return file.getPath(); - } - }); - Map class2Src = new HashMap(); + final VirtualFile finalOutputDir = getMainOutput(compileContext, module, tests); + LOG.assertTrue(finalOutputDir != null, "No output directory for module " + module.getName() + (tests ? " tests" : " production")); + final Charset ideCharset = EncodingProjectManager.getInstance(myProject).getDefaultCharset(); + String encoding = ideCharset != null && !Comparing.equal(CharsetToolkit.getDefaultSystemCharset(), ideCharset) ? ideCharset.name() : null; + Set paths2Compile = ContainerUtil.map2Set(toCompile, new Function() { + @Override + public String fun(VirtualFile file) { + return file.getPath(); + } + }); + Map class2Src = new HashMap(); - for (VirtualFile file : enumerateGroovyFiles(module)) { - if (!paths2Compile.contains(file.getPath())) { - for (String name : TranslatingCompilerFilesMonitor.getInstance().getCompiledClassNames(file, myProject)) { - class2Src.put(name, file.getPath()); - } + for (VirtualFile file : enumerateGroovyFiles(module)) { + if (!paths2Compile.contains(file.getPath())) { + for (String name : TranslatingCompilerFilesMonitor.getInstance().getCompiledClassNames(file, myProject)) { + class2Src.put(name, file.getPath()); } } + } - File fileWithParameters = GroovycOSProcessHandler + final File fileWithParameters; + try { + fileWithParameters = GroovycOSProcessHandler .fillFileWithGroovycParameters(outputDir.getPath(), paths2Compile, FileUtil.toSystemDependentName(finalOutputDir.getPath()), class2Src, encoding, patchers); - - parameters.getProgramParametersList().add(forStubs ? "stubs" : "groovyc"); - parameters.getProgramParametersList().add(fileWithParameters.getPath()); } catch (IOException e) { - LOG.error(e); + LOG.info(e); + compileContext.addMessage(CompilerMessageCategory.ERROR, "Error creating a temp file to launch Groovy compiler: " + e.getMessage(), null, -1, -1); + return; } + parameters.getProgramParametersList().add(forStubs ? "stubs" : "groovyc"); + parameters.getProgramParametersList().add(fileWithParameters.getPath()); try { Process process = JdkUtil.setupJVMCommandLine(exePath, parameters, true).createProcess(); From 453b655becec490d999a331e7970ab54d5202e85 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Mar 2012 12:46:08 +0100 Subject: [PATCH 061/106] fix NPE (EA-34593) --- .../codeInsight/editorActions/XmlAutoPopupHandler.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlAutoPopupHandler.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlAutoPopupHandler.java index 139ea62d72b4..97cbbcef64c8 100644 --- a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlAutoPopupHandler.java +++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlAutoPopupHandler.java @@ -117,7 +117,10 @@ public class XmlAutoPopupHandler extends TypedHandlerDelegate { Boolean result = isRelevantLanguage.get(); if (result == null) { Language language = element.getLanguage(); - if (element instanceof PsiWhiteSpace) language = element.getParent().getLanguage(); + PsiElement parent = element.getParent(); + if (element instanceof PsiWhiteSpace && parent != null) { + language = parent.getLanguage(); + } result = language instanceof XMLLanguage || isAntFile.booleanValue(); isRelevantLanguage.set(result); } From 30a44cb7063021fd007aa121c827a3f6dd2bc0bb Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Mar 2012 13:08:10 +0100 Subject: [PATCH 062/106] fix NPE (EA-34474) --- .../lang-impl/src/com/intellij/ide/actions/GotoActionBase.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java index dd3afc04bb4e..f7586f8ce300 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java @@ -175,7 +175,8 @@ public abstract class GotoActionBase extends AnAction { @Override public void onClose() { ourLastStrings.put(myInAction, Pair.create(popup.getEnteredText(), popup.getSelectedIndex())); - if (startedAction.equals(myInAction)) { + //noinspection ConstantConditions + if (startedAction != null && startedAction.equals(myInAction)) { myInAction = null; } if (filter != null) { From 3871aa35af0f17f42ca7c438d4f8c56f4790d46a Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Mar 2012 13:09:22 +0100 Subject: [PATCH 063/106] a more gentle error reporting (EA-34454) --- .../jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java index e044b6054b1d..d546b64d0ebc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java @@ -274,7 +274,8 @@ public abstract class GroovyCompilerBase implements TranslatingCompiler { sink.add(outputDir.getPath(), items, VfsUtil.toVirtualFileArray(toRecompile)); } catch (ExecutionException e) { - LOG.error(e); + LOG.info(e); + compileContext.addMessage(CompilerMessageCategory.ERROR, "Error running Groovy compiler: " + e.getMessage(), null, -1, -1); } } From a66b7c2d4801383bf86c6f7cb114f38f98bf4726 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Mar 2012 15:39:10 +0100 Subject: [PATCH 064/106] only print to event log console after the project has been initialized (EA-34525) --- .../platform-impl/src/com/intellij/notification/EventLog.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/notification/EventLog.java b/platform/platform-impl/src/com/intellij/notification/EventLog.java index 2ac011e9a5b9..89e8189e62e0 100644 --- a/platform/platform-impl/src/com/intellij/notification/EventLog.java +++ b/platform/platform-impl/src/com/intellij/notification/EventLog.java @@ -36,6 +36,7 @@ import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.ui.SimpleToolWindowPanel; import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.util.*; @@ -403,7 +404,7 @@ public class EventLog implements Notifications { myProjectModel.addNotification(notification); - ApplicationManager.getApplication().invokeLater(new Runnable() { + StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new Runnable() { @Override public void run() { if (!ShutDownTracker.isShutdownHookRunning() && !myProject.isDisposed()) { From f0f9f5f75a8c4a07755e1135eae33880218215d8 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Mar 2012 15:42:52 +0100 Subject: [PATCH 065/106] not-null assertions --- .../src/com/intellij/psi/search/LocalSearchScope.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/platform/core-api/src/com/intellij/psi/search/LocalSearchScope.java b/platform/core-api/src/com/intellij/psi/search/LocalSearchScope.java index c092c70e2d10..9c751afbed35 100644 --- a/platform/core-api/src/com/intellij/psi/search/LocalSearchScope.java +++ b/platform/core-api/src/com/intellij/psi/search/LocalSearchScope.java @@ -41,11 +41,11 @@ public class LocalSearchScope extends SearchScope { public static final LocalSearchScope EMPTY = new LocalSearchScope(PsiElement.EMPTY_ARRAY); private String myDisplayName; - public LocalSearchScope(PsiElement scope) { + public LocalSearchScope(@NotNull PsiElement scope) { this(scope, null); } - public LocalSearchScope(PsiElement scope, String displayName) { + public LocalSearchScope(@NotNull PsiElement scope, @Nullable String displayName) { this(new PsiElement[]{scope}); myDisplayName = displayName; } @@ -54,16 +54,17 @@ public class LocalSearchScope extends SearchScope { this(scope, null); } - public LocalSearchScope(PsiElement[] scope, String displayName) { + public LocalSearchScope(PsiElement[] scope, @Nullable String displayName) { this(scope, displayName, false); } - public LocalSearchScope(final PsiElement[] scope, final String displayName, final boolean ignoreInjectedPsi) { + public LocalSearchScope(final PsiElement[] scope, @Nullable final String displayName, final boolean ignoreInjectedPsi) { myIgnoreInjectedPsi = ignoreInjectedPsi; myDisplayName = displayName; Set localScope = new LinkedHashSet(scope.length); for (final PsiElement element : scope) { + LOG.assertTrue(element != null, "null element"); LOG.assertTrue(element.getContainingFile() != null, element.getClass().getName()); if (element instanceof PsiFile) { List files = ((PsiFile)element).getViewProvider().getAllFiles(); From 081c6eac330d1c845a8621136558944479fee738 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Mar 2012 15:46:01 +0100 Subject: [PATCH 066/106] @Nullable --- .../src/com/intellij/psi/scope/util/PsiScopesUtil.java | 2 +- platform/core-api/src/com/intellij/psi/PsiElement.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/util/PsiScopesUtil.java b/java/java-psi-impl/src/com/intellij/psi/scope/util/PsiScopesUtil.java index d44097d038d4..962d7cb9256a 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/util/PsiScopesUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/util/PsiScopesUtil.java @@ -144,7 +144,7 @@ public class PsiScopesUtil { public static boolean resolveAndWalk(PsiScopeProcessor processor, PsiJavaCodeReferenceElement ref, - PsiElement maxScope, + @Nullable PsiElement maxScope, boolean incompleteCode) { final PsiElement qualifier = ref.getQualifier(); final PsiElement classNameElement = ref.getReferenceNameElement(); diff --git a/platform/core-api/src/com/intellij/psi/PsiElement.java b/platform/core-api/src/com/intellij/psi/PsiElement.java index f26dbf06b44d..99bc7789c90c 100644 --- a/platform/core-api/src/com/intellij/psi/PsiElement.java +++ b/platform/core-api/src/com/intellij/psi/PsiElement.java @@ -269,7 +269,7 @@ public interface PsiElement extends UserDataHolder, Iconable { * @return the element which was actually added (either element or its copy). * @throws IncorrectOperationException if the modification is not supported or not possible for some reason. */ - PsiElement addBefore(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException; + PsiElement addBefore(@NotNull PsiElement element, @Nullable PsiElement anchor) throws IncorrectOperationException; /** * Adds a child to this PSI element, after the specified anchor element. @@ -279,7 +279,7 @@ public interface PsiElement extends UserDataHolder, Iconable { * @return the element which was actually added (either element or its copy). * @throws IncorrectOperationException if the modification is not supported or not possible for some reason. */ - PsiElement addAfter(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException; + PsiElement addAfter(@NotNull PsiElement element, @Nullable PsiElement anchor) throws IncorrectOperationException; /** * Checks if it is possible to add the specified element as a child to this element, From a898760eebd8172f894b4f1b8da028e3815f1378 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Mar 2012 16:10:24 +0100 Subject: [PATCH 067/106] there may be no containing file for (light) members (EA-34904) --- .../src/com/intellij/psi/impl/PsiImplUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java index 31a4851df62c..d4dcd96dd43f 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java @@ -272,7 +272,7 @@ public class PsiImplUtil { return new PsiImmediateClassType(classClass, substitutor); } - public static PsiAnnotation findAnnotation(@NotNull PsiAnnotationOwner modifierList, @NotNull String qualifiedName) { + @Nullable public static PsiAnnotation findAnnotation(@NotNull PsiAnnotationOwner modifierList, @NotNull String qualifiedName) { final String shortName = StringUtil.getShortName(qualifiedName); PsiAnnotation[] annotations = modifierList.getAnnotations(); for (PsiAnnotation annotation : annotations) { @@ -368,7 +368,7 @@ public class PsiImplUtil { } else if (member.hasModifierProperty(PsiModifier.PRIVATE)) { PsiClass topClass = PsiUtil.getTopLevelClass(member); - return topClass != null ? new LocalSearchScope(topClass) : new LocalSearchScope(file); + return topClass != null ? new LocalSearchScope(topClass) : file != null ? new LocalSearchScope(file) : maximalUseScope; } else { if (file instanceof PsiJavaFile) { @@ -388,7 +388,7 @@ public class PsiImplUtil { return getServerPageFile(element) != null; } - public static ServerPageFile getServerPageFile(final PsiElement element) { + @Nullable public static ServerPageFile getServerPageFile(final PsiElement element) { final PsiFile psiFile = PsiUtilCore.getTemplateLanguageFile(element); return psiFile instanceof ServerPageFile ? (ServerPageFile)psiFile : null; } From bd3804c7d6e9554fb0e0dc8afb06ab4a37509675 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Mar 2012 16:35:59 +0100 Subject: [PATCH 068/106] 2 escapes instead of 3 to cancel rename --- .../src/com/intellij/codeInsight/lookup/impl/LookupImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index ef1ca8393cf9..9d2c76e76879 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -924,7 +924,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable @Override public boolean vetoesHiding() { - return myChangeGuard || myDisposed; + return myChangeGuard; } public boolean isAvailableToUser() { From e21ab049dcc1236cd8b33d8a3c677b302898ecc2 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Mar 2012 17:34:03 +0100 Subject: [PATCH 069/106] don't let chained call completion create uncompilable code due to language level problems (EA-34925) --- .../completion/JavaNoVariantsDelegator.java | 8 +++-- ...erenceExpressionCompletionContributor.java | 33 +++++++++++++------ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java index 1cb0667bd7e8..669905ed006e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java @@ -112,9 +112,11 @@ public class JavaNoVariantsDelegator extends CompletionContributor { PsiType type = JavaCompletionUtil.getLookupElementType(base); if (type != null && !PsiType.VOID.equals(type)) { PsiReferenceExpression ref = ReferenceExpressionCompletionContributor.createMockReference(position, type, base); - for (final LookupElement item : JavaSmartCompletionContributor.completeReference(position, ref, filter, true, true, parameters, - result.getPrefixMatcher())) { - qualifiedCollector.addElement(new JavaChainLookupElement(base, item)); + if (ref != null) { + for (final LookupElement item : JavaSmartCompletionContributor.completeReference(position, ref, filter, true, true, parameters, + result.getPrefixMatcher())) { + qualifiedCollector.addElement(new JavaChainLookupElement(base, item)); + } } } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java index 5033f6a629cd..e1f28cd2b85a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java @@ -25,8 +25,8 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.patterns.PsiJavaPatterns; import com.intellij.patterns.PsiMethodPattern; +import com.intellij.patterns.StandardPatterns; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.JavaCodeStyleManager; @@ -46,7 +46,10 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; import static com.intellij.patterns.PsiJavaPatterns.psiElement; import static com.intellij.patterns.PsiJavaPatterns.psiMethod; @@ -57,7 +60,7 @@ import static com.intellij.patterns.PsiJavaPatterns.psiMethod; public class ReferenceExpressionCompletionContributor { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.ReferenceExpressionCompletionContributor"); private static final PsiMethodPattern OBJECT_METHOD_PATTERN = psiMethod().withName( - PsiJavaPatterns.string().oneOf("hashCode", "equals", "finalize", "wait", "notify", "notifyAll", "getClass", "clone", "toString")). + StandardPatterns.string().oneOf("hashCode", "equals", "finalize", "wait", "notify", "notifyAll", "getClass", "clone", "toString")). definedInClass(CommonClassNames.JAVA_LANG_OBJECT); private static final PrefixMatcher TRUE_MATCHER = new PrefixMatcher("") { @Override @@ -83,9 +86,9 @@ public class ReferenceExpressionCompletionContributor { } if (psiElement().inside( - PsiJavaPatterns.or( - psiElement(PsiAnnotationParameterList.class), - psiElement(PsiSwitchLabelStatement.class)) + StandardPatterns.or( + psiElement(PsiAnnotationParameterList.class), + psiElement(PsiSwitchLabelStatement.class)) ).accepts(element)) { return new ElementExtractorFilter(new AndFilter( new ClassFilter(PsiField.class), @@ -426,27 +429,37 @@ public class ReferenceExpressionCompletionContributor { PsiType qualifierType, final PsiType expectedType, JavaSmartCompletionParameters parameters) throws IncorrectOperationException { final PsiReferenceExpression mockRef = createMockReference(place, qualifierType, qualifierItem); + if (mockRef == null) { + return; + } final ElementFilter filter = getReferenceFilter(place, true); for (final LookupElement item : completeFinalReference(place, mockRef, filter, parameters)) { - if (shoudChain(place, qualifierType, expectedType, item)) { + if (shouldChain(place, qualifierType, expectedType, item)) { result.consume(new JavaChainLookupElement(qualifierItem, item)); } } } + @Nullable public static PsiReferenceExpression createMockReference(final PsiElement place, @NotNull PsiType qualifierType, LookupElement qualifierItem) { PsiElementFactory factory = JavaPsiFacade.getElementFactory(place.getProject()); if (qualifierItem.getObject() instanceof PsiClass) { - return (PsiReferenceExpression)factory - .createExpressionFromText(((PsiClass)qualifierItem.getObject()).getQualifiedName() + ".xxx", place); + try { + return (PsiReferenceExpression)factory + .createExpressionFromText(((PsiClass)qualifierItem.getObject()).getQualifiedName() + ".xxx", place); + } + catch (IncorrectOperationException e) { + LOG.info(e); + return null; + } } return (PsiReferenceExpression) factory.createExpressionFromText("xxx.xxx", JavaCompletionUtil .createContextWithXxxVariable(place, qualifierType)); } - private static boolean shoudChain(PsiElement element, PsiType qualifierType, PsiType expectedType, LookupElement item) { + private static boolean shouldChain(PsiElement element, PsiType qualifierType, PsiType expectedType, LookupElement item) { if (item.getObject() instanceof PsiMethod) { final PsiMethod method = (PsiMethod)item.getObject(); if (psiMethod().withName("toArray").withParameterCount(1) From f1bd79a177749e38377ec73a161e2a785e06a008 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 20 Mar 2012 18:25:59 +0100 Subject: [PATCH 070/106] less disk operations in integrate --- .../ether/dependencyView/Mappings.java | 35 +++++++++++-------- .../ether/dependencyView/MultiMaplet.java | 1 + .../dependencyView/PersistentMultiMaplet.java | 19 ++++++++-- .../dependencyView/TransientMultiMaplet.java | 13 +++++-- 4 files changed, 48 insertions(+), 20 deletions(-) diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java index 71918d2578b9..7ff64fdb13bc 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java @@ -1650,40 +1650,46 @@ public class Mappings { if (delta.isDifferentiated()) { for (DependencyContext.S c : delta.getChangedClasses()) { - myClassToSubclasses.remove(c); - final Collection subClasses = delta.myClassToSubclasses.get(c); - if (subClasses != null) { - myClassToSubclasses.put(c, subClasses); + myClassToSubclasses.replace(c, subClasses); + } + else { + myClassToSubclasses.remove(c); } - myClassToSourceFile.remove(c); - final DependencyContext.S sourceFile = delta.myClassToSourceFile.get(c); - if (sourceFile != null) { myClassToSourceFile.put(c, sourceFile); } + else { + myClassToSourceFile.remove(c); + } } for (DependencyContext.S f : delta.getChangedFiles()) { - mySourceFileToClasses.remove(f); final Collection classes = delta.mySourceFileToClasses.get(f); if (classes != null) { - mySourceFileToClasses.put(f, classes); + mySourceFileToClasses.replace(f, classes); + } + else { + mySourceFileToClasses.remove(f); } - mySourceFileToUsages.remove(f); final Collection clusters = delta.mySourceFileToUsages.get(f); if (clusters != null) { - mySourceFileToUsages.put(f, clusters); + mySourceFileToUsages.replace(f, clusters); + } + else { + mySourceFileToUsages.remove(f); } - mySourceFileToAnnotationUsages.remove(f); final Collection usages = delta.mySourceFileToAnnotationUsages.get(f); if (usages != null) { - mySourceFileToAnnotationUsages.put(f, usages); + mySourceFileToAnnotationUsages.replace(f, usages); + } + else { + mySourceFileToAnnotationUsages.remove(f); } } } @@ -1728,8 +1734,7 @@ public class Mappings { changed |= past.addAll(now); if (changed) { - myClassToClassDependency.remove(aClass); - myClassToClassDependency.put(aClass, past); + myClassToClassDependency.replace(aClass, past); } } } diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/MultiMaplet.java b/jps/model/src/org/jetbrains/ether/dependencyView/MultiMaplet.java index a7152b3684dc..15a2875086e3 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/MultiMaplet.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/MultiMaplet.java @@ -30,6 +30,7 @@ interface MultiMaplet { Collection get(final K key); void put(final K key, final V value); void put(final K key, final Collection value); + void replace(final K key, final Collection value); void putAll(MultiMaplet m); void replaceAll(MultiMaplet m); void remove(final K key); diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/PersistentMultiMaplet.java b/jps/model/src/org/jetbrains/ether/dependencyView/PersistentMultiMaplet.java index f1d288696244..0ac8cdfc1168 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/PersistentMultiMaplet.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/PersistentMultiMaplet.java @@ -66,6 +66,21 @@ class PersistentMultiMaplet implements MultiMaplet { } } + @Override + public void replace(K key, Collection value) { + try { + if (value == null || value.isEmpty()) { + myMap.remove(key); + } + else { + myMap.put(key, value); + } + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + @Override public void put(final K key, final Collection value) { try { @@ -149,9 +164,7 @@ class PersistentMultiMaplet implements MultiMaplet { @Override public void replaceAll(MultiMaplet m) { for (Map.Entry> entry : m.entrySet()) { - final K key = entry.getKey(); - remove(key); - put(key, entry.getValue()); + replace(entry.getKey(), entry.getValue()); } } diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/TransientMultiMaplet.java b/jps/model/src/org/jetbrains/ether/dependencyView/TransientMultiMaplet.java index 7a5f2b85eb90..9a2792e15558 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/TransientMultiMaplet.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/TransientMultiMaplet.java @@ -72,6 +72,16 @@ class TransientMultiMaplet implements MultiMaplet { } } + @Override + public void replace(K key, Collection value) { + if (value == null || value.isEmpty()) { + myMap.remove(key); + } + else { + myMap.put(key, value); + } + } + @Override public void put(final K key, final V value) { final Collection x = constr.create(); @@ -111,8 +121,7 @@ class TransientMultiMaplet implements MultiMaplet { @Override public void replaceAll(MultiMaplet m) { for (Map.Entry> e : m.entrySet()) { - remove(e.getKey()); - put(e.getKey(), e.getValue()); + replace(e.getKey(), e.getValue()); } } From d50839ec1a1f7269f558b40a56d82c140225a6d1 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 20 Mar 2012 18:33:06 +0100 Subject: [PATCH 071/106] allow empty values --- .../jetbrains/ether/dependencyView/PersistentMultiMaplet.java | 2 +- .../jetbrains/ether/dependencyView/TransientMultiMaplet.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/PersistentMultiMaplet.java b/jps/model/src/org/jetbrains/ether/dependencyView/PersistentMultiMaplet.java index 0ac8cdfc1168..e5497ab73994 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/PersistentMultiMaplet.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/PersistentMultiMaplet.java @@ -69,7 +69,7 @@ class PersistentMultiMaplet implements MultiMaplet { @Override public void replace(K key, Collection value) { try { - if (value == null || value.isEmpty()) { + if (value == null) { myMap.remove(key); } else { diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/TransientMultiMaplet.java b/jps/model/src/org/jetbrains/ether/dependencyView/TransientMultiMaplet.java index 9a2792e15558..71aafd8696c8 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/TransientMultiMaplet.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/TransientMultiMaplet.java @@ -74,7 +74,7 @@ class TransientMultiMaplet implements MultiMaplet { @Override public void replace(K key, Collection value) { - if (value == null || value.isEmpty()) { + if (value == null) { myMap.remove(key); } else { From ea42119150cd8147f25ef15724804c415d27b169 Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Tue, 20 Mar 2012 21:47:33 +0400 Subject: [PATCH 072/106] Properties --- .../designer/model/PropertyParser.java | 10 + .../propertyTable/AttributeProperty.java | 19 +- .../propertyTable/editors/ResourceDialog.java | 308 ++++++++++++++++++ .../editors/StringsComboEditor.java | 2 +- .../componentTree/TreeNodeDescriptor.java | 5 + .../designSurface/DesignerEditorPanel.java | 4 + .../propertyTable/PropertyEditor.java | 2 +- .../designer/propertyTable/PropertyTable.java | 2 +- .../editors/AbstractTextFieldEditor.java | 2 +- .../propertyTable/editors/BooleanEditor.java | 2 +- 10 files changed, 349 insertions(+), 7 deletions(-) create mode 100644 plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ResourceDialog.java diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/PropertyParser.java b/plugins/android-designer/src/com/intellij/android/designer/model/PropertyParser.java index 2221502b153f..9e8ad8fc9e2d 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/PropertyParser.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/PropertyParser.java @@ -16,9 +16,11 @@ package com.intellij.android.designer.model; import com.android.ide.common.rendering.api.ViewInfo; +import com.android.resources.ResourceType; import com.android.sdklib.IAndroidTarget; import com.intellij.android.designer.propertyTable.AttributeProperty; import com.intellij.android.designer.propertyTable.FlagProperty; +import com.intellij.android.designer.propertyTable.editors.ResourceDialog; import com.intellij.designer.model.MetaManager; import com.intellij.designer.model.MetaModel; import com.intellij.designer.model.RadComponent; @@ -33,6 +35,7 @@ import org.jetbrains.android.sdk.AndroidPlatform; import org.jetbrains.android.sdk.AndroidTargetData; import org.jetbrains.android.uipreview.ProjectClassLoader; import org.jetbrains.android.uipreview.RenderServiceFactory; +import org.jetbrains.annotations.NotNull; import java.util.*; @@ -43,12 +46,14 @@ import java.util.*; public class PropertyParser { public static final String KEY = "PROPERTY_PARSER"; + private final Module myModule; private MetaManager myMetaManager; private AttributeDefinitions myDefinitions; private ProjectClassLoader myClassLoader; private Map> myCachedProperties; public PropertyParser(Module module, IAndroidTarget target) throws Exception { + myModule = module; myMetaManager = ViewsMetaManager.getInstance(module.getProject()); myCachedProperties = myMetaManager.getCache(target.hashString()); if (myCachedProperties == null) { @@ -166,4 +171,9 @@ public class PropertyParser { return properties; } + + @NotNull + public ResourceDialog createResourceDialog(ResourceType... types) { + return new ResourceDialog(myModule, types); + } } \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/AttributeProperty.java b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/AttributeProperty.java index 8fbcc73a3caf..356fda1dfcc9 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/AttributeProperty.java +++ b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/AttributeProperty.java @@ -15,8 +15,11 @@ */ package com.intellij.android.designer.propertyTable; +import com.android.resources.ResourceType; +import com.intellij.android.designer.model.PropertyParser; import com.intellij.android.designer.model.RadViewComponent; import com.intellij.android.designer.propertyTable.editors.BooleanEditor; +import com.intellij.android.designer.propertyTable.editors.ResourceDialog; import com.intellij.android.designer.propertyTable.editors.StringsComboEditor; import com.intellij.android.designer.propertyTable.renderers.BooleanRenderer; import com.intellij.designer.model.RadComponent; @@ -26,6 +29,7 @@ import com.intellij.designer.propertyTable.PropertyRenderer; import com.intellij.designer.propertyTable.editors.AbstractTextFieldEditor; import com.intellij.designer.propertyTable.renderers.LabelPropertyRenderer; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.xml.XmlAttribute; @@ -141,12 +145,22 @@ public class AttributeProperty extends Property { private static class TextDialogEditor extends PropertyEditor { private TextFieldWithBrowseButton myTextField; + private RadComponent myRootComponent; public TextDialogEditor() { myTextField = new TextFieldWithBrowseButton(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - // TODO: Auto-generated method stub + PropertyParser parser = myRootComponent.getClientProperty(PropertyParser.KEY); + ResourceDialog dialog = parser + .createResourceDialog(ResourceType.BOOL, ResourceType.COLOR, ResourceType.DIMEN, ResourceType.DRAWABLE, ResourceType.INTEGER, + ResourceType.STRING, ResourceType.ID); + dialog.show(); + + if (dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) { + myTextField.setText(dialog.getResourceName()); + fireValueCommitted(true, false); + } } }); myTextField.getTextField().setBorder(null); @@ -154,7 +168,8 @@ public class AttributeProperty extends Property { @NotNull @Override - public JComponent getComponent(@Nullable RadComponent component, Object value) { + public JComponent getComponent(@NotNull RadComponent rootComponent, @Nullable RadComponent component, Object value) { + myRootComponent = rootComponent; myTextField.setText(value == null ? "" : value.toString()); myTextField.getTextField().setBorder(null); return myTextField; diff --git a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ResourceDialog.java b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ResourceDialog.java new file mode 100644 index 000000000000..03f2b7c91d20 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ResourceDialog.java @@ -0,0 +1,308 @@ +/* + * 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. + * 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.android.designer.propertyTable.editors; + +import com.android.resources.ResourceType; +import com.intellij.designer.componentTree.TreeNodeDescriptor; +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.module.Module; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.Disposer; +import com.intellij.ui.ScrollPaneFactory; +import com.intellij.ui.SimpleTextAttributes; +import com.intellij.ui.TreeSpeedSearch; +import com.intellij.ui.components.JBTabbedPane; +import com.intellij.ui.speedSearch.SpeedSearchUtil; +import com.intellij.ui.treeStructure.Tree; +import com.intellij.util.ArrayUtil; +import com.intellij.util.ui.tree.TreeUtil; +import org.jetbrains.android.facet.AndroidFacet; +import org.jetbrains.android.resourceManagers.ResourceManager; +import org.jetbrains.android.util.AndroidUtils; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeSelectionModel; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.util.*; +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class ResourceDialog extends DialogWrapper implements TreeSelectionListener { + private final JBTabbedPane myContentPanel; + private final ResourcePanel myProjectPanel; + private final ResourcePanel mySystemPanel; + private final Action myNewResourceAction = new AbstractAction("New Resource...") { + @Override + public void actionPerformed(ActionEvent e) { + // TODO: Auto-generated method stub + } + }; + private String myResultResourceName; + + public ResourceDialog(Module module, ResourceType[] types) { + super(module.getProject()); + + setTitle("Resource Dialog"); + getOKAction().setEnabled(false); + + AndroidFacet facet = AndroidFacet.getInstance(module); + myProjectPanel = new ResourcePanel(facet, types, false); + mySystemPanel = new ResourcePanel(facet, types, true); + + myContentPanel = new JBTabbedPane(); + myContentPanel.setPreferredSize(new Dimension(500, 400)); + myContentPanel.addTab("Project", myProjectPanel.myComponent); + myContentPanel.addTab("System", mySystemPanel.myComponent); + + myContentPanel.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + myNewResourceAction.setEnabled(myContentPanel.getSelectedComponent() == myProjectPanel.myComponent); + valueChanged(null); + } + }); + + init(); + } + + @Override + public JComponent getPreferredFocusedComponent() { + return myProjectPanel.myTree; + } + + @Override + protected JComponent createCenterPanel() { + return myContentPanel; + } + + @Override + protected Action[] createLeftSideActions() { + return new Action[]{myNewResourceAction}; + } + + @Override + protected void dispose() { + super.dispose(); + Disposer.dispose(myProjectPanel.myTreeBuilder); + Disposer.dispose(mySystemPanel.myTreeBuilder); + } + + public String getResourceName() { + return myResultResourceName; + } + + @Override + public void valueChanged(TreeSelectionEvent e) { + ResourcePanel panel = myContentPanel.getSelectedComponent() == myProjectPanel.myComponent ? myProjectPanel : mySystemPanel; + Set elements = panel.myTreeBuilder.getSelectedElements(ResourceItem.class); + getOKAction().setEnabled(!elements.isEmpty()); + + if (elements.isEmpty()) { + myResultResourceName = null; + } + else { + String prefix = panel == myProjectPanel ? "@" : "@android:"; + myResultResourceName = prefix + elements.iterator().next().getName(); + } + } + + private class ResourcePanel { + public final Tree myTree; + public final AbstractTreeBuilder myTreeBuilder; + public final JScrollPane myComponent; + + public ResourcePanel(AndroidFacet facet, ResourceType[] types, boolean system) { + myTree = new Tree(); + myTree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode())); + myTree.setScrollsOnExpand(true); + myTree.setRootVisible(false); + myTree.setShowsRootHandles(true); + ToolTipManager.sharedInstance().registerComponent(myTree); + TreeUtil.installActions(myTree); + + ResourceManager manager = facet.getResourceManager(system ? AndroidUtils.SYSTEM_RESOURCE_PACKAGE : null); + ResourceGroup[] groups = new ResourceGroup[types.length]; + + for (int i = 0; i < types.length; i++) { + groups[i] = new ResourceGroup(types[i], manager); + } + + myTreeBuilder = + new AbstractTreeBuilder(myTree, (DefaultTreeModel)myTree.getModel(), new TreeContentProvider(groups), null); + myTreeBuilder.initRootNode(); + + TreeSelectionModel selectionModel = myTree.getSelectionModel(); + selectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + selectionModel.addTreeSelectionListener(ResourceDialog.this); + + myTree.setCellRenderer(new NodeRenderer() { + @Override + protected void doAppend(@NotNull @Nls String fragment, + @NotNull SimpleTextAttributes attributes, + boolean isMainText, + boolean selected) { + SpeedSearchUtil.appendFragmentsForSpeedSearch(myTree, fragment, attributes, selected, this); + } + + @Override + public void doAppend(@NotNull String fragment, @NotNull SimpleTextAttributes attributes, boolean selected) { + SpeedSearchUtil.appendFragmentsForSpeedSearch(myTree, fragment, attributes, selected, this); + } + + @Override + public void doAppend(String fragment, boolean selected) { + SpeedSearchUtil.appendFragmentsForSpeedSearch(myTree, fragment, SimpleTextAttributes.REGULAR_ATTRIBUTES, selected, this); + } + }); + new TreeSpeedSearch(myTree, TreeSpeedSearch.NODE_DESCRIPTOR_TOSTRING, true); + + myComponent = ScrollPaneFactory.createScrollPane(myTree); + } + } + + private static class ResourceGroup { + private List myItems = new ArrayList(); + private final ResourceType myType; + + public ResourceGroup(ResourceType type, ResourceManager manager) { + myType = type; + + Collection resourceNames = manager.getValueResourceNames(type.getName()); + for (String resourceName : resourceNames) { + myItems.add(new ResourceItem(this, resourceName)); + } + + for (String file : manager.getFileResourcesNames(type.getName())) { + myItems.add(new ResourceItem(this, file)); + } + + if (type == ResourceType.ID) { + for (String id : manager.getIds()) { + if (!resourceNames.contains(id)) { + myItems.add(new ResourceItem(this, id)); + } + } + } + + Collections.sort(myItems, new Comparator() { + @Override + public int compare(ResourceItem resource1, ResourceItem resource2) { + return resource1.toString().compareTo(resource2.toString()); + } + }); + } + + public String getName() { + return myType.getName(); + } + + public List getItems() { + return myItems; + } + + @Override + public String toString() { + return myType.getDisplayName(); + } + } + + private static class ResourceItem { + private final ResourceGroup myGroup; + private final String myName; + + public ResourceItem(@NotNull ResourceGroup group, @NotNull String name) { + myGroup = group; + myName = name; + } + + public ResourceGroup getGroup() { + return myGroup; + } + + public String getName() { + return myGroup.getName() + "/" + myName; + } + + @Override + public String toString() { + return myName; + } + } + + private static class TreeContentProvider extends AbstractTreeStructure { + private final Object myTreeRoot = new Object(); + private final ResourceGroup[] myGroups; + + public TreeContentProvider(ResourceGroup[] groups) { + myGroups = groups; + } + + @Override + public Object getRootElement() { + return myTreeRoot; + } + + @Override + public Object[] getChildElements(Object element) { + if (element == myTreeRoot) { + return myGroups; + } + if (element instanceof ResourceGroup) { + ResourceGroup group = (ResourceGroup)element; + return group.getItems().toArray(); + } + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } + + @Override + public Object getParentElement(Object element) { + if (element instanceof ResourceItem) { + ResourceItem resource = (ResourceItem)element; + return resource.getGroup(); + } + return null; + } + + @NotNull + @Override + public NodeDescriptor createDescriptor(Object element, NodeDescriptor parentDescriptor) { + return new TreeNodeDescriptor(parentDescriptor, element, element == null ? null : element.toString()); + } + + @Override + public boolean hasSomethingToCommit() { + return false; + } + + @Override + public void commit() { + } + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/StringsComboEditor.java b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/StringsComboEditor.java index ea286687ea59..8028c3f5e0d4 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/StringsComboEditor.java +++ b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/StringsComboEditor.java @@ -32,7 +32,7 @@ public class StringsComboEditor extends ComboEditor { @NotNull @Override - public JComponent getComponent(@Nullable RadComponent component, Object value) { + public JComponent getComponent(@NotNull RadComponent rootComponent, @Nullable RadComponent component, Object value) { myCombo.setSelectedItem(value); return myCombo; } diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/componentTree/TreeNodeDescriptor.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/componentTree/TreeNodeDescriptor.java index aea7d02606fc..64d5933f982e 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/componentTree/TreeNodeDescriptor.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/componentTree/TreeNodeDescriptor.java @@ -30,6 +30,11 @@ public final class TreeNodeDescriptor extends NodeDescriptor { myElement = element; } + public TreeNodeDescriptor(@Nullable NodeDescriptor parentDescriptor, Object element, String name) { + this(parentDescriptor, element); + myName = name; + } + @Override public boolean update() { return false; diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java index b2aa0f8e20a4..3dda7b490b9f 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java @@ -359,6 +359,10 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider return myDesignerCard.isVisible() ? myGlassLayer : myErrorLabel; } + public RadComponent getRootComponent() { + return myRootComponent; + } + public Object[] getTreeRoots() { return myRootComponent == null ? ArrayUtil.EMPTY_OBJECT_ARRAY : new Object[]{myRootComponent}; } diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/PropertyEditor.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/PropertyEditor.java index 224c84f81e13..905b3fc515bc 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/PropertyEditor.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/PropertyEditor.java @@ -29,7 +29,7 @@ public abstract class PropertyEditor { private final EventListenerList myListenerList = new EventListenerList(); @NotNull - public abstract JComponent getComponent(@Nullable RadComponent component, Object value); + public abstract JComponent getComponent(@NotNull RadComponent rootComponent, @Nullable RadComponent component, Object value); @Nullable public JComponent getPreferredFocusedComponent(@NotNull JComponent component) { diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/PropertyTable.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/PropertyTable.java index 61dafdd06cbc..df45e10bf096 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/PropertyTable.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/PropertyTable.java @@ -821,7 +821,7 @@ public final class PropertyTable extends JBTable implements ComponentSelectionLi @Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { try { - JComponent component = myEditor.getComponent(getCurrentComponent(), getValue((Property)value)); + JComponent component = myEditor.getComponent(myDesigner.getRootComponent(), getCurrentComponent(), getValue((Property)value)); if (component instanceof JComboBox) { component.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE); diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/editors/AbstractTextFieldEditor.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/editors/AbstractTextFieldEditor.java index 7e1c5c73b798..68435e5609ee 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/editors/AbstractTextFieldEditor.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/editors/AbstractTextFieldEditor.java @@ -41,7 +41,7 @@ public abstract class AbstractTextFieldEditor extends PropertyEditor { @NotNull @Override - public JComponent getComponent(@Nullable RadComponent component, Object value) { + public JComponent getComponent(@NotNull RadComponent rootComponent, @Nullable RadComponent component, Object value) { setEditorValue(component, value); myTextField.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 0)); return myTextField; diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/editors/BooleanEditor.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/editors/BooleanEditor.java index 1e181cc43015..d4ac1d7c9bbb 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/editors/BooleanEditor.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/editors/BooleanEditor.java @@ -57,7 +57,7 @@ public class BooleanEditor extends PropertyEditor { } @NotNull - public JComponent getComponent(@Nullable RadComponent component, Object value) { + public JComponent getComponent(@NotNull RadComponent rootComponent, @Nullable RadComponent component, Object value) { try { myInsideChange = true; myCheckBox.setBackground(UIUtil.getTableBackground()); From 09519ee737505a11de0eb907e7931c5992d66032 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Tue, 20 Mar 2012 23:12:53 +0400 Subject: [PATCH 073/106] IDEA-70283 EmptyText should repaint itself --- .../platform-api/src/com/intellij/util/ui/StatusText.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-api/src/com/intellij/util/ui/StatusText.java b/platform/platform-api/src/com/intellij/util/ui/StatusText.java index 2510f91d6940..043b377610bc 100644 --- a/platform/platform-api/src/com/intellij/util/ui/StatusText.java +++ b/platform/platform-api/src/com/intellij/util/ui/StatusText.java @@ -16,7 +16,6 @@ package com.intellij.util.ui; -import com.intellij.ui.ScreenUtil; import com.intellij.ui.SimpleColoredComponent; import com.intellij.ui.SimpleTextAttributes; import com.intellij.ui.UIBundle; @@ -134,6 +133,7 @@ public abstract class StatusText { myText = ""; myComponent.clear(); myClickListeners.clear(); + if (myOwner != null) myOwner.repaint(); return this; } @@ -154,7 +154,7 @@ public abstract class StatusText { myText += text; myComponent.append(text, attrs); myClickListeners.add(listener); - + if (myOwner != null) myOwner.repaint(); return this; } From db3c13a9f282ebe7954593b90ddade498e069456 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 20 Mar 2012 20:43:12 +0100 Subject: [PATCH 074/106] Reorder JARs task dependencies --- build/scripts/layouts.gant | 16 ++++++++++++++++ build/update.xml | 1 + 2 files changed, 17 insertions(+) diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index 75b46b1aa8ef..87ce61b2bf04 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -1,3 +1,18 @@ +/* + * 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. + * 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. + */ import static org.jetbrains.jps.idea.IdeaProjectLoader.guessHome includeTargets << new File("${guessHome(this)}/build/scripts/utils.gant") @@ -468,6 +483,7 @@ def reorder(String home, String targetDirectory) { classpath { pathelement(location: util.output) pathelement(location: "$home/lib/jna.jar") + pathelement(location: "$home/lib/trove4j.jar") } } } diff --git a/build/update.xml b/build/update.xml index 4bdc3584b15c..ebef6ac3cc2b 100644 --- a/build/update.xml +++ b/build/update.xml @@ -51,6 +51,7 @@ + From 87a8ff7033b5400829d6cf0798e31e83b455eddf Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 20 Mar 2012 20:33:06 +0100 Subject: [PATCH 075/106] Cleanup --- .../compiler/ArtifactsCompilerInstance.java | 4 +-- .../intellij/openapi/util/io/FileUtil.java | 25 +++++++++++++------ .../maven/compiler/MavenResourceCompiler.java | 4 +-- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactsCompilerInstance.java b/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactsCompilerInstance.java index e93a68fed095..f719d740ee5f 100644 --- a/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactsCompilerInstance.java +++ b/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactsCompilerInstance.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. @@ -305,7 +305,7 @@ public class ArtifactsCompilerInstance extends GenericCompilerInstance createPathsHashSet() { - return new THashSet(FileUtil.T_HASHING_STRATEGY); + return new THashSet(FileUtil.PATH_HASHING_STRATEGY); } @Override diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java index a8ab9439d248..149dbea1ac0f 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.openapi.util.io; import com.intellij.CommonBundle; @@ -35,6 +34,7 @@ import org.intellij.lang.annotations.RegExp; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.util.rt.FileUtilRt; import java.io.*; import java.lang.reflect.Method; @@ -45,8 +45,21 @@ import java.util.regex.Pattern; @SuppressWarnings({"UtilityClassWithoutPrivateConstructor"}) public class FileUtil extends FileUtilLight { public static final int MEGABYTE = 1024 * 1024; + @NonNls public static final String ASYNC_DELETE_EXTENSION = ".__del__"; + public static final TObjectHashingStrategy PATH_HASHING_STRATEGY; + static { + if (SystemInfo.isFileSystemCaseSensitive) { + @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"}) + final TObjectHashingStrategy canonical = TObjectHashingStrategy.CANONICAL; + PATH_HASHING_STRATEGY = canonical; + } + else { + PATH_HASHING_STRATEGY = CaseInsensitiveStringHashingStrategy.INSTANCE; + } + } + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.io.FileUtil"); private static final ThreadLocal BUFFER = new ThreadLocal() { @@ -57,13 +70,11 @@ public class FileUtil extends FileUtilLight { // do not use channels to copy files larger than 5 Mb because of possible MapFailed error private static final long CHANNELS_COPYING_LIMIT = 5L * MEGABYTE; - private static final int MAX_FILE_DELETE_ATTEMPTS = 10; - public static final Method JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD; - public static final Object/* java.io.FileSystem */ JAVA_IO_FILESYSTEM; - public static final TObjectHashingStrategy T_HASHING_STRATEGY = SystemInfo.isFileSystemCaseSensitive - ? TObjectHashingStrategy.CANONICAL - : CaseInsensitiveStringHashingStrategy.INSTANCE; + private static final int MAX_FILE_DELETE_ATTEMPTS = 10; + + private static final Method JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD; + private static final Object JAVA_IO_FILESYSTEM; // java.io.FileSystem @Nullable public static String getRelativePath(File base, File file) { 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 ca6c14b1ba73..d736683ad70d 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 @@ -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. @@ -96,7 +96,7 @@ public class MavenResourceCompiler implements ClassPostProcessingCompiler { } private static Set createPathsSet() { - return new THashSet(FileUtil.T_HASHING_STRATEGY); + return new THashSet(FileUtil.PATH_HASHING_STRATEGY); } private void saveCache(final Project project) { From 5d54369378e72a7fa19634bece1c7afb26315783 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 20 Mar 2012 20:43:40 +0100 Subject: [PATCH 076/106] util-rt module introduced --- .idea/modules.xml | 1 + .../org/jetbrains/util/rt/FileUtilRt.java} | 36 ++-- .../src/org/jetbrains/util/rt/Logger.java | 159 ++++++++++++++++++ .../org/jetbrains/util/rt/StringUtilRt.java | 124 ++++++++++++++ .../org/jetbrains/util/rt/SystemInfoRt.java | 37 ++++ platform/util-rt/util-rt.iml | 13 ++ .../com/intellij/openapi/util/SystemInfo.java | 22 +-- .../intellij/openapi/util/io/FileUtil.java | 2 +- .../openapi/util/text/StringUtil.java | 104 +----------- platform/util/util.iml | 1 + .../jetbrains/git4idea/ssh/GitSSHService.java | 7 +- .../org/jetbrains/git4idea/ssh/SSHMain.java | 6 +- .../git4idea/util/ScriptGenerator.java | 10 +- 13 files changed, 381 insertions(+), 141 deletions(-) rename platform/{util/src/com/intellij/openapi/util/io/FileUtilLight.java => util-rt/src/org/jetbrains/util/rt/FileUtilRt.java} (84%) create mode 100644 platform/util-rt/src/org/jetbrains/util/rt/Logger.java create mode 100644 platform/util-rt/src/org/jetbrains/util/rt/StringUtilRt.java create mode 100644 platform/util-rt/src/org/jetbrains/util/rt/SystemInfoRt.java create mode 100644 platform/util-rt/util-rt.iml diff --git a/.idea/modules.xml b/.idea/modules.xml index 52a0244f3249..b4b07b103f8d 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -107,6 +107,7 @@ + diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtilLight.java b/platform/util-rt/src/org/jetbrains/util/rt/FileUtilRt.java similarity index 84% rename from platform/util/src/com/intellij/openapi/util/io/FileUtilLight.java rename to platform/util-rt/src/org/jetbrains/util/rt/FileUtilRt.java index ae174b7901d7..b91b1dc48490 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtilLight.java +++ b/platform/util-rt/src/org/jetbrains/util/rt/FileUtilRt.java @@ -13,11 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.openapi.util.io; +package org.jetbrains.util.rt; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -27,14 +24,16 @@ import java.io.*; import java.util.UUID; /** - * This is a light version of {@link FileUtil}. - * It is used by scripts loaded externally and almost independent of IDEA, so add here as few dependencies as possible. + * Stripped-down version of {@code com.intellij.openapi.util.io.FileUtil}. + * Intended to use by external (out-of-IDE-process) runners and helpers so it should not contain any library dependencies. + * + * @since 12.0 */ -public class FileUtilLight { - - private static String ourCanonicalTempPathCache = null; +@SuppressWarnings({"UtilityClassWithoutPrivateConstructor"}) +public class FileUtilRt { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.io.FileUtilLight"); + private static String ourCanonicalTempPathCache = null; @NotNull public static File createTempDirectory(@NotNull @NonNls String prefix, @Nullable @NonNls String suffix) throws IOException { @@ -55,8 +54,7 @@ public class FileUtilLight { } @NotNull - public static File createTempFile(@NonNls final File dir, @NotNull @NonNls String prefix, @Nullable @NonNls String suffix, final boolean create) - throws IOException { + public static File createTempFile(@NonNls File dir, @NotNull @NonNls String prefix, @Nullable @NonNls String suffix, boolean create) throws IOException { return createTempFile(dir, prefix, suffix, create, true); } @@ -122,7 +120,7 @@ public class FileUtilLight { private static File normalizeFile(File temp) throws IOException { final File canonical = temp.getCanonicalFile(); - return SystemInfo.isWindows && canonical.getAbsolutePath().contains(" ") ? temp.getAbsoluteFile() : canonical; + return SystemInfoRt.isWindows && canonical.getAbsolutePath().contains(" ") ? temp.getAbsoluteFile() : canonical; } public static String getTempDirectory() { @@ -136,7 +134,7 @@ public class FileUtilLight { final File file = new File(System.getProperty("java.io.tmpdir")); try { final String canonical = file.getCanonicalPath(); - if (!SystemInfo.isWindows || !canonical.contains(" ")) { + if (!SystemInfoRt.isWindows || !canonical.contains(" ")) { return canonical; } } @@ -169,7 +167,7 @@ public class FileUtilLight { * * @param path the path to use * @param executableFlag new value of executable attribute - * @throws IOException if there is a problem with setting the flag + * @throws java.io.IOException if there is a problem with setting the flag */ public static void setExecutableAttribute(@NotNull String path, boolean executableFlag) throws IOException { final File file = new File(path); @@ -189,14 +187,14 @@ public class FileUtilLight { } @NotNull - public static String loadFile(@NotNull File file, String encoding) throws IOException { + public static String loadFile(@NotNull File file, @Nullable @NonNls String encoding) throws IOException { return loadFile(file, encoding, false); } @NotNull - public static String loadFile(@NotNull File file, String encoding, boolean convertLineSeparators) throws IOException { + public static String loadFile(@NotNull File file, @Nullable @NonNls String encoding, boolean convertLineSeparators) throws IOException { final String s = new String(loadFileText(file, encoding)); - return convertLineSeparators ? StringUtil.convertLineSeparators(s) : s; + return convertLineSeparators ? StringUtilRt.convertLineSeparators(s) : s; } @NotNull @@ -205,8 +203,9 @@ public class FileUtilLight { } @NotNull - public static char[] loadFileText(@NotNull File file, @NonNls String encoding) throws IOException { + public static char[] loadFileText(@NotNull File file, @Nullable @NonNls String encoding) throws IOException { InputStream stream = new FileInputStream(file); + @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") Reader reader = encoding == null ? new InputStreamReader(stream) : new InputStreamReader(stream, encoding); try { return loadText(reader, (int)file.length()); @@ -234,5 +233,4 @@ public class FileUtilLight { return newChars; } } - } diff --git a/platform/util-rt/src/org/jetbrains/util/rt/Logger.java b/platform/util-rt/src/org/jetbrains/util/rt/Logger.java new file mode 100644 index 000000000000..0ccd5c85d579 --- /dev/null +++ b/platform/util-rt/src/org/jetbrains/util/rt/Logger.java @@ -0,0 +1,159 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.util.rt; + +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Method; +import java.util.logging.Level; +import java.util.logging.LogManager; + +/** + * A wrapper which uses either IDE logging subsystem (if available) or java.util.logging. + * + * @since 12.0 + */ +public abstract class Logger { + private interface Factory { + Logger getInstance(@NotNull @NonNls final String category); + } + + private static final Factory ourFactory; + static { + Factory factory; + try { + factory = new IdeaFactory(); + } + catch (Exception e) { + factory = new JavaFactory(); + } + ourFactory = factory; + } + + @NotNull + public static Logger getInstance(@NotNull @NonNls final String category) { + return ourFactory.getInstance(category); + } + + public void info(@Nullable @NonNls final String message) { + info(message, null); + } + + public void info(@NotNull final Throwable t) { + info(t.getMessage(), t); + } + + public void warn(@Nullable @NonNls final String message) { + warn(message, null); + } + + public void warn(@NotNull final Throwable t) { + warn(t.getMessage(), t); + } + + public void error(@Nullable @NonNls final String message) { + error(message, null); + } + + public void error(@NotNull final Throwable t) { + error(t.getMessage(), t); + } + + public abstract void info(@Nullable @NonNls final String message, @Nullable final Throwable t); + public abstract void warn(@Nullable @NonNls final String message, @Nullable final Throwable t); + public abstract void error(@Nullable @NonNls final String message, @Nullable final Throwable t); + + private static class JavaFactory implements Factory { + private final LogManager myManager = LogManager.getLogManager(); + + @Override + public Logger getInstance(@NotNull @NonNls final String category) { + final java.util.logging.Logger logger = myManager.getLogger(category); + return new Logger() { + @Override + public void info(@Nullable @NonNls final String message, @Nullable final Throwable t) { + logger.log(Level.INFO, message, t); + } + + @Override + public void warn(@Nullable @NonNls final String message, @Nullable final Throwable t) { + logger.log(Level.WARNING, message, t); + } + + @Override + public void error(@Nullable @NonNls final String message, @Nullable final Throwable t) { + logger.log(Level.SEVERE, message, t); + } + }; + } + } + + private static class IdeaFactory implements Factory { + private final Method myGetInstance; + private final Method myInfo; + private final Method myWarn; + private final Method myError; + + private IdeaFactory() throws Exception { + final Class loggerClass = Class.forName("com.intellij.openapi.diagnostic.Logger"); + myGetInstance = loggerClass.getMethod("getInstance", String.class); + myGetInstance.setAccessible(true); + myInfo = loggerClass.getMethod("info", String.class, Throwable.class); + myInfo.setAccessible(true); + myWarn = loggerClass.getMethod("warn", String.class, Throwable.class); + myInfo.setAccessible(true); + myError = loggerClass.getMethod("error", String.class, Throwable.class); + myError.setAccessible(true); + } + + @Override + public Logger getInstance(@NotNull @NonNls final String category) { + try { + final Object logger = myGetInstance.invoke(null, category); + return new Logger() { + @Override + public void info(@Nullable @NonNls final String message, @Nullable final Throwable t) { + try { + myInfo.invoke(logger, message, t); + } + catch (Exception ignored) { } + } + + @Override + public void warn(@Nullable @NonNls final String message, @Nullable final Throwable t) { + try { + myWarn.invoke(logger, message, t); + } + catch (Exception ignored) { } + } + + @Override + public void error(@Nullable @NonNls final String message, @Nullable final Throwable t) { + try { + myError.invoke(logger, message, t); + } + catch (Exception ignored) { } + } + }; + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + } +} diff --git a/platform/util-rt/src/org/jetbrains/util/rt/StringUtilRt.java b/platform/util-rt/src/org/jetbrains/util/rt/StringUtilRt.java new file mode 100644 index 000000000000..cc915bc08591 --- /dev/null +++ b/platform/util-rt/src/org/jetbrains/util/rt/StringUtilRt.java @@ -0,0 +1,124 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.util.rt; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Stripped-down version of {@code com.intellij.openapi.util.text.StringUtil}. + * Intended to use by external (out-of-IDE-process) runners and helpers so it should not contain any library dependencies. + * + * @since 12.0 + */ +@SuppressWarnings({"UtilityClassWithoutPrivateConstructor"}) +public class StringUtilRt { + /** + * Converts line separators to "\n" + */ + @NotNull + public static String convertLineSeparators(@NotNull String text) { + return convertLineSeparators(text, false); + } + + @NotNull + public static String convertLineSeparators(@NotNull String text, boolean keepCarriageReturn) { + return convertLineSeparators(text, "\n", null, keepCarriageReturn); + } + + @NotNull + public static String convertLineSeparators(@NotNull String text, @NotNull String newSeparator) { + return convertLineSeparators(text, newSeparator, null); + } + + @NotNull + public static String convertLineSeparators(@NotNull String text, @NotNull String newSeparator, @Nullable int[] offsetsToKeep) { + return convertLineSeparators(text, newSeparator, offsetsToKeep, false); + } + + @NotNull + public static String convertLineSeparators(@NotNull String text, @NotNull String newSeparator, @Nullable int[] offsetsToKeep, + boolean keepCarriageReturn) { + StringBuilder buffer = null; + int intactLength = 0; + final boolean newSeparatorIsSlashN = "\n".equals(newSeparator); + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + if (c == '\n') { + if (!newSeparatorIsSlashN) { + if (buffer == null) { + buffer = new StringBuilder(text.length()); + buffer.append(text, 0, intactLength); + } + buffer.append(newSeparator); + shiftOffsets(offsetsToKeep, buffer.length(), 1, newSeparator.length()); + } + else if (buffer == null) { + intactLength++; + } + else { + buffer.append(c); + } + } + else if (c == '\r') { + boolean followedByLineFeed = i < text.length() - 1 && text.charAt(i + 1) == '\n'; + if (!followedByLineFeed && keepCarriageReturn) { + if (buffer == null) { + intactLength++; + } + else { + buffer.append(c); + } + continue; + } + if (buffer == null) { + buffer = new StringBuilder(text.length()); + buffer.append(text, 0, intactLength); + } + buffer.append(newSeparator); + if (followedByLineFeed) { + //noinspection AssignmentToForLoopParameter + i++; + shiftOffsets(offsetsToKeep, buffer.length(), 2, newSeparator.length()); + } + else { + shiftOffsets(offsetsToKeep, buffer.length(), 1, newSeparator.length()); + } + } + else { + if (buffer == null) { + intactLength++; + } + else { + buffer.append(c); + } + } + } + return buffer == null ? text : buffer.toString(); + } + + private static void shiftOffsets(int[] offsets, int changeOffset, int oldLength, int newLength) { + if (offsets == null) return; + int shift = newLength - oldLength; + if (shift == 0) return; + for (int i = 0; i < offsets.length; i++) { + int offset = offsets[i]; + if (offset >= changeOffset + oldLength) { + offsets[i] += shift; + } + } + } +} diff --git a/platform/util-rt/src/org/jetbrains/util/rt/SystemInfoRt.java b/platform/util-rt/src/org/jetbrains/util/rt/SystemInfoRt.java new file mode 100644 index 000000000000..6b3dd54260af --- /dev/null +++ b/platform/util-rt/src/org/jetbrains/util/rt/SystemInfoRt.java @@ -0,0 +1,37 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.util.rt; + +/** + * Stripped-down version of {@code com.intellij.openapi.util.SystemInfo}. + * Intended to use by external (out-of-IDE-process) runners and helpers so it should not contain any library dependencies. + * + * @since 12.0 + */ +@SuppressWarnings({"HardCodedStringLiteral", "UtilityClassWithoutPrivateConstructor"}) +public class SystemInfoRt { + public static final String OS_NAME = System.getProperty("os.name"); + public static final String OS_VERSION = System.getProperty("os.version").toLowerCase(); + + protected static final String _OS_NAME = OS_NAME.toLowerCase(); + public static final boolean isWindows = _OS_NAME.startsWith("windows"); + public static final boolean isOS2 = _OS_NAME.startsWith("os/2") || _OS_NAME.startsWith("os2"); + public static final boolean isMac = _OS_NAME.startsWith("mac"); + public static final boolean isLinux = _OS_NAME.startsWith("linux"); + public static final boolean isUnix = !isWindows && !isOS2; + + public static final boolean isFileSystemCaseSensitive = !isWindows && !isOS2 && !isMac; +} diff --git a/platform/util-rt/util-rt.iml b/platform/util-rt/util-rt.iml new file mode 100644 index 000000000000..4d3f06e41375 --- /dev/null +++ b/platform/util-rt/util-rt.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/platform/util/src/com/intellij/openapi/util/SystemInfo.java b/platform/util/src/com/intellij/openapi/util/SystemInfo.java index a72b268f74cb..6e13a9f1cb71 100644 --- a/platform/util/src/com/intellij/openapi/util/SystemInfo.java +++ b/platform/util/src/com/intellij/openapi/util/SystemInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 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. @@ -17,22 +17,22 @@ package com.intellij.openapi.util; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.util.rt.SystemInfoRt; import java.io.File; import java.util.List; @SuppressWarnings({"HardCodedStringLiteral", "UtilityClassWithoutPrivateConstructor", "UnusedDeclaration"}) -public class SystemInfo { - public static final String OS_NAME = System.getProperty("os.name"); - public static final String OS_VERSION = System.getProperty("os.version").toLowerCase(); +public class SystemInfo extends SystemInfoRt { + public static final String OS_NAME = SystemInfoRt.OS_NAME; + public static final String OS_VERSION = SystemInfoRt.OS_VERSION; public static final String OS_ARCH = System.getProperty("os.arch"); public static final String JAVA_VERSION = System.getProperty("java.version"); public static final String JAVA_RUNTIME_VERSION = System.getProperty("java.runtime.version"); public static final String ARCH_DATA_MODEL = System.getProperty("sun.arch.data.model"); public static final String SUN_DESKTOP = System.getProperty("sun.desktop", ""); - private static final String _OS_NAME = OS_NAME.toLowerCase(); - public static final boolean isWindows = _OS_NAME.startsWith("windows"); + public static final boolean isWindows = SystemInfoRt.isWindows; public static final boolean isWindowsNT = _OS_NAME.startsWith("windows nt"); public static final boolean isWindows2000 = _OS_NAME.startsWith("windows 2000"); public static final boolean isWindows2003 = _OS_NAME.startsWith("windows 2003"); @@ -40,12 +40,12 @@ public class SystemInfo { public static final boolean isWindowsVista = _OS_NAME.startsWith("windows vista"); public static final boolean isWindows7 = _OS_NAME.startsWith("windows 7"); public static final boolean isWindows9x = _OS_NAME.startsWith("windows 9") || _OS_NAME.startsWith("windows me"); - public static final boolean isOS2 = _OS_NAME.startsWith("os/2") || _OS_NAME.startsWith("os2"); - public static final boolean isMac = _OS_NAME.startsWith("mac"); + public static final boolean isOS2 = SystemInfoRt.isOS2; + public static final boolean isMac = SystemInfoRt.isMac; + public static final boolean isLinux = SystemInfoRt.isLinux; public static final boolean isFreeBSD = _OS_NAME.startsWith("freebsd"); - public static final boolean isLinux = _OS_NAME.startsWith("linux"); public static final boolean isSolaris = _OS_NAME.startsWith("sunos"); - public static final boolean isUnix = !isWindows && !isOS2; + public static final boolean isUnix = SystemInfoRt.isUnix; private static final String _SUN_DESKTOP = SUN_DESKTOP.toLowerCase(); public static final boolean isKDE = _SUN_DESKTOP.contains("kde"); @@ -55,7 +55,7 @@ public class SystemInfo { public static final boolean isMacSystemMenu = isMac && "true".equals(System.getProperty("apple.laf.useScreenMenuBar")); - public static final boolean isFileSystemCaseSensitive = !isWindows && !isOS2 && !isMac; + public static final boolean isFileSystemCaseSensitive = SystemInfoRt.isFileSystemCaseSensitive; public static final boolean areSymLinksSupported = isUnix || isWindows && OS_VERSION.compareTo("6.0") >= 0 && isJavaVersionAtLeast("1.7"); diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java index 149dbea1ac0f..1125485bf795 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java @@ -43,7 +43,7 @@ import java.util.*; import java.util.regex.Pattern; @SuppressWarnings({"UtilityClassWithoutPrivateConstructor"}) -public class FileUtil extends FileUtilLight { +public class FileUtil extends FileUtilRt { public static final int MEGABYTE = 1024 * 1024; @NonNls public static final String ASYNC_DELETE_EXTENSION = ".__del__"; diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index d4c5412e294e..4f7453801e2c 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 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.util.text.LineReader; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.util.rt.StringUtilRt; import java.beans.Introspector; import java.io.ByteArrayInputStream; @@ -37,10 +38,12 @@ import java.util.regex.Pattern; //TeamCity inherits StringUtil: do not add private constructors!!! @SuppressWarnings({"UtilityClassWithoutPrivateConstructor"}) -public class StringUtil { +public class StringUtil extends StringUtilRt { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.text.StringUtil"); + @NonNls private static final String VOWELS = "aeiouy"; - private static final Pattern EOL_SPLIT_PATTERN = Pattern.compile(" *(\r|\n|\r\n)+ *"); + @NonNls private static final Pattern EOL_SPLIT_PATTERN = Pattern.compile(" *(\r|\n|\r\n)+ *"); + public static final NotNullFunction QUOTER = new NotNullFunction() { @NotNull public String fun(String s) { @@ -284,101 +287,6 @@ public class StringUtil { return ""; } - /** - * Converts line separators to "\n" - */ - @NotNull - public static String convertLineSeparators(@NotNull String text) { - return convertLineSeparators(text, false); - } - - @NotNull - public static String convertLineSeparators(@NotNull String text, boolean keepCarriageReturn) { - return convertLineSeparators(text, "\n", null, keepCarriageReturn); - } - - @NotNull - public static String convertLineSeparators(@NotNull String text, @NotNull String newSeparator) { - return convertLineSeparators(text, newSeparator, null); - } - - @NotNull - public static String convertLineSeparators(@NotNull String text, @NotNull String newSeparator, @Nullable int[] offsetsToKeep) { - return convertLineSeparators(text, newSeparator, offsetsToKeep, false); - } - - @NotNull - public static String convertLineSeparators(@NotNull String text, @NotNull String newSeparator, @Nullable int[] offsetsToKeep, - boolean keepCarriageReturn) { - StringBuilder buffer = null; - int intactLength = 0; - final boolean newSeparatorIsSlashN = "\n".equals(newSeparator); - for (int i = 0; i < text.length(); i++) { - char c = text.charAt(i); - if (c == '\n') { - if (!newSeparatorIsSlashN) { - if (buffer == null) { - buffer = new StringBuilder(text.length()); - buffer.append(text, 0, intactLength); - } - buffer.append(newSeparator); - shiftOffsets(offsetsToKeep, buffer.length(), 1, newSeparator.length()); - } - else if (buffer == null) { - intactLength++; - } - else { - buffer.append(c); - } - } - else if (c == '\r') { - boolean followedByLineFeed = i < text.length() - 1 && text.charAt(i + 1) == '\n'; - if (!followedByLineFeed && keepCarriageReturn) { - if (buffer == null) { - intactLength++; - } - else { - buffer.append(c); - } - continue; - } - if (buffer == null) { - buffer = new StringBuilder(text.length()); - buffer.append(text, 0, intactLength); - } - buffer.append(newSeparator); - if (followedByLineFeed) { - i++; - shiftOffsets(offsetsToKeep, buffer.length(), 2, newSeparator.length()); - } - else { - shiftOffsets(offsetsToKeep, buffer.length(), 1, newSeparator.length()); - } - } - else { - if (buffer == null) { - intactLength++; - } - else { - buffer.append(c); - } - } - } - return buffer == null ? text : buffer.toString(); - } - - private static void shiftOffsets(int[] offsets, int changeOffset, int oldLength, int newLength) { - if (offsets == null) return; - int shift = newLength - oldLength; - if (shift == 0) return; - for (int i = 0; i < offsets.length; i++) { - int offset = offsets[i]; - if (offset >= changeOffset + oldLength) { - offsets[i] += shift; - } - } - } - public static int getLineBreakCount(@NotNull CharSequence text) { int count = 0; for (int i = 0; i < text.length(); i++) { diff --git a/platform/util/util.iml b/platform/util/util.iml index 160382d542e7..378b380da974 100644 --- a/platform/util/util.iml +++ b/platform/util/util.iml @@ -15,6 +15,7 @@ + diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHService.java b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHService.java index 389254f3ab8a..430ea6f0b8ba 100644 --- a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHService.java +++ b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHService.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. @@ -15,7 +15,6 @@ */ package org.jetbrains.git4idea.ssh; -import com.intellij.openapi.util.io.FileUtilLight; import com.trilead.ssh2.KnownHosts; import gnu.trove.THashMap; import org.apache.commons.codec.DecoderException; @@ -23,6 +22,7 @@ import org.apache.xmlrpc.XmlRpcClientLite; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.git4idea.util.ScriptGenerator; +import org.jetbrains.util.rt.FileUtilRt; import java.io.File; import java.io.IOException; @@ -66,8 +66,7 @@ public abstract class GitSSHService { public synchronized File getScriptPath() throws IOException { if (myScriptPath == null || !myScriptPath.exists()) { ScriptGenerator generator = new ScriptGenerator(GitSSHHandler.GIT_SSH_PREFIX, SSHMain.class, getTempDir()); - generator.addClasses(XmlRpcClientLite.class, DecoderException.class); - generator.addClasses(KnownHosts.class, FileUtilLight.class); + generator.addClasses(XmlRpcClientLite.class, DecoderException.class, KnownHosts.class, FileUtilRt.class); generator.addResource(SSHMainBundle.class, "/org/jetbrains/git4idea/ssh/SSHMainBundle.properties"); myScriptPath = generator.generate(); } diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMain.java b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMain.java index 85b67ce944ca..bc3737565480 100644 --- a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMain.java +++ b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMain.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. @@ -15,12 +15,12 @@ */ package org.jetbrains.git4idea.ssh; -import com.intellij.openapi.util.io.FileUtilLight; import com.intellij.util.ArrayUtil; import com.trilead.ssh2.*; import com.trilead.ssh2.crypto.PEMDecoder; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; +import org.jetbrains.util.rt.FileUtilRt; import java.io.*; import java.util.*; @@ -302,7 +302,7 @@ public class SSHMain { if (file.exists()) { // if encrypted ask user for passphrase String passphrase = null; - char[] text = FileUtilLight.loadFileText(file); + char[] text = FileUtilRt.loadFileText(file); if (isEncryptedKey(text)) { // need to ask passphrase from user int i; diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/util/ScriptGenerator.java b/plugins/git4idea/src/org/jetbrains/git4idea/util/ScriptGenerator.java index b754a56493e6..a2903ae32095 100644 --- a/plugins/git4idea/src/org/jetbrains/git4idea/util/ScriptGenerator.java +++ b/plugins/git4idea/src/org/jetbrains/git4idea/util/ScriptGenerator.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. @@ -17,11 +17,11 @@ package org.jetbrains.git4idea.util; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.io.FileUtilLight; import com.intellij.util.PathUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; +import org.jetbrains.util.rt.FileUtilRt; import java.io.File; import java.io.FileWriter; @@ -149,8 +149,8 @@ public class ScriptGenerator { */ @SuppressWarnings({"HardCodedStringLiteral"}) public File generate() throws IOException { - File scriptPath = myTempDir != null ? FileUtilLight.createTempFile(myTempDir, myPrefix, SCRIPT_EXT, true) - : FileUtilLight.createTempFile(myPrefix, SCRIPT_EXT); + File scriptPath = myTempDir != null ? FileUtilRt.createTempFile(myTempDir, myPrefix, SCRIPT_EXT, true) + : FileUtilRt.createTempFile(myPrefix, SCRIPT_EXT); scriptPath.deleteOnExit(); PrintWriter out = new PrintWriter(new FileWriter(scriptPath)); try { @@ -172,7 +172,7 @@ public class ScriptGenerator { finally { out.close(); } - FileUtilLight.setExecutableAttribute(scriptPath.getPath(), true); + FileUtilRt.setExecutableAttribute(scriptPath.getPath(), true); return scriptPath; } From 6073b072f87fed0f782654051675162d71ebd7cb Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 20 Mar 2012 21:38:15 +0100 Subject: [PATCH 077/106] Fix layouts --- build/scripts/layouts.gant | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index 87ce61b2bf04..bb5439064698 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -115,7 +115,11 @@ def layoutFull(String home, String targetDirectory, String patchedDescriptorDir dir("rt") { fileset(dir: "${home}/lib/rt", includesfile: "${home}/lib/rt/required_for_dist.txt") } - jar("util.jar") { module("util") } + + jar("util.jar") { + module("util") + module("util-rt") + } jar("openapi.jar") { openapiModules.each { module it} From 3c504588c1cead47a09b67622736de3316ee16d9 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 20 Mar 2012 22:23:51 +0100 Subject: [PATCH 078/106] Fix Maven runtime dependencies --- .../org/jetbrains/idea/maven/server/MavenServerManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java index c8d10de2385e..7f5b8f685c76 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.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. @@ -58,6 +58,7 @@ import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.utils.MavenLog; import org.jetbrains.idea.maven.utils.MavenProgressIndicator; import org.jetbrains.idea.maven.utils.MavenUtil; +import org.jetbrains.util.rt.SystemInfoRt; import java.io.File; import java.nio.charset.Charset; @@ -172,6 +173,7 @@ public class MavenServerManager extends RemoteObjectWrapper { final ArrayList classPath = new ArrayList(); ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(NotNull.class), classPath); ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(StringUtil.class), classPath); + ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(SystemInfoRt.class), classPath); ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(THashSet.class), classPath); ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(Element.class), classPath); ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(Query.class), classPath); From 87059f0d4ad4c67fe9dc92ff75e8fcff4f94e5d6 Mon Sep 17 00:00:00 2001 From: Evgeny Zakrevsky Date: Wed, 21 Mar 2012 00:24:17 +0400 Subject: [PATCH 079/106] Some UI fixes. [reviewed by Konstantin Bulenkov] --- .../src/com/intellij/util/ui/FormBuilder.java | 6 ++--- .../vcs/history/FileHistoryPanelImpl.java | 2 +- .../dialogs/browser/MkdirOptionsDialog.form | 27 +++++++------------ .../browser/MkdirOptionsDialogOld.form | 27 +++++++------------ 4 files changed, 24 insertions(+), 38 deletions(-) diff --git a/platform/util/src/com/intellij/util/ui/FormBuilder.java b/platform/util/src/com/intellij/util/ui/FormBuilder.java index f5437de681c5..e7065dfd71a7 100644 --- a/platform/util/src/com/intellij/util/ui/FormBuilder.java +++ b/platform/util/src/com/intellij/util/ui/FormBuilder.java @@ -52,15 +52,15 @@ public class FormBuilder { return new FormBuilder(); } - public FormBuilder addLabeledComponent(@Nullable JLabel label, JComponent component) { + public FormBuilder addLabeledComponent(@Nullable JComponent label, JComponent component) { return addLabeledComponent(label, component, myVerticalGap, false); } - public FormBuilder addLabeledComponent(@Nullable JLabel label, JComponent component, final int topInset) { + public FormBuilder addLabeledComponent(@Nullable JComponent label, JComponent component, final int topInset) { return addLabeledComponent(label, component, topInset, false); } - public FormBuilder addLabeledComponent(@Nullable JLabel label, JComponent component, boolean labelOnTop) { + public FormBuilder addLabeledComponent(@Nullable JComponent label, JComponent component, boolean labelOnTop) { return addLabeledComponent(label, component, myVerticalGap, labelOnTop); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java index 1f9bba3fa3b1..008a1ad75491 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java @@ -676,7 +676,7 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton { final JLabel commentLabel = new JLabel(COMMIT_MESSAGE_TITLE + ":") { @Override public Dimension getPreferredSize() { - return new Dimension(super.getWidth(), 29); + return super.getPreferredSize(); } }; commentGroup.add(commentLabel, BorderLayout.NORTH); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/browser/MkdirOptionsDialog.form b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/browser/MkdirOptionsDialog.form index 7717abaf507b..74d271602149 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/browser/MkdirOptionsDialog.form +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/browser/MkdirOptionsDialog.form @@ -1,8 +1,9 @@
- + + - + @@ -10,7 +11,6 @@ - @@ -18,8 +18,7 @@ - - + @@ -28,7 +27,6 @@ - @@ -36,8 +34,7 @@ - - + @@ -46,17 +43,15 @@ - - + - + - - + @@ -74,8 +69,7 @@ - - + @@ -83,8 +77,7 @@ - - + diff --git a/plugins/svn4ideaOld/src/org/jetbrains/idea/svn/dialogs/browser/MkdirOptionsDialogOld.form b/plugins/svn4ideaOld/src/org/jetbrains/idea/svn/dialogs/browser/MkdirOptionsDialogOld.form index 4db89de78a79..55c8981b8400 100644 --- a/plugins/svn4ideaOld/src/org/jetbrains/idea/svn/dialogs/browser/MkdirOptionsDialogOld.form +++ b/plugins/svn4ideaOld/src/org/jetbrains/idea/svn/dialogs/browser/MkdirOptionsDialogOld.form @@ -1,8 +1,9 @@ - + + - + @@ -10,7 +11,6 @@ - @@ -18,8 +18,7 @@ - - + @@ -28,7 +27,6 @@ - @@ -36,8 +34,7 @@ - - + @@ -46,17 +43,15 @@ - - + - + - - + @@ -74,8 +69,7 @@ - - + @@ -83,8 +77,7 @@ - - + From ac2eca6b52255702231e57d428bc1f9e903802b5 Mon Sep 17 00:00:00 2001 From: Evgeny Zakrevsky Date: Wed, 21 Mar 2012 00:22:19 +0400 Subject: [PATCH 080/106] IDEA-82753 Move Up and Remove buttons are always disabled in Import Layout config. [reviewed by Konstantin Bulenkov] --- .../application/options/CodeStyleImportsPanel.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/java/java-impl/src/com/intellij/application/options/CodeStyleImportsPanel.java b/java/java-impl/src/com/intellij/application/options/CodeStyleImportsPanel.java index 083ff43a44db..8a042c1a6ae0 100644 --- a/java/java-impl/src/com/intellij/application/options/CodeStyleImportsPanel.java +++ b/java/java-impl/src/com/intellij/application/options/CodeStyleImportsPanel.java @@ -29,6 +29,8 @@ import com.intellij.util.ui.UIUtil; import javax.swing.*; import javax.swing.event.CellEditorListener; import javax.swing.event.ChangeEvent; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellEditor; import javax.swing.table.TableColumn; @@ -291,6 +293,7 @@ public class CodeStyleImportsPanel extends JPanel { PackageEntry entry = new PackageEntry(false,"", true); myImportLayoutList.insertEntryAt(entry, selected); refreshTableModel(selected, myImportLayoutTable); + updateButtons(); } private static void refreshTableModel(int selectedRow, JBTable table) { @@ -323,6 +326,7 @@ public class CodeStyleImportsPanel extends JPanel { AbstractTableModel model = (AbstractTableModel)myImportLayoutTable.getModel(); model.fireTableRowsInserted(selected, selected); myImportLayoutTable.setRowSelectionInterval(selected, selected); + updateButtons(); } private void removeEntryFromImportLayouts() { @@ -343,6 +347,7 @@ public class CodeStyleImportsPanel extends JPanel { if(selected >= 0) { myImportLayoutTable.setRowSelectionInterval(selected, selected); } + updateButtons(); } private void removeEntryFromPackages() { @@ -358,6 +363,7 @@ public class CodeStyleImportsPanel extends JPanel { if(selected >= 0) { myPackageTable.setRowSelectionInterval(selected, selected); } + updateButtons(); } private void moveRowUp() { @@ -374,6 +380,7 @@ public class CodeStyleImportsPanel extends JPanel { AbstractTableModel model = (AbstractTableModel)myImportLayoutTable.getModel(); model.fireTableRowsUpdated(selected-1, selected); myImportLayoutTable.setRowSelectionInterval(selected-1, selected-1); + updateButtons(); } private void moveRowDown() { @@ -390,6 +397,7 @@ public class CodeStyleImportsPanel extends JPanel { AbstractTableModel model = (AbstractTableModel)myImportLayoutTable.getModel(); model.fireTableRowsUpdated(selected, selected+1); myImportLayoutTable.setRowSelectionInterval(selected+1, selected+1); + updateButtons(); } private JBTable createTableForPackageEntries(final PackageEntryTable packageTable) { @@ -473,6 +481,12 @@ public class CodeStyleImportsPanel extends JPanel { final JBTable result = new JBTable(dataModel); result.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); resizeColumns(packageTable, result); + result.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + updateButtons(); + } + }); TableCellEditor editor = result.getDefaultEditor(String.class); if (editor instanceof DefaultCellEditor) { From 9aaa9a6aa315a58d8a385bd04b3ae614a58516bf Mon Sep 17 00:00:00 2001 From: Evgeny Zakrevsky Date: Wed, 21 Mar 2012 00:21:54 +0400 Subject: [PATCH 081/106] IDEA-82047 Search action by name in Add Actions to Quick Lists dialog & IDEA-82050 Add action by doubleclick Add Actions to Quick Lists. [reviewed by Konstantin Bulenkov] --- .../keymap/impl/ui/ChooseActionsDialog.java | 204 +++++++++++++++++- .../openapi/keymap/impl/ui/KeymapPanel.java | 65 +++--- 2 files changed, 239 insertions(+), 30 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ChooseActionsDialog.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ChooseActionsDialog.java index 2a668c4cb46c..072aea54019c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ChooseActionsDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ChooseActionsDialog.java @@ -19,41 +19,85 @@ */ package com.intellij.openapi.keymap.impl.ui; +import com.intellij.ide.CommonActionsManager; +import com.intellij.ide.TreeExpander; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.QuickList; +import com.intellij.openapi.keymap.KeyMapBundle; import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.util.IconLoader; +import com.intellij.packageDependencies.ui.TreeExpansionMonitor; +import com.intellij.ui.DocumentAdapter; +import com.intellij.ui.FilterComponent; +import com.intellij.util.Alarm; import com.intellij.util.ArrayUtil; +import com.intellij.util.IJSwingUtilities; +import com.intellij.util.ui.FormBuilder; +import com.intellij.util.ui.UIUtil; +import com.intellij.util.ui.tree.TreeUtil; import javax.swing.*; +import javax.swing.border.EmptyBorder; +import javax.swing.event.DocumentEvent; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.util.ArrayList; public class ChooseActionsDialog extends DialogWrapper { private final ActionsTree myActionsTree; + private FilterComponent myFilterComponent; + private TreeExpansionMonitor myTreeExpansionMonitor; + private Keymap myKeymap; + private QuickList[] myQuicklists; + private JBPopup myPopup; public ChooseActionsDialog(Component parent, Keymap keymap, QuickList[] quicklists) { super(parent, true); + myKeymap = keymap; + myQuicklists = quicklists; myActionsTree = new ActionsTree(); myActionsTree.reset(keymap, quicklists); myActionsTree.getTree().getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); + myActionsTree.getTree().addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + doOKAction(); + } + } + }); + + myTreeExpansionMonitor = TreeExpansionMonitor.install(myActionsTree.getTree()); + setTitle("Add Actions to Quick List"); init(); } + @Override + protected JComponent createNorthPanel() { + return createToolbarPanel(); + } + @Override protected JComponent createCenterPanel() { JPanel panel = new JPanel(new BorderLayout()); panel.add(myActionsTree.getComponent()); panel.setPreferredSize(new Dimension(400, 500)); - + return panel; } - + public String[] getTreeSelectedActionIds() { TreePath[] paths = myActionsTree.getTree().getSelectionPaths(); if (paths == null) return ArrayUtil.EMPTY_STRING_ARRAY; @@ -74,4 +118,160 @@ public class ChooseActionsDialog extends DialogWrapper { } return ArrayUtil.toStringArray(actions); } + + private JPanel createToolbarPanel() { + final JPanel panel = new JPanel(new BorderLayout()); + DefaultActionGroup group = new DefaultActionGroup(); + final JComponent toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true).getComponent(); + final CommonActionsManager commonActionsManager = CommonActionsManager.getInstance(); + final TreeExpander treeExpander = new TreeExpander() { + public void expandAll() { + TreeUtil.expandAll(myActionsTree.getTree()); + } + + public boolean canExpand() { + return true; + } + + public void collapseAll() { + TreeUtil.collapseAll(myActionsTree.getTree(), 0); + } + + public boolean canCollapse() { + return true; + } + }; + group.add(commonActionsManager.createExpandAllAction(treeExpander, myActionsTree.getTree())); + group.add(commonActionsManager.createCollapseAllAction(treeExpander, myActionsTree.getTree())); + + panel.add(toolbar, BorderLayout.WEST); + group = new DefaultActionGroup(); + final JComponent searchToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true).getComponent(); + final Alarm alarm = new Alarm(); + myFilterComponent = new FilterComponent("KEYMAP_IN_QUICK_LISTS", 5) { + public void filter() { + alarm.cancelAllRequests(); + alarm.addRequest(new Runnable() { + public void run() { + if (!myFilterComponent.isShowing()) return; + if (!myTreeExpansionMonitor.isFreeze()) myTreeExpansionMonitor.freeze(); + final String filter = getFilter(); + myActionsTree.filter(filter, myQuicklists); + final JTree tree = myActionsTree.getTree(); + TreeUtil.expandAll(tree); + if (filter == null || filter.length() == 0) { + TreeUtil.collapseAll(tree, 0); + myTreeExpansionMonitor.restore(); + } + } + }, 300); + } + }; + myFilterComponent.reset(); + + panel.add(myFilterComponent, BorderLayout.CENTER); + + group.add(new AnAction(KeyMapBundle.message("filter.shortcut.action.text"), + KeyMapBundle.message("filter.shortcut.action.text"), + IconLoader.getIcon("/ant/shortcutFilter.png")) { + public void actionPerformed(AnActionEvent e) { + myFilterComponent.reset(); + if (myPopup == null || myPopup.getContent() == null) { + myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(createFilteringPanel(), null) + .setRequestFocus(true) + .setTitle(KeyMapBundle.message("filter.settings.popup.title")) + .setMovable(true) + .createPopup(); + } + myPopup.showUnderneathOf(searchToolbar); + } + }); + group.add(new AnAction(KeyMapBundle.message("filter.clear.action.text"), + KeyMapBundle.message("filter.clear.action.text"), IconLoader.getIcon("/actions/gc.png")) { + public void actionPerformed(AnActionEvent e) { + myActionsTree.filter(null, myQuicklists); //clear filtering + TreeUtil.collapseAll(myActionsTree.getTree(), 0); + myTreeExpansionMonitor.restore(); + } + }); + + panel.add(searchToolbar, BorderLayout.EAST); + return panel; + } + + private void filterTreeByShortcut(final ShortcutTextField firstShortcut, + final JCheckBox enable2Shortcut, + final ShortcutTextField secondShortcut) { + final KeyStroke keyStroke = firstShortcut.getKeyStroke(); + if (keyStroke != null) { + if (!myTreeExpansionMonitor.isFreeze()) myTreeExpansionMonitor.freeze(); + myActionsTree.filterTree(new KeyboardShortcut(keyStroke, enable2Shortcut.isSelected() ? secondShortcut.getKeyStroke() : null), + myQuicklists); + final JTree tree = myActionsTree.getTree(); + TreeUtil.expandAll(tree); + } + } + + private JPanel createFilteringPanel() { + myActionsTree.reset(myKeymap, myQuicklists); + + final JLabel firstLabel = new JLabel(KeyMapBundle.message("filter.first.stroke.input")); + final JCheckBox enable2Shortcut = new JCheckBox(KeyMapBundle.message("filter.second.stroke.input")); + final ShortcutTextField firstShortcut = new ShortcutTextField(); + firstShortcut.setColumns(10); + final ShortcutTextField secondShortcut = new ShortcutTextField(); + secondShortcut.setColumns(10); + + enable2Shortcut.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + secondShortcut.setEnabled(enable2Shortcut.isSelected()); + if (enable2Shortcut.isSelected()) { + secondShortcut.requestFocusInWindow(); + } + } + }); + + firstShortcut.getDocument().addDocumentListener(new DocumentAdapter() { + protected void textChanged(DocumentEvent e) { + filterTreeByShortcut(firstShortcut, enable2Shortcut, secondShortcut); + } + }); + + secondShortcut.getDocument().addDocumentListener(new DocumentAdapter() { + protected void textChanged(DocumentEvent e) { + filterTreeByShortcut(firstShortcut, enable2Shortcut, secondShortcut); + } + }); + + IJSwingUtilities.adjustComponentsOnMac(firstLabel, firstShortcut); + JPanel filterComponent = FormBuilder.createFormBuilder() + .addLabeledComponent(firstLabel, firstShortcut, true) + .addComponent(enable2Shortcut) + .setVerticalGap(0) + .setIndent(5) + .addComponent(secondShortcut) + .getPanel(); + + filterComponent.setBorder(new EmptyBorder(UIUtil.PANEL_SMALL_INSETS)); + + enable2Shortcut.setSelected(false); + secondShortcut.setEnabled(false); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + firstShortcut.requestFocus(); + } + }); + return filterComponent; + } + + + public void dispose() { + super.dispose(); + if (myPopup != null && myPopup.isVisible()) { + myPopup.cancel(); + } + if (myFilterComponent != null) { + myFilterComponent.dispose(); + } + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java index a53ec8bed25b..6d223a185ef1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java @@ -50,12 +50,16 @@ import com.intellij.ui.DocumentAdapter; import com.intellij.ui.FilterComponent; import com.intellij.ui.awt.RelativePoint; import com.intellij.util.Alarm; +import com.intellij.util.IJSwingUtilities; import com.intellij.util.containers.HashMap; +import com.intellij.util.ui.FormBuilder; +import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import javax.swing.*; +import javax.swing.border.EmptyBorder; import javax.swing.event.DocumentEvent; import java.awt.*; import java.awt.event.*; @@ -119,7 +123,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi if (shortcuts != null) { for (Shortcut shortcut : shortcuts) { - impl.removeShortcut(actionId, shortcut); + impl.removeShortcut(actionId, shortcut); impl.addShortcut(newActionId, shortcut); } } @@ -270,7 +274,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi importButton.setMargin(insets); panel.add(importButton,gc); - + } @@ -376,7 +380,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi }; group.add(commonActionsManager.createExpandAllAction(treeExpander, myActionsTree.getTree())); group.add(commonActionsManager.createCollapseAllAction(treeExpander, myActionsTree.getTree())); - + group.add(new AnAction("Edit Shortcut", "Edit Shortcut", IconLoader.getIcon("/actions/properties.png")) { { registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)), myActionsTree.getTree()); @@ -459,40 +463,45 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi private JPanel createFilteringPanel() { myActionsTree.reset(getSelectedKeymap(), getCurrentQuickListIds()); - JPanel filterComponent = new JPanel(new GridBagLayout()); - filterComponent.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); + final JLabel firstLabel = new JLabel(KeyMapBundle.message("filter.first.stroke.input")); + final JCheckBox enable2Shortcut = new JCheckBox(KeyMapBundle.message("filter.second.stroke.input")); final ShortcutTextField firstShortcut = new ShortcutTextField(); final ShortcutTextField secondShortcut = new ShortcutTextField(); - final JCheckBox enable2Shortcut = new JCheckBox(KeyMapBundle.message("filter.enable.second.stroke.checkbox")); - firstShortcut.getDocument().addDocumentListener(new DocumentAdapter() { - protected void textChanged(DocumentEvent e) { - filterTreeByShortcut(firstShortcut, enable2Shortcut, secondShortcut); - } - }); - secondShortcut.getDocument().addDocumentListener(new DocumentAdapter() { - protected void textChanged(DocumentEvent e) { - filterTreeByShortcut(firstShortcut, enable2Shortcut, secondShortcut); - } - }); - final JLabel firstLabel = new JLabel(KeyMapBundle.message("filter.first.stroke.input")); - final JLabel secondLabel = new JLabel(KeyMapBundle.message("filter.second.stroke.input")); - filterComponent.add(firstLabel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1, 0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(5,2,0,0),0,0)); - filterComponent.add(firstShortcut, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1, 0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0,2,0,0),0,0)); + enable2Shortcut.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { secondShortcut.setEnabled(enable2Shortcut.isSelected()); - secondLabel.setEnabled(enable2Shortcut.isSelected()); if (enable2Shortcut.isSelected()){ secondShortcut.requestFocusInWindow(); } } }); - filterComponent.add(enable2Shortcut, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1, 0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0),0,0)); - filterComponent.add(secondLabel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1, 0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0,2,0,0),0,0)); - filterComponent.add(secondShortcut, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1, 0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0,2,0,0),0,0)); + + firstShortcut.getDocument().addDocumentListener(new DocumentAdapter() { + protected void textChanged(DocumentEvent e) { + filterTreeByShortcut(firstShortcut, enable2Shortcut, secondShortcut); + } + }); + + secondShortcut.getDocument().addDocumentListener(new DocumentAdapter() { + protected void textChanged(DocumentEvent e) { + filterTreeByShortcut(firstShortcut, enable2Shortcut, secondShortcut); + } + }); + + IJSwingUtilities.adjustComponentsOnMac(firstLabel, firstShortcut); + JPanel filterComponent = FormBuilder.createFormBuilder() + .addLabeledComponent(firstLabel, firstShortcut, true) + .addComponent(enable2Shortcut) + .setVerticalGap(0) + .setIndent(5) + .addComponent(secondShortcut) + .getPanel(); + + filterComponent.setBorder(new EmptyBorder(UIUtil.PANEL_SMALL_INSETS)); + enable2Shortcut.setSelected(false); - secondLabel.setEnabled(false); secondShortcut.setEnabled(false); SwingUtilities.invokeLater(new Runnable() { public void run() { @@ -938,7 +947,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi DefaultActionGroup group = new DefaultActionGroup(); final Shortcut[] shortcuts = mySelectedKeymap.getShortcuts(actionId); - + group.add(new AnAction("Add Keyboard Shortcut") { @Override public void actionPerformed(AnActionEvent e) { @@ -953,7 +962,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi addKeyboardShortcut(firstKeyboard); } }); - + group.add(new AnAction("Add Mouse Shortcut") { @Override public void actionPerformed(AnActionEvent e) { @@ -991,7 +1000,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi dataContext, JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, true); - + if (e instanceof MouseEvent) { popup.show(new RelativePoint((MouseEvent)e)); } From 52031cedddb86292ef7ad6624fef59a951261c51 Mon Sep 17 00:00:00 2001 From: Evgeny Zakrevsky Date: Wed, 21 Mar 2012 00:21:36 +0400 Subject: [PATCH 082/106] Correct size for ScopeChooserCombo. [reviewed by Konstantin Bulenkov] --- .../lang-impl/src/com/intellij/find/impl/FindDialog.java | 7 +------ .../ide/util/scopeChooser/ScopeChooserCombo.java | 9 +++++++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java index af422a858909..1a7796276ff2 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java @@ -804,12 +804,7 @@ public class FindDialog extends DialogWrapper { gbConstraints.gridx++; gbConstraints.weightx = 1; gbConstraints.gridwidth = 2; - myScopeCombo = new ScopeChooserCombo(myProject, true, true, FindSettings.getInstance().getDefaultScopeName()) { - @Override - public Dimension getMinimumSize() { - return new Dimension(200, super.getMinimumSize().height); - } - }; + myScopeCombo = new ScopeChooserCombo(myProject, true, true, FindSettings.getInstance().getDefaultScopeName()); Disposer.register(myDisposable, myScopeCombo); scopePanel.add(myScopeCombo, gbConstraints); diff --git a/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeChooserCombo.java b/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeChooserCombo.java index 7dcd14a4b40b..48b78e2bee88 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeChooserCombo.java +++ b/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeChooserCombo.java @@ -190,6 +190,15 @@ public class ScopeChooserCombo extends ComboboxWithBrowseButton implements Dispo return new Dimension(Math.min(400, preferredSize.width), preferredSize.height); } + @Override + public Dimension getMinimumSize() { + if (isMinimumSizeSet()) { + return super.getMinimumSize(); + } + Dimension minimumSize = super.getMinimumSize(); + return new Dimension(Math.min(200, minimumSize.width), minimumSize.height); + } + private void createPredefinedScopeDescriptors(DefaultComboBoxModel model) { for (SearchScope scope : getPredefinedScopes(myProject, DataManager.getInstance().getDataContext(), mySuggestSearchInLibs, myPrevSearchFiles, true, true)) { model.addElement(new ScopeDescriptor(scope)); From 484c88c7bc807d95a72d25e604545054873ceb46 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 20 Mar 2012 23:44:44 +0100 Subject: [PATCH 083/106] Fix compile server runtime dependencies --- .../jps/server/ClasspathBootstrap.java | 6 ++--- .../src/org/jetbrains/util/rt/Logger.java | 22 ++++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/server/ClasspathBootstrap.java b/jps/jps-builders/src/org/jetbrains/jps/server/ClasspathBootstrap.java index 65ba0c22b12d..e8d70f0e3f1b 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/server/ClasspathBootstrap.java +++ b/jps/jps-builders/src/org/jetbrains/jps/server/ClasspathBootstrap.java @@ -23,13 +23,13 @@ import com.intellij.uiDesigner.compiler.AlienFormFileException; import com.intellij.uiDesigner.core.GridConstraints; import com.jgoodies.forms.layout.CellConstraints; import com.sun.jna.Pointer; -import com.sun.jna.platform.FileMonitor; import gnu.trove.TIntHash; import net.n3.nanoxml.IXMLBuilder; import org.codehaus.groovy.GroovyException; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.MacroExpander; import org.jetbrains.jps.javac.JavacServer; +import org.jetbrains.util.rt.FileUtilRt; import org.objectweb.asm.ClassWriter; import javax.tools.*; @@ -91,10 +91,10 @@ public class ClasspathBootstrap { cp.add(getResourcePath(com.google.protobuf.Message.class)); // protobuf cp.add(getResourcePath(org.jboss.netty.bootstrap.Bootstrap.class)); // netty cp.add(getResourcePath(TIntHash.class)); // trove + cp.add(getResourcePath(FileUtilRt.class)); // util-rt module cp.add(getResourcePath(FileUtil.class)); // util module cp.add(getResourcePath(Pointer.class)); // jna.jar cp.add(getResourcePath(CacheBuilder.class)); // guava - cp.add(getResourcePath(FileMonitor.class)); // jna-utils.jar cp.add(getResourcePath(ClassWriter.class)); // asm cp.add(getResourcePath(org.objectweb.asm.commons.EmptyVisitor.class)); // asm-commons cp.add(getResourcePath(MacroExpander.class)); // jps-model @@ -136,10 +136,10 @@ public class ClasspathBootstrap { cp.add(getResourcePath(com.google.protobuf.Message.class)); // protobuf cp.add(getResourcePath(org.jboss.netty.bootstrap.Bootstrap.class)); // netty cp.add(getResourcePath(TIntHash.class)); // trove + cp.add(getResourcePath(FileUtilRt.class)); // util-rt module cp.add(getResourcePath(FileUtil.class)); // util module cp.add(getResourcePath(Pointer.class)); // jna.jar cp.add(getResourcePath(CacheBuilder.class)); // guava - cp.add(getResourcePath(FileMonitor.class)); // jna-utils.jar cp.add(getResourcePath(org.jdom.input.SAXBuilder.class)); // jdom final Class optimizedFileManagerClass = getOptimizedFileManagerClass(); diff --git a/platform/util-rt/src/org/jetbrains/util/rt/Logger.java b/platform/util-rt/src/org/jetbrains/util/rt/Logger.java index 0ccd5c85d579..58fc8da74727 100644 --- a/platform/util-rt/src/org/jetbrains/util/rt/Logger.java +++ b/platform/util-rt/src/org/jetbrains/util/rt/Logger.java @@ -33,21 +33,23 @@ public abstract class Logger { Logger getInstance(@NotNull @NonNls final String category); } - private static final Factory ourFactory; - static { - Factory factory; - try { - factory = new IdeaFactory(); + private static Factory ourFactory; + + private synchronized static Factory getFactory() { + if (ourFactory == null) { + try { + ourFactory = new IdeaFactory(); + } + catch (Throwable t) { + ourFactory = new JavaFactory(); + } } - catch (Exception e) { - factory = new JavaFactory(); - } - ourFactory = factory; + return ourFactory; } @NotNull public static Logger getInstance(@NotNull @NonNls final String category) { - return ourFactory.getInstance(category); + return getFactory().getInstance(category); } public void info(@Nullable @NonNls final String message) { From 9555e57bff995b30ebba37107a66630eca147784 Mon Sep 17 00:00:00 2001 From: "kirill.safonov" Date: Tue, 20 Mar 2012 17:51:10 +0400 Subject: [PATCH 084/106] all capitals in dialog title --- .../idea/copyright/actions/GenerateCopyrightAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/GenerateCopyrightAction.java b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/GenerateCopyrightAction.java index e5f1a32b138a..9e58609dca9f 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/GenerateCopyrightAction.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/GenerateCopyrightAction.java @@ -73,7 +73,7 @@ public class GenerateCopyrightAction extends AnAction PsiFile file = getFile(context, project); assert file != null; if (CopyrightManager.getInstance(project).getCopyrightOptions(file) == null) { - if (Messages.showOkCancelDialog(project, "No copyright configured for current file. Would you like to edit copyright settings?", "No copyright available", Messages.getQuestionIcon()) == DialogWrapper.OK_EXIT_CODE) { + if (Messages.showOkCancelDialog(project, "No copyright configured for current file. Would you like to edit copyright settings?", "No Copyright Available", Messages.getQuestionIcon()) == DialogWrapper.OK_EXIT_CODE) { ShowSettingsUtil.getInstance().showSettingsDialog(project, new CopyrightProjectConfigurable(project).getDisplayName()); } else { return; From 6a7dd8b435d9d536b35e8568a0bfcb74dd15958a Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 21 Mar 2012 08:34:54 +0100 Subject: [PATCH 085/106] invalidate stub-based psi on stub replacement --- .../com/intellij/psi/StubAstSwitchTest.groovy | 26 ++++++++++++++++--- .../extapi/psi/StubBasedPsiElementBase.java | 8 +++--- .../intellij/psi/impl/source/PsiFileImpl.java | 14 ++++++++++ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy b/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy index a996ce26aecf..3ad83a0f32bd 100644 --- a/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy +++ b/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy @@ -17,7 +17,9 @@ package com.intellij.psi import com.intellij.openapi.application.ApplicationManager import com.intellij.psi.impl.source.PsiFileImpl +import com.intellij.psi.util.PsiTreeUtil import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import com.intellij.reference.SoftReference /** * @author peter @@ -30,13 +32,29 @@ class StubAstSwitchTest extends LightCodeInsightFixtureTestCase { def cls = ((PsiJavaFile)file).classes[0] assert file.stub + def oldCount = psiManager.modificationTracker.javaStructureModificationCount + ApplicationManager.application.runWriteAction { file.virtualFile.setBinaryContent(file.virtualFile.contentsToByteArray()) } assert file.stub - //todo - //either: assert !cls.valid - //or: assert cls == PsiTreeUtil.findElementOfClassAtOffset(file, 1, PsiClass, false) - //assert !file.stub + assert psiManager.modificationTracker.javaStructureModificationCount != oldCount + assert !cls.valid + assert cls != PsiTreeUtil.findElementOfClassAtOffset(file, 1, PsiClass, false) + assert !file.stub + } + + public void "test reachable psi classes remain valid when nothing changes"() { + int count = 1000 + List> classList = (0.. extends ASTDelegateP public boolean isValid() { T stub = myStub; if (stub != null) { - if (stub instanceof PsiFileStub) { - return stub.getPsi().isValid(); + PsiElement parentPsi = stub.getParentStub().getPsi(); + if (parentPsi instanceof PsiFileImpl) { + return ((PsiFileImpl) parentPsi).isStubBasedChildValid(this); } - - return stub.getParentStub().getPsi().isValid(); + return parentPsi.isValid(); } return super.isValid(); 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..d3ff3e9ae771 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 @@ -249,6 +249,20 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF return findTreeForStub(ast, stubs, stub); } + public boolean isStubBasedChildValid(@NotNull StubBasedPsiElementBase psi) { + StubElement fileStub = getStub(); + if (fileStub != null) { + synchronized (myStubLock) { + fileStub = getStub(); + StubElement childStub = psi.getStub(); + if (fileStub != null && childStub != null && fileStub != childStub.getParentStub()) { + return false; + } + } + } + return isValid(); + } + @Nullable private static ASTNode findTreeForStub(ASTNode tree, final Iterator> stubs, final StubElement stub) { final IElementType type = tree.getElementType(); From de5d2513bc7d921931fedd9d3a1514db4f4d2ff4 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Mar 2012 15:58:06 +0400 Subject: [PATCH 086/106] turn off extra checks in performance tests --- .../src/com/intellij/openapi/editor/impl/CharArray.java | 2 +- .../src/com/intellij/openapi/editor/impl/DocumentImpl.java | 1 + .../src/com/intellij/testFramework/LightPlatformTestCase.java | 2 ++ .../src/com/intellij/testFramework/PlatformTestCase.java | 2 ++ 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java index a3f9d7d5b652..08c65c2ac35f 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java @@ -44,7 +44,7 @@ abstract class CharArray implements CharSequenceBackedByArray { private static final boolean DISABLE_DEFERRED_PROCESSING = Boolean.getBoolean("idea.document.deny.deferred.changes"); @SuppressWarnings("UseOfArchaicSystemPropertyAccessors") - private static final boolean DEBUG_DEFERRED_PROCESSING = LOG.isDebugEnabled() || Boolean.getBoolean("idea.document.debug.bulk.processing"); + private static final boolean DEBUG_DEFERRED_PROCESSING = LOG.isDebugEnabled() || Boolean.getBoolean("idea.document.debug.bulk.processing") || DocumentImpl.CHECK_DOCUMENT_CONSISTENCY; /** * We can't exclude possibility of situation when 'defer changes' state is {@link #setDeferredChangeMode(boolean) entered} * but not exited, hence, we want to perform automatic flushing if necessary in order to avoid memory leaks. This constant holds diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java index 18c0a2347654..f777f1b92b76 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java @@ -50,6 +50,7 @@ import java.util.concurrent.CopyOnWriteArrayList; public class DocumentImpl extends UserDataHolderBase implements DocumentEx { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.DocumentImpl"); + public static boolean CHECK_DOCUMENT_CONSISTENCY = true; private final CopyOnWriteArrayList myDocumentListeners = ContainerUtil.createEmptyCOWList(); private final RangeMarkerTree myRangeMarkers = new RangeMarkerTree(this); diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java index 01eca8e8d941..f4e051cf3f87 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java @@ -45,6 +45,7 @@ import com.intellij.openapi.command.undo.UndoManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.editor.impl.DocumentImpl; import com.intellij.openapi.editor.impl.EditorFactoryImpl; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl; @@ -335,6 +336,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da storeSettings(); myThreadTracker = new ThreadTracker(); + DocumentImpl.CHECK_DOCUMENT_CONSISTENCY = !isPerformanceTest(); } public static void doSetup(final LightProjectDescriptor descriptor, diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java index 6eaef6b87234..84a3123ea6cf 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java @@ -36,6 +36,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.editor.event.DocumentListener; +import com.intellij.openapi.editor.impl.DocumentImpl; import com.intellij.openapi.module.EmptyModuleType; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; @@ -189,6 +190,7 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro } DocumentCommitThread.getInstance().clearQueue(); + DocumentImpl.CHECK_DOCUMENT_CONSISTENCY = !isPerformanceTest(); } public Project getProject() { From 33aea8526ee042194a7982ad4c57031bb9bd1ad2 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Mar 2012 19:59:28 +0400 Subject: [PATCH 087/106] extra checks in tests only --- .../src/com/intellij/openapi/editor/impl/DocumentImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java index f777f1b92b76..e2a823c10e71 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java @@ -50,7 +50,7 @@ import java.util.concurrent.CopyOnWriteArrayList; public class DocumentImpl extends UserDataHolderBase implements DocumentEx { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.DocumentImpl"); - public static boolean CHECK_DOCUMENT_CONSISTENCY = true; + public static boolean CHECK_DOCUMENT_CONSISTENCY = ApplicationManager.getApplication().isUnitTestMode(); private final CopyOnWriteArrayList myDocumentListeners = ContainerUtil.createEmptyCOWList(); private final RangeMarkerTree myRangeMarkers = new RangeMarkerTree(this); From 6f2f47dda92198398af2765f13c416f7d2d6b5bf Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 20 Mar 2012 20:02:41 +0400 Subject: [PATCH 088/106] cleanup --- .../JavaCodeBlockModificationListener.java | 3 +- .../src/com/intellij/core/CoreASTFactory.java | 1 + .../intellij/lang/impl/PsiBuilderImpl.java | 2 ++ .../psi/SingleRootFileViewProvider.java | 3 +- .../psi/impl/AbstractModificationTracker.java | 4 ++- .../psi/impl/PsiModificationTrackerImpl.java | 3 +- .../psi/impl/PsiTreeChangePreprocessor.java | 3 +- ...lePsiFilesPerDocumentFileViewProvider.java | 3 +- .../impl/PsiTreeChangePreprocessorBase.java | 3 +- .../SmartPsiElementPointerImpl.java | 1 + .../impl/FileDocumentManagerImpl.java | 34 +++++++++++++++++++ 11 files changed, 52 insertions(+), 8 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/JavaCodeBlockModificationListener.java b/java/java-impl/src/com/intellij/psi/impl/JavaCodeBlockModificationListener.java index ba8fffebe15c..5ab99de764ed 100644 --- a/java/java-impl/src/com/intellij/psi/impl/JavaCodeBlockModificationListener.java +++ b/java/java-impl/src/com/intellij/psi/impl/JavaCodeBlockModificationListener.java @@ -20,6 +20,7 @@ import com.intellij.psi.*; import com.intellij.psi.impl.source.jsp.jspXml.JspDirective; import com.intellij.psi.util.PsiModificationTracker; import com.intellij.psi.xml.XmlFile; +import org.jetbrains.annotations.NotNull; public class JavaCodeBlockModificationListener implements PsiTreeChangePreprocessor { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.JavaCodeBlockModificationListener"); @@ -31,7 +32,7 @@ public class JavaCodeBlockModificationListener implements PsiTreeChangePreproces } @Override - public void treeChanged(final PsiTreeChangeEventImpl event) { + public void treeChanged(@NotNull final PsiTreeChangeEventImpl event) { switch (event.getCode()) { case BEFORE_CHILDREN_CHANGE: case BEFORE_PROPERTY_CHANGE: diff --git a/platform/core-impl/src/com/intellij/core/CoreASTFactory.java b/platform/core-impl/src/com/intellij/core/CoreASTFactory.java index 5e91b4fc3e57..a70a1eb13b1f 100644 --- a/platform/core-impl/src/com/intellij/core/CoreASTFactory.java +++ b/platform/core-impl/src/com/intellij/core/CoreASTFactory.java @@ -60,6 +60,7 @@ public class CoreASTFactory extends ASTFactory implements DefaultASTFactory { return new LeafPsiElement(type, text); } + @Override public LeafElement createComment(IElementType type, CharSequence text) { return new PsiCoreCommentImpl(type, text); } diff --git a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java index 6ddebaf8b7f8..505689a11b30 100644 --- a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java +++ b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java @@ -423,6 +423,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder, AS return myType; } + @Override public void remapTokenType(IElementType type) { //assert myType != null && type != null; myType = type; @@ -547,6 +548,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder, AS return myParsed; } + @Override public ASTNodeBuilder getBuilder() { return myBuilder; } diff --git a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java index 9bb2fe2f2d72..af2a1cab97f5 100644 --- a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java +++ b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java @@ -144,7 +144,7 @@ public class SingleRootFileViewProvider extends UserDataHolderBase implements Fi } @Nullable - protected PsiFile getPsiInner(final Language target) { + protected PsiFile getPsiInner(@NotNull Language target) { if (target != getBaseLanguage()) { return null; } @@ -510,6 +510,7 @@ public class SingleRootFileViewProvider extends UserDataHolderBase implements Fi } if (myContent != null) return myContent; return myContent = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override @NotNull public CharSequence compute() { return myFile.calcTreeElement().getText(); diff --git a/platform/core-impl/src/com/intellij/psi/impl/AbstractModificationTracker.java b/platform/core-impl/src/com/intellij/psi/impl/AbstractModificationTracker.java index d95321ece57a..e8e5cc3e3899 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/AbstractModificationTracker.java +++ b/platform/core-impl/src/com/intellij/psi/impl/AbstractModificationTracker.java @@ -17,6 +17,7 @@ package com.intellij.psi.impl; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; /** * @author Roman.Chernyatchik @@ -40,7 +41,8 @@ public abstract class AbstractModificationTracker implements PsiTreeChangePrepro myPsiManager.addTreeChangePreprocessor(this); } - public void treeChanged(final PsiTreeChangeEventImpl event) { + @Override + public void treeChanged(@NotNull final PsiTreeChangeEventImpl event) { boolean changedInsideCodeBlock = false; switch (event.getCode()) { diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiModificationTrackerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/PsiModificationTrackerImpl.java index 360720da51a6..d3c6b410abd8 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/PsiModificationTrackerImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/PsiModificationTrackerImpl.java @@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDirectory; import com.intellij.psi.util.PsiModificationTracker; import com.intellij.util.messages.MessageBus; +import org.jetbrains.annotations.NotNull; import java.util.concurrent.atomic.AtomicLong; @@ -68,7 +69,7 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr } @Override - public void treeChanged(PsiTreeChangeEventImpl event) { + public void treeChanged(@NotNull PsiTreeChangeEventImpl event) { myModificationCount.getAndIncrement(); if (event.getParent() instanceof PsiDirectory) { incOutOfCodeBlockModificationCounter(); diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiTreeChangePreprocessor.java b/platform/core-impl/src/com/intellij/psi/impl/PsiTreeChangePreprocessor.java index 35224e14613f..7eaac7f30076 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/PsiTreeChangePreprocessor.java +++ b/platform/core-impl/src/com/intellij/psi/impl/PsiTreeChangePreprocessor.java @@ -17,6 +17,7 @@ package com.intellij.psi.impl; import com.intellij.openapi.extensions.ExtensionPointName; +import org.jetbrains.annotations.NotNull; /** * @author yole @@ -24,5 +25,5 @@ import com.intellij.openapi.extensions.ExtensionPointName; public interface PsiTreeChangePreprocessor { ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.psi.treeChangePreprocessor"); - void treeChanged(PsiTreeChangeEventImpl event); + void treeChanged(@NotNull PsiTreeChangeEventImpl event); } diff --git a/platform/lang-impl/src/com/intellij/psi/MultiplePsiFilesPerDocumentFileViewProvider.java b/platform/lang-impl/src/com/intellij/psi/MultiplePsiFilesPerDocumentFileViewProvider.java index ec5ee72b429b..bc650fdf8ef4 100644 --- a/platform/lang-impl/src/com/intellij/psi/MultiplePsiFilesPerDocumentFileViewProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/MultiplePsiFilesPerDocumentFileViewProvider.java @@ -28,7 +28,6 @@ import com.intellij.psi.impl.SharedPsiElementImplUtil; import com.intellij.psi.impl.source.PsiFileImpl; import com.intellij.psi.impl.source.tree.FileElement; import com.intellij.psi.templateLanguages.OuterLanguageElement; -import com.intellij.testFramework.LightVirtualFile; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.ReflectionCache; import com.intellij.util.containers.ConcurrentHashMap; @@ -72,7 +71,7 @@ public abstract class MultiplePsiFilesPerDocumentFileViewProvider extends Single } @Override - protected PsiFile getPsiInner(final Language target) { + protected PsiFile getPsiInner(@NotNull final Language target) { PsiFile file = myRoots.get(target); if (file == null) { if (isPhysical()) { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiTreeChangePreprocessorBase.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiTreeChangePreprocessorBase.java index 3e018129246b..fad5f62205e9 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiTreeChangePreprocessorBase.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiTreeChangePreprocessorBase.java @@ -18,6 +18,7 @@ package com.intellij.psi.impl; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; /** * @author yole @@ -31,7 +32,7 @@ public abstract class PsiTreeChangePreprocessorBase implements PsiTreeChangePrep } @Override - public void treeChanged(PsiTreeChangeEventImpl event) { + public void treeChanged(@NotNull PsiTreeChangeEventImpl event) { boolean changedInsideCodeBlock = false; switch (event.getCode()) { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java index dde40cb8887b..ad73760f78ed 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java @@ -106,6 +106,7 @@ class SmartPsiElementPointerImpl implements SmartPointerEx myElement = element == null ? null : new SoftReference(element); } + @Override public E getCachedElement() { Reference ref = myElement; return ref == null ? null : ref.get(); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java index bf47f92b6559..57309076daf1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java @@ -99,6 +99,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl myBus = ApplicationManager.getApplication().getMessageBus(); InvocationHandler handler = new InvocationHandler() { + @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { multicast(method, args); return null; @@ -135,17 +136,21 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl } } + @Override @NotNull public String getComponentName() { return "FileDocumentManager"; } + @Override public void initComponent() { } + @Override public void disposeComponent() { } + @Override @Nullable public Document getDocument(@NotNull final VirtualFile file) { DocumentEx document = (DocumentEx)getCachedDocument(file); @@ -167,6 +172,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl if (!(file instanceof LightVirtualFile || file.getFileSystem() instanceof DummyFileSystem)) { document.addDocumentListener( new DocumentAdapter() { + @Override public void documentChanged(DocumentEvent e) { final Document document = e.getDocument(); myUnsavedDocuments.add(document); @@ -205,6 +211,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl return EditorFactory.getInstance().createDocument(text); } + @Override @Nullable public Document getCachedDocument(@NotNull VirtualFile file) { Reference reference = file.getUserData(DOCUMENT_KEY); @@ -222,6 +229,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl public static void registerDocument(@NotNull final Document document, @NotNull VirtualFile virtualFile) { synchronized (lock) { virtualFile.putUserData(DOCUMENT_KEY, new SoftReference(document) { + @Override public Document get() { return document; } @@ -230,6 +238,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl } } + @Override @Nullable public VirtualFile getFile(@NotNull Document document) { return document.getUserData(FILE_KEY); @@ -269,6 +278,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl }); } + @Override public void saveAllDocuments() { ApplicationManager.getApplication().assertIsDispatchThread(); @@ -293,11 +303,13 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl } } + @Override public void saveDocument(@NotNull final Document document) { ApplicationManager.getApplication().assertIsDispatchThread(); if (!myUnsavedDocuments.contains(document)) return; ApplicationManager.getApplication().runWriteAction(new DocumentRunnable(document, null) { + @Override public void run() { _saveDocument(document); } @@ -394,6 +406,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl return lineSeparator; } + @Override @NotNull public String getLineSeparator(@Nullable VirtualFile file, @Nullable Project project) { String lineSeparator = file != null ? LoadTextUtil.getDetectedLineSeparator(file) : null; @@ -421,6 +434,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl return false; } + @Override public void reloadFiles(final VirtualFile... files) { for (VirtualFile file : files) { if (file.exists()) { @@ -432,6 +446,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl } } + @Override @NotNull public Document[] getUnsavedDocuments() { if (myUnsavedDocuments.isEmpty()) { @@ -442,15 +457,18 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl return list.toArray(new Document[list.size()]); } + @Override public boolean isDocumentUnsaved(@NotNull Document document) { return myUnsavedDocuments.contains(document); } + @Override public boolean isFileModified(@NotNull VirtualFile file) { final Document doc = getCachedDocument(file); return doc != null && isDocumentUnsaved(doc) && doc.getModificationStamp() != file.getModificationStamp(); } + @Override public void propertyChanged(final VirtualFilePropertyEvent event) { if (VirtualFile.PROP_WRITABLE.equals(event.getPropertyName())) { final VirtualFile file = event.getFile(); @@ -459,6 +477,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl ApplicationManager.getApplication().runWriteAction( new ExternalChangeAction() { + @Override public void run() { document.setReadOnly(!event.getFile().isWritable()); } @@ -478,6 +497,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl return ft.isBinary() && BinaryFileTypeDecompilers.INSTANCE.forFileType(ft) == null; } + @Override public void contentsChanged(VirtualFileEvent event) { if (event.isFromSave()) return; final VirtualFile file = event.getFile(); @@ -499,6 +519,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl LOG.info(" oldFileStamp:" + oldFileStamp); Runnable askReloadRunnable = new Runnable() { + @Override public void run() { if (!file.isValid()) return; if (askReloadFromDisk(file, document)) { @@ -518,6 +539,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl myMultiCaster.fileWithNoDocumentChanged(file); } + @Override public void reloadFromDisk(@NotNull final Document document) { ApplicationManager.getApplication().assertIsDispatchThread(); final VirtualFile file = getFile(document); @@ -527,9 +549,11 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl final Project project = ProjectLocator.getInstance().guessProjectForFile(file); CommandProcessor.getInstance().executeCommand(project, new Runnable() { + @Override public void run() { ApplicationManager.getApplication().runWriteAction( new ExternalChangeAction.ExternalDocumentChange(document, project) { + @Override public void run() { boolean wasWritable = document.isWritable(); DocumentEx documentEx = (DocumentEx)document; @@ -558,6 +582,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl builder.addOkAction().setText(UIBundle.message("file.cache.conflict.load.fs.changes.button")); builder.addCancelAction().setText(UIBundle.message("file.cache.conflict.keep.memory.changes.button")); builder.addAction(new AbstractAction(UIBundle.message("file.cache.conflict.show.difference.button")) { + @Override public void actionPerformed(ActionEvent e) { String windowtitle = UIBundle.message("file.cache.conflict.for.file.dialog.title", file.getPresentableUrl()); final ProjectEx project = (ProjectEx)ProjectLocator.getInstance().guessProjectForFile(file); @@ -591,6 +616,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl protected void reportErrorOnSave(final IOException e) { // invokeLater here prevents attempt to show dialog in write action ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override public void run() { Messages.showMessageDialog( UIBundle.message("cannot.save.file.with.error.error.message", e.getMessage()), @@ -601,9 +627,11 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl }); } + @Override public void fileCreated(VirtualFileEvent event) { } + @Override public void fileDeleted(VirtualFileEvent event) { Document doc = getCachedDocument(event.getFile()); if (doc != null) { @@ -611,22 +639,28 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl } } + @Override public void fileMoved(VirtualFileMoveEvent event) { } + @Override public void fileCopied(VirtualFileCopyEvent event) { fileCreated(event); } + @Override public void beforePropertyChange(VirtualFilePropertyEvent event) { } + @Override public void beforeContentsChange(VirtualFileEvent event) { } + @Override public void beforeFileDeletion(VirtualFileEvent event) { } + @Override public void beforeFileMovement(VirtualFileMoveEvent event) { } From 7d1bf044ef71fa68051a06a059373793c5a34939 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 21 Mar 2012 09:36:06 +0100 Subject: [PATCH 089/106] Migrate JDBC/JPA/Hibernate consoles to util-rt --- .../execution/rmi/RemoteProcessSupport.java | 15 ++ .../execution/rmi/RemoteCastable.java | 26 +++ .../intellij/execution/rmi/RemoteObject.java | 10 +- .../intellij/execution/rmi/RemoteServer.java | 38 ++--- .../com/intellij/openapi/util/Comparing.java | 6 +- .../src/com/intellij/openapi/util/Pair.java | 3 +- .../src/com/intellij/util/ArrayUtilRt.java | 50 ++++++ .../src/com/intellij/util/Function.java | 4 +- .../com/intellij/util/NotNullFunction.java | 2 +- .../com/intellij/util/NullableFunction.java | 2 +- .../util/containers/ContainerUtilRt.java | 148 ++++++++++++++++++ .../intellij/util/io/LimitedInputStream.java | 10 +- .../src/org/jetbrains/util/rt/FileUtilRt.java | 32 ++++ .../org/jetbrains/util/rt/StringUtilRt.java | 63 ++++++++ .../execution/rmi/RemoteCastable.java | 11 -- .../intellij/execution/rmi/RemoteUtil.java | 15 ++ .../intellij/openapi/util/io/FileUtil.java | 31 ---- .../openapi/util/text/StringUtil.java | 63 -------- .../util/src/com/intellij/util/ArrayUtil.java | 39 ++--- .../util/containers/ContainerUtil.java | 116 +------------- 20 files changed, 404 insertions(+), 280 deletions(-) create mode 100644 platform/util-rt/src/com/intellij/execution/rmi/RemoteCastable.java rename platform/{util => util-rt}/src/com/intellij/execution/rmi/RemoteObject.java (92%) rename platform/{util => util-rt}/src/com/intellij/execution/rmi/RemoteServer.java (76%) rename platform/{util => util-rt}/src/com/intellij/openapi/util/Comparing.java (96%) rename platform/{util => util-rt}/src/com/intellij/openapi/util/Pair.java (98%) create mode 100644 platform/util-rt/src/com/intellij/util/ArrayUtilRt.java rename platform/{util => util-rt}/src/com/intellij/util/Function.java (94%) rename platform/{util => util-rt}/src/com/intellij/util/NotNullFunction.java (95%) rename platform/{util => util-rt}/src/com/intellij/util/NullableFunction.java (95%) create mode 100644 platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java rename platform/{util => util-rt}/src/com/intellij/util/io/LimitedInputStream.java (89%) delete mode 100644 platform/util/src/com/intellij/execution/rmi/RemoteCastable.java diff --git a/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java b/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java index 0c163ed00a14..f6c95bf4276b 100644 --- a/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java +++ b/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java @@ -1,3 +1,18 @@ +/* + * 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. + * 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.execution.rmi; import com.intellij.execution.ExecutionException; diff --git a/platform/util-rt/src/com/intellij/execution/rmi/RemoteCastable.java b/platform/util-rt/src/com/intellij/execution/rmi/RemoteCastable.java new file mode 100644 index 000000000000..816cb32afc17 --- /dev/null +++ b/platform/util-rt/src/com/intellij/execution/rmi/RemoteCastable.java @@ -0,0 +1,26 @@ +/* + * 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. + * 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.execution.rmi; + +import java.rmi.Remote; +import java.rmi.RemoteException; + +/** + * @author Gregory.Shrago + */ +public interface RemoteCastable extends Remote { + String getCastToClassName() throws RemoteException; +} diff --git a/platform/util/src/com/intellij/execution/rmi/RemoteObject.java b/platform/util-rt/src/com/intellij/execution/rmi/RemoteObject.java similarity index 92% rename from platform/util/src/com/intellij/execution/rmi/RemoteObject.java rename to platform/util-rt/src/com/intellij/execution/rmi/RemoteObject.java index 2a487832a849..859186d41bce 100644 --- a/platform/util/src/com/intellij/execution/rmi/RemoteObject.java +++ b/platform/util-rt/src/com/intellij/execution/rmi/RemoteObject.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. @@ -15,9 +15,9 @@ */ package com.intellij.execution.rmi; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import com.intellij.util.containers.ContainerUtilRt; import java.lang.ref.WeakReference; import java.rmi.Remote; @@ -45,7 +45,7 @@ public class RemoteObject implements Remote, Unreferenced { @Nullable public synchronized T export(@Nullable T child) throws RemoteException { if (child == null) return null; - final T result = (T)UnicastRemoteObject.exportObject(child, 0); + @SuppressWarnings("unchecked") final T result = (T)UnicastRemoteObject.exportObject(child, 0); myChildren.put((RemoteObject)child, result); ((RemoteObject)child).myParent = this; return result; @@ -68,7 +68,7 @@ public class RemoteObject implements Remote, Unreferenced { if (children.isEmpty()) return; final ArrayList list = new ArrayList(children.size()); for (WeakReference child : children) { - ContainerUtil.addIfNotNull(child.get(), list); + ContainerUtilRt.addIfNotNull(child.get(), list); } myChildren.keySet().removeAll(list); for (RemoteObject child : list) { @@ -85,6 +85,7 @@ public class RemoteObject implements Remote, Unreferenced { UnicastRemoteObject.unexportObject(this, false); } catch (RemoteException e) { + //noinspection CallToPrintStackTrace e.printStackTrace(); } } @@ -113,5 +114,4 @@ public class RemoteObject implements Remote, Unreferenced { protected boolean isKnownException(Throwable ex) { return false; } - } diff --git a/platform/util/src/com/intellij/execution/rmi/RemoteServer.java b/platform/util-rt/src/com/intellij/execution/rmi/RemoteServer.java similarity index 76% rename from platform/util/src/com/intellij/execution/rmi/RemoteServer.java rename to platform/util-rt/src/com/intellij/execution/rmi/RemoteServer.java index aa1b2100b0b7..9e846ea83a56 100644 --- a/platform/util/src/com/intellij/execution/rmi/RemoteServer.java +++ b/platform/util-rt/src/com/intellij/execution/rmi/RemoteServer.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. @@ -15,8 +15,9 @@ */ package com.intellij.execution.rmi; +import org.jetbrains.annotations.Nullable; + import javax.naming.Context; -import javax.naming.InitialContext; import javax.naming.NamingException; import javax.naming.spi.InitialContextFactory; import java.lang.reflect.InvocationHandler; @@ -32,18 +33,17 @@ import java.util.Random; public class RemoteServer { private static Remote ourRemote; - private static Remote ourStub; + @SuppressWarnings("UseOfSystemOutOrSystemErr") protected static void start(Remote remote) throws Exception { setupRMI(); banJNDI(); if (ourRemote != null) throw new AssertionError("Already started"); - ourRemote = remote; Registry registry; - int port = 0; + int port; for (Random random = new Random(); ;) { port = random.nextInt(0xffff); if (port < 4000) continue; @@ -51,22 +51,23 @@ public class RemoteServer { registry = LocateRegistry.createRegistry(port); break; } - catch (ExportException ex) { - } + catch (ExportException ignored) { } } - try { - ourStub = UnicastRemoteObject.exportObject(ourRemote, 0); - final String name = remote.getClass().getSimpleName() + Integer.toHexString(ourStub.hashCode()); - registry.bind(name, ourStub); - System.out.println("Port/ID:" + port + "/" + name); + try { + Remote stub = UnicastRemoteObject.exportObject(ourRemote, 0); + final String name = remote.getClass().getSimpleName() + Integer.toHexString(stub.hashCode()); + registry.bind(name, stub); + + System.out.println("Port/ID: " + port + "/" + name); + Object lock = new Object(); synchronized (lock) { lock.wait(); } } catch (Throwable e) { - e.printStackTrace(); + e.printStackTrace(System.err); System.exit(1); } } @@ -77,23 +78,24 @@ public class RemoteServer { // do not use domain or http address for server System.setProperty("java.rmi.server.hostname", "localhost"); - // do not use http tunnelling + // do not use HTTP tunnelling System.setProperty("java.rmi.server.disableHttp", "true"); } private static void banJNDI() { - if (System.getProperty(InitialContext.INITIAL_CONTEXT_FACTORY) == null) { - System.setProperty(InitialContext.INITIAL_CONTEXT_FACTORY, "com.intellij.execution.rmi.RemoteServer$Jndi"); + if (System.getProperty(Context.INITIAL_CONTEXT_FACTORY) == null) { + System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.intellij.execution.rmi.RemoteServer$Jndi"); } } + @SuppressWarnings("UnusedDeclaration") public static class Jndi implements InitialContextFactory, InvocationHandler { - @Override public Context getInitialContext(final Hashtable environment) throws NamingException { - return (Context) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { Context.class}, this ); + return (Context)Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Context.class}, this); } + @Nullable @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { return null; diff --git a/platform/util/src/com/intellij/openapi/util/Comparing.java b/platform/util-rt/src/com/intellij/openapi/util/Comparing.java similarity index 96% rename from platform/util/src/com/intellij/openapi/util/Comparing.java rename to platform/util-rt/src/com/intellij/openapi/util/Comparing.java index 4860c7ab53f7..4c9d7dd1a1bb 100644 --- a/platform/util/src/com/intellij/openapi/util/Comparing.java +++ b/platform/util-rt/src/com/intellij/openapi/util/Comparing.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. @@ -15,7 +15,7 @@ */ package com.intellij.openapi.util; -import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.util.rt.StringUtilRt; import java.util.Arrays; import java.util.Collection; @@ -77,7 +77,7 @@ public class Comparing { if (c1 == c2) { continue; } - if (!caseSensitive && StringUtil.charsEqualIgnoreCase(c1, c2)) continue; + if (!caseSensitive && StringUtilRt.charsEqualIgnoreCase(c1, c2)) continue; return false; } diff --git a/platform/util/src/com/intellij/openapi/util/Pair.java b/platform/util-rt/src/com/intellij/openapi/util/Pair.java similarity index 98% rename from platform/util/src/com/intellij/openapi/util/Pair.java rename to platform/util-rt/src/com/intellij/openapi/util/Pair.java index d380de5a044a..ce63e207fcfa 100644 --- a/platform/util/src/com/intellij/openapi/util/Pair.java +++ b/platform/util-rt/src/com/intellij/openapi/util/Pair.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 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,7 +18,6 @@ package com.intellij.openapi.util; import com.intellij.util.Function; import org.jetbrains.annotations.Nullable; - public class Pair { public final A first; public final B second; diff --git a/platform/util-rt/src/com/intellij/util/ArrayUtilRt.java b/platform/util-rt/src/com/intellij/util/ArrayUtilRt.java new file mode 100644 index 000000000000..c898e0149572 --- /dev/null +++ b/platform/util-rt/src/com/intellij/util/ArrayUtilRt.java @@ -0,0 +1,50 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util; + +import org.jetbrains.annotations.NotNull; +import com.intellij.util.containers.ContainerUtilRt; + +import java.io.File; +import java.util.Collection; + +/** + * Stripped-down version of {@code com.intellij.util.ArrayUtil}. + * Intended to use by external (out-of-IDE-process) runners and helpers so it should not contain any library dependencies. + * + * @since 12.0 + */ +@SuppressWarnings({"UtilityClassWithoutPrivateConstructor", "SSBasedInspection"}) +public class ArrayUtilRt { + public static final short[] EMPTY_SHORT_ARRAY = new short[0]; + public static final char[] EMPTY_CHAR_ARRAY = new char[0]; + public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; + public static final int[] EMPTY_INT_ARRAY = new int[0]; + public static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0]; + public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0]; + public static final String[] EMPTY_STRING_ARRAY = new String[0]; + public static final Class[] EMPTY_CLASS_ARRAY = new Class[0]; + public static final long[] EMPTY_LONG_ARRAY = new long[0]; + public static final Collection[] EMPTY_COLLECTION_ARRAY = new Collection[0]; + public static final File[] EMPTY_FILE_ARRAY = new File[0]; + public static final Runnable[] EMPTY_RUNNABLE_ARRAY = new Runnable[0]; + + @NotNull + public static String[] toStringArray(@NotNull Collection collection) { + if (collection.isEmpty()) return EMPTY_STRING_ARRAY; + return ContainerUtilRt.toArray(collection, new String[collection.size()]); + } +} diff --git a/platform/util/src/com/intellij/util/Function.java b/platform/util-rt/src/com/intellij/util/Function.java similarity index 94% rename from platform/util/src/com/intellij/util/Function.java rename to platform/util-rt/src/com/intellij/util/Function.java index 089895796a25..fef2a94aaf2d 100644 --- a/platform/util/src/com/intellij/util/Function.java +++ b/platform/util-rt/src/com/intellij/util/Function.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. @@ -15,8 +15,6 @@ */ package com.intellij.util; -import org.jetbrains.annotations.Nullable; - import java.util.Collection; /** diff --git a/platform/util/src/com/intellij/util/NotNullFunction.java b/platform/util-rt/src/com/intellij/util/NotNullFunction.java similarity index 95% rename from platform/util/src/com/intellij/util/NotNullFunction.java rename to platform/util-rt/src/com/intellij/util/NotNullFunction.java index cae730360bd4..802172e3e5c4 100644 --- a/platform/util/src/com/intellij/util/NotNullFunction.java +++ b/platform/util-rt/src/com/intellij/util/NotNullFunction.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. diff --git a/platform/util/src/com/intellij/util/NullableFunction.java b/platform/util-rt/src/com/intellij/util/NullableFunction.java similarity index 95% rename from platform/util/src/com/intellij/util/NullableFunction.java rename to platform/util-rt/src/com/intellij/util/NullableFunction.java index a57e9b5dff17..ed768ae3ef7a 100644 --- a/platform/util/src/com/intellij/util/NullableFunction.java +++ b/platform/util-rt/src/com/intellij/util/NullableFunction.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. diff --git a/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java b/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java new file mode 100644 index 000000000000..7716a6d7d050 --- /dev/null +++ b/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java @@ -0,0 +1,148 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util.containers; + +import com.intellij.util.ArrayUtilRt; +import com.intellij.util.Function; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Stripped-down version of {@code com.intellij.util.containers.ContainerUtil}. + * Intended to use by external (out-of-IDE-process) runners and helpers so it should not contain any library dependencies. + * + * @since 12.0 + */ +@SuppressWarnings({"UtilityClassWithoutPrivateConstructor"}) +public class ContainerUtilRt { + private static final int ARRAY_COPY_THRESHOLD = 20; + + /** + * Optimized toArray() as opposed to the {@link java.util.Collections#emptyList()}. + */ + private static class EmptyList extends AbstractList implements RandomAccess { + private static final EmptyList INSTANCE = new EmptyList(); + + public int size() { + return 0; + } + + public boolean contains(Object obj) { + return false; + } + + public Object get(int index) { + throw new IndexOutOfBoundsException("Index: " + index); + } + + @Override + public Object[] toArray() { + return ArrayUtilRt.EMPTY_OBJECT_ARRAY; + } + + @Override + public T[] toArray(T[] a) { + return a; + } + } + + @NotNull + public static List emptyList() { + @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"}) final List list = (List)EmptyList.INSTANCE; + return list; + } + + @NotNull + public static CopyOnWriteArrayList createEmptyCOWList() { + // does not create garbage new Object[0] + return new CopyOnWriteArrayList(ContainerUtilRt.emptyList()); + } + + public static void addIfNotNull(final T element, @NotNull Collection result) { + if (element != null) { + result.add(element); + } + } + + public static void addIfNotNull(@NotNull Collection result, @Nullable final T element) { + if (element != null) { + result.add(element); + } + } + + @NotNull + public static List map2List(@NotNull T[] array, @NotNull Function mapper) { + return map2List(Arrays.asList(array), mapper); + } + + @NotNull + public static List map2List(@NotNull Collection collection, @NotNull Function mapper) { + final ArrayList list = new ArrayList(collection.size()); + for (final T t : collection) { + list.add(mapper.fun(t)); + } + return list; + } + + @NotNull + public static Set map2Set(@NotNull T[] collection, @NotNull Function mapper) { + return map2Set(Arrays.asList(collection), mapper); + } + + @NotNull + public static Set map2Set(@NotNull Collection collection, @NotNull Function mapper) { + final HashSet set = new HashSet(collection.size()); + for (final T t : collection) { + set.add(mapper.fun(t)); + } + return set; + } + + @NotNull + public static T[] toArray(@NotNull List collection, @NotNull T[] array) { + final int length = array.length; + if (length < ARRAY_COPY_THRESHOLD) { + for (int i = 0; i < collection.size(); i++) { + array[i] = collection.get(i); + } + return array; + } + else { + return collection.toArray(array); + } + } + + /** + * This is a replacement for {@link Collection#toArray(Object[])}. For small collections it is faster to stay at java level and refrain + * from calling JNI {@link System#arraycopy(Object, int, Object, int, int)} + */ + @NotNull + public static T[] toArray(@NotNull Collection c, @NotNull T[] sample) { + final int size = c.size(); + if (size == sample.length && size < ARRAY_COPY_THRESHOLD) { + int i = 0; + for (T t : c) { + sample[i++] = t; + } + return sample; + } + + return c.toArray(sample); + } +} diff --git a/platform/util/src/com/intellij/util/io/LimitedInputStream.java b/platform/util-rt/src/com/intellij/util/io/LimitedInputStream.java similarity index 89% rename from platform/util/src/com/intellij/util/io/LimitedInputStream.java rename to platform/util-rt/src/com/intellij/util/io/LimitedInputStream.java index c18bdbe9f777..bc0f868a83a4 100644 --- a/platform/util/src/com/intellij/util/io/LimitedInputStream.java +++ b/platform/util-rt/src/com/intellij/util/io/LimitedInputStream.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. @@ -53,10 +53,10 @@ public class LimitedInputStream extends FilterInputStream { len = Math.min(len, myReadLimit - myBytesRead); if (len <= 0) return -1; - final int acutallyRead = super.read(b, off, len); - if (acutallyRead >= 0) myBytesRead += acutallyRead; + final int actuallyRead = super.read(b, off, len); + if (actuallyRead >= 0) myBytesRead += actuallyRead; - return acutallyRead; + return actuallyRead; } public long skip(long n) throws IOException { @@ -72,7 +72,7 @@ public class LimitedInputStream extends FilterInputStream { return Math.min(super.available(), myReadLimit - myBytesRead); } - public synchronized void mark(final int readlimit) { + public synchronized void mark(final int readLimit) { throw new UnsupportedOperationException(); } diff --git a/platform/util-rt/src/org/jetbrains/util/rt/FileUtilRt.java b/platform/util-rt/src/org/jetbrains/util/rt/FileUtilRt.java index b91b1dc48490..9d92d5ee8512 100644 --- a/platform/util-rt/src/org/jetbrains/util/rt/FileUtilRt.java +++ b/platform/util-rt/src/org/jetbrains/util/rt/FileUtilRt.java @@ -33,6 +33,12 @@ import java.util.UUID; public class FileUtilRt { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.io.FileUtilLight"); + protected static final ThreadLocal BUFFER = new ThreadLocal() { + protected byte[] initialValue() { + return new byte[1024 * 20]; + } + }; + private static String ourCanonicalTempPathCache = null; @NotNull @@ -233,4 +239,30 @@ public class FileUtilRt { return newChars; } } + + @NotNull + public static byte[] loadBytes(@NotNull InputStream stream) throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + final byte[] bytes = BUFFER.get(); + while (true) { + int n = stream.read(bytes, 0, bytes.length); + if (n <= 0) break; + buffer.write(bytes, 0, n); + } + buffer.close(); + return buffer.toByteArray(); + } + + @NotNull + public static byte[] loadBytes(@NotNull InputStream stream, int length) throws IOException { + byte[] bytes = new byte[length]; + int count = 0; + while (count < length) { + int n = stream.read(bytes, count, length - count); + if (n <= 0) break; + count += n; + } + return bytes; + } + } diff --git a/platform/util-rt/src/org/jetbrains/util/rt/StringUtilRt.java b/platform/util-rt/src/org/jetbrains/util/rt/StringUtilRt.java index cc915bc08591..9698ac290056 100644 --- a/platform/util-rt/src/org/jetbrains/util/rt/StringUtilRt.java +++ b/platform/util-rt/src/org/jetbrains/util/rt/StringUtilRt.java @@ -26,6 +26,32 @@ import org.jetbrains.annotations.Nullable; */ @SuppressWarnings({"UtilityClassWithoutPrivateConstructor"}) public class StringUtilRt { + public static boolean charsEqualIgnoreCase(char a, char b) { + return a == b || toUpperCase(a) == toUpperCase(b) || toLowerCase(a) == toLowerCase(b); + } + + public static char toUpperCase(char a) { + if (a < 'a') { + return a; + } + if (a >= 'a' && a <= 'z') { + return (char)(a + ('A' - 'a')); + } + return Character.toUpperCase(a); + } + + public static char toLowerCase(final char a) { + if (a < 'A' || a >= 'a' && a <= 'z') { + return a; + } + + if (a >= 'A' && a <= 'Z') { + return (char)(a + ('a' - 'A')); + } + + return Character.toLowerCase(a); + } + /** * Converts line separators to "\n" */ @@ -121,4 +147,41 @@ public class StringUtilRt { } } } + + public static int parseInt(final String string, final int defaultValue) { + try { + return Integer.parseInt(string); + } + catch (Exception e) { + return defaultValue; + } + } + + public static double parseDouble(final String string, final double defaultValue) { + try { + return Double.parseDouble(string); + } + catch (Exception e) { + return defaultValue; + } + } + + @NotNull + public static String getShortName(@NotNull Class aClass) { + return getShortName(aClass.getName()); + } + + @NotNull + public static String getShortName(@NotNull String fqName) { + return getShortName(fqName, '.'); + } + + @NotNull + public static String getShortName(@NotNull String fqName, char separator) { + int lastPointIdx = fqName.lastIndexOf(separator); + if (lastPointIdx >= 0) { + return fqName.substring(lastPointIdx + 1); + } + return fqName; + } } diff --git a/platform/util/src/com/intellij/execution/rmi/RemoteCastable.java b/platform/util/src/com/intellij/execution/rmi/RemoteCastable.java deleted file mode 100644 index 28395a18b04d..000000000000 --- a/platform/util/src/com/intellij/execution/rmi/RemoteCastable.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.intellij.execution.rmi; - -import java.rmi.Remote; -import java.rmi.RemoteException; - -/** - * @author Gregory.Shrago - */ -public interface RemoteCastable extends Remote { - String getCastToClassName() throws RemoteException; -} diff --git a/platform/util/src/com/intellij/execution/rmi/RemoteUtil.java b/platform/util/src/com/intellij/execution/rmi/RemoteUtil.java index e98026215195..5ca43ada3991 100644 --- a/platform/util/src/com/intellij/execution/rmi/RemoteUtil.java +++ b/platform/util/src/com/intellij/execution/rmi/RemoteUtil.java @@ -1,3 +1,18 @@ +/* + * 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. + * 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.execution.rmi; import com.intellij.openapi.util.Pair; diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java index 1125485bf795..393d1a6ae079 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java @@ -62,12 +62,6 @@ public class FileUtil extends FileUtilRt { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.io.FileUtil"); - private static final ThreadLocal BUFFER = new ThreadLocal() { - protected byte[] initialValue() { - return new byte[1024 * 20]; - } - }; - // do not use channels to copy files larger than 5 Mb because of possible MapFailed error private static final long CHANNELS_COPYING_LIMIT = 5L * MEGABYTE; @@ -217,31 +211,6 @@ public class FileUtil extends FileUtilRt { return bytes; } - @NotNull - public static byte[] loadBytes(@NotNull InputStream stream, int length) throws IOException { - byte[] bytes = new byte[length]; - int count = 0; - while (count < length) { - int n = stream.read(bytes, count, length - count); - if (n <= 0) break; - count += n; - } - return bytes; - } - - @NotNull - public static byte[] loadBytes(@NotNull InputStream stream) throws IOException { - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - final byte[] bytes = BUFFER.get(); - while (true) { - int n = stream.read(bytes, 0, bytes.length); - if (n <= 0) break; - buffer.write(bytes, 0, n); - } - buffer.close(); - return buffer.toByteArray(); - } - public static boolean processFirstBytes(@NotNull InputStream stream, int length, @NotNull Processor processor) throws IOException { final byte[] bytes = BUFFER.get(); assert bytes.length >= length : "Cannot process more than " + bytes.length + " in one call, requested:" + length; diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index 4f7453801e2c..b2fd28e88334 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -155,16 +155,6 @@ public class StringUtil extends StringUtilRt { return newText!= null ? newText.toString():""; } - @NotNull - public static String getShortName(@NotNull String fqName) { - return getShortName(fqName, '.'); - } - - @NotNull - public static String getShortName(@NotNull Class aClass) { - return getShortName(aClass.getName()); - } - /** * Implementation copied from {@link String#indexOf(String, int)} except character comparisons made case insensitive */ @@ -225,32 +215,6 @@ public class StringUtil extends StringUtilRt { return stringLength >= prefixLength && str.regionMatches(true, 0, prefix, 0, prefixLength); } - public static boolean charsEqualIgnoreCase(char a, char b) { - return a == b || toUpperCase(a) == toUpperCase(b) || toLowerCase(a) == toLowerCase(b); - } - - public static char toUpperCase(char a) { - if (a < 'a') { - return a; - } - if (a >= 'a' && a <= 'z') { - return (char)(a + ('A' - 'a')); - } - return Character.toUpperCase(a); - } - - public static char toLowerCase(final char a) { - if (a < 'A' || a >= 'a' && a <= 'z') { - return a; - } - - if (a >= 'A' && a <= 'Z') { - return (char)(a + ('a' - 'A')); - } - - return Character.toLowerCase(a); - } - public static String stripHtml(String html, boolean convertBreaks) { if (convertBreaks) { html = html.replaceAll("
", "\n\n"); @@ -264,15 +228,6 @@ public class StringUtil extends StringUtilRt { return str == null ? null : str.toLowerCase(); } - @NotNull - public static String getShortName(@NotNull String fqName, char separator) { - int lastPointIdx = fqName.lastIndexOf(separator); - if (lastPointIdx >= 0) { - return fqName.substring(lastPointIdx + 1); - } - return fqName; - } - @NotNull public static String getPackageName(@NotNull String fqName) { return getPackageName(fqName, '.'); @@ -1920,24 +1875,6 @@ public class StringUtil extends StringUtilRt { } } - public static int parseInt(final String string, final int defaultValue) { - try { - return Integer.parseInt(string); - } - catch (Exception e) { - return defaultValue; - } - } - - public static double parseDouble(final String string, final double defaultValue) { - try { - return Double.parseDouble(string); - } - catch (Exception e) { - return defaultValue; - } - } - public static int getOccurenceCount(@NotNull String text, final char c) { int res = 0; int i = 0; diff --git a/platform/util/src/com/intellij/util/ArrayUtil.java b/platform/util/src/com/intellij/util/ArrayUtil.java index 009c01f9ba77..a4f92f60f5a8 100644 --- a/platform/util/src/com/intellij/util/ArrayUtil.java +++ b/platform/util/src/com/intellij/util/ArrayUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 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. @@ -16,7 +16,6 @@ package com.intellij.util; import com.intellij.openapi.util.Comparing; -import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.CharArrayCharSequence; import gnu.trove.Equality; import org.jetbrains.annotations.NotNull; @@ -31,20 +30,20 @@ import java.util.List; /** * Author: msk */ -public class ArrayUtil { - public static final short[] EMPTY_SHORT_ARRAY = new short[0]; - public static final char[] EMPTY_CHAR_ARRAY = new char[0]; - public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; - public static final int[] EMPTY_INT_ARRAY = new int[0]; - public static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0]; - @SuppressWarnings({"SSBasedInspection"}) public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0]; - @SuppressWarnings({"SSBasedInspection"}) public static final String[] EMPTY_STRING_ARRAY = new String[0]; - @SuppressWarnings({"SSBasedInspection"}) public static final Class[] EMPTY_CLASS_ARRAY = new Class[0]; - public static final long[] EMPTY_LONG_ARRAY = new long[0]; - public static final Collection[] EMPTY_COLLECTION_ARRAY = new Collection[0]; +public class ArrayUtil extends ArrayUtilRt { + public static final short[] EMPTY_SHORT_ARRAY = ArrayUtilRt.EMPTY_SHORT_ARRAY; + public static final char[] EMPTY_CHAR_ARRAY = ArrayUtilRt.EMPTY_CHAR_ARRAY; + public static final byte[] EMPTY_BYTE_ARRAY = ArrayUtilRt.EMPTY_BYTE_ARRAY; + public static final int[] EMPTY_INT_ARRAY = ArrayUtilRt.EMPTY_INT_ARRAY; + public static final boolean[] EMPTY_BOOLEAN_ARRAY = ArrayUtilRt.EMPTY_BOOLEAN_ARRAY; + public static final Object[] EMPTY_OBJECT_ARRAY = ArrayUtilRt.EMPTY_OBJECT_ARRAY; + public static final String[] EMPTY_STRING_ARRAY = ArrayUtilRt.EMPTY_STRING_ARRAY; + public static final Class[] EMPTY_CLASS_ARRAY = ArrayUtilRt.EMPTY_CLASS_ARRAY; + public static final long[] EMPTY_LONG_ARRAY = ArrayUtilRt.EMPTY_LONG_ARRAY; + public static final Collection[] EMPTY_COLLECTION_ARRAY = ArrayUtilRt.EMPTY_COLLECTION_ARRAY; + public static final File[] EMPTY_FILE_ARRAY = ArrayUtilRt.EMPTY_FILE_ARRAY; + public static final Runnable[] EMPTY_RUNNABLE_ARRAY = ArrayUtilRt.EMPTY_RUNNABLE_ARRAY; public static final CharSequence EMPTY_CHAR_SEQUENCE = new CharArrayCharSequence(EMPTY_CHAR_ARRAY); - public static final File[] EMPTY_FILE_ARRAY = new File[0]; - public static final Runnable[] EMPTY_RUNNABLE_ARRAY = new Runnable[0]; public static final ArrayFactory STRING_ARRAY_FACTORY = new ArrayFactory() { @Override @@ -125,13 +124,13 @@ public class ArrayUtil { @NotNull public static T[] toObjectArray(@NotNull Collection collection, @NotNull Class aClass) { - T[] array = (T[])Array.newInstance(aClass, collection.size()); + @SuppressWarnings("unchecked") T[] array = (T[])Array.newInstance(aClass, collection.size()); return collection.toArray(array); } @NotNull public static T[] toObjectArray(@NotNull Class aClass, Object... source) { - T[] array = (T[])Array.newInstance(aClass, source.length); + @SuppressWarnings("unchecked") T[] array = (T[])Array.newInstance(aClass, source.length); System.arraycopy(source, 0, array, 0, array.length); return array; } @@ -143,12 +142,6 @@ public class ArrayUtil { return collection.toArray(new Object[collection.size()]); } - @NotNull - public static String[] toStringArray(@NotNull Collection collection) { - if (collection.isEmpty()) return EMPTY_STRING_ARRAY; - return ContainerUtil.toArray(collection, new String[collection.size()]); - } - @NotNull public static int[] toIntArray(@NotNull List list) { int[] ret = new int[list.size()]; diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java index 2e85f0996935..5f3b4e7f39c0 100644 --- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java +++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 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. @@ -29,10 +29,9 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.Array; import java.util.*; -import java.util.concurrent.CopyOnWriteArrayList; @SuppressWarnings({"UtilityClassWithoutPrivateConstructor", "unchecked"}) -public class ContainerUtil { +public class ContainerUtil extends ContainerUtilRt { private static final int INSERTION_SORT_THRESHOLD = 10; public static Map intersection(Map map1, Map map2) { @@ -290,34 +289,6 @@ public class ContainerUtil { return null; } - @NotNull - public static List map2List(@NotNull T[] array, @NotNull Function mapper) { - return map2List(Arrays.asList(array), mapper); - } - - @NotNull - public static List map2List(@NotNull Collection collection, @NotNull Function mapper) { - final ArrayList list = new ArrayList(collection.size()); - for (final T t : collection) { - list.add(mapper.fun(t)); - } - return list; - } - - @NotNull - public static Set map2Set(@NotNull T[] collection, @NotNull Function mapper) { - return map2Set(Arrays.asList(collection), mapper); - } - - @NotNull - public static Set map2Set(@NotNull Collection collection, @NotNull Function mapper) { - final HashSet set = new HashSet(collection.size()); - for (final T t : collection) { - set.add(mapper.fun(t)); - } - return set; - } - @NotNull public static Map map2Map(@NotNull T[] collection, @NotNull Function> mapper) { return map2Map(Arrays.asList(collection), mapper); @@ -736,38 +707,6 @@ public class ContainerUtil { public static T[] mergeCollectionsToArray(@NotNull Collection c1, @NotNull Collection c2, @NotNull ArrayFactory factory) { return ArrayUtil.mergeCollections(c1, c2, factory); } - - @NotNull - public static T[] toArray(@NotNull List collection, @NotNull T[] array) { - final int length = array.length; - if (length < 20) { - for (int i = 0; i < collection.size(); i++) { - array[i] = collection.get(i); - } - return array; - } - else { - return collection.toArray(array); - } - } - - /** - * This is a replacement for {@link Collection#toArray(Object[])}. For small collections it is faster to stay at java level and refrain - * from calling JNI {@link System#arraycopy(Object, int, Object, int, int)} - */ - @NotNull - public static T[] toArray(@NotNull Collection c, @NotNull T[] sample) { - final int size = c.size(); - if (size == sample.length && size < 20) { - int i = 0; - for (T t : c) { - sample[i++] = t; - } - return sample; - } - - return c.toArray(sample); - } public static > void sort(@NotNull List list) { int size = list.size(); @@ -980,17 +919,6 @@ public class ContainerUtil { return addAll(new HashSet(), items); } - public static void addIfNotNull(final T element, @NotNull Collection result) { - if (element != null) { - result.add(element); - } - } - public static void addIfNotNull(@NotNull Collection result, @Nullable final T element) { - if (element != null) { - result.add(element); - } - } - public static void putIfNotNull(final K key, @Nullable V value, @NotNull final Map result) { if (value != null) { result.put(key, value); @@ -1166,17 +1094,6 @@ public class ContainerUtil { } } - @NotNull - public static CopyOnWriteArrayList createEmptyCOWList() { - // does not create garbage new Object[0] - return new CopyOnWriteArrayList(ContainerUtil.emptyList()); - } - - @NotNull - public static List emptyList() { - return (List)EmptyList.INSTANCE; - } - /** * Merge sorted points, which are sorted by x and with equal x by y. * Result is put to x1 y1. @@ -1228,35 +1145,6 @@ public class ContainerUtil { y1.add(newY.toNativeArray()); } - /** - * has optimized toArray() as opposed to the {@link java.util.Collections#emptyList()} - */ - private static class EmptyList extends AbstractList implements RandomAccess { - private static final EmptyList INSTANCE = new EmptyList(); - - public int size() { - return 0; - } - - public boolean contains(Object obj) { - return false; - } - - public Object get(int index) { - throw new IndexOutOfBoundsException("Index: " + index); - } - - @Override - public Object[] toArray() { - return ArrayUtil.EMPTY_OBJECT_ARRAY; - } - - @Override - public T[] toArray(T[] a) { - return a; - } - } - @NotNull public static Set singleton(final T o, @NotNull final TObjectHashingStrategy strategy) { return new Set() { From 60a2342b4f9b614d9f99975de0bcc176a555e667 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 21 Mar 2012 09:41:36 +0100 Subject: [PATCH 090/106] Move util-rt logger to a more familiar place --- .../util/rt => com/intellij/openapi/diagnostic}/Logger.java | 2 +- platform/util-rt/src/org/jetbrains/util/rt/FileUtilRt.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) rename platform/util-rt/src/{org/jetbrains/util/rt => com/intellij/openapi/diagnostic}/Logger.java (99%) diff --git a/platform/util-rt/src/org/jetbrains/util/rt/Logger.java b/platform/util-rt/src/com/intellij/openapi/diagnostic/Logger.java similarity index 99% rename from platform/util-rt/src/org/jetbrains/util/rt/Logger.java rename to platform/util-rt/src/com/intellij/openapi/diagnostic/Logger.java index 58fc8da74727..802efe43b9c3 100644 --- a/platform/util-rt/src/org/jetbrains/util/rt/Logger.java +++ b/platform/util-rt/src/com/intellij/openapi/diagnostic/Logger.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.util.rt; +package com.intellij.openapi.diagnostic; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; diff --git a/platform/util-rt/src/org/jetbrains/util/rt/FileUtilRt.java b/platform/util-rt/src/org/jetbrains/util/rt/FileUtilRt.java index 9d92d5ee8512..5d4bd35a7cff 100644 --- a/platform/util-rt/src/org/jetbrains/util/rt/FileUtilRt.java +++ b/platform/util-rt/src/org/jetbrains/util/rt/FileUtilRt.java @@ -15,6 +15,7 @@ */ package org.jetbrains.util.rt; +import com.intellij.openapi.diagnostic.Logger; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; From 71f910e1cfecea63f8a5e61390581387540bffd1 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 21 Mar 2012 09:44:05 +0100 Subject: [PATCH 091/106] Move util-rt utility classes to a more familiar place --- .../src/org/jetbrains/jps/server/ClasspathBootstrap.java | 2 +- platform/util-rt/src/com/intellij/openapi/util/Comparing.java | 2 +- .../util/rt => com/intellij/openapi/util}/SystemInfoRt.java | 2 +- .../util/rt => com/intellij/openapi/util/io}/FileUtilRt.java | 4 +++- .../rt => com/intellij/openapi/util/text}/StringUtilRt.java | 2 +- platform/util/src/com/intellij/openapi/util/SystemInfo.java | 1 - platform/util/src/com/intellij/openapi/util/io/FileUtil.java | 1 - .../util/src/com/intellij/openapi/util/text/StringUtil.java | 1 - .../src/org/jetbrains/git4idea/ssh/GitSSHService.java | 2 +- plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMain.java | 2 +- .../src/org/jetbrains/git4idea/util/ScriptGenerator.java | 2 +- .../org/jetbrains/idea/maven/server/MavenServerManager.java | 2 +- 12 files changed, 11 insertions(+), 12 deletions(-) rename platform/util-rt/src/{org/jetbrains/util/rt => com/intellij/openapi/util}/SystemInfoRt.java (97%) rename platform/util-rt/src/{org/jetbrains/util/rt => com/intellij/openapi/util/io}/FileUtilRt.java (98%) rename platform/util-rt/src/{org/jetbrains/util/rt => com/intellij/openapi/util/text}/StringUtilRt.java (99%) diff --git a/jps/jps-builders/src/org/jetbrains/jps/server/ClasspathBootstrap.java b/jps/jps-builders/src/org/jetbrains/jps/server/ClasspathBootstrap.java index e8d70f0e3f1b..ffc4b7efff97 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/server/ClasspathBootstrap.java +++ b/jps/jps-builders/src/org/jetbrains/jps/server/ClasspathBootstrap.java @@ -29,7 +29,7 @@ import org.codehaus.groovy.GroovyException; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.MacroExpander; import org.jetbrains.jps.javac.JavacServer; -import org.jetbrains.util.rt.FileUtilRt; +import com.intellij.openapi.util.io.FileUtilRt; import org.objectweb.asm.ClassWriter; import javax.tools.*; diff --git a/platform/util-rt/src/com/intellij/openapi/util/Comparing.java b/platform/util-rt/src/com/intellij/openapi/util/Comparing.java index 4c9d7dd1a1bb..95c7d6df8676 100644 --- a/platform/util-rt/src/com/intellij/openapi/util/Comparing.java +++ b/platform/util-rt/src/com/intellij/openapi/util/Comparing.java @@ -15,7 +15,7 @@ */ package com.intellij.openapi.util; -import org.jetbrains.util.rt.StringUtilRt; +import com.intellij.openapi.util.text.StringUtilRt; import java.util.Arrays; import java.util.Collection; diff --git a/platform/util-rt/src/org/jetbrains/util/rt/SystemInfoRt.java b/platform/util-rt/src/com/intellij/openapi/util/SystemInfoRt.java similarity index 97% rename from platform/util-rt/src/org/jetbrains/util/rt/SystemInfoRt.java rename to platform/util-rt/src/com/intellij/openapi/util/SystemInfoRt.java index 6b3dd54260af..cdce6e247e32 100644 --- a/platform/util-rt/src/org/jetbrains/util/rt/SystemInfoRt.java +++ b/platform/util-rt/src/com/intellij/openapi/util/SystemInfoRt.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.util.rt; +package com.intellij.openapi.util; /** * Stripped-down version of {@code com.intellij.openapi.util.SystemInfo}. diff --git a/platform/util-rt/src/org/jetbrains/util/rt/FileUtilRt.java b/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java similarity index 98% rename from platform/util-rt/src/org/jetbrains/util/rt/FileUtilRt.java rename to platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java index 5d4bd35a7cff..d9e3d5c56bd9 100644 --- a/platform/util-rt/src/org/jetbrains/util/rt/FileUtilRt.java +++ b/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java @@ -13,13 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.util.rt; +package com.intellij.openapi.util.io; import com.intellij.openapi.diagnostic.Logger; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; +import com.intellij.openapi.util.text.StringUtilRt; +import com.intellij.openapi.util.SystemInfoRt; import java.io.*; import java.util.UUID; diff --git a/platform/util-rt/src/org/jetbrains/util/rt/StringUtilRt.java b/platform/util-rt/src/com/intellij/openapi/util/text/StringUtilRt.java similarity index 99% rename from platform/util-rt/src/org/jetbrains/util/rt/StringUtilRt.java rename to platform/util-rt/src/com/intellij/openapi/util/text/StringUtilRt.java index 9698ac290056..9b98436709b8 100644 --- a/platform/util-rt/src/org/jetbrains/util/rt/StringUtilRt.java +++ b/platform/util-rt/src/com/intellij/openapi/util/text/StringUtilRt.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.util.rt; +package com.intellij.openapi.util.text; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/platform/util/src/com/intellij/openapi/util/SystemInfo.java b/platform/util/src/com/intellij/openapi/util/SystemInfo.java index 6e13a9f1cb71..4022b3210a61 100644 --- a/platform/util/src/com/intellij/openapi/util/SystemInfo.java +++ b/platform/util/src/com/intellij/openapi/util/SystemInfo.java @@ -17,7 +17,6 @@ package com.intellij.openapi.util; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.util.rt.SystemInfoRt; import java.io.File; import java.util.List; diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java index 393d1a6ae079..c21488878104 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java @@ -34,7 +34,6 @@ import org.intellij.lang.annotations.RegExp; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.util.rt.FileUtilRt; import java.io.*; import java.lang.reflect.Method; diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index b2fd28e88334..c687682275dd 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -27,7 +27,6 @@ import com.intellij.util.text.LineReader; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.util.rt.StringUtilRt; import java.beans.Introspector; import java.io.ByteArrayInputStream; diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHService.java b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHService.java index 430ea6f0b8ba..c262e41d4266 100644 --- a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHService.java +++ b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHService.java @@ -22,7 +22,7 @@ import org.apache.xmlrpc.XmlRpcClientLite; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.git4idea.util.ScriptGenerator; -import org.jetbrains.util.rt.FileUtilRt; +import com.intellij.openapi.util.io.FileUtilRt; import java.io.File; import java.io.IOException; diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMain.java b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMain.java index bc3737565480..ed9f9b3fdd62 100644 --- a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMain.java +++ b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMain.java @@ -20,7 +20,7 @@ import com.trilead.ssh2.*; import com.trilead.ssh2.crypto.PEMDecoder; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; -import org.jetbrains.util.rt.FileUtilRt; +import com.intellij.openapi.util.io.FileUtilRt; import java.io.*; import java.util.*; diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/util/ScriptGenerator.java b/plugins/git4idea/src/org/jetbrains/git4idea/util/ScriptGenerator.java index a2903ae32095..ffdb80c526cd 100644 --- a/plugins/git4idea/src/org/jetbrains/git4idea/util/ScriptGenerator.java +++ b/plugins/git4idea/src/org/jetbrains/git4idea/util/ScriptGenerator.java @@ -21,7 +21,7 @@ import com.intellij.util.PathUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; -import org.jetbrains.util.rt.FileUtilRt; +import com.intellij.openapi.util.io.FileUtilRt; import java.io.File; import java.io.FileWriter; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java index 7f5b8f685c76..d19ce28b6230 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java @@ -58,7 +58,7 @@ import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.utils.MavenLog; import org.jetbrains.idea.maven.utils.MavenProgressIndicator; import org.jetbrains.idea.maven.utils.MavenUtil; -import org.jetbrains.util.rt.SystemInfoRt; +import com.intellij.openapi.util.SystemInfoRt; import java.io.File; import java.nio.charset.Charset; From 205cdd5b59d43807cff9786bb3fde83f85cc280f Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 21 Mar 2012 10:03:27 +0100 Subject: [PATCH 092/106] Move util-rt logger to a non-conflicting location --- .../com/intellij/openapi/diagnostic/{ => rt}/Logger.java | 2 +- .../src/com/intellij/openapi/util/io/FileUtilRt.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename platform/util-rt/src/com/intellij/openapi/diagnostic/{ => rt}/Logger.java (99%) diff --git a/platform/util-rt/src/com/intellij/openapi/diagnostic/Logger.java b/platform/util-rt/src/com/intellij/openapi/diagnostic/rt/Logger.java similarity index 99% rename from platform/util-rt/src/com/intellij/openapi/diagnostic/Logger.java rename to platform/util-rt/src/com/intellij/openapi/diagnostic/rt/Logger.java index 802efe43b9c3..8eb116e18585 100644 --- a/platform/util-rt/src/com/intellij/openapi/diagnostic/Logger.java +++ b/platform/util-rt/src/com/intellij/openapi/diagnostic/rt/Logger.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.openapi.diagnostic; +package com.intellij.openapi.diagnostic.rt; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; diff --git a/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java b/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java index d9e3d5c56bd9..ff77c63af49c 100644 --- a/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java +++ b/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java @@ -15,13 +15,13 @@ */ package com.intellij.openapi.util.io; -import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.diagnostic.rt.Logger; +import com.intellij.openapi.util.SystemInfoRt; +import com.intellij.openapi.util.text.StringUtilRt; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; -import com.intellij.openapi.util.text.StringUtilRt; -import com.intellij.openapi.util.SystemInfoRt; import java.io.*; import java.util.UUID; From 4ba6b0c1a412c75d75985aeddff4cd636861eb5b Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 21 Mar 2012 10:17:21 +0100 Subject: [PATCH 093/106] VcsRoot#toString --- .../vcs-api/src/com/intellij/openapi/vcs/VcsRoot.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsRoot.java b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsRoot.java index d43190347b75..c05995636b45 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsRoot.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsRoot.java @@ -52,4 +52,12 @@ public class VcsRoot { } return hashcode; } + + @Override + public String toString() { + return "VcsRoot{" + + "vcs=" + vcs + + ", path=" + path + + '}'; + } } \ No newline at end of file From ffbb4473f56bd43a2fdba31762ac309375db2e8c Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 21 Mar 2012 10:25:31 +0100 Subject: [PATCH 094/106] FilePathUnderVcs#toString --- .../intellij/openapi/vcs/changes/FilePathUnderVcs.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FilePathUnderVcs.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FilePathUnderVcs.java index 61b1c353590f..b5e0e447a739 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FilePathUnderVcs.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FilePathUnderVcs.java @@ -65,4 +65,12 @@ public class FilePathUnderVcs { } return hashcode; } + + @Override + public String toString() { + return "FilePathUnderVcs{" + + "myPath=" + myPath + + ", myVcs=" + myVcs + + '}'; + } } From 2ed1832ba76cb0b44316a1a74b60ce8cd4e0acd5 Mon Sep 17 00:00:00 2001 From: irengrig Date: Wed, 21 Mar 2012 13:40:20 +0400 Subject: [PATCH 095/106] IDEA-82748 SVN Commit Failed with Error E155007 after update to 116.108 --- .../idea/svn/checkin/SvnCheckinEnvironment.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java index ffd784799587..c265a4969d3f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java @@ -25,6 +25,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.CheckinProjectPanel; import com.intellij.openapi.vcs.FilePath; @@ -176,17 +177,21 @@ public class SvnCheckinEnvironment implements CheckinEnvironment { return Collections.singletonList(committables); } - final MultiMap result = new MultiMap(); + final MultiMap, File> result = new MultiMap, File>(); for (File committable : committables) { final RootUrlInfo path = mySvnVcs.getSvnFileUrlMapping().getWcRootForFilePath(committable); - result.putValue(path == null ? null : path.getRepositoryUrlUrl(), committable); + if (path == null) { + result.putValue(new Pair(null, null), committable); + } else { + result.putValue(new Pair(path.getRepositoryUrlUrl(), path.getFormat()), committable); + } } if (result.size() == 1) { return Collections.singletonList(committables); } final Collection> result2 = new ArrayList>(); - for (Map.Entry> entry : result.entrySet()) { + for (Map.Entry, Collection> entry : result.entrySet()) { result2.add(entry.getValue()); } return result2; From 71e4960ffab0bd71bd101550832ac1ffcd8f57bc Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 21 Mar 2012 10:54:54 +0100 Subject: [PATCH 096/106] Reorder JARs task dependencies once again --- build/update.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/build/update.xml b/build/update.xml index ebef6ac3cc2b..5372bd479360 100644 --- a/build/update.xml +++ b/build/update.xml @@ -49,6 +49,7 @@ + From 5ffd29ad22dc4b3fcb8018bfbeef00d38e646630 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 21 Mar 2012 11:16:19 +0100 Subject: [PATCH 097/106] Extract git runtime module --- .idea/modules.xml | 1 + build/scripts/layouts.gant | 3 + .../util-rt/src/com/intellij/BundleBase.java | 109 ++++++++++++++++++ .../util/src/com/intellij/CommonBundle.java | 44 +------ .../util/src/com/intellij/util/ui/UIUtil.java | 41 +------ plugins/git4idea/git4idea.iml | 1 + plugins/git4idea/rt/git4idea-rt.iml | 26 +++++ .../jetbrains/git4idea/ssh/GitSSHHandler.java | 2 +- .../git4idea/ssh/GitSSHXmlRpcClient.java | 4 +- .../org/jetbrains/git4idea/ssh/SSHConfig.java | 2 +- .../org/jetbrains/git4idea/ssh/SSHMain.java | 12 +- .../jetbrains/git4idea/ssh/SSHMainBundle.java | 10 +- .../git4idea/ssh/SSHMainBundle.properties | 0 13 files changed, 161 insertions(+), 94 deletions(-) create mode 100644 platform/util-rt/src/com/intellij/BundleBase.java create mode 100644 plugins/git4idea/rt/git4idea-rt.iml rename plugins/git4idea/{ => rt}/src/org/jetbrains/git4idea/ssh/GitSSHHandler.java (99%) rename plugins/git4idea/{ => rt}/src/org/jetbrains/git4idea/ssh/GitSSHXmlRpcClient.java (98%) rename plugins/git4idea/{ => rt}/src/org/jetbrains/git4idea/ssh/SSHConfig.java (99%) rename plugins/git4idea/{ => rt}/src/org/jetbrains/git4idea/ssh/SSHMain.java (98%) rename plugins/git4idea/{ => rt}/src/org/jetbrains/git4idea/ssh/SSHMainBundle.java (90%) rename plugins/git4idea/{ => rt}/src/org/jetbrains/git4idea/ssh/SSHMainBundle.properties (100%) diff --git a/.idea/modules.xml b/.idea/modules.xml index b4b07b103f8d..553b6854a1ac 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -41,6 +41,7 @@ + diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index bb5439064698..07361cb807b2 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -250,6 +250,9 @@ public def layoutCommunityPlugins(String home) { } layoutPlugin("git4idea") { + jar("git4idea-rt.jar") { + module("git4idea-rt") + } fileset(dir: "$home/plugins/git4idea/lib") { include(name: "trilead-ssh2.jar") } diff --git a/platform/util-rt/src/com/intellij/BundleBase.java b/platform/util-rt/src/com/intellij/BundleBase.java new file mode 100644 index 000000000000..566be37adda1 --- /dev/null +++ b/platform/util-rt/src/com/intellij/BundleBase.java @@ -0,0 +1,109 @@ +/* + * 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. + * 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; + +import com.intellij.openapi.util.SystemInfoRt; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * @author yole + */ +public abstract class BundleBase { + public static final char MNEMONIC = 0x1B; + + public static boolean assertKeyIsFound = false; + + public static String messageOrDefault(@Nullable final ResourceBundle bundle, + final String key, + @Nullable final String defaultValue, + final Object... params) { + if (bundle == null) return defaultValue; + + String value; + try { + value = bundle.getString(key); + } + catch (MissingResourceException e) { + if (defaultValue != null) { + value = defaultValue; + } + else { + value = "!" + key + "!"; + if (assertKeyIsFound) { + assert false : key + " is not found in " + bundle; + } + } + } + + value = replaceMnemonicAmpersand(value); + + if (params.length > 0 && value.indexOf('{') >= 0) { + return MessageFormat.format(value, params); + } + + return value; + } + + @NotNull + public static String message(@NotNull ResourceBundle bundle, @NotNull String key, @NotNull Object... params) { + return messageOrDefault(bundle, key, null, params); + } + + public static String replaceMnemonicAmpersand(final String value) { + if (value.indexOf('&') >= 0) { + boolean useMacMnemonic = value.contains("&&"); + StringBuilder realValue = new StringBuilder(); + int i = 0; + while (i < value.length()) { + char c = value.charAt(i); + if (c == '\\') { + if (i < value.length() - 1 && value.charAt(i + 1) == '&') { + realValue.append('&'); + i++; + } + else { + realValue.append(c); + } + } + else if (c == '&') { + if (i < value.length() - 1 && value.charAt(i + 1) == '&') { + if (SystemInfoRt.isMac) { + realValue.append(MNEMONIC); + } + i++; + } + else { + if (!SystemInfoRt.isMac || !useMacMnemonic) { + realValue.append(MNEMONIC); + } + } + } + else { + realValue.append(c); + } + i++; + } + + return realValue.toString(); + } + return value; + } +} diff --git a/platform/util/src/com/intellij/CommonBundle.java b/platform/util/src/com/intellij/CommonBundle.java index 19a540d3ae6f..941ce72fdd19 100644 --- a/platform/util/src/com/intellij/CommonBundle.java +++ b/platform/util/src/com/intellij/CommonBundle.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. @@ -16,25 +16,22 @@ package com.intellij; -import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.PropertyKey; import java.lang.ref.Reference; import java.lang.ref.SoftReference; -import java.text.MessageFormat; -import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author yole */ -public class CommonBundle { +public class CommonBundle extends BundleBase { + public static boolean assertKeyIsFound = false; + @NonNls private static final String BUNDLE = "messages.CommonBundle"; private static Reference ourBundle; - public static boolean assertKeyIsFound = false; private CommonBundle() {} @@ -53,38 +50,6 @@ public class CommonBundle { return bundle; } - public static String messageOrDefault(@Nullable final ResourceBundle bundle, final String key, @Nullable final String defaultValue, final Object... params) { - if (bundle == null) return defaultValue; - - String value; - try { - value = bundle.getString(key); - } - catch (MissingResourceException e) { - if (defaultValue != null) { - value = defaultValue; - } else { - value = "!" + key + "!"; - if (assertKeyIsFound) { - assert false: key + " is not found in "+BUNDLE; - } - } - } - - value = UIUtil.replaceMnemonicAmpersand(value); - - if (params.length > 0 && value.indexOf('{')>=0) { - return MessageFormat.format(value, params); - } - - return value; - } - - @NotNull - public static String message(@NotNull ResourceBundle bundle, @NotNull String key, @NotNull Object... params) { - return messageOrDefault(bundle, key, null, params); - } - @NotNull public static String getCancelButtonText() { return message("button.cancel"); @@ -142,5 +107,4 @@ public class CommonBundle { public static String getApplyButtonText() { return message("button.apply"); } - } diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index b4740ec6c465..002432d18d20 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -15,6 +15,7 @@ */ package com.intellij.util.ui; +import com.intellij.BundleBase; import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.*; @@ -100,7 +101,7 @@ public class UIUtil { public enum ComponentStyle {REGULAR, SMALL, MINI} public enum FontColor {NORMAL, BRIGHTER} - public static final char MNEMONIC = 0x1B; + public static final char MNEMONIC = BundleBase.MNEMONIC; @NonNls public static final String HTML_MIME = "text/html"; @NonNls public static final String JSLIDER_ISFILLED = "JSlider.isFilled"; @NonNls public static final String ARIAL_FONT_NAME = "Arial"; @@ -384,43 +385,7 @@ public class UIUtil { } public static String replaceMnemonicAmpersand(final String value) { - if (value.indexOf('&') >= 0) { - boolean useMacMnemonic = value.contains("&&"); - StringBuilder realValue = new StringBuilder(); - int i = 0; - while (i < value.length()) { - char c = value.charAt(i); - if (c == '\\') { - if (i < value.length() - 1 && value.charAt(i + 1) == '&') { - realValue.append('&'); - i++; - } - else { - realValue.append(c); - } - } - else if (c == '&') { - if (i < value.length() - 1 && value.charAt(i + 1) == '&') { - if (SystemInfo.isMac) { - realValue.append(MNEMONIC); - } - i++; - } - else { - if (!SystemInfo.isMac || !useMacMnemonic) { - realValue.append(MNEMONIC); - } - } - } - else { - realValue.append(c); - } - i++; - } - - return realValue.toString(); - } - return value; + return BundleBase.replaceMnemonicAmpersand(value); } public static Color getTableHeaderBackground() { diff --git a/plugins/git4idea/git4idea.iml b/plugins/git4idea/git4idea.iml index 733b2cb41b6a..6b8c1cb32ef8 100644 --- a/plugins/git4idea/git4idea.iml +++ b/plugins/git4idea/git4idea.iml @@ -34,6 +34,7 @@ + diff --git a/plugins/git4idea/rt/git4idea-rt.iml b/plugins/git4idea/rt/git4idea-rt.iml new file mode 100644 index 000000000000..62b44f66acf7 --- /dev/null +++ b/plugins/git4idea/rt/git4idea-rt.iml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHHandler.java b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHHandler.java similarity index 99% rename from plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHHandler.java rename to plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHHandler.java index ae9384fd46fd..c5ed99e20966 100644 --- a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHHandler.java +++ b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHHandler.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. diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHXmlRpcClient.java b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHXmlRpcClient.java similarity index 98% rename from plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHXmlRpcClient.java rename to plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHXmlRpcClient.java index 83d9cd325aaa..0f2f668a5caf 100644 --- a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/GitSSHXmlRpcClient.java +++ b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/GitSSHXmlRpcClient.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. @@ -83,7 +83,7 @@ public class GitSSHXmlRpcClient implements GitSSHHandler { * @return full method name */ private static String methodName(@NonNls final String method) { - return HANDLER_NAME + "." + method; + return GitSSHHandler.HANDLER_NAME + "." + method; } /** diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHConfig.java b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHConfig.java similarity index 99% rename from plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHConfig.java rename to plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHConfig.java index 00a065da7114..5799db2270f4 100644 --- a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHConfig.java +++ b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHConfig.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. diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMain.java b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMain.java similarity index 98% rename from plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMain.java rename to plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMain.java index ed9f9b3fdd62..858a2d3e0317 100644 --- a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMain.java +++ b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMain.java @@ -15,12 +15,12 @@ */ package org.jetbrains.git4idea.ssh; -import com.intellij.util.ArrayUtil; +import com.intellij.openapi.util.io.FileUtilRt; +import com.intellij.util.ArrayUtilRt; import com.trilead.ssh2.*; import com.trilead.ssh2.crypto.PEMDecoder; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; -import com.intellij.openapi.util.io.FileUtilRt; import java.io.*; import java.util.*; @@ -368,7 +368,7 @@ public class SSHMain { String line; while ((line = in.readLine()) != null) { //noinspection HardCodedStringLiteral - if (line.startsWith("Proc-Type: ") && line.indexOf("ENCRYPTED") != -1) { + if (line.startsWith("Proc-Type: ") && line.contains("ENCRYPTED")) { return true; } if (line.length() == 0) { @@ -445,7 +445,7 @@ public class SSHMain { database.addHostkeys(knownHostFile); } final List algorithms = myHost.getHostKeyAlgorithms(); - c.setServerHostKeyAlgorithms(ArrayUtil.toStringArray(algorithms)); + c.setServerHostKeyAlgorithms(ArrayUtilRt.toStringArray(algorithms)); } /** @@ -506,7 +506,7 @@ public class SSHMain { final String[] prompt, final boolean[] echo) throws Exception { if (numPrompts == 0) { - return ArrayUtil.EMPTY_STRING_ARRAY; + return ArrayUtilRt.EMPTY_STRING_ARRAY; } myPromptCount++; Vector vPrompts = new Vector(prompt.length); @@ -524,7 +524,7 @@ public class SSHMain { return rc; } else { - return ArrayUtil.toStringArray(result); + return ArrayUtilRt.toStringArray(result); } } } diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMainBundle.java b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMainBundle.java similarity index 90% rename from plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMainBundle.java rename to plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMainBundle.java index 0a5122fc9b9c..507d1fc52919 100644 --- a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMainBundle.java +++ b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMainBundle.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. @@ -15,7 +15,7 @@ */ package org.jetbrains.git4idea.ssh; -import com.intellij.CommonBundle; +import com.intellij.BundleBase; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.PropertyKey; @@ -32,11 +32,10 @@ public class SSHMainBundle { @NonNls private static final String BUNDLE = "org.jetbrains.git4idea.ssh.SSHMainBundle"; - private SSHMainBundle() { - } + private SSHMainBundle() { } public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) { - return CommonBundle.message(getBundle(), key, params); + return BundleBase.message(getBundle(), key, params); } private static ResourceBundle getBundle() { @@ -52,5 +51,4 @@ public class SSHMainBundle { public static String getString(@PropertyKey(resourceBundle = BUNDLE) final String key) { return getBundle().getString(key); } - } diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMainBundle.properties b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMainBundle.properties similarity index 100% rename from plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHMainBundle.properties rename to plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMainBundle.properties From addebb5e34585ff7ce331fbd4176cb0cc6bea708 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Wed, 21 Mar 2012 14:10:40 +0400 Subject: [PATCH 098/106] IDEA-82839 Skip too complex methods in Groovy DFA analysis --- .../plugins/groovy/GroovyBundle.properties | 2 ++ .../groovy/annotator/GroovyAnnotator.java | 21 ++++++++++++++ .../unusedDef/UnusedDefInspection.java | 6 +++- .../utils/ControlFlowUtils.java | 16 +++++----- .../groovy/lang/psi/dataFlow/DFAEngine.java | 23 ++++++++++++++- .../ReachingDefinitionsCollector.java | 29 ++++++++++--------- .../lang/psi/impl/TypeInferenceHelper.java | 11 +++++-- 7 files changed, 82 insertions(+), 26 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties index c3735295a072..57c820df5558 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties @@ -302,3 +302,5 @@ method.with.type.parameters.should.have.return.type=Method with type parameters primitive.type.parameters.are.not.allowed=Primitive type parameters are not allowed primitive.bound.types.are.not.allowed=Primitive bound types are not allowed ellipsis.type.is.not.allowed.here=Ellipsis type is not allowed here +method.0.is.too.complex.too.analyze=Method ''{0}'' is too complex to analyze.\nTypes of local variables are not inferred. +closure.is.too.complex.to.analyze=Closure is complex to analyze.\nTypes of local variables are not inferred. diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index 3a81c5db8a1d..a9ff9c221209 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -99,6 +99,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatem import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.types.*; import org.jetbrains.plugins.groovy.lang.psi.api.util.GrVariableDeclarationOwner; +import org.jetbrains.plugins.groovy.lang.psi.impl.TypeInferenceHelper; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightParameter; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; @@ -532,6 +533,12 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { checkMethodWithTypeParamsShouldHaveReturnType(myHolder, method); checkInnerMethod(myHolder, method); checkMethodParameters(myHolder, method); + + GrOpenBlock block = method.getBlock(); + if (block != null && TypeInferenceHelper.isTooComplexTooAnalyze(block)) { + myHolder.createWeakWarningAnnotation(method.getNameIdentifierGroovy(), GroovyBundle.message("method.0.is.too.complex.too.analyze", + method.getName())); + } } private static void checkMethodWithTypeParamsShouldHaveReturnType(AnnotationHolder holder, GrMethod method) { @@ -936,6 +943,20 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { if (!closure.hasParametersSection() && isClosureAmbiguous(closure)) { myHolder.createErrorAnnotation(closure, GroovyBundle.message("ambiguous.code.block")); } + + if (TypeInferenceHelper.isTooComplexTooAnalyze(closure)) { + int startOffset = closure.getLBrace().getTextRange().getStartOffset(); + int endOffset; + if (closure.getArrow()!=null) { + endOffset = closure.getArrow().getTextRange().getEndOffset(); + } + else { + String text = + PsiDocumentManager.getInstance(closure.getProject()).getDocument(closure.getContainingFile()).getText(); + endOffset = Math.min(closure.getTextRange().getEndOffset(), text.indexOf('\n', startOffset)); + } + myHolder.createWeakWarningAnnotation(new TextRange(startOffset, endOffset), GroovyBundle.message("closure.is.too.complex.to.analyze")); + } } private static boolean isClosureAmbiguous(GrClosableBlock closure) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java index da1bd028bac2..4bb6ad43dfae 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java @@ -83,7 +83,11 @@ public class UnusedDefInspection extends GroovyLocalInspectionBase { final ReachingDefinitionsDfaInstance dfaInstance = new ReachingDefinitionsDfaInstance(flow); final ReachingDefinitionsSemilattice lattice = new ReachingDefinitionsSemilattice(); final DFAEngine> engine = new DFAEngine>(flow, dfaInstance, lattice); - final List> dfaResult = engine.performDFA(); + final List> dfaResult = engine.performDFAWithTimeout(); + if (dfaResult == null) { + return; + } + final TIntHashSet unusedDefs = new TIntHashSet(); for (Instruction instruction : flow) { if (instruction instanceof ReadWriteVariableInstruction && ((ReadWriteVariableInstruction) instruction).isWrite()) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java index 18fb9b913a0c..bd663678c098 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java @@ -153,17 +153,13 @@ public class ControlFlowUtils { if (openBlockMayCompleteNormally(tryBlock)) { return true; } - final GrCatchClause[] catchClauses = tryStatement.getCatchClauses(); - if (catchClauses != null) { - - for (GrCatchClause catchClause : catchClauses) { - if (openBlockMayCompleteNormally(catchClause.getBody())) { - return true; - } + for (GrCatchClause catchClause : tryStatement.getCatchClauses()) { + if (openBlockMayCompleteNormally(catchClause.getBody())) { + return true; } - } + return false; } @@ -650,6 +646,7 @@ public class ControlFlowUtils { place = place.getContext(); } while (true) { + assert place != null; place = place.getContext(); if (place == null) return null; if (place instanceof GrClosableBlock) return (GrClosableBlock)place; @@ -740,6 +737,7 @@ public class ControlFlowUtils { }); } + @NotNull public static ArrayList inferWriteAccessMap(final Instruction[] flow, final GrVariable var) { final Semilattice sem = new Semilattice() { @@ -790,7 +788,7 @@ public class ControlFlowUtils { } }; - return new DFAEngine(flow, dfa, sem).performDFA(); + return new DFAEngine(flow, dfa, sem).performForceDFA(); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/DFAEngine.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/DFAEngine.java index 72e975a3b555..0db8157ec869 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/DFAEngine.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/DFAEngine.java @@ -16,6 +16,8 @@ package org.jetbrains.plugins.groovy.lang.psi.dataFlow; import com.intellij.openapi.progress.ProgressManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.CallEnvironment; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.CallInstruction; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.ControlFlowBuilderUtil; @@ -27,6 +29,8 @@ import java.util.*; * @author ven */ public class DFAEngine { + private static final long ourTimeLimit = 1000; + private final Instruction[] myFlow; private final DfaInstance myDfa; @@ -57,7 +61,22 @@ public class DFAEngine { } } - public ArrayList performDFA() { + @NotNull + public ArrayList performForceDFA() { + ArrayList result = performDFA(false); + assert result != null; + return result; + } + + @Nullable + public ArrayList performDFAWithTimeout() { + return performDFA(true); + } + + @Nullable + private ArrayList performDFA(boolean timeout) { + long startTime = System.currentTimeMillis(); + ArrayList info = new ArrayList(myFlow.length); CallEnvironment env = new MyCallEnvironment(myFlow.length); for (int i = 0; i < myFlow.length; i++) { @@ -78,6 +97,8 @@ public class DFAEngine { visited[instr.num()] = true; while (!workList.isEmpty()) { + if (timeout && System.currentTimeMillis() - startTime > ourTimeLimit) return null; + ProgressManager.checkCanceled(); final Instruction curr = workList.remove(); final int num = curr.num(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/reachingDefs/ReachingDefinitionsCollector.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/reachingDefs/ReachingDefinitionsCollector.java index ad34f71449f4..4ebd0621742f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/reachingDefs/ReachingDefinitionsCollector.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/reachingDefs/ReachingDefinitionsCollector.java @@ -53,6 +53,7 @@ public class ReachingDefinitionsCollector { private ReachingDefinitionsCollector() { } + @NotNull public static FragmentVariableInfos obtainVariableFlowInformation(final GrStatement first, final GrStatement last) { GroovyPsiElement context = PsiTreeUtil.getParentOfType(first, GrMethod.class, GrClosableBlock.class, GroovyFileBase.class, GrClassInitializer.class); GrControlFlowOwner flowOwner; @@ -66,7 +67,7 @@ public class ReachingDefinitionsCollector { final ReachingDefinitionsDfaInstance dfaInstance = new ReachingDefinitionsDfaInstance(flow); final ReachingDefinitionsSemilattice lattice = new ReachingDefinitionsSemilattice(); final DFAEngine> engine = new DFAEngine>(flow, dfaInstance, lattice); - final TIntObjectHashMap dfaResult = postprocess(engine.performDFA(), flow, dfaInstance); + final TIntObjectHashMap dfaResult = postprocess(engine.performForceDFA(), flow, dfaInstance); final LinkedHashSet fragmentInstructions = getFragmentInstructions(first, last, flow); final int[] postorder = ControlFlowBuilderUtil.postorder(flow); @@ -149,16 +150,15 @@ public class ReachingDefinitionsCollector { } String name = variable.getName(); - if (name != null) { - if (!(variable instanceof GrField)) { - if (!isInFragment(first, last, resolved)) { - if (isInFragment(first, last, closure)) { - addVariable(name, imap, variable.getManager(), variable.getType()); - } - } else { - if (!isInFragment(first, last, closure)) { - addVariable(name, omap, variable.getManager(), variable.getType()); - } + if (!(variable instanceof GrField)) { + if (!isInFragment(first, last, resolved)) { + if (isInFragment(first, last, closure)) { + addVariable(name, imap, variable.getManager(), variable.getType()); + } + } + else { + if (!isInFragment(first, last, closure)) { + addVariable(name, omap, variable.getManager(), variable.getType()); } } } @@ -306,7 +306,7 @@ public class ReachingDefinitionsCollector { final StringBuffer buffer = new StringBuffer(); for (int i = 0; i < dfaResult.size(); i++) { TIntObjectHashMap map = dfaResult.get(i); - buffer.append("At " + i + ":\n"); + buffer.append("At ").append(i).append(":\n"); map.forEachEntry(new TIntObjectProcedure() { public boolean execute(int i, TIntHashSet defs) { buffer.append(i).append(" -> "); @@ -366,7 +366,10 @@ public class ReachingDefinitionsCollector { } } - private static TIntObjectHashMap postprocess(final ArrayList> dfaResult, Instruction[] flow, ReachingDefinitionsDfaInstance dfaInstance) { + @NotNull + private static TIntObjectHashMap postprocess(@NotNull final ArrayList> dfaResult, + @NotNull Instruction[] flow, + @NotNull ReachingDefinitionsDfaInstance dfaInstance) { TIntObjectHashMap result = new TIntObjectHashMap(); for (int i = 0; i < flow.length; i++) { Instruction insn = flow[i]; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/TypeInferenceHelper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/TypeInferenceHelper.java index edc9c60ee6c4..ddcbd868464c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/TypeInferenceHelper.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/TypeInferenceHelper.java @@ -89,6 +89,10 @@ public class TypeInferenceHelper { return getInferredType(variableName, instruction, flow, scope); } + public static boolean isTooComplexTooAnalyze(GrControlFlowOwner scope) { + return getDefUseMaps(scope).second == null; + } + @Nullable private static Instruction findInstructionAt(PsiElement place, Instruction[] flow) { List applicable = new ArrayList(); @@ -131,7 +135,10 @@ public class TypeInferenceHelper { final Pair>> pair = getDefUseMaps(scope); final int varIndex = pair.first.getVarIndex(varName); - final TIntObjectHashMap allDefs = pair.second.get(instruction.num()); + List> second = pair.second; + if (second == null) return null; + + final TIntObjectHashMap allDefs = second.get(instruction.num()); final TIntHashSet varDefs = allDefs.get(varIndex); if (varDefs == null) return null; @@ -174,7 +181,7 @@ public class TypeInferenceHelper { }; final ReachingDefinitionsSemilattice lattice = new ReachingDefinitionsSemilattice(); final DFAEngine> engine = new DFAEngine>(flow, dfaInstance, lattice); - final List> dfaResult = engine.performDFA(); + final List> dfaResult = engine.performDFAWithTimeout(); return Result.create(Pair.create(dfaInstance, dfaResult), PsiModificationTracker.MODIFICATION_COUNT); } }); From cb69dc3a6208df3182b42a78749a948a04a5bc80 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Mar 2012 18:20:07 +0100 Subject: [PATCH 099/106] avoid SOE via getText (EA-34046) --- .../src/com/intellij/extapi/psi/StubBasedPsiElementBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/core-impl/src/com/intellij/extapi/psi/StubBasedPsiElementBase.java b/platform/core-impl/src/com/intellij/extapi/psi/StubBasedPsiElementBase.java index 588957ca7594..1477e2344d70 100644 --- a/platform/core-impl/src/com/intellij/extapi/psi/StubBasedPsiElementBase.java +++ b/platform/core-impl/src/com/intellij/extapi/psi/StubBasedPsiElementBase.java @@ -111,7 +111,7 @@ public class StubBasedPsiElementBase extends ASTDelegateP "; stubTree=" + stubTree; PsiElement each = this; while (each != null) { - message += "\n each=" + each + " of class " + each.getClass(); + message += "\n each of class " + each.getClass(); if (each instanceof StubBasedPsiElementBase) { message += "; node=" + ((StubBasedPsiElementBase)each).myNode + "; stub=" + ((StubBasedPsiElementBase)each).myStub; each = ((StubBasedPsiElementBase)each).getParentByStub(); From 2fa78de9fb5d2b227416435bc0603f8a98c5cb51 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 20 Mar 2012 18:25:27 +0100 Subject: [PATCH 100/106] more info on EA-34347 --- .../com/intellij/codeInsight/lookup/impl/LookupImpl.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index 9d2c76e76879..978dbe22d15d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -890,8 +890,9 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable public boolean performGuardedChange(Runnable change, @Nullable final String debug) { checkValid(); - assert myLookupStartMarker.isValid(); - assert !myChangeGuard; + assert myLookupStartMarker != null : "null start before"; + assert myLookupStartMarker.isValid() : "invalid start"; + assert !myChangeGuard : "already in change"; myChangeGuard = true; final Document document = myEditor.getDocument(); @@ -911,7 +912,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable document.removeDocumentListener(spy); myChangeGuard = false; } - if (!myLookupStartMarker.isValid() || myDisposed) { + if (myDisposed || !myLookupStartMarker.isValid()) { hide(); return false; } From f411ef2e858c73b4cdfc8823c1da75913fb3d895 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Wed, 21 Mar 2012 12:56:14 +0400 Subject: [PATCH 101/106] Add pom-packaging type 'maven-plugin' --- .../org/jetbrains/idea/maven/project/MavenProject.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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 9487d00d168d..521ed69f086f 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 @@ -29,6 +29,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.SmartList; +import com.intellij.util.containers.CollectionFactory; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; import gnu.trove.THashSet; @@ -617,9 +618,9 @@ public class MavenProject { @NotNull public Set getSupportedPackagings() { - Set result = new THashSet(Arrays.asList(MavenConstants.TYPE_POM, - MavenConstants.TYPE_JAR, - "ejb", "ejb-client", "war", "ear", "bundle")); + Set result = CollectionFactory.newSet(MavenConstants.TYPE_POM, + MavenConstants.TYPE_JAR, + "ejb", "ejb-client", "war", "ear", "bundle", "maven-plugin"); for (MavenImporter each : getSuitableImporters()) { each.getSupportedPackagings(result); } From 34162f63aa251187e45a7c05f31cd47c55af05fe Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Wed, 21 Mar 2012 15:00:47 +0400 Subject: [PATCH 102/106] Support maven plugin com.bluetrainsoftware.bluegrails:grails-maven-plugin --- .../idea/maven/model/MavenPlugin.java | 12 +++++++ .../idea/maven/importing/MavenImporter.java | 35 ++++++++++++++----- .../idea/maven/project/MavenProject.java | 13 ++----- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenPlugin.java b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenPlugin.java index 9f6c8efb1e84..8b9a31793075 100644 --- a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenPlugin.java +++ b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenPlugin.java @@ -18,6 +18,7 @@ package org.jetbrains.idea.maven.model; import com.intellij.openapi.util.JDOMUtil; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.Serializable; @@ -86,6 +87,17 @@ public class MavenPlugin implements Serializable { return myDependencies; } + @Nullable + public Element getGoalConfiguration(@NotNull String goal) { + for (MavenPlugin.Execution each : getExecutions()) { + if (each.getGoals().contains(goal)) { + return each.getConfigurationElement(); + } + } + + return null; + } + public String getDisplayString() { StringBuilder builder = new StringBuilder(); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java index 843f8d2caa97..80158a7c67ff 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java @@ -22,12 +22,14 @@ import com.intellij.openapi.module.StdModuleTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Pair; +import com.intellij.util.NullableFunction; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.model.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenPlugin; import org.jetbrains.idea.maven.project.*; import org.jetbrains.idea.maven.server.MavenEmbedderWrapper; import org.jetbrains.idea.maven.server.NativeMavenProjectHolder; @@ -38,12 +40,20 @@ import java.util.*; public abstract class MavenImporter { public static ExtensionPointName EXTENSION_POINT_NAME = ExtensionPointName.create("org.jetbrains.idea.maven.importer"); - protected final String myPluginGroupID; - protected final String myPluginArtifactID; - public MavenImporter(String pluginGroupID, String pluginArtifactID) { - myPluginGroupID = pluginGroupID; - myPluginArtifactID = pluginArtifactID; + private final NullableFunction myPluginFinder; + + public MavenImporter(final String pluginGroupID, final String pluginArtifactID) { + this(new NullableFunction() { + @Override + public MavenPlugin fun(MavenProject mavenProject) { + return mavenProject.findPlugin(pluginGroupID, pluginArtifactID); + } + }); + } + + protected MavenImporter(NullableFunction pluginFinder) { + myPluginFinder = pluginFinder; } public static List getSuitableImporters(MavenProject p) { @@ -81,8 +91,13 @@ public abstract class MavenImporter { }); } + @Nullable + protected MavenPlugin getPlugin(MavenProject mavenProject) { + return myPluginFinder.fun(mavenProject); + } + public boolean isApplicable(MavenProject mavenProject) { - return mavenProject.findPlugin(myPluginGroupID, myPluginArtifactID) != null; + return getPlugin(mavenProject) != null; } @NotNull @@ -136,7 +151,8 @@ public abstract class MavenImporter { @Nullable protected Element getConfig(MavenProject p) { - return p.getPluginConfiguration(myPluginGroupID, myPluginArtifactID); + MavenPlugin plugin = getPlugin(p); + return plugin == null ? null : plugin.getConfigurationElement(); } @Nullable @@ -155,8 +171,9 @@ public abstract class MavenImporter { } @Nullable - protected Element getGoalConfig(MavenProject p, String goal) { - return p.getPluginGoalConfiguration(myPluginGroupID, myPluginArtifactID, goal); + protected Element getGoalConfig(MavenProject p, @NotNull String goal) { + MavenPlugin plugin = getPlugin(p); + return plugin == null ? null : plugin.getGoalConfiguration(goal); } @Nullable 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 521ed69f086f..258972e1bb52 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 @@ -728,18 +728,11 @@ public class MavenProject { MavenPlugin plugin = findPlugin(groupId, artifactId); if (plugin == null) return null; - Element configElement = null; if (goalOrNull == null) { - configElement = plugin.getConfigurationElement(); + return plugin.getConfigurationElement(); } - else { - for (MavenPlugin.Execution each : plugin.getExecutions()) { - if (each.getGoals().contains(goalOrNull)) { - configElement = each.getConfigurationElement(); - } - } - } - return configElement; + + return plugin.getGoalConfiguration(goalOrNull); } @Nullable From 2fd2a64138225b5060a9a74cab5f134a037b52c9 Mon Sep 17 00:00:00 2001 From: irengrig Date: Wed, 21 Mar 2012 15:11:27 +0400 Subject: [PATCH 103/106] SVN: correctly report inner working copy root to the system --- .../idea/svn/NestedCopiesBuilder.java | 12 ++++++++---- .../jetbrains/idea/svn/StatusReceiver.java | 5 ++++- .../idea/svn/SvnChangeProviderContext.java | 11 ++++++----- .../idea/svn/SvnRecursiveStatusWalker.java | 19 +++++++++++++------ .../src/org/jetbrains/idea/svn/SvnVcs.java | 14 ++++++++++---- 5 files changed, 41 insertions(+), 20 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/NestedCopiesBuilder.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/NestedCopiesBuilder.java index 3c3a491233b9..1a4e514a2ca5 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/NestedCopiesBuilder.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/NestedCopiesBuilder.java @@ -23,6 +23,7 @@ import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.SVNStatus; import org.tmatesoft.svn.core.wc.SVNStatusType; +import java.io.File; import java.util.HashSet; import java.util.Set; @@ -33,7 +34,7 @@ public class NestedCopiesBuilder implements StatusReceiver { mySet = new HashSet(); } - public void process(final FilePath path, final SVNStatus status, final boolean isInnerCopyRoot) throws SVNException { + public void process(final FilePath path, final SVNStatus status) throws SVNException { if ((path.getVirtualFile() != null) && SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_EXTERNAL)) { final MyPointInfo info = new MyPointInfo(path.getVirtualFile(), null, WorkingCopyFormat.UNKNOWN, NestedCopyType.external); mySet.add(info); @@ -46,9 +47,6 @@ public class NestedCopiesBuilder implements StatusReceiver { return; } else if (status.isSwitched()) { type = NestedCopyType.switched; - } else if (isInnerCopyRoot) { - // will not be changed or modified; can't be switched or external - type = NestedCopyType.inner; } else { return; } @@ -63,6 +61,12 @@ public class NestedCopiesBuilder implements StatusReceiver { public void processUnversioned(final VirtualFile vFile) { } + @Override + public void processCopyRoot(VirtualFile file, SVNURL url, WorkingCopyFormat format) { + final MyPointInfo info = new MyPointInfo(file, url, format, NestedCopyType.inner); + mySet.add(info); + } + static class MyPointInfo { private final VirtualFile myFile; private SVNURL myUrl; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusReceiver.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusReceiver.java index afd8a5370231..1cd827424c8e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusReceiver.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusReceiver.java @@ -18,12 +18,15 @@ package org.jetbrains.idea.svn; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vfs.VirtualFile; import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.SVNStatus; +import java.io.File; import java.util.EventListener; public interface StatusReceiver extends EventListener { - void process(final FilePath path, final SVNStatus status, final boolean isInnerCopyRoot) throws SVNException; + void process(final FilePath path, final SVNStatus status) throws SVNException; void processIgnored(final VirtualFile vFile); void processUnversioned(final VirtualFile vFile); + void processCopyRoot(VirtualFile file, SVNURL url, WorkingCopyFormat format); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java index 4388ee270827..716c1d503cc8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java @@ -26,10 +26,7 @@ import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.actions.AbstractShowPropertiesDiffAction; -import org.tmatesoft.svn.core.SVNErrorCode; -import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.SVNLock; -import org.tmatesoft.svn.core.SVNNodeKind; +import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb; import org.tmatesoft.svn.core.wc.*; @@ -60,7 +57,7 @@ class SvnChangeProviderContext implements StatusReceiver { myBranchConfigurationManager = SvnBranchConfigurationManager.getInstance(myVcs.getProject()); } - public void process(FilePath path, SVNStatus status, boolean isInnerCopyRoot) throws SVNException { + public void process(FilePath path, SVNStatus status) throws SVNException { processStatusFirstPass(path, status); } @@ -72,6 +69,10 @@ class SvnChangeProviderContext implements StatusReceiver { myChangelistBuilder.processUnversionedFile(vFile); } + @Override + public void processCopyRoot(VirtualFile file, SVNURL url, WorkingCopyFormat format) { + } + public ChangelistBuilder getBuilder() { return myChangelistBuilder; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java index f329bbf30601..3928df4a6009 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java @@ -28,10 +28,7 @@ import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNNodeKind; -import org.tmatesoft.svn.core.wc.ISVNStatusHandler; -import org.tmatesoft.svn.core.wc.SVNRevision; -import org.tmatesoft.svn.core.wc.SVNStatus; -import org.tmatesoft.svn.core.wc.SVNStatusClient; +import org.tmatesoft.svn.core.wc.*; import java.io.File; import java.util.LinkedList; @@ -92,7 +89,7 @@ public class SvnRecursiveStatusWalker { } else { // just file final SVNStatus status = item.getClient().doStatus(ioFile, false, false); - myReceiver.process(path, status, false); + myReceiver.process(path, status); } } } @@ -168,14 +165,24 @@ public class SvnRecursiveStatusWalker { private class MyHandler implements ISVNStatusHandler { private MyItem myCurrentItem; + private boolean myMetCurrentItem; public void setCurrentItem(MyItem currentItem) { myCurrentItem = currentItem; + myMetCurrentItem = false; } public void handleStatus(final SVNStatus status) throws SVNException { myPartner.checkCanceled(); final File ioFile = status.getFile(); + if (! myMetCurrentItem && myCurrentItem.isIsInnerCopyRoot()) { + myMetCurrentItem = true; + final SVNStatus statusInner = SvnUtil.getStatus(SvnVcs.getInstance(myProject), myCurrentItem.getPath().getIOFile()); + if (myCurrentItem.getPath().getVirtualFile() != null || statusInner != null) { + myReceiver.processCopyRoot(myCurrentItem.getPath().getVirtualFile(), statusInner.getURL(), + WorkingCopyFormat.getInstance(statusInner.getWorkingCopyFormat())); + } + } final LocalFileSystem lfs = LocalFileSystem.getInstance(); VirtualFile vFile = lfs.findFileByIoFile(ioFile); if (vFile == null) { @@ -190,7 +197,7 @@ public class SvnRecursiveStatusWalker { } } else { final FilePath path = VcsUtil.getFilePath(ioFile, status.getKind().equals(SVNNodeKind.DIR)); - myReceiver.process(path, status, myCurrentItem.isIsInnerCopyRoot()); + myReceiver.process(path, status); } } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java index ca76ab2915f8..3e25901512c5 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java @@ -299,13 +299,14 @@ public class SvnVcs extends AbstractVcs { ChangeListManager.getInstance(myProject).setReadOnly(SvnChangeProvider.ourDefaultListName, true); supportOptions = myConfiguration.getSupportOptions(myProject); - if (! supportOptions.changeListsSynchronized()) { + if (!supportOptions.changeListsSynchronized()) { processChangeLists(lists); } } catch (ProcessCanceledException e) { // - } finally { + } + finally { if (supportOptions != null) { supportOptions.upgrade(); } @@ -817,11 +818,16 @@ public class SvnVcs extends AbstractVcs { @Nullable public SVNInfo getInfo(final VirtualFile file) { + final File ioFile = new File(file.getPath()); + return getInfo(ioFile); + } + + public SVNInfo getInfo(File ioFile) { try { SVNWCClient wcClient = createWCClient(); - SVNInfo info = wcClient.doInfo(new File(file.getPath()), SVNRevision.UNDEFINED); + SVNInfo info = wcClient.doInfo(ioFile, SVNRevision.UNDEFINED); if (info == null || info.getRepositoryRootURL() == null) { - info = wcClient.doInfo(new File(file.getPath()), SVNRevision.HEAD); + info = wcClient.doInfo(ioFile, SVNRevision.HEAD); } return info; } From b50226fbfeaddfbf07fa0d54cb809c47b5c519e7 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Wed, 21 Mar 2012 15:18:50 +0400 Subject: [PATCH 104/106] Support maven plugin com.bluetrainsoftware.bluegrails:grails-maven-plugin Return myPluginGroupID and myPluginArtifactID to compatibility. --- .../jetbrains/idea/maven/importing/MavenImporter.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java index 80158a7c67ff..5aa8a7c57fb1 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java @@ -41,6 +41,12 @@ import java.util.*; public abstract class MavenImporter { public static ExtensionPointName EXTENSION_POINT_NAME = ExtensionPointName.create("org.jetbrains.idea.maven.importer"); + @Deprecated + protected String myPluginGroupID; + + @Deprecated + protected String myPluginArtifactID; + private final NullableFunction myPluginFinder; public MavenImporter(final String pluginGroupID, final String pluginArtifactID) { @@ -50,6 +56,9 @@ public abstract class MavenImporter { return mavenProject.findPlugin(pluginGroupID, pluginArtifactID); } }); + + myPluginGroupID = pluginGroupID; + myPluginArtifactID = pluginArtifactID; } protected MavenImporter(NullableFunction pluginFinder) { From c9d38d7dcc831afdf4d671ee214af4248b8bf67e Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 21 Mar 2012 12:37:21 +0100 Subject: [PATCH 105/106] More logging on failed plugin file name guessing --- .../intellij/openapi/updateSettings/impl/PluginDownloader.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java index 55440a7c90a8..75a7c922e459 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java @@ -329,6 +329,7 @@ public class PluginDownloader { if (fileName == null || !PathUtil.isValidFileName(fileName)) { FileUtil.delete(file); + LOG.warn("Invalid file name (header=" + contentDisposition + "; url=" + connection.getURL() + "; name=" + fileName + ")"); throw new IOException("Invalid filename returned by the server"); } From dfd3b331a9be5f22ed9e3adfbc0769c2201f1b20 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 21 Mar 2012 13:01:04 +0100 Subject: [PATCH 106/106] Fix intellij-core.jar assembling --- build/scripts/layouts.gant | 1 + 1 file changed, 1 insertion(+) diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index 07361cb807b2..1985a382aaa9 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -499,6 +499,7 @@ def reorder(String home, String targetDirectory) { def layout_core(String home, String target) { layout(target) { jar("intellij-core.jar") { + module("util-rt") module("util") module("core-api") module("core-impl")