From 6ff114a34f896191adda4c2a712b5467153cdb39 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 28 Mar 2012 17:14:30 +0200 Subject: [PATCH 01/32] remove unused method --- .../src/com/intellij/openapi/vcs/history/VcsFileRevision.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/history/VcsFileRevision.java b/platform/vcs-api/src/com/intellij/openapi/vcs/history/VcsFileRevision.java index cde1286f74f5..7debd8ac98c7 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/history/VcsFileRevision.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/history/VcsFileRevision.java @@ -56,10 +56,6 @@ public interface VcsFileRevision extends VcsFileContent, VcsRevisionDescription public byte[] getContent() throws IOException, VcsException { return ArrayUtil.EMPTY_BYTE_ARRAY; } - - public int compareTo(VcsFileRevision vcsFileRevision) { - return 0; - } }; String getBranchName(); From 369aebd0a3f0a3c9582d4a6e9e2d75bade08b9fa Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 2 Apr 2012 14:11:38 +0200 Subject: [PATCH 02/32] a registry key for IDEA-83547 "Show implementations" does not show derived interfaces --- .../codeInsight/navigation/ClassImplementationsSearch.java | 7 ++++++- .../platform-resources-en/src/misc/registry.properties | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/navigation/ClassImplementationsSearch.java b/java/java-impl/src/com/intellij/codeInsight/navigation/ClassImplementationsSearch.java index 537f2ff19087..a19630dad65c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/navigation/ClassImplementationsSearch.java +++ b/java/java-impl/src/com/intellij/codeInsight/navigation/ClassImplementationsSearch.java @@ -17,6 +17,7 @@ package com.intellij.codeInsight.navigation; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.search.PsiElementProcessor; @@ -33,6 +34,7 @@ public class ClassImplementationsSearch implements QueryExecutor processor) { + final boolean showInterfaces = Registry.is("ide.goto.implementation.show.interfaces"); return ClassInheritorsSearch.search(psiClass, ApplicationManager.getApplication().runReadAction(new Computable() { @Override public SearchScope compute() { @@ -40,7 +42,10 @@ public class ClassImplementationsSearch implements QueryExecutor(new PsiElementProcessor() { public boolean execute(@NotNull PsiClass element) { - return element.isInterface() || processor.process(element); + if (!showInterfaces && element.isInterface()) { + return true; + } + return processor.process(element); } })); } diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index 8ea41c1133c1..a85422a2a634 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -206,3 +206,6 @@ python.exported.names.local.cache=false ide.use.nautilus3=true ide.use.nautilus3.description=Use Nautilus if available + +ide.goto.implementation.show.interfaces=false +ide.goto.implementation.show.interfaces.description=Whether to show sub-interfaces when invoking Goto Implementation (Ctrl+Alt+B) on an interface \ No newline at end of file From 2d5a17c46fe7486d8a6d91513d37c857b7585cce Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 30 Mar 2012 18:11:20 +0200 Subject: [PATCH 03/32] skip change lists scopes for default project (IDEA-83804) --- .../intellij/packageDependencies/ChangeListsScopesProvider.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ChangeListsScopesProvider.java b/platform/lang-impl/src/com/intellij/packageDependencies/ChangeListsScopesProvider.java index 694bc0421d45..64f8867eeae8 100644 --- a/platform/lang-impl/src/com/intellij/packageDependencies/ChangeListsScopesProvider.java +++ b/platform/lang-impl/src/com/intellij/packageDependencies/ChangeListsScopesProvider.java @@ -89,6 +89,7 @@ public class ChangeListsScopesProvider extends CustomScopesProviderEx { @Override public boolean isVetoed(NamedScope scope, ScopePlace place) { if (place == ScopePlace.SETTING) { + if (myProject.isDefault()) return false; final ChangeListManager changeListManager = ChangeListManager.getInstance(myProject); return changeListManager.findChangeList(scope.getName()) != null; } From 1e7c9dd3801bede80da76ec8d0677084cecda426 Mon Sep 17 00:00:00 2001 From: anna Date: Fri, 30 Mar 2012 18:48:54 +0200 Subject: [PATCH 04/32] generate test method template: do not override users template with default method body (IDEA-83443) --- .../com/intellij/testIntegration/TestIntegrationUtils.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/testIntegration/TestIntegrationUtils.java b/java/java-impl/src/com/intellij/testIntegration/TestIntegrationUtils.java index 5ca01a66ab2b..ab378ccbc312 100644 --- a/java/java-impl/src/com/intellij/testIntegration/TestIntegrationUtils.java +++ b/java/java-impl/src/com/intellij/testIntegration/TestIntegrationUtils.java @@ -160,7 +160,9 @@ public class TestIntegrationUtils { if (el != null) { PsiMethod method = PsiTreeUtil.getParentOfType(el, PsiMethod.class, false); if (method != null) { - GenerateMembersUtil.setupGeneratedMethod(method); + if (method.findDeepestSuperMethods().length > 0) { + GenerateMembersUtil.setupGeneratedMethod(method); + } CreateFromUsageUtils.setupEditor(method, editor); } } From 0be81dd0db3ffededcf6478d9b0d784615cfa7c8 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 2 Apr 2012 11:29:05 +0200 Subject: [PATCH 05/32] backgroundable check foe updates (IDEA-83771) --- .../plugins/InstalledPluginsTableModel.java | 2 +- .../ide/plugins/PluginManagerMain.java | 5 ++- .../ide/plugins/RepositoryHelper.java | 40 +++++++++++++------ .../impl/CheckForUpdateAction.java | 5 ++- .../updateSettings/impl/UpdateChecker.java | 26 ++++++++---- 5 files changed, 54 insertions(+), 24 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java index eb7988bdee4d..b961f4c80423 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java @@ -136,7 +136,7 @@ public class InstalledPluginsTableModel extends PluginTableModel { for (String host : pluginHosts) { try { final ArrayList downloaded = new ArrayList(); - UpdateChecker.checkPluginsHost(host, downloaded, false); + UpdateChecker.checkPluginsHost(host, downloaded, false, null); for (PluginDownloader downloader : downloaded) { myPlugin2host.put(downloader.getPluginId(), host); } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java index 18f873d2c270..4d533fc3a724 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java @@ -25,6 +25,7 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; @@ -219,7 +220,7 @@ public abstract class PluginManagerMain implements Disposable { for (String host : UpdateSettings.getInstance().myPluginHosts) { final ArrayList downloaded = new ArrayList(); try { - UpdateChecker.checkPluginsHost(host, downloaded, false); + UpdateChecker.checkPluginsHost(host, downloaded, false, null); for (PluginDownloader downloader : downloaded) { final PluginNode pluginNode = PluginDownloader.createPluginNode(host, downloader); if (pluginNode != null) { @@ -228,6 +229,8 @@ public abstract class PluginManagerMain implements Disposable { } } } + catch (ProcessCanceledException ignore) { + } catch (Exception e) { LOG.info(e); errorMessages.add(e.getMessage()); diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java index 40e5787fed51..2afa077e15ab 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java @@ -19,6 +19,8 @@ import com.intellij.ide.IdeBundle; import com.intellij.openapi.application.ApplicationInfo; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.impl.ApplicationInfoImpl; +import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.util.BuildNumber; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.net.HttpConfigurable; @@ -53,31 +55,39 @@ public class RepositoryHelper { @NonNls private static final String FILENAME = "filename="; @NonNls public static final String extPluginsFile = "availables.xml"; - public static ArrayList process(@Nullable JLabel label) throws IOException, ParserConfigurationException, SAXException { + public static ArrayList process(@Nullable ProgressIndicator indicator) throws IOException, ParserConfigurationException, SAXException { ArrayList plugins = null; try { BuildNumber buildNumber = ApplicationInfo.getInstance().getBuild(); @NonNls String url = getListUrl() + "?build=" + buildNumber.asString(); - setLabelText(label, IdeBundle.message("progress.connecting.to.plugin.manager", getRepositoryHost())); + if (indicator != null) { + indicator.setText2(IdeBundle.message("progress.connecting.to.plugin.manager", getRepositoryHost())); + } HttpConfigurable.getInstance().prepareURL(getRepositoryHost()); // if( !pi.isCanceled() ) { RepositoryContentHandler handler = new RepositoryContentHandler(); HttpURLConnection connection = (HttpURLConnection)new URL(url).openConnection(); - setLabelText(label, IdeBundle.message("progress.waiting.for.reply.from.plugin.manager", getRepositoryHost())); + if (indicator != null) { + indicator.setText2(IdeBundle.message("progress.waiting.for.reply.from.plugin.manager", getRepositoryHost())); + } InputStream is = getConnectionInputStream(connection); if (is != null) { - setLabelText(label, IdeBundle.message("progress.downloading.list.of.plugins")); - File temp = createLocalPluginsDescriptions(); - readPluginsStream(temp, is, handler); + if (indicator != null) { + indicator.setText2(IdeBundle.message("progress.downloading.list.of.plugins")); + } + readPluginsStream( is, handler, indicator, extPluginsFile); plugins = handler.getPluginsList(); } } } + catch (ProcessCanceledException e) { + throw e; + } catch (RuntimeException e) { e.printStackTrace(); if (e.getCause() == null || !(e.getCause() instanceof InterruptedException)) { @@ -105,11 +115,11 @@ public class RepositoryHelper { } } - public static File createLocalPluginsDescriptions() throws IOException { + private static File createLocalPluginsDescriptions(final String file) throws IOException { File basePath = new File(PathManager.getPluginsPath()); basePath.mkdirs(); - File temp = new File(basePath, extPluginsFile); + File temp = new File(basePath, file); if (temp.exists()) { FileUtil.delete(temp); } @@ -117,8 +127,9 @@ public class RepositoryHelper { return temp; } - public static void readPluginsStream(File temp, InputStream is, RepositoryContentHandler handler) - throws SAXException, IOException, ParserConfigurationException { + private static void readPluginsStream(InputStream is, RepositoryContentHandler handler, ProgressIndicator indicator, final String file) + throws SAXException, IOException, ParserConfigurationException, ProcessCanceledException { + File temp = createLocalPluginsDescriptions(file); SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); FileOutputStream fos = null; try { @@ -128,6 +139,10 @@ public class RepositoryHelper { int size = is.read(buffer); if (size == -1) break; fos.write(buffer, 0, size); + + if (indicator != null) { + indicator.checkCanceled(); + } } while (true); fos.close(); @@ -142,11 +157,10 @@ public class RepositoryHelper { } } - public static ArrayList loadPluginsFromDescription(InputStream inputStream) throws SAXException, IOException, ParserConfigurationException { + public static ArrayList loadPluginsFromDescription(InputStream inputStream, ProgressIndicator indicator) throws SAXException, IOException, ParserConfigurationException { try { RepositoryContentHandler handler = new RepositoryContentHandler(); - SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); - parser.parse(inputStream, handler); + readPluginsStream(inputStream, handler, indicator, "host.xml"); return handler.getPluginsList(); } finally { 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 98b9f4d6bf93..089338910882 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 @@ -46,13 +46,14 @@ public class CheckForUpdateAction extends AnAction implements DumbAware { final boolean enableLink, final @Nullable PluginHostsConfigurable hostsConfigurable, final UpdateSettings instance) { - ProgressManager.getInstance().run(new Task.Modal(project, "Checking for updates", false) { + ProgressManager.getInstance().run(new Task.Backgroundable(project, "Checking for updates", true) { @Override public void run(@NotNull ProgressIndicator indicator) { indicator.setIndeterminate(true); final CheckForUpdateResult result = UpdateChecker.checkForUpdates(instance, true); - final List updatedPlugins = UpdateChecker.updatePlugins(true, hostsConfigurable); + final List updatedPlugins = UpdateChecker.updatePlugins(true, hostsConfigurable, indicator); + if (updatedPlugins == null) return; ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java index 94684b597904..74601a31c964 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java @@ -160,7 +160,7 @@ public final class UpdateChecker { public void run() { final CheckForUpdateResult checkForUpdateResult = checkForUpdates(updateSettings, false); - final List updatedPlugins = updatePlugins(false, null); + final List updatedPlugins = updatePlugins(false, null, null); app.invokeLater(new Runnable() { @Override public void run() { @@ -174,12 +174,16 @@ public final class UpdateChecker { } public static List updatePlugins(final boolean showErrorDialog, - final @Nullable PluginHostsConfigurable hostsConfigurable) { + final @Nullable PluginHostsConfigurable hostsConfigurable, + @Nullable ProgressIndicator indicator) { final List downloaded = new ArrayList(); final Set failed = new HashSet(); for (String host : getPluginHosts(hostsConfigurable)) { try { - checkPluginsHost(host, downloaded); + checkPluginsHost(host, downloaded, true, indicator); + } + catch (ProcessCanceledException e) { + return null; } catch (Exception e) { LOG.info(e); @@ -198,7 +202,7 @@ public final class UpdateChecker { updateSettings.myOutdatedPlugins.clear(); if (!toUpdate.isEmpty()) { try { - final ArrayList process = RepositoryHelper.process(null); + final ArrayList process = RepositoryHelper.process(indicator); for (IdeaPluginDescriptor loadedPlugin : process) { final String idString = loadedPlugin.getPluginId().getIdString(); final IdeaPluginDescriptor installedPlugin = toUpdate.get(idString); @@ -215,6 +219,9 @@ public final class UpdateChecker { } } } + catch (ProcessCanceledException ignore) { + return null; + } catch (Exception e) { showErrorMessage(showErrorDialog, e.getMessage()); } @@ -256,12 +263,17 @@ public final class UpdateChecker { } public static boolean checkPluginsHost(final String host, final List downloaded) throws Exception { - return checkPluginsHost(host, downloaded, true); + try { + return checkPluginsHost(host, downloaded, true, null); + } + catch (ProcessCanceledException e) { + return false; + } } public static boolean checkPluginsHost(final String host, final List downloaded, - final boolean collectToUpdate) throws Exception { + final boolean collectToUpdate, @Nullable ProgressIndicator indicator) throws Exception { InputStream inputStream = loadVersionInfo(host); if (inputStream == null) return false; final Document document; @@ -274,7 +286,7 @@ public final class UpdateChecker { inputStream = loadVersionInfo(host); if (inputStream == null) return false; - final ArrayList descriptors = RepositoryHelper.loadPluginsFromDescription(inputStream); + final ArrayList descriptors = RepositoryHelper.loadPluginsFromDescription(inputStream, indicator); for (IdeaPluginDescriptor descriptor : descriptors) { ((PluginNode)descriptor).setRepositoryName(host); downloaded.add(PluginDownloader.createDownloader(descriptor)); From 671a9e1c612aedde2f97cac60dab9b56c3c6f4ad Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 2 Apr 2012 11:38:20 +0200 Subject: [PATCH 06/32] configurable installed/updated plugin colors (IDEA-83784) --- .../com/intellij/ide/plugins/AvailablePluginColumnInfo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginColumnInfo.java b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginColumnInfo.java index 757647ed8cd0..2d6f38fab769 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginColumnInfo.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginColumnInfo.java @@ -97,7 +97,7 @@ class AvailablePluginColumnInfo extends PluginManagerColumnInfo { } final IdeaPluginDescriptor installed = PluginManager.getPlugin(pluginNode.getPluginId()); if (isDownloaded(pluginNode) || (installed != null && InstalledPluginsTableModel.wasUpdated(installed.getPluginId()))) { - if (!isSelected) myNameLabel.setForeground(FileStatus.COLOR_ADDED); + if (!isSelected) myNameLabel.setForeground(FileStatus.ADDED.getColor()); myStatusLabel.setText("[Downloaded]"); myPanel.setToolTipText(IdeBundle.message("plugin.download.status.tooltip")); myStatusLabel.setBorder(BorderFactory.createEmptyBorder(0, LEFT_MARGIN, 0, 0)); @@ -105,7 +105,7 @@ class AvailablePluginColumnInfo extends PluginManagerColumnInfo { else if (pluginNode.getStatus() == PluginNode.STATUS_INSTALLED) { PluginId pluginId = pluginNode.getPluginId(); final boolean hasNewerVersion = InstalledPluginsTableModel.hasNewerVersion(pluginId); - if (!isSelected) myNameLabel.setForeground(FileStatus.COLOR_MODIFIED); + if (!isSelected) myNameLabel.setForeground(FileStatus.MODIFIED.getColor()); if (hasNewerVersion) { if (!isSelected){ myNameLabel.setForeground(Color.RED); From 6c7ec7a2f7f4a74edd88abf323bc0410b1ed2adb Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 2 Apr 2012 14:25:53 +0200 Subject: [PATCH 07/32] plugins: sort should update default sort key (IDEA-83783) --- .../ide/plugins/PluginManagerColumnInfo.java | 18 ++++++++++-------- .../com/intellij/ide/plugins/PluginTable.java | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerColumnInfo.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerColumnInfo.java index 1f22aeb65f66..a5d4c4b98715 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerColumnInfo.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerColumnInfo.java @@ -126,35 +126,37 @@ class PluginManagerColumnInfo extends ColumnInfo { public Comparator getComparator() { final Comparator comparator = getColumnComparator(); if (isSortByStatus()) { + final RowSorter.SortKey defaultSortKey = myModel.getDefaultSortKey(); + final int up = defaultSortKey != null && defaultSortKey.getSortOrder() == SortOrder.ASCENDING ? -1 : 1; return new Comparator() { public int compare(IdeaPluginDescriptor o1, IdeaPluginDescriptor o2) { if (o1 instanceof PluginNode && o2 instanceof PluginNode) { final int status1 = ((PluginNode)o1).getStatus(); final int status2 = ((PluginNode)o2).getStatus(); if (isDownloaded((PluginNode)o1)){ - if (!isDownloaded((PluginNode)o2)) return -1; + if (!isDownloaded((PluginNode)o2)) return up; return comparator.compare(o1, o2); } - if (isDownloaded((PluginNode)o2)) return 1; + if (isDownloaded((PluginNode)o2)) return -up; if (status1 == PluginNode.STATUS_DELETED) { - if (status2 != PluginNode.STATUS_DELETED) return -1; + if (status2 != PluginNode.STATUS_DELETED) return up; return comparator.compare(o1, o2); } - if (status2 == PluginNode.STATUS_DELETED) return 1; + if (status2 == PluginNode.STATUS_DELETED) return -up; if (status1 == PluginNode.STATUS_INSTALLED) { - if (status2 !=PluginNode.STATUS_INSTALLED) return -1; + if (status2 !=PluginNode.STATUS_INSTALLED) return up; final boolean hasNewerVersion1 = InstalledPluginsTableModel.hasNewerVersion(o1.getPluginId()); final boolean hasNewerVersion2 = InstalledPluginsTableModel.hasNewerVersion(o2.getPluginId()); if (hasNewerVersion1 != hasNewerVersion2) { - if (hasNewerVersion1) return -1; - return 1; + if (hasNewerVersion1) return up; + return -up; } return comparator.compare(o1, o2); } if (status2 == PluginNode.STATUS_INSTALLED) { - return 1; + return -up; } } return comparator.compare(o1, o2); diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginTable.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginTable.java index a468bf65fe6c..5d06987c5006 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginTable.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginTable.java @@ -23,6 +23,9 @@ import com.intellij.util.ui.ColumnInfo; import javax.swing.*; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; +import javax.swing.table.TableRowSorter; +import java.util.List; /** * Created by IntelliJ IDEA. @@ -59,6 +62,19 @@ public class PluginTable extends JBTable { column.setMaxWidth(width); } + @Override + protected TableRowSorter createRowSorter(TableModel model) { + return new DefaultColumnInfoBasedRowSorter(model){ + @Override + public void setSortKeys(List sortKeys) { + if (sortKeys != null && !sortKeys.isEmpty()) { + ((PluginTableModel)getModel()).setSortKey(sortKeys.get(0)); + } + super.setSortKeys(sortKeys); + } + }; + } + @Override protected boolean isSortOnUpdates() { return false; From 7513ab344e27ff1371d9e1e63f41be89668f30c2 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Sun, 1 Apr 2012 18:38:07 +0400 Subject: [PATCH 08/32] some refactoring --- .../controlFlow/impl/ControlFlowBuilder.java | 36 +++++++------------ 1 file changed, 13 insertions(+), 23 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 1fea9d257838..6cc10132a17c 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 @@ -236,6 +236,11 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { myHead = instruction; } + private void addNodeAndCheckPending(InstructionImpl i) { + addNode(i); + checkPending(i); + } + private static void addEdge(InstructionImpl begin, InstructionImpl end) { begin.addSuccessor(end); end.addPredecessor(begin); @@ -256,15 +261,10 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { } for (String name : names) { - ReadWriteVariableInstruction i = new ReadWriteVariableInstruction(name, closure, myInstructionNumber++, READ); - addNode(i); - checkPending(i); + addNodeAndCheckPending(new ReadWriteVariableInstruction(name, closure, myInstructionNumber++, READ)); } - - InstructionImpl i = new InstructionImpl(closure, myInstructionNumber++); - addNode(i); - checkPending(i); + addNodeAndCheckPending(new InstructionImpl(closure, myInstructionNumber++)); } public void visitBreakStatement(GrBreakStatement breakStatement) { @@ -332,8 +332,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { exception.accept(this); final InstructionImpl throwInstruction = new ThrowingInstruction(throwStatement, myInstructionNumber++); - addNode(throwInstruction); - checkPending(throwInstruction); + addNodeAndCheckPending(throwInstruction); interruptFlow(); final PsiType type = exception.getNominalType(); @@ -382,9 +381,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++, READ); - addNode(instruction); - checkPending(instruction); + addNodeAndCheckPending(new ReadWriteVariableInstruction(referenceName, lValue, myInstructionNumber++, READ)); } } } @@ -438,9 +435,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { } else { boolean isWrite = !myAssertionsOnly && PsiUtil.isLValue(refExpr); - final InstructionImpl i = new ReadWriteVariableInstruction(name, refExpr, myInstructionNumber++, isWrite ? WRITE : READ); - addNode(i); - checkPending(i); + addNodeAndCheckPending(new ReadWriteVariableInstruction(name, refExpr, myInstructionNumber++, isWrite ? WRITE : READ)); } } else if (!(refExpr.getParent() instanceof GrCall)) { @@ -507,8 +502,7 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { return; } final InstructionImpl instruction = new ThrowingInstruction(call, myInstructionNumber++); - addNode(instruction); - checkPending(instruction); + addNodeAndCheckPending(instruction); for (ExceptionInfo info : myCaughtExceptionInfos) { info.myThrowers.add(instruction); @@ -934,13 +928,9 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { } for (String var : vars) { - ReadWriteVariableInstruction i = new ReadWriteVariableInstruction(var, typeDefinition, myInstructionNumber++, READ); - addNode(i); - checkPending(i); + addNodeAndCheckPending(new ReadWriteVariableInstruction(var, typeDefinition, myInstructionNumber++, READ)); } - InstructionImpl i = new InstructionImpl(typeDefinition, myInstructionNumber++); - addNode(i); - checkPending(i); + addNodeAndCheckPending(new InstructionImpl(typeDefinition, myInstructionNumber++)); } public void visitVariable(GrVariable variable) { From a657f4dba2dc70b4c13990b3c8bd5a61506d1fe2 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Mon, 2 Apr 2012 15:19:16 +0400 Subject: [PATCH 09/32] some refactoring in GrClosureSignatureUtil --- .../ConvertParameterToMapEntryIntention.java | 5 +- .../impl/types/GrClosureSignatureUtil.java | 25 +--- .../GrMethodCallUsageInfo.java | 5 +- .../convertToJava/ArgumentListGenerator.java | 4 +- .../convertToJava/TypeProvider.java | 3 +- .../GrIntroduceClosureParameterProcessor.java | 14 +- .../GroovyIntroduceParameterUtil.java | 9 +- ...troduceParameterMethodUsagesProcessor.java | 5 +- .../completion/GroovyCompletionTest.groovy | 130 +++++++++++++++--- .../lang/resolve/ResolveMethodTest.groovy | 52 +++++++ .../lang/resolve/TypeInferenceTest.groovy | 70 +++++++++- .../highlighting/UnknownVarInArgList.groovy | 3 +- 12 files changed, 256 insertions(+), 69 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java index 5f9135e6b5a8..9df9be1313fa 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java @@ -267,11 +267,8 @@ public class ConvertParameterToMapEntryIntention extends Intention { } } } - final GrArgumentList argumentList = call.getArgumentList(); - final GrClosableBlock[] closureArguments = call.getClosureArguments(); - final GrClosureSignatureUtil.ArgInfo[] argInfos = - GrClosureSignatureUtil.mapParametersToArguments(signature, argumentList, argumentList, closureArguments); + final GrClosureSignatureUtil.ArgInfo[] argInfos = GrClosureSignatureUtil.mapParametersToArguments(signature, call); if (argInfos == null) continue; final GrClosureSignatureUtil.ArgInfo argInfo = argInfos[index]; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java index b0bea6e761d6..b22bff737a58 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java @@ -30,7 +30,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; @@ -494,7 +493,7 @@ public class GrClosureSignatureUtil { return null; } - final ArgInfo[] argInfos = mapParametersToArguments(signature, namedArgs, expressionArgs, context, closureArguments, partial, eraseArgs); + final ArgInfo[] argInfos = mapParametersToArguments(signature, namedArgs, expressionArgs, closureArguments, context, partial, eraseArgs); if (argInfos == null) { return null; } @@ -520,30 +519,18 @@ public class GrClosureSignatureUtil { @Nullable - public static ArgInfo[] mapParametersToArguments(@NotNull GrClosureSignature signature, - @Nullable GrArgumentList list, - @NotNull GroovyPsiElement context, - @NotNull GrClosableBlock[] closureArguments) { - return mapParametersToArguments(signature, list, context, closureArguments, false, false); - } - - @Nullable - public static ArgInfo[] mapParametersToArguments(@NotNull GrClosureSignature signature, - @Nullable GrArgumentList list, - @NotNull GroovyPsiElement context, - @NotNull GrClosableBlock[] closureArguments, final boolean partial, final boolean eraseArgs) { - final GrNamedArgument[] namedArgs = list == null ? GrNamedArgument.EMPTY_ARRAY : list.getNamedArguments(); - final GrExpression[] expressionArgs = list == null ? GrExpression.EMPTY_ARRAY : list.getExpressionArguments(); - return mapParametersToArguments(signature, namedArgs, expressionArgs, context, closureArguments, partial, eraseArgs); + public static ArgInfo[] mapParametersToArguments(@NotNull GrClosureSignature signature, @NotNull GrCall call) { + return mapParametersToArguments(signature, call.getNamedArguments(), call.getExpressionArguments(), call.getClosureArguments(), call, + false, false); } @Nullable public static ArgInfo[] mapParametersToArguments(@NotNull GrClosureSignature signature, @NotNull GrNamedArgument[] namedArgs, @NotNull GrExpression[] expressionArgs, - @NotNull GroovyPsiElement context, @NotNull GrClosableBlock[] closureArguments, - final boolean partial, boolean eraseArgs) { + @NotNull GroovyPsiElement context, + boolean partial, boolean eraseArgs) { List innerArgs = new ArrayList(); boolean hasNamedArgs = namedArgs.length > 0; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java index 560f2dbdf212..ff776b36f855 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java @@ -81,9 +81,8 @@ public class GrMethodCallUsageInfo extends UsageInfo implements PossiblyIncorrec myMapToArguments = GrClosureSignatureUtil.ArgInfo.empty_array(); } else { - myMapToArguments = GrClosureSignatureUtil - .mapParametersToArguments(signature, call.getNamedArguments(), call.getExpressionArguments(), call, call.getClosureArguments(), - false, false); + myMapToArguments = GrClosureSignatureUtil.mapParametersToArguments(signature, call.getNamedArguments(), call.getExpressionArguments(), + call.getClosureArguments(), call, false, false); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java index f62cde5b3726..125ff6181ac9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java @@ -56,10 +56,10 @@ class ArgumentListGenerator { GrClosableBlock[] clArgs, GroovyPsiElement context) { GrClosureSignatureUtil.ArgInfo[] argInfos = - signature == null ? null : GrClosureSignatureUtil.mapParametersToArguments(signature, namedArgs, exprs, context, clArgs, false, false); + signature == null ? null : GrClosureSignatureUtil.mapParametersToArguments(signature, namedArgs, exprs, clArgs, context, false, false); if (argInfos == null && signature != null) { - argInfos = GrClosureSignatureUtil.mapParametersToArguments(signature, namedArgs, exprs, context, clArgs, true, true); + argInfos = GrClosureSignatureUtil.mapParametersToArguments(signature, namedArgs, exprs, clArgs, context, true, true); } final PsiSubstitutor substitutor = signature == null ? PsiSubstitutor.EMPTY : signature.getSubstitutor(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/TypeProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/TypeProvider.java index be043d1771ce..e25b52f8ef63 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/TypeProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/TypeProvider.java @@ -129,8 +129,7 @@ public class TypeProvider { if (element instanceof GrReferenceExpression) { final GrCall call = (GrCall)element.getParent(); - final GrClosureSignatureUtil.ArgInfo[] argInfos = GrClosureSignatureUtil - .mapParametersToArguments(signature, call.getArgumentList(), ((GrReferenceExpression)element), call.getClosureArguments()); + final GrClosureSignatureUtil.ArgInfo[] argInfos = GrClosureSignatureUtil.mapParametersToArguments(signature, call); if (argInfos == null) return true; paramInds.forEach(new TIntProcedure() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceClosureParameterProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceClosureParameterProcessor.java index 94e1e6780310..4a639e00077d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceClosureParameterProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceClosureParameterProcessor.java @@ -396,8 +396,9 @@ public class GrIntroduceClosureParameterProcessor extends BaseRefactoringProcess GrClosureSignature signature = GrClosureSignatureUtil.createSignature(callExpression); if (signature == null) signature = GrClosureSignatureUtil.createSignature(toReplaceIn); - final GrClosureSignatureUtil.ArgInfo[] actualArgs = - GrClosureSignatureUtil.mapParametersToArguments(signature, argList, callExpression, callExpression.getClosureArguments(), true, true); + final GrClosureSignatureUtil.ArgInfo[] actualArgs = GrClosureSignatureUtil + .mapParametersToArguments(signature, callExpression.getNamedArguments(), callExpression.getExpressionArguments(), + callExpression.getClosureArguments(), callExpression, true, true); if (PsiTreeUtil.isAncestor(toReplaceIn, callExpression, false)) { argList.addAfter(factory.createExpressionFromText(settings.getName()), anchor); @@ -568,7 +569,7 @@ public class GrIntroduceClosureParameterProcessor extends BaseRefactoringProcess argList.add(expression); } - removeParametersFromCall(methodCall, argList, settings); + removeParametersFromCall(methodCall, settings); } else { @@ -576,15 +577,12 @@ public class GrIntroduceClosureParameterProcessor extends BaseRefactoringProcess } } - private static void removeParametersFromCall(GrMethodCallExpression methodCall, - GrArgumentList argList, - GrIntroduceParameterSettings settings) { + private static void removeParametersFromCall(GrMethodCallExpression methodCall, GrIntroduceParameterSettings settings) { final GroovyResolveResult resolveResult = methodCall.advancedResolve(); final PsiElement resolved = resolveResult.getElement(); LOG.assertTrue(resolved instanceof PsiMethod); final GrClosureSignature signature = GrClosureSignatureUtil.createSignature((PsiMethod)resolved, resolveResult.getSubstitutor()); - final GrClosureSignatureUtil.ArgInfo[] argInfos = - GrClosureSignatureUtil.mapParametersToArguments(signature, argList, methodCall, methodCall.getClosureArguments()); + final GrClosureSignatureUtil.ArgInfo[] argInfos = GrClosureSignatureUtil.mapParametersToArguments(signature, methodCall); LOG.assertTrue(argInfos != null); settings.parametersToRemove().forEach(new TIntProcedure() { @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GroovyIntroduceParameterUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GroovyIntroduceParameterUtil.java index c4c04e341240..5878254aa972 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GroovyIntroduceParameterUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GroovyIntroduceParameterUtil.java @@ -219,18 +219,15 @@ public class GroovyIntroduceParameterUtil { argList.add(expression); } - removeParametersFromCall(methodCall, argList, settings); + removeParametersFromCall(methodCall, settings); } - private static void removeParametersFromCall(GrMethodCallExpression methodCall, - GrArgumentList argList, - GrIntroduceParameterSettings settings) { + private static void removeParametersFromCall(GrMethodCallExpression methodCall, GrIntroduceParameterSettings settings) { final GroovyResolveResult resolveResult = methodCall.advancedResolve(); final PsiElement resolved = resolveResult.getElement(); LOG.assertTrue(resolved instanceof PsiMethod); final GrClosureSignature signature = GrClosureSignatureUtil.createSignature((PsiMethod)resolved, resolveResult.getSubstitutor()); - final GrClosureSignatureUtil.ArgInfo[] argInfos = - GrClosureSignatureUtil.mapParametersToArguments(signature, argList, methodCall, methodCall.getClosureArguments()); + final GrClosureSignatureUtil.ArgInfo[] argInfos = GrClosureSignatureUtil.mapParametersToArguments(signature, methodCall); LOG.assertTrue(argInfos != null); settings.parametersToRemove().forEach(new TIntProcedure() { @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java index c27c632706a5..58956c089553 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java @@ -101,8 +101,9 @@ public class GroovyIntroduceParameterMethodUsagesProcessor implements IntroduceP GrClosureSignature signature = GrClosureSignatureUtil.createSignature(callExpression); if (signature == null) signature = GrClosureSignatureUtil.createSignature(data.getMethodToSearchFor(), PsiSubstitutor.EMPTY); - final GrClosureSignatureUtil.ArgInfo[] actualArgs = - GrClosureSignatureUtil.mapParametersToArguments(signature, argList, callExpression, callExpression.getClosureArguments(), true, true); + final GrClosureSignatureUtil.ArgInfo[] actualArgs = GrClosureSignatureUtil + .mapParametersToArguments(signature, callExpression.getNamedArguments(), callExpression.getExpressionArguments(), + callExpression.getClosureArguments(), callExpression, true, true); final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(data.getProject()); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy index 7fc3be78c15b..8c50592d29a6 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy @@ -1142,16 +1142,13 @@ Util.foo()''' public void testPropertyChain() { doBasicTest() } public void testMethodPointer() { - myFixture.configureByText('_a.groovy', '''\ + doBasicTest('''\ class Base { def prefixMethod(){} def prefixField } -new Base().&prefix''') - myFixture.completeBasic() - assertNull(myFixture.lookupElements) - myFixture.checkResult('''\ +new Base().&prefix''', '''\ class Base { def prefixMethod(){} def prefixField @@ -1160,23 +1157,27 @@ class Base { new Base().&prefixMethod''') } - public void testFieldPointer() { - myFixture.configureByText('_a.groovy', '''\ -class Base { - def prefixMethod(){} - def prefixField -} - -new Base().@prefix''') + private void doBasicTest(String before, String after) { + myFixture.configureByText('_a.groovy', before) myFixture.completeBasic() assertNull(myFixture.lookupElements) - myFixture.checkResult('''\ + myFixture.checkResult(after) + } + + public void testFieldPointer() { + doBasicTest '''\ class Base { def prefixMethod(){} def prefixField } -new Base().@prefixField''') +new Base().@prefix''', '''\ +class Base { + def prefixMethod(){} + def prefixField +} + +new Base().@prefixField''' } public void testPrivateFieldOnSecondInvocation() { @@ -1196,24 +1197,111 @@ new Base().fiex''') } public void testReturnInVoidMethod() { - myFixture.configureByText('''\ + doBasicTest('''\ void foo() { retur } ''', '''\ void foo() { return -}''') +} +''') } public void testReturnInNotVoidMethod() { - myFixture.configureByText('''\ -void foo() { + doBasicTest('''\ +String foo() { retur } ''', '''\ -void foo() { +String foo() { return -}''') +} +''') } + + void testInferArgumentTypeFromMethod1() { + doBasicTest('''\ +def bar(String s) {} + +def foo(Integer a) { + bar(a) + a.subSequen() +} +''', '''\ +def bar(String s) {} + +def foo(Integer a) { + bar(a) + a.subSequence() +} +''') + } + + void testInferArgumentTypeFromMethod2() { + doBasicTest('''\ +def bar(String s) {} + +def foo(Integer a) { + while(true) { + bar(a) + a.subSequen() + } +} +''', '''\ +def bar(String s) {} + +def foo(Integer a) { + while(true) { + bar(a) + a.subSequence() + } +} +''') + } + + void testInferArgumentTypeFromMethod3() { + doBasicTest('''\ +def bar(String s) {} + +def foo(Integer a) { + bar(a) + print a + a.subSequen() +} +''', '''\ +def bar(String s) {} + +def foo(Integer a) { + bar(a) + print a + a.subSequence() +} +''') + } + + void testInferArgumentTypeFromMethod4() { + doBasicTest('''\ +def bar(String s) {} + +def foo(Integer a) { + while(true) { + bar(a) + print a + a.subSequen() + } +} +''', '''\ +def bar(String s) {} + +def foo(Integer a) { + while(true) { + bar(a) + print a + a.subSequence() + } +} +''') + } + } \ No newline at end of file diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy index 5ca76c8eab4f..f8cd46a4ffbb 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy @@ -939,5 +939,57 @@ class A { assertEquals 'A', resolved.containingClass.name } + public void testInferArgumentTypeFromMethod1() { + def ref = configureByText('''\ +def bar(String s) {} +def foo(Integer a) { + bar(a) + + a.substring(2) +} +''') + assertNotNull(ref.resolve()) + } + + public void testInferArgumentTypeFromMethod2() { + def ref = configureByText('''\ +def bar(String s) {} + +def foo(Integer a) { + while(true) { + bar(a) + a.substring(2) + } +} +''') + assertNotNull(ref.resolve()) + } + + public void testInferArgumentTypeFromMethod3() { + def ref = configureByText('''\ +def bar(String s) {} + +def foo(Integer a) { + bar(a) + + a.intValue() +} +''') + assertNotNull(ref.resolve()) + } + + public void testInferArgumentTypeFromMethod4() { + def ref = configureByText('''\ +def bar(String s) {} + +def foo(Integer a) { + while(true) { + bar(a) + a.intValue() + } +} +''') + assertNotNull(ref.resolve()) + } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.groovy index 73085a9825e0..d4317e372681 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.groovy @@ -344,9 +344,77 @@ def found = arr.findAll({it==1}) print found''', 'java.util.Set') } + void testInferArgumentTypeFromMethod1() { + doTest('''\ +def bar(String s) {} + +def foo(Integer a) { + while(true) { + bar(a) + a.substring(2) + } +} +''', '[java.lang.String,java.lang.Integer]') + } + + void testInferArgumentTypeFromMethod2() { + doTest('''\ +def bar(String s) {} + +def foo(Integer a) { + bar(a) + a.substring(2) +} +''', '[java.lang.String,java.lang.Integer]') + } + + void testInferArgumentTypeFromMethod3() { + doTest('''\ +def bar(String s) {} + +def foo(Integer a) { + bar(a) + print a + a.substring(2) +} +''', '[java.lang.String,java.lang.Integer]') + } + + void testInferArgumentTypeFromMethod4() { + doTest('''\ +def bar(String s) {} + +def foo(Integer a) { + while(true) { + bar(a) + print a + a.substring(2) + } +} +''', '[java.lang.String,java.lang.Integer]') + } + + private void doTest(String text, String type) { def file = myFixture.configureByText('_.groovy', text) def ref = file.findReferenceAt(myFixture.editor.caretModel.offset) as GrReferenceExpression - assertEquals(type, ref.type.canonicalText) + def actual = ref.type + if (actual instanceof PsiIntersectionType) { + assertEquals(type, genIntersectionTypeText(actual)) + } + else { + assertEquals(type, actual.canonicalText) + } + } + + private static String genIntersectionTypeText(PsiIntersectionType t) { + StringBuilder b = new StringBuilder('[') + for (PsiType c : t.conjuncts) { + b.append(c.canonicalText).append(',') + } + if (t.conjuncts) { + b.replace(b.length() - 1, b.length(), ']') + } + return b.toString() } } diff --git a/plugins/groovy/testdata/highlighting/UnknownVarInArgList.groovy b/plugins/groovy/testdata/highlighting/UnknownVarInArgList.groovy index 6ca415d37913..4ed8ca33a0dc 100644 --- a/plugins/groovy/testdata/highlighting/UnknownVarInArgList.groovy +++ b/plugins/groovy/testdata/highlighting/UnknownVarInArgList.groovy @@ -9,4 +9,5 @@ foo(a) \ No newline at end of file +def x = unknown2 +abc(x) \ No newline at end of file From 801eb6055d2dec55d29947f0b36efa66efc43936 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Mon, 2 Apr 2012 16:23:41 +0400 Subject: [PATCH 10/32] IDEA-51916 Groovy variable type inference should respect the method arguments where the variable is passed --- .../psi/controlFlow/AssertionInstruction.java | 50 +++++++- .../psi/controlFlow/MixinTypeInstruction.java | 33 ++++++ .../controlFlow/impl/ArgumentInstruction.java | 108 ++++++++++++++++++ .../controlFlow/impl/ControlFlowBuilder.java | 4 + .../lang/psi/impl/TypeInferenceHelper.java | 56 ++++++--- .../groovy/controlFlow/anonymous.test | 5 +- .../groovy/controlFlow/assignment.test | 9 +- .../testdata/groovy/controlFlow/closure.test | 5 +- .../testdata/groovy/controlFlow/foreach1.test | 7 +- .../testdata/groovy/controlFlow/grvy1497.test | 5 +- .../testdata/groovy/controlFlow/switch1.test | 7 +- .../testdata/groovy/controlFlow/throw1.test | 5 +- .../testdata/groovy/controlFlow/try1.test | 7 +- .../testdata/groovy/controlFlow/try5.test | 7 +- .../testdata/groovy/controlFlow/try6.test | 15 +-- 15 files changed, 272 insertions(+), 51 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/MixinTypeInstruction.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ArgumentInstruction.java diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/AssertionInstruction.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/AssertionInstruction.java index ec7029696865..8d137a817f54 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/AssertionInstruction.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/AssertionInstruction.java @@ -15,13 +15,20 @@ */ package org.jetbrains.plugins.groovy.lang.psi.controlFlow; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiType; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrInstanceOfExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.InstructionImpl; /** * @author peter */ -public class AssertionInstruction extends InstructionImpl { +public class AssertionInstruction extends InstructionImpl implements MixinTypeInstruction { private final boolean myNegate; public AssertionInstruction(int num, GrExpression assertion, boolean negate) { @@ -37,4 +44,45 @@ public class AssertionInstruction extends InstructionImpl { return "assertion: " + (myNegate ? "! " : "") + getElement().getText(); } + @Nullable + private GrInstanceOfExpression getApplicableInstanceofOrNull() { + final PsiElement element = getElement(); + if (element instanceof GrInstanceOfExpression && !isNegate()) { + GrExpression operand = ((GrInstanceOfExpression)element).getOperand(); + final GrTypeElement typeElement = ((GrInstanceOfExpression)element).getTypeElement(); + if (operand instanceof GrReferenceExpression && ((GrReferenceExpression)operand).getQualifier() == null && typeElement != null) { + return (GrInstanceOfExpression)element; + } + } + return null; + } + + @Nullable + public PsiType inferMixinType() { + GrInstanceOfExpression instanceOf = getApplicableInstanceofOrNull(); + if (instanceOf == null) return null; + + return instanceOf.getTypeElement().getType(); + } + + @Override + public ReadWriteVariableInstruction getInstructionToMixin(Instruction[] flow) { + GrInstanceOfExpression instanceOf = getApplicableInstanceofOrNull(); + if (instanceOf == null) return null; + + Instruction instruction = ControlFlowUtils.findInstruction(instanceOf.getOperand(), flow); + if (instruction instanceof ReadWriteVariableInstruction) { + return (ReadWriteVariableInstruction)instruction; + } + return null; + } + + @Nullable + @Override + public String getVariableName() { + GrInstanceOfExpression instanceOf = getApplicableInstanceofOrNull(); + if (instanceOf == null) return null; + + return instanceOf.getOperand().getText(); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/MixinTypeInstruction.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/MixinTypeInstruction.java new file mode 100644 index 000000000000..8a8ce7e0e715 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/MixinTypeInstruction.java @@ -0,0 +1,33 @@ +/* + * 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.lang.psi.controlFlow; + +import com.intellij.psi.PsiType; +import org.jetbrains.annotations.Nullable; + +/** + * @author Max Medvedev + */ +public interface MixinTypeInstruction extends Instruction { + @Nullable + ReadWriteVariableInstruction getInstructionToMixin(Instruction[] flow); + + @Nullable + PsiType inferMixinType(); + + @Nullable + String getVariableName(); +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ArgumentInstruction.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ArgumentInstruction.java new file mode 100644 index 000000000000..3471561d016f --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ArgumentInstruction.java @@ -0,0 +1,108 @@ +/* + * 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.lang.psi.controlFlow.impl; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiType; +import com.intellij.util.ArrayUtil; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; +import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; +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.types.GrClosureParameter; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; +import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction; +import org.jetbrains.plugins.groovy.lang.psi.controlFlow.MixinTypeInstruction; +import org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; +import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; + +import static org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil.createSignature; + +/** + * @author Max Medvedev + */ +public class ArgumentInstruction extends InstructionImpl implements MixinTypeInstruction { + private static final Logger LOG = Logger.getInstance(ArgumentInstruction.class); + + public ArgumentInstruction(@Nullable GrReferenceExpression ref, int num) { + super(ref, num); + } + + @Nullable + public PsiType inferMixinType() { + PsiElement element = getElement(); + LOG.assertTrue(element instanceof GrReferenceExpression); + + PsiElement parent = element.getParent().getParent(); + LOG.assertTrue(parent instanceof GrCall, "elemText: " + element.getText() + + "\n elemParent = " + (element.getParent() == null ? "null" : element.getParent().getClass()) + + "\n elemPParent" + (parent == null ? "null" : parent.getClass())); + + GrCall call = (GrCall)parent; + + int index = ArrayUtil.indexOf(call.getExpressionArguments(), element); + if (call.getNamedArguments().length > 0) index++; + + GroovyResolveResult[] variants = call.getCallVariants((GrReferenceExpression)element); + + PsiType result = null; + for (GroovyResolveResult variant : variants) { + GrClosureSignature signature = createSignature(variant); + if (signature == null) continue; + + if (GrClosureSignatureUtil.mapParametersToArguments(signature, call) != null && !haveNullParameters(call)) { + return null; + } + GrClosureParameter[] parameters = signature.getParameters(); + if (index >= parameters.length) continue; + + result = TypesUtil.getLeastUpperBoundNullable(result, parameters[index].getType(), element.getManager()); + } + return result; + } + + private static boolean haveNullParameters(GrCall call) { + for (GrExpression argument : call.getExpressionArguments()) { + if (argument.getType() == null) return true; + } + return false; + } + + @Override + public ReadWriteVariableInstruction getInstructionToMixin(Instruction[] flow) { + Instruction instruction = ControlFlowUtils.findInstruction(getElement(), flow); + if (instruction instanceof ReadWriteVariableInstruction) { + return (ReadWriteVariableInstruction)instruction; + } + else { + return null; + } + } + + public String getVariableName() { + return ((GrReferenceExpression)getElement()).getReferenceName(); + } + + @Override + protected String getElementPresentation() { + return "ARGUMENT " + super.getElementPresentation(); + } +} + 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 6cc10132a17c..cfe842b2e42c 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 @@ -29,6 +29,7 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrCondition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.*; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; @@ -436,6 +437,9 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { else { boolean isWrite = !myAssertionsOnly && PsiUtil.isLValue(refExpr); addNodeAndCheckPending(new ReadWriteVariableInstruction(name, refExpr, myInstructionNumber++, isWrite ? WRITE : READ)); + if (refExpr.getParent() instanceof GrArgumentList) { + addNodeAndCheckPending(new ArgumentInstruction(refExpr, myInstructionNumber++)); + } } } else if (!(refExpr.getParent() instanceof GrCall)) { 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 ddcbd868464c..610ddc746113 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 @@ -21,6 +21,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.RecursionManager; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiIntersectionType; import com.intellij.psi.PsiType; import com.intellij.psi.util.*; import gnu.trove.TIntHashSet; @@ -36,7 +37,9 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.AssertionInstruction; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction; +import org.jetbrains.plugins.groovy.lang.psi.controlFlow.MixinTypeInstruction; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction; +import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ArgumentInstruction; 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; @@ -66,7 +69,7 @@ public class TypeInferenceHelper { final Instruction[] flow = scope.getControlFlow(); ReadWriteVariableInstruction instruction = findInstruction(refExpr, flow); if (instruction == null) return null; - + if (instruction.isWrite()) { return getInitializerType(refExpr); } @@ -76,7 +79,7 @@ public class TypeInferenceHelper { }); } - + @Nullable public static PsiType getInferredType(@NotNull PsiElement place, String variableName) { final GrControlFlowOwner scope = ControlFlowUtils.findControlFlowOwner(place); @@ -134,17 +137,18 @@ public class TypeInferenceHelper { private static PsiType getInferredType(String varName, Instruction instruction, Instruction[] flow, GrControlFlowOwner scope) { final Pair>> pair = getDefUseMaps(scope); - final int varIndex = pair.first.getVarIndex(varName); - List> second = pair.second; - if (second == null) return null; + List> dfaResult = pair.second; + if (dfaResult == null) return null; - final TIntObjectHashMap allDefs = second.get(instruction.num()); + final int varIndex = pair.first.getVarIndex(varName); + + final TIntObjectHashMap allDefs = dfaResult.get(instruction.num()); final TIntHashSet varDefs = allDefs.get(varIndex); if (varDefs == null) return null; PsiType result = null; for (int defIndex : varDefs.toArray()) { - PsiType defType = getDefinitionType(flow[defIndex]); + PsiType defType = getDefinitionType(flow[defIndex], flow, scope); if (defType != null) { defType = TypesUtil.boxPrimitiveType(defType, scope.getManager(), scope.getResolveScope()); result = result == null ? defType : TypesUtil.getLeastUpperBound(result, defType, scope.getManager()); @@ -174,7 +178,12 @@ public class TypeInferenceHelper { } } } - } else { + } + else if (instruction instanceof ArgumentInstruction) { + final int varIndex = getVarIndex(((ArgumentInstruction)instruction).getVariableName()); + registerDef(m, instruction, varIndex); + } + else { super.fun(m, instruction); } } @@ -188,26 +197,35 @@ public class TypeInferenceHelper { } @Nullable - private static PsiType getDefinitionType(Instruction instruction) { + private static PsiType getDefinitionType(Instruction instruction, Instruction[] flow, GrControlFlowOwner scope) { if (instruction instanceof ReadWriteVariableInstruction && ((ReadWriteVariableInstruction) instruction).isWrite()) { final PsiElement element = instruction.getElement(); if (element != null) { return getInitializerType(element); } } - if (instruction instanceof AssertionInstruction) { - final AssertionInstruction assertionInstruction = (AssertionInstruction)instruction; - final PsiElement element = assertionInstruction.getElement(); - if (element instanceof GrInstanceOfExpression && !assertionInstruction.isNegate()) { - final GrTypeElement typeElement = ((GrInstanceOfExpression)element).getTypeElement(); - if (typeElement != null) { - return typeElement.getType(); - } - } + if (instruction instanceof MixinTypeInstruction) { + return mixinType((MixinTypeInstruction)instruction, flow, scope); } return null; } + @Nullable + private static PsiType mixinType(final MixinTypeInstruction instruction, final Instruction[] flow, final GrControlFlowOwner scope) { + return RecursionManager.doPreventingRecursion(instruction, false, new NullableComputable() { + @Override + @Nullable + public PsiType compute() { + final PsiType original = getInferredType(instruction.getVariableName(), instruction.getInstructionToMixin(flow), flow, scope); + final PsiType mixin = instruction.inferMixinType(); + if (mixin == null) return original; + if (original == null) return mixin; + if (TypesUtil.isAssignableByMethodCallConversion(mixin, original, scope)) return original; + return PsiIntersectionType.createIntersection(mixin, original); + } + }); + } + @Nullable private static ReadWriteVariableInstruction findInstruction(final GrReferenceExpression refExpr, final Instruction[] flow) { @@ -218,7 +236,7 @@ public class TypeInferenceHelper { } return null; } - + @Nullable public static PsiType getInitializerType(final PsiElement element) { if (element instanceof GrReferenceExpression && ((GrReferenceExpression) element).getQualifierExpression() == null) { diff --git a/plugins/groovy/testdata/groovy/controlFlow/anonymous.test b/plugins/groovy/testdata/groovy/controlFlow/anonymous.test index 79b93ac0c3fd..560fe20e7e53 100644 --- a/plugins/groovy/testdata/groovy/controlFlow/anonymous.test +++ b/plugins/groovy/testdata/groovy/controlFlow/anonymous.test @@ -13,5 +13,6 @@ print 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 +6(7) ARGUMENT element: Reference expression +7(8) element: Call expression MAYBE_RETURN +8() element: null \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/controlFlow/assignment.test b/plugins/groovy/testdata/groovy/controlFlow/assignment.test index 9a7e724a0e36..7915928aadfa 100644 --- a/plugins/groovy/testdata/groovy/controlFlow/assignment.test +++ b/plugins/groovy/testdata/groovy/controlFlow/assignment.test @@ -6,7 +6,8 @@ def t = k 1(2) WRITE k 2(3) READ sss 3(4) READ k -4(5) WRITE k -5(6) READ k -6(7) WRITE t -7() element: null \ No newline at end of file +4(5) ARGUMENT element: Reference expression +5(6) WRITE k +6(7) READ k +7(8) WRITE t +8() 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 index ed94fc177ee3..87458711a133 100644 --- a/plugins/groovy/testdata/groovy/controlFlow/closure.test +++ b/plugins/groovy/testdata/groovy/controlFlow/closure.test @@ -11,5 +11,6 @@ print 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 +6(7) ARGUMENT element: Reference expression +7(8) element: Call expression MAYBE_RETURN +8() element: null \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/controlFlow/foreach1.test b/plugins/groovy/testdata/groovy/controlFlow/foreach1.test index 8b7fb6467242..1890499df8cd 100644 --- a/plugins/groovy/testdata/groovy/controlFlow/foreach1.test +++ b/plugins/groovy/testdata/groovy/controlFlow/foreach1.test @@ -4,8 +4,9 @@ for (e in [1,2,3,4]) { ----- 0(1) element: null 1(2) WRITE e -2(3,6) element: For statement +2(3,7) element: For statement 3(4) element: Block statement 4(5) READ print -5(2) READ e -6() element: null \ No newline at end of file +5(6) READ e +6(2) ARGUMENT element: Reference expression +7() element: null \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/controlFlow/grvy1497.test b/plugins/groovy/testdata/groovy/controlFlow/grvy1497.test index 7accd1c00a27..acc55ec03c94 100644 --- a/plugins/groovy/testdata/groovy/controlFlow/grvy1497.test +++ b/plugins/groovy/testdata/groovy/controlFlow/grvy1497.test @@ -13,5 +13,6 @@ println blah 7(8) WRITE blah 8(9) READ println 9(10) READ blah -10(11) element: Call expression MAYBE_RETURN -11() element: null \ No newline at end of file +10(11) ARGUMENT element: Reference expression +11(12) element: Call expression MAYBE_RETURN +12() element: null \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/controlFlow/switch1.test b/plugins/groovy/testdata/groovy/controlFlow/switch1.test index f3a4e9279fd2..9eafcf8cd498 100644 --- a/plugins/groovy/testdata/groovy/controlFlow/switch1.test +++ b/plugins/groovy/testdata/groovy/controlFlow/switch1.test @@ -8,9 +8,10 @@ switch(i) { ----- 0(1) element: null 1(2) READ i -2(3,5,7) element: Switch statement +2(3,5,8) element: Switch statement 3(4) READ i -4(7) WRITE j +4(8) WRITE j 5(6) READ print 6(7) READ i -7() element: null \ No newline at end of file +7(8) ARGUMENT element: Reference expression +8() element: null \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/controlFlow/throw1.test b/plugins/groovy/testdata/groovy/controlFlow/throw1.test index a5960b313589..0878aa114719 100644 --- a/plugins/groovy/testdata/groovy/controlFlow/throw1.test +++ b/plugins/groovy/testdata/groovy/controlFlow/throw1.test @@ -12,5 +12,6 @@ try { 5(6) WRITE e 6(7) READ print 7(8) READ e -8(9) element: Call expression MAYBE_RETURN -9() element: null \ No newline at end of file +8(9) ARGUMENT element: Reference expression +9(10) element: Call expression MAYBE_RETURN +10() element: null \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/controlFlow/try1.test b/plugins/groovy/testdata/groovy/controlFlow/try1.test index 437f718912e7..6a516dd61fc9 100644 --- a/plugins/groovy/testdata/groovy/controlFlow/try1.test +++ b/plugins/groovy/testdata/groovy/controlFlow/try1.test @@ -13,12 +13,13 @@ print e 5(9) element: IF statement 6(11) element: Finally clause 7(6,8) CALL 6 -8(16) AFTER CALL 7 +8(17) AFTER CALL 7 9(6,10) CALL 6 10(13) AFTER CALL 9 11(12) READ e 12(8,10) RETURN 13(14) READ print 14(15) READ e -15(16) element: Call expression MAYBE_RETURN -16() element: null \ No newline at end of file +15(16) ARGUMENT element: Reference expression +16(17) element: Call expression MAYBE_RETURN +17() element: null \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/controlFlow/try5.test b/plugins/groovy/testdata/groovy/controlFlow/try5.test index 8131184f4e5b..111dd0292008 100644 --- a/plugins/groovy/testdata/groovy/controlFlow/try5.test +++ b/plugins/groovy/testdata/groovy/controlFlow/try5.test @@ -14,7 +14,7 @@ fScript.previewTask(taskName) 1(2,5) element: IF statement 2(3) READ ddd 3(4) READ fXRec -4(15) element: RETURN statement +4(16) element: RETURN statement 5(6) element: IF statement 6(7) WRITE fScript 7(9) element: Open block @@ -24,5 +24,6 @@ fScript.previewTask(taskName) 11(10) RETURN 12(13) READ fScript 13(14) READ taskName -14(15) element: Method call MAYBE_RETURN -15() element: null \ No newline at end of file +14(15) ARGUMENT element: Reference expression +15(16) element: Method call MAYBE_RETURN +16() element: null \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/controlFlow/try6.test b/plugins/groovy/testdata/groovy/controlFlow/try6.test index c778335dc01c..d984d59e5c5d 100644 --- a/plugins/groovy/testdata/groovy/controlFlow/try6.test +++ b/plugins/groovy/testdata/groovy/controlFlow/try6.test @@ -9,15 +9,16 @@ if (url == null) { return url ----- 0(1) element: null -1(2,9) element: IF statement +1(2,10) element: IF statement 2(3) READ url 3(4) element: Open block -4(10) WRITE url +4(11) WRITE url 5(6) element: Catch clause 6(7) WRITE e 7(8) READ e -8(12) THROW. element: THROW statement -9(10) element: IF statement -10(11) READ url -11(12) element: RETURN statement -12() element: null \ No newline at end of file +8(9) ARGUMENT element: Reference expression +9(13) THROW. element: THROW statement +10(11) element: IF statement +11(12) READ url +12(13) element: RETURN statement +13() element: null \ No newline at end of file From db35848c726cbdd6bec4a6d122ac4f6271cfcb14 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 2 Apr 2012 17:06:37 +0400 Subject: [PATCH 11/32] Fetch current remote (not just current branch upstream) for Update Project and Push. In the case if current behavior changes again, leave fetching current branch functionality. Move common code to getFetchParams(). --- .../src/git4idea/update/GitFetcher.java | 87 ++++++++++++++++--- 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/plugins/git4idea/src/git4idea/update/GitFetcher.java b/plugins/git4idea/src/git4idea/update/GitFetcher.java index 39da8d8e5a42..191fe6496f6b 100644 --- a/plugins/git4idea/src/git4idea/update/GitFetcher.java +++ b/plugins/git4idea/src/git4idea/update/GitFetcher.java @@ -91,26 +91,60 @@ public class GitFetcher { fetchResult = fetchAll(root, repository, fetchResult); } else { - return fetchCurrentBranch(root, repository); + return fetchCurrentRemote(repository); } repository.update(GitRepository.TrackedTopic.BRANCHES); return fetchResult; } + private GitFetchResult fetchCurrentRemote(@NotNull GitRepository repository) { + FetchParams fetchParams = getFetchParams(repository); + if (fetchParams.isError()) { + return fetchParams.getError(); + } + + GitRemote remote = fetchParams.getRemote(); + String url = fetchParams.getUrl(); + + if (GitHttpAdapter.shouldUseJGit(url)) { + return GitHttpAdapter.fetch(repository, remote, url, null); + } + return fetchNatively(repository.getRoot(), remote, null); + } + + // leaving this unused method, because the wanted behavior can change again + @SuppressWarnings("UnusedDeclaration") @NotNull - private GitFetchResult fetchCurrentBranch(@NotNull VirtualFile root, @NotNull GitRepository repository) { + private GitFetchResult fetchCurrentBranch(@NotNull GitRepository repository) { + FetchParams fetchParams = getFetchParams(repository); + if (fetchParams.isError()) { + return fetchParams.getError(); + } + + GitRemote remote = fetchParams.getRemote(); + String remoteBranch = fetchParams.getRemoteBranch(); + String url = fetchParams.getUrl(); + if (GitHttpAdapter.shouldUseJGit(url)) { + return GitHttpAdapter.fetch(repository, remote, url, remoteBranch); + } + return fetchNatively(repository.getRoot(), remote, remoteBranch); + } + + @NotNull + private static FetchParams getFetchParams(@NotNull GitRepository repository) { GitBranch currentBranch = repository.getCurrentBranch(); if (currentBranch == null) { + // fetching current branch is called from Update Project and Push, where branch tracking is pre-checked String message = "Current branch can't be null here. \nRepository: " + repository; LOG.error(message); - return GitFetchResult.error(new Exception(message)); + return new FetchParams(GitFetchResult.error(new Exception(message))); } GitBranchTrackInfo trackInfo = GitBranchUtil.getTrackInfoForBranch(repository, currentBranch); if (trackInfo == null) { String message = "Tracked info is null for branch " + currentBranch + "\n Repository: " + repository; LOG.error(message); - return GitFetchResult.error(new Exception(message)); + return new FetchParams(GitFetchResult.error(new Exception(message))); } GitRemote remote = trackInfo.getRemote(); @@ -118,14 +152,10 @@ public class GitFetcher { if (url == null) { String message = "URL is null for remote " + remote.getName(); LOG.error(message); - return GitFetchResult.error(new Exception(message)); + return new FetchParams(GitFetchResult.error(new Exception(message))); } - String remoteBranch = trackInfo.getRemoteBranch(); - if (GitHttpAdapter.shouldUseJGit(url)) { - return GitHttpAdapter.fetch(repository, remote, url, remoteBranch); - } - return fetchNatively(root, remote, remoteBranch); + return new FetchParams(remote, trackInfo.getRemoteBranch(), url); } @NotNull @@ -317,4 +347,41 @@ public class GitFetcher { return myPrunedRefs; } } + + private static class FetchParams { + private GitRemote myRemote; + private String myRemoteBranch; + private GitFetchResult myError; + private String myUrl; + + FetchParams(GitFetchResult error) { + myError = error; + } + + FetchParams(GitRemote remote, String remoteBranch, String url) { + myRemote = remote; + myRemoteBranch = remoteBranch; + myUrl = url; + } + + boolean isError() { + return myError != null; + } + + public GitFetchResult getError() { + return myError; + } + + public GitRemote getRemote() { + return myRemote; + } + + public String getRemoteBranch() { + return myRemoteBranch; + } + + public String getUrl() { + return myUrl; + } + } } From b541d5930e6f7625b6f99f83bce22237b606f741 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Mon, 2 Apr 2012 15:00:58 +0200 Subject: [PATCH 12/32] [r=peter] clear output associations on moved file (IDEA-83859 IDEA) --- .../compiler/impl/TranslatingCompilerFilesMonitor.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java b/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java index 11e70830a41d..90c825db1148 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java @@ -1552,7 +1552,7 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent { markDirtyIfSource(event.getFile(), true); } - private void markDirtyIfSource(final VirtualFile file, boolean fromMove) { + private void markDirtyIfSource(final VirtualFile file, final boolean fromMove) { final Set pathsToMark = new HashSet(); processRecursively(file, false, new FileProcessor() { public void execute(final VirtualFile file) { @@ -1568,6 +1568,12 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent { } else { addSourceForRecompilation(projectId, file, srcInfo); + // when the file is moved to a new location, we should 'forget' previous associations + if (fromMove) { + if (srcInfo.clearPaths(projectId)) { + saveSourceInfo(file, srcInfo); + } + } } } } From 0744a2e5cc0abee4afd80e2b71006d638a4c8716 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 2 Apr 2012 16:25:13 +0400 Subject: [PATCH 13/32] check if keystore file exists --- plugins/android/resources/messages/AndroidBundle.properties | 3 ++- .../jetbrains/android/exportSignedPackage/KeystoreStep.java | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/android/resources/messages/AndroidBundle.properties b/plugins/android/resources/messages/AndroidBundle.properties index 93215293da5a..1538759af6aa 100644 --- a/plugins/android/resources/messages/AndroidBundle.properties +++ b/plugins/android/resources/messages/AndroidBundle.properties @@ -402,4 +402,5 @@ android.launch.ddms.already.launched.error=DDMS is already launched android.disable.adb.service.title=Disable ADB service android.launch.hierarchy.viewer.action=Hierarchy Viewer android.launch.draw.9.patch.action=Draw 9 Patch -android.facet.settings.include.system.proguard=Include system proguard file \ No newline at end of file +android.facet.settings.include.system.proguard=Include system proguard file +file.already.exists.error=File {0} already exists \ No newline at end of file diff --git a/plugins/android/src/org/jetbrains/android/exportSignedPackage/KeystoreStep.java b/plugins/android/src/org/jetbrains/android/exportSignedPackage/KeystoreStep.java index e9350bd5bffa..7e5f85855776 100644 --- a/plugins/android/src/org/jetbrains/android/exportSignedPackage/KeystoreStep.java +++ b/plugins/android/src/org/jetbrains/android/exportSignedPackage/KeystoreStep.java @@ -129,6 +129,12 @@ class KeystoreStep extends ExportSignedPackageWizardStep { private void checkNewKeystoreOptions(File keystoreFile) throws CommitStepException { checkNewPassword(myKeystorePasswordField, myConfirmKeystorePasswordField); + + if (keystoreFile.exists()) { + throw new CommitStepException(AndroidBundle.message( + "file.already.exists.error", keystoreFile.getPath())); + } + File parentFile = keystoreFile.getParentFile(); if (parentFile == null || !parentFile.isDirectory()) { String parentDir = keystoreFile.getParent(); From 3d225264afce89653a85d2ab2c9ad70fc828179e Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 2 Apr 2012 17:17:35 +0400 Subject: [PATCH 14/32] remove "Enable/Disable ADB" action from logcat view --- .../jetbrains/android/logcat/AndroidLogcatToolWindowView.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowView.java b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowView.java index 7ca98102182b..233e06c51cf7 100644 --- a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowView.java +++ b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatToolWindowView.java @@ -37,7 +37,6 @@ import com.intellij.openapi.util.Pair; import com.intellij.ui.CollectionListModel; import com.intellij.ui.components.JBList; import com.intellij.util.IconUtil; -import org.jetbrains.android.actions.AndroidEnableAdbServiceAction; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.sdk.AndroidPlatform; import org.jetbrains.android.util.AndroidBundle; @@ -216,7 +215,6 @@ public abstract class AndroidLogcatToolWindowView implements Disposable { final DefaultActionGroup group1 = new DefaultActionGroup(); group1.addAll(myLogConsole.getToolbarActions()); - group1.add(new AndroidEnableAdbServiceAction(AndroidUtils.DDMS_ICON)); group1.add(new MyRestartAction()); final JComponent tbComp1 = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group1, false).getComponent(); From 5c263b14b8a22fdcdc5f8a3a28f1a4ef3c709365 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 2 Apr 2012 17:19:36 +0400 Subject: [PATCH 15/32] IDEA-80077 store android keystore and key per project (cherry picked from commit 9a240fc) --- .../android/exportSignedPackage/InitialKeyStep.java | 4 ++-- .../jetbrains/android/exportSignedPackage/KeystoreStep.java | 6 +++--- .../jetbrains/android/exportSignedPackage/NewKeyStep.java | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/exportSignedPackage/InitialKeyStep.java b/plugins/android/src/org/jetbrains/android/exportSignedPackage/InitialKeyStep.java index 0b342430374d..fc9e6de8540b 100644 --- a/plugins/android/src/org/jetbrains/android/exportSignedPackage/InitialKeyStep.java +++ b/plugins/android/src/org/jetbrains/android/exportSignedPackage/InitialKeyStep.java @@ -88,7 +88,7 @@ class InitialKeyStep extends ExportSignedPackageWizardStep { myNewKeyButton.setSelected(true); } myAliasCombo.setModel(new CollectionComboBoxModel(myAliasList, myAliasList.size() > 0 ? myAliasList.get(0) : null)); - String defaultAlias = PropertiesComponent.getInstance().getValue(DEFAULT_KEY_ALIAS); + String defaultAlias = PropertiesComponent.getInstance(myWizard.getProject()).getValue(DEFAULT_KEY_ALIAS); if (defaultAlias != null) { myAliasCombo.setSelectedItem(defaultAlias); } @@ -113,7 +113,7 @@ class InitialKeyStep extends ExportSignedPackageWizardStep { if (privateKey == null || certificate == null) { throw new CommitStepException(AndroidBundle.message("android.extract.package.cannot.find.key.error", alias)); } - PropertiesComponent.getInstance().setValue(DEFAULT_KEY_ALIAS, alias); + PropertiesComponent.getInstance(myWizard.getProject()).setValue(DEFAULT_KEY_ALIAS, alias); myWizard.setPrivateKey(privateKey); myWizard.setCertificate((X509Certificate)certificate); } diff --git a/plugins/android/src/org/jetbrains/android/exportSignedPackage/KeystoreStep.java b/plugins/android/src/org/jetbrains/android/exportSignedPackage/KeystoreStep.java index 7e5f85855776..be70a41ff723 100644 --- a/plugins/android/src/org/jetbrains/android/exportSignedPackage/KeystoreStep.java +++ b/plugins/android/src/org/jetbrains/android/exportSignedPackage/KeystoreStep.java @@ -57,7 +57,7 @@ class KeystoreStep extends ExportSignedPackageWizardStep { public KeystoreStep(ExportSignedPackageWizard wizard) { myWizard = wizard; myKeystoreLocationLabel.setLabelFor(myKeystoreLocationField); - final String defaultLocation = PropertiesComponent.getInstance().getValue(DEFAULT_KEYSTORE_LOCATION); + final String defaultLocation = PropertiesComponent.getInstance(wizard.getProject()).getValue(DEFAULT_KEYSTORE_LOCATION); final SaveFileListener newKeystoreLocationListener = new SaveFileListener(myContentPanel, myKeystoreLocationField, AndroidBundle.message( "android.extract.package.choose.keystore.title")) { @@ -190,7 +190,7 @@ class KeystoreStep extends ExportSignedPackageWizardStep { else { throw new CommitStepException(AndroidBundle.message("android.export.package.keystore.error.title")); } - PropertiesComponent.getInstance().setValue(DEFAULT_KEYSTORE_LOCATION, keyStoreLocation); + PropertiesComponent.getInstance(myWizard.getProject()).setValue(DEFAULT_KEYSTORE_LOCATION, keyStoreLocation); } myWizard.setKeystoreLocation(keyStoreLocation); myWizard.setKeystorePassword(myKeystorePasswordField.getPassword()); @@ -200,7 +200,7 @@ class KeystoreStep extends ExportSignedPackageWizardStep { public void actionPerformed(ActionEvent e) { String path = myKeystoreLocationField.getText().trim(); if (path == null || path.length() == 0) { - String defaultLocation = PropertiesComponent.getInstance().getValue(DEFAULT_KEYSTORE_LOCATION); + String defaultLocation = PropertiesComponent.getInstance(myWizard.getProject()).getValue(DEFAULT_KEYSTORE_LOCATION); path = defaultLocation != null ? defaultLocation : ""; } VirtualFile f = LocalFileSystem.getInstance().findFileByPath(path); diff --git a/plugins/android/src/org/jetbrains/android/exportSignedPackage/NewKeyStep.java b/plugins/android/src/org/jetbrains/android/exportSignedPackage/NewKeyStep.java index 87e82a9554a2..bb4887969ae8 100644 --- a/plugins/android/src/org/jetbrains/android/exportSignedPackage/NewKeyStep.java +++ b/plugins/android/src/org/jetbrains/android/exportSignedPackage/NewKeyStep.java @@ -201,7 +201,7 @@ public class NewKeyStep extends ExportSignedPackageWizardStep { } throw new CommitStepException(AndroidBundle.message("android.cannot.create.new.key.error")); } - PropertiesComponent.getInstance().setValue(KeystoreStep.DEFAULT_KEYSTORE_LOCATION, keystoreLocation); + PropertiesComponent.getInstance(myWizard.getProject()).setValue(KeystoreStep.DEFAULT_KEYSTORE_LOCATION, keystoreLocation); loadKeystoreAndKey(keystoreLocation, keystorePassword, keyAlias, keyPassword); } finally { @@ -227,7 +227,7 @@ public class NewKeyStep extends ExportSignedPackageWizardStep { if (privateKey == null || certificate == null) { throw new CommitStepException(AndroidBundle.message("android.extract.package.cannot.find.key.error", keyAlias)); } - PropertiesComponent.getInstance().setValue(InitialKeyStep.DEFAULT_KEY_ALIAS, keyAlias); + PropertiesComponent.getInstance(myWizard.getProject()).setValue(InitialKeyStep.DEFAULT_KEY_ALIAS, keyAlias); myWizard.setPrivateKey(privateKey); myWizard.setCertificate((X509Certificate)certificate); From 3afff1df92e58c0270be388a391850c9144951a7 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 2 Apr 2012 17:20:16 +0400 Subject: [PATCH 16/32] IDEA-81463 create run configurations silently (cherry picked from commit 34e11534c5ead07de9b64dce286a90e0d2969e70) --- .../org/jetbrains/android/facet/AndroidFrameworkDetector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFrameworkDetector.java b/plugins/android/src/org/jetbrains/android/facet/AndroidFrameworkDetector.java index 0530e4366b90..f27e9533e733 100644 --- a/plugins/android/src/org/jetbrains/android/facet/AndroidFrameworkDetector.java +++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFrameworkDetector.java @@ -68,7 +68,7 @@ public class AndroidFrameworkDetector extends FacetBasedFrameworkDetector Date: Mon, 2 Apr 2012 16:29:24 +0400 Subject: [PATCH 17/32] IDEA-76946 Using java2d xrender pipeline produced garbage in editor pane Use xrender-supported composite during editor painting if xrender pipeline is on --- .../editor/impl/EditorComponentImpl.java | 7 +++-- .../util/src/com/intellij/util/ui/UIUtil.java | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java index 477c546cb56d..d265dabbcb99 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.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. @@ -39,6 +39,9 @@ import java.awt.im.InputMethodRequests; import java.util.Map; public class EditorComponentImpl extends JComponent implements Scrollable, DataProvider, Queryable, TypingTarget { + + private static final Composite COMPOSITE_TO_USE = UIUtil.isXRenderActive() ? AlphaComposite.SrcOver : AlphaComposite.Src; + private final EditorImpl myEditor; public EditorComponentImpl(EditorImpl editor) { @@ -144,7 +147,7 @@ public class EditorComponentImpl extends JComponent implements Scrollable, DataP ((ApplicationImpl)ApplicationManager.getApplication()).editorPaintStart(); try { - ((Graphics2D)g).setComposite(AlphaComposite.Src); + ((Graphics2D)g).setComposite(COMPOSITE_TO_USE); UISettings.setupAntialiasing(g); myEditor.paint((Graphics2D)g); diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index ce17aba15305..35cd20025af1 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -72,6 +72,24 @@ import java.util.regex.Pattern; public class UIUtil { private static final String TABLE_DECORATION_KEY = "TABLE_DECORATION_KEY"; private static final Color DECORATED_ROW_BG_COLOR = new Color(242, 245, 249); + + private static final AtomicNotNullLazyValue X_RENDER_ACTIVE = new AtomicNotNullLazyValue() { + @NotNull + @Override + protected Boolean compute() { + if (!SystemInfo.isLinux) { + return false; + } + try { + final Class clazz = ClassLoader.getSystemClassLoader().loadClass("sun.awt.X11GraphicsEnvironment"); + final Method method = clazz.getMethod("isXRenderAvailable"); + return (Boolean)method.invoke(null); + } + catch (Throwable e) { + return false; + } + } + }; public static void applyStyle(@NotNull ComponentStyle componentStyle, @NotNull Component comp) { if (!(comp instanceof JComponent)) return; @@ -1228,6 +1246,14 @@ public class UIUtil { } } + /** + * @return true if XRender-based pipeline is active; + * false otherwise + */ + public static boolean isXRenderActive() { + return X_RENDER_ACTIVE.getValue(); + } + @TestOnly public static void dispatchAllInvocationEvents() { assert SwingUtilities.isEventDispatchThread() : Thread.currentThread(); From b9edf41a8076f522c243f45ba6973daf87385540 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Mon, 2 Apr 2012 17:22:14 +0400 Subject: [PATCH 18/32] IDEA-76946 Using java2d xrender pipeline produced garbage in editor pane Generalised composite setup in order to share the solution with the text drawing at the 'about' dialog as well --- .../src/com/intellij/ide/actions/AboutDialog.java | 4 ++-- .../openapi/editor/impl/EditorComponentImpl.java | 6 ++---- platform/util/src/com/intellij/util/ui/UIUtil.java | 14 +++++++++----- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java b/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java index 8a4d61ff7389..3bbefc88fca7 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.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. @@ -236,7 +236,7 @@ public class AboutDialog extends JDialog { g2.setColor(col); TextRenderer renderer = new TextRenderer(0, 145, 398, 120, g2); - g2.setComposite(AlphaComposite.Src); + UIUtil.setupComposite(g2); myFont = labelFont.deriveFont(Font.PLAIN, labelSize); myBoldFont = labelFont.deriveFont(Font.BOLD, labelSize + 1); try { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java index d265dabbcb99..aba79cd119a7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java @@ -39,9 +39,7 @@ import java.awt.im.InputMethodRequests; import java.util.Map; public class EditorComponentImpl extends JComponent implements Scrollable, DataProvider, Queryable, TypingTarget { - - private static final Composite COMPOSITE_TO_USE = UIUtil.isXRenderActive() ? AlphaComposite.SrcOver : AlphaComposite.Src; - + private final EditorImpl myEditor; public EditorComponentImpl(EditorImpl editor) { @@ -147,7 +145,7 @@ public class EditorComponentImpl extends JComponent implements Scrollable, DataP ((ApplicationImpl)ApplicationManager.getApplication()).editorPaintStart(); try { - ((Graphics2D)g).setComposite(COMPOSITE_TO_USE); + UIUtil.setupComposite((Graphics2D)g); UISettings.setupAntialiasing(g); myEditor.paint((Graphics2D)g); diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 35cd20025af1..b65181ae178d 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -1247,13 +1247,17 @@ public class UIUtil { } /** - * @return true if XRender-based pipeline is active; - * false otherwise + * Configures composite to use for drawing text with the given graphics container. + *

+ * The whole idea is that XRender-based pipeline doesn't support + * {@link AlphaComposite#SRC} and we should use {@link AlphaComposite#SRC_OVER} instead. + * + * @param g target graphics container */ - public static boolean isXRenderActive() { - return X_RENDER_ACTIVE.getValue(); + public static void setupComposite(@NotNull Graphics2D g) { + g.setComposite(X_RENDER_ACTIVE.getValue() ? AlphaComposite.SrcOver : AlphaComposite.Src); } - + @TestOnly public static void dispatchAllInvocationEvents() { assert SwingUtilities.isEventDispatchThread() : Thread.currentThread(); From f9106f36461479d1b703aee044d0b1f60fef87fd Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 2 Apr 2012 17:47:33 +0400 Subject: [PATCH 19/32] Fix already disposed in GitRepositoryReader --- plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java index 6917cec47765..0b7a08ae321b 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java @@ -15,6 +15,7 @@ */ package git4idea.repo; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -489,7 +490,7 @@ class GitRepositoryReader { @Nullable private static Charset calcEncoding(File file) { VirtualFile vf = VcsUtil.getVirtualFile(file); - return EncodingManager.getInstance().getEncoding(vf, false); + return ApplicationManager.getApplication().isDisposed() ? null : EncodingManager.getInstance().getEncoding(vf, false); } /** From 69344c357c8055678e2b9bb1cbb8a74b1650a1fb Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 2 Apr 2012 16:31:54 +0200 Subject: [PATCH 20/32] do not automatically include ignored files when adding a directory to cvs --- .../actions/AddFileOrDirectoryAction.java | 77 +++++++------------ .../cvsSupport2/actions/IgnoreFileAction.java | 34 ++++---- 2 files changed, 44 insertions(+), 67 deletions(-) diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/AddFileOrDirectoryAction.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/AddFileOrDirectoryAction.java index e55d902b6098..678ac3383951 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/AddFileOrDirectoryAction.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/AddFileOrDirectoryAction.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. @@ -28,9 +28,10 @@ import com.intellij.cvsSupport2.cvshandlers.CommandCvsHandler; import com.intellij.cvsSupport2.cvshandlers.CvsHandler; import com.intellij.cvsSupport2.cvsoperations.cvsAdd.AddedFileInfo; import com.intellij.cvsSupport2.cvsoperations.cvsAdd.ui.AbstractAddOptionsDialog; -import com.intellij.cvsSupport2.ui.Options; import com.intellij.cvsSupport2.ui.CvsTabbedWindow; +import com.intellij.cvsSupport2.ui.Options; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.actions.VcsContext; import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; @@ -47,31 +48,27 @@ public class AddFileOrDirectoryAction extends ActionOnSelectedElement { private final String myTitle; private final Options myOptions; - private final boolean myIsAutomaticallyAction; public static AddFileOrDirectoryAction createActionToAddNewFileAutomatically() { - return new AddFileOrDirectoryAction(CvsBundle.getAddingFilesOperationName(), Options.ON_FILE_ADDING, true); + return new AddFileOrDirectoryAction(CvsBundle.getAddingFilesOperationName(), Options.ON_FILE_ADDING); } public AddFileOrDirectoryAction() { - this(CvsBundle.getAddingFilesOperationName(), Options.ADD_ACTION, false); + this(CvsBundle.getAddingFilesOperationName(), Options.ADD_ACTION); getVisibility().canBePerformedOnSeveralFiles(); } - public AddFileOrDirectoryAction(String title, Options options, boolean isAutomatically) { + public AddFileOrDirectoryAction(String title, Options options) { super(false); myTitle = title; myOptions = options; - myIsAutomaticallyAction = isAutomatically; - - CvsActionVisibility visibility = getVisibility(); + final CvsActionVisibility visibility = getVisibility(); visibility.addCondition(FILES_ARENT_UNDER_CVS); } public void update(AnActionEvent e) { super.update(e); - if (!e.getPresentation().isVisible()) - return; - Project project = CvsContextWrapper.createInstance(e).getProject(); + if (!e.getPresentation().isVisible()) return; + final Project project = CvsContextWrapper.createInstance(e).getProject(); if (project == null) return; adjustName(CvsVcs2.getInstance(project).getAddOptions().getValue(), e); } @@ -81,41 +78,34 @@ public class AddFileOrDirectoryAction extends ActionOnSelectedElement { } protected CvsHandler getCvsHandler(CvsContext context) { - Project project = context.getProject(); - boolean showDialog = myOptions.isToBeShown(project) || OptionsDialog.shiftIsPressed(context.getModifiers()); - - return getCvsHandler(project, context.getSelectedFiles(), !myIsAutomaticallyAction, showDialog, myOptions); + final Project project = context.getProject(); + final boolean showDialog = myOptions.isToBeShown(project) || OptionsDialog.shiftIsPressed(context.getModifiers()); + return getCvsHandler(project, context.getSelectedFiles(), showDialog, myOptions); } public static CvsHandler getDefaultHandler(Project project, VirtualFile[] files) { - return getCvsHandler(project, files, true, true, Options.NULL); + return getCvsHandler(project, files, true, Options.NULL); } private static CvsHandler getCvsHandler(final Project project, final VirtualFile[] files, - final boolean includeAllRoots, final boolean showDialog, final Options dialogOptions) { - ArrayList filesToAdd = collectFilesToAdd(files); + final ArrayList filesToAdd = collectFilesToAdd(files); if (filesToAdd.isEmpty()) return CvsHandler.NULL; LOG.assertTrue(!filesToAdd.isEmpty()); - Collection roots = new CreateTreeOnFileList(filesToAdd, project, includeAllRoots).getRoots(); - - if (roots.size() == 0) { + final Collection roots = new CreateTreeOnFileList(filesToAdd, project).getRoots(); + if (roots.isEmpty()) { LOG.error(filesToAdd); } if (showDialog){ - AbstractAddOptionsDialog dialog = AbstractAddOptionsDialog.createDialog(project, - roots, - dialogOptions); + final AbstractAddOptionsDialog dialog = AbstractAddOptionsDialog.createDialog(project, roots, dialogOptions); dialog.show(); - if (!dialog.isOK()) return CvsHandler.NULL; } - return CommandCvsHandler.createAddFilesHandler(project, roots); } @@ -123,7 +113,7 @@ public class AddFileOrDirectoryAction extends ActionOnSelectedElement { protected void onActionPerformed(final CvsContext context, final CvsTabbedWindow tabbedWindow, final boolean successfully, final CvsHandler handler) { super.onActionPerformed(context, tabbedWindow, successfully, handler); - VirtualFile[] filesToAdd = context.getSelectedFiles(); + final VirtualFile[] filesToAdd = context.getSelectedFiles(); final VcsDirtyScopeManager dirtyScopeManager = VcsDirtyScopeManager.getInstance(context.getProject()); for(VirtualFile file: filesToAdd) { if (file.isDirectory()) { @@ -136,9 +126,9 @@ public class AddFileOrDirectoryAction extends ActionOnSelectedElement { } private static ArrayList collectFilesToAdd(final VirtualFile[] files) { - ArrayList result = new ArrayList(); + final ArrayList result = new ArrayList(); for (VirtualFile file : files) { - List parentsToAdd = new ArrayList(); + final List parentsToAdd = new ArrayList(); VirtualFile parent = file.getParent(); do { if (parent == null || CvsUtil.fileExistsInCvs(parent) || result.contains(parent)) break; @@ -150,23 +140,20 @@ public class AddFileOrDirectoryAction extends ActionOnSelectedElement { if (parent != null) { result.addAll(parentsToAdd); } - addFilesToCollection(result, file); } - Collections.sort(result, new Comparator() { public int compare(final VirtualFile o1, final VirtualFile o2) { return o1.getPath().compareTo(o2.getPath()); } }); - return result; } private static void addFilesToCollection(Collection collection, VirtualFile file) { if (DeletedCVSDirectoryStorage.isAdminDir(file)) return; collection.add(file); - VirtualFile[] children = file.getChildren(); + final VirtualFile[] children = file.getChildren(); if (children == null) return; for (VirtualFile child : children) { addFilesToCollection(collection, child); @@ -175,21 +162,18 @@ public class AddFileOrDirectoryAction extends ActionOnSelectedElement { static class CreateTreeOnFileList { private final Collection myFiles; - private final Map myResult - = new HashMap(); + private final Map myResult = new HashMap(); private final Project myProject; - public CreateTreeOnFileList(Collection files, Project project, boolean shouldIncludeAllRoots) { + public CreateTreeOnFileList(Collection files, Project project) { myFiles = files; myProject = project; fillFileToInfoMap(); setAllParents(); - if (!shouldIncludeAllRoots) { - final CvsEntriesManager entriesManager = CvsEntriesManager.getInstance(); - for (final VirtualFile file : files) { - if (entriesManager.fileIsIgnored(file)) { - myResult.get(file).setIncluded(false); - } + final CvsEntriesManager entriesManager = CvsEntriesManager.getInstance(); + for (final VirtualFile file : files) { + if (entriesManager.fileIsIgnored(file) || FileTypeManager.getInstance().isFileIgnored(file)) { + myResult.get(file).setIncluded(false); } } removeFromMapInfoWithParentAndResortAll(); @@ -202,7 +186,7 @@ public class AddFileOrDirectoryAction extends ActionOnSelectedElement { private void removeFromMapInfoWithParentAndResortAll() { for (final VirtualFile file : myFiles) { if (myResult.containsKey(file)) { - AddedFileInfo info = myResult.get(file); + final AddedFileInfo info = myResult.get(file); if (info.getParent() != null) { myResult.remove(file); } @@ -216,7 +200,7 @@ public class AddFileOrDirectoryAction extends ActionOnSelectedElement { private void setAllParents() { for (final VirtualFile file : myFiles) { if (myResult.containsKey(file.getParent()) && myResult.containsKey(file)) { - AddedFileInfo info = myResult.get(file); + final AddedFileInfo info = myResult.get(file); info.setParent(myResult.get(file.getParent())); } } @@ -227,8 +211,5 @@ public class AddFileOrDirectoryAction extends ActionOnSelectedElement { myResult.put(file, new AddedFileInfo(file, myProject, CvsConfiguration.getInstance(myProject))); } } - - } - } diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/IgnoreFileAction.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/IgnoreFileAction.java index 75b428a19981..8e4b2258378b 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/IgnoreFileAction.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/IgnoreFileAction.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. @@ -35,6 +35,7 @@ import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; import com.intellij.openapi.vcs.ui.Refreshable; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.HashMap; import java.io.File; import java.io.IOException; @@ -43,13 +44,12 @@ import java.util.*; /** * author: lesya */ - public class IgnoreFileAction extends AnAction { private static final Logger LOG = Logger.getInstance("#com.intellij.cvsSupport2.actions.IgnoreFileAction"); private final CvsActionVisibility myVisibility = new CvsActionVisibility(); - private final Map> myParentToSelectedChildren = new com.intellij.util.containers.HashMap>(); + private final Map> myParentToSelectedChildren = new HashMap>(); public IgnoreFileAction() { myVisibility.canBePerformedOnSeveralFiles(); @@ -57,17 +57,15 @@ public class IgnoreFileAction extends AnAction { myVisibility.addCondition(ActionOnSelectedElement.FILES_ARE_NOT_IGNORED); } - public void update(AnActionEvent e) { myVisibility.applyToEvent(e); } public void actionPerformed(AnActionEvent e) { - CvsContext context = CvsContextWrapper.createCachedInstance(e); - VirtualFile[] selectedFiles = context.getSelectedFiles(); - + final CvsContext context = CvsContextWrapper.createCachedInstance(e); + final VirtualFile[] selectedFiles = context.getSelectedFiles(); for (VirtualFile selectedFile : selectedFiles) { - VirtualFile parent = selectedFile.getParent(); + final VirtualFile parent = selectedFile.getParent(); if (!myParentToSelectedChildren.containsKey(parent)) myParentToSelectedChildren.put(parent, new HashSet()); myParentToSelectedChildren.get(parent).add(selectedFile); try { @@ -79,13 +77,11 @@ public class IgnoreFileAction extends AnAction { CvsBundle.message("message.error.ignore.files.title")); } } - refreshFilesAndStatuses(context); - } private static void refreshPanel(CvsContext context) { - Refreshable refreshablePanel = context.getRefreshableDialog(); + final Refreshable refreshablePanel = context.getRefreshableDialog(); if (refreshablePanel != null) { refreshablePanel.restoreState(); refreshablePanel.refresh(); @@ -93,7 +89,7 @@ public class IgnoreFileAction extends AnAction { } private void refreshFilesAndStatuses(final CvsContext context) { - Refreshable refreshablePanel = context.getRefreshableDialog(); + final Refreshable refreshablePanel = context.getRefreshableDialog(); if (refreshablePanel != null) refreshablePanel.saveState(); final int[] refreshedParents = new int[]{0}; final Collection createdCvsIgnoreFiles = new ArrayList(); @@ -109,10 +105,11 @@ public class IgnoreFileAction extends AnAction { return new Runnable() { public void run() { try { - VirtualFile cvsIgnoreFile = CvsVfsUtil.refreshAndfFindChild(parent, CvsUtil.CVS_IGNORE_FILE); + final VirtualFile cvsIgnoreFile = CvsVfsUtil.refreshAndfFindChild(parent, CvsUtil.CVS_IGNORE_FILE); if (cvsIgnoreFile == null) { - String path = parent.getPath() + "/" + CvsUtil.CVS_IGNORE_FILE; - LOG.error(String.valueOf(CvsVfsUtil.findFileByPath(path)) + " " + parent.getPath() + " " + new File(VfsUtil.virtualToIoFile(parent), CvsUtil.CVS_IGNORE_FILE).isFile()); + final String path = parent.getPath() + "/" + CvsUtil.CVS_IGNORE_FILE; + LOG.error(String.valueOf(CvsVfsUtil.findFileByPath(path)) + " " + parent.getPath() + " " + + new File(VfsUtil.virtualToIoFile(parent), CvsUtil.CVS_IGNORE_FILE).isFile()); return; } @@ -120,7 +117,7 @@ public class IgnoreFileAction extends AnAction { createdCvsIgnoreFiles.add(cvsIgnoreFile); } - Set filesToUpdateStatus = myParentToSelectedChildren.get(parent); + final Set filesToUpdateStatus = myParentToSelectedChildren.get(parent); for (final VirtualFile file : filesToUpdateStatus) { FileStatusManager.getInstance(context.getProject()).fileStatusChanged(file); VcsDirtyScopeManager.getInstance(context.getProject()).fileDirty(file); @@ -144,7 +141,7 @@ public class IgnoreFileAction extends AnAction { } private AddFileOrDirectoryAction createAddFilesAction() { - return new AddFileOrDirectoryAction(CvsBundle.message("adding.cvsignore.files.to.cvs.action.name"), Options.ON_FILE_ADDING, true) { + return new AddFileOrDirectoryAction(CvsBundle.message("adding.cvsignore.files.to.cvs.action.name"), Options.ON_FILE_ADDING) { protected void onActionPerformed(CvsContext context, CvsTabbedWindow tabbedWindow, boolean successfully, @@ -156,8 +153,7 @@ public class IgnoreFileAction extends AnAction { }; } - private static CvsContextAdapter createContext(final Collection createdCvsIgnoreFiles, - final CvsContext context) { + private static CvsContextAdapter createContext(final Collection createdCvsIgnoreFiles, final CvsContext context) { return new CvsContextAdapter() { public VirtualFile[] getSelectedFiles() { return VfsUtil.toVirtualFileArray(createdCvsIgnoreFiles); From 63ba4af884026d9627ca19041cd5cd13c7d74180 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 2 Apr 2012 15:20:36 +0200 Subject: [PATCH 21/32] goto action: do not use editor selection for initial text (IDEA-83914): allow to ignore according to a parameter --- .../src/com/intellij/ide/actions/GotoActionBase.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) 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 f7586f8ce300..28e9fb53427d 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java @@ -110,11 +110,13 @@ public abstract class GotoActionBase extends AnAction { } protected static Pair getInitialText(boolean useEditorSelection, AnActionEvent e) { - final Editor editor = e.getData(PlatformDataKeys.EDITOR); - if (editor != null) { - final String selectedText = editor.getSelectionModel().getSelectedText(); - if (selectedText != null && !selectedText.contains("\n")) { - return Pair.create(selectedText, 0); + if (useEditorSelection) { + final Editor editor = e.getData(PlatformDataKeys.EDITOR); + if (editor != null) { + final String selectedText = editor.getSelectionModel().getSelectedText(); + if (selectedText != null && !selectedText.contains("\n")) { + return Pair.create(selectedText, 0); + } } } From 6092d88b7da48c5f0a3c675563ce4bcb6a75e0a9 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 2 Apr 2012 16:08:47 +0200 Subject: [PATCH 22/32] plugins: update from check from updates should clear cached status (IDEA-83910) --- .../intellij/ide/plugins/InstalledPluginsTableModel.java | 8 ++++++-- .../openapi/updateSettings/impl/PluginDownloader.java | 1 + .../openapi/updateSettings/impl/UpdateChecker.java | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java index b961f4c80423..21d8a5bbc3af 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java @@ -93,8 +93,7 @@ public class InstalledPluginsTableModel extends PluginTableModel { final PluginId descrId = descriptor.getPluginId(); final IdeaPluginDescriptor existing = PluginManager.getPlugin(descrId); if (existing != null) { - updateExistingPluginInfo(descriptor, existing); - updatedPlugins.add(existing.getPluginId()); + updateExistingPlugin(descriptor, existing); } else { myInstalled.add(descriptor); view.add(descriptor); @@ -103,6 +102,11 @@ public class InstalledPluginsTableModel extends PluginTableModel { } } + public static void updateExistingPlugin(IdeaPluginDescriptor descriptor, IdeaPluginDescriptor existing) { + updateExistingPluginInfo(descriptor, existing); + updatedPlugins.add(existing.getPluginId()); + } + public String getPluginHostUrl(String idString) { return myPlugin2host.get(idString); } 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 5c91df5975d4..78cce1952c4f 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 @@ -127,6 +127,7 @@ public class PluginDownloader { IdeaPluginDescriptorImpl descriptor = loadDescriptionFromJar(myFile); if (descriptor != null) { + if (InstalledPluginsTableModel.wasUpdated(descriptor.getPluginId())) return false; //already updated myPluginVersion = descriptor.getVersion(); if (ideaPluginDescriptor != null && StringUtil.compareVersionNumbers(ideaPluginDescriptor.getVersion(), descriptor.getVersion()) >= 0) { LOG.info("Plugin " + myPluginId + ": current version (max) " + myPluginVersion); diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java index 74601a31c964..d3098820dceb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java @@ -547,6 +547,8 @@ public final class UpdateChecker { for (PluginDownloader downloader : downloaders) { if (getDisabledToUpdatePlugins().contains(downloader.getPluginId())) continue; try { + final IdeaPluginDescriptor descriptor = downloader.getDescriptor(); + InstalledPluginsTableModel.updateExistingPlugin(descriptor, PluginManager.getPlugin(descriptor.getPluginId())); downloader.install(); installed = true; } From ec4e0dc63bc3a0ca5d312dd993774d5a9ff98a6a Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 2 Apr 2012 16:39:13 +0200 Subject: [PATCH 23/32] fix right stripes --- .../openapi/vcs/ex/LineStatusTrackerDrawing.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java index eb5a165829b7..031d0c4c72da 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java @@ -59,7 +59,7 @@ public class LineStatusTrackerDrawing { } static TextAttributes getAttributesFor(final Range range) { - final Color stripeColor = getDiffColor(range); + final Color stripeColor = getDiffColor(range, false); final TextAttributes textAttributes = new TextAttributes(null, stripeColor, null, EffectType.BOXED, Font.PLAIN); textAttributes.setErrorStripeColor(stripeColor); return textAttributes; @@ -117,7 +117,7 @@ public class LineStatusTrackerDrawing { public static LineMarkerRenderer createRenderer(final Range range, final LineStatusTracker tracker) { return new ActiveGutterRenderer() { public void paint(final Editor editor, final Graphics g, final Rectangle r) { - paintGutterFragment(editor, g, r, getDiffColor(range)); + paintGutterFragment(editor, g, r, getDiffColor(range, true)); } public void doAction(final Editor editor, final MouseEvent e) { @@ -258,15 +258,17 @@ public class LineStatusTrackerDrawing { }); } - private static Color getDiffColor(Range range) { + private static Color getDiffColor(Range range, boolean gutter) { final EditorColorsScheme globalScheme = EditorColorsManager.getInstance().getGlobalScheme(); switch (range.getType()) { case Range.INSERTED: - return globalScheme.getColor(EditorColors.ADDED_LINES_COLOR); + return gutter ? globalScheme.getColor(EditorColors.ADDED_LINES_COLOR) + : globalScheme.getAttributes(DiffColors.DIFF_INSERTED).getErrorStripeColor(); case Range.DELETED: - return globalScheme.getAttributes(DiffColors.DIFF_DELETED).getEffectColor(); + return globalScheme.getAttributes(DiffColors.DIFF_DELETED).getErrorStripeColor(); case Range.MODIFIED: - return globalScheme.getColor(EditorColors.MODIFIED_LINES_COLOR); + return gutter ? globalScheme.getColor(EditorColors.MODIFIED_LINES_COLOR) + : globalScheme.getAttributes(DiffColors.DIFF_MODIFIED).getErrorStripeColor(); default: assert false; return null; From c4002294d088a52259d469920c73271814d22115 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 2 Apr 2012 16:39:49 +0200 Subject: [PATCH 24/32] color chooser in xml attr values --- .../src/META-INF/XmlPlugin.xml | 5 ++ .../description.html | 5 ++ .../XmlChooseColorIntentionAction.java | 87 +++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 xml/impl/resources/intentionDescriptions/XmlChooseColorIntentionAction/description.html create mode 100644 xml/impl/src/com/intellij/codeInsight/intentions/XmlChooseColorIntentionAction.java diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml index 678706f07a58..08df98a961b1 100644 --- a/platform/platform-resources/src/META-INF/XmlPlugin.xml +++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml @@ -372,6 +372,11 @@ XML com.intellij.codeInsight.daemon.impl.analysis.ConvertSchemaPrefixToDefaultIntention + + XML + com.intellij.codeInsight.intentions.XmlChooseColorIntentionAction + + diff --git a/xml/impl/resources/intentionDescriptions/XmlChooseColorIntentionAction/description.html b/xml/impl/resources/intentionDescriptions/XmlChooseColorIntentionAction/description.html new file mode 100644 index 000000000000..18345fe2ff30 --- /dev/null +++ b/xml/impl/resources/intentionDescriptions/XmlChooseColorIntentionAction/description.html @@ -0,0 +1,5 @@ + + +Allows to call Color Chooser for attributes + + \ No newline at end of file diff --git a/xml/impl/src/com/intellij/codeInsight/intentions/XmlChooseColorIntentionAction.java b/xml/impl/src/com/intellij/codeInsight/intentions/XmlChooseColorIntentionAction.java new file mode 100644 index 000000000000..65e7e7e94816 --- /dev/null +++ b/xml/impl/src/com/intellij/codeInsight/intentions/XmlChooseColorIntentionAction.java @@ -0,0 +1,87 @@ +/* + * 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.codeInsight.intentions; + +import com.intellij.codeInsight.CodeInsightBundle; +import com.intellij.codeInsight.CodeInsightUtilBase; +import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.XmlElementFactory; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlAttribute; +import com.intellij.psi.xml.XmlAttributeValue; +import com.intellij.ui.ColorChooser; +import com.intellij.ui.ColorUtil; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; + +/** + * @author Konstantin Bulenkov + */ +public class XmlChooseColorIntentionAction extends PsiElementBaseIntentionAction { + public XmlChooseColorIntentionAction() { + setText(CodeInsightBundle.message("intention.color.chooser.dialog")); + } + + public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) { + final PsiElement parent = element.getParent(); + return parent instanceof XmlAttributeValue && ColorUtil.fromHex(((XmlAttributeValue)parent).getValue(), null) != null; + } + + @NotNull + public String getFamilyName() { + return getText(); + } + + public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException { + if (!CodeInsightUtilBase.prepareFileForWrite(file)) return; + PsiElement element = file.findElementAt(editor.getCaretModel().getOffset()); + invokeForLiteral(editor.getComponent(), element); + } + + private void invokeForLiteral(JComponent editorComponent, PsiElement element) { + final XmlAttributeValue literal = PsiTreeUtil.getParentOfType(element, XmlAttributeValue.class); + if (literal == null) return; + final String text = StringUtil.unquoteString(literal.getValue()); + final String hexPrefix = text.startsWith("#") ? "#" : ""; + + Color oldColor; + try { + oldColor = Color.decode(text); + } + catch (NumberFormatException e) { + oldColor = Color.GRAY; + } + Color color = ColorChooser.chooseColor(editorComponent, getText(), oldColor, true); + if (color == null) return; + if (!Comparing.equal(color, oldColor)) { + final String newText = hexPrefix + ColorUtil.toHex(color); + final PsiManager manager = literal.getManager(); + final XmlAttribute newAttribute = XmlElementFactory.getInstance(manager.getProject()).createXmlAttribute("name", newText); + literal.replace(newAttribute.getValueElement()); + } + } +} + From 7deae44a0d9ff2b9106460980122a1748e2627a6 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 2 Apr 2012 19:49:27 +0400 Subject: [PATCH 25/32] fix ui cosmetics --- .../android/facet/AndroidFacetEditorTab.form | 22 +++++++++--------- .../android/facet/AndroidFacetEditorTab.java | 23 +++++++++++++++++++ 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.form b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.form index 3a1c1c2b7223..ec501111512b 100644 --- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.form +++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.form @@ -212,26 +212,26 @@ - + - + - + - + - + - + - + @@ -250,14 +250,14 @@ - + - + @@ -265,13 +265,13 @@ - + - + diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java index 0460f021df72..984c19c932f6 100644 --- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java +++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java @@ -233,6 +233,24 @@ public class AndroidFacetEditorTab extends FacetEditorTab { return file.isDirectory() || "apk".equals(file.getExtension()); } }); + + myGenerateIdlWhenChanged.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + final boolean enabled = myGenerateIdlWhenChanged.isSelected(); + myAidlGenPathLabel.setEnabled(enabled); + myAidlGenPathField.setEnabled(enabled); + } + }); + + myGenerateRJavaWhenChanged.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + final boolean enabled = myGenerateRJavaWhenChanged.isSelected(); + myRGenPathLabel.setEnabled(enabled); + myRGenPathField.setEnabled(enabled); + } + }); } private void updateAptPanel() { @@ -579,7 +597,12 @@ public class AndroidFacetEditorTab extends FacetEditorTab { myIncludeSystemProguardFileCheckBox.setVisible(AndroidCommonUtils.isIncludingInProguardSupported(sdkToolsRevision)); myGenerateRJavaWhenChanged.setSelected(configuration.REGENERATE_R_JAVA); + myRGenPathLabel.setEnabled(configuration.REGENERATE_R_JAVA); + myRGenPathField.setEnabled(configuration.REGENERATE_R_JAVA); + myGenerateIdlWhenChanged.setSelected(configuration.REGENERATE_JAVA_BY_AIDL); + myAidlGenPathLabel.setEnabled(configuration.REGENERATE_JAVA_BY_AIDL); + myAidlGenPathField.setEnabled(configuration.REGENERATE_JAVA_BY_AIDL); myUseCustomSourceDirectoryRadio.setSelected(configuration.USE_CUSTOM_APK_RESOURCE_FOLDER); myUseAptResDirectoryFromPathRadio.setSelected(!configuration.USE_CUSTOM_APK_RESOURCE_FOLDER); From 5d6cb953b8fdf169d1177dfa982077ab55fe9357 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 2 Apr 2012 19:50:25 +0400 Subject: [PATCH 26/32] IDEA-82976 fix compilation in maven resource processing mode --- .../android/compiler/AndroidCompileUtil.java | 33 +++++++++++++++---- .../android/facet/AndroidRootUtil.java | 8 +++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidCompileUtil.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidCompileUtil.java index 5714557c8852..0058e0200846 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidCompileUtil.java +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidCompileUtil.java @@ -40,6 +40,7 @@ import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; @@ -652,18 +653,38 @@ public class AndroidCompileUtil { final Module module = facet.getModule(); final GlobalSearchScope moduleScope = facet.getModule().getModuleScope(); - initializeGenSourceRoot(module, - AndroidRootUtil.getRenderscriptGenSourceRootPath(facet), + initializeGenSourceRoot(module, AndroidRootUtil.getRenderscriptGenSourceRootPath(facet), FileTypeIndex.getFiles(AndroidRenderscriptFileType.INSTANCE, moduleScope).size() > 0); + if (AndroidAptCompiler.isToCompileModule(module, facet.getConfiguration())) { + initializeGenSourceRoot(module, AndroidRootUtil.getAptGenSourceRootPath(facet), true); + } + else { + // we need to include generated-sources/r to compilation, because it contains R.java generated by Maven, + // which should be used in Maven-based resource processing mode + includeAaptGenSourceRootToCompilation(facet); + } - initializeGenSourceRoot(module, AndroidRootUtil.getAptGenSourceRootPath(facet), true); - - initializeGenSourceRoot(module, - AndroidRootUtil.getAidlGenSourceRootPath(facet), + initializeGenSourceRoot(module, AndroidRootUtil.getAidlGenSourceRootPath(facet), FileTypeIndex.getFiles(AndroidIdlFileType.ourFileType, moduleScope).size() > 0); } + private static void includeAaptGenSourceRootToCompilation(AndroidFacet facet) { + final Project project = facet.getModule().getProject(); + final ExcludedEntriesConfiguration configuration = + ((CompilerConfigurationImpl)CompilerConfiguration.getInstance(project)).getExcludedEntriesConfiguration(); + final ExcludeEntryDescription[] descriptions = configuration.getExcludeEntryDescriptions(); + + configuration.removeAllExcludeEntryDescriptions(); + + for (ExcludeEntryDescription description : descriptions) { + final VirtualFile vFile = description.getVirtualFile(); + if (!Comparing.equal(vFile, AndroidRootUtil.getAaptGenDir(facet))) { + configuration.addExcludeEntryDescription(description); + } + } + } + private static void initializeGenSourceRoot(@NotNull Module module, @Nullable String sourceRootPath, boolean createIfNotExist) { if (sourceRootPath == null) { return; diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidRootUtil.java b/plugins/android/src/org/jetbrains/android/facet/AndroidRootUtil.java index ea617758a1f1..10badcdde18d 100644 --- a/plugins/android/src/org/jetbrains/android/facet/AndroidRootUtil.java +++ b/plugins/android/src/org/jetbrains/android/facet/AndroidRootUtil.java @@ -159,6 +159,14 @@ public class AndroidRootUtil { : null; } + @Nullable + public static VirtualFile getAaptGenDir(@NotNull AndroidFacet facet) { + final String genPath = getAptGenSourceRootPath(facet); + return genPath != null + ? LocalFileSystem.getInstance().findFileByPath(genPath) + : null; + } + @Nullable public static VirtualFile getRenderscriptGenDir(@NotNull AndroidFacet facet) { final String path = getRenderscriptGenSourceRootPath(facet); From ac4fcb35b7082d2484545e8a9a2f23875270e9e8 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 2 Apr 2012 19:53:17 +0400 Subject: [PATCH 27/32] android: look at facet settings before running autogenerator --- .../android/compiler/AndroidAutogenerator.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidAutogenerator.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidAutogenerator.java index 3d1387a147a2..311e402bb30a 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidAutogenerator.java +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidAutogenerator.java @@ -47,7 +47,25 @@ public class AndroidAutogenerator { private AndroidAutogenerator() { } + private static boolean toRun(@NotNull AndroidAutogeneratorMode mode, @NotNull AndroidFacet facet) { + switch (mode) { + case AAPT: + return facet.getConfiguration().REGENERATE_R_JAVA && + AndroidAptCompiler.isToCompileModule(facet.getModule(), facet.getConfiguration()); + case AIDL: + return facet.getConfiguration().REGENERATE_JAVA_BY_AIDL; + case RENDERSCRIPT: + return true; + default: + LOG.error("Unknown autogenerator mode " + mode); + return false; + } + } + public static void run(@NotNull AndroidAutogeneratorMode mode, @NotNull AndroidFacet facet, @NotNull CompileContext context) { + if (!toRun(mode, facet)) { + return; + } final Set obsoleteFiles = new HashSet(facet.getAutogeneratedFiles(mode)); switch (mode) { From f03a6355b32e8f79692d726782ff11082e2d5063 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Mon, 2 Apr 2012 18:28:17 +0200 Subject: [PATCH 28/32] [peter] ensure atomic root change + psi counter increment + java resolve cache drop --- .../impl/source/resolve/JavaResolveCache.java | 18 +++++++++++++++--- .../roots/impl/ProjectRootManagerImpl.java | 7 ++++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java index e4bca75a0eb0..91a8419a50e6 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java @@ -24,16 +24,21 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.NotNullLazyKey; -import com.intellij.psi.*; +import com.intellij.psi.PsiExpression; +import com.intellij.psi.PsiJavaCodeReferenceElement; +import com.intellij.psi.PsiType; +import com.intellij.psi.PsiVariable; import com.intellij.psi.impl.AnyPsiChangeListener; import com.intellij.psi.impl.PsiManagerImpl; import com.intellij.psi.impl.source.PsiClassReferenceType; +import com.intellij.psi.util.PsiModificationTracker; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.reference.SoftReference; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.Function; import com.intellij.util.containers.ConcurrentWeakHashMap; import com.intellij.util.messages.MessageBus; +import com.intellij.util.messages.MessageBusConnection; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -64,16 +69,23 @@ public class JavaResolveCache { myVarToConstValueMapNonPhysical = new ConcurrentWeakHashMap(); if (messageBus != null) { - messageBus.connect().subscribe(PsiManagerImpl.ANY_PSI_CHANGE_TOPIC, new AnyPsiChangeListener() { + final MessageBusConnection connection = messageBus.connect(); + connection.subscribe(PsiManagerImpl.ANY_PSI_CHANGE_TOPIC, new AnyPsiChangeListener() { @Override public void beforePsiChanged(boolean isPhysical) { clearCaches(isPhysical); } - + @Override public void afterPsiChanged(boolean isPhysical) { } }); + connection.subscribe(PsiModificationTracker.TOPIC, new PsiModificationTracker.Listener() { + @Override + public void modificationCountChanged() { + clearCaches(true); + } + }); } } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java index 811aa5dce501..3865076918fa 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java @@ -52,10 +52,13 @@ import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.ex.VirtualFileManagerAdapter; import com.intellij.openapi.vfs.pointers.VirtualFilePointer; import com.intellij.openapi.vfs.pointers.VirtualFilePointerListener; +import com.intellij.psi.PsiManager; +import com.intellij.psi.impl.PsiModificationTrackerImpl; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.EventDispatcher; -import com.intellij.util.containers.*; +import com.intellij.util.containers.ConcurrentHashMap; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.HashSet; import com.intellij.util.messages.MessageBusConnection; @@ -525,6 +528,8 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj myModificationCount++; + ((PsiModificationTrackerImpl)PsiManager.getInstance(myProject).getModificationTracker()).incCounter(); + isFiringEvent = true; try { myProject.getMessageBus() From 5cb30a937d1a8a20a876284b9fde8267d50ef556 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Mon, 2 Apr 2012 20:51:08 +0400 Subject: [PATCH 29/32] Add additional logining to understand cause of failing maven tests. --- .../main/java/org/jetbrains/idea/maven/indices/MavenIndex.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java index fdb24a97580b..6be07ffa5292 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java @@ -492,7 +492,7 @@ public class MavenIndex { } @TestOnly - public void printInfo() { + public synchronized void printInfo() { doIndexTask(new IndexTask>() { public Set doTask() throws Exception { System.out.println("BaseFile: " + myData.groupToArtifactMap.getBaseFile()); From 3fbb7213407acdf89084fd585d4eeab877de8663 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 2 Apr 2012 17:13:13 +0200 Subject: [PATCH 30/32] margins (IDEA-83904) --- .../intellij/codeInsight/daemon/impl/HectorComponent.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HectorComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HectorComponent.java index d994196e6b6a..52f410268636 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HectorComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HectorComponent.java @@ -197,7 +197,7 @@ public class HectorComponent extends JPanel { slider.setOrientation(SwingConstants.HORIZONTAL); slider.setPreferredSize(new Dimension(200, 40)); panel.add(slider, new GridBagConstraints(0, 1, 1, 1, 1, 0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(0, 0, 0, 0), 0, 0)); + new Insets(5, 0, 5, 0), 0, 0)); } } @@ -205,11 +205,11 @@ public class HectorComponent extends JPanel { for (Language language : mySliders.keySet()) { JSlider slider = mySliders.get(language); JPanel borderPanel = new JPanel(new BorderLayout()); - slider.setPreferredSize(new Dimension(80, 100)); + slider.setPreferredSize(new Dimension(100, 100)); borderPanel.add(new JLabel(language.getID()), BorderLayout.NORTH); borderPanel.add(slider, BorderLayout.CENTER); panel.add(borderPanel, new GridBagConstraints(GridBagConstraints.RELATIVE, 1, 1, 1, 0, 1, GridBagConstraints.CENTER, GridBagConstraints.VERTICAL, - new Insets(0, 0, 0, 0), 0, 0)); + new Insets(0, 5, 0, 5), 0, 0)); } } From 6b06d65ecf3f1cf7a68de5168d6a0bd3717d1bd6 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 2 Apr 2012 17:42:17 +0200 Subject: [PATCH 31/32] plugins: sort by installed status: take enable/disable; incompatibility into account (IDEA-83782) --- .../ide/plugins/InstalledPluginsTableModel.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java index 21d8a5bbc3af..c651ebc863bc 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java @@ -641,6 +641,14 @@ public class InstalledPluginsTableModel extends PluginTableModel { @Override public int compare(IdeaPluginDescriptor o1, IdeaPluginDescriptor o2) { if (isSortByStatus()) { + final boolean incompatible1 = PluginManager.isIncompatible(o1); + final boolean incompatible2 = PluginManager.isIncompatible(o2); + if (incompatible1) { + if (incompatible2) return comparator.compare(o1, o2); + return -1; + } + if (incompatible2) return 1; + final boolean hasNewerVersion1 = hasNewerVersion(o1.getPluginId()); final boolean hasNewerVersion2 = hasNewerVersion(o2.getPluginId()); if (hasNewerVersion1) { @@ -673,6 +681,11 @@ public class InstalledPluginsTableModel extends PluginTableModel { return -1; } if (deleted2) return 1; + + final boolean enabled1 = isEnabled(o1.getPluginId()); + final boolean enabled2 = isEnabled(o2.getPluginId()); + if (enabled1 && !enabled2) return -1; + if (enabled2 && !enabled1) return 1; } return comparator.compare(o1, o2); } From 29bdd83b983f1ebcf6f69677a8e3798b6fadc3cf Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 2 Apr 2012 19:00:59 +0200 Subject: [PATCH 32/32] move: leave preserve source root folder if package is moved (IDEA-83833) --- .../MoveClassesOrPackagesToNewDirectoryDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesToNewDirectoryDialog.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesToNewDirectoryDialog.java index 2cfd42d1a3d0..8a11a20021ac 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesToNewDirectoryDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesToNewDirectoryDialog.java @@ -114,7 +114,7 @@ public class MoveClassesOrPackagesToNewDirectoryDialog extends DialogWrapper { for (PsiDirectory psiDirectory : ((PsiPackage)element).getDirectories()) { final VirtualFile virtualFile = psiDirectory.getVirtualFile(); sourceRoots.add(fileIndex.getSourceRootForFile(virtualFile)); - sameModule &= destinationModule == fileIndex.getModuleForFile(virtualFile); + //sameModule &= destinationModule == fileIndex.getModuleForFile(virtualFile); } } else if (element instanceof PsiClass) { final VirtualFile virtualFile = element.getContainingFile().getVirtualFile();