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); + } + } } } } 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/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(); 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); } } 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/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)); } } 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); + } } } 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() 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; } 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/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); 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..c651ebc863bc 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); } @@ -136,7 +140,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); } @@ -637,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) { @@ -669,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); } 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/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/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; 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/editor/impl/EditorComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java index 477c546cb56d..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 @@ -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,7 @@ import java.awt.im.InputMethodRequests; import java.util.Map; public class EditorComponentImpl extends JComponent implements Scrollable, DataProvider, Queryable, TypingTarget { + private final EditorImpl myEditor; public EditorComponentImpl(EditorImpl editor) { @@ -144,7 +145,7 @@ public class EditorComponentImpl extends JComponent implements Scrollable, DataP ((ApplicationImpl)ApplicationManager.getApplication()).editorPaintStart(); try { - ((Graphics2D)g).setComposite(AlphaComposite.Src); + UIUtil.setupComposite((Graphics2D)g); UISettings.setupAntialiasing(g); myEditor.paint((Graphics2D)g); 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/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 94684b597904..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 @@ -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)); @@ -535,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; } 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 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/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index ce17aba15305..b65181ae178d 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,18 @@ public class UIUtil { } } + /** + * 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 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(); 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(); 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; 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/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) { 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/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 e9350bd5bffa..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")) { @@ -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(); @@ -184,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()); @@ -194,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); 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); 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 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); 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); } /** 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; + } + } } 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/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 1fea9d257838..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; @@ -236,6 +237,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 +262,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 +333,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 +382,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 +436,10 @@ 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)); + if (refExpr.getParent() instanceof GrArgumentList) { + addNodeAndCheckPending(new ArgumentInstruction(refExpr, myInstructionNumber++)); + } } } else if (!(refExpr.getParent() instanceof GrCall)) { @@ -507,8 +506,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 +932,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) { 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/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/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 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 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()); 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()); + } + } +} +