From 4a94b7473a25bad064ad2166e9ad0b6956f37a11 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 6 Oct 2014 17:11:22 +0200 Subject: [PATCH 01/34] =?UTF-8?q?security.xml=20=E2=80=94=20disable=20roam?= =?UTF-8?q?ing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ide/passwordSafe/config/PasswordSafeSettings.java | 9 +++------ .../impl/providers/masterKey/PasswordDatabase.java | 9 +++------ .../src/git4idea/config/SSHConnectionSettings.java | 4 ++-- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/config/PasswordSafeSettings.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/config/PasswordSafeSettings.java index 10c5c933c41d..ab8fac21dd3a 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/config/PasswordSafeSettings.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/config/PasswordSafeSettings.java @@ -15,10 +15,7 @@ */ package com.intellij.ide.passwordSafe.config; -import com.intellij.openapi.components.PersistentStateComponent; -import com.intellij.openapi.components.State; -import com.intellij.openapi.components.Storage; -import com.intellij.openapi.components.StoragePathMacros; +import com.intellij.openapi.components.*; /** * The password safe settings @@ -28,8 +25,8 @@ import com.intellij.openapi.components.StoragePathMacros; */ @State( name = "PasswordSafe", - storages = {@Storage( - file = StoragePathMacros.APP_CONFIG + "/security.xml")}) + storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/security.xml", roamingType = RoamingType.DISABLED)} +) public class PasswordSafeSettings implements PersistentStateComponent { /** * The selected provider type diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/PasswordDatabase.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/PasswordDatabase.java index 4bb0eaefae53..ee2b3a8d7a98 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/PasswordDatabase.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/PasswordDatabase.java @@ -17,10 +17,7 @@ package com.intellij.ide.passwordSafe.impl.providers.masterKey; import com.intellij.ide.passwordSafe.impl.providers.ByteArrayWrapper; -import com.intellij.openapi.components.PersistentStateComponent; -import com.intellij.openapi.components.State; -import com.intellij.openapi.components.Storage; -import com.intellij.openapi.components.StoragePathMacros; +import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Hex; @@ -35,8 +32,8 @@ import java.util.TreeMap; */ @State( name = "PasswordDatabase", - storages = {@Storage( - file = StoragePathMacros.APP_CONFIG + "/security.xml")}) + storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/security.xml", roamingType = RoamingType.DISABLED)} +) public class PasswordDatabase implements PersistentStateComponent { /** * The name of logger diff --git a/plugins/git4idea/src/git4idea/config/SSHConnectionSettings.java b/plugins/git4idea/src/git4idea/config/SSHConnectionSettings.java index 72de867803e5..c48b352ac1e2 100644 --- a/plugins/git4idea/src/git4idea/config/SSHConnectionSettings.java +++ b/plugins/git4idea/src/git4idea/config/SSHConnectionSettings.java @@ -28,8 +28,8 @@ import java.util.TreeMap; */ @State( name = "SSHConnectionSettings", - storages = {@Storage( - file = StoragePathMacros.APP_CONFIG + "/security.xml")}) + storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/security.xml", roamingType = RoamingType.DISABLED)} +) public class SSHConnectionSettings implements PersistentStateComponent { /** * The last successful hosts, the entries are sorted to save on efforts on sorting during saving and loading From 95c035dd77e6f164cab6efc0bcf7fd3266c3a60a Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Mon, 6 Oct 2014 19:16:58 +0400 Subject: [PATCH 02/34] IDEA-130552 Different font size in the inspection profile popup --- platform/util/src/com/intellij/util/ui/UIUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index d7b5534979fe..66adb1ed0952 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -1939,7 +1939,7 @@ public class UIUtil { public static Font getTitledBorderFont() { Font defFont = getLabelFont(); - return defFont.deriveFont(Math.max(defFont.getSize() - 2f, 11f)); + return defFont.deriveFont(defFont.getSize() - 1f); } /** @@ -3025,7 +3025,7 @@ public class UIUtil { } public static Color getSidePanelColor() { - return new JBColor(new Color(0xD2D6DD), new Color(60, 68, 71)); + return new JBColor(0xD2D6DD, 0x3C4447); } /** From b51d40f717070727fd1301c92d633b24c2cf4334 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 6 Oct 2014 13:00:30 +0200 Subject: [PATCH 03/34] beware of null in IDEA-130746 Incorrect cast after completion in evaluate dialog --- .../completion/JavaCompletionUtil.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index 93a75f3c9c47..17cb8724dc56 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -448,12 +448,15 @@ public class JavaCompletionUtil { PsiSubstitutor plainSub = plainResult.getSubstitutor(); PsiSubstitutor castSub = TypeConversionUtil.getSuperClassSubstitutor(plainClass, (PsiClassType)castType); PsiType returnType = method.getReturnType(); - if (method.getSignature(plainSub).equals(method.getSignature(castSub)) && - returnType != null && - toRaw(castSub.substitute(returnType)).isAssignableFrom(toRaw(plainSub.substitute(returnType))) && - processor.isAccessible(plainClass.findMethodBySignature(method, true)) - ) { - return item; + if (method.getSignature(plainSub).equals(method.getSignature(castSub))) { + PsiType typeAfterCast = toRaw(castSub.substitute(returnType)); + PsiType typeDeclared = toRaw(plainSub.substitute(returnType)); + if (typeAfterCast != null && typeDeclared != null && + typeAfterCast.isAssignableFrom(typeDeclared) && + processor.isAccessible(plainClass.findMethodBySignature(method, true)) + ) { + return item; + } } } } @@ -495,7 +498,8 @@ public class JavaCompletionUtil { }); } - private static PsiType toRaw(@NotNull PsiType type) { + @Nullable + private static PsiType toRaw(@Nullable PsiType type) { return type instanceof PsiClassType ? ((PsiClassType)type).rawType() : type; } From aef398ac16ff14e98e9442af2c7b361a27ab818b Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 6 Oct 2014 17:13:00 +0200 Subject: [PATCH 04/34] ChooseByNameBase: cancel background thread immediately before restarting (EA-58991) --- .../ide/util/gotoByName/ChooseByNameBase.java | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java index 66b590aa9b96..309b400b8c47 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java @@ -950,6 +950,17 @@ public abstract class ChooseByNameBase { } myAlarm.cancelAllRequests(); + + if (delay > 0) { + myAlarm.addRequest(new Runnable() { + @Override + public void run() { + rebuildList(pos, 0, modalityState, postRunnable); + } + }, delay, ModalityState.stateForComponent(myTextField)); + return; + } + myListUpdater.cancelAll(); final CalcElementsThread calcElementsThread = myCalcElementsThread; @@ -977,32 +988,20 @@ public abstract class ChooseByNameBase { ((MatcherHolder)cellRenderer).setPatternMatcher(matcher); } - final Runnable request = new Runnable() { + scheduleCalcElements(text, myCheckBox.isSelected(), modalityState, new Consumer>() { @Override - public void run() { - scheduleCalcElements(text, myCheckBox.isSelected(), modalityState, new Consumer>() { - @Override - public void consume(Set elements) { - ApplicationManager.getApplication().assertIsDispatchThread(); - if (checkDisposed()) { - return; - } - backgroundCalculationFinished(elements, pos); + public void consume(Set elements) { + ApplicationManager.getApplication().assertIsDispatchThread(); + if (checkDisposed()) { + return; + } + backgroundCalculationFinished(elements, pos); - if (postRunnable != null) { - postRunnable.run(); - } - } - }); + if (postRunnable != null) { + postRunnable.run(); + } } - }; - - if (delay > 0) { - myAlarm.addRequest(request, delay, ModalityState.stateForComponent(myTextField)); - } - else { - request.run(); - } + }); } private void backgroundCalculationFinished(Collection result, int toSelect) { From 7ba41ebecc21a1adf05c6dcf18b13875ff53196f Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 6 Oct 2014 17:26:24 +0200 Subject: [PATCH 05/34] java-decompiler: minor optimization (no more empty array creation) --- .../struct/attr/StructLineNumberTableAttribute.java | 5 +++-- .../java/decompiler/util/FastSparseSetFactory.java | 1 + .../jetbrains/java/decompiler/util/InterpreterUtil.java | 2 ++ .../java/decompiler/util/SFormsFastMapDirect.java | 8 ++++---- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructLineNumberTableAttribute.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructLineNumberTableAttribute.java index 695d6598869d..f35d3d95cf4f 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructLineNumberTableAttribute.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/struct/attr/StructLineNumberTableAttribute.java @@ -17,6 +17,7 @@ package org.jetbrains.java.decompiler.struct.attr; import org.jetbrains.java.decompiler.struct.consts.ConstantPool; import org.jetbrains.java.decompiler.util.DataInputFullStream; +import org.jetbrains.java.decompiler.util.InterpreterUtil; import java.io.IOException; @@ -29,7 +30,7 @@ import java.io.IOException; * Created by Egor on 05.10.2014. */ public class StructLineNumberTableAttribute extends StructGeneralAttribute { - private int[] myLineInfo = new int[0]; + private int[] myLineInfo = InterpreterUtil.EMPTY_INT_ARRAY; @Override public void initContent(ConstantPool pool) throws IOException { @@ -44,7 +45,7 @@ public class StructLineNumberTableAttribute extends StructGeneralAttribute { } } else if (myLineInfo.length > 0) { - myLineInfo = new int[0]; + myLineInfo = InterpreterUtil.EMPTY_INT_ARRAY; } } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/FastSparseSetFactory.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/FastSparseSetFactory.java index bf01035616a4..64e98a04388b 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/FastSparseSetFactory.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/FastSparseSetFactory.java @@ -88,6 +88,7 @@ public class FastSparseSetFactory { public static class FastSparseSet implements Iterable { + public static final FastSparseSet[] EMPTY_ARRAY = new FastSparseSet[0]; private FastSparseSetFactory factory; diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/InterpreterUtil.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/InterpreterUtil.java index 09e7bad5ccbb..eaada902b03d 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/InterpreterUtil.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/InterpreterUtil.java @@ -29,6 +29,8 @@ import java.util.zip.ZipFile; public class InterpreterUtil { public static final boolean IS_WINDOWS = System.getProperty("os.name", "").startsWith("Windows"); + public static final int[] EMPTY_INT_ARRAY = new int[0]; + private static final int CHANNEL_WINDOW_SIZE = IS_WINDOWS ? 64 * 1024 * 1024 - (32 * 1024) : 64 * 1024 * 1024; // magic number for Windows private static final int BUFFER_SIZE = 16 * 1024; diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/SFormsFastMapDirect.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/SFormsFastMapDirect.java index 996607a2bdbc..b70dedea6a78 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/SFormsFastMapDirect.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/SFormsFastMapDirect.java @@ -38,9 +38,9 @@ public class SFormsFastMapDirect { private SFormsFastMapDirect(boolean initialize) { if (initialize) { for (int i = 2; i >= 0; i--) { - @SuppressWarnings("unchecked") FastSparseSet[] empty = new FastSparseSet[0]; + @SuppressWarnings("unchecked") FastSparseSet[] empty = FastSparseSet.EMPTY_ARRAY; elements[i] = empty; - next[i] = new int[0]; + next[i] = InterpreterUtil.EMPTY_INT_ARRAY; } } } @@ -99,8 +99,8 @@ public class SFormsFastMapDirect { while (pointer != 0); } else { - mapelements[i] = new FastSparseSet[0]; - mapnext[i] = new int[0]; + mapelements[i] = FastSparseSet.EMPTY_ARRAY; + mapnext[i] = InterpreterUtil.EMPTY_INT_ARRAY; } } From d7ac798b7b6d9186ff6ec80338e6179675ab808b Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 6 Oct 2014 17:26:48 +0200 Subject: [PATCH 06/34] java-decompiler: test data path updated --- .../java/decompiler/IdeaDecompilerTest.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java b/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java index c584bae2daa7..29c7dc3d9c32 100644 --- a/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java +++ b/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java @@ -91,9 +91,7 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase { } public void testNavigation() { - String path = PluginPathManager.getPluginHomePath("java-decompiler") + "/testData/Navigation.class"; - VirtualFile file = StandardFileSystems.local().findFileByPath(path); - assertNotNull(path, file); + VirtualFile file = getTestFile(); myFixture.openFileInEditor(file); doTestNavigation(11, 14, 14, 10); // to "m2()" @@ -101,6 +99,13 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase { doTestNavigation(16, 28, 15, 13); // to "int r" } + private VirtualFile getTestFile() { + String path = PluginPathManager.getPluginHomePath("java-decompiler") + "/plugin/testData/" + getTestName(false) + ".class"; + VirtualFile file = StandardFileSystems.local().findFileByPath(path); + assertNotNull(path, file); + return file; + } + private void doTestNavigation(int line, int column, int expectedLine, int expectedColumn) { PsiElement target = GotoDeclarationAction.findTargetElement(getProject(), myFixture.getEditor(), offset(line, column)); assertTrue(String.valueOf(target), target instanceof Navigatable); @@ -114,9 +119,7 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase { } public void testHighlighting() { - String path = PluginPathManager.getPluginHomePath("java-decompiler") + "/testData/Navigation.class"; - VirtualFile file = StandardFileSystems.local().findFileByPath(path); - assertNotNull(path, file); + VirtualFile file = getTestFile(); myFixture.openFileInEditor(file); IdentifierHighlighterPassFactory.doWithHighlightingEnabled(new Runnable() { From 84ee551a36609e877a8cb71b40833646f1b03b15 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 6 Oct 2014 17:29:18 +0200 Subject: [PATCH 07/34] javafx page script fixed --- .../javaFX/fxml/JavaFXQuickfixTest.java | 2 - .../JavaFxInjectPageLanguageIntention.java | 45 +++++-------------- .../quickfix/registerPageLanguage_after.fxml | 2 +- 3 files changed, 13 insertions(+), 36 deletions(-) diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXQuickfixTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXQuickfixTest.java index b85da167f45d..b95b12497e7b 100644 --- a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXQuickfixTest.java +++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXQuickfixTest.java @@ -18,8 +18,6 @@ package org.jetbrains.plugins.javaFX.fxml; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.openapi.application.PluginPathManager; import com.intellij.openapi.module.Module; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl; import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.testFramework.LightProjectDescriptor; diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/intentions/JavaFxInjectPageLanguageIntention.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/intentions/JavaFxInjectPageLanguageIntention.java index 01dc2e06e364..0cbd61f765a9 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/intentions/JavaFxInjectPageLanguageIntention.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/intentions/JavaFxInjectPageLanguageIntention.java @@ -17,14 +17,13 @@ package org.jetbrains.plugins.javaFX.fxml.codeInsight.intentions; import com.intellij.codeInsight.FileModificationService; import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.OrderEnumerator; import com.intellij.openapi.ui.popup.JBPopupFactory; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFileFactory; import com.intellij.psi.PsiParserFacade; @@ -36,16 +35,15 @@ import com.intellij.psi.xml.XmlProlog; import com.intellij.ui.components.JBList; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.lang.UrlClassLoader; import org.jetbrains.annotations.NotNull; import javax.script.ScriptEngine; import javax.script.ScriptEngineFactory; import javax.script.ScriptEngineManager; -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; /** * User: anna @@ -55,33 +53,14 @@ public class JavaFxInjectPageLanguageIntention extends PsiElementBaseIntentionAc public static final Logger LOG = Logger.getInstance("#" + JavaFxInjectPageLanguageIntention.class.getName()); private static Set getAvailableLanguages(Project project) { - final List engineFactories = new ScriptEngineManager(composeUserClassLoader(project)).getEngineFactories(); + final List engineFactories = new ScriptEngineManager().getEngineFactories(); - if (engineFactories != null) { - final Set availableNames = new TreeSet(); - for (ScriptEngineFactory factory : engineFactories) { - final String engineName = (String)factory.getParameter(ScriptEngine.NAME); - availableNames.add(engineName); - } - return availableNames; + final Set availableNames = new TreeSet(); + for (ScriptEngineFactory factory : engineFactories) { + final String engineName = (String)factory.getParameter(ScriptEngine.NAME); + availableNames.add(engineName); } - - return null; - } - - private static UrlClassLoader composeUserClassLoader(Project project) { - final List urls = new ArrayList(); - final List list = OrderEnumerator.orderEntries(project).recursively().runtimeOnly().getPathsList().getPathList(); - for (String path : list) { - try { - urls.add(new File(FileUtil.toSystemIndependentName(path)).toURI().toURL()); - } - catch (MalformedURLException e1) { - LOG.info(e1); - } - } - - return UrlClassLoader.build().urls(urls).get(); + return availableNames; } @Override @@ -90,7 +69,7 @@ public class JavaFxInjectPageLanguageIntention extends PsiElementBaseIntentionAc final XmlFile containingFile = (XmlFile)element.getContainingFile(); final Set availableLanguages = getAvailableLanguages(project); - if (availableLanguages.size() == 1) { + if (availableLanguages.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) { registerPageLanguage(project, containingFile, availableLanguages.iterator().next()); } else { final JBList list = new JBList(availableLanguages); diff --git a/plugins/javaFX/testData/quickfix/registerPageLanguage_after.fxml b/plugins/javaFX/testData/quickfix/registerPageLanguage_after.fxml index eeac829d7175..f794f91d61ba 100644 --- a/plugins/javaFX/testData/quickfix/registerPageLanguage_after.fxml +++ b/plugins/javaFX/testData/quickfix/registerPageLanguage_after.fxml @@ -1,4 +1,4 @@ - + From 9f9960b7d1745d3f4d8eb5eebd397bf20a04f96a Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 6 Oct 2014 17:44:35 +0200 Subject: [PATCH 08/34] project: java decompiler plugin layout updated --- build/scripts/layouts.gant | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index 6842e6379d6d..c1aaa37f871d 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -145,7 +145,7 @@ def layoutFull(String home, String targetDirectory, String patchedDescriptorDir } jar("bootstrap.jar") { module("bootstrap") } - + jar("jps-launcher.jar") { module("jps-launcher") } jar("resources.jar") { @@ -557,7 +557,14 @@ public def layoutCommunityPlugins(String home) { } } - layoutPlugin("java-decompiler") + pluginDir("java-decompiler") { + dir("lib") { + jar("java-decompiler.jar") { + module("java-decompiler-engine") + module("java-decompiler-plugin") + } + } + } } } From 0e7b172ae0b6418f16a5861eebd7b8b7aaa4bb46 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 6 Oct 2014 17:54:58 +0200 Subject: [PATCH 09/34] compilation fix --- .../component/ArrangementAtomMatchConditionComponent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementAtomMatchConditionComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementAtomMatchConditionComponent.java index 4891d703b6db..a1b15c6bf33f 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementAtomMatchConditionComponent.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementAtomMatchConditionComponent.java @@ -237,7 +237,7 @@ public class ArrangementAtomMatchConditionComponent implements ArrangementUiComp @NotNull @Override public ArrangementAtomMatchCondition getMatchCondition() { - if (myInverted == myCondition.getValue()) { + if (Boolean.valueOf(myInverted) == myCondition.getValue()) { if (myOppositeCondition == null) { myOppositeCondition = new ArrangementAtomMatchCondition(myCondition.getType(), !myInverted); } From e6b9a4e6aed679dd27aee97a7c75661b5d78690a Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Mon, 6 Oct 2014 19:58:08 +0400 Subject: [PATCH 10/34] IDEA-130779 Exception when pushing Mercurial repository in a mixed project --- .../dvcs-impl/src/com/intellij/dvcs/push/PushController.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java index da25c7da8663..d639a9c74b34 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java @@ -376,7 +376,10 @@ public class PushController implements Disposable { boolean force) { VcsPushOptionValue options = myDialog.getAdditionalOptionValue(support); Pusher pusher = support.getPusher(); - pusher.push(collectPushSpecsForVcs(support), options, force); + Map> specs = collectPushSpecsForVcs(support); + if (!specs.isEmpty()) { + pusher.push(specs, options, force); + } } @NotNull From 72d5733ebcae6acd916a65b4672585b2c351b848 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 6 Oct 2014 20:11:20 +0400 Subject: [PATCH 11/34] accept @Nullable parameters --- .../src/com/intellij/openapi/util/text/StringUtil.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index e8132521cf6e..ba8554c08e28 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -2683,7 +2683,15 @@ public class StringUtil extends StringUtilRt { } @Contract(pure = true) - public static boolean equalsIgnoreWhitespaces(@NotNull CharSequence s1, @NotNull CharSequence s2) { + public static boolean equalsIgnoreWhitespaces(@Nullable CharSequence s1, @Nullable CharSequence s2) { + if (s1 == null ^ s2 == null) { + return false; + } + + if (s1 == null) { + return true; + } + int len1 = s1.length(); int len2 = s2.length(); From 24b9ce219a9f4bba62ab9fd861e5993590db0905 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 6 Oct 2014 20:11:47 +0400 Subject: [PATCH 12/34] add test on equalsIgnoreWhitespace() --- .../intellij/util/text/StringUtilTest.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java index 93ebb038cae1..84c2acbba767 100644 --- a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java +++ b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java @@ -233,4 +233,29 @@ public class StringUtilTest extends TestCase { public void testReplace() { assertEquals(StringUtil.replace("$PROJECT_FILE$/filename", "$PROJECT_FILE$", "/tmp"), "/tmp/filename"); } + + public void testEqualsIgnoreWhitespaces() { + assertTrue(StringUtil.equalsIgnoreWhitespaces(null, null)); + assertFalse(StringUtil.equalsIgnoreWhitespaces("", null)); + + assertTrue(StringUtil.equalsIgnoreWhitespaces("", "")); + assertTrue(StringUtil.equalsIgnoreWhitespaces("\n\t ", "")); + assertTrue(StringUtil.equalsIgnoreWhitespaces("", "\t\n \n\t")); + assertTrue(StringUtil.equalsIgnoreWhitespaces("\t", "\n")); + + assertTrue(StringUtil.equalsIgnoreWhitespaces("x", " x")); + assertTrue(StringUtil.equalsIgnoreWhitespaces("x", "x ")); + assertTrue(StringUtil.equalsIgnoreWhitespaces("x\n", "x")); + + assertTrue(StringUtil.equalsIgnoreWhitespaces("abcd", "a\nb\nc\nd\n")); + assertTrue(StringUtil.equalsIgnoreWhitespaces("x y x", "x y x")); + assertTrue(StringUtil.equalsIgnoreWhitespaces("xyx", "x y x")); + + assertFalse(StringUtil.equalsIgnoreWhitespaces("x", "\t\n ")); + assertFalse(StringUtil.equalsIgnoreWhitespaces("", " x ")); + assertFalse(StringUtil.equalsIgnoreWhitespaces("", "x ")); + assertFalse(StringUtil.equalsIgnoreWhitespaces("", " x")); + assertFalse(StringUtil.equalsIgnoreWhitespaces("xyx", "xxx")); + assertFalse(StringUtil.equalsIgnoreWhitespaces("xyx", "xYx")); + } } From 6b85507a2efa0d534bf5905e1ae4b0d84e1fe22f Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 6 Oct 2014 20:16:57 +0400 Subject: [PATCH 13/34] add test on testStringHashCodeIgnoreWhitespaces --- .../intellij/util/text/StringUtilTest.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java index 84c2acbba767..8b11f1f33db6 100644 --- a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java +++ b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java @@ -15,6 +15,7 @@ */ package com.intellij.util.text; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; import junit.framework.TestCase; @@ -258,4 +259,26 @@ public class StringUtilTest extends TestCase { assertFalse(StringUtil.equalsIgnoreWhitespaces("xyx", "xxx")); assertFalse(StringUtil.equalsIgnoreWhitespaces("xyx", "xYx")); } + + public void testStringHashCodeIgnoreWhitespaces() { + assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces(""), StringUtil.stringHashCodeIgnoreWhitespaces(""))); + assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("\n\t "), StringUtil.stringHashCodeIgnoreWhitespaces(""))); + assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces(""), StringUtil.stringHashCodeIgnoreWhitespaces("\t\n \n\t"))); + assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("\t"), StringUtil.stringHashCodeIgnoreWhitespaces("\n"))); + + assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("x"), StringUtil.stringHashCodeIgnoreWhitespaces(" x"))); + assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("x"), StringUtil.stringHashCodeIgnoreWhitespaces("x "))); + assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("x\n"), StringUtil.stringHashCodeIgnoreWhitespaces("x"))); + + assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("abcd"), StringUtil.stringHashCodeIgnoreWhitespaces("a\nb\nc\nd\n"))); + assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("x y x"), StringUtil.stringHashCodeIgnoreWhitespaces("x y x"))); + assertTrue(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("xyx"), StringUtil.stringHashCodeIgnoreWhitespaces("x y x"))); + + assertFalse(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("x"), StringUtil.stringHashCodeIgnoreWhitespaces("\t\n "))); + assertFalse(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces(""), StringUtil.stringHashCodeIgnoreWhitespaces(" x "))); + assertFalse(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces(""), StringUtil.stringHashCodeIgnoreWhitespaces("x "))); + assertFalse(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces(""), StringUtil.stringHashCodeIgnoreWhitespaces(" x"))); + assertFalse(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("xyx"), StringUtil.stringHashCodeIgnoreWhitespaces("xxx"))); + assertFalse(Comparing.equal(StringUtil.stringHashCodeIgnoreWhitespaces("xyx"), StringUtil.stringHashCodeIgnoreWhitespaces("xYx"))); + } } From 14e104ed9198d126e8d53036e79ab6fccabc5bf3 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Mon, 6 Oct 2014 18:11:56 +0200 Subject: [PATCH 14/34] fix cleanup on commit: proceed with commit --- .../ex/GlobalInspectionContextImpl.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java index b130b3cd420d..a82d5ba1f69d 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java @@ -701,14 +701,17 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp }); if (results.isEmpty()) { - if (commandName != null) { - UIUtil.invokeLaterIfNeeded(new Runnable() { - @Override - public void run() { + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + if (commandName != null) { NOTIFICATION_GROUP.createNotification(InspectionsBundle.message("inspection.no.problems.message"), MessageType.INFO).notify(getProject()); } - }); - } + if (postRunnable != null) { + postRunnable.run(); + } + } + }); return; } Runnable runnable = new Runnable() { From 61ae83eef7392c1bcdf3ebac078cedc1534a9104 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 6 Oct 2014 20:30:09 +0400 Subject: [PATCH 15/34] fixed tests ( PY-11879) --- .../python/documentation/DocStringParameterReference.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/documentation/DocStringParameterReference.java b/python/src/com/jetbrains/python/documentation/DocStringParameterReference.java index 968d41368d37..f0b15da7a7a6 100644 --- a/python/src/com/jetbrains/python/documentation/DocStringParameterReference.java +++ b/python/src/com/jetbrains/python/documentation/DocStringParameterReference.java @@ -173,7 +173,7 @@ public class DocStringParameterReference extends PsiReferenceBase Date: Mon, 6 Oct 2014 18:30:18 +0200 Subject: [PATCH 16/34] java: read action in default decompiler --- .../com/intellij/psi/impl/compiled/ClsFileImpl.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java index a5347f2e9767..b2952f369275 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java @@ -565,8 +565,14 @@ public class ClsFileImpl extends ClsRepositoryPsiElement @NotNull public static CharSequence decompile(@NotNull VirtualFile file) { PsiManager manager = PsiManager.getInstance(DefaultProjectFactory.getInstance().getDefaultProject()); - StringBuilder buffer = new StringBuilder(); - new ClsFileImpl(new ClassFileViewProvider(manager, file), true).appendMirrorText(0, buffer); + final ClsFileImpl clsFile = new ClsFileImpl(new ClassFileViewProvider(manager, file), true); + final StringBuilder buffer = new StringBuilder(); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + clsFile.appendMirrorText(0, buffer); + } + }); return buffer; } From 6d44e1bfaf5bcff80636b70009d278d31049b8e9 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Mon, 6 Oct 2014 20:34:20 +0400 Subject: [PATCH 17/34] CR-IC-6468 rename method --- .../intellij/codeInsight/intention/impl/QuickEditAction.java | 2 +- .../src/com/intellij/injected/editor/DocumentWindowImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java index 5e4f9b315042..0a31503e9a99 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java @@ -107,7 +107,7 @@ public class QuickEditAction implements IntentionAction, LowPriorityAction { if (!ApplicationManager.getApplication().isUnitTestMode()) { DocumentWindow documentWindow = InjectedLanguageUtil.getDocumentWindow(injectedFile); if (documentWindow != null) { - handler.navigate(((DocumentWindowImpl)documentWindow).hostToUnescaped(offset)); + handler.navigate(((DocumentWindowImpl)documentWindow).hostToInjectedUnescaped(offset)); } } return handler; diff --git a/platform/lang-impl/src/com/intellij/injected/editor/DocumentWindowImpl.java b/platform/lang-impl/src/com/intellij/injected/editor/DocumentWindowImpl.java index 3ed4e0a16022..7c67fe95a71f 100644 --- a/platform/lang-impl/src/com/intellij/injected/editor/DocumentWindowImpl.java +++ b/platform/lang-impl/src/com/intellij/injected/editor/DocumentWindowImpl.java @@ -668,7 +668,7 @@ public class DocumentWindowImpl extends UserDataHolderBase implements Disposable } } - public int hostToUnescaped(int hostOffset) { + public int hostToInjectedUnescaped(int hostOffset) { synchronized (myLock) { Segment hostRangeMarker = myShreds.get(0).getHostRangeMarker(); if (hostRangeMarker == null || hostOffset < hostRangeMarker.getStartOffset()) return myShreds.get(0).getPrefix().length(); From 8f3def851556d6b91eac9b160f0a3c1a381d94cc Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 6 Oct 2014 18:31:39 +0200 Subject: [PATCH 18/34] allow to change custom configurable shortcut in single setting page mode (e.g. alt+enter from completion) --- .../template/impl/TemplateListPanel.java | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateListPanel.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateListPanel.java index a1a60ad9d39e..4505c5b1ed49 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateListPanel.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateListPanel.java @@ -31,6 +31,7 @@ import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.keymap.impl.ui.KeymapPanel; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SchemesManager; +import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.options.ex.Settings; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.ui.*; @@ -398,23 +399,25 @@ public class TemplateListPanel extends JPanel implements Disposable { return evt.getPropertyName().equals("ancestor") && evt.getNewValue() != null && evt.getOldValue() == null; } - private void resizeComboToFitCustomShortcut() { - myExpandByCombo.setPrototypeDisplayValue(null); - myExpandByCombo.setPrototypeDisplayValue(CUSTOM); - } }); myOpenKeymapLabel.addHyperlinkListener(new HyperlinkAdapter() { @Override protected void hyperlinkActivated(HyperlinkEvent e) { Settings allSettings = Settings.KEY.getData(DataManager.getInstance().getDataContext(myOpenKeymapLabel)); - final KeymapPanel keymapPanel = allSettings == null ? null : allSettings.find(KeymapPanel.class); - if (keymapPanel != null) { - allSettings.select(keymapPanel).doWhenDone(new Runnable() { - public void run() { - keymapPanel.selectAction(IdeActions.ACTION_EXPAND_LIVE_TEMPLATE_CUSTOM); - } - }); + final KeymapPanel keymapPanel = allSettings == null ? new KeymapPanel() : allSettings.find(KeymapPanel.class); + if (keymapPanel == null) return; + + Runnable selectAction = new Runnable() { + public void run() { + keymapPanel.selectAction(IdeActions.ACTION_EXPAND_LIVE_TEMPLATE_CUSTOM); + } + }; + if (allSettings != null) { + allSettings.select(keymapPanel).doWhenDone(selectAction); + } else { + ShowSettingsUtil.getInstance().editConfigurable(myOpenKeymapLabel, keymapPanel, selectAction); + resizeComboToFitCustomShortcut(); } } }); @@ -422,6 +425,14 @@ public class TemplateListPanel extends JPanel implements Disposable { return panel; } + @SuppressWarnings("unchecked") + private void resizeComboToFitCustomShortcut() { + myExpandByCombo.setPrototypeDisplayValue(null); + myExpandByCombo.setPrototypeDisplayValue(CUSTOM); + myExpandByCombo.revalidate(); + myExpandByCombo.repaint(); + } + @Nullable private TemplateImpl getTemplate(int row) { JTree tree = myTree; From f00d7189f85fd011f167bc3a807800d9150f7e8a Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 6 Oct 2014 18:35:48 +0200 Subject: [PATCH 19/34] trim live template contexts label text to avoid the dialog becoming too wide --- .../codeInsight/template/impl/LiveTemplateSettingsEditor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateSettingsEditor.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateSettingsEditor.java index 46f51dd2a52a..8ce2b7428c6a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateSettingsEditor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateSettingsEditor.java @@ -340,7 +340,8 @@ public class LiveTemplateSettingsEditor extends JPanel { sb.append(ownName); } final boolean noContexts = sb.length() == 0; - ctxLabel.setText((noContexts ? "No applicable contexts" + (allowNoContexts ? "" : " yet") : "Applicable in " + sb.toString()) + ". "); + String contexts = (noContexts ? "No applicable contexts" + (allowNoContexts ? "" : " yet") : "Applicable in " + sb.toString()) + ". "; + ctxLabel.setText(StringUtil.first(contexts, 100, true)); ctxLabel.setForeground(noContexts ? allowNoContexts ? JBColor.GRAY : JBColor.RED : UIUtil.getLabelForeground()); change.setText(noContexts ? "Define" : "Change"); } From 9b8cc4cd96d94d86aaf57783942c91520e0943c6 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 6 Oct 2014 20:39:57 +0400 Subject: [PATCH 20/34] IDEA-128864 diff: fix invalid range applying MergeOperation is created with fixed TextRange, so it will not be updated on change, like RangeHighlighters (and usage of RangeHighlighter is dangerous, as it could be updated incorrectly) So we have to disable all actions until diff rebuild to prevent document corruption. The 'right' fix of this issue could be to store line numbers inside action, update them on document change (like in LST), and use Document.getLineStartOffset() and etc inside write action. --- .../src/com/intellij/openapi/diff/impl/Rediffers.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/Rediffers.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/Rediffers.java index 3a1f8b055ab5..95afab208a13 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/Rediffers.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/Rediffers.java @@ -87,9 +87,7 @@ public class Rediffers { public void beforeDocumentChange(DocumentEvent event) {} public void documentChanged(DocumentEvent event) { - int newLines = StringUtil.getLineBreakCount(event.getNewFragment()); - int oldLines = StringUtil.getLineBreakCount(event.getOldFragment()); - if (newLines != oldLines) myPanel.invalidateDiff(); + if (event.getOldLength() != event.getNewLength()) myPanel.invalidateDiff(); requestRediff(); } From 8739127fe7b1dfd80f18a52a222afa66b3a7ca79 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Mon, 6 Oct 2014 21:00:03 +0400 Subject: [PATCH 21/34] Revert to fix tests --- .../openapi/editor/impl/PersistentRangeMarkerUtil.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/PersistentRangeMarkerUtil.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/PersistentRangeMarkerUtil.java index 5a8b633ff95b..2e78c2cc067b 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/PersistentRangeMarkerUtil.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/PersistentRangeMarkerUtil.java @@ -48,11 +48,6 @@ public class PersistentRangeMarkerUtil { return false; } - if (rangeMarker.getStartOffset() == rangeMarker.getEndOffset() && e.getOffset() == rangeMarker.getStartOffset() && e.getOldLength() == 0) { - //One-point range marker - return true; - } - if (e.getOffset() >= rangeMarker.getEndOffset() || e.getOffset() + e.getOldLength() <= rangeMarker.getStartOffset()) { // Don't perform complex processing if the change doesn't affect target range. return false; From fa05e3b5e439a3038278e2627d4f1752c8daa364 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 6 Oct 2014 19:29:08 +0200 Subject: [PATCH 22/34] ContractInference: faster and lazier method notnull check --- .../codeInspection/dataFlow/ContractInference.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java index 63df26ff3e17..a23da345e7cb 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java @@ -84,10 +84,14 @@ class ContractInferenceInterpreter { } List inferContracts() { - final boolean notNull = NullableNotNullManager.isNotNull(myMethod); + List contracts = doInferContracts(); + if (contracts.isEmpty()) return contracts; + PsiTypeElement typeElement = myMethod.getReturnTypeElement(); final PsiType returnType = typeElement == null ? null : typeElement.getType(); - return ContainerUtil.filter(doInferContracts(), new Condition() { + final boolean notNull = !(returnType instanceof PsiPrimitiveType) && + NullableNotNullManager.getInstance(myMethod.getProject()).isNotNull(myMethod, false); + return ContainerUtil.filter(contracts, new Condition() { @Override public boolean value(MethodContract contract) { if (notNull && contract.returnValue == NOT_NULL_VALUE) { From db32cae0c74c9bfa4e439e548758cf718d8d6328 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Mon, 6 Oct 2014 21:32:08 +0400 Subject: [PATCH 23/34] IDEA-130808 Settings dialog: search field: clean icon disappears when focus is off the field Also, I fixed the issue with HAND cursor over the hidden icon. --- .../ui/laf/darcula/ui/DarculaTextFieldUI.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextFieldUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextFieldUI.java index 6d5bb3b40c43..7cffd25ae46c 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextFieldUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextFieldUI.java @@ -18,6 +18,7 @@ package com.intellij.ide.ui.laf.darcula.ui; import com.intellij.ide.ui.laf.darcula.DarculaUIUtil; import com.intellij.openapi.ui.GraphicsConfig; import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.Gray; import com.intellij.util.ui.JBInsets; @@ -103,15 +104,18 @@ public class DarculaTextFieldUI extends BasicTextFieldUI { } } + private boolean hasText() { + JTextComponent component = getComponent(); + return (component != null) && !StringUtil.isEmpty(component.getText()); + } + private SearchAction getActionUnder(MouseEvent e) { - final Point cPoint = getClearIconCoord(); - final Point sPoint = getSearchIconCoord(); - cPoint.x+=8; - cPoint.y+=8; - sPoint.x+=8; - sPoint.y+=8; - final Point ePoint = e.getPoint(); - return cPoint.distance(ePoint) <= 8 ? SearchAction.CLEAR : sPoint.distance(ePoint) <= 8 ? SearchAction.POPUP : null; + Point point = new Point(e.getX() - 8, e.getY() - 8); + return point.distance(getSearchIconCoord()) <= 8 + ? SearchAction.POPUP + : hasText() && point.distance(getClearIconCoord()) <= 8 + ? SearchAction.CLEAR + : null; } protected Rectangle getDrawingRect() { @@ -169,7 +173,7 @@ public class DarculaTextFieldUI extends BasicTextFieldUI { searchIcon = IconLoader.findIcon("/com/intellij/ide/ui/laf/icons/search.png", DarculaTextFieldUI.class, true); } searchIcon.paintIcon(null, g, p.x, p.y); - if (getComponent().hasFocus() && getComponent().getText().length() > 0) { + if (hasText()) { p = getClearIconCoord(); Icon clearIcon = UIManager.getIcon("TextField.darcula.clear.icon"); if (clearIcon == null) { From de5f5f0f765a631141d0334cc75e40954833bf6f Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Mon, 6 Oct 2014 21:37:51 +0400 Subject: [PATCH 24/34] PY-13740: Django 1.7 QuerySet.as_manager() code completion support --- ...DynamicMember.java => PyCustomMember.java} | 39 ++-- .../src/com/jetbrains/python/psi/PyClass.java | 14 +- .../com/jetbrains/python/psi/PyFunction.java | 46 +++++ .../psi/types/PyClassMembersProvider.java | 4 +- .../psi/types/PyClassMembersProviderBase.java | 10 +- .../psi/types/PyModuleMembersProvider.java | 8 +- .../jetbrains/python/psi/types/PyType.java | 4 +- .../python/psi/types/PyTypeProviderBase.java | 1 + .../NumpyModuleMembersProvider.java | 8 +- .../com/jetbrains/python/PyBundle.properties | 6 +- .../jetbrains/python/PyCustomMembersType.java | 189 ++++++++++++++++++ .../codeInsight/PyCustomMemberUtils.java | 34 ++++ .../PyMethodNavigationOffsetProvider.java | 2 +- .../PySuperMethodCompletionContributor.java | 4 +- .../override/PyOverrideImplementUtil.java | 2 +- .../stdlib/PyStdlibClassMembersProvider.java | 16 +- .../stdlib/PyStdlibModuleMembersProvider.java | 8 +- .../PyUserSkeletonsClassMembersProvider.java | 16 +- .../PyUserSkeletonsModuleMembersProvider.java | 8 +- .../PyOldStyleClassesInspection.java | 2 +- .../quickfix/AddFieldQuickFix.java | 2 +- .../PyUnresolvedReferencesInspection.java | 32 ++- .../python/projectView/PyElementNode.java | 2 +- .../com/jetbrains/python/psi/PsiQuery.java | 23 ++- .../python/psi/impl/PyClassImpl.java | 44 +++- .../python/psi/impl/PyEvaluator.java | 9 + .../python/psi/impl/PyFunctionImpl.java | 36 ++++ .../python/psi/types/PyClassTypeImpl.java | 21 +- .../python/psi/types/PyModuleType.java | 4 +- .../membersManager/MethodsManager.java | 4 +- .../extractmethod/PyExtractMethodUtil.java | 2 +- .../PythonAtTestConfigurationProducer.java | 2 +- .../testing/doctest/PythonDocTestUtil.java | 2 +- .../python/testing/pytest/PyTestUtil.java | 2 +- .../python/PyControlFlowBuilderTest.java | 4 +- .../com/jetbrains/python/PyOverrideTest.java | 8 +- .../com/jetbrains/python/PyStubsTest.java | 10 +- .../classes/PyDependenciesComparatorTest.java | 3 +- 38 files changed, 508 insertions(+), 123 deletions(-) rename python/psi-api/src/com/jetbrains/python/codeInsight/{PyDynamicMember.java => PyCustomMember.java} (80%) create mode 100644 python/src/com/jetbrains/python/PyCustomMembersType.java create mode 100644 python/src/com/jetbrains/python/codeInsight/PyCustomMemberUtils.java diff --git a/python/psi-api/src/com/jetbrains/python/codeInsight/PyDynamicMember.java b/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java similarity index 80% rename from python/psi-api/src/com/jetbrains/python/codeInsight/PyDynamicMember.java rename to python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java index a344e892588c..ffc846796806 100644 --- a/python/psi-api/src/com/jetbrains/python/codeInsight/PyDynamicMember.java +++ b/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java @@ -33,7 +33,7 @@ import javax.swing.*; /** * @author Dennis.Ushakov */ -public class PyDynamicMember { +public class PyCustomMember { private String myName; private final boolean myResolveToInstance; private final Function myTypeCallback; @@ -45,7 +45,7 @@ public class PyDynamicMember { boolean myFunction = false; - public PyDynamicMember(@NotNull final String name, @Nullable final String type, final boolean resolveToInstance) { + public PyCustomMember(@NotNull final String name, @Nullable final String type, final boolean resolveToInstance) { myName = name; myResolveToInstance = resolveToInstance; myTypeName = type; @@ -54,7 +54,7 @@ public class PyDynamicMember { myTypeCallback = null; } - public PyDynamicMember(@NotNull final String name) { + public PyCustomMember(@NotNull final String name) { myName = name; myResolveToInstance = false; myTypeName = null; @@ -63,9 +63,9 @@ public class PyDynamicMember { myTypeCallback = null; } - public PyDynamicMember(@NotNull final String name, - @Nullable final String type, - final Function typeCallback) { + public PyCustomMember(@NotNull final String name, + @Nullable final String type, + final Function typeCallback) { myName = name; myResolveToInstance = false; @@ -75,55 +75,58 @@ public class PyDynamicMember { myTypeCallback = typeCallback; } - public PyDynamicMember(@NotNull final String name, @Nullable final PsiElement target) { + public PyCustomMember(@NotNull final String name, @Nullable final PsiElement target, @Nullable String typeName) { myName = name; myTarget = target; myResolveToInstance = false; - myTypeName = null; + myTypeName = typeName; myTypeCallback = null; } + public PyCustomMember(@NotNull final String name, @Nullable final PsiElement target) { + this(name, target, null); + } - public PyDynamicMember resolvesTo(String moduleQName) { + public PyCustomMember resolvesTo(String moduleQName) { myPsiPath = new PyPsiPath.ToFile(moduleQName); return this; } - public PyDynamicMember resolvesToClass(String classQName) { + public PyCustomMember resolvesToClass(String classQName) { myPsiPath = new PyPsiPath.ToClassQName(classQName); return this; } - public PyDynamicMember toClass(String name) { + public PyCustomMember toClass(String name) { myPsiPath = new PyPsiPath.ToClass(myPsiPath, name); return this; } - public PyDynamicMember toFunction(String name) { + public PyCustomMember toFunction(String name) { myPsiPath = new PyPsiPath.ToFunction(myPsiPath, name); return this; } - public PyDynamicMember toFunctionRecursive(String name) { + public PyCustomMember toFunctionRecursive(String name) { myPsiPath = new PyPsiPath.ToFunctionRecursive(myPsiPath, name); return this; } - public PyDynamicMember toClassAttribute(String name) { + public PyCustomMember toClassAttribute(String name) { myPsiPath = new PyPsiPath.ToClassAttribute(myPsiPath, name); return this; } - public PyDynamicMember toCall(String name, String... args) { + public PyCustomMember toCall(String name, String... args) { myPsiPath = new PyPsiPath.ToCall(myPsiPath, name, args); return this; } - public PyDynamicMember toAssignment(String assignee) { + public PyCustomMember toAssignment(String assignee) { myPsiPath = new PyPsiPath.ToAssignment(myPsiPath, assignee); return this; } - public PyDynamicMember toPsiElement(final PsiElement psiElement) { + public PyCustomMember toPsiElement(final PsiElement psiElement) { myPsiPath = new PyPsiPath() { @Override @@ -179,7 +182,7 @@ public class PyDynamicMember { return myTypeName.substring(pos + 1); } - public PyDynamicMember asFunction() { + public PyCustomMember asFunction() { myFunction = true; return this; } diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyClass.java b/python/psi-api/src/com/jetbrains/python/psi/PyClass.java index a988714c144a..b6a26fc35539 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyClass.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyClass.java @@ -110,8 +110,12 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefine @NotNull PyExpression[] getSuperClassExpressions(); + /** + * @param inherited return inherited (parent) methods as well + * @return class methods + */ @NotNull - PyFunction[] getMethods(); + PyFunction[] getMethods(boolean inherited); /** * Get class properties. @@ -243,4 +247,12 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefine */ @Nullable PyExpression getMetaClassExpression(); + + /** + * + * @param context eval context + * @return {@link com.jetbrains.python.psi.types.PyType} casted if it has right type + */ + @Nullable + PyClassLikeType getType(@NotNull TypeEvalContext context); } diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyFunction.java b/python/psi-api/src/com/jetbrains/python/psi/PyFunction.java index e70a7ad12a51..0f7031b85dc2 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyFunction.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyFunction.java @@ -26,6 +26,8 @@ import com.jetbrains.python.psi.types.PyType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; + /** * Function declaration in source (the def and everything within). * @@ -101,4 +103,48 @@ extends @Nullable PyAnnotation getAnnotation(); + + // TODO: Doc + // + + /** + * Searches for function attributes. + * See PEP-0232 + * @return assignment statements for function attributes + */ + @NotNull + List findAttributes(); + + /** + * @return function protection level (underscore based) + */ + @NotNull + ProtectionLevel getProtectionLevel(); + + enum ProtectionLevel { + /** + * public members + */ + PUBLIC(0), + /** + * _protected_memebers + */ + PROTECTED(1), + /** + * __private_memebrs + */ + PRIVATE(2); + private final int myUnderscoreLevel; + + ProtectionLevel(final int underscoreLevel) { + myUnderscoreLevel = underscoreLevel; + } + + /** + * @return number of underscores + */ + public int getUnderscoreLevel() { + return myUnderscoreLevel; + } + } } diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProvider.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProvider.java index e051b48fbfaa..6a61de999abc 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProvider.java +++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProvider.java @@ -17,7 +17,7 @@ package com.jetbrains.python.psi.types; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.psi.PsiElement; -import com.jetbrains.python.codeInsight.PyDynamicMember; +import com.jetbrains.python.codeInsight.PyCustomMember; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -30,7 +30,7 @@ public interface PyClassMembersProvider { ExtensionPointName EP_NAME = ExtensionPointName.create("Pythonid.pyClassMembersProvider"); @NotNull - Collection getMembers(PyClassType clazz, @Nullable PsiElement location); + Collection getMembers(PyClassType clazz, @Nullable PsiElement location); @Nullable PsiElement resolveMember(PyClassType clazz, String name, @Nullable PsiElement location); diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProviderBase.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProviderBase.java index a7d66499cf52..6ec96559911a 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProviderBase.java +++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProviderBase.java @@ -16,7 +16,7 @@ package com.jetbrains.python.psi.types; import com.intellij.psi.PsiElement; -import com.jetbrains.python.codeInsight.PyDynamicMember; +import com.jetbrains.python.codeInsight.PyCustomMember; import com.jetbrains.python.psi.PyClass; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -30,22 +30,22 @@ import java.util.Collections; public class PyClassMembersProviderBase implements PyClassMembersProvider { @NotNull @Override - public Collection getMembers(PyClassType clazz, PsiElement location) { + public Collection getMembers(PyClassType clazz, PsiElement location) { return Collections.emptyList(); } @Override public PsiElement resolveMember(PyClassType clazz, String name, PsiElement location) { - final Collection members = getMembers(clazz, location); + final Collection members = getMembers(clazz, location); return resolveMemberByName(members, clazz, name); } @Nullable - public static PsiElement resolveMemberByName(Collection members, + public static PsiElement resolveMemberByName(Collection members, PyClassType clazz, String name) { final PyClass pyClass = clazz.getPyClass(); - for (PyDynamicMember member : members) { + for (PyCustomMember member : members) { if (member.getName().equals(name)) { return member.resolve(pyClass); } diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyModuleMembersProvider.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyModuleMembersProvider.java index 696dcaee6623..60d13fde976e 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/types/PyModuleMembersProvider.java +++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyModuleMembersProvider.java @@ -18,7 +18,7 @@ package com.jetbrains.python.psi.types; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; -import com.jetbrains.python.codeInsight.PyDynamicMember; +import com.jetbrains.python.codeInsight.PyCustomMember; import com.jetbrains.python.psi.PyFile; import com.jetbrains.python.psi.PyPsiFacade; import com.jetbrains.python.psi.resolve.PointInImport; @@ -33,7 +33,7 @@ import java.util.Collections; public abstract class PyModuleMembersProvider { public static final ExtensionPointName EP_NAME = ExtensionPointName.create("Pythonid.pyModuleMembersProvider"); - public Collection getMembers(PyFile module, PointInImport point) { + public Collection getMembers(PyFile module, PointInImport point) { final VirtualFile vFile = module.getVirtualFile(); if (vFile != null) { final String qName = PyPsiFacade.getInstance(module.getProject()).findShortestImportableName(vFile, module); @@ -46,7 +46,7 @@ public abstract class PyModuleMembersProvider { @Nullable public PsiElement resolveMember(PyFile module, String name) { - for (PyDynamicMember o : getMembers(module, PointInImport.NONE)) { + for (PyCustomMember o : getMembers(module, PointInImport.NONE)) { if (o.getName().equals(name)) { return o.resolve(module); } @@ -54,5 +54,5 @@ public abstract class PyModuleMembersProvider { return null; } - protected abstract Collection getMembersByQName(PyFile module, String qName); + protected abstract Collection getMembersByQName(PyFile module, String qName); } diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyType.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyType.java index 67ba765bbf81..4640fceb324d 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/types/PyType.java +++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyType.java @@ -47,8 +47,8 @@ public interface PyType { * or a list of elements that define the name, a la multiResolve(). */ @Nullable - List resolveMember(@NotNull final String name, @Nullable PyExpression location, - @NotNull AccessDirection direction, @NotNull PyResolveContext resolveContext); + List resolveMember(@NotNull String name, @Nullable final PyExpression location, + @NotNull final AccessDirection direction, @NotNull final PyResolveContext resolveContext); /** * Proposes completion variants from type's attributes. diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java index 0c60e6555b59..320397c4c12a 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java +++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java @@ -80,6 +80,7 @@ public class PyTypeProviderBase implements PyTypeProvider { } }; + @Nullable @Override public PyType getReferenceExpressionType(@NotNull PyReferenceExpression referenceExpression, @NotNull TypeEvalContext context) { return null; diff --git a/python/src/com/jetbrains/numpy/codeInsight/NumpyModuleMembersProvider.java b/python/src/com/jetbrains/numpy/codeInsight/NumpyModuleMembersProvider.java index 1fd2e3afd58f..fadf38916d0b 100644 --- a/python/src/com/jetbrains/numpy/codeInsight/NumpyModuleMembersProvider.java +++ b/python/src/com/jetbrains/numpy/codeInsight/NumpyModuleMembersProvider.java @@ -15,7 +15,7 @@ */ package com.jetbrains.numpy.codeInsight; -import com.jetbrains.python.codeInsight.PyDynamicMember; +import com.jetbrains.python.codeInsight.PyCustomMember; import com.jetbrains.python.psi.PyFile; import com.jetbrains.python.psi.types.PyModuleMembersProvider; @@ -39,11 +39,11 @@ public class NumpyModuleMembersProvider extends PyModuleMembersProvider { }; @Override - protected Collection getMembersByQName(PyFile module, String qName) { + protected Collection getMembersByQName(PyFile module, String qName) { if ("numpy".equals(qName)) { - final List members = new ArrayList(); + final List members = new ArrayList(); for (String type : NUMERIC_TYPES) { - members.add(new PyDynamicMember(type, "numpy.core.multiarray.dtype", false)); + members.add(new PyCustomMember(type, "numpy.core.multiarray.dtype", false)); } return members; } diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties index d82e9a6fde62..9e9c68f64a69 100644 --- a/python/src/com/jetbrains/python/PyBundle.properties +++ b/python/src/com/jetbrains/python/PyBundle.properties @@ -846,4 +846,8 @@ remote.interpreter.default.interpreter.path=/usr/bin/python remote.interpreter.unspecified.interpreter.path=Specify Python interpreter path remote.interpreter.unspecified.temp.files.path=Specify path for PyCharm helpers remote.interpreter.configure.path.label=Python interpreter path: -remote.interpreter.configure.temp.files.path.label=PyCharm helpers path: \ No newline at end of file +remote.interpreter.configure.temp.files.path.label=PyCharm helpers path: + +# Message we display for inspection if user uses custom class type members that do not exist +custom.type.name=Dynamic class +custom.type.mimic.name=Dynamic class based on {0} \ No newline at end of file diff --git a/python/src/com/jetbrains/python/PyCustomMembersType.java b/python/src/com/jetbrains/python/PyCustomMembersType.java new file mode 100644 index 000000000000..7e6b3b07f727 --- /dev/null +++ b/python/src/com/jetbrains/python/PyCustomMembersType.java @@ -0,0 +1,189 @@ +package com.jetbrains.python; + +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.psi.PsiElement; +import com.intellij.util.ArrayUtil; +import com.intellij.util.ProcessingContext; +import com.jetbrains.python.codeInsight.PyCustomMember; +import com.jetbrains.python.codeInsight.PyCustomMemberUtils; +import com.jetbrains.python.psi.AccessDirection; +import com.jetbrains.python.psi.PyCallSiteExpression; +import com.jetbrains.python.psi.PyExpression; +import com.jetbrains.python.psi.resolve.PyResolveContext; +import com.jetbrains.python.psi.resolve.RatedResolveResult; +import com.jetbrains.python.psi.types.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +/** + * Custom (aka dynamic) type that has some members you pass to it. To be used for cases like "type()" + * This class can also mimic any other class (optionally). When mimics, it has all methods from this class and its own. + * @author Ilya.Kazakevich + */ +public class PyCustomMembersType implements PyClassLikeType { + @NotNull + private final Map myMembers; + @Nullable + private final PyClassType myTypeToMimic; + + /** + * @param typeToMimic this type may mimic some other class-based type. Pass it to have all members from this class + custom. + * Check class manual for more info. + * @param members custom members + */ + public PyCustomMembersType(@Nullable final PyClassType typeToMimic, @NotNull final PyCustomMember... members) { + myTypeToMimic = typeToMimic; + + myMembers = new HashMap(members.length); + for (final PyCustomMember member : members) { + myMembers.put(member.getName(), member); + } + } + + /** + * @return class we mimic (if any). Check class manual for more info. + */ + @Nullable + public PyClassType getTypeToMimic() { + return myTypeToMimic; + } + + @Override + public boolean isDefinition() { + return false; + } + + @Override + public PyClassLikeType toInstance() { + return this; + } + + @Nullable + @Override + public String getClassQName() { + return null; + } + + @NotNull + @Override + public List getSuperClassTypes(@NotNull TypeEvalContext context) { + return Collections.emptyList(); + } + + @Nullable + @Override + public List resolveMember(@NotNull final String name, + @Nullable final PyExpression location, + @NotNull final AccessDirection direction, + @NotNull final PyResolveContext resolveContext, + final boolean inherited) { + if (myMembers.containsKey(name)) { + PsiElement context = null; + if (location != null) { + context = location; + } + if (context == null) { + context = resolveContext.getTypeEvalContext().getOrigin(); + } + if (context != null) { + final PsiElement resolveResult = myMembers.get(name).resolve(context); + if (resolveResult != null) { + return Collections.singletonList(new RatedResolveResult(0, resolveResult)); + } + } + } + if (myTypeToMimic != null) { + return myTypeToMimic.resolveMember(name, location, direction, resolveContext, inherited); + } + return null; + } + + @Override + public boolean isValid() { + return true; + } + + @Nullable + @Override + public PyClassLikeType getMetaClassType(@NotNull TypeEvalContext context, boolean inherited) { + return null; + } + + @Override + public boolean isCallable() { + return true; + } + + @Nullable + @Override + public PyType getReturnType(@NotNull TypeEvalContext context) { + return null; + } + + @Nullable + @Override + public PyType getCallType(@NotNull TypeEvalContext context, @NotNull PyCallSiteExpression callSite) { + return this; + } + + @Nullable + @Override + public List getParameters(@NotNull TypeEvalContext context) { + return null; + } + + @Nullable + @Override + public List resolveMember(@NotNull final String name, + @Nullable final PyExpression location, + @NotNull final AccessDirection direction, + @NotNull final PyResolveContext resolveContext) { + return resolveMember(name, location, direction, resolveContext, true); + } + + @Override + public Object[] getCompletionVariants(final String completionPrefix, final PsiElement location, final ProcessingContext context) { + final Collection lookupElements = new ArrayList(myMembers.size()); + for (final PyCustomMember member : myMembers.values()) { + lookupElements.add(PyCustomMemberUtils.toLookUpElement(member, member.getShortType())); + } + return ArrayUtil.mergeArrays(ArrayUtil.toObjectArray(lookupElements), + ((myTypeToMimic != null) + ? myTypeToMimic.getCompletionVariants(completionPrefix, location, context) + : PsiElement.EMPTY_ARRAY)); + } + + + @Nullable + @Override + public String getName() { + String mimicName = null; + if (myTypeToMimic != null) { + mimicName = myTypeToMimic.getName(); + } + if (mimicName != null) { + return PyBundle.message("custom.type.mimic.name", mimicName); + } + return PyBundle.message("custom.type.name"); + } + + @Override + public boolean isBuiltin() { + return false; + } + + @Override + public void assertValid(final String message) { + + } + + /** + * @param name name to check + * @return True if this class (not the one it mimics!) has member with passed name + */ + public boolean hasMember(@NotNull final String name) { + return myMembers.containsKey(name); + } +} diff --git a/python/src/com/jetbrains/python/codeInsight/PyCustomMemberUtils.java b/python/src/com/jetbrains/python/codeInsight/PyCustomMemberUtils.java new file mode 100644 index 000000000000..86da6a9326f5 --- /dev/null +++ b/python/src/com/jetbrains/python/codeInsight/PyCustomMemberUtils.java @@ -0,0 +1,34 @@ +package com.jetbrains.python.codeInsight; + +import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler; +import com.intellij.codeInsight.lookup.LookupElementBuilder; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * TODO: Move methods to {@link com.jetbrains.python.codeInsight.PyCustomMember}. Only dependency hell prevents me from doing it + */ +public final class PyCustomMemberUtils { + private PyCustomMemberUtils() { + } + + /** + * Creates {@link com.intellij.codeInsight.lookup.LookupElement} to be used in cases like {@link com.jetbrains.python.psi.types.PyType#getCompletionVariants(String, com.intellij.psi.PsiElement, com.intellij.util.ProcessingContext)} + * This method should be in {@link com.jetbrains.python.codeInsight.PyCustomMember} but it does not. We need to move it. + * + * @param member custom member + * @param typeText type text (if any) + * @return lookup element + */ + @NotNull + public static LookupElementBuilder toLookUpElement(@NotNull final PyCustomMember member, @Nullable final String typeText) { + + LookupElementBuilder lookupElementBuilder = LookupElementBuilder.create(member.getName()) + .withIcon(member.getIcon()) + .withTypeText(typeText); + if (member.isFunction()) { + lookupElementBuilder = lookupElementBuilder.withInsertHandler(ParenthesesInsertHandler.NO_PARAMETERS).withLookupString("()"); + } + return lookupElementBuilder; + } +} diff --git a/python/src/com/jetbrains/python/codeInsight/PyMethodNavigationOffsetProvider.java b/python/src/com/jetbrains/python/codeInsight/PyMethodNavigationOffsetProvider.java index 045bdc1307b3..a00366ab5d7d 100644 --- a/python/src/com/jetbrains/python/codeInsight/PyMethodNavigationOffsetProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/PyMethodNavigationOffsetProvider.java @@ -54,7 +54,7 @@ public class PyMethodNavigationOffsetProvider implements MethodNavigationOffsetP array.add(psiElement); } else if (psiElement instanceof PyClass) { - Collections.addAll(array, ((PyClass)psiElement).getMethods()); + Collections.addAll(array, ((PyClass)psiElement).getMethods(false)); } } } diff --git a/python/src/com/jetbrains/python/codeInsight/completion/PySuperMethodCompletionContributor.java b/python/src/com/jetbrains/python/codeInsight/completion/PySuperMethodCompletionContributor.java index 04ad5ae8e958..4778c6db1ccc 100644 --- a/python/src/com/jetbrains/python/codeInsight/completion/PySuperMethodCompletionContributor.java +++ b/python/src/com/jetbrains/python/codeInsight/completion/PySuperMethodCompletionContributor.java @@ -57,13 +57,13 @@ public class PySuperMethodCompletionContributor extends CompletionContributor { return; } Set seenNames = new HashSet(); - for (PyFunction function : containingClass.getMethods()) { + for (PyFunction function : containingClass.getMethods(false)) { seenNames.add(function.getName()); } LanguageLevel languageLevel = LanguageLevel.forElement(parameters.getOriginalFile()); seenNames.addAll(PyNames.getBuiltinMethods(languageLevel).keySet()); for (PyClass ancestor : containingClass.getAncestorClasses()) { - for (PyFunction superMethod : ancestor.getMethods()) { + for (PyFunction superMethod : ancestor.getMethods(false)) { if (!seenNames.contains(superMethod.getName())) { String text = superMethod.getName() + superMethod.getParameterList().getText(); LookupElementBuilder element = LookupElementBuilder.create(text); diff --git a/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java b/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java index 5a6caf0a8941..634eaf9a59c9 100644 --- a/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java +++ b/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java @@ -281,7 +281,7 @@ public class PyOverrideImplementUtil { public static Collection getAllSuperFunctions(@NotNull final PyClass pyClass) { final Map superFunctions = new HashMap(); for (PyClass aClass : pyClass.getAncestorClasses()) { - for (PyFunction function : aClass.getMethods()) { + for (PyFunction function : aClass.getMethods(false)) { if (!superFunctions.containsKey(function.getName())) { superFunctions.put(function.getName(), function); } diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibClassMembersProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibClassMembersProvider.java index b0b8c06c92de..334552aaf8c0 100644 --- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibClassMembersProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibClassMembersProvider.java @@ -17,7 +17,7 @@ package com.jetbrains.python.codeInsight.stdlib; import com.intellij.openapi.util.Key; import com.intellij.psi.PsiElement; -import com.jetbrains.python.codeInsight.PyDynamicMember; +import com.jetbrains.python.codeInsight.PyCustomMember; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyFile; import com.jetbrains.python.psi.PyTargetExpression; @@ -35,16 +35,16 @@ import java.util.List; * @author yole */ public class PyStdlibClassMembersProvider extends PyClassMembersProviderBase { - private Key> mySocketMembersKey = Key.create("socket.members"); + private Key> mySocketMembersKey = Key.create("socket.members"); @NotNull @Override - public Collection getMembers(PyClassType classType, PsiElement location) { + public Collection getMembers(PyClassType classType, PsiElement location) { PyClass clazz = classType.getPyClass(); final String qualifiedName = clazz.getQualifiedName(); if ("socket._socketobject".equals(qualifiedName)) { final PyFile socketFile = (PyFile)clazz.getContainingFile(); - List socketMembers = socketFile.getUserData(mySocketMembersKey); + List socketMembers = socketFile.getUserData(mySocketMembersKey); if (socketMembers == null) { socketMembers = calcSocketMembers(socketFile); socketFile.putUserData(mySocketMembersKey, socketMembers); @@ -54,20 +54,20 @@ public class PyStdlibClassMembersProvider extends PyClassMembersProviderBase { return Collections.emptyList(); } - private static List calcSocketMembers(PyFile socketFile) { - List result = new ArrayList(); + private static List calcSocketMembers(PyFile socketFile) { + List result = new ArrayList(); addMethodsFromAttr(socketFile, result, "_socketmethods"); addMethodsFromAttr(socketFile, result, "_delegate_methods"); return result; } - private static void addMethodsFromAttr(PyFile socketFile, List result, final String attrName) { + private static void addMethodsFromAttr(PyFile socketFile, List result, final String attrName) { final PyTargetExpression socketMethods = socketFile.findTopLevelAttribute(attrName); if (socketMethods != null) { final List methods = PyUtil.getStringListFromTargetExpression(socketMethods); if (methods != null) { for (String name : methods) { - result.add(new PyDynamicMember(name).resolvesTo("_socket").toClass("SocketType").toFunction(name)); + result.add(new PyCustomMember(name).resolvesTo("_socket").toClass("SocketType").toFunction(name)); } } } diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibModuleMembersProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibModuleMembersProvider.java index 80d3627ac083..a724b7808a75 100644 --- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibModuleMembersProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibModuleMembersProvider.java @@ -18,7 +18,7 @@ package com.jetbrains.python.codeInsight.stdlib; import com.intellij.openapi.util.SystemInfo; import com.intellij.psi.PsiElement; import com.intellij.psi.util.QualifiedName; -import com.jetbrains.python.codeInsight.PyDynamicMember; +import com.jetbrains.python.codeInsight.PyCustomMember; import com.jetbrains.python.psi.PyFile; import com.jetbrains.python.psi.resolve.ResolveImportUtil; import com.jetbrains.python.psi.types.PyModuleMembersProvider; @@ -33,15 +33,15 @@ import java.util.List; */ public class PyStdlibModuleMembersProvider extends PyModuleMembersProvider { @Override - protected Collection getMembersByQName(PyFile module, String qName) { + protected Collection getMembersByQName(PyFile module, String qName) { if (qName.equals("os")) { - final List results = new ArrayList(); + final List results = new ArrayList(); PsiElement path = null; if (module != null) { final String pathModuleName = SystemInfo.isWindows ? "ntpath" : "posixpath"; path = ResolveImportUtil.resolveModuleInRoots(QualifiedName.fromDottedString(pathModuleName), module); } - results.add(new PyDynamicMember("path", path)); + results.add(new PyCustomMember("path", path)); return results; } return Collections.emptyList(); diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java index 5ac7fc10751c..bcc39aab9010 100644 --- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java @@ -16,7 +16,7 @@ package com.jetbrains.python.codeInsight.userSkeletons; import com.intellij.psi.PsiElement; -import com.jetbrains.python.codeInsight.PyDynamicMember; +import com.jetbrains.python.codeInsight.PyCustomMember; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyFunction; import com.jetbrains.python.psi.PyTargetExpression; @@ -37,7 +37,7 @@ import java.util.List; public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderBase implements PyOverridingAncestorsClassMembersProvider { @NotNull @Override - public Collection getMembers(@NotNull PyClassType classType, PsiElement location) { + public Collection getMembers(@NotNull PyClassType classType, PsiElement location) { final PyClass cls = classType.getPyClass(); final PyClass skeleton = PyUserSkeletonsUtil.getUserSkeleton(cls); if (skeleton != null) { @@ -73,24 +73,24 @@ public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderB return null; } - private static Collection getClassMembers(@NotNull PyClass cls) { - final List result = new ArrayList(); - for (PyFunction function : cls.getMethods()) { + private static Collection getClassMembers(@NotNull PyClass cls) { + final List result = new ArrayList(); + for (PyFunction function : cls.getMethods(false)) { final String name = function.getName(); if (name != null) { - result.add(new PyDynamicMember(name, function)); + result.add(new PyCustomMember(name, function)); } } for (PyTargetExpression attribute : cls.getInstanceAttributes()) { final String name = attribute.getName(); if (name != null) { - result.add(new PyDynamicMember(name, attribute)); + result.add(new PyCustomMember(name, attribute)); } } for (PyTargetExpression attribute : cls.getClassAttributes()) { final String name = attribute.getName(); if (name != null) { - result.add(new PyDynamicMember(name, attribute)); + result.add(new PyCustomMember(name, attribute)); } } return result; diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsModuleMembersProvider.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsModuleMembersProvider.java index ad876ee4ec91..c42d15c6f463 100644 --- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsModuleMembersProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsModuleMembersProvider.java @@ -17,7 +17,7 @@ package com.jetbrains.python.codeInsight.userSkeletons; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFileSystemItem; -import com.jetbrains.python.codeInsight.PyDynamicMember; +import com.jetbrains.python.codeInsight.PyCustomMember; import com.jetbrains.python.psi.PyElement; import com.jetbrains.python.psi.PyFile; import com.jetbrains.python.psi.types.PyModuleMembersProvider; @@ -43,17 +43,17 @@ public class PyUserSkeletonsModuleMembersProvider extends PyModuleMembersProvide } @Override - protected Collection getMembersByQName(PyFile module, String qName) { + protected Collection getMembersByQName(PyFile module, String qName) { final PyFile moduleSkeleton = PyUserSkeletonsUtil.getUserSkeletonForModuleQName(qName, module); if (moduleSkeleton != null) { - final List results = new ArrayList(); + final List results = new ArrayList(); for (PyElement element : moduleSkeleton.iterateNames()) { if (element instanceof PsiFileSystemItem) { continue; } final String name = element.getName(); if (name != null) { - results.add(new PyDynamicMember(name, element)); + results.add(new PyCustomMember(name, element)); } } return results; diff --git a/python/src/com/jetbrains/python/inspections/PyOldStyleClassesInspection.java b/python/src/com/jetbrains/python/inspections/PyOldStyleClassesInspection.java index a253be86344f..0ea757dbebc1 100644 --- a/python/src/com/jetbrains/python/inspections/PyOldStyleClassesInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyOldStyleClassesInspection.java @@ -74,7 +74,7 @@ public class PyOldStyleClassesInspection extends PyInspection { registerProblem(attr, "Old-style class contains __slots__ definition", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, null, quickFixes.toArray(new LocalQuickFix[quickFixes.size()])); } } - for (PyFunction attr : node.getMethods()) { + for (PyFunction attr : node.getMethods(false)) { if ("__getattribute__".equals(attr.getName())) { final ASTNode nameNode = attr.getNameNode(); assert nameNode != null; diff --git a/python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java index 8ecd8a5d9b03..367f22b0540c 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java @@ -166,7 +166,7 @@ public class AddFieldQuickFix implements LocalQuickFix { appendToMethod(newInit, callback); PsiElement addAnchor = null; - PyFunction[] meths = cls.getMethods(); + PyFunction[] meths = cls.getMethods(false); if (meths.length > 0) addAnchor = meths[0].getPrevSibling(); PyStatementList clsContent = cls.getStatementList(); newInit = (PyFunction) clsContent.addAfter(newInit, addAnchor); diff --git a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java index 8049546a6e92..10b4c6f8705a 100644 --- a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java +++ b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java @@ -33,9 +33,10 @@ import com.intellij.psi.util.QualifiedName; import com.intellij.util.Consumer; import com.intellij.util.PlatformUtils; import com.jetbrains.python.PyBundle; +import com.jetbrains.python.PyCustomMembersType; import com.jetbrains.python.PyNames; import com.jetbrains.python.codeInsight.PyCodeInsightSettings; -import com.jetbrains.python.codeInsight.PyDynamicMember; +import com.jetbrains.python.codeInsight.PyCustomMember; import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil; import com.jetbrains.python.codeInsight.imports.AutoImportHintAction; @@ -462,7 +463,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection { } if (expr.isQualified()) { final PyClassTypeImpl object_type = (PyClassTypeImpl)PyBuiltinCache.getInstance(node).getObjectType(); - if ((object_type != null) && object_type.getPossibleInstanceMembers().contains(refName)){ + if ((object_type != null) && object_type.getPossibleInstanceMembers().contains(refName)) { return; } } @@ -542,6 +543,10 @@ public class PyUnresolvedReferencesInspection extends PyInspection { } markedQualified = true; } + else if (isHasCustomMember(refName, type)) { + // We have dynamic members + return; + } else { description = PyBundle.message("INSP.cannot.find.$0.in.$1", refText, type.getName()); markedQualified = true; @@ -605,6 +610,16 @@ public class PyUnresolvedReferencesInspection extends PyInspection { registerProblem(node, description, hl_type, null, rangeInElement, actions.toArray(new LocalQuickFix[actions.size()])); } + /** + * Checks if type is custom-member based and has custom member with certain name + * @param refName name to check + * @param type type + * @return true if has one + */ + private static boolean isHasCustomMember(@NotNull final String refName, @NotNull final PyType type) { + return (type instanceof PyCustomMembersType) && ((PyCustomMembersType)type).hasMember(refName); + } + /** * Return the canonical qualified name for a reference (even for an unresolved one). */ @@ -687,6 +702,13 @@ public class PyUnresolvedReferencesInspection extends PyInspection { return true; } } + if (type instanceof PyCustomMembersType) { + // Skip custom member types that mimics another class with fuzzy parents + PyClassType mimic = ((PyCustomMembersType)type).getTypeToMimic(); + if (mimic != null && PyUtil.hasUnresolvedAncestors(mimic.getPyClass(), myTypeEvalContext)) { + return true; + } + } if (type instanceof PyClassTypeImpl) { PyClass cls = ((PyClassType)type).getPyClass(); if (overridesGetAttr(cls, myTypeEvalContext)) { @@ -721,8 +743,8 @@ public class PyUnresolvedReferencesInspection extends PyInspection { PsiReference reference, @NotNull final String name) { for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) { - final Collection resolveResult = provider.getMembers(type, reference.getElement()); - for (PyDynamicMember member : resolveResult) { + final Collection resolveResult = provider.getMembers(type, reference.getElement()); + for (PyCustomMember member : resolveResult) { if (member.getName().equals(name)) return true; } } @@ -810,7 +832,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection { } } } - for (PyFunction method : containedClass.getMethods()) { + for (PyFunction method : containedClass.getMethods(false)) { if (expr.getText().equals(method.getName())) { actions.add(new UnresolvedReferenceAddSelfQuickFix(expr, qualifier)); } diff --git a/python/src/com/jetbrains/python/projectView/PyElementNode.java b/python/src/com/jetbrains/python/projectView/PyElementNode.java index 6ec347236773..3ef8ddd71a6b 100644 --- a/python/src/com/jetbrains/python/projectView/PyElementNode.java +++ b/python/src/com/jetbrains/python/projectView/PyElementNode.java @@ -50,7 +50,7 @@ public class PyElementNode extends BasePsiNode { for (PyClass aClass : pyClass.getNestedClasses()) { result.add(new PyElementNode(myProject, aClass, getSettings())); } - for (PyFunction function : pyClass.getMethods()) { + for (PyFunction function : pyClass.getMethods(false)) { result.add(new PyElementNode(myProject, function, getSettings())); } return result; diff --git a/python/src/com/jetbrains/python/psi/PsiQuery.java b/python/src/com/jetbrains/python/psi/PsiQuery.java index d41f6ba68a2c..3e1e26de12c3 100644 --- a/python/src/com/jetbrains/python/psi/PsiQuery.java +++ b/python/src/com/jetbrains/python/psi/PsiQuery.java @@ -172,9 +172,7 @@ public class PsiQuery { } } } - @SuppressWarnings("unchecked") // Type is preserved - final T[] array = (T[])result.toArray(new PsiElement[result.size()]); - return new PsiTypedQuery(clazz, array); + return new PsiTypedQuery(clazz, result); } @@ -309,14 +307,17 @@ public class PsiQuery { * Filter elements by class */ @NotNull - public PsiQuery filter(@NotNull final Class clazz) { + public PsiTypedQuery filter(@NotNull final Class clazz) { final Set result = new HashSet(Arrays.asList(myPsiElements)); for (final PsiElement element : myPsiElements) { - if (PyUtil.as(element, clazz) == null) { + if (!(clazz.isInstance(element))) { result.remove(element); } } - return new PsiQuery(result.toArray(new PsiElement[result.size()])); + // We checked it in runtime + @SuppressWarnings("unchecked") + final List toAdd = (List)new ArrayList(result); + return new PsiTypedQuery(clazz, toAdd); } @@ -351,16 +352,16 @@ public class PsiQuery { @NotNull private final Class myClass; @NotNull - private final T[] myElements; + private final List myElements; /** * @param clazz type * @param elements elements */ - private PsiTypedQuery(@NotNull final Class clazz, @NotNull final T... elements) { + private PsiTypedQuery(@NotNull final Class clazz, @NotNull final List elements) { super(elements); myClass = clazz; - myElements = elements.clone(); + myElements = elements; } /** @@ -383,8 +384,8 @@ public class PsiQuery { * @return All elements of certain type */ @NotNull - public T[] getElements() { - return myElements.clone(); + public List getElements() { + return Collections.unmodifiableList(myElements); } } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index 611cbc84ad2e..c7f2173973c0 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -389,9 +389,34 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla return result; } + @Override @NotNull - public PyFunction[] getMethods() { - return getClassChildren(PythonDialectsTokenSetProvider.INSTANCE.getFunctionDeclarationTokens(), PyFunction.ARRAY_FACTORY); + public PyFunction[] getMethods(final boolean inherited) { + final PyFunction[] thisClassFunctions = + getClassChildren(PythonDialectsTokenSetProvider.INSTANCE.getFunctionDeclarationTokens(), PyFunction.ARRAY_FACTORY); + if (!inherited) { + return thisClassFunctions; + } + // Map to get rid of duplicated (overwritten methods) + final Map result = new HashMap(); + // We get classes in MRO order (hopefully), so last methods are last + for (final PyClass superClass : getSuperClasses()) { + for (final PyFunction function : superClass.getMethods(false)) { + final String functionName = function.getName(); + if (functionName != null) { + result.put(functionName, function); + } + } + } + // We now need to add our own methods + for (final PyFunction function : thisClassFunctions) { + final String functionName = function.getName(); + if (functionName != null) { + result.put(functionName, function); + } + } + final Collection functionsToReturn = result.values(); + return functionsToReturn.toArray(new PyFunction[functionsToReturn.size()]); } @Override @@ -514,7 +539,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla // look at @property decorators Map> grouped = new HashMap>(); // group suitable same-named methods, each group defines a property - for (PyFunction method : getMethods()) { + for (PyFunction method : getMethods(false)) { final String methodName = method.getName(); if (name == null || name.equals(methodName)) { List bucket = grouped.get(methodName); @@ -826,7 +851,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla public boolean visitMethods(Processor processor, boolean inherited, boolean skipClassObj) { - PyFunction[] methods = getMethods(); + PyFunction[] methods = getMethods(false); if (!ContainerUtil.process(methods, processor)) return false; if (inherited) { for (PyClass ancestor : getAncestorClasses()) { @@ -932,7 +957,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla collectInstanceAttributes(initMethod, result); } Set namesInInit = new HashSet(result.keySet()); - final PyFunction[] methods = getMethods(); + final PyFunction[] methods = getMethods(false); for (PyFunction method : methods) { if (!PyNames.INIT.equals(method.getName())) { collectInstanceAttributes(method, result, namesInInit); @@ -981,7 +1006,8 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla final List result = new ArrayList(); statementList.accept(new PyRecursiveElementVisitor() { @Override - public void visitPyClass(PyClass node) {} + public void visitPyClass(PyClass node) { + } public void visitPyAssignmentStatement(final PyAssignmentStatement node) { for (PyExpression expression : node.getTargets()) { @@ -1338,4 +1364,10 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla } return null; } + + @Nullable + @Override + public PyClassLikeType getType(@NotNull TypeEvalContext context) { + return PyUtil.as(context.getType(this), PyClassLikeType.class); + } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyEvaluator.java b/python/src/com/jetbrains/python/psi/impl/PyEvaluator.java index dea9296f12c6..3f948c496592 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyEvaluator.java +++ b/python/src/com/jetbrains/python/psi/impl/PyEvaluator.java @@ -65,6 +65,15 @@ public class PyEvaluator { if (expr instanceof PySequenceExpression) { return evaluateSequenceExpression((PySequenceExpression)expr); } + if (expr instanceof PyQualifiedExpression) { // support bool + final String referencedName = ((PyQualifiedExpression)expr).getReferencedName(); + if (PyNames.TRUE.equals(referencedName)) { + return true; + } + if (PyNames.FALSE.equals(referencedName)) { + return true; + } + } if (expr instanceof PyCallExpression) { return evaluateCall((PyCallExpression)expr); } diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java index 2c1842f3337f..9f6afb5e43f7 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java @@ -23,6 +23,7 @@ import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; import com.intellij.psi.StubBasedPsiElement; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.SearchScope; @@ -699,4 +700,39 @@ public class PyFunctionImpl extends PyBaseElementImpl implements public String getQualifiedName() { return QualifiedNameFinder.getQualifiedName(this); } + + @NotNull + @Override + public List findAttributes() { + final List result = new ArrayList(); + for (final PyAssignmentStatement statement : new PsiQuery(this).siblings(PyAssignmentStatement.class).getElements()) { + for (final PyQualifiedExpression targetExpression : new PsiQuery(statement.getTargets()).filter(PyQualifiedExpression.class) + .getElements()) { + final PyExpression qualifier = targetExpression.getQualifier(); + if (qualifier == null) { + continue; + } + final PsiReference qualifierReference = qualifier.getReference(); + if (qualifierReference == null) { + continue; + } + if (qualifierReference.isReferenceTo(this)) { + result.add(statement); + } + } + } + return result; + } + + @NotNull + @Override + public ProtectionLevel getProtectionLevel() { + final int underscoreLevels = PyUtil.getInitialUnderscores(getName()); + for (final ProtectionLevel level : ProtectionLevel.values()) { + if (level.getUnderscoreLevel() == underscoreLevels) { + return level; + } + } + return ProtectionLevel.PRIVATE; + } } diff --git a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java index 34a92e16bf01..d9b69121aa50 100644 --- a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java +++ b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java @@ -16,7 +16,6 @@ package com.jetbrains.python.psi.types; import com.intellij.codeInsight.completion.CompletionUtil; -import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.openapi.extensions.Extensions; @@ -33,7 +32,8 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.ProcessingContext; import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.PyNames; -import com.jetbrains.python.codeInsight.PyDynamicMember; +import com.jetbrains.python.codeInsight.PyCustomMember; +import com.jetbrains.python.codeInsight.PyCustomMemberUtils; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyBuiltinCache; import com.jetbrains.python.psi.impl.ResolveResultList; @@ -151,7 +151,8 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { @NotNull PyResolveContext resolveContext, boolean inherited) { final TypeEvalContext context = resolveContext.getTypeEvalContext(); - PsiElement classMember = resolveByOverridingMembersProviders(this, name, location); //overriding members provers have priority to normal resolve + PsiElement classMember = + resolveByOverridingMembersProviders(this, name, location); //overriding members provers have priority to normal resolve if (classMember != null) { return ResolveResultList.to(classMember); } @@ -219,7 +220,8 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { } if (inherited) { - classMember = resolveByMembersProviders(this, name, location); //ask providers after real class introspection as providers have less priority + classMember = + resolveByMembersProviders(this, name, location); //ask providers after real class introspection as providers have less priority } if (classMember != null) { @@ -414,16 +416,11 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { addInheritedMembers(prefix, location, namesAlready, context, ret, typeEvalContext); // from providers - for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) { - for (PyDynamicMember member : provider.getMembers(this, location)) { + for (final PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) { + for (final PyCustomMember member : provider.getMembers(this, location)) { final String name = member.getName(); if (!namesAlready.contains(name)) { - LookupElementBuilder lookupElementBuilder = LookupElementBuilder.create(name).withIcon(member.getIcon()).withTypeText(getName()); - if (member.isFunction()) { - lookupElementBuilder = lookupElementBuilder.withInsertHandler(ParenthesesInsertHandler.NO_PARAMETERS); - lookupElementBuilder.withTailText("()"); - } - ret.add(lookupElementBuilder); + ret.add(PyCustomMemberUtils.toLookUpElement(member, getName())); } } } diff --git a/python/src/com/jetbrains/python/psi/types/PyModuleType.java b/python/src/com/jetbrains/python/psi/types/PyModuleType.java index db5a9ba3f1ae..0aec8612c989 100644 --- a/python/src/com/jetbrains/python/psi/types/PyModuleType.java +++ b/python/src/com/jetbrains/python/psi/types/PyModuleType.java @@ -30,7 +30,7 @@ import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ProcessingContext; import com.jetbrains.python.PyNames; -import com.jetbrains.python.codeInsight.PyDynamicMember; +import com.jetbrains.python.codeInsight.PyCustomMember; import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil; import com.jetbrains.python.psi.*; @@ -289,7 +289,7 @@ public class PyModuleType implements PyType { // Modules don't descend from obje Set namesAlready = context.get(CTX_NAMES); PointInImport point = ResolveImportUtil.getPointInImport(location); for (PyModuleMembersProvider provider : Extensions.getExtensions(PyModuleMembersProvider.EP_NAME)) { - for (PyDynamicMember member : provider.getMembers(myModule, point)) { + for (PyCustomMember member : provider.getMembers(myModule, point)) { final String name = member.getName(); if (namesAlready != null) { namesAlready.add(name); diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java index 52c32d95d38d..56bd80ca3077 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java +++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java @@ -44,7 +44,7 @@ class MethodsManager extends MembersManager { @Override public boolean hasConflict(@NotNull final PyFunction member, @NotNull final PyClass aClass) { - return NamePredicate.hasElementWithSameName(member, Arrays.asList(aClass.getMethods())); + return NamePredicate.hasElementWithSameName(member, Arrays.asList(aClass.getMethods(false))); } @NotNull @@ -64,7 +64,7 @@ class MethodsManager extends MembersManager { @NotNull @Override protected List getMembersCouldBeMoved(@NotNull final PyClass pyClass) { - return FluentIterable.from(Arrays.asList(pyClass.getMethods())).filter(new NamelessFilter()).filter(NO_PROPERTIES).toList(); + return FluentIterable.from(Arrays.asList(pyClass.getMethods(false))).filter(new NamelessFilter()).filter(NO_PROPERTIES).toList(); } @Override diff --git a/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java b/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java index d16712dea6c7..a396a354a381 100644 --- a/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java +++ b/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java @@ -181,7 +181,7 @@ public class PyExtractMethodUtil { scope.add(owner); final PyClass containingClass = ((PyFunction)owner).getContainingClass(); if (containingClass != null) { - for (PyFunction function : containingClass.getMethods()) { + for (PyFunction function : containingClass.getMethods(false)) { if (!function.equals(owner) && !function.equals(generatedMethod)) scope.add(function); } diff --git a/python/src/com/jetbrains/python/testing/attest/PythonAtTestConfigurationProducer.java b/python/src/com/jetbrains/python/testing/attest/PythonAtTestConfigurationProducer.java index d0a6d19e19e2..006749a25e96 100644 --- a/python/src/com/jetbrains/python/testing/attest/PythonAtTestConfigurationProducer.java +++ b/python/src/com/jetbrains/python/testing/attest/PythonAtTestConfigurationProducer.java @@ -60,7 +60,7 @@ public class PythonAtTestConfigurationProducer extends } private static boolean hasTestFunction(@NotNull final PyClass pyClass) { - PyFunction[] methods = pyClass.getMethods(); + PyFunction[] methods = pyClass.getMethods(false); for (PyFunction function : methods) { PyDecoratorList decorators = function.getDecoratorList(); if (decorators == null) continue; diff --git a/python/src/com/jetbrains/python/testing/doctest/PythonDocTestUtil.java b/python/src/com/jetbrains/python/testing/doctest/PythonDocTestUtil.java index fd6e9ef357af..b0889b72c46d 100644 --- a/python/src/com/jetbrains/python/testing/doctest/PythonDocTestUtil.java +++ b/python/src/com/jetbrains/python/testing/doctest/PythonDocTestUtil.java @@ -58,7 +58,7 @@ public class PythonDocTestUtil { } public static boolean isDocTestClass(PyClass pyClass) { - for (PyFunction cls : pyClass.getMethods()) { + for (PyFunction cls : pyClass.getMethods(false)) { if (isDocTestFunction(cls)) { return true; } diff --git a/python/src/com/jetbrains/python/testing/pytest/PyTestUtil.java b/python/src/com/jetbrains/python/testing/pytest/PyTestUtil.java index b6f463b15706..357227532727 100644 --- a/python/src/com/jetbrains/python/testing/pytest/PyTestUtil.java +++ b/python/src/com/jetbrains/python/testing/pytest/PyTestUtil.java @@ -80,7 +80,7 @@ public class PyTestUtil { if (className == null) return false; final String name = className.toLowerCase(); if (name.startsWith("test")) { - for (PyFunction cls : pyClass.getMethods()) { + for (PyFunction cls : pyClass.getMethods(false)) { if (isPyTestFunction(cls)) { return true; } diff --git a/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java b/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java index 203b462c5a44..c5e489c06485 100644 --- a/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java +++ b/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java @@ -205,7 +205,7 @@ public class PyControlFlowBuilderTest extends LightMarkedTestCase { configureByFile(testName + ".py"); final String fullPath = getTestDataPath() + testName + ".txt"; final PyClass pyClass = ((PyFile) myFile).getTopLevelClasses().get(0); - final ControlFlow flow = ControlFlowCache.getControlFlow(pyClass.getMethods()[0]); + final ControlFlow flow = ControlFlowCache.getControlFlow(pyClass.getMethods(false)[0]); check(fullPath, flow); } @@ -214,7 +214,7 @@ public class PyControlFlowBuilderTest extends LightMarkedTestCase { configureByFile(testName + ".py"); final String fullPath = getTestDataPath() + testName + ".txt"; final PyClass pyClass = ((PyFile) myFile).getTopLevelClasses().get(0); - final ControlFlow flow = ControlFlowCache.getControlFlow(pyClass.getMethods()[0]); + final ControlFlow flow = ControlFlowCache.getControlFlow(pyClass.getMethods(false)[0]); check(fullPath, flow); } diff --git a/python/testSrc/com/jetbrains/python/PyOverrideTest.java b/python/testSrc/com/jetbrains/python/PyOverrideTest.java index d80dc06182e7..fddb9e26c905 100644 --- a/python/testSrc/com/jetbrains/python/PyOverrideTest.java +++ b/python/testSrc/com/jetbrains/python/PyOverrideTest.java @@ -35,7 +35,7 @@ import java.util.Collections; public class PyOverrideTest extends PyTestCase { private void doTest() { myFixture.configureByFile("override/" + getTestName(true) + ".py"); - PyFunction toOverride = getTopLevelClass(0).getMethods() [0]; + PyFunction toOverride = getTopLevelClass(0).getMethods(false) [0]; PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), getTopLevelClass(1), Collections.singletonList(new PyMethodMember(toOverride)), false); myFixture.checkResultByFile("override/" + getTestName(true) + "_after.py", true); @@ -86,7 +86,7 @@ public class PyOverrideTest extends PyTestCase { public void testInnerClass() { // PY-10976 myFixture.configureByFile("override/" + getTestName(true) + ".py"); - PyFunction toOverride = getTopLevelClass(0).getMethods()[0]; + PyFunction toOverride = getTopLevelClass(0).getMethods(false)[0]; PyClass pyClass = getTopLevelClass(1).getNestedClasses()[0]; PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), pyClass, Collections.singletonList(new PyMethodMember(toOverride)), false); @@ -95,7 +95,7 @@ public class PyOverrideTest extends PyTestCase { public void testInnerFunctionClass() { myFixture.configureByFile("override/" + getTestName(true) + ".py"); - PyFunction toOverride = getTopLevelClass(0).getMethods()[0]; + PyFunction toOverride = getTopLevelClass(0).getMethods(false)[0]; final PsiElement element = myFixture.getElementAtCaret(); PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), PsiTreeUtil.getParentOfType(element, PyClass.class, false), Collections.singletonList(new PyMethodMember(toOverride)), false); @@ -115,7 +115,7 @@ public class PyOverrideTest extends PyTestCase { public void testImplement() { myFixture.configureByFile("override/" + getTestName(true) + ".py"); - PyFunction toImplement = getTopLevelClass(0).getMethods()[1]; + PyFunction toImplement = getTopLevelClass(0).getMethods(false)[1]; PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), getTopLevelClass(1), Collections.singletonList(new PyMethodMember(toImplement)), true); myFixture.checkResultByFile("override/" + getTestName(true) + "_after.py", true); diff --git a/python/testSrc/com/jetbrains/python/PyStubsTest.java b/python/testSrc/com/jetbrains/python/PyStubsTest.java index 0904b4c3d7d0..2a58613f1668 100644 --- a/python/testSrc/com/jetbrains/python/PyStubsTest.java +++ b/python/testSrc/com/jetbrains/python/PyStubsTest.java @@ -75,7 +75,7 @@ public class PyStubsTest extends PyTestCase { assertEquals("staticField", attrs.get(0).getName()); assertTrue(attrs.get(0).getAssignedQName().matches("deco")); - final PyFunction[] methods = pyClass.getMethods(); + final PyFunction[] methods = pyClass.getMethods(false); assertEquals(2, methods.length); assertEquals("__init__", methods [0].getName()); assertEquals("fooFunction", methods [1].getName()); @@ -122,7 +122,7 @@ public class PyStubsTest extends PyTestCase { Property prop = pyClass.findProperty("value", true); Maybe maybe_function = prop.getGetter(); assertTrue(maybe_function.isDefined()); - assertEquals(pyClass.getMethods()[0], maybe_function.value()); + assertEquals(pyClass.getMethods(false)[0], maybe_function.value()); Property setvalueProp = pyClass.findProperty("setvalue", true); Maybe setter = setvalueProp.getSetter(); @@ -135,10 +135,10 @@ public class PyStubsTest extends PyTestCase { prop = pyClass.findProperty("x", true); maybe_function = prop.getGetter(); assertTrue(maybe_function.isDefined()); - assertEquals(pyClass.getMethods()[0], maybe_function.value()); + assertEquals(pyClass.getMethods(false)[0], maybe_function.value()); maybe_function = prop.getSetter(); assertTrue(maybe_function.isDefined()); - assertEquals(pyClass.getMethods()[1], maybe_function.value()); + assertEquals(pyClass.getMethods(false)[1], maybe_function.value()); // ...and the juice: assertNotParsed(file); @@ -342,7 +342,7 @@ public class PyStubsTest extends PyTestCase { public void testWrappedStaticMethod() { final PyFileImpl file = (PyFileImpl) getTestFile(); final PyClass pyClass = file.getTopLevelClasses().get(0); - final PyFunction[] methods = pyClass.getMethods(); + final PyFunction[] methods = pyClass.getMethods(false); assertEquals(1, methods.length); final PyFunction.Modifier modifier = methods[0].getModifier(); assertEquals(PyFunction.Modifier.STATICMETHOD, modifier); diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/PyDependenciesComparatorTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/PyDependenciesComparatorTest.java index 9ebe01b127dc..b3be3825f970 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/classes/PyDependenciesComparatorTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/classes/PyDependenciesComparatorTest.java @@ -1,7 +1,6 @@ package com.jetbrains.python.refactoring.classes; import com.intellij.psi.PsiElement; -import com.intellij.util.text.Matcher; import com.jetbrains.python.fixtures.PyTestCase; import com.jetbrains.python.psi.*; import org.hamcrest.Matchers; @@ -23,7 +22,7 @@ public class PyDependenciesComparatorTest extends PyTestCase { @SuppressWarnings("ConstantConditions") // Can't be null (class has docstring) PsiElement docStringExpression = clazz.getDocStringExpression().getParent(); - PyFunction method = clazz.getMethods()[0]; + PyFunction method = clazz.getMethods(false)[0]; PsiElement classField = clazz.getClassAttributes().get(0).getParent(); final List elementList = new ArrayList(); From 0646c8b2fb3cd969556ef990d48ce485af90e097 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Mon, 6 Oct 2014 23:04:22 +0400 Subject: [PATCH 25/34] IDEA-130532 Bookmarks: merging lines with Delete or Backspace keys joins several bookmarks on the same line [added new test] --- .../ide/bookmarks/BookmarkManagerTest.java | 61 ++++++++++++++++++- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java b/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java index ed3c995edf48..e7503afea1a6 100644 --- a/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/ide/bookmarks/BookmarkManagerTest.java @@ -15,9 +15,7 @@ */ package com.intellij.ide.bookmarks; -import com.intellij.openapi.editor.CaretModel; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.impl.AbstractEditorTest; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.OpenFileDescriptor; @@ -30,6 +28,7 @@ import org.picocontainer.ComponentAdapter; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -91,6 +90,62 @@ public class BookmarkManagerTest extends AbstractEditorTest { delete(); assertTrue(getManager().getValidBookmarks().isEmpty()); } + + public void testTwoBookmarksOnSameLine1() throws IOException { + @NonNls String text = + "public class Test {\n" + + " public void test() {\n" + + " int i = 1;\n" + + " int j = 1;\n" + + " }\n" + + "}"; + init(text, TestFileType.TEXT); + + addBookmark(2); + addBookmark(3); + List bookmarksBefore = getManager().getValidBookmarks(); + assertEquals(2, bookmarksBefore.size()); + + myEditor.getCaretModel().setCaretsAndSelections( + Collections.singletonList(new CaretState(myEditor.visualToLogicalPosition(new VisualPosition(3, 0)), null, null))); + backspace(); + + List bookmarksAfter = getManager().getValidBookmarks(); + assertEquals(1, bookmarksAfter.size()); + for (Bookmark bookmark : bookmarksAfter) { + checkBookmarkNavigation(bookmark); + } + } + public void testTwoBookmarksOnSameLine2() throws IOException { + @NonNls String text = + "public class Test {\n" + + " public void test() {\n" + + " int i = 1;\n" + + " int j = 1;\n" + + " }\n" + + "}"; + init(text, TestFileType.TEXT); + + addBookmark(2); + addBookmark(3); + List bookmarksBefore = getManager().getValidBookmarks(); + assertEquals(2, bookmarksBefore.size()); + + myEditor.getCaretModel().setCaretsAndSelections( + Collections.singletonList(new CaretState(myEditor.visualToLogicalPosition(new VisualPosition(2, myEditor.getDocument().getLineEndOffset(2)+1)), null, null))); + delete(); + + List bookmarksAfter = getManager().getValidBookmarks(); + assertEquals(1, bookmarksAfter.size()); + for (Bookmark bookmark : bookmarksAfter) { + checkBookmarkNavigation(bookmark); + } + init(text, TestFileType.TEXT); + myEditor.getCaretModel().setCaretsAndSelections( + Collections.singletonList( + new CaretState(myEditor.visualToLogicalPosition(new VisualPosition(2, myEditor.getDocument().getLineEndOffset(2))), null, null))); + delete(); + } public void testBookmarkIsSavedAfterRemoteChange() throws IOException { @NonNls String text = From b81f65b4e80e033be1d6f124926a1e90f0f0be1d Mon Sep 17 00:00:00 2001 From: Stiver Date: Tue, 7 Oct 2014 07:31:22 +0200 Subject: [PATCH 26/34] Fixed some errors in line counting --- .../java/decompiler/main/ClassWriter.java | 13 ++++++---- .../decompiler/main/ClassesProcessor.java | 3 ++- .../collectors/BytecodeMappingTracer.java | 25 ++++++++++++++++--- .../main/collectors/BytecodeSourceMapper.java | 2 +- .../modules/decompiler/ExprProcessor.java | 6 ++--- .../decompiler/stats/CatchAllStatement.java | 12 ++++----- .../decompiler/stats/CatchStatement.java | 10 ++++---- .../modules/decompiler/stats/DoStatement.java | 18 ++++++------- .../modules/decompiler/stats/IfStatement.java | 16 +++++++----- .../decompiler/stats/SequenceStatement.java | 6 ++--- .../decompiler/stats/SwitchStatement.java | 10 ++++---- .../stats/SynchronizedStatement.java | 8 +++--- 12 files changed, 77 insertions(+), 52 deletions(-) diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java index 830e6683e5f3..0383dd410e47 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -182,8 +182,8 @@ public class ClassWriter { int start_class_def = buffer.length(); writeClassDefinition(node, buffer, indent); - // count lines in class definition the easiest way - total_offset_lines = buffer.substring(start_class_def).toString().split(lineSeparator, -1).length - 1; +// // count lines in class definition the easiest way +// total_offset_lines = buffer.substring(start_class_def).toString().split(lineSeparator, -1).length - 1; boolean hasContent = false; @@ -220,6 +220,9 @@ public class ClassWriter { buffer.append(lineSeparator); } + // FIXME: fields don't matter at the moment + total_offset_lines = buffer.substring(start_class_def).toString().split(lineSeparator, -1).length - 1; + // methods for (StructMethod mt : cl.getMethods()) { boolean hide = mt.isSynthetic() && DecompilerContext.getOption(IFernflowerPreferences.REMOVE_SYNTHETIC) || @@ -237,7 +240,7 @@ public class ClassWriter { hasContent = true; DecompilerContext.getBytecodeSourceMapper().addTracer(cl.qualifiedName, InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()), method_tracer); - total_offset_lines = method_tracer.getCurrentSourceline(); + total_offset_lines = (method_tracer.getCurrentSourceLine() + 1); // zero-based line index } else { buffer.setLength(position); @@ -805,7 +808,7 @@ public class ClassWriter { if (root != null && !methodWrapper.decompiledWithErrors) { // check for existence try { - tracer.setCurrentSourceline(buffer.substring(start_index_method).split(lineSeparator, -1).length - 1); + tracer.incrementCurrentSourceLine(buffer.substring(start_index_method).split(lineSeparator, -1).length - 1); String code = root.toJava(indent + 1, tracer); @@ -836,7 +839,7 @@ public class ClassWriter { // save total lines // TODO: optimize - tracer.setCurrentSourceline(buffer.substring(start_index_method).split(lineSeparator, -1).length - 1); + tracer.setCurrentSourceLine(buffer.substring(start_index_method).split(lineSeparator, -1).length - 1); return !hideMethod; } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java index bab697643e45..c79e3555daba 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java @@ -268,7 +268,7 @@ public class ClassesProcessor { int index = cl.qualifiedName.lastIndexOf("/"); if (index >= 0) { - total_offset_lines++; + total_offset_lines+=2; String packageName = cl.qualifiedName.substring(0, index).replace('/', '.'); buffer.append("package "); @@ -283,6 +283,7 @@ public class ClassesProcessor { buffer.append(lineSeparator); total_offset_lines += import_lines_written + 1; } + //buffer.append(lineSeparator); buffer.append(classBuffer); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeMappingTracer.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeMappingTracer.java index 95321e5d7537..20af4272e6ec 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeMappingTracer.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeMappingTracer.java @@ -1,6 +1,7 @@ package org.jetbrains.java.decompiler.main.collectors; import java.util.HashMap; +import java.util.Map.Entry; import java.util.Set; public class BytecodeMappingTracer { @@ -16,14 +17,20 @@ public class BytecodeMappingTracer { current_sourceline = initial_source_line; } - public void incrementSourceLine() { + public void incrementCurrentSourceLine() { current_sourceline++; } - public void incrementSourceLine(int number_lines) { + public void incrementCurrentSourceLine(int number_lines) { current_sourceline += number_lines; } + public void shiftSourceLines(int shift) { + for(Entry entry : mapping.entrySet()) { + entry.setValue(entry.getValue() + shift); + } + } + public void addMapping(int bytecode_offset) { if(!mapping.containsKey(bytecode_offset)) { mapping.put(bytecode_offset, current_sourceline); @@ -38,15 +45,25 @@ public class BytecodeMappingTracer { } } + public void addTracer(BytecodeMappingTracer tracer) { + if(tracer != null) { + for(Entry entry : tracer.mapping.entrySet()) { + if(!mapping.containsKey(entry.getKey())) { + mapping.put(entry.getKey(), entry.getValue()); + } + } + } + } + public HashMap getMapping() { return mapping; } - public int getCurrentSourceline() { + public int getCurrentSourceLine() { return current_sourceline; } - public void setCurrentSourceline(int current_sourceline) { + public void setCurrentSourceLine(int current_sourceline) { this.current_sourceline = current_sourceline; } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java index f31394b0a285..53f92b2bb2e8 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java @@ -59,7 +59,7 @@ public class BytecodeSourceMapper { buffer.append(indentstr1 + "method " + method_entry.getKey() + "{" + lineSeparator); for(Entry line : method_mapping.entrySet()) { - buffer.append(indentstr2 + line.getKey() + indentstr2 + line.getValue() + lineSeparator); + buffer.append(indentstr2 + line.getKey() + indentstr2 + (line.getValue() +offset_total) + lineSeparator); } buffer.append(indentstr1 + "}" + lineSeparator); is_first_method = false; diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java index f4b7aa271aea..dc284856a475 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java @@ -778,13 +778,13 @@ public class ExprProcessor implements CodeConstants { buf.append(" label").append(edge.closure.id); } buf.append(";").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } } if (buf.length() == 0 && semicolon) { buf.append(InterpreterUtil.getIndentString(indent)).append(";").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } return buf.toString(); @@ -828,7 +828,7 @@ public class ExprProcessor implements CodeConstants { buf.append(";"); } buf.append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java index 9ab7ec235c3f..f22d1b17eded 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java @@ -124,7 +124,7 @@ public class CatchAllStatement extends Statement { boolean labeled = isLabeled(); if (labeled) { buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } List lstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL); @@ -137,30 +137,30 @@ public class CatchAllStatement extends Statement { } else { buf.append(indstr).append("try {").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer)); buf.append(indstr).append("}"); } buf.append(isFinally ? " finally" : " catch (" + vars.get(0).toJava(indent, tracer) + ")").append(" {").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); if (monitor != null) { indstr1 = InterpreterUtil.getIndentString(indent + 1); buf.append(indstr1).append("if(").append(monitor.toJava(indent, tracer)).append(") {").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } buf.append(ExprProcessor.jmpWrapper(handler, indent + 1 + (monitor != null ? 1 : 0), true, tracer)); if (monitor != null) { buf.append(indstr1).append("}").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } buf.append(indstr).append("}").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); return buf.toString(); } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java index 7162f15eb072..a09625851d73 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java @@ -160,11 +160,11 @@ public class CatchStatement extends Statement { if (isLabeled()) { buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } buf.append(indstr).append("try {").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer)); buf.append(indstr).append("}"); @@ -183,14 +183,14 @@ public class CatchStatement extends Statement { } buf.append(vars.get(i - 1).toJava(indent, tracer)); buf.append(") {").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); buf.append(ExprProcessor.jmpWrapper(stats.get(i), indent + 1, true, tracer)).append(indstr) .append("}"); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } buf.append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); return buf.toString(); } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/DoStatement.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/DoStatement.java index 299659a0bb06..1ddce1b80637 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/DoStatement.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/DoStatement.java @@ -102,39 +102,39 @@ public class DoStatement extends Statement { if (isLabeled()) { buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } switch (looptype) { case LOOP_DO: buf.append(indstr).append("while(true) {").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer)); buf.append(indstr).append("}").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); break; case LOOP_DOWHILE: buf.append(indstr).append("do {").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer)); buf.append(indstr).append("} while(").append(conditionExprent.get(0).toJava(indent, tracer)).append(");").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); break; case LOOP_WHILE: buf.append(indstr).append("while(").append(conditionExprent.get(0).toJava(indent, tracer)).append(") {").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer)); buf.append(indstr).append("}").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); break; case LOOP_FOR: buf.append(indstr).append("for(").append(initExprent.get(0) == null ? "" : initExprent.get(0).toJava(indent, tracer)).append("; ") .append(conditionExprent.get(0).toJava(indent, tracer)).append("; ").append(incExprent.get(0).toJava(indent, tracer)).append(") {") .append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true, tracer)); buf.append(indstr).append("}").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } return buf.toString(); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java index 343d99ec38c3..ebe2bd793b11 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java @@ -211,11 +211,11 @@ public class IfStatement extends Statement { if (isLabeled()) { buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } buf.append(indstr).append(headexprent.get(0).toJava(indent, tracer)).append(" {").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); if (ifstat == null) { buf.append(InterpreterUtil.getIndentString(indent + 1)); @@ -235,7 +235,7 @@ public class IfStatement extends Statement { } } buf.append(";").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } else { buf.append(ExprProcessor.jmpWrapper(ifstat, indent + 1, true, tracer)); @@ -258,11 +258,15 @@ public class IfStatement extends Statement { elseif = true; } else { - String content = ExprProcessor.jmpWrapper(elsestat, indent + 1, false, tracer); + BytecodeMappingTracer else_tracer = new BytecodeMappingTracer(tracer.getCurrentSourceLine()); + String content = ExprProcessor.jmpWrapper(elsestat, indent + 1, false, else_tracer); if (content.length() > 0) { buf.append(indstr).append("} else {").append(new_line_separator); - tracer.incrementSourceLine(); // FIXME: wrong order + + else_tracer.shiftSourceLines(1); + tracer.setCurrentSourceLine(else_tracer.getCurrentSourceLine() + 1); + tracer.addTracer(else_tracer); buf.append(content); } @@ -271,7 +275,7 @@ public class IfStatement extends Statement { if (!elseif) { buf.append(indstr).append("}").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } return buf.toString(); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java index 24152f363d93..38420e0c2bc4 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java @@ -114,7 +114,7 @@ public class SequenceStatement extends Statement { indstr = InterpreterUtil.getIndentString(indent); indent++; buf.append(indstr).append("label").append(this.id).append(": {").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } boolean notempty = false; @@ -125,7 +125,7 @@ public class SequenceStatement extends Statement { if (i > 0 && notempty) { buf.append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } String str = ExprProcessor.jmpWrapper(st, indent, false, tracer); @@ -136,7 +136,7 @@ public class SequenceStatement extends Statement { if (islabeled) { buf.append(indstr).append("}").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } return buf.toString(); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java index 3b75fdce792b..aea44de948cc 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java @@ -119,11 +119,11 @@ public class SwitchStatement extends Statement { if (isLabeled()) { buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } buf.append(indstr).append(headexprent.get(0).toJava(indent, tracer)).append(" {").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); VarType switch_type = headexprent.get(0).getExprType(); @@ -136,14 +136,14 @@ public class SwitchStatement extends Statement { for (int j = 0; j < edges.size(); j++) { if (edges.get(j) == default_edge) { buf.append(indstr).append("default:").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } else { ConstExprent value = (ConstExprent)values.get(j).copy(); value.setConsttype(switch_type); buf.append(indstr).append("case ").append(value.toJava(indent, tracer)).append(":").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } } @@ -151,7 +151,7 @@ public class SwitchStatement extends Statement { } buf.append(indstr).append("}").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); return buf.toString(); } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java index 3d61198130ee..eb94ddc97265 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java @@ -80,17 +80,17 @@ public class SynchronizedStatement extends Statement { if (isLabeled()) { buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); } buf.append(indstr).append(headexprent.get(0).toJava(indent, tracer)).append(" {").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); buf.append(ExprProcessor.jmpWrapper(body, indent + 1, true, tracer)); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); buf.append(indstr).append("}").append(new_line_separator); - tracer.incrementSourceLine(); + tracer.incrementCurrentSourceLine(); return buf.toString(); } From c61a8809693c782e8416a81b2c332aa8c92fe62b Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Tue, 7 Oct 2014 11:24:34 +0400 Subject: [PATCH 27/34] library name for Java-WebSocket library license --- build/scripts/libLicenses.gant | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant index 66ac8a061d85..dfd53103ceca 100644 --- a/build/scripts/libLicenses.gant +++ b/build/scripts/libLicenses.gant @@ -189,7 +189,7 @@ libraryLicense(name: "JavaCVS", attachedTo: "javacvs-src", version: "no version libraryLicense(name: "JAXB", libraryName: "JAXB", version: "2.2.4-1", license: "CDDL 1.1", url: "http://jaxb.java.net/", licenseUrl: "http://glassfish.java.net/public/CDDL+GPL_1_1.html") libraryLicense(name: "Jaxen", version: "", license: "modified Apache", url: "http://www.jaxen.org/", licenseUrl: "http://www.jaxen.org/license.html") libraryLicense(name: "JavaHelp", version: "2.0_02", license: "included as license/javahelp_license.html in IntelliJ IDEA distribution", url: "http://java.sun.com/products/javahelp/") -libraryLicense(name: "Java-WebSocket", version: "1.3.0", license: "MIT", url: "https://github.com/TooTallNate/Java-WebSocket", licenseUrl:"https://github.com/TooTallNate/Java-WebSocket/blob/master/LICENSE") +libraryLicense(name: "Java-WebSocket", libraryName: "java_websocket.jar", version: "1.3.0", license: "MIT", url: "https://github.com/TooTallNate/Java-WebSocket", licenseUrl:"https://github.com/TooTallNate/Java-WebSocket/blob/master/LICENSE") libraryLicense(name: "JCIP Annotations", libraryName: "jcip", license: "Creative Commons Attribution License", url: "http://www.jcip.net", licenseUrl: "http://creativecommons.org/licenses/by/2.5") libraryLicense(name: "JDOM", version: "1.1 (with patches by JetBrains)", license: "modified Apache", url: "http://www.jdom.org/", licenseUrl: "http://www.jdom.org/docs/faq.html#a0030") libraryLicense(name: "javawriter", libraryName: "javawriter", license: "Apache 2.0", url: "https://github.com/square/javawriter") From 9d2a2daa9aeda82e4bae8e3f4a06e94dc56db22f Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 7 Oct 2014 11:39:34 +0400 Subject: [PATCH 28/34] use 'test' scope for dependency on 'junit' library --- python/ipnb/ipnb.iml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/python/ipnb/ipnb.iml b/python/ipnb/ipnb.iml index fe287d2fafbd..4fd2c2691fe1 100644 --- a/python/ipnb/ipnb.iml +++ b/python/ipnb/ipnb.iml @@ -15,7 +15,7 @@ - + @@ -26,5 +26,4 @@ - - + \ No newline at end of file From 4da5e7802a208ab6c56d935e2b8e06815594973d Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 7 Oct 2014 10:15:19 +0200 Subject: [PATCH 29/34] java-decompiler: test data path updated --- .../java/decompiler/IdeaDecompilerTest.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java b/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java index 29c7dc3d9c32..f99510e6625b 100644 --- a/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java +++ b/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java @@ -91,7 +91,7 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase { } public void testNavigation() { - VirtualFile file = getTestFile(); + VirtualFile file = getTestFile("Navigation.class"); myFixture.openFileInEditor(file); doTestNavigation(11, 14, 14, 10); // to "m2()" @@ -99,8 +99,24 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase { doTestNavigation(16, 28, 15, 13); // to "int r" } - private VirtualFile getTestFile() { - String path = PluginPathManager.getPluginHomePath("java-decompiler") + "/plugin/testData/" + getTestName(false) + ".class"; + public void testHighlighting() { + VirtualFile file = getTestFile("Navigation.class"); + myFixture.openFileInEditor(file); + + IdentifierHighlighterPassFactory.doWithHighlightingEnabled(new Runnable() { + public void run() { + myFixture.getEditor().getCaretModel().moveToOffset(offset(11, 14)); // m2(): usage, declaration + assertEquals(2, myFixture.doHighlighting().size()); + myFixture.getEditor().getCaretModel().moveToOffset(offset(15, 21)); // int i: usage, declaration + assertEquals(2, myFixture.doHighlighting().size()); + myFixture.getEditor().getCaretModel().moveToOffset(offset(16, 28)); // int r: usage, declaration + assertEquals(2, myFixture.doHighlighting().size()); + } + }); + } + + private static VirtualFile getTestFile(String name) { + String path = PluginPathManager.getPluginHomePath("java-decompiler") + "/plugin/testData/" + name; VirtualFile file = StandardFileSystems.local().findFileByPath(path); assertNotNull(path, file); return file; @@ -117,20 +133,4 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase { private int offset(int line, int column) { return myFixture.getEditor().getDocument().getLineStartOffset(line - 1) + column - 1; } - - public void testHighlighting() { - VirtualFile file = getTestFile(); - myFixture.openFileInEditor(file); - - IdentifierHighlighterPassFactory.doWithHighlightingEnabled(new Runnable() { - public void run() { - myFixture.getEditor().getCaretModel().moveToOffset(offset(11, 14)); // m2(): usage, declaration - assertEquals(2, myFixture.doHighlighting().size()); - myFixture.getEditor().getCaretModel().moveToOffset(offset(15, 21)); // int i: usage, declaration - assertEquals(2, myFixture.doHighlighting().size()); - myFixture.getEditor().getCaretModel().moveToOffset(offset(16, 28)); // int r: usage, declaration - assertEquals(2, myFixture.doHighlighting().size()); - } - }); - } } From 61f622fa791c86840e1771d6c7a9d3d3af51e3a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20C=C3=A9bron?= Date: Tue, 7 Oct 2014 10:18:21 +0200 Subject: [PATCH 30/34] vcs-impl: jUnit -> test scope --- platform/vcs-impl/vcs-impl.iml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/platform/vcs-impl/vcs-impl.iml b/platform/vcs-impl/vcs-impl.iml index 9492e1b4205c..364c9db4d10a 100644 --- a/platform/vcs-impl/vcs-impl.iml +++ b/platform/vcs-impl/vcs-impl.iml @@ -17,8 +17,7 @@ - + - - + \ No newline at end of file From 514ccfd88d3aaae275c5bf1f43261b8a3dcc2270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20C=C3=A9bron?= Date: Tue, 7 Oct 2014 10:32:09 +0200 Subject: [PATCH 31/34] learn-python: jUnit -> test scope --- python/edu/learn-python/learn-python.iml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/python/edu/learn-python/learn-python.iml b/python/edu/learn-python/learn-python.iml index 613d67594a7a..db91c2ed7f66 100644 --- a/python/edu/learn-python/learn-python.iml +++ b/python/edu/learn-python/learn-python.iml @@ -14,8 +14,7 @@ - + - - + \ No newline at end of file From e8be9c102a9a5755885477b6fe7aab50c1d402f5 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 7 Oct 2014 10:36:43 +0200 Subject: [PATCH 32/34] use language from context when create scratch file --- .../com/intellij/ide/scratch/NewScratchFileAction.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/ide/scratch/NewScratchFileAction.java b/platform/lang-impl/src/com/intellij/ide/scratch/NewScratchFileAction.java index 29320e24f9a4..790b36b414cb 100644 --- a/platform/lang-impl/src/com/intellij/ide/scratch/NewScratchFileAction.java +++ b/platform/lang-impl/src/com/intellij/ide/scratch/NewScratchFileAction.java @@ -21,6 +21,7 @@ import com.intellij.lang.LanguageUtil; import com.intellij.lang.StdLanguages; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.project.DumbAware; @@ -33,6 +34,7 @@ import com.intellij.openapi.ui.popup.util.BaseListPopupStep; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiFile; import com.intellij.util.Consumer; import com.intellij.util.ObjectUtils; import com.intellij.util.ui.EmptyIcon; @@ -63,6 +65,12 @@ public class NewScratchFileAction extends AnAction implements DumbAware { final Project project = e.getProject(); if (project == null) return; Language previous = ScratchpadManager.getInstance(project).getLatestLanguage(); + if (previous == null) { + PsiFile file = e.getData(CommonDataKeys.PSI_FILE); + if (file != null) { + previous = file.getLanguage(); + } + } ListPopup popup = buildLanguagePopup(previous, new Consumer() { @Override public void consume(Language language) { From 60b2b3a2e0f0316fdf5d2ef463d0bbe5ab1c7384 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 7 Oct 2014 12:45:15 +0400 Subject: [PATCH 33/34] fixed regression after fix for IDEA-130589 - not full value is shown in view full value for toString renderer --- .../src/com/intellij/debugger/engine/JavaValue.java | 10 +++++++++- .../debugger/ui/tree/render/LabelRenderer.java | 2 +- .../debugger/ui/tree/render/ToStringRenderer.java | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java index 5dc61a146a0b..a7f5b352c5ff 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java @@ -138,9 +138,13 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV presentation = new TypedStringValuePresentation(value, type); } else { + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") EvaluateException exception = myValueDescriptor.getEvaluateException(); if (myValueDescriptor.getLastRenderer() instanceof ToStringRenderer && exception == null) { - presentation = new XRegularValuePresentation(StringUtil.wrapWithDoubleQuote(value.substring(0,Math.min(value.length(), XValueNode.MAX_VALUE_LENGTH))), type); + presentation = new XRegularValuePresentation(StringUtil.wrapWithDoubleQuote(truncateToMaxLength(value)), type); + } + else if (myValueDescriptor.getLastRenderer() instanceof CompoundReferenceRenderer && exception == null) { + presentation = new XRegularValuePresentation(truncateToMaxLength(value), type); } else { presentation = new JavaValuePresentation(value, type, exception != null ? exception.getMessage() : null); @@ -180,6 +184,10 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV }); } + private static String truncateToMaxLength(String value) { + return value.substring(0, Math.min(value.length(), XValueNode.MAX_VALUE_LENGTH)); + } + private static class JavaValuePresentation extends XValuePresentation implements XValueCompactPresentation { private final String myValue; private final String myType; diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/LabelRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/LabelRenderer.java index 31a457a260af..2f40df45cd7c 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/LabelRenderer.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/LabelRenderer.java @@ -83,7 +83,7 @@ public class LabelRenderer extends com.intellij.debugger.ui.tree.render.Referenc } EvaluationContext thisEvaluationContext = evaluationContext.createEvaluationContext(value); Value labelValue = evaluator.evaluate(thisEvaluationContext); - result = DebuggerUtils.convertToPresentationString(DebuggerUtils.getValueAsString(thisEvaluationContext, labelValue)); + result = DebuggerUtils.getValueAsString(thisEvaluationContext, labelValue); } catch (final EvaluateException ex) { throw new EvaluateException(DebuggerBundle.message("error.unable.to.evaluate.expression") + " " + ex.getMessage(), ex); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ToStringRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ToStringRenderer.java index 4016289147a7..eb9bf6f5f284 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ToStringRenderer.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ToStringRenderer.java @@ -28,6 +28,7 @@ import com.intellij.debugger.ui.tree.ValueDescriptor; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.JDOMExternalizerUtil; import com.intellij.openapi.util.WriteExternalException; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.CommonClassNames; import com.intellij.psi.PsiExpression; import com.intellij.ui.classFilter.ClassFilter; @@ -78,8 +79,7 @@ public class ToStringRenderer extends NodeRendererImpl { BatchEvaluator.getBatchEvaluator(evaluationContext.getDebugProcess()).invoke(new ToStringCommand(evaluationContext, value) { public void evaluationResult(String message) { valueDescriptor.setValueLabel( - // no need to add quotes and escape characters here, XValueTextRendererImpl handles the presentation - message == null? "" : /*"\"" + DebuggerUtils.convertToPresentationString(*/DebuggerUtilsEx.truncateString(message)/*) + "\""*/ + StringUtil.notNullize(message) ); labelListener.labelChanged(); } From 97861493dbf2aa06c833a5af257b3c15a39b0cfc Mon Sep 17 00:00:00 2001 From: Sergey Simonchik Date: Tue, 7 Oct 2014 13:09:49 +0400 Subject: [PATCH 34/34] +gulpfile --- spellchecker/src/com/intellij/spellchecker/jetbrains.dic | 1 + 1 file changed, 1 insertion(+) diff --git a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic index b7738ec08ef8..6fc2aa0775b6 100644 --- a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic +++ b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic @@ -169,6 +169,7 @@ giud globals google gruntfile +gulpfile gzip gzipped hamcrest