From 4bac2bc23ac215b0631bc96966959c03459b48ec Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 7 Jan 2015 11:41:14 +0100 Subject: [PATCH 01/19] smaller static memory footprint & removed duplicate code --- .../siyeh/ig/psiutils/ExpectedTypeUtils.java | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpectedTypeUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpectedTypeUtils.java index 541d39c57d96..a930d690314b 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpectedTypeUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExpectedTypeUtils.java @@ -20,11 +20,12 @@ import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; +import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.HashSet; import java.util.Set; public class ExpectedTypeUtils { @@ -56,13 +57,13 @@ public class ExpectedTypeUtils { /** * @noinspection StaticCollection */ - private static final Set arithmeticOps = new HashSet(5); + private static final Set arithmeticOps = new THashSet(5); - private static final Set booleanOps = new HashSet(5); + private static final Set booleanOps = new THashSet(5); - private static final Set shiftOps = new HashSet(3); + private static final Set shiftOps = new THashSet(3); - private static final Set operatorAssignmentOps = new HashSet(11); + private static final Set operatorAssignmentOps = new THashSet(11); static { arithmeticOps.add(JavaTokenType.PLUS); @@ -611,13 +612,7 @@ public class ExpectedTypeUtils { } private static int getParameterPosition(@NotNull PsiExpressionList expressionList, PsiExpression expression) { - final PsiExpression[] expressions = expressionList.getExpressions(); - for (int i = 0; i < expressions.length; i++) { - if (expressions[i].equals(expression)) { - return i; - } - } - return -1; + return ArrayUtil.indexOf(expressionList.getExpressions(), expression); } @Nullable From 177bc93ad2ec13defe3a73e6fc7a64b780d49d39 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 7 Jan 2015 12:22:30 +0100 Subject: [PATCH 02/19] enhance dependencies calculation for cache element descriptor, use depending file information for elements produced via entity expansion. This change fixes XmlRenameTest.testRenameDtdUsedViaEntity sporadic failures --- .../xml/impl/dtd/XmlNSDescriptorImpl.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/dtd/XmlNSDescriptorImpl.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/dtd/XmlNSDescriptorImpl.java index 18ea646c8b8b..d4a183339396 100644 --- a/xml/xml-psi-impl/src/com/intellij/xml/impl/dtd/XmlNSDescriptorImpl.java +++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/dtd/XmlNSDescriptorImpl.java @@ -21,6 +21,7 @@ import com.intellij.lang.dtd.DTDLanguage; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.util.SimpleFieldCache; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import com.intellij.psi.filters.ClassFilter; import com.intellij.psi.scope.processor.FilterElementProcessor; import com.intellij.psi.search.PsiElementProcessor; @@ -32,6 +33,7 @@ import com.intellij.xml.XmlElementDescriptor; import com.intellij.xml.XmlNSDescriptorEx; import com.intellij.xml.impl.ExternalDocumentValidator; import com.intellij.xml.util.XmlUtil; +import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -95,8 +97,8 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator delcarations = buildDeclarationMap().values(); - return delcarations.toArray(new XmlElementDescriptor[delcarations.size()]); + final Collection declarations = buildDeclarationMap().values(); + return declarations.toArray(new XmlElementDescriptor[declarations.size()]); } private Map buildDeclarationMap() { @@ -111,16 +113,24 @@ public class XmlNSDescriptorImpl implements XmlNSDescriptorEx,Validator result = new ArrayList(); myElement.processElements(new FilterElementProcessor(new ClassFilter(XmlElementDecl.class), result), getDeclaration()); final Map ret = new LinkedHashMap((int)(result.size() * 1.5)); + Set dependencies = new THashSet(1); + dependencies.add(myDescriptorFile); for (final XmlElementDecl xmlElementDecl : result) { final String name = xmlElementDecl.getName(); if (name != null) { if (!ret.containsKey(name)) { ret.put(name, new XmlElementDescriptorImpl(xmlElementDecl)); + // if element descriptor was produced from entity reference use proper dependency + PsiElement dependingElement = xmlElementDecl.getUserData(XmlElement.DEPENDING_ELEMENT); + if (dependingElement != null) { + PsiFile dependingElementContainingFile = dependingElement.getContainingFile(); + if (dependingElementContainingFile != null) dependencies.add(dependingElementContainingFile); + } } } } - return new Result>(ret, myDescriptorFile); + return new Result>(ret, dependencies.toArray()); } }, false); } From 3658d45c49063c8a483ce4b85ae1f75993b01fef Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 2 Jan 2015 17:04:15 +0300 Subject: [PATCH 03/19] [git] cleanup: unused fields, obsolete javadoc --- plugins/git4idea/src/git4idea/GitVcs.java | 2 +- .../src/git4idea/update/GitUpdateEnvironment.java | 13 +------------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/plugins/git4idea/src/git4idea/GitVcs.java b/plugins/git4idea/src/git4idea/GitVcs.java index c12356977209..ae795ee22439 100644 --- a/plugins/git4idea/src/git4idea/GitVcs.java +++ b/plugins/git4idea/src/git4idea/GitVcs.java @@ -155,7 +155,7 @@ public class GitVcs extends AbstractVcs { myRollbackEnvironment = gitRollbackEnvironment; myRevSelector = new GitRevisionSelector(); myConfigurable = new GitVcsConfigurable(myProject, gitProjectSettings, sharedSettings); - myUpdateEnvironment = new GitUpdateEnvironment(myProject, this, gitProjectSettings); + myUpdateEnvironment = new GitUpdateEnvironment(myProject, gitProjectSettings); myCommittedChangeListProvider = new GitCommittedChangeListProvider(myProject); myOutgoingChangesProvider = new GitOutgoingChangesProvider(myProject); myTreeDiffProvider = new GitTreeDiffProvider(myProject); diff --git a/plugins/git4idea/src/git4idea/update/GitUpdateEnvironment.java b/plugins/git4idea/src/git4idea/update/GitUpdateEnvironment.java index f5068f10383e..3e9c48abbbbb 100644 --- a/plugins/git4idea/src/git4idea/update/GitUpdateEnvironment.java +++ b/plugins/git4idea/src/git4idea/update/GitUpdateEnvironment.java @@ -16,7 +16,6 @@ package git4idea.update; import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; @@ -29,7 +28,6 @@ import com.intellij.openapi.vcs.update.UpdateSession; import com.intellij.openapi.vcs.update.UpdatedFiles; import com.intellij.openapi.vfs.VirtualFile; import git4idea.GitPlatformFacade; -import git4idea.GitVcs; import git4idea.config.GitVcsSettings; import git4idea.repo.GitRepositoryManager; import org.jetbrains.annotations.NotNull; @@ -41,21 +39,12 @@ import java.util.Set; import static git4idea.GitUtil.*; -/** - * Git update environment implementation. The environment does - * {@code git pull -v} for each vcs root. Rebase variant is detected - * and processed as well. - */ public class GitUpdateEnvironment implements UpdateEnvironment { - private final GitVcs myVcs; private final Project myProject; private final GitVcsSettings mySettings; @NotNull private final GitPlatformFacade myPlatformFacade; - private static final Logger LOG = Logger.getInstance(GitUpdateEnvironment.class); - - public GitUpdateEnvironment(@NotNull Project project, @NotNull GitVcs vcs, GitVcsSettings settings) { - myVcs = vcs; + public GitUpdateEnvironment(@NotNull Project project, @NotNull GitVcsSettings settings) { myProject = project; mySettings = settings; myPlatformFacade = ServiceManager.getService(project, GitPlatformFacade.class); From 030939953813fdca1ca356e40e495ac039cd3c62 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 2 Jan 2015 14:47:46 +0300 Subject: [PATCH 04/19] [git] Respect branch default setting for update-when-rejected-push + remove the unneeded extra UpdateMethod enum Relates to IDEA-134326 --- .../src/git4idea/push/GitPushOperation.java | 13 ++- .../push/GitRejectedPushUpdateDialog.java | 6 + .../git4idea/update/GitUpdateEnvironment.java | 2 +- .../src/git4idea/update/GitUpdateProcess.java | 18 +-- .../src/git4idea/update/GitUpdater.java | 50 ++++----- .../push/GitPushOperationSingleRepoTest.java | 105 ++++++++++++++++++ 6 files changed, 144 insertions(+), 50 deletions(-) diff --git a/plugins/git4idea/src/git4idea/push/GitPushOperation.java b/plugins/git4idea/src/git4idea/push/GitPushOperation.java index f67a807bfbaf..8973cd2b7b4b 100644 --- a/plugins/git4idea/src/git4idea/push/GitPushOperation.java +++ b/plugins/git4idea/src/git4idea/push/GitPushOperation.java @@ -52,6 +52,7 @@ import git4idea.repo.GitRepositoryManager; import git4idea.update.GitRebaseOverMergeProblem; import git4idea.update.GitUpdateProcess; import git4idea.update.GitUpdateResult; +import git4idea.update.GitUpdater; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -383,7 +384,8 @@ public class GitPushOperation { private void savePushUpdateSettings(@NotNull PushUpdateSettings settings, boolean rebaseOverMergeDetected) { UpdateMethod updateMethod = settings.getUpdateMethod(); mySettings.setUpdateAllRootsIfPushRejected(settings.shouldUpdateAllRoots()); - if (!rebaseOverMergeDetected) { // don't overwrite explicit "rebase" with temporary "merge" caused by merge commits + if (!rebaseOverMergeDetected // don't overwrite explicit "rebase" with temporary "merge" caused by merge commits + && mySettings.getUpdateType() != updateMethod && mySettings.getUpdateType() != UpdateMethod.BRANCH_DEFAULT) { // don't overwrite "branch default" setting mySettings.setUpdateType(updateMethod); } } @@ -392,6 +394,10 @@ public class GitPushOperation { private PushUpdateSettings readPushUpdateSettings() { boolean updateAllRoots = mySettings.shouldUpdateAllRootsIfPushRejected(); UpdateMethod updateMethod = mySettings.getUpdateType(); + if (updateMethod == UpdateMethod.BRANCH_DEFAULT) { + // deliberate limitation: we have only 2 buttons => choose method from the 1st repo if different + updateMethod = GitUpdater.resolveUpdateMethod(myProject, myPushSpecs.keySet().iterator().next().getRoot()); + } return new PushUpdateSettings(updateAllRoots, updateMethod); } @@ -429,12 +435,9 @@ public class GitPushOperation { protected GitUpdateResult update(@NotNull Collection rootsToUpdate, @NotNull UpdateMethod updateMethod, boolean checkForRebaseOverMergeProblem) { - GitUpdateProcess.UpdateMethod um = updateMethod == UpdateMethod.MERGE ? - GitUpdateProcess.UpdateMethod.MERGE : - GitUpdateProcess.UpdateMethod.REBASE; GitUpdateResult updateResult = new GitUpdateProcess(myProject, myPlatformFacade, myProgressIndicator, new HashSet(rootsToUpdate), UpdatedFiles.create(), - checkForRebaseOverMergeProblem).update(um); + checkForRebaseOverMergeProblem).update(updateMethod); for (GitRepository repository : rootsToUpdate) { repository.getRoot().refresh(true, true); repository.update(); diff --git a/plugins/git4idea/src/git4idea/push/GitRejectedPushUpdateDialog.java b/plugins/git4idea/src/git4idea/push/GitRejectedPushUpdateDialog.java index fdbdf229d277..a24da32017ab 100644 --- a/plugins/git4idea/src/git4idea/push/GitRejectedPushUpdateDialog.java +++ b/plugins/git4idea/src/git4idea/push/GitRejectedPushUpdateDialog.java @@ -220,6 +220,12 @@ class GitRejectedPushUpdateDialog extends DialogWrapper { return myRebaseOverMergeProblemDetected; } + @TestOnly + @NotNull + Action getDefaultAction() { + return Boolean.TRUE.equals(myMergeAction.getValue(DEFAULT_ACTION)) ? myMergeAction : myRebaseAction; + } + private class MergeAction extends AbstractAction { MergeAction() { super("&Merge"); diff --git a/plugins/git4idea/src/git4idea/update/GitUpdateEnvironment.java b/plugins/git4idea/src/git4idea/update/GitUpdateEnvironment.java index 3e9c48abbbbb..b7903cc2b719 100644 --- a/plugins/git4idea/src/git4idea/update/GitUpdateEnvironment.java +++ b/plugins/git4idea/src/git4idea/update/GitUpdateEnvironment.java @@ -61,7 +61,7 @@ public class GitUpdateEnvironment implements UpdateEnvironment { final GitUpdateProcess gitUpdateProcess = new GitUpdateProcess(myProject, myPlatformFacade, progressIndicator, getRepositoriesFromRoots(repositoryManager, roots), updatedFiles, true); - boolean result = gitUpdateProcess.update(GitUpdateProcess.UpdateMethod.READ_FROM_SETTINGS).isSuccess(); + boolean result = gitUpdateProcess.update(mySettings.getUpdateType()).isSuccess(); return new GitUpdateSession(result); } diff --git a/plugins/git4idea/src/git4idea/update/GitUpdateProcess.java b/plugins/git4idea/src/git4idea/update/GitUpdateProcess.java index 33909cd9fa31..6c610575a00f 100644 --- a/plugins/git4idea/src/git4idea/update/GitUpdateProcess.java +++ b/plugins/git4idea/src/git4idea/update/GitUpdateProcess.java @@ -45,6 +45,7 @@ import git4idea.GitUtil; import git4idea.branch.GitBranchPair; import git4idea.branch.GitBranchUtil; import git4idea.commands.Git; +import git4idea.config.UpdateMethod; import git4idea.merge.GitConflictResolver; import git4idea.merge.GitMergeCommittingConflictResolver; import git4idea.merge.GitMerger; @@ -83,12 +84,6 @@ public class GitUpdateProcess { private GitUpdateResult myResult; private final Collection myRootsToSave; - public enum UpdateMethod { - MERGE, - REBASE, - READ_FROM_SETTINGS - } - public GitUpdateProcess(@NotNull Project project, @NotNull GitPlatformFacade platformFacade, @Nullable ProgressIndicator progressIndicator, @@ -298,15 +293,8 @@ public class GitUpdateProcess { LOG.info("updateImpl: defining updaters..."); for (GitRepository repository : myRepositories) { VirtualFile root = repository.getRoot(); - final GitUpdater updater; - if (updateMethod == UpdateMethod.MERGE) { - updater = new GitMergeUpdater(myProject, myGit, root, myTrackedBranches, myProgressIndicator, myUpdatedFiles); - } else if (updateMethod == UpdateMethod.REBASE) { - updater = new GitRebaseUpdater(myProject, myGit, root, myTrackedBranches, myProgressIndicator, myUpdatedFiles); - } else { - updater = GitUpdater.getUpdater(myProject, myGit, myTrackedBranches, root, myProgressIndicator, myUpdatedFiles); - } - + GitUpdater updater = GitUpdater.getUpdater(myProject, myGit, myTrackedBranches, root, myProgressIndicator, myUpdatedFiles, + updateMethod); if (updater.isUpdateNeeded()) { updaters.put(root, updater); } diff --git a/plugins/git4idea/src/git4idea/update/GitUpdater.java b/plugins/git4idea/src/git4idea/update/GitUpdater.java index a093aafba89b..42c44df2cf06 100644 --- a/plugins/git4idea/src/git4idea/update/GitUpdater.java +++ b/plugins/git4idea/src/git4idea/update/GitUpdater.java @@ -29,7 +29,7 @@ import git4idea.commands.Git; import git4idea.commands.GitCommand; import git4idea.commands.GitSimpleHandler; import git4idea.config.GitConfigUtil; -import git4idea.config.GitVcsSettings; +import git4idea.config.UpdateMethod; import git4idea.merge.MergeChangeCollector; import git4idea.repo.GitRepositoryManager; import org.jetbrains.annotations.NotNull; @@ -76,43 +76,35 @@ public abstract class GitUpdater { * @return {@link GitMergeUpdater} or {@link GitRebaseUpdater}. */ @NotNull - public static GitUpdater getUpdater(@NotNull Project project, @NotNull Git git, @NotNull Map trackedBranches, - @NotNull VirtualFile root, @NotNull ProgressIndicator progressIndicator, - @NotNull UpdatedFiles updatedFiles) { - final GitVcsSettings settings = GitVcsSettings.getInstance(project); - if (settings == null) { - return getDefaultUpdaterForBranch(project, git, root, trackedBranches, progressIndicator, updatedFiles); + public static GitUpdater getUpdater(@NotNull Project project, + @NotNull Git git, + @NotNull Map trackedBranches, + @NotNull VirtualFile root, + @NotNull ProgressIndicator progressIndicator, + @NotNull UpdatedFiles updatedFiles, + @NotNull UpdateMethod updateMethod) { + if (updateMethod == UpdateMethod.BRANCH_DEFAULT) { + updateMethod = resolveUpdateMethod(project, root); } - switch (settings.getUpdateType()) { - case REBASE: - return new GitRebaseUpdater(project, git, root, trackedBranches, progressIndicator, updatedFiles); - case MERGE: - return new GitMergeUpdater(project, git, root, trackedBranches, progressIndicator, updatedFiles); - case BRANCH_DEFAULT: - // use default for the branch - return getDefaultUpdaterForBranch(project, git, root, trackedBranches, progressIndicator, updatedFiles); - } - return getDefaultUpdaterForBranch(project, git, root, trackedBranches, progressIndicator, updatedFiles); + return updateMethod == UpdateMethod.REBASE ? + new GitRebaseUpdater(project, git, root, trackedBranches, progressIndicator, updatedFiles): + new GitMergeUpdater(project, git, root, trackedBranches, progressIndicator, updatedFiles); } @NotNull - private static GitUpdater getDefaultUpdaterForBranch(@NotNull Project project, @NotNull Git git, @NotNull VirtualFile root, - @NotNull Map trackedBranches, - @NotNull ProgressIndicator progressIndicator, @NotNull UpdatedFiles updatedFiles) { - try { - GitLocalBranch branch = GitBranchUtil.getCurrentBranch(project, root); - boolean rebase = false; - if (branch != null) { + public static UpdateMethod resolveUpdateMethod(@NotNull Project project, @NotNull VirtualFile root) { + GitLocalBranch branch = GitBranchUtil.getCurrentBranch(project, root); + boolean rebase = false; + if (branch != null) { + try { String rebaseValue = GitConfigUtil.getValue(project, root, "branch." + branch.getName() + ".rebase"); rebase = rebaseValue != null && rebaseValue.equalsIgnoreCase("true"); } - if (rebase) { - return new GitRebaseUpdater(project, git, root, trackedBranches, progressIndicator, updatedFiles); + catch (VcsException e) { + LOG.warn("Couldn't get git config branch." + branch.getName() + ".rebase", e); } - } catch (VcsException e) { - LOG.info("getDefaultUpdaterForBranch branch", e); } - return new GitMergeUpdater(project, git, root, trackedBranches, progressIndicator, updatedFiles); + return rebase ? UpdateMethod.REBASE : UpdateMethod.MERGE; } @NotNull diff --git a/plugins/git4idea/tests/git4idea/push/GitPushOperationSingleRepoTest.java b/plugins/git4idea/tests/git4idea/push/GitPushOperationSingleRepoTest.java index 8f1882e09269..dc6f65b76177 100644 --- a/plugins/git4idea/tests/git4idea/push/GitPushOperationSingleRepoTest.java +++ b/plugins/git4idea/tests/git4idea/push/GitPushOperationSingleRepoTest.java @@ -18,6 +18,7 @@ package git4idea.push; import com.intellij.dvcs.push.PushSpec; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.Trinity; import com.intellij.openapi.util.io.FileUtil; @@ -36,6 +37,7 @@ import git4idea.update.GitUpdateResult; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.io.File; import java.io.IOException; import java.util.Collection; @@ -47,6 +49,7 @@ import static git4idea.test.GitExecutor.*; import static git4idea.test.GitTestUtil.makeCommit; import static java.util.Collections.singletonMap; +@SuppressWarnings("StringToUpperCaseOrToLowerCaseWithoutLocale") public class GitPushOperationSingleRepoTest extends GitPushOperationBaseTest { protected GitRepository myRepository; @@ -188,6 +191,50 @@ public class GitPushOperationSingleRepoTest extends GitPushOperationBaseTest { assertFalse("The commit shouldn't be pushed", history.contains(hash)); } + public void test_use_selected_update_method_for_all_consecutive_updates() throws IOException { + pushCommitFromBro(); + cd(myRepository); + makeCommit("afile.txt"); + + agreeToUpdate(GitRejectedPushUpdateDialog.REBASE_EXIT_CODE); + + refresh(); + PushSpec pushSpec = makePushSpec(myRepository, "master", "origin/master"); + + GitPushResult result = new GitPushOperation(myProject, myPushSupport, singletonMap(myRepository, pushSpec), null, false) { + boolean updateHappened; + + @NotNull + @Override + protected GitUpdateResult update(@NotNull Collection rootsToUpdate, + @NotNull UpdateMethod updateMethod, + boolean checkForRebaseOverMergeProblem) { + GitUpdateResult updateResult = super.update(rootsToUpdate, updateMethod, checkForRebaseOverMergeProblem); + try { + if (!updateHappened) { + updateHappened = true; + pushCommitFromBro(); + } + } + catch (IOException e) { + throw new RuntimeException(e); + } + return updateResult; + } + }.execute(); + + assertResult(SUCCESS, 1, "master", "origin/master", GitUpdateResult.SUCCESS, result.getResults().get(myRepository)); + cd(myRepository); + String[] commitMessages = StringUtil.splitByLines(log("--pretty=%s")); + boolean mergeCommitsInTheLog = ContainerUtil.exists(commitMessages, new Condition() { + @Override + public boolean value(String s) { + return s.toLowerCase().contains("merge"); + } + }); + assertFalse("Unexpected merge commits when rebase method is selected", mergeCommitsInTheLog); + } + public void test_force_push() throws IOException { String lostHash = pushCommitFromBro(); cd(myRepository); @@ -305,6 +352,64 @@ public class GitPushOperationSingleRepoTest extends GitPushOperationBaseTest { UpdateMethod.REBASE, myGitSettings.getUpdateType()); } + public void test_respect_branch_default_setting_for_rejected_push_dialog() throws IOException { + generateUpdateNeeded(); + myGitSettings.setUpdateType(UpdateMethod.BRANCH_DEFAULT); + git("config branch.master.rebase true"); + + final Ref defaultActionName = Ref.create(); + myDialogManager.registerDialogHandler(GitRejectedPushUpdateDialog.class, new TestDialogHandler() { + @Override + public int handleDialog(@NotNull GitRejectedPushUpdateDialog dialog) { + defaultActionName.set((String)dialog.getDefaultAction().getValue(Action.NAME)); + return DialogWrapper.CANCEL_EXIT_CODE; + } + }); + + push("master", "origin/master"); + assertTrue("Default action in rejected-push dialog is incorrect: " + defaultActionName.get(), + defaultActionName.get().toLowerCase().contains("rebase")); + + git("config branch.master.rebase false"); + push("master", "origin/master"); + assertTrue("Default action in rejected-push dialog is incorrect: " + defaultActionName.get(), + defaultActionName.get().toLowerCase().contains("merge")); + } + + public void test_respect_branch_default_setting_for_silent_update_when_rejected_push() throws IOException { + generateUpdateNeeded(); + myGitSettings.setUpdateType(UpdateMethod.BRANCH_DEFAULT); + git("config branch.master.rebase true"); + myGitSettings.setAutoUpdateIfPushRejected(true); + + push("master", "origin/master"); + assertFalse("Unexpected merge commit: rebase should have happened", log("-1 --pretty=%s").toLowerCase().startsWith("merge")); + } + + // there is no "branch default" choice in the rejected push dialog + // => simply don't rewrite the setting if the same value is chosen, as was default value initially + public void test_dont_overwrite_branch_default_setting_when_agree_in_rejected_push_dialog() throws IOException { + generateUpdateNeeded(); + myGitSettings.setUpdateType(UpdateMethod.BRANCH_DEFAULT); + git("config branch.master.rebase true"); + + myDialogManager.registerDialogHandler(GitRejectedPushUpdateDialog.class, new TestDialogHandler() { + @Override + public int handleDialog(@NotNull GitRejectedPushUpdateDialog dialog) { + return GitRejectedPushUpdateDialog.REBASE_EXIT_CODE; + } + }); + + push("master", "origin/master"); + assertEquals(UpdateMethod.BRANCH_DEFAULT, myGitSettings.getUpdateType()); + } + + private void generateUpdateNeeded() throws IOException { + pushCommitFromBro(); + cd(myRepository); + makeCommit("file.txt"); + } + private void generateUnpushedMergedCommitProblem() throws IOException { pushCommitFromBro(); cd(myRepository); From 3119e758617aa59d2345f9bc9f62c4f3c88369d0 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 2 Jan 2015 17:46:11 +0300 Subject: [PATCH 05/19] [git tests] dispose the dialog if handler fails with exception --- .../tests/git4idea/test/TestDialogManager.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/plugins/git4idea/tests/git4idea/test/TestDialogManager.java b/plugins/git4idea/tests/git4idea/test/TestDialogManager.java index d20904099d9f..871d53cab1fb 100644 --- a/plugins/git4idea/tests/git4idea/test/TestDialogManager.java +++ b/plugins/git4idea/tests/git4idea/test/TestDialogManager.java @@ -48,8 +48,15 @@ public class TestDialogManager extends DialogManager { @Override protected void showDialog(@NotNull DialogWrapper dialog) { TestDialogHandler handler = myHandlers.get(dialog.getClass()); - int exitCode = handler != null ? handler.handleDialog(dialog) : DialogWrapper.OK_EXIT_CODE; - dialog.close(exitCode, exitCode == DialogWrapper.OK_EXIT_CODE); + int exitCode = DialogWrapper.OK_EXIT_CODE; + try { + if (handler != null) { + exitCode = handler.handleDialog(dialog); + } + } + finally { + dialog.close(exitCode, exitCode == DialogWrapper.OK_EXIT_CODE); + } } @Override From 82e704df10276b6949bdd75362ddf5f7c0cb7f26 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 2 Jan 2015 18:01:02 +0300 Subject: [PATCH 06/19] [git tests] use correct dialog type --- .../tests/git4idea/push/GitPushOperationBaseTest.java | 5 ++--- .../git4idea/push/GitPushOperationSingleRepoTest.java | 8 ++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/plugins/git4idea/tests/git4idea/push/GitPushOperationBaseTest.java b/plugins/git4idea/tests/git4idea/push/GitPushOperationBaseTest.java index 4d6576ae6718..7328b4d305b9 100644 --- a/plugins/git4idea/tests/git4idea/push/GitPushOperationBaseTest.java +++ b/plugins/git4idea/tests/git4idea/push/GitPushOperationBaseTest.java @@ -18,7 +18,6 @@ package git4idea.push; import com.intellij.dvcs.push.PushSpec; import com.intellij.dvcs.push.PushSupport; import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Trinity; import com.intellij.openapi.vcs.AbstractVcsHelper; @@ -148,9 +147,9 @@ abstract class GitPushOperationBaseTest extends GitPlatformTest { } protected void agreeToUpdate(final int exitCode) { - myDialogManager.registerDialogHandler(GitRejectedPushUpdateDialog.class, new TestDialogHandler() { + myDialogManager.registerDialogHandler(GitRejectedPushUpdateDialog.class, new TestDialogHandler() { @Override - public int handleDialog(DialogWrapper dialog) { + public int handleDialog(GitRejectedPushUpdateDialog dialog) { return exitCode; } }); diff --git a/plugins/git4idea/tests/git4idea/push/GitPushOperationSingleRepoTest.java b/plugins/git4idea/tests/git4idea/push/GitPushOperationSingleRepoTest.java index dc6f65b76177..d5057f5d6683 100644 --- a/plugins/git4idea/tests/git4idea/push/GitPushOperationSingleRepoTest.java +++ b/plugins/git4idea/tests/git4idea/push/GitPushOperationSingleRepoTest.java @@ -124,9 +124,9 @@ public class GitPushOperationSingleRepoTest extends GitPushOperationBaseTest { pushCommitFromBro(); final Ref dialogShown = Ref.create(false); - myDialogManager.registerDialogHandler(GitRejectedPushUpdateDialog.class, new TestDialogHandler() { + myDialogManager.registerDialogHandler(GitRejectedPushUpdateDialog.class, new TestDialogHandler() { @Override - public int handleDialog(DialogWrapper dialog) { + public int handleDialog(GitRejectedPushUpdateDialog dialog) { dialogShown.set(true); return DialogWrapper.CANCEL_EXIT_CODE; } @@ -144,9 +144,9 @@ public class GitPushOperationSingleRepoTest extends GitPushOperationBaseTest { git("checkout -b feature"); final Ref dialogShown = Ref.create(false); - myDialogManager.registerDialogHandler(GitRejectedPushUpdateDialog.class, new TestDialogHandler() { + myDialogManager.registerDialogHandler(GitRejectedPushUpdateDialog.class, new TestDialogHandler() { @Override - public int handleDialog(DialogWrapper dialog) { + public int handleDialog(GitRejectedPushUpdateDialog dialog) { dialogShown.set(true); return DialogWrapper.CANCEL_EXIT_CODE; } From 93e5e035ba7b247eba8d2ae71fa01522cfc4121f Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 7 Jan 2015 15:03:11 +0300 Subject: [PATCH 07/19] [vcs] ChangesTreeList: extract method for searching for file in tree --- .../vcs/changes/ui/ChangesTreeList.java | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java index b4c8fbb9f90e..ed72f047c26c 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java @@ -26,6 +26,7 @@ import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.EmptyRunnable; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.registry.Registry; @@ -400,28 +401,10 @@ public abstract class ChangesTreeList extends JPanel implements TypeSafeDataP } } else { if (toSelect != null) { - ChangesBrowserNode root = (ChangesBrowserNode)model.getRoot(); - final int[] rowToSelect = new int[] {-1}; - TreeUtil.traverse(root, new TreeUtil.Traverse() { - @Override - public boolean accept(Object node) { - if (node instanceof DefaultMutableTreeNode) { - Object userObject = ((DefaultMutableTreeNode)node).getUserObject(); - if (userObject instanceof Change) { - Change change = (Change)userObject; - VirtualFile virtualFile = change.getVirtualFile(); - if ((virtualFile != null && virtualFile.equals(toSelect)) || seemsToBeMoved(change, toSelect)) { - TreeNode[] path = ((DefaultMutableTreeNode)node).getPath(); - rowToSelect[0] = myTree.getRowForPath(new TreePath(path)); - } - } - } - - return rowToSelect[0] == -1; - } - }); - - scrollRow = rowToSelect[0] == -1 ? scrollRow : rowToSelect[0]; + int rowInTree = findRowContainingFile((TreeNode)model.getRoot(), toSelect); + if (rowInTree > -1) { + scrollRow = rowInTree; + } } } @@ -443,6 +426,33 @@ public abstract class ChangesTreeList extends JPanel implements TypeSafeDataP } } + private int findRowContainingFile(@NotNull TreeNode root, @Nullable final VirtualFile toSelect) { + if (toSelect == null) { + return -1; + } + + final Ref row = Ref.create(-1); + TreeUtil.traverse(root, new TreeUtil.Traverse() { + @Override + public boolean accept(Object node) { + if (node instanceof DefaultMutableTreeNode) { + Object userObject = ((DefaultMutableTreeNode)node).getUserObject(); + if (userObject instanceof Change) { + Change change = (Change)userObject; + VirtualFile virtualFile = change.getVirtualFile(); + if ((virtualFile != null && virtualFile.equals(toSelect)) || seemsToBeMoved(change, toSelect)) { + TreeNode[] path = ((DefaultMutableTreeNode)node).getPath(); + row.set(myTree.getRowForPath(new TreePath(path))); + } + } + } + + return row.get() == -1; + } + }); + return row.get(); + } + private static boolean seemsToBeMoved(Change change, VirtualFile toSelect) { ContentRevision afterRevision = change.getAfterRevision(); if (afterRevision == null) return false; From dbd7ac0096df2cc70db9b9636c1b27bc860792e3 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 7 Jan 2015 15:04:08 +0300 Subject: [PATCH 08/19] [vcs] ChangesTreeList: rename variables --- .../vcs/changes/ui/ChangesTreeList.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java index ed72f047c26c..54a9125aad83 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java @@ -363,15 +363,15 @@ public abstract class ChangesTreeList extends JPanel implements TypeSafeDataP if (myProject.isDisposed()) return; TreeUtil.expandAll(myTree); - int listSelection = 0; - int scrollRow = -1; + int selectedListRow = 0; + int selectedTreeRow = -1; if (myShowCheckboxes) { if (myIncludedChanges.size() > 0) { for (int i = 0; i < sortedChanges.size(); i++) { T t = sortedChanges.get(i); if (myIncludedChanges.contains(t)) { - listSelection = i; + selectedListRow = i; break; } } @@ -394,7 +394,7 @@ public abstract class ChangesTreeList extends JPanel implements TypeSafeDataP @SuppressWarnings("unchecked") final CheckboxTree.NodeState state = getNodeStatus(node); if (state == CheckboxTree.NodeState.FULL && node.isLeaf()) { - scrollRow = myTree.getRowForPath(new TreePath(node.getPath())); + selectedTreeRow = myTree.getRowForPath(new TreePath(node.getPath())); break; } } @@ -403,19 +403,19 @@ public abstract class ChangesTreeList extends JPanel implements TypeSafeDataP if (toSelect != null) { int rowInTree = findRowContainingFile((TreeNode)model.getRoot(), toSelect); if (rowInTree > -1) { - scrollRow = rowInTree; + selectedTreeRow = rowInTree; } } } if (changes.size() > 0) { - myList.setSelectedIndex(listSelection); - myList.ensureIndexIsVisible(listSelection); + myList.setSelectedIndex(selectedListRow); + myList.ensureIndexIsVisible(selectedListRow); - if (scrollRow >= 0) { - myTree.setSelectionRow(scrollRow); + if (selectedTreeRow >= 0) { + myTree.setSelectionRow(selectedTreeRow); } - TreeUtil.showRowCentered(myTree, scrollRow, false); + TreeUtil.showRowCentered(myTree, selectedTreeRow, false); } } }; From a177e0377a9fe124a89d01d09d421481a7a4ac83 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 7 Jan 2015 15:14:13 +0300 Subject: [PATCH 09/19] [vcs] IDEA-134956 Fix file preselection for list view --- .../vcs/changes/ui/ChangesTreeList.java | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java index 54a9125aad83..d5d8b3ea5e00 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java @@ -405,6 +405,10 @@ public abstract class ChangesTreeList extends JPanel implements TypeSafeDataP if (rowInTree > -1) { selectedTreeRow = rowInTree; } + int rowInList = findRowContainingFile(myList.getModel(), toSelect); + if (rowInList > -1) { + selectedListRow = rowInList; + } } } @@ -426,6 +430,20 @@ public abstract class ChangesTreeList extends JPanel implements TypeSafeDataP } } + private static int findRowContainingFile(@NotNull ListModel listModel, @Nullable final VirtualFile toSelect) { + if (toSelect == null) { + return -1; + } + + for (int i = 0; i < listModel.getSize(); i++) { + Object item = listModel.getElementAt(i); + if (item instanceof Change && matches((Change)item, toSelect)) { + return i; + } + } + return -1; + } + private int findRowContainingFile(@NotNull TreeNode root, @Nullable final VirtualFile toSelect) { if (toSelect == null) { return -1; @@ -438,9 +456,7 @@ public abstract class ChangesTreeList extends JPanel implements TypeSafeDataP if (node instanceof DefaultMutableTreeNode) { Object userObject = ((DefaultMutableTreeNode)node).getUserObject(); if (userObject instanceof Change) { - Change change = (Change)userObject; - VirtualFile virtualFile = change.getVirtualFile(); - if ((virtualFile != null && virtualFile.equals(toSelect)) || seemsToBeMoved(change, toSelect)) { + if (matches((Change)userObject, toSelect)) { TreeNode[] path = ((DefaultMutableTreeNode)node).getPath(); row.set(myTree.getRowForPath(new TreePath(path))); } @@ -453,6 +469,11 @@ public abstract class ChangesTreeList extends JPanel implements TypeSafeDataP return row.get(); } + private static boolean matches(@NotNull Change change, @NotNull VirtualFile file) { + VirtualFile virtualFile = change.getVirtualFile(); + return virtualFile != null && virtualFile.equals(file) || seemsToBeMoved(change, file); + } + private static boolean seemsToBeMoved(Change change, VirtualFile toSelect) { ContentRevision afterRevision = change.getAfterRevision(); if (afterRevision == null) return false; From a00ab04019d69b8ec5c466925ec1df0daf68bca0 Mon Sep 17 00:00:00 2001 From: pasynkov Date: Wed, 7 Jan 2015 13:22:04 +0100 Subject: [PATCH 10/19] meaningful error message --- .../src/com/intellij/core/CoreProjectLoader.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/platform/projectModel-impl/src/com/intellij/core/CoreProjectLoader.java b/platform/projectModel-impl/src/com/intellij/core/CoreProjectLoader.java index 5c9449dd3863..a94f8daa11f6 100644 --- a/platform/projectModel-impl/src/com/intellij/core/CoreProjectLoader.java +++ b/platform/projectModel-impl/src/com/intellij/core/CoreProjectLoader.java @@ -34,6 +34,7 @@ import org.jdom.Element; import org.jdom.JDOMException; import org.jetbrains.annotations.NotNull; +import java.io.FileNotFoundException; import java.io.IOException; /** @@ -55,9 +56,13 @@ public class CoreProjectLoader { private static void loadDirectoryProject(MockProject project, VirtualFile projectDir) throws IOException, JDOMException, InvalidDataException { VirtualFile dotIdea = projectDir.findChild(Project.DIRECTORY_STORE_FOLDER); - assert dotIdea != null; + if (dotIdea == null) + throw new FileNotFoundException("Missing '" + Project.DIRECTORY_STORE_FOLDER + "' in " + projectDir.getPath()); + VirtualFile modulesXml = dotIdea.findChild("modules.xml"); - assert modulesXml != null; + if (modulesXml == null) + throw new FileNotFoundException("Missing 'modules.xml' in " + dotIdea.getPath()); + StorageData storageData = loadStorageFile(project, modulesXml); final Element moduleManagerState = storageData.getState("ProjectModuleManager"); if (moduleManagerState == null) { @@ -67,7 +72,8 @@ public class CoreProjectLoader { moduleManager.loadState(moduleManagerState); VirtualFile miscXml = dotIdea.findChild("misc.xml"); - assert miscXml != null; + if (miscXml == null) + throw new FileNotFoundException("Missing 'misc.xml' in " + dotIdea.getPath()); storageData = loadStorageFile(project, miscXml); final Element projectRootManagerState = storageData.getState("ProjectRootManager"); if (projectRootManagerState == null) { From 88091efcbf3ebca7756add00e760b001ff72d9a3 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 7 Jan 2015 13:49:19 +0100 Subject: [PATCH 11/19] SSR: find annotations in more places --- .../compiler/JavaCompilingVisitor.java | 12 ----- .../strategies/ExprMatchingStrategy.java | 21 ++++++++ .../strategies/SymbolMatchingStrategy.java | 54 ------------------- .../StructuralSearchTest.java | 4 +- 4 files changed, 24 insertions(+), 67 deletions(-) delete mode 100644 java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/strategies/SymbolMatchingStrategy.java diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/compiler/JavaCompilingVisitor.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/compiler/JavaCompilingVisitor.java index 1733ead28937..26b11476cf39 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/compiler/JavaCompilingVisitor.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/compiler/JavaCompilingVisitor.java @@ -589,18 +589,6 @@ public class JavaCompilingVisitor extends JavaRecursiveElementWalkingVisitor { } private MatchingStrategy findStrategy(PsiElement el) { - // identify matching strategy - final MatchingHandler handler = myCompilingVisitor.getContext().getPattern().getHandler(el); - - //if (handler instanceof SubstitutionHandler) { - // final SubstitutionHandler shandler = (SubstitutionHandler) handler; - if (handler.getFilter() instanceof SymbolNodeFilter || - handler.getFilter() instanceof TypedSymbolNodeFilter - ) { - return SymbolMatchingStrategy.getInstance(); - } - //} - if (el instanceof PsiDocComment) { return JavaDocMatchingStrategy.getInstance(); } diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/strategies/ExprMatchingStrategy.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/strategies/ExprMatchingStrategy.java index d19205ff3317..4a38b7f40193 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/strategies/ExprMatchingStrategy.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/strategies/ExprMatchingStrategy.java @@ -7,6 +7,27 @@ import com.intellij.psi.*; */ public class ExprMatchingStrategy extends MatchingStrategyBase { + @Override + public void visitTypeElement(PsiTypeElement type) { + result = true; + } + + @Override public void visitReferenceParameterList(PsiReferenceParameterList psiReferenceParameterList) { + result = true; + } + + @Override public void visitReferenceElement(PsiJavaCodeReferenceElement psiJavaCodeReferenceElement) { + result = true; + } + + @Override public void visitTypeParameterList(PsiTypeParameterList psiTypeParameterList) { + result = true; + } + + @Override public void visitReferenceList(final PsiReferenceList list) { + result = true; + } + @Override public void visitAnnotation(final PsiAnnotation annotation) { result = true; } diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/strategies/SymbolMatchingStrategy.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/strategies/SymbolMatchingStrategy.java deleted file mode 100644 index f31ee37e8aed..000000000000 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/strategies/SymbolMatchingStrategy.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.intellij.structuralsearch.impl.matcher.strategies; - -import com.intellij.psi.*; - -/** - * CommonStrategy to match symbols - */ -public class SymbolMatchingStrategy extends ExprMatchingStrategy { - @Override public void visitReferenceList(final PsiReferenceList list) { - result = true; - } - - @Override public void visitAnnotation(final PsiAnnotation annotation) { - result = true; - } - - @Override public void visitAnnotationParameterList(final PsiAnnotationParameterList list) { - result = true; - } - - @Override public void visitModifierList(final PsiModifierList list) { - result = true; - } - - @Override public void visitNameValuePair(final PsiNameValuePair pair) { - result = true; - } - - @Override public void visitTypeParameterList(PsiTypeParameterList psiTypeParameterList) { - result = true; - } - - @Override public void visitTypeElement(PsiTypeElement psiTypeElement) { - result = true; - } - - @Override public void visitReferenceElement(PsiJavaCodeReferenceElement psiJavaCodeReferenceElement) { - result = true; - } - - @Override public void visitReferenceParameterList(PsiReferenceParameterList psiReferenceParameterList) { - result = true; - } - - private SymbolMatchingStrategy() {} - - private static class SymbolMatchingStrategyHolder { - private static final SymbolMatchingStrategy instance = new SymbolMatchingStrategy(); - } - - public static MatchingStrategy getInstance() { - return SymbolMatchingStrategyHolder.instance; - } -} diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java index f5f6ee36de49..6398627faff1 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java @@ -2445,12 +2445,14 @@ public class StructuralSearchTest extends StructuralSearchTestCase { "}\n"; assertEquals("Find all annotations", 4, findMatchesCount(source2, "@'_Annotation")); - String source3 = "class A {\n" + + String source3 = "class A<@HH T> extends @HH Object {\n" + " @HH final String s = (@HH String) new @HH Object();\n" + " final String t = (String) new Object();\n" + + " Map<@HH String, @HH List<@HH String>> map;\n" + "}\n"; assertEquals("Find annotated casts", 1, findMatchesCount(source3, "(@'_A 'Cast) '_Expression")); assertEquals("Find annotated new expressions", 1, findMatchesCount(source3, "new @'_A 'Type()")); + assertEquals("Find all annotations 2", 8, findMatchesCount(source3, "@'_Annotation")); // package-info.java final String source4 = "/**\n" + From b4065a7b4daa08ac5c678a1a067685c417f3c63c Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 7 Jan 2015 13:55:35 +0100 Subject: [PATCH 12/19] project: tolerate path spaces when indexing searchable options --- build/scripts/utils.gant | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant index 2a57fb8ff01b..29a081c309a7 100644 --- a/build/scripts/utils.gant +++ b/build/scripts/utils.gant @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,6 @@ * limitations under the License. */ - import org.jetbrains.jps.gant.JpsGantTool import org.jetbrains.jps.gant.TeamCityBuildInfoPrinter import org.jetbrains.jps.model.java.JavaSourceRootType @@ -929,13 +928,18 @@ binding.setVariable("buildSearchableOptions", { String target, List licenses, Cl ant.replace(file: classpathFile, token: File.pathSeparator, value: "\n") ant.java(classname: "com.intellij.rt.execution.CommandLineWrapper", fork: true, failonerror: true) { - jvmarg(line: "-Xbootclasspath/a:${projectBuilder.moduleOutput(findModule("boot"))} -ea -Xmx500m -XX:MaxPermSize=200m") - jvmarg(line: "-Didea.home.path=$home -Didea.system.path=${paths.ideaSystem} -Didea.config.path=${paths.ideaConfig}") + jvmarg(line: "-ea -Xmx500m -XX:MaxPermSize=200m") + jvmarg(value: "-Xbootclasspath/a:${projectBuilder.moduleOutput(findModule("boot"))}") + jvmarg(value: "-Didea.home.path=${home}") + jvmarg(value: "-Didea.system.path=${paths.ideaSystem}") + jvmarg(value: "-Didea.config.path=${paths.ideaConfig}") if (jvmArgs != null) { jvmarg(line: jvmArgs) } - arg(line: "${classpathFile} com.intellij.idea.Main traverseUI ${target}/searchableOptions.xml") + arg(value: "${classpathFile}") + arg(line: "com.intellij.idea.Main traverseUI") + arg(value: "${target}/searchableOptions.xml") classpath() { pathelement(location: "${projectBuilder.moduleOutput(findModule("java-runtime"))}") From 775fdd26163241b5fd19eb1b29b55d05ef48ed68 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 7 Jan 2015 14:15:14 +0100 Subject: [PATCH 13/19] project: index searchable options in CE builds --- build/scripts/dist.gant | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/build/scripts/dist.gant b/build/scripts/dist.gant index 3a7d54ca6c43..3d6b4f5e7502 100644 --- a/build/scripts/dist.gant +++ b/build/scripts/dist.gant @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +29,8 @@ class Paths { final artifacts final artifacts_core final artifacts_jps + final ideaSystem + final ideaConfig def Paths(String out) { sandbox = out @@ -39,6 +41,8 @@ class Paths { artifacts = "$sandbox/artifacts" artifacts_core = "$artifacts/core" artifacts_jps = "$artifacts/jps" + ideaSystem = "$sandbox/system" + ideaConfig = "$sandbox/config" } } @@ -75,6 +79,8 @@ target('default': 'The default target') { zipSources(home, paths.artifacts) + indexSearchableOptions() + layoutAll([buildNumber: "IC-$snapshot", system_selector: "IdeaIC${p("component.version.major")}", tools_jar: true], @@ -83,15 +89,28 @@ target('default': 'The default target') { target('build-dist-jars' : 'Target to build jars from locally compiled classes') { loadProject() + // load ApplicationInfo.xml properties ant.xmlproperty(file: appInfoFile(), collapseAttributes: "true") + indexSearchableOptions() + layoutAll([buildNumber: "IC-$snapshot", system_selector: "IdeaIC${p("component.version.major")}", tools_jar: true], home, null, paths) } +private void indexSearchableOptions() { + buildSearchableOptions("${projectBuilder.moduleOutput(findModule("resources-en"))}/search", [], { + ant.pathelement(location: "$jdkHome/lib/tools.jar") + ant.pathelement(location: "$home/lib/junit.jar") + projectBuilder.moduleRuntimeClasspath(findModule("community-main"), false).each { + ant.pathelement(location: it) + } + }) +} + def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = false) { Paths paths = _paths != null ? _paths : new Paths(out) From 30d745d07998d3304243b643a7a6b29bfa77f0e8 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 7 Jan 2015 13:13:51 +0100 Subject: [PATCH 14/19] IDEA-135005 wrong contract inferred for method which return primitive type --- .../dataFlow/ContractInspection.java | 2 +- .../ContractInferenceFromSourceTest.groovy | 18 ++++++++++++++++++ .../openapi/vfs/local/SymlinkHandlingTest.java | 11 +++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInspection.java index dc86cba28de2..c037da08be16 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInspection.java @@ -115,6 +115,6 @@ public class ContractInspection extends BaseJavaBatchLocalInspectionTool { returnValue == MethodContract.ValueConstraint.NOT_NULL_VALUE; } - return true; + return false; } } diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/ContractInferenceFromSourceTest.groovy b/java/java-tests/testSrc/com/intellij/codeInspection/ContractInferenceFromSourceTest.groovy index 2d2aeb7c92e5..9b13347bba7a 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/ContractInferenceFromSourceTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInspection/ContractInferenceFromSourceTest.groovy @@ -291,6 +291,15 @@ class ContractInferenceFromSourceTest extends LightCodeInsightFixtureTestCase { assert c == [] } + public void "test double constant auto-unboxing"() { + def c = inferContracts(""" + static double method() { + return 1; + } + """) + assert c == [] + } + public void "test non-returning delegation"() { def c = inferContracts(""" static void test2(Object o) { @@ -433,6 +442,15 @@ class ContractInferenceFromSourceTest extends LightCodeInsightFixtureTestCase { assert c == ['null -> !null'] } + public void "test primitive return type"() { + def c = inferContracts(""" + String s(String s) { + return s != "a" ? "b" : null; + } + """) + assert c == ['null -> !null'] + } + public void "test return after if without else"() { def c = inferContracts(""" public static boolean isBlank(String s) { diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/SymlinkHandlingTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/SymlinkHandlingTest.java index 3710fb4bed88..d85cf16e4837 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/SymlinkHandlingTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/SymlinkHandlingTest.java @@ -116,6 +116,17 @@ public class SymlinkHandlingTest extends SymlinkTestCase { link2.getPath() + "/" + link1Home.getName() + "/" + link1.getName()); } + public void testSameTargetShouldBeVisitedSeveralTimesFromSeveralNonRecursiveLinks() throws Exception { + File target = createTestDir(myTempDir, "target"); + File child = createTestDir(myTempDir, "child"); + File link1 = createSymLink(target.getPath(), myTempDir.getPath() + "/link1"); + File link2 = createSymLink(target.getPath(), myTempDir.getPath() + "/link2"); + assertVisitedPaths(myTempDir, + target.getPath(), child.getPath(), + link1.getPath(), link1.getPath() + "/child", + link2.getPath(), link2.getPath() + "/child"); + } + public void testTargetIsWritable() throws Exception { File targetFile = createTestFile(myTempDir, "target.txt"); File linkFile = createSymLink(targetFile.getPath(), myTempDir + "/link"); From 4832a1d4c94eab3ed23639e86e309a7673e26c38 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 7 Jan 2015 13:14:27 +0100 Subject: [PATCH 15/19] move isReturnTypeCompatible to InferenceFromSourceUtil --- .../dataFlow/ContractInference.java | 2 +- .../dataFlow/ContractInspection.java | 21 +------------------ .../dataFlow/InferenceFromSourceUtil.java | 20 ++++++++++++++++++ 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java index 7dcf36afb4ee..231e9d708539 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java @@ -90,7 +90,7 @@ class ContractInferenceInterpreter { if (notNull && contract.returnValue == NOT_NULL_VALUE) { return false; } - return ContractInspection.isReturnTypeCompatible(returnType, contract.returnValue); + return InferenceFromSourceUtil.isReturnTypeCompatible(returnType, contract.returnValue); } }); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInspection.java index c037da08be16..69206a74251a 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInspection.java @@ -92,29 +92,10 @@ public class ContractInspection extends BaseJavaBatchLocalInspectionTool { return "Method takes " + paramCount + " parameters, while contract clause number " + (i + 1) + " expects " + contract.arguments.length; } PsiType returnType = method.getReturnType(); - if (returnType != null && !isReturnTypeCompatible(returnType, contract.returnValue)) { + if (returnType != null && !InferenceFromSourceUtil.isReturnTypeCompatible(returnType, contract.returnValue)) { return "Method returns " + returnType.getPresentableText() + " but the contract specifies " + contract.returnValue; } } return null; } - - static boolean isReturnTypeCompatible(@Nullable PsiType returnType, @NotNull MethodContract.ValueConstraint returnValue) { - if (returnValue == MethodContract.ValueConstraint.ANY_VALUE || returnValue == MethodContract.ValueConstraint.THROW_EXCEPTION) { - return true; - } - if (PsiType.VOID.equals(returnType)) return false; - - if (PsiType.BOOLEAN.equals(returnType)) { - return returnValue == MethodContract.ValueConstraint.TRUE_VALUE || - returnValue == MethodContract.ValueConstraint.FALSE_VALUE; - } - - if (returnType instanceof PsiClassType) { - return returnValue == MethodContract.ValueConstraint.NULL_VALUE || - returnValue == MethodContract.ValueConstraint.NOT_NULL_VALUE; - } - - return false; - } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/InferenceFromSourceUtil.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/InferenceFromSourceUtil.java index 408277627937..998abf2318d2 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/InferenceFromSourceUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/InferenceFromSourceUtil.java @@ -23,6 +23,7 @@ import com.intellij.psi.search.searches.MethodReferencesSearch; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.PsiUtilCore; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author peter @@ -52,4 +53,23 @@ public class InferenceFromSourceUtil { VirtualFile virtualFile = PsiUtilCore.getVirtualFile(method); return virtualFile != null && FileIndexFacade.getInstance(method.getProject()).isInLibrarySource(virtualFile); } + + static boolean isReturnTypeCompatible(@Nullable PsiType returnType, @NotNull MethodContract.ValueConstraint returnValue) { + if (returnValue == MethodContract.ValueConstraint.ANY_VALUE || returnValue == MethodContract.ValueConstraint.THROW_EXCEPTION) { + return true; + } + if (PsiType.VOID.equals(returnType)) return false; + + if (PsiType.BOOLEAN.equals(returnType)) { + return returnValue == MethodContract.ValueConstraint.TRUE_VALUE || + returnValue == MethodContract.ValueConstraint.FALSE_VALUE; + } + + if (returnType instanceof PsiClassType) { + return returnValue == MethodContract.ValueConstraint.NULL_VALUE || + returnValue == MethodContract.ValueConstraint.NOT_NULL_VALUE; + } + + return false; + } } From be013a9adc6c5c61442b740a51c21a8a38e9b797 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Wed, 7 Jan 2015 14:35:54 +0100 Subject: [PATCH 16/19] Execute selection in selected visible console when there are more then one (PY-14847). --- .../actions/PyExecuteSelectionAction.java | 5 ++++- .../console/PythonConsoleToolWindow.java | 20 +++++++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/python/src/com/jetbrains/python/actions/PyExecuteSelectionAction.java b/python/src/com/jetbrains/python/actions/PyExecuteSelectionAction.java index adc8dc77fd0e..f23943f3f113 100644 --- a/python/src/com/jetbrains/python/actions/PyExecuteSelectionAction.java +++ b/python/src/com/jetbrains/python/actions/PyExecuteSelectionAction.java @@ -15,6 +15,7 @@ */ package com.jetbrains.python.actions; +import com.google.common.collect.Lists; import com.intellij.execution.ExecutionHelper; import com.intellij.execution.console.LanguageConsoleView; import com.intellij.execution.process.ProcessHandler; @@ -28,6 +29,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; +import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; import com.intellij.util.NotNullFunction; import com.jetbrains.python.console.PyCodeExecutor; @@ -191,7 +193,8 @@ public class PyExecuteSelectionAction extends AnAction { PythonConsoleToolWindow toolWindow = PythonConsoleToolWindow.getInstance(project); if (toolWindow != null && toolWindow.getToolWindow().isVisible()) { - return toolWindow.getConsoleContentDescriptors(); + RunContentDescriptor selectedContentDescriptor = toolWindow.getSelectedContentDescriptor(); + return selectedContentDescriptor != null ? Lists.newArrayList(selectedContentDescriptor) : Lists.newArrayList(); } Collection descriptors = diff --git a/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java b/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java index c5cac180ed1a..1ddbe97a0fa1 100644 --- a/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java +++ b/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java @@ -45,6 +45,14 @@ import java.util.List; public class PythonConsoleToolWindow { public static final Key CONTENT_DESCRIPTOR = Key.create("CONTENT_DESCRIPTOR"); + public static final Function + CONTENT_TO_DESCRIPTOR_FUNCTION = new Function() { + @Override + public RunContentDescriptor apply(@Nullable Content input) { + return input != null ? input.getUserData(CONTENT_DESCRIPTOR) : null; + } + }; + private final Project myProject; private boolean myInitialized = false; @@ -61,12 +69,7 @@ public class PythonConsoleToolWindow { public List getConsoleContentDescriptors() { return FluentIterable.from(Lists.newArrayList(getToolWindow().getContentManager().getContents())) - .transform(new Function() { - @Override - public RunContentDescriptor apply(@Nullable Content input) { - return input != null ? input.getUserData(CONTENT_DESCRIPTOR) : null; - } - }).filter( + .transform(CONTENT_TO_DESCRIPTOR_FUNCTION).filter( Predicates.notNull()).toList(); } @@ -172,4 +175,9 @@ public class PythonConsoleToolWindow { myActivation.doWhenDone(runnable); getToolWindow().activate(null); } + + @Nullable + public RunContentDescriptor getSelectedContentDescriptor() { + return CONTENT_TO_DESCRIPTOR_FUNCTION.apply(getToolWindow().getContentManager().getSelectedContent()); + } } From ee90d442b1a959c96a7bfbe8c69658494ceb6076 Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Wed, 7 Jan 2015 09:39:09 +0300 Subject: [PATCH 17/19] Emmet: fix implicit attributes expansion --- xml/impl/resources/liveTemplates/zen_html.xml | 12 +++++++-- .../template/emmet/tokens/TemplateToken.java | 26 +++---------------- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/xml/impl/resources/liveTemplates/zen_html.xml b/xml/impl/resources/liveTemplates/zen_html.xml index 76a1d65d4779..acb372af0c34 100644 --- a/xml/impl/resources/liveTemplates/zen_html.xml +++ b/xml/impl/resources/liveTemplates/zen_html.xml @@ -159,6 +159,14 @@