From 17e7380fd5a20f6322bd44972feb6f4a65f7b46c Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 28 Mar 2011 20:32:46 +0400 Subject: [PATCH 01/27] do not ask for restarting ddms if it is corrupted --- .../run/AndroidRunConfigurationBase.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/run/AndroidRunConfigurationBase.java b/plugins/android/src/org/jetbrains/android/run/AndroidRunConfigurationBase.java index 2154d9f8b7a5..f761e33f4230 100644 --- a/plugins/android/src/org/jetbrains/android/run/AndroidRunConfigurationBase.java +++ b/plugins/android/src/org/jetbrains/android/run/AndroidRunConfigurationBase.java @@ -277,19 +277,23 @@ public abstract class AndroidRunConfigurationBase extends ModuleBasedConfigurati } private static boolean activateDdmsIfNeccessary(@NotNull AndroidFacet facet) { - Project project = facet.getModule().getProject(); - boolean ddmsEnabled = AndroidEnableDdmsAction.isDdmsEnabled(); + final Project project = facet.getModule().getProject(); + final boolean ddmsEnabled = AndroidEnableDdmsAction.isDdmsEnabled(); + boolean shouldRestartDdms = !ddmsEnabled; + if (ddmsEnabled && isDdmsCorrupted(facet)) { - ddmsEnabled = false; + shouldRestartDdms = true; AndroidEnableDdmsAction.setDdmsEnabled(project, false); } - if (!ddmsEnabled) { - int result = Messages.showYesNoDialog(project, AndroidBundle.message("android.ddms.disabled.error"), - AndroidBundle.message("android.ddms.disabled.dialog.title"), - Messages.getQuestionIcon()); - if (result != 0) { - return false; + if (shouldRestartDdms) { + if (!ddmsEnabled) { + int result = Messages.showYesNoDialog(project, AndroidBundle.message("android.ddms.disabled.error"), + AndroidBundle.message("android.ddms.disabled.dialog.title"), + Messages.getQuestionIcon()); + if (result != 0) { + return false; + } } AndroidEnableDdmsAction.setDdmsEnabled(project, true); } From 0758300e1350d024ec8e2d3e2299b892115e92c2 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 28 Mar 2011 18:05:13 +0200 Subject: [PATCH 02/27] fix typo --- .../lang-api/src/com/intellij/psi/impl/ElementBase.java | 8 ++++---- .../openapi/fileTypes/impl/NativeFileIconProvider.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/platform/lang-api/src/com/intellij/psi/impl/ElementBase.java b/platform/lang-api/src/com/intellij/psi/impl/ElementBase.java index 99f6fc642074..3aabf8906f7d 100644 --- a/platform/lang-api/src/com/intellij/psi/impl/ElementBase.java +++ b/platform/lang-api/src/com/intellij/psi/impl/ElementBase.java @@ -59,8 +59,8 @@ public abstract class ElementBase extends UserDataHolderBase implements Iconable }; private TIntObjectHashMap myBaseIcon; - private static final Icon VISIBILITY_ICON_PLACHOLDER = new EmptyIcon(Icons.PUBLIC_ICON); - public static final Icon ICON_PLACHOLDER = IconLoader.getIcon("/nodes/nodePlaceholder.png"); + private static final Icon VISIBILITY_ICON_PLACEHOLDER = new EmptyIcon(Icons.PUBLIC_ICON); + public static final Icon ICON_PLACEHOLDER = IconLoader.getIcon("/nodes/nodePlaceholder.png"); @Nullable public Icon getIcon(int flags) { @@ -132,7 +132,7 @@ public abstract class ElementBase extends UserDataHolderBase implements Iconable } } } - return ICON_PLACHOLDER; + return ICON_PLACEHOLDER; } public static boolean isNativeFileType(FileType fileType) { @@ -144,7 +144,7 @@ public abstract class ElementBase extends UserDataHolderBase implements Iconable if ((flags & ICON_FLAG_VISIBILITY) > 0) { RowIcon rowIcon = new RowIcon(2); rowIcon.setIcon(icon, 0); - rowIcon.setIcon(VISIBILITY_ICON_PLACHOLDER, 1); + rowIcon.setIcon(VISIBILITY_ICON_PLACEHOLDER, 1); result = rowIcon; } diff --git a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/NativeFileIconProvider.java b/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/NativeFileIconProvider.java index 2dfaaccb732f..5eac40bb93e6 100644 --- a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/NativeFileIconProvider.java +++ b/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/NativeFileIconProvider.java @@ -68,7 +68,7 @@ public class NativeFileIconProvider implements FileIconProvider { if (icon != null) { return icon; } - return new DeferredIconImpl(ElementBase.ICON_PLACHOLDER, file, false, new Function() { + return new DeferredIconImpl(ElementBase.ICON_PLACEHOLDER, file, false, new Function() { public Icon fun(VirtualFile virtualFile) { final File f = new File(filePath); if (!f.exists()) { From 04452ec1fabb475544ae064d16b58e313f881dd7 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 28 Mar 2011 18:49:40 +0200 Subject: [PATCH 03/27] a correct tree range anchor hashCode that doesn't change over time diagnostics for EA-25219 --- .../src/com/intellij/psi/PsiAnchor.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/PsiAnchor.java b/platform/lang-impl/src/com/intellij/psi/PsiAnchor.java index 91a6103b95f5..82705817268f 100644 --- a/platform/lang-impl/src/com/intellij/psi/PsiAnchor.java +++ b/platform/lang-impl/src/com/intellij/psi/PsiAnchor.java @@ -180,10 +180,10 @@ public abstract class PsiAnchor { } public int hashCode() { - int result = myClass != null ? myClass.getName().hashCode() : 0; - result = 31 * result + myStartOffset; //todo + int result = myClass.getName().hashCode(); + result = 31 * result + myStartOffset; result = 31 * result + myEndOffset; - result = 31 * result + myVirtualFile.getName().hashCode(); + result = 31 * result + myVirtualFile.hashCode(); return result; } @@ -326,6 +326,17 @@ public abstract class PsiAnchor { return ((31 * myVirtualFile.hashCode() + myIndex) * 31 + myElementType.hashCode()) * 31 + myLanguage.hashCode(); } + @Override + public String toString() { + return "StubIndexReference{" + + "myVirtualFile=" + myVirtualFile + + ", myProject=" + myProject + + ", myIndex=" + myIndex + + ", myLanguage=" + myLanguage + + ", myElementType=" + myElementType + + '}'; + } + public int getStartOffset() { final PsiElement resolved = retrieve(); if (resolved == null) throw new PsiInvalidElementAccessException(null); From 61cb1246e2c688ba9efff548944765f437d2d32f Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 28 Mar 2011 22:28:21 +0400 Subject: [PATCH 04/27] IDEA-66204 we should compile aidl files only under source root --- .../src/org/jetbrains/android/compiler/AndroidIdlCompiler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidIdlCompiler.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidIdlCompiler.java index d17c6dc39211..66d7bc5aa57e 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidIdlCompiler.java +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidIdlCompiler.java @@ -162,7 +162,7 @@ public class AndroidIdlCompiler implements SourceGeneratingCompiler { if (myContext.getProject().isDisposed()) { return EMPTY_GENERATION_ITEM_ARRAY; } - VirtualFile[] files = myContext.getProjectCompileScope().getFiles(AndroidIdlFileType.ourFileType, false); + VirtualFile[] files = myContext.getProjectCompileScope().getFiles(AndroidIdlFileType.ourFileType, true); List items = new ArrayList(files.length); for (VirtualFile file : files) { Module module = myContext.getModuleByFile(file); From 97a00c311ce11db030ca1ef21a07c43982df2afd Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 28 Mar 2011 22:49:42 +0400 Subject: [PATCH 05/27] IDEA-66282 correct assigning of android application name --- .../newProject/AndroidModuleBuilder.java | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java index 05c1cdd71426..7d364b5ec5d0 100644 --- a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java +++ b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java @@ -49,10 +49,12 @@ import com.intellij.psi.PsiManager; import com.intellij.util.ArrayUtil; import org.jetbrains.android.AndroidFileTemplateProvider; import org.jetbrains.android.dom.manifest.Manifest; +import org.jetbrains.android.dom.resources.ResourceElement; import org.jetbrains.android.dom.resources.ResourceValue; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.facet.AndroidFacetConfiguration; import org.jetbrains.android.facet.AndroidRootUtil; +import org.jetbrains.android.resourceManagers.LocalResourceManager; import org.jetbrains.android.run.testing.AndroidTestRunConfiguration; import org.jetbrains.android.run.testing.AndroidTestRunConfigurationType; import org.jetbrains.android.sdk.AndroidPlatform; @@ -253,10 +255,7 @@ public class AndroidModuleBuilder extends JavaModuleBuilder { return; } if (myProjectType == ProjectType.APPLICATION) { - Manifest manifest = facet.getManifest(); - if (manifest != null && myApplicationName.length() > 0) { - manifest.getApplication().getLabel().setValue(ResourceValue.literal(myApplicationName)); - } + assignApplicationName(facet); createChildDirectoryIfNotExist(project, contentRoot, SdkConstants.FD_ASSETS); createChildDirectoryIfNotExist(project, contentRoot, SdkConstants.FD_NATIVE_LIBS); } @@ -284,6 +283,35 @@ public class AndroidModuleBuilder extends JavaModuleBuilder { return true; } + private void assignApplicationName(AndroidFacet facet) { + if (myApplicationName == null || myApplicationName.length() == 0) { + return; + } + + final LocalResourceManager manager = facet.getLocalResourceManager(); + ResourceElement appNameResElement = null; + final String appNameResource = "app_name"; + + for (ResourceElement resElement : manager.getValueResources("string")) { + if (appNameResource.equals(resElement.getName().getValue())) { + appNameResElement = resElement; + } + } + + if (appNameResElement == null) { + manager.addValueResource("string", appNameResource, myApplicationName); + } + else { + appNameResElement.setStringValue(myApplicationName); + } + + final Manifest manifest = facet.getManifest(); + + if (manifest != null) { + manifest.getApplication().getLabel().setValue(ResourceValue.referenceTo('@', null, "string", appNameResource)); + } + } + private static void moveContentAndRemoveDir(Project project, @NotNull VirtualFile from, @NotNull VirtualFile to) throws IOException { for (VirtualFile child : from.getChildren()) { child.move(project, to); @@ -386,9 +414,8 @@ public class AndroidModuleBuilder extends JavaModuleBuilder { FileDocumentManager.getInstance().saveAllDocuments(); } }); - if (myApplicationName.length() > 0) { - manifest.getApplication().getLabel().setValue(ResourceValue.literal(myApplicationName)); - } + + assignApplicationName(facet); } } }; From 9604adb816f470e0f7fb2b938defad48bd825e4c Mon Sep 17 00:00:00 2001 From: andrey zaytsev Date: Mon, 28 Mar 2011 22:50:06 +0400 Subject: [PATCH 06/27] search/replace: search inside diff in case of modal diff dialog. --- .../find/impl/livePreview/LivePreviewControllerBase.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java index 31845dd7dcc9..098e18e69c8f 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreviewControllerBase.java @@ -138,6 +138,7 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil if (findModel == null) return; final boolean unitTestMode = ApplicationManager.getApplication().isUnitTestMode(); final FindModel copy = (FindModel)findModel.clone(); + final ModalityState modalityState = ModalityState.current(); Runnable request = new Runnable() { @Override public void run() { @@ -150,7 +151,7 @@ public class LivePreviewControllerBase implements LivePreview.Delegate, FindUtil if (unitTestMode) { denyReplace.run(); } else { - ApplicationManager.getApplication().invokeAndWait(denyReplace, ModalityState.NON_MODAL); + ApplicationManager.getApplication().invokeAndWait(denyReplace, modalityState); } mySearchResults.updateThreadSafe(copy, allowedToChangedEditorSelection, null); } From f6d95a2d6a88778056b414d90027f00d94c4a18d Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 28 Mar 2011 23:25:20 +0400 Subject: [PATCH 07/27] IDEA-66206 possibility to create pure android without generated files --- .../AndroidAppPropertiesEditor.form | 2 +- .../newProject/AndroidModuleBuilder.java | 4 + .../newProject/AndroidModuleWizardStep.form | 101 +++++++++++------- .../newProject/AndroidModuleWizardStep.java | 66 ++++++++---- 4 files changed, 111 insertions(+), 62 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.form b/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.form index 085b3efb8ee1..f43a933de4c7 100644 --- a/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.form +++ b/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.form @@ -60,7 +60,7 @@ - + diff --git a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java index 7d364b5ec5d0..0278ef242abd 100644 --- a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java +++ b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleBuilder.java @@ -92,6 +92,10 @@ public class AndroidModuleBuilder extends JavaModuleBuilder { rootModel.setSdk(mySdk); + if (myProjectType == null) { + return; + } + VirtualFile[] files = rootModel.getContentRoots(); if (files.length > 0) { final VirtualFile contentRoot = files[0]; diff --git a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleWizardStep.form b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleWizardStep.form index 9128854590ea..0df9506def97 100644 --- a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleWizardStep.form +++ b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleWizardStep.form @@ -1,9 +1,9 @@
- + - + @@ -13,44 +13,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -61,10 +23,67 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleWizardStep.java b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleWizardStep.java index d0d046a95076..fd38b445b94e 100644 --- a/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleWizardStep.java +++ b/plugins/android/src/org/jetbrains/android/newProject/AndroidModuleWizardStep.java @@ -57,6 +57,8 @@ public class AndroidModuleWizardStep extends ModuleWizardStep { private JPanel myPropertiesPanel; private AndroidSdkComboBoxWithBrowseButton mySdkComboBoxWithBrowseButton; + private JCheckBox myCreateDefaultStructure; + private JPanel myApplicationPanel; private final WizardContext myWizardContext; @@ -84,31 +86,47 @@ public class AndroidModuleWizardStep extends ModuleWizardStep { ActionListener listener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - if (myApplicationProjectButton.isSelected() || myLibProjectButton.isSelected()) { - myAppPropertiesEditor.getContentPanel().setVisible(true); - if (myTestPropertiesEditor != null) { - myTestPropertiesEditor.getContentPanel().setVisible(false); - } - boolean app = myApplicationProjectButton.isSelected(); - myAppPropertiesEditor.getApplicationNameField().setEnabled(app); - myAppPropertiesEditor.getHelloAndroidCheckBox().setEnabled(app); - if (app) { - myAppPropertiesEditor.updateActivityPanel(); - } - else { - UIUtil.setEnabled(myAppPropertiesEditor.getActivtiyPanel(), app, true); - } - } - else { - myAppPropertiesEditor.getContentPanel().setVisible(false); - assert myTestPropertiesEditor != null; - myTestPropertiesEditor.getContentPanel().setVisible(true); - } + updatePropertiesEditor(); } }; myApplicationProjectButton.addActionListener(listener); myLibProjectButton.addActionListener(listener); myTestProjectButton.addActionListener(listener); + + myCreateDefaultStructure.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + final boolean enabled = myCreateDefaultStructure.isSelected(); + UIUtil.setEnabled(myApplicationPanel, enabled, true); + + if (enabled) { + updatePropertiesEditor(); + } + } + }); + } + + private void updatePropertiesEditor() { + if (myApplicationProjectButton.isSelected() || myLibProjectButton.isSelected()) { + myAppPropertiesEditor.getContentPanel().setVisible(true); + if (myTestPropertiesEditor != null) { + myTestPropertiesEditor.getContentPanel().setVisible(false); + } + boolean app = myApplicationProjectButton.isSelected(); + myAppPropertiesEditor.getApplicationNameField().setEnabled(app); + myAppPropertiesEditor.getHelloAndroidCheckBox().setEnabled(app); + if (app) { + myAppPropertiesEditor.updateActivityPanel(); + } + else { + UIUtil.setEnabled(myAppPropertiesEditor.getActivtiyPanel(), app, true); + } + } + else { + myAppPropertiesEditor.getContentPanel().setVisible(false); + assert myTestPropertiesEditor != null; + myTestPropertiesEditor.getContentPanel().setVisible(true); + } } public JComponent getComponent() { @@ -135,6 +153,10 @@ public class AndroidModuleWizardStep extends ModuleWizardStep { throw new ConfigurationException(AndroidBundle.message("select.platform.error")); } + if (!myCreateDefaultStructure.isSelected()) { + return true; + } + if (myApplicationProjectButton.isSelected() || myLibProjectButton.isSelected()) { myAppPropertiesEditor.validate(myTestProjectButton.isSelected()); } @@ -153,6 +175,10 @@ public class AndroidModuleWizardStep extends ModuleWizardStep { PropertiesComponent.getInstance().setValue(AndroidSdkUtils.DEFAULT_PLATFORM_NAME_PROPERTY, selectedSdk.getName()); myModuleBuilder.setSdk(selectedSdk); + if (!myCreateDefaultStructure.isSelected()) { + return; + } + if (myApplicationProjectButton.isSelected() || myLibProjectButton.isSelected()) { myModuleBuilder.setProjectType(myApplicationProjectButton.isSelected() ? ProjectType.APPLICATION : ProjectType.LIBRARY); myModuleBuilder.setActivityName(myAppPropertiesEditor.getActivityName()); From bd0e7ba9a46c66037b938e40f454c93afe67f97a Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 28 Mar 2011 23:31:31 +0400 Subject: [PATCH 08/27] restore foreground --- .../android/newProject/AndroidAppPropertiesEditor.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.java b/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.java index ea2831327363..3d6d4f114d18 100644 --- a/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.java +++ b/plugins/android/src/org/jetbrains/android/newProject/AndroidAppPropertiesEditor.java @@ -29,6 +29,7 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.event.DocumentEvent; +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -71,6 +72,7 @@ public class AndroidAppPropertiesEditor { } public void updateActivityPanel() { + myErrorLabel.setForeground(Color.RED); UIUtil.setEnabled(myActivtiyPanel, myHelloAndroidCheckBox.isSelected(), true); } From 674ae2685844cbe9d73092ed51044a6a88be7045 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 28 Mar 2011 21:31:59 +0200 Subject: [PATCH 09/27] A bit more realistic I/O timing --- .../com/intellij/testFramework/Timings.java | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/Timings.java b/platform/testFramework/src/com/intellij/testFramework/Timings.java index 5ba700eb58d4..7fa1027753c9 100644 --- a/platform/testFramework/src/com/intellij/testFramework/Timings.java +++ b/platform/testFramework/src/com/intellij/testFramework/Timings.java @@ -17,10 +17,7 @@ package com.intellij.testFramework; import com.intellij.openapi.util.io.FileUtil; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; +import java.io.*; import java.math.BigInteger; /** @@ -28,6 +25,9 @@ import java.math.BigInteger; */ @SuppressWarnings({"UtilityClassWithoutPrivateConstructor"}) public class Timings { + private static final int CPU_PROBES = 1000000; + private static final int IO_PROBES = 42; + public static final long CPU_TIMING; public static final long IO_TIMING; public static final long MACHINE_TIMING; @@ -37,13 +37,13 @@ public class Timings { start = System.currentTimeMillis(); BigInteger k = new BigInteger("1"); - for (int i = 0; i < 1000000; i++) { + for (int i = 0; i < CPU_PROBES; i++) { k = k.add(new BigInteger("1")); } CPU_TIMING = System.currentTimeMillis() - start; start = System.currentTimeMillis(); - for (int i = 0; i < 42; i++) { + for (int i = 0; i < IO_PROBES; i++) { try { final File tempFile = FileUtil.createTempFile("test", "test" + i); @@ -66,6 +66,16 @@ public class Timings { reader.close(); } + if (i == IO_PROBES - 1) { + final FileOutputStream stream = new FileOutputStream(tempFile); + try { + stream.getFD().sync(); + } + finally { + stream.close(); + } + } + if (!tempFile.delete()) { throw new IOException("Unable to delete: " + tempFile); } From c3edbcdf47275a89f921b1fc132594cc436d99ab Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 28 Mar 2011 15:59:22 +0400 Subject: [PATCH 10/27] typo --- .../com/intellij/openapi/ui/popup/PopupChooserBuilder.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java b/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java index 8aa1dbbd027d..58a90ad1f6f9 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/popup/PopupChooserBuilder.java @@ -48,7 +48,7 @@ public class PopupChooserBuilder { private JComponent myChooserComponent; private String myTitle; private final ArrayList myAdditionalKeystrokes = new ArrayList(); - private Runnable myItemChoosenRunnable; + private Runnable myItemChosenRunnable; private JComponent mySouthComponent; private JComponent myEastComponent; @@ -103,7 +103,7 @@ public class PopupChooserBuilder { @NotNull public PopupChooserBuilder setItemChoosenCallback(@NotNull Runnable runnable) { - myItemChoosenRunnable = runnable; + myItemChosenRunnable = runnable; return this; } @@ -283,7 +283,7 @@ public class PopupChooserBuilder { private void closePopup(boolean shouldPerformAction, MouseEvent e, boolean isOk) { if (shouldPerformAction) { - myPopup.setFinalRunnable(myItemChoosenRunnable); + myPopup.setFinalRunnable(myItemChosenRunnable); } if (isOk) { From 5eecc462d544028a129cfd6aa9577b8b5e511a8b Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 28 Mar 2011 16:39:34 +0400 Subject: [PATCH 11/27] two useful methods --- platform/util/src/com/intellij/util/ui/UIUtil.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 1f0ada94107b..b0b2350e19c5 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -435,10 +435,18 @@ public class UIUtil { return isUnderGTKLookAndFeel() ? getTreeTextBackground() : UIManager.getColor("List.background"); } + public static Color getListBackground(boolean isSelected) { + return isSelected ? getListSelectionBackground() : getListBackground(); + } + public static Color getListForeground() { return UIManager.getColor("List.foreground"); } + public static Color getListForeground(boolean isSelected) { + return isSelected ? getListSelectionForeground() : getListForeground(); + } + public static Color getPanelBackground() { return UIManager.getColor("Panel.background"); } From 4c0bd2eb57840a48fae0caf7ebf8796aa40669ee Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 28 Mar 2011 19:02:43 +0400 Subject: [PATCH 12/27] SpringGuttersTest restored --- .../fixtures/impl/CodeInsightTestFixtureImpl.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java index 948a00cf3765..62605f5fdb76 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -758,7 +758,6 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig @Nullable public GutterIconRenderer findGutter(final String filePath) { assertInitialized(); - final Ref result = new Ref(); configureByFilesInner(filePath); int offset = myEditor.getCaretModel().getOffset(); @@ -767,12 +766,20 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig if (info.endOffset >= offset && info.startOffset <= offset) { final GutterIconRenderer renderer = info.getGutterIconRenderer(); if (renderer != null) { - result.set(renderer); - break; + return renderer; } } } - return result.get(); + RangeHighlighter[] highlighters = myEditor.getDocument().getMarkupModel(getProject()).getAllHighlighters(); + for (RangeHighlighter highlighter : highlighters) { + if (highlighter.getEndOffset() >= offset && highlighter.getStartOffset() <= offset) { + GutterIconRenderer renderer = highlighter.getGutterIconRenderer(); + if (renderer != null) { + return renderer; + } + } + } + return null; } @Override From 5522fdd35f3713c35b7a0f688c110573f209714f Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 29 Mar 2011 10:39:44 +0400 Subject: [PATCH 13/27] GoToRelatedAction introduced --- .../intellij/navigation/GotoRelatedItem.java | 39 ++++++ .../navigation/GotoRelatedProvider.java | 34 +++++ .../ide/actions/GoToRelatedAction.java | 121 ++++++++++++++++++ .../src/META-INF/LangExtensionPoints.xml | 2 + .../src/idea/LangActions.xml | 1 + .../navigation/DomGotoRelatedItem.java | 58 +++++++++ 6 files changed, 255 insertions(+) create mode 100644 platform/lang-api/src/com/intellij/navigation/GotoRelatedItem.java create mode 100644 platform/lang-api/src/com/intellij/navigation/GotoRelatedProvider.java create mode 100644 platform/lang-impl/src/com/intellij/ide/actions/GoToRelatedAction.java create mode 100644 xml/dom-openapi/src/com/intellij/codeInsight/navigation/DomGotoRelatedItem.java diff --git a/platform/lang-api/src/com/intellij/navigation/GotoRelatedItem.java b/platform/lang-api/src/com/intellij/navigation/GotoRelatedItem.java new file mode 100644 index 000000000000..be570cd04373 --- /dev/null +++ b/platform/lang-api/src/com/intellij/navigation/GotoRelatedItem.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2011 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.navigation; + +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +/** + * @author Dmitry Avdeev + */ +public abstract class GotoRelatedItem { + + public abstract void navigate(); + + @NotNull + public abstract String getText(); + + @Nullable + public abstract Icon getIcon(); + + @Nullable + public abstract PsiFile getContainingFile(); +} diff --git a/platform/lang-api/src/com/intellij/navigation/GotoRelatedProvider.java b/platform/lang-api/src/com/intellij/navigation/GotoRelatedProvider.java new file mode 100644 index 000000000000..c07231989af6 --- /dev/null +++ b/platform/lang-api/src/com/intellij/navigation/GotoRelatedProvider.java @@ -0,0 +1,34 @@ +/* + * Copyright 2000-2011 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.navigation; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * @author Dmitry Avdeev + */ +public abstract class GotoRelatedProvider { + + public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.gotoRelatedProvider"); + + @NotNull + public abstract List getItems(PsiElement context); +} diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GoToRelatedAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GoToRelatedAction.java new file mode 100644 index 000000000000..c18efecf2faf --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/actions/GoToRelatedAction.java @@ -0,0 +1,121 @@ +/* + * Copyright 2000-2011 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.ide.actions; + +import com.intellij.navigation.GotoRelatedItem; +import com.intellij.navigation.GotoRelatedProvider; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.ui.CollectionListModel; +import com.intellij.ui.components.JBList; +import com.intellij.util.ui.UIUtil; + +import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Dmitry Avdeev + */ +public class GoToRelatedAction extends AnAction { + + @Override + public void actionPerformed(AnActionEvent e) { + + DataContext context = e.getDataContext(); + Editor editor = PlatformDataKeys.EDITOR.getData(context); + PsiFile psiFile = LangDataKeys.PSI_FILE.getData(context); + if (editor == null || psiFile == null) return; + + PsiElement psiElement = psiFile.findElementAt(editor.getCaretModel().getOffset()); + if (psiElement == null) psiElement = psiFile; + + List items = new ArrayList(); + + for (GotoRelatedProvider provider : Extensions.getExtensions(GotoRelatedProvider.EP_NAME)) { + items.addAll(provider.getItems(psiElement)); + } + if (items.isEmpty()) return; + if (items.size() == 1) { + items.get(0).navigate(); + return; + } + + final JBList list = new JBList(new CollectionListModel(items)); + list.setCellRenderer(new ItemCellRenderer()); + + JBPopupFactory.getInstance() + .createListPopupBuilder(list) + .setTitle("Goto Related") + .setItemChoosenCallback(new Runnable() { + @Override + public void run() { + Object value = list.getSelectedValue(); + if (value instanceof GotoRelatedItem) { + ((GotoRelatedItem)value).navigate(); + } + } + }) + .createPopup() + .showInBestPositionFor(context); + } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled(PlatformDataKeys.EDITOR.getData(e.getDataContext()) != null && + LangDataKeys.PSI_FILE.getData(e.getDataContext()) != null); + } + + private static class ItemCellRenderer extends JPanel implements ListCellRenderer { + + private final JLabel myLeft = new JLabel(); + private final JLabel myRight = new JLabel(); + private final JPanel mySpacer = new JPanel(); + + private ItemCellRenderer() { + super(new BorderLayout()); + setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); + add(myLeft, BorderLayout.WEST); + add(myRight, BorderLayout.EAST); + + mySpacer.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 2)); + mySpacer.setOpaque(false); + add(mySpacer, BorderLayout.CENTER); + } + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + GotoRelatedItem item = (GotoRelatedItem)value; + myLeft.setText(item.getText()); + myLeft.setIcon(item.getIcon()); + + PsiFile file = item.getContainingFile(); + myRight.setText(file == null ? null : file.getName()); + myRight.setIcon(file == null ? null : file.getIcon(0)); + + setBackground(UIUtil.getListBackground(isSelected)); + Color foreground = UIUtil.getListForeground(isSelected); + myLeft.setForeground(foreground); + myRight.setForeground(foreground); + return this; + } + } +} diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index 8ce5e8bebf3b..fbbd83351eee 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -138,6 +138,8 @@ + + diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 32efe5e05383..fd0f7a10a12c 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -225,6 +225,7 @@ + diff --git a/xml/dom-openapi/src/com/intellij/codeInsight/navigation/DomGotoRelatedItem.java b/xml/dom-openapi/src/com/intellij/codeInsight/navigation/DomGotoRelatedItem.java new file mode 100644 index 000000000000..94233cdd5f27 --- /dev/null +++ b/xml/dom-openapi/src/com/intellij/codeInsight/navigation/DomGotoRelatedItem.java @@ -0,0 +1,58 @@ +/* + * Copyright 2000-2011 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.navigation; + +import com.intellij.navigation.GotoRelatedItem; +import com.intellij.psi.DelegatePsiTarget; +import com.intellij.psi.PsiFile; +import com.intellij.util.xml.DomElement; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +/** + * @author Dmitry Avdeev + */ +public class DomGotoRelatedItem extends GotoRelatedItem { + + private final DomElement myElement; + + public DomGotoRelatedItem(DomElement element) { + + myElement = element; + } + + @Override + public void navigate() { + new DelegatePsiTarget(myElement.getXmlElement()).navigate(true); + } + + @NotNull + @Override + public String getText() { + return myElement.getPresentation().getElementName(); + } + + @Override + public Icon getIcon() { + return myElement.getPresentation().getIcon(); + } + + @Override + public PsiFile getContainingFile() { + return myElement.getXmlElement().getContainingFile(); + } +} From 59279b613596c4f12621b5190972dbdd2854df44 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 29 Mar 2011 11:19:27 +0400 Subject: [PATCH 14/27] GotoRelatedAction introduced --- platform/platform-resources/src/idea/LangActions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index fd0f7a10a12c..feac6b0caee0 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -225,7 +225,7 @@ - + From 5622ac85c5e3f629f3add3e313777ced0b3dde1e Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 29 Mar 2011 12:09:25 +0400 Subject: [PATCH 15/27] GotoRelatedAction introduced --- platform/platform-resources/src/idea/LangActions.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index feac6b0caee0..11070fd94846 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -225,7 +225,9 @@ - + + + From 19b6fb0300cce531b6ccb1241fdd50637d6466f5 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 29 Mar 2011 12:30:11 +0400 Subject: [PATCH 16/27] GotoRelatedAction introduced --- ...Action.java => GotoRelatedFileAction.java} | 23 +++++++++++-------- .../src/idea/LangActions.xml | 2 +- 2 files changed, 15 insertions(+), 10 deletions(-) rename platform/lang-impl/src/com/intellij/ide/actions/{GoToRelatedAction.java => GotoRelatedFileAction.java} (94%) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GoToRelatedAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java similarity index 94% rename from platform/lang-impl/src/com/intellij/ide/actions/GoToRelatedAction.java rename to platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java index c18efecf2faf..ed927538c584 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GoToRelatedAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java @@ -35,7 +35,7 @@ import java.util.List; /** * @author Dmitry Avdeev */ -public class GoToRelatedAction extends AnAction { +public class GotoRelatedFileAction extends AnAction { @Override public void actionPerformed(AnActionEvent e) { @@ -45,14 +45,7 @@ public class GoToRelatedAction extends AnAction { PsiFile psiFile = LangDataKeys.PSI_FILE.getData(context); if (editor == null || psiFile == null) return; - PsiElement psiElement = psiFile.findElementAt(editor.getCaretModel().getOffset()); - if (psiElement == null) psiElement = psiFile; - - List items = new ArrayList(); - - for (GotoRelatedProvider provider : Extensions.getExtensions(GotoRelatedProvider.EP_NAME)) { - items.addAll(provider.getItems(psiElement)); - } + List items = getItems(editor, psiFile); if (items.isEmpty()) return; if (items.size() == 1) { items.get(0).navigate(); @@ -78,6 +71,18 @@ public class GoToRelatedAction extends AnAction { .showInBestPositionFor(context); } + public static List getItems(Editor editor, PsiFile psiFile) { + PsiElement psiElement = psiFile.findElementAt(editor.getCaretModel().getOffset()); + if (psiElement == null) psiElement = psiFile; + + List items = new ArrayList(); + + for (GotoRelatedProvider provider : Extensions.getExtensions(GotoRelatedProvider.EP_NAME)) { + items.addAll(provider.getItems(psiElement)); + } + return items; + } + @Override public void update(AnActionEvent e) { e.getPresentation().setEnabled(PlatformDataKeys.EDITOR.getData(e.getDataContext()) != null && diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 11070fd94846..b53b214ad8ae 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -225,7 +225,7 @@ - + From 0e43bd831b1d98dc6a688cddce290c4d37f8c096 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 29 Mar 2011 10:49:59 +0200 Subject: [PATCH 17/27] fix instance methods lookup presentation --- .../codeInsight/completion/JavaMethodCallElement.java | 3 ++- .../intellij/codeInsight/completion/MemberLookupHelper.java | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java index 406addec2c41..65e9f578aee6 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java @@ -234,6 +234,7 @@ public class JavaMethodCallElement extends LookupItem implements Type presentation.setItemTextBold(getAttribute(HIGHLIGHTED_ATTR) != null); MemberLookupHelper helper = myHelper != null ? myHelper : new MemberLookupHelper(myMethod, myContainingClass, false, false); - helper.renderElement(presentation, getAttribute(FORCE_QUALIFY) != null, getSubstitutor()); + final Boolean qualify = getAttribute(FORCE_QUALIFY) != null ? Boolean.TRUE : myHelper == null ? Boolean.FALSE : null; + helper.renderElement(presentation, qualify, getSubstitutor()); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/MemberLookupHelper.java b/java/java-impl/src/com/intellij/codeInsight/completion/MemberLookupHelper.java index c36c9f9c7fd1..afde766917d0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/MemberLookupHelper.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/MemberLookupHelper.java @@ -45,11 +45,11 @@ public class MemberLookupHelper { return myShouldImport; } - public void renderElement(LookupElementPresentation presentation, boolean forceQualify, PsiSubstitutor substitutor) { + public void renderElement(LookupElementPresentation presentation, @Nullable Boolean qualify, PsiSubstitutor substitutor) { final String className = myContainingClass == null ? "???" : myContainingClass.getName(); final String memberName = myMember.getName(); - if (!myShouldImport && StringUtil.isNotEmpty(className) || forceQualify) { + if (!Boolean.FALSE.equals(qualify) && (!myShouldImport && StringUtil.isNotEmpty(className) || Boolean.TRUE.equals(qualify))) { presentation.setItemText(className + "." + memberName); } else { presentation.setItemText(memberName); From d6cc802106631cb8b6cb441e6854479609ad284d Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 29 Mar 2011 13:04:33 +0400 Subject: [PATCH 18/27] @NotNull --- .../src/com/intellij/uiDesigner/binding/FormClassIndex.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormClassIndex.java b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormClassIndex.java index 62c28bbd17e9..4b455f628b75 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormClassIndex.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormClassIndex.java @@ -122,7 +122,7 @@ public class FormClassIndex extends ScalarIndexExtension { }); } - public static List findFormsBoundToClass(PsiClass psiClass) { + public static List findFormsBoundToClass(@NotNull PsiClass psiClass) { String qName = FormReferencesSearcher.getQualifiedName(psiClass); if (qName == null) return Collections.emptyList(); return findFormsBoundToClass(psiClass.getProject(), qName); From bc9e5a29a43e0aa0e5a869a71d63bc17e869fcba Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 29 Mar 2011 13:15:52 +0400 Subject: [PATCH 19/27] GotoRelatedFileAction for forms --- .../navigation/PsiGotoRelatedItem.java | 55 +++++++++++++++++++ plugins/ui-designer/src/META-INF/plugin.xml | 1 + .../binding/FormRelatedFilesProvider.java | 52 ++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 platform/lang-api/src/com/intellij/navigation/PsiGotoRelatedItem.java create mode 100644 plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormRelatedFilesProvider.java diff --git a/platform/lang-api/src/com/intellij/navigation/PsiGotoRelatedItem.java b/platform/lang-api/src/com/intellij/navigation/PsiGotoRelatedItem.java new file mode 100644 index 000000000000..2b3c9e75c151 --- /dev/null +++ b/platform/lang-api/src/com/intellij/navigation/PsiGotoRelatedItem.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2011 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.navigation; + +import com.intellij.psi.NavigatablePsiElement; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +/** + * @author Dmitry Avdeev + */ +public class PsiGotoRelatedItem extends GotoRelatedItem { + + private final NavigatablePsiElement myElement; + + public PsiGotoRelatedItem(@NotNull NavigatablePsiElement element) { + myElement = element; + } + + @Override + public void navigate() { + myElement.navigate(true); + } + + @NotNull + @Override + public String getText() { + return myElement.getName(); + } + + @Override + public Icon getIcon() { + return myElement.getIcon(0); + } + + @Override + public PsiFile getContainingFile() { + return myElement.getContainingFile(); + } +} diff --git a/plugins/ui-designer/src/META-INF/plugin.xml b/plugins/ui-designer/src/META-INF/plugin.xml index 6c1f403e23aa..c14277c05805 100644 --- a/plugins/ui-designer/src/META-INF/plugin.xml +++ b/plugins/ui-designer/src/META-INF/plugin.xml @@ -111,6 +111,7 @@ + diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormRelatedFilesProvider.java b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormRelatedFilesProvider.java new file mode 100644 index 000000000000..46e4dd1a351a --- /dev/null +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormRelatedFilesProvider.java @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2011 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.uiDesigner.binding; + +import com.intellij.navigation.GotoRelatedItem; +import com.intellij.navigation.GotoRelatedProvider; +import com.intellij.navigation.PsiGotoRelatedItem; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +/** + * @author Dmitry Avdeev + */ +public class FormRelatedFilesProvider extends GotoRelatedProvider { + + @NotNull + @Override + public List getItems(PsiElement context) { + PsiClass psiClass = PsiTreeUtil.getParentOfType(context, PsiClass.class, false); + if (psiClass != null) { + List forms = FormClassIndex.findFormsBoundToClass(psiClass); + return ContainerUtil.map(forms, new Function() { + @Override + public GotoRelatedItem fun(PsiFile psiFile) { + return new PsiGotoRelatedItem(psiFile); + } + }); + } + return Collections.emptyList(); + } +} From d22bc305fcc27c173b34cf980137d3caa479d185 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 29 Mar 2011 13:51:40 +0400 Subject: [PATCH 20/27] GotoRelatedFileAction for forms: reverse navigation --- .../ide/actions/GotoRelatedFileAction.java | 12 ++++++---- .../uiDesigner/FormFileTypeFactory.java | 3 ++- .../intellij/uiDesigner/GuiFormFileType.java | 3 +++ .../binding/FormRelatedFilesProvider.java | 23 +++++++++++++++++++ 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java index ed927538c584..1bce641bc154 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java @@ -43,7 +43,7 @@ public class GotoRelatedFileAction extends AnAction { DataContext context = e.getDataContext(); Editor editor = PlatformDataKeys.EDITOR.getData(context); PsiFile psiFile = LangDataKeys.PSI_FILE.getData(context); - if (editor == null || psiFile == null) return; + if (psiFile == null) return; List items = getItems(editor, psiFile); if (items.isEmpty()) return; @@ -72,8 +72,11 @@ public class GotoRelatedFileAction extends AnAction { } public static List getItems(Editor editor, PsiFile psiFile) { - PsiElement psiElement = psiFile.findElementAt(editor.getCaretModel().getOffset()); - if (psiElement == null) psiElement = psiFile; + + PsiElement psiElement = psiFile; + if (editor != null) { + psiElement = psiFile.findElementAt(editor.getCaretModel().getOffset()); + } List items = new ArrayList(); @@ -85,8 +88,7 @@ public class GotoRelatedFileAction extends AnAction { @Override public void update(AnActionEvent e) { - e.getPresentation().setEnabled(PlatformDataKeys.EDITOR.getData(e.getDataContext()) != null && - LangDataKeys.PSI_FILE.getData(e.getDataContext()) != null); + e.getPresentation().setEnabled(LangDataKeys.PSI_FILE.getData(e.getDataContext()) != null); } private static class ItemCellRenderer extends JPanel implements ListCellRenderer { diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/FormFileTypeFactory.java b/plugins/ui-designer/src/com/intellij/uiDesigner/FormFileTypeFactory.java index bb36249ac376..c360a994332e 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/FormFileTypeFactory.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/FormFileTypeFactory.java @@ -23,7 +23,8 @@ import org.jetbrains.annotations.NotNull; * @author yole */ public class FormFileTypeFactory extends FileTypeFactory { + public void createFileTypes(@NotNull FileTypeConsumer consumer) { - consumer.consume(new GuiFormFileType(), GuiFormFileType.DEFAULT_EXTENSION); + consumer.consume(GuiFormFileType.INSTANCE); } } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/GuiFormFileType.java b/plugins/ui-designer/src/com/intellij/uiDesigner/GuiFormFileType.java index 5d6d1b5dd50d..9d9693ed5d55 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/GuiFormFileType.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/GuiFormFileType.java @@ -26,6 +26,9 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; public class GuiFormFileType implements FileType { + + public static final GuiFormFileType INSTANCE = new GuiFormFileType(); + @NonNls public static final String DEFAULT_EXTENSION = "form"; @NonNls public static final String DOT_DEFAULT_EXTENSION = "." + DEFAULT_EXTENSION; diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormRelatedFilesProvider.java b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormRelatedFilesProvider.java index 46e4dd1a351a..6723d414c4ba 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormRelatedFilesProvider.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormRelatedFilesProvider.java @@ -18,10 +18,15 @@ package com.intellij.uiDesigner.binding; import com.intellij.navigation.GotoRelatedItem; import com.intellij.navigation.GotoRelatedProvider; import com.intellij.navigation.PsiGotoRelatedItem; +import com.intellij.openapi.project.Project; +import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.uiDesigner.GuiFormFileType; +import com.intellij.uiDesigner.compiler.Utils; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -47,6 +52,24 @@ public class FormRelatedFilesProvider extends GotoRelatedProvider { } }); } + else { + PsiFile file = context.getContainingFile(); + if (file.getFileType() == GuiFormFileType.INSTANCE) { + try { + String className = Utils.getBoundClassName(file.getText()); + if (className != null) { + Project project = file.getProject(); + PsiClass aClass = JavaPsiFacade.getInstance(project).findClass(className, GlobalSearchScope.allScope(project)); + if (aClass != null) { + return Collections.singletonList(new PsiGotoRelatedItem(aClass)); + } + } + } + catch (Exception ignore) { + + } + } + } return Collections.emptyList(); } } From e2c9ac7abf9409f7dbc4fd985f159834d89f526a Mon Sep 17 00:00:00 2001 From: irengrig Date: Tue, 29 Mar 2011 13:49:01 +0400 Subject: [PATCH 21/27] IDEA-67198 VCS: Show file history action update() should be optimized --- .../vcs/actions/TabbedShowHistoryAction.java | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/TabbedShowHistoryAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/TabbedShowHistoryAction.java index 35e5e509e084..464a5d90c1a4 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/TabbedShowHistoryAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/TabbedShowHistoryAction.java @@ -22,16 +22,16 @@ import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.history.VcsHistoryProvider; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.Nullable; import java.io.File; -import java.util.ArrayList; public class TabbedShowHistoryAction extends AbstractVcsAction { protected void update(VcsContext context, Presentation presentation) { presentation.setEnabled(isEnabled(context)); final Project project = context.getProject(); - presentation.setVisible(project != null && ProjectLevelVcsManager.getInstance(project).getAllActiveVcss().length > 0); + presentation.setVisible(project != null && ProjectLevelVcsManager.getInstance(project).hasActiveVcss()); } protected VcsHistoryProvider getProvider(AbstractVcs activeVcs) { @@ -39,50 +39,51 @@ public class TabbedShowHistoryAction extends AbstractVcsAction { } protected boolean isEnabled(VcsContext context) { - FilePath[] selectedFiles = getSelectedFiles(context); - if (selectedFiles == null) return false; - if (selectedFiles.length != 1) return false; - FilePath path = selectedFiles[0]; + FilePath selectedFile = getSelectedFileOrNull(context); + if (selectedFile == null) return false; Project project = context.getProject(); if (project == null) return false; - VirtualFile someVFile = path.getVirtualFile() != null ? path.getVirtualFile() : path.getVirtualFileParent(); + VirtualFile someVFile = selectedFile.getVirtualFile() != null ? + selectedFile.getVirtualFile() : selectedFile.getVirtualFileParent(); AbstractVcs vcs = ProjectLevelVcsManager.getInstance(project).getVcsFor(someVFile); if (vcs == null) return false; VcsHistoryProvider vcsHistoryProvider = getProvider(vcs); if (vcsHistoryProvider == null) return false; - if (selectedFiles[0].isDirectory() && (! vcsHistoryProvider.supportsHistoryForDirectories())) return false; + if (selectedFile.isDirectory() && (! vcsHistoryProvider.supportsHistoryForDirectories())) return false; final FileStatus fileStatus = FileStatusManager.getInstance(project).getStatus(someVFile); return fileStatus != FileStatus.ADDED && fileStatus != FileStatus.UNKNOWN && fileStatus != FileStatus.IGNORED; } - protected static FilePath[] getSelectedFiles(VcsContext context) { - ArrayList result = new ArrayList(); + @Nullable + protected static FilePath getSelectedFileOrNull(VcsContext context) { + FilePath result = null; VirtualFile[] virtualFileArray = context.getSelectedFiles(); if (virtualFileArray != null) { - for (VirtualFile virtualFile : virtualFileArray) { - result.add(new FilePathImpl(virtualFile)); + if (virtualFileArray.length > 1) return null; + if (virtualFileArray.length > 0) { + result = new FilePathImpl(virtualFileArray[0]); } } File[] fileArray = context.getSelectedIOFiles(); - if (fileArray != null) { + if (fileArray != null && fileArray.length > 0) { for (File file : fileArray) { final File parentIoFile = file.getParentFile(); if (parentIoFile == null) continue; final VirtualFile parent = LocalFileSystem.getInstance().findFileByIoFile(parentIoFile); if (parent != null) { final FilePathImpl child = new FilePathImpl(parent, file.getName(), false); - if (! result.contains(child)) { - result.add(child); - } + if (result != null) return null; + result = child; } } } - return result.toArray(new FilePath[result.size()]); + return result; } protected void actionPerformed(VcsContext context) { - FilePath path = getSelectedFiles(context)[0]; + FilePath path = getSelectedFileOrNull(context); + if (path == null) return; Project project = context.getProject(); VirtualFile someVFile = path.getVirtualFile() != null ? path.getVirtualFile() : path.getVirtualFileParent(); AbstractVcs activeVcs = ProjectLevelVcsManager.getInstance(project).getVcsFor(someVFile); From c0769d63fedbdfa5a84d74133b16aa2d03370cb8 Mon Sep 17 00:00:00 2001 From: irengrig Date: Tue, 29 Mar 2011 13:55:39 +0400 Subject: [PATCH 22/27] IDEA-67200 Git changes provider could be optimized --- plugins/git4idea/src/git4idea/changes/ChangeCollector.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/git4idea/src/git4idea/changes/ChangeCollector.java b/plugins/git4idea/src/git4idea/changes/ChangeCollector.java index 5d58bae6ad21..57e76e96ea1d 100644 --- a/plugins/git4idea/src/git4idea/changes/ChangeCollector.java +++ b/plugins/git4idea/src/git4idea/changes/ChangeCollector.java @@ -24,6 +24,7 @@ import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.ContentRevision; import com.intellij.openapi.vcs.changes.VcsDirtyScope; +import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.vcsUtil.VcsUtil; import git4idea.GitContentRevision; @@ -190,6 +191,10 @@ class ChangeCollector { */ private static boolean isAncestor(FilePath parentCandidate, FilePath childCandidate, boolean strict) { try { + if (childCandidate.getPath().length() < parentCandidate.getPath().length()) return false; + if (childCandidate.getVirtualFile() != null && parentCandidate.getVirtualFile() != null) { + return VfsUtil.isAncestor(parentCandidate.getVirtualFile(), childCandidate.getVirtualFile(), strict); + } return FileUtil.isAncestor(parentCandidate.getIOFile(), childCandidate.getIOFile(), strict); } catch (IOException e) { From 9154af274372ce21385912e1649ce0d9677074f4 Mon Sep 17 00:00:00 2001 From: Oleg Shpynov Date: Tue, 29 Mar 2011 14:36:03 +0400 Subject: [PATCH 23/27] IDEA-67156 GitHub integration does not allow to manually type in project and does not show organization's projects --- .../github/GithubCheckoutProvider.java | 20 ++++- .../plugins/github/GithubRebaseAction.java | 2 +- .../jetbrains/plugins/github/GithubUtil.java | 8 +- .../plugins/github/RepositoryInfo.java | 4 + .../plugins/github/UnknownRepositoryInfo.java | 52 ++++++++++++ .../github/ui/GithubCloneProjectDialog.java | 25 +++++- .../github/ui/GithubCloneProjectPane.form | 14 ++-- .../github/ui/GithubCloneProjectPane.java | 81 ++++++++++++------- 8 files changed, 160 insertions(+), 46 deletions(-) create mode 100644 plugins/github/src/org/jetbrains/plugins/github/UnknownRepositoryInfo.java diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubCheckoutProvider.java b/plugins/github/src/org/jetbrains/plugins/github/GithubCheckoutProvider.java index a1157119cba0..7c3912506457 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubCheckoutProvider.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubCheckoutProvider.java @@ -19,6 +19,7 @@ import com.intellij.ide.GeneralSettings; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.vcs.CheckoutProvider; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; @@ -82,21 +83,32 @@ public class GithubCheckoutProvider implements CheckoutProvider { } // All the preliminary work is already done, go and clone the selected repository! - final RepositoryInfo selectedRepository = checkoutDialog.getSelectedRepository(); + RepositoryInfo selectedRepository = checkoutDialog.getSelectedRepository(); + // Check if selected repository exists + final String owner = selectedRepository.getOwner(); + final String name = selectedRepository.getName(); + if (selectedRepository instanceof UnknownRepositoryInfo) { + selectedRepository = GithubUtil.getDetailedRepositoryInfo(project, owner, name); + } + if (selectedRepository == null){ + Messages.showErrorDialog(project, "Selected repository ''" + owner +"/" + name + "'' doesn't exist.", "Cannot clone repository"); + return; + } + final boolean writeAccessAllowed = GithubUtil.isWriteAccessAllowed(project, selectedRepository); if (!writeAccessAllowed){ Messages.showErrorDialog(project, "It seems that you have only read access to the selected repository.\n" + "GitHub supports only https protocol for readonly access, which is not supported yet.\n" + "As a workaround, please fork it and clone your forked repository instead.\n" + - "More details are available here: http://youtrack.jetbrains.net/issue/IDEA-55298", "Cannot clone this repository"); + "More details are available here: http://youtrack.jetbrains.net/issue/IDEA-55298", "Cannot clone repository"); return; } final String host = writeAccessAllowed ? "git@" + settings.getHost() + ":" : "https://github.com" + settings.getHost() + "/"; final String selectedPath = checkoutDialog.getSelectedPath(); final VirtualFile selectedPathFile = LocalFileSystem.getInstance().findFileByPath(selectedPath); final String projectName = checkoutDialog.getProjectName(); - final String repositoryName = selectedRepository.getName(); - final String repositoryOwner = selectedRepository.getOwner(); + final String repositoryName = name; + final String repositoryOwner = owner; final String checkoutUrl = host + repositoryOwner + "/" + repositoryName + ".git"; GitCheckoutProvider.checkout(project, listener, selectedPathFile, checkoutUrl, projectName, "origin", selectedPath); } diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java index 7541ad618ce2..8ffcbce46d96 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java @@ -106,7 +106,7 @@ public class GithubRebaseAction extends DumbAwareAction { repoName = repoName.substring(0, repoName.length() - 4); } - final RepositoryInfo repositoryInfo = GithubUtil.getDetailedRepositoryInfo(project, repoName); + final RepositoryInfo repositoryInfo = GithubUtil.getDetailedRepositoryInfo(project, login, repoName); if (repositoryInfo == null) { Messages .showErrorDialog(project, "Github repository doesn't seem to be your own repository: " + pushUrl, CANNOT_PERFORM_GITHUB_REBASE); diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java index fec480c3eb79..e87089f1e35f 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java @@ -182,9 +182,9 @@ public class GithubUtil { } @Nullable - public static RepositoryInfo getDetailedRepoInfo(final String url, final String login, final String password, final String name) { + public static RepositoryInfo getDetailedRepoInfo(final String url, final String login, final String password, final String owner, final String name) { try { - final String request = "/repos/show/" + login + "/" + name; + final String request = "/repos/show/" + owner + "/" + name; final HttpMethod method = doREST(url, login, password, request, false); final InputStream stream = method.getResponseBodyAsStream(); final Element element = new SAXBuilder(false).build(stream).getRootElement(); @@ -302,7 +302,7 @@ public class GithubUtil { * @return */ @Nullable - public static RepositoryInfo getDetailedRepositoryInfo(final Project project, final String name) { + public static RepositoryInfo getDetailedRepositoryInfo(final Project project, final String owner, final String name) { final GithubSettings settings = GithubSettings.getInstance(); final boolean validCredentials; try { @@ -330,7 +330,7 @@ public class GithubUtil { @Override public RepositoryInfo compute() { ProgressManager.getInstance().getProgressIndicator().setText("Extracting detailed info about repository ''" + name + "''"); - return getDetailedRepoInfo(settings.getHost(), settings.getLogin(), settings.getPassword(), name); + return getDetailedRepoInfo(settings.getHost(), settings.getLogin(), settings.getPassword(), owner, name); } }); } diff --git a/plugins/github/src/org/jetbrains/plugins/github/RepositoryInfo.java b/plugins/github/src/org/jetbrains/plugins/github/RepositoryInfo.java index 7d33bf5975e0..947e236f6529 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/RepositoryInfo.java +++ b/plugins/github/src/org/jetbrains/plugins/github/RepositoryInfo.java @@ -30,6 +30,10 @@ public class RepositoryInfo { return myRepository.getChildText("parent"); } + public String getId() { + return getOwner() + "/" + getName(); + } + @Override public boolean equals(Object obj) { if (!(obj instanceof RepositoryInfo)){ diff --git a/plugins/github/src/org/jetbrains/plugins/github/UnknownRepositoryInfo.java b/plugins/github/src/org/jetbrains/plugins/github/UnknownRepositoryInfo.java new file mode 100644 index 000000000000..afe76ce5dbca --- /dev/null +++ b/plugins/github/src/org/jetbrains/plugins/github/UnknownRepositoryInfo.java @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2011 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.github; + +/** +* @author oleg +*/ +public class UnknownRepositoryInfo extends RepositoryInfo { + private final String myId; + private final String myName; + private final String myOwner; + + public UnknownRepositoryInfo(final String id) { + super(null); + myId = id; + myName = myId.substring(myId.lastIndexOf('/') + 1); + myOwner = myId.substring(0, myId.lastIndexOf('/')); + } + + public String getName() { + return myName; + } + + public String getOwner() { + return myOwner; + } + + public boolean isFork() { + throw new UnsupportedOperationException("UnknownRepositoryInfo#isFork() shouldn't be called"); + } + + public String getParent() { + throw new UnsupportedOperationException("UnknownRepositoryInfo#isFork() shouldn't be called"); + } + + public String getId() { + return myId; + } +} diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCloneProjectDialog.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCloneProjectDialog.java index eb8fdc7d604f..8de8fc2c2110 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCloneProjectDialog.java +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCloneProjectDialog.java @@ -4,9 +4,14 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.HashMap; +import org.intellij.lang.annotations.Pattern; import org.jetbrains.plugins.github.RepositoryInfo; +import org.jetbrains.plugins.github.UnknownRepositoryInfo; import javax.swing.*; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -14,14 +19,22 @@ import java.util.List; */ public class GithubCloneProjectDialog extends DialogWrapper { + private static final java.util.regex.Pattern PATTERN = java.util.regex.Pattern.compile("[\\w\\d-_]+/[\\w\\d-_]+"); private GithubCloneProjectPane myGithubCloneProjectPane; + private HashMap myRepositoryInfoHashMap; public GithubCloneProjectDialog(final Project project, final List repos) { super(project, true); myGithubCloneProjectPane = new GithubCloneProjectPane(this); setTitle("Select repository to clone"); setOKButtonText("Clone"); - myGithubCloneProjectPane.setAvailableRepos(repos); + myRepositoryInfoHashMap = new HashMap(); + for (RepositoryInfo repo : repos) { + myRepositoryInfoHashMap.put(repo.getId(), repo); + } + final ArrayList ids = new ArrayList(myRepositoryInfoHashMap.keySet()); + Collections.sort(ids); + myGithubCloneProjectPane.setAvailableRepos(ids); init(); setOKActionEnabled(false); } @@ -46,8 +59,9 @@ public class GithubCloneProjectDialog extends DialogWrapper { } public void updateOkButton() { - if (getSelectedRepository() == null){ - setErrorText("No repository selected"); + final String selectedRepositoryId = getSelectedRepositoryId(); + if (!PATTERN.matcher(selectedRepositoryId).matches()){ + setErrorText("Wrong repository format. owner/repository expected"); setOKActionEnabled(false); return; } @@ -79,6 +93,11 @@ public class GithubCloneProjectDialog extends DialogWrapper { } public RepositoryInfo getSelectedRepository() { + final String id = getSelectedRepositoryId(); + return myRepositoryInfoHashMap.containsKey(id) ? myRepositoryInfoHashMap.get(id) : new UnknownRepositoryInfo(id); + } + + private String getSelectedRepositoryId() { return myGithubCloneProjectPane.getSelectedRepository(); } diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCloneProjectPane.form b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCloneProjectPane.form index 4b43f7674fc2..f9f124dd7709 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCloneProjectPane.form +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCloneProjectPane.form @@ -3,7 +3,7 @@ - + @@ -32,12 +32,6 @@ - - - - - - @@ -60,6 +54,12 @@ + + + + + + diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCloneProjectPane.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCloneProjectPane.java index 5052c447033b..35bf8e204570 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCloneProjectPane.java +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCloneProjectPane.java @@ -1,11 +1,20 @@ package org.jetbrains.plugins.github.ui; import com.intellij.ide.ui.ListCellRendererWrapper; +import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.FileTypes; +import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.EditorComboBoxEditor; +import com.intellij.ui.EditorComboBoxRenderer; +import com.intellij.ui.EditorTextField; +import com.intellij.ui.StringComboboxEditor; import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; import org.jetbrains.annotations.Nullable; @@ -26,31 +35,31 @@ import java.util.List; */ public class GithubCloneProjectPane { private JPanel myPanel; - private JComboBox mySelectRepositoryComboBox; private TextFieldWithBrowseButton myTextFieldWithBrowseButton; private JTextField myProjectNameText; + private ComboBox myRepositoryComboBox; private final GithubCloneProjectDialog myDialog; public GithubCloneProjectPane(final GithubCloneProjectDialog dialog) { myDialog = dialog; - mySelectRepositoryComboBox.setRenderer(new ListCellRendererWrapper(mySelectRepositoryComboBox.getRenderer()){ - @Override - public void customize(final JList list, final RepositoryInfo value, final int index, final boolean selected, final boolean cellHasFocus) { - setText(value.getOwner() + "/" + value.getName()); - } - }); - mySelectRepositoryComboBox.addItemListener(new ItemListener() { - @Override - public void itemStateChanged(final ItemEvent e) { - final RepositoryInfo repositoryInfo = (RepositoryInfo)e.getItem(); - if (repositoryInfo != null) { - myProjectNameText.setText(repositoryInfo.getName()); - myDialog.updateOkButton(); + final EditorComboBoxEditor comboEditor = new StringComboboxEditor(ProjectManager.getInstance().getDefaultProject(), FileTypes.PLAIN_TEXT, myRepositoryComboBox); + myRepositoryComboBox.setEditor(comboEditor); + ((EditorTextField) comboEditor.getEditorComponent()).addDocumentListener( + new DocumentAdapter() { + @Override + public void beforeDocumentChange(final com.intellij.openapi.editor.event.DocumentEvent e) { + updateControls(); } - } - }); - final DocumentListener updateOkButtonListener = new DocumentListener() { + @Override + public void documentChanged(final com.intellij.openapi.editor.event.DocumentEvent e) { + updateControls(); + } + }); + myRepositoryComboBox.setRenderer(new EditorComboBoxRenderer(comboEditor)); + myRepositoryComboBox.setEditable(true); + + myProjectNameText.getDocument().addDocumentListener(new DocumentListener() { // update Ok button state depending on the current state of the fields public void insertUpdate(final DocumentEvent e) { myDialog.updateOkButton(); @@ -63,9 +72,21 @@ public class GithubCloneProjectPane { public void changedUpdate(final DocumentEvent e) { myDialog.updateOkButton(); } - }; - myProjectNameText.getDocument().addDocumentListener(updateOkButtonListener); - myTextFieldWithBrowseButton.getChildComponent().getDocument().addDocumentListener(updateOkButtonListener); + }); + myTextFieldWithBrowseButton.getChildComponent().getDocument().addDocumentListener(new DocumentListener() { + // update Ok button state depending on the current state of the fields + public void insertUpdate(final DocumentEvent e) { + myDialog.updateOkButton(); + } + + public void removeUpdate(final DocumentEvent e) { + myDialog.updateOkButton(); + } + + public void changedUpdate(final DocumentEvent e) { + myDialog.updateOkButton(); + } + }); } public JComponent getPanel() { @@ -73,11 +94,11 @@ public class GithubCloneProjectPane { } public JComponent getPreferrableFocusComponent() { - return mySelectRepositoryComboBox; + return myRepositoryComboBox; } - public RepositoryInfo getSelectedRepository(){ - return (RepositoryInfo) mySelectRepositoryComboBox.getModel().getSelectedItem(); + public String getSelectedRepository(){ + return (String) myRepositoryComboBox.getEditor().getItem(); } public String getSelectedPath(){ @@ -120,12 +141,18 @@ public class GithubCloneProjectPane { }); } - public void setAvailableRepos(final List repos) { - mySelectRepositoryComboBox.setModel(new DefaultComboBoxModel(ArrayUtil.toObjectArray(repos))); - final RepositoryInfo preselectedRepository = (RepositoryInfo)mySelectRepositoryComboBox.getSelectedItem(); + public void setAvailableRepos(final List repos) { + myRepositoryComboBox.setModel(new DefaultComboBoxModel(ArrayUtil.toObjectArray(repos))); + updateControls(); + } + + private void updateControls() { + final String preselectedRepository = (String)myRepositoryComboBox.getEditor().getItem(); if (preselectedRepository != null) { - myProjectNameText.setText(preselectedRepository.getName()); + final int i = preselectedRepository.lastIndexOf('/'); + myProjectNameText.setText(i != -1 ? preselectedRepository.substring(i + 1) : ""); } + myDialog.updateOkButton(); } public void setSelectedPath(final String path) { From 290502e38770fb82950814ef49f8f597d2df731f Mon Sep 17 00:00:00 2001 From: Oleg Shpynov Date: Tue, 29 Mar 2011 14:51:15 +0400 Subject: [PATCH 24/27] Do not sort twice --- .../jetbrains/plugins/github/ui/GithubCloneProjectDialog.java | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCloneProjectDialog.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCloneProjectDialog.java index 8de8fc2c2110..cf2f38816d66 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCloneProjectDialog.java +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCloneProjectDialog.java @@ -33,7 +33,6 @@ public class GithubCloneProjectDialog extends DialogWrapper { myRepositoryInfoHashMap.put(repo.getId(), repo); } final ArrayList ids = new ArrayList(myRepositoryInfoHashMap.keySet()); - Collections.sort(ids); myGithubCloneProjectPane.setAvailableRepos(ids); init(); setOKActionEnabled(false); From 174336236453295b1a96830974e8ba1f8ad982c5 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 29 Mar 2011 12:55:15 +0200 Subject: [PATCH 25/27] don't walk cached super methods more than once (red field.getName() problem) make raw method substitutor apply only to this method --- .../intellij/psi/impl/PsiClassImplUtil.java | 251 +++++++++--------- .../MultipleInheritancePathsToMethod.java | 20 ++ .../psi/resolve/ResolveMethodTest.java | 10 + 3 files changed, 156 insertions(+), 125 deletions(-) create mode 100644 java/java-tests/testData/psi/resolve/method/MultipleInheritancePathsToMethod.java diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java b/java/java-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java index 247e5fdaf429..34e6ae81765c 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java @@ -57,7 +57,6 @@ import java.util.*; */ public class PsiClassImplUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiClassImplUtil"); - private static final Key NAME_MAPS_BUILT_FLAG = Key.create("NAME_MAPS_BUILT_FLAG"); private static final Key> MAP_IN_CLASS_KEY = Key.create("MAP_KEY"); @@ -102,35 +101,6 @@ public class PsiClassImplUtil { final PsiMethod patternMethod, final boolean checkBases, final boolean stopOnFirst) { -/* final MethodSignature patternSignature = MethodSignatureBackedByPsiMethod.create(patternMethod, PsiSubstitutor.EMPTY); - if (!checkBases) { - final PsiMethod[] methodsByName = aClass.findMethodsByName(patternMethod.getName(), false); - if (methodsByName.length == 0) return PsiMethod.EMPTY_ARRAY; - List result = new ArrayList(); - for (PsiMethod method : methodsByName) { - final MethodSignature otherSignature = method.getSignature(PsiSubstitutor.EMPTY); - if (otherSignature.equals(patternSignature)) { - result.add(method); - if (stopOnFirst) break; - } - } - - return result.toArray(new PsiMethod[result.size()]); - } - else { - final Set signatures = getOverrideEquivalentSignatures(aClass); - final HierarchicalMethodSignature signatureWithSupers = signatures.get(patternSignature); - if (signatureWithSupers == null) return PsiMethod.EMPTY_ARRAY; - final List result = new ArrayList(); - MethodSignatureUtil.processMethodHierarchy(signatureWithSupers, new Processor() { - public boolean process(final HierarchicalMethodSignature sig) { - result.add(sig.getSignature().getMethod()); - return !stopOnFirst; - } - }); - return result.toArray(new PsiMethod[result.size()]); - }*/ - final PsiMethod[] methodsByName = aClass.findMethodsByName(patternMethod.getName(), checkBases); if (methodsByName.length == 0) return Collections.emptyList(); final List methods = new SmartList(); @@ -238,14 +208,12 @@ public class PsiClassImplUtil { } } }; - PsiElementFactory factory = JavaPsiFacade.getInstance(psiClass.getProject()).getElementFactory(); - processDeclarationsInClassNotCached(psiClass, processor, ResolveState.initial(), new THashSet(), null, psiClass, false, factory); + processDeclarationsInClassNotCached(psiClass, processor, ResolveState.initial(), new THashSet(), null, psiClass, false); Map, Map>>> result = new HashMap, Map>>>(3); result.put(PsiClass.class, generateMapByList(classes)); result.put(PsiMethod.class, generateMapByList(methods)); result.put(PsiField.class, generateMapByList(fields)); - psiClass.putUserData(NAME_MAPS_BUILT_FLAG, Boolean.TRUE); return result; } @@ -275,6 +243,12 @@ public class PsiClassImplUtil { value = ((UserDataHolderEx)aClass).putUserDataIfAbsent(MAP_IN_CLASS_KEY, value); } } + return getCachedMembers(value, memberClazz); + } + + private static Map>> getCachedMembers(CachedValue value, + Class memberClazz) { + //noinspection unchecked return (Map>>)value.getValue().get(memberClazz); } @@ -308,7 +282,7 @@ public class PsiClassImplUtil { } } - private static final Function FULL_ICON_EVALUATOR = new Function() { + private static final Function FULL_ICON_EVALUATOR = new NullableFunction() { public Icon fun(ClassIconRequest r) { if (!r.psiClass.isValid() || r.psiClass.getProject().isDisposed()) return null; @@ -406,112 +380,140 @@ public class PsiClassImplUtil { PsiElement last, PsiElement place, boolean isRaw) { + if (last instanceof PsiTypeParameterList || last instanceof PsiModifierList) return true; //TypeParameterList and ModifierList do not see our declarations if (visited != null && visited.contains(aClass)) return true; + PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY); isRaw = isRaw || PsiUtil.isRawSubstitutor(aClass, substitutor); - if (last instanceof PsiTypeParameterList || last instanceof PsiModifierList) return true; //TypeParameterList and ModifierList do not see our declarations - final Boolean built = aClass.getUserData(NAME_MAPS_BUILT_FLAG); - PsiElementFactory factory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory(); - if (built == null) { - return processDeclarationsInClassNotCached(aClass, processor, state, visited, last, place, isRaw, factory); - } - final NameHint nameHint = processor.getHint(NameHint.KEY); + CachedValue cache = aClass.getUserData(MAP_IN_CLASS_KEY); + if (cache != null && cache.hasUpToDateValue()) { + final NameHint nameHint = processor.getHint(NameHint.KEY); + if (nameHint != null) { + return processCachedMembersByName(aClass, processor, state, visited, last, place, isRaw, substitutor, cache, nameHint); + } + } + return processDeclarationsInClassNotCached(aClass, processor, state, visited, last, place, isRaw); + } + + private static boolean processCachedMembersByName(PsiClass aClass, + PsiScopeProcessor processor, + ResolveState state, + Set visited, + PsiElement last, + PsiElement place, + boolean isRaw, + PsiSubstitutor substitutor, + CachedValue cache, NameHint nameHint) { final ElementClassHint classHint = processor.getHint(ElementClassHint.KEY); - if (nameHint != null) { - if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.FIELD)) { - final PsiField fieldByName = aClass.findFieldByName(nameHint.getName(state), false); - if (fieldByName != null) { - processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, aClass); - if (!processor.execute(fieldByName, state)) return false; - } - else { - final Map>> allFieldsMap = getMap(aClass, PsiField.class); + PsiElementFactory factory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory(); - final List> list = allFieldsMap.get(nameHint.getName(state)); - if (list != null) { - for (final Pair candidate : list) { - PsiField candidateField = candidate.getFirst(); - PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor(candidateField.getContainingClass(), candidate.getSecond(), aClass, - substitutor, place, factory); + if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.FIELD)) { + final PsiField fieldByName = aClass.findFieldByName(nameHint.getName(state), false); + if (fieldByName != null) { + processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, aClass); + if (!processor.execute(fieldByName, state)) return false; + } + else { + final Map>> allFieldsMap = getCachedMembers(cache, PsiField.class); - processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, candidateField.getContainingClass()); - if (!processor.execute(candidateField, state.put(PsiSubstitutor.KEY, finalSubstitutor))) return false; - } + final List> list = allFieldsMap.get(nameHint.getName(state)); + if (list != null) { + for (final Pair candidate : list) { + PsiField candidateField = candidate.getFirst(); + PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor(candidateField.getContainingClass(), candidate.getSecond(), aClass, + substitutor, place, factory); + + processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, candidateField.getContainingClass()); + if (!processor.execute(candidateField, state.put(PsiSubstitutor.KEY, finalSubstitutor))) return false; } } } - if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.CLASS)) { - if (last != null && last.getParent() == aClass) { - if (last instanceof PsiClass) { - if (!processor.execute(last, state)) return false; - } - // Parameters - final PsiTypeParameterList list = aClass.getTypeParameterList(); - if (list != null && !list.processDeclarations(processor, state, last, place)) return false; + } + if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.CLASS)) { + if (last != null && last.getParent() == aClass) { + if (last instanceof PsiClass) { + if (!processor.execute(last, state)) return false; } - if (!(last instanceof PsiReferenceList)) { - final PsiClass classByName = aClass.findInnerClassByName(nameHint.getName(state), false); - if (classByName != null) { - processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, aClass); - if (!processor.execute(classByName, state)) return false; - } - else { - final Map>> allClassesMap = getMap(aClass, PsiClass.class); + // Parameters + final PsiTypeParameterList list = aClass.getTypeParameterList(); + if (list != null && !list.processDeclarations(processor, state, last, place)) return false; + } + if (!(last instanceof PsiReferenceList)) { + final PsiClass classByName = aClass.findInnerClassByName(nameHint.getName(state), false); + if (classByName != null) { + processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, aClass); + if (!processor.execute(classByName, state)) return false; + } + else { + final Map>> allClassesMap = getCachedMembers(cache, PsiClass.class); - final List> list = allClassesMap.get(nameHint.getName(state)); - if (list != null) { - for (final Pair candidate : list) { - final PsiClass inner = candidate.getFirst(); - final PsiClass containingClass = inner.getContainingClass(); - if (containingClass != null) { - PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor(containingClass, candidate.getSecond(), aClass, - substitutor, place, factory); - processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, containingClass); - if (!processor.execute(inner, state.put(PsiSubstitutor.KEY, finalSubstitutor))) return false; - } + final List> list = allClassesMap.get(nameHint.getName(state)); + if (list != null) { + for (final Pair candidate : list) { + final PsiClass inner = candidate.getFirst(); + final PsiClass containingClass = inner.getContainingClass(); + if (containingClass != null) { + PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor(containingClass, candidate.getSecond(), aClass, + substitutor, place, factory); + processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, containingClass); + if (!processor.execute(inner, state.put(PsiSubstitutor.KEY, finalSubstitutor))) return false; } } } } } - if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD)) { - if (processor instanceof MethodResolverProcessor) { - final MethodResolverProcessor methodResolverProcessor = (MethodResolverProcessor)processor; - if (methodResolverProcessor.isConstructor()) { - final PsiMethod[] constructors = aClass.getConstructors(); - methodResolverProcessor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, aClass); - for (PsiMethod constructor : constructors) { - if (!methodResolverProcessor.execute(constructor, state)) return false; - } - return true; - } - } - final Map>> allMethodsMap = getMap(aClass, PsiMethod.class); - final List> list = allMethodsMap.get(nameHint.getName(state)); - if (list != null) { - for (final Pair candidate : list) { - PsiMethod candidateMethod = candidate.getFirst(); - if (processor instanceof MethodResolverProcessor) { - if (candidateMethod.isConstructor() != ((MethodResolverProcessor)processor).isConstructor()) continue; - } - final PsiClass containingClass = candidateMethod.getContainingClass(); - PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor(containingClass, candidate.getSecond(), aClass, - substitutor, place, factory); - if (isRaw && !candidateMethod.hasModifierProperty(PsiModifier.STATIC)) { //static methods are not erased due to raw overriding - PsiTypeParameter[] methodTypeParameters = candidateMethod.getTypeParameters(); - finalSubstitutor = factory.createRawSubstitutor(finalSubstitutor, methodTypeParameters); - } - processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, containingClass); - if (!processor.execute(candidateMethod, state.put(PsiSubstitutor.KEY, finalSubstitutor))) return false; + } + if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD)) { + if (processor instanceof MethodResolverProcessor) { + final MethodResolverProcessor methodResolverProcessor = (MethodResolverProcessor)processor; + if (methodResolverProcessor.isConstructor()) { + final PsiMethod[] constructors = aClass.getConstructors(); + methodResolverProcessor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, aClass); + for (PsiMethod constructor : constructors) { + if (!methodResolverProcessor.execute(constructor, state)) return false; } + return true; } } - return true; + final Map>> allMethodsMap = getCachedMembers(cache, PsiMethod.class); + final List> list = allMethodsMap.get(nameHint.getName(state)); + if (list != null) { + for (final Pair candidate : list) { + PsiMethod candidateMethod = candidate.getFirst(); + if (processor instanceof MethodResolverProcessor) { + if (candidateMethod.isConstructor() != ((MethodResolverProcessor)processor).isConstructor()) continue; + } + final PsiClass containingClass = candidateMethod.getContainingClass(); + if (visited != null && visited.contains(candidateMethod.getContainingClass())) { + continue; + } + + PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor(containingClass, candidate.getSecond(), aClass, + substitutor, place, factory); + finalSubstitutor = checkRaw(isRaw, factory, candidateMethod, finalSubstitutor); + processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, containingClass); + if (!processor.execute(candidateMethod, state.put(PsiSubstitutor.KEY, finalSubstitutor))) return false; + } + + if (visited != null) { + for (Pair aList : list) { + visited.add(aList.getFirst().getContainingClass()); + } + } + + } + } + return true; } - return processDeclarationsInClassNotCached(aClass, processor, state, visited, last, place, isRaw, factory); + private static PsiSubstitutor checkRaw(boolean isRaw, PsiElementFactory factory, PsiMethod candidateMethod, PsiSubstitutor substitutor) { + if (isRaw && !candidateMethod.hasModifierProperty(PsiModifier.STATIC)) { //static methods are not erased due to raw overriding + PsiTypeParameter[] methodTypeParameters = candidateMethod.getTypeParameters(); + substitutor = factory.createRawSubstitutor(substitutor, methodTypeParameters); + } + return substitutor; } public static PsiSubstitutor obtainFinalSubstitutor(@NotNull PsiClass candidateClass, PsiSubstitutor candidateSubstitutor, PsiClass aClass, @@ -531,8 +533,7 @@ public class PsiClassImplUtil { private static boolean processDeclarationsInClassNotCached(PsiClass aClass, PsiScopeProcessor processor, ResolveState state, Set visited, PsiElement last, PsiElement place, - boolean isRaw, - PsiElementFactory factory) { + boolean isRaw) { if (visited == null) visited = new THashSet(); if (!visited.add(aClass)) return true; processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, aClass); @@ -555,15 +556,15 @@ public class PsiClassImplUtil { } } + PsiElementFactory factory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory(); + if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD)) { + PsiSubstitutor baseSubstitutor = state.get(PsiSubstitutor.KEY); final PsiMethod[] methods = nameHint != null ? aClass.findMethodsByName(nameHint.getName(state), false) : aClass.getMethods(); for (final PsiMethod method : methods) { - if (isRaw && !method.hasModifierProperty(PsiModifier.STATIC)) { //static methods are not erased due to raw overriding - PsiTypeParameter[] methodTypeParameters = method.getTypeParameters(); - PsiSubstitutor raw = factory.createRawSubstitutor(state.get(PsiSubstitutor.KEY), methodTypeParameters); - state = state.put(PsiSubstitutor.KEY, raw); - } - if (!processor.execute(method, state)) return false; + PsiSubstitutor finalSubstitutor = checkRaw(isRaw, factory, method, baseSubstitutor); + ResolveState methodState = finalSubstitutor == baseSubstitutor ? state : state.put(PsiSubstitutor.KEY, finalSubstitutor); + if (!processor.execute(method, methodState)) return false; } } diff --git a/java/java-tests/testData/psi/resolve/method/MultipleInheritancePathsToMethod.java b/java/java-tests/testData/psi/resolve/method/MultipleInheritancePathsToMethod.java new file mode 100644 index 000000000000..3fea76f410e8 --- /dev/null +++ b/java/java-tests/testData/psi/resolve/method/MultipleInheritancePathsToMethod.java @@ -0,0 +1,20 @@ +interface N1 { + String getName(); +} +interface N2 { + String getName(); +} +interface NN extends N1 {} + +interface N3 { + String getName(); +} +interface VeryNamed extends NN, N2, N3, N1 {} + +class MyClass { + + void foo(VeryNamed f) { + f.getName(); + } + +} diff --git a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveMethodTest.java b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveMethodTest.java index 5ae52f7d5b86..c226e398dd3e 100644 --- a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveMethodTest.java @@ -262,4 +262,14 @@ public class ResolveMethodTest extends ResolveTestCase { PsiMethod method = (PsiMethod) target; assertEquals("PublicCloneable", method.getContainingClass().getName()); } + + public void testMultipleInheritancePathsToMethod() throws Exception { + PsiReference ref = configureByFile("method/" + getTestName(false) + ".java"); + + // just assume this is called by some highlighting inspection/intention/pass before the resolve + JavaPsiFacade.getInstance(getProject()).findClass("NN").getAllMethods(); + + PsiElement target = ref.resolve(); + assertInstanceOf(target, PsiMethod.class); + } } From d856bda11063f5d6dbfe8e35168f587144dfa9e3 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 29 Mar 2011 13:15:40 +0200 Subject: [PATCH 26/27] fix npe while rendering member variants --- .../com/intellij/codeInsight/completion/MemberLookupHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/MemberLookupHelper.java b/java/java-impl/src/com/intellij/codeInsight/completion/MemberLookupHelper.java index afde766917d0..8403668b5b05 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/MemberLookupHelper.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/MemberLookupHelper.java @@ -56,7 +56,7 @@ public class MemberLookupHelper { } final String qname = myContainingClass == null ? "" : myContainingClass.getQualifiedName(); - String pkg = StringUtil.getPackageName(qname); + String pkg = qname == null ? "" : StringUtil.getPackageName(qname); String location = StringUtil.isEmpty(pkg) ? "" : " (" + pkg + ")"; final String params = myMergedOverloads From 2236f1bed07f6919064559fa76ea641371194f25 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Tue, 29 Mar 2011 15:22:56 +0400 Subject: [PATCH 27/27] IDEA-66737 Copy text from quick doc popup doesn't work 1. Provided dedicated action that allows to copy text from quick doc hint to the clipboard; 2. Green cody policy is partially applied at the affected classed; --- .../DefaultCompletionContributor.java | 8 ++- .../documentation/DocumentationComponent.java | 13 +++- .../documentation/DocumentationManager.java | 60 ++++++++++--------- .../actions/CopyQuickDocAction.java | 46 ++++++++++++++ ...ction.java => ShowQuickDocInfoAction.java} | 4 +- .../src/idea/LangActions.xml | 2 +- .../src/idea/PlatformActions.xml | 1 + 7 files changed, 99 insertions(+), 35 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/documentation/actions/CopyQuickDocAction.java rename platform/lang-impl/src/com/intellij/codeInsight/documentation/actions/{ShowJavaDocInfoAction.java => ShowQuickDocInfoAction.java} (96%) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/DefaultCompletionContributor.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/DefaultCompletionContributor.java index 4b196a0b3f59..cbe534857650 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/DefaultCompletionContributor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/DefaultCompletionContributor.java @@ -15,7 +15,7 @@ */ package com.intellij.codeInsight.completion; -import com.intellij.codeInsight.documentation.actions.ShowJavaDocInfoAction; +import com.intellij.codeInsight.documentation.actions.ShowQuickDocInfoAction; import com.intellij.codeInsight.hint.actions.ShowImplementationsAction; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.lang.LangBundle; @@ -23,6 +23,7 @@ import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Random; @@ -31,6 +32,7 @@ import java.util.Random; */ public class DefaultCompletionContributor extends CompletionContributor { + @Nullable public static String getDefaultAdvertisementText(@NotNull final CompletionParameters parameters) { final Random random = new Random(); if (random.nextInt(5) < 2 && CompletionUtil.shouldShowFeature(parameters, CodeCompletionFeatures.EDITING_COMPLETION_FINISH_BY_DOT_ETC)) { @@ -56,8 +58,8 @@ public class DefaultCompletionContributor extends CompletionContributor { } if (random.nextInt(5) < 2 && - (CompletionUtil.shouldShowFeature(parameters, ShowJavaDocInfoAction.CODEASSISTS_QUICKJAVADOC_FEATURE) || - CompletionUtil.shouldShowFeature(parameters, ShowJavaDocInfoAction.CODEASSISTS_QUICKJAVADOC_LOOKUP_FEATURE))) { + (CompletionUtil.shouldShowFeature(parameters, ShowQuickDocInfoAction.CODEASSISTS_QUICKJAVADOC_FEATURE) || + CompletionUtil.shouldShowFeature(parameters, ShowQuickDocInfoAction.CODEASSISTS_QUICKJAVADOC_LOOKUP_FEATURE))) { final String shortcut = getActionShortcut(IdeActions.ACTION_QUICK_JAVADOC); if (shortcut != null) { return LangBundle.message("completion.quick.javadoc.ad", shortcut); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java index 665c62d71953..5e98b4da87b6 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java @@ -62,8 +62,8 @@ import java.awt.event.*; import java.util.List; import java.util.Stack; -public class DocumentationComponent extends JPanel implements Disposable { - +public class DocumentationComponent extends JPanel implements Disposable, DataProvider { + private static final DataContext EMPTY_DATA_CONTEXT = new DataContext() { @Override public Object getData(@NonNls String dataId) { @@ -318,6 +318,15 @@ public class DocumentationComponent extends JPanel implements Disposable { this(manager, null); } + @Override + public Object getData(@NonNls String dataId) { + if (DocumentationManager.SELECTED_QUICK_DOC_TEXT.getName().equals(dataId)) { + return myEditorPane.getSelectedText(); + } + + return null; + } + private JComponent createSettingsPanel() { JPanel result = new JPanel(new FlowLayout(FlowLayout.RIGHT, 3, 0)); result.add(new JLabel(ApplicationBundle.message("label.font.size"))); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index 8606406f6a06..626a74ef2d8b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -43,7 +43,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.OrderEntry; @@ -83,10 +82,14 @@ import java.util.*; import java.util.List; public class DocumentationManager { + + @NonNls public static final String JAVADOC_LOCATION_AND_SIZE = "javadoc.popup"; + public static final DataKey SELECTED_QUICK_DOC_TEXT = DataKey.create("QUICK_DOC.SELECTED_TEXT"); + private static final Logger LOG = Logger.getInstance("#" + DocumentationManager.class.getName()); private static final String SHOW_DOCUMENTATION_IN_TOOL_WINDOW = "ShowDocumentationInToolWindow"; private static final String DOCUMENTATION_AUTO_UPDATE_ENABLED = "DocumentationAutoUpdateEnabled"; - @NonNls public static final String JAVADOC_LOCATION_AND_SIZE = "javadoc.popup"; + private final Project myProject; private Editor myEditor = null; private ParameterInfoController myParameterInfoController; @@ -203,14 +206,11 @@ public class DocumentationManager { DocumentationProvider documentationProvider = getProviderFromElement(file); - PsiElement element = null; - if (documentationProvider!=null) { - element = documentationProvider.getDocumentationElementForLookupItem( - PsiManager.getInstance(myProject), - lookupIteObject, - originalElement - ); - } + PsiElement element = documentationProvider.getDocumentationElementForLookupItem( + PsiManager.getInstance(myProject), + lookupIteObject, + originalElement + ); if (element == null) return; @@ -235,7 +235,7 @@ public class DocumentationManager { Project project = getProject(element); if (myToolWindow == null && PropertiesComponent.getInstance().isTrueValue(SHOW_DOCUMENTATION_IN_TOOL_WINDOW)) { - createToolWindow(element, originalElement, true); + createToolWindow(element, originalElement); return; } else if (myToolWindow != null) { @@ -270,7 +270,7 @@ public class DocumentationManager { }); Processor pinCallback = new Processor() { public boolean process(JBPopup popup) { - createToolWindow(element, originalElement, true); + createToolWindow(element, originalElement); popup.cancel(); return false; } @@ -279,7 +279,7 @@ public class DocumentationManager { final KeyboardShortcut keyboardShortcut = ActionManagerEx.getInstanceEx().getKeyboardShortcut("QuickJavaDoc"); final List> actions = Collections.singletonList(Pair.create(new ActionListener() { public void actionPerformed(ActionEvent e) { - createToolWindow(element, originalElement, false); + createToolWindow(element, originalElement); final JBPopup hint = getDocInfoHint(); if (hint != null && hint.isVisible()) hint.cancel(); } @@ -344,7 +344,7 @@ public class DocumentationManager { } } - private void createToolWindow(final PsiElement element, PsiElement originalElement, final boolean automatic) { + private void createToolWindow(final PsiElement element, PsiElement originalElement) { assert myToolWindow == null; final DocumentationComponent component = new DocumentationComponent(this, new AnAction[]{ @@ -423,24 +423,30 @@ public class DocumentationManager { public void run() { if (myProject.isDisposed()) return; - final DataContext dataContext = DataManager.getInstance().getDataContext(); + AsyncResult asyncResult = DataManager.getInstance().getDataContextFromFocus(); + DataContext dataContext = asyncResult.getResult(); + if (dataContext == null) { + return; + } final Editor editor = PlatformDataKeys.EDITOR.getData(dataContext); - if (editor != null) { - final PsiFile file = PsiUtilBase.getPsiFileInEditor(editor, myProject); + if (editor == null) { + return; + } - final Editor injectedEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(editor, file); - if (injectedEditor != null) { - final PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(injectedEditor, myProject); - if (psiFile != null) { - showJavaDocInfo(injectedEditor, psiFile, false, true); - return; - } - } + final PsiFile file = PsiUtilBase.getPsiFileInEditor(editor, myProject); - if (file != null) { - showJavaDocInfo(editor, file, false, true); + final Editor injectedEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(editor, file); + if (injectedEditor != null) { + final PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(injectedEditor, myProject); + if (psiFile != null) { + showJavaDocInfo(injectedEditor, psiFile, false, true); + return; } } + + if (file != null) { + showJavaDocInfo(editor, file, false, true); + } } }; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/actions/CopyQuickDocAction.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/actions/CopyQuickDocAction.java new file mode 100644 index 000000000000..d7fcebe61cab --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/actions/CopyQuickDocAction.java @@ -0,0 +1,46 @@ +/* + * Copyright 2000-2011 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.documentation.actions; + +import com.intellij.codeInsight.documentation.DocumentationManager; +import com.intellij.codeInsight.hint.HintManagerImpl; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.ide.CopyPasteManager; +import com.intellij.openapi.project.DumbAware; + +import java.awt.datatransfer.StringSelection; + +/** + * @author Denis Zhdanov + * @since 3/29/11 1:28 PM + */ +public class CopyQuickDocAction extends AnAction implements DumbAware, HintManagerImpl.ActionToIgnore { + + public CopyQuickDocAction() { + setEnabledInModalContext(true); + } + + @Override + public void actionPerformed(AnActionEvent e) { + String selected = e.getData(DocumentationManager.SELECTED_QUICK_DOC_TEXT); + if (selected == null || selected.isEmpty()) { + return; + } + + CopyPasteManager.getInstance().setContents(new StringSelection(selected)); + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/actions/ShowJavaDocInfoAction.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/actions/ShowQuickDocInfoAction.java similarity index 96% rename from platform/lang-impl/src/com/intellij/codeInsight/documentation/actions/ShowJavaDocInfoAction.java rename to platform/lang-impl/src/com/intellij/codeInsight/documentation/actions/ShowQuickDocInfoAction.java index cea5400d218f..ea8339928dc0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/actions/ShowJavaDocInfoAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/actions/ShowQuickDocInfoAction.java @@ -34,11 +34,11 @@ import com.intellij.psi.*; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -public class ShowJavaDocInfoAction extends BaseCodeInsightAction implements HintManagerImpl.ActionToIgnore, DumbAware, PopupAction { +public class ShowQuickDocInfoAction extends BaseCodeInsightAction implements HintManagerImpl.ActionToIgnore, DumbAware, PopupAction { @NonNls public static final String CODEASSISTS_QUICKJAVADOC_LOOKUP_FEATURE = "codeassists.quickjavadoc.lookup"; @NonNls public static final String CODEASSISTS_QUICKJAVADOC_FEATURE = "codeassists.quickjavadoc"; - public ShowJavaDocInfoAction() { + public ShowQuickDocInfoAction() { setEnabledInModalContext(true); setInjectedContext(true); } diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index b53b214ad8ae..c5a7d3c54158 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -136,7 +136,7 @@ - + diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index 22b63fd3e470..bcda6f9e02e8 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -19,6 +19,7 @@ +