From 0bbefa7e77c1e957844dedab50d2bfba8b9afbcc Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Tue, 15 Jan 2013 16:42:43 +0400 Subject: [PATCH 1/8] fixed PY-8200 Introduce parameter: do not allow refactoring when there is local variable in the selection --- .../PyIntroduceParameterHandler.java | 68 +++++++++++++------ .../introduceParameter/functionDef.py | 2 + .../refactoring/introduceParameter/global.py | 4 ++ .../introduceParameter/localVariable1.py | 3 + .../introduceParameter/localVariableInFor.py | 2 + .../introduceParameter/localVariableParam.py | 2 + .../introduceParameter/nonLocal.py | 4 ++ .../refactoring/PyIntroduceParameterTest.java | 32 +++++++++ 8 files changed, 95 insertions(+), 22 deletions(-) create mode 100644 python/testData/refactoring/introduceParameter/functionDef.py create mode 100644 python/testData/refactoring/introduceParameter/global.py create mode 100644 python/testData/refactoring/introduceParameter/localVariable1.py create mode 100644 python/testData/refactoring/introduceParameter/localVariableInFor.py create mode 100644 python/testData/refactoring/introduceParameter/localVariableParam.py create mode 100644 python/testData/refactoring/introduceParameter/nonLocal.py diff --git a/python/src/com/jetbrains/python/refactoring/introduce/parameter/PyIntroduceParameterHandler.java b/python/src/com/jetbrains/python/refactoring/introduce/parameter/PyIntroduceParameterHandler.java index 0148426ac4d3..e72aca56ec5c 100644 --- a/python/src/com/jetbrains/python/refactoring/introduce/parameter/PyIntroduceParameterHandler.java +++ b/python/src/com/jetbrains/python/refactoring/introduce/parameter/PyIntroduceParameterHandler.java @@ -2,6 +2,7 @@ package com.jetbrains.python.refactoring.introduce.parameter; import com.intellij.codeInsight.CodeInsightUtilBase; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiNamedElement; import com.intellij.psi.PsiReference; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.introduce.inplace.InplaceVariableIntroducer; @@ -61,32 +62,55 @@ public class PyIntroduceParameterHandler extends IntroduceHandler { protected boolean isValidIntroduceContext(PsiElement element) { if (element != null) { - final PyFunction function = PsiTreeUtil.getParentOfType(element, PyFunction.class); - final ScopeOwner scopeOwner = ScopeUtil.getScopeOwner(element); - final boolean[] isValid = {true}; - if (scopeOwner != null) { - new PyRecursiveElementVisitor() { - @Override - public void visitPyReferenceExpression(PyReferenceExpression node) { - super.visitPyReferenceExpression(node); - if (ControlFlowCache.getScope(scopeOwner).containsDeclaration(node.getName())) { - isValid[0] = false; - } - } - }.visitElement(element); - } - final PyStatement nonlocalStatement = - PsiTreeUtil.getParentOfType(element, PyNonlocalStatement.class, PyGlobalStatement.class); - final PyStatementList statementList = - PsiTreeUtil.getParentOfType(element, PyStatementList.class); - PyImportStatement importStatement = PsiTreeUtil.getParentOfType(element, PyImportStatement.class); - return function != null && !isResolvedToParameter(element) && isValid[0] && nonlocalStatement == null && - statementList != null && importStatement == null; + if (!isValidPlace(element)) return false; + + return isNotDeclared(element); } return false; } - private boolean isResolvedToParameter(PsiElement element) { + private static boolean isNotDeclared(PsiElement element) { + final ScopeOwner scopeOwner = ScopeUtil.getScopeOwner(element); + final boolean[] isValid = {true}; + + if (scopeOwner != null) { + final String name = element instanceof PsiNamedElement? ((PsiNamedElement)element).getName() : element.getText(); + if (name != null && ControlFlowCache.getScope(scopeOwner).containsDeclaration(name)) { + return false; + } + new PyRecursiveElementVisitor() { + @Override + public void visitPyReferenceExpression(PyReferenceExpression node) { + super.visitPyReferenceExpression(node); + + final String name = node.getName(); + if (name != null && ControlFlowCache.getScope(scopeOwner).containsDeclaration(name)) { + isValid[0] = false; + } + } + }.visitElement(element); + } + return !isResolvedToParameter(element) && isValid[0]; + } + + private static boolean isValidPlace(PsiElement element) { + final PyFunction function = PsiTreeUtil.getParentOfType(element, PyFunction.class); + final PyForPart forPart = PsiTreeUtil.getParentOfType(element, PyForPart.class); + if (forPart != null) { + final PyExpression target = forPart.getTarget(); + if (target instanceof PyTargetExpression && element.getText().equals(target.getName())) + return false; + } + final PyStatement nonlocalStatement = + PsiTreeUtil.getParentOfType(element, PyNonlocalStatement.class, PyGlobalStatement.class); + final PyStatementList statementList = + PsiTreeUtil.getParentOfType(element, PyStatementList.class); + PyImportStatement importStatement = PsiTreeUtil.getParentOfType(element, PyImportStatement.class); + return nonlocalStatement == null && importStatement == null && + statementList != null && function != null; + } + + private static boolean isResolvedToParameter(PsiElement element) { while (element instanceof PyReferenceExpression) { final PsiReference reference = element.getReference(); if (reference != null && reference.resolve() instanceof PyNamedParameter) diff --git a/python/testData/refactoring/introduceParameter/functionDef.py b/python/testData/refactoring/introduceParameter/functionDef.py new file mode 100644 index 000000000000..61262d42427b --- /dev/null +++ b/python/testData/refactoring/introduceParameter/functionDef.py @@ -0,0 +1,2 @@ +def f(b="myValue"): + pass \ No newline at end of file diff --git a/python/testData/refactoring/introduceParameter/global.py b/python/testData/refactoring/introduceParameter/global.py new file mode 100644 index 000000000000..ac3caa0898a8 --- /dev/null +++ b/python/testData/refactoring/introduceParameter/global.py @@ -0,0 +1,4 @@ +def f2(): + param = 1 + def f(): + global param \ No newline at end of file diff --git a/python/testData/refactoring/introduceParameter/localVariable1.py b/python/testData/refactoring/introduceParameter/localVariable1.py new file mode 100644 index 000000000000..a1c0d883a1af --- /dev/null +++ b/python/testData/refactoring/introduceParameter/localVariable1.py @@ -0,0 +1,3 @@ +def f(): + a = 1 + print a + 3 \ No newline at end of file diff --git a/python/testData/refactoring/introduceParameter/localVariableInFor.py b/python/testData/refactoring/introduceParameter/localVariableInFor.py new file mode 100644 index 000000000000..4b92eea3da06 --- /dev/null +++ b/python/testData/refactoring/introduceParameter/localVariableInFor.py @@ -0,0 +1,2 @@ +for item in range(100): + pass \ No newline at end of file diff --git a/python/testData/refactoring/introduceParameter/localVariableParam.py b/python/testData/refactoring/introduceParameter/localVariableParam.py new file mode 100644 index 000000000000..67011a83d668 --- /dev/null +++ b/python/testData/refactoring/introduceParameter/localVariableParam.py @@ -0,0 +1,2 @@ +def f(b=1): + return b + 1 \ No newline at end of file diff --git a/python/testData/refactoring/introduceParameter/nonLocal.py b/python/testData/refactoring/introduceParameter/nonLocal.py new file mode 100644 index 000000000000..1f42e3c56360 --- /dev/null +++ b/python/testData/refactoring/introduceParameter/nonLocal.py @@ -0,0 +1,4 @@ +def f2(): + param = 1 + def f(): + nonlocal param \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceParameterTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceParameterTest.java index 19047fc12fea..b31b0fb87048 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceParameterTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceParameterTest.java @@ -3,6 +3,7 @@ package com.jetbrains.python.refactoring; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.testFramework.TestDataPath; import com.jetbrains.python.PyBundle; +import com.jetbrains.python.psi.LanguageLevel; import com.jetbrains.python.refactoring.introduce.IntroduceHandler; import com.jetbrains.python.refactoring.introduce.parameter.PyIntroduceParameterHandler; @@ -35,6 +36,27 @@ public class PyIntroduceParameterTest extends PyIntroduceTestCase { doTestCannotPerform(PyBundle.message("refactoring.introduce.selection.error")); } + public void testLocalVariable1() { + doTestCannotPerform(PyBundle.message("refactoring.introduce.selection.error")); + } + + public void testLocalVariableParam() { + doTestCannotPerform(PyBundle.message("refactoring.introduce.selection.error")); + } + + public void testNonLocal() { + doTestCannotPerform(PyBundle.message("refactoring.introduce.selection.error"), LanguageLevel.PYTHON32); + } + + public void testGlobal() { + doTestCannotPerform(PyBundle.message("refactoring.introduce.selection.error")); + } + + public void testFunctionDef() { + doTestCannotPerform(PyBundle.message("refactoring.introduce.selection.error")); + } + + @Override protected String getTestDataPath() { return super.getTestDataPath() + "/refactoring/introduceParameter"; @@ -52,4 +74,14 @@ public class PyIntroduceParameterTest extends PyIntroduceTestCase { assertEquals(expected, e.getMessage()); } } + + private void doTestCannotPerform(String expected, LanguageLevel languageLevel) { + setLanguageLevel(languageLevel); + try { + doTestCannotPerform(expected); + } + finally { + setLanguageLevel(null); + } + } } From 35ee12fefa91a7d167aef030b6645733a9c94aa4 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Tue, 15 Jan 2013 16:55:40 +0400 Subject: [PATCH 2/8] fixed PY-8151 Don't highlight deprecation on symbols imported as fallbacks after ImportError --- .../python/inspections/PyDeprecationInspection.java | 10 +++++++--- python/testData/deprecation/deprecatedAsFallback.py | 4 ++++ .../com/jetbrains/python/PyDeprecationTest.java | 6 ++++++ 3 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 python/testData/deprecation/deprecatedAsFallback.py diff --git a/python/src/com/jetbrains/python/inspections/PyDeprecationInspection.java b/python/src/com/jetbrains/python/inspections/PyDeprecationInspection.java index a119489b548e..f6ec90fa9d3b 100644 --- a/python/src/com/jetbrains/python/inspections/PyDeprecationInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyDeprecationInspection.java @@ -6,9 +6,8 @@ import com.intellij.codeInspection.ProblemsHolder; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; -import com.jetbrains.python.psi.PyFile; -import com.jetbrains.python.psi.PyFunction; -import com.jetbrains.python.psi.PyReferenceExpression; +import com.intellij.psi.util.PsiTreeUtil; +import com.jetbrains.python.psi.*; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,6 +38,11 @@ public class PyDeprecationInspection extends PyInspection { @Override public void visitPyReferenceExpression(PyReferenceExpression node) { + final PyExceptPart exceptPart = PsiTreeUtil.getParentOfType(node, PyExceptPart.class); + if (exceptPart != null) { + final PyExpression exceptClass = exceptPart.getExceptClass(); + if (exceptClass != null && "ImportError".equals(exceptClass.getText())) return; + } PsiElement resolveResult = node.getReference(resolveWithoutImplicits()).resolve(); String deprecationMessage = null; if (resolveResult instanceof PyFunction) { diff --git a/python/testData/deprecation/deprecatedAsFallback.py b/python/testData/deprecation/deprecatedAsFallback.py new file mode 100644 index 000000000000..5302aeca7437 --- /dev/null +++ b/python/testData/deprecation/deprecatedAsFallback.py @@ -0,0 +1,4 @@ +try: + from urlparse import parse_qs, parse_qsl +except ImportError: + from cgi import parse_qs, parse_qsl \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyDeprecationTest.java b/python/testSrc/com/jetbrains/python/PyDeprecationTest.java index abb10de9c0f8..3a63d62acf6f 100644 --- a/python/testSrc/com/jetbrains/python/PyDeprecationTest.java +++ b/python/testSrc/com/jetbrains/python/PyDeprecationTest.java @@ -27,6 +27,12 @@ public class PyDeprecationTest extends PyTestCase { assertNotParsed((PyFile) myFixture.getFile()); } + public void testDeprecatedAsFallback() { + myFixture.enableInspections(PyDeprecationInspection.class); + myFixture.configureByFile("deprecation/deprecatedAsFallback.py"); + myFixture.checkHighlighting(true, false, false); + } + public void testDeprecatedProperty() { myFixture.enableInspections(PyDeprecationInspection.class); myFixture.configureByFile("deprecation/deprecatedProperty.py"); From 519b7a9b74d939564f9dc0c789d2ddbb8ca5c618 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 16 Jan 2013 14:48:01 +0400 Subject: [PATCH 3/8] fixed PY-7829 Ignore missing docstring inspection feedback for Django model inner Meta classes --- .../jetbrains/python/inspections/PyDocstringInspection.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/inspections/PyDocstringInspection.java b/python/src/com/jetbrains/python/inspections/PyDocstringInspection.java index 06f14fa2498b..0914a4b0c2f4 100644 --- a/python/src/com/jetbrains/python/inspections/PyDocstringInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyDocstringInspection.java @@ -13,6 +13,8 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; +import com.jetbrains.django.model.DjangoMeta; +import com.jetbrains.django.model.DjangoModel; import com.jetbrains.python.PyBundle; import com.jetbrains.python.PyNames; import com.jetbrains.python.documentation.*; @@ -68,7 +70,9 @@ public class PyDocstringInspection extends PyInspection { @Override public void visitPyClass(PyClass node) { final String name = node.getName(); - if (name != null && !name.startsWith("_")) checkDocString(node); + final PyClass outerClass = PsiTreeUtil.getParentOfType(node, PyClass.class); + final boolean isDjangoMeta = DjangoModel.isDjangoModelDescendant(outerClass) && DjangoMeta.isMetaClass(node); + if (name != null && !name.startsWith("_") && !isDjangoMeta) checkDocString(node); } private void checkDocString(PyDocStringOwner node) { From df5ef4abf17e6ff8a72173a5f81db0ecebc2fe57 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 16 Jan 2013 16:12:55 +0400 Subject: [PATCH 4/8] fixed Convert triple-quoted string: loses data in case of double quote inside the string and leads to syntax error --- .../PyConvertTripleQuotedStringIntention.java | 10 +--------- .../intentions/afterConvertTripleQuotedString1.py | 3 +++ .../intentions/beforeConvertTripleQuotedString1.py | 3 +++ .../testSrc/com/jetbrains/python/PyIntentionTest.java | 5 +++++ 4 files changed, 12 insertions(+), 9 deletions(-) create mode 100644 python/testData/intentions/afterConvertTripleQuotedString1.py create mode 100644 python/testData/intentions/beforeConvertTripleQuotedString1.py diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertTripleQuotedStringIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertTripleQuotedStringIntention.java index 035f199d2358..339f32fc6853 100644 --- a/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertTripleQuotedStringIntention.java +++ b/python/src/com/jetbrains/python/codeInsight/intentions/PyConvertTripleQuotedStringIntention.java @@ -95,16 +95,8 @@ public class PyConvertTripleQuotedStringIntention extends BaseIntentionAction { subString = convertToValidSubString(trimmed.substring(0, trimmed.length() - 3), firstQuote); } else { - s = StringUtil.escapeStringCharacters(s); StringBuilder stringBuilder = new StringBuilder(); - for (Character ch : s.toCharArray()) { - if (ch == firstQuote) { - stringBuilder.append("\\").append(firstQuote); - } - else { - stringBuilder.append(ch); - } - } + stringBuilder = StringUtil.escapeStringCharacters(s.length(), s, String.valueOf(firstQuote), true, stringBuilder); subString = stringBuilder.toString(); } return subString; diff --git a/python/testData/intentions/afterConvertTripleQuotedString1.py b/python/testData/intentions/afterConvertTripleQuotedString1.py new file mode 100644 index 000000000000..90c7819ca4e4 --- /dev/null +++ b/python/testData/intentions/afterConvertTripleQuotedString1.py @@ -0,0 +1,3 @@ +s = ("\n" + "my quote\" some text after it\n" +) \ No newline at end of file diff --git a/python/testData/intentions/beforeConvertTripleQuotedString1.py b/python/testData/intentions/beforeConvertTripleQuotedString1.py new file mode 100644 index 000000000000..bc08e8b13fa4 --- /dev/null +++ b/python/testData/intentions/beforeConvertTripleQuotedString1.py @@ -0,0 +1,3 @@ +s = """ +my quote" some text after it +""" \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyIntentionTest.java b/python/testSrc/com/jetbrains/python/PyIntentionTest.java index 8d9b82e994e1..6dc0a3cfda75 100644 --- a/python/testSrc/com/jetbrains/python/PyIntentionTest.java +++ b/python/testSrc/com/jetbrains/python/PyIntentionTest.java @@ -237,10 +237,15 @@ public class PyIntentionTest extends PyTestCase { public void testConvertVariadicParam() { //PY-2264 doTest(PyBundle.message("INTN.convert.variadic.param")); } + public void testConvertTripleQuotedString() { //PY-2697 doTest(PyBundle.message("INTN.triple.quoted.string")); } + public void testConvertTripleQuotedString1() { //PY-7774 + doTest(PyBundle.message("INTN.triple.quoted.string")); + } + public void testTransformConditionalExpression() { //PY-3094 doTest(PyBundle.message("INTN.transform.into.if.else.statement")); } From 2cad8ebd16b29b96657e0a9f81f6278f3f9785e1 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Wed, 16 Jan 2013 16:48:14 +0400 Subject: [PATCH 5/8] Moved Python-related icons to resources/icons/ folders --- .../python/facet/PythonFacetType.java | 2 +- .../facet/PythonFrameworkSupportProvider.java | 2 +- python/psi-api/python-psi-api.iml | 1 + .../icons/com/jetbrains/python/pythonFile.png | Bin 0 -> 612 bytes .../com/jetbrains/python/PythonFileType.java | 7 ++----- .../psi-api/src/icons/PythonPsiApiIcons.java | 17 +++++++++++++++++ .../resources/icons/com/jetbrains/rest/rst.png | Bin 0 -> 458 bytes python/rest/src/icons/RestIcons.java | 2 +- python/src/com/jetbrains/pyqt/tsFile.png | Bin 316 -> 0 bytes python/src/com/jetbrains/pyqt/uiForm.png | Bin 879 -> 0 bytes .../jetbrains/python/PythonModuleTypeBase.java | 4 ++-- .../python/buildout/BuildoutFacetType.java | 2 +- .../buildout/config/BuildoutCfgFileType.java | 2 +- ...pecialMethodNamesCompletionContributor.java | 2 +- .../PythonDebugLanguageConsoleView.java | 2 +- .../python/console/RunPythonConsoleAction.java | 3 +-- .../python/psi/impl/PyFunctionImpl.java | 6 +++--- .../python/run/PythonConfigurationType.java | 2 +- .../jetbrains/python/sdk/PythonSdkType.java | 2 +- .../sdk/flavors/IronPythonSdkFlavor.java | 2 +- .../python/sdk/flavors/JythonSdkFlavor.java | 2 +- .../python/sdk/flavors/PyPySdkFlavor.java | 2 +- .../python/sdk/flavors/PythonSdkFlavor.java | 2 +- .../sdk/flavors/VirtualEnvSdkFlavor.java | 2 +- .../structureView/PyStructureViewElement.java | 6 +++--- .../testing/PythonTestConfigurationType.java | 2 +- 26 files changed, 44 insertions(+), 30 deletions(-) create mode 100644 python/psi-api/resources/icons/com/jetbrains/python/pythonFile.png create mode 100644 python/psi-api/src/icons/PythonPsiApiIcons.java create mode 100644 python/rest/resources/icons/com/jetbrains/rest/rst.png delete mode 100644 python/src/com/jetbrains/pyqt/tsFile.png delete mode 100644 python/src/com/jetbrains/pyqt/uiForm.png diff --git a/python/pluginSrc/com/jetbrains/python/facet/PythonFacetType.java b/python/pluginSrc/com/jetbrains/python/facet/PythonFacetType.java index b1f0f0f7e991..9f761daceec5 100644 --- a/python/pluginSrc/com/jetbrains/python/facet/PythonFacetType.java +++ b/python/pluginSrc/com/jetbrains/python/facet/PythonFacetType.java @@ -57,7 +57,7 @@ public class PythonFacetType extends FacetType { diff --git a/python/pluginSrc/com/jetbrains/python/facet/PythonFrameworkSupportProvider.java b/python/pluginSrc/com/jetbrains/python/facet/PythonFrameworkSupportProvider.java index 98586d34b5df..67b1be902efc 100644 --- a/python/pluginSrc/com/jetbrains/python/facet/PythonFrameworkSupportProvider.java +++ b/python/pluginSrc/com/jetbrains/python/facet/PythonFrameworkSupportProvider.java @@ -22,7 +22,7 @@ public class PythonFrameworkSupportProvider extends FrameworkSupportProvider { @Override public Icon getIcon() { - return PythonIcons.Python.Icons.Python; + return PythonIcons.Python.Python; } @NotNull diff --git a/python/psi-api/python-psi-api.iml b/python/psi-api/python-psi-api.iml index 5e3914f028e3..e64340eea3fa 100644 --- a/python/psi-api/python-psi-api.iml +++ b/python/psi-api/python-psi-api.iml @@ -4,6 +4,7 @@ + diff --git a/python/psi-api/resources/icons/com/jetbrains/python/pythonFile.png b/python/psi-api/resources/icons/com/jetbrains/python/pythonFile.png new file mode 100644 index 0000000000000000000000000000000000000000..ccd74ff4320c0411c2a5690ac76bdbe0e9d66264 GIT binary patch literal 612 zcmV-q0-ODbP)pFGFBUV~Q_BU`bwzY=5X=b){TzqE~C5QfHn~W}QM= zlU8n#|NsAUgv;gd`{?ui{Qdr0ZKwVI|L5`g^7#G!{{Qau`C*W@=<@vT^Z4oW{9})= zJ8_;ZWt_ssoBR3Y^Z5NdbfH3ZpFnV$H)fJDV34r0ZtB%QI&z*haHBtPn^Ss|PjirG zgOkg{Qt8JVFlCfPbe+1yeBsqd+|5Yg%|GeKCE&CgQGBRphm_peMeE!y>d7hNz9rYM zAIzj3;OO$QzrEnfFyzG}(z8R_$btL({_FMqx69?{@cN~>(`b9c=komY`u^ts|MmL* z;rjjU=FIK&{pIfZ`~3Ie!bQ}p6TX-fvXdp*%%0xq_~7gL-|G0^>-ez7*Vg3sl&IQW zaH~FYm@{pcTa2~p_54nLs^aPE^7sAh^ZclXlQIAR02FjmPE!Es*z4Z_A{aQ=EYsiL z-{0Tg+s-E?1Kt1t0I5ktK~xx5ZH+Ms!ax)S=f&VIS{Mu{B6yD=SO``&V&T0!fY{qw zr%PueF&0000et`u+v4op;FMiZ$g3pN`(L3=>HdF{~TxkQHlRki~n1V|67m$W0e17mH%v-{cW24 zc%l1vqWplS`+=nSgOaI;sriYg_>ivnk+1lcvGc%Q*hkq|3Ff05nlJ+>Hk4fZ{X?w5nuh|?Ed5I|K#lchS*S^8Z3ra9y45d;kCd3v^OWQvm7h^7{Jv`uqF*Nm34I0001uNklUV!$X&uPsNMX)W>VMZ&4IND$U zjAvm`{0&=`fo)?f8cz2MHni0#->4XwyJZ&Hw-a07*qoM6N<$f}%D3 AJpcdz literal 0 HcmV?d00001 diff --git a/python/rest/src/icons/RestIcons.java b/python/rest/src/icons/RestIcons.java index 810d775edecd..7be4044574bc 100644 --- a/python/rest/src/icons/RestIcons.java +++ b/python/rest/src/icons/RestIcons.java @@ -13,5 +13,5 @@ public class RestIcons { return IconLoader.getIcon(path, RestIcons.class); } - public static final Icon Rst = load("/com/jetbrains/rest/res/rst.png"); // 16x16 + public static final Icon Rst = load("/icons/com/jetbrains/rest/rst.png"); // 16x16 } diff --git a/python/src/com/jetbrains/pyqt/tsFile.png b/python/src/com/jetbrains/pyqt/tsFile.png deleted file mode 100644 index 1b9450576c8a1f9aad5651b0860f93cd69eb6494..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 316 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}T7XZ8E0AUgP+;(qX7Z6^@Rly# zp~2`a14n{kT5{>~IwgvRx$gGW9-b3a68Z~sH>sEG)TrHS+Iq-&!jahNr{m_I&t7r4 za^sD*U3aFOe!A|;%RP7AoqYP~`nzvWzWx66|NsB(+^2T}E#fQ*@(X5AFlgwXzyJLE zh(_T~pkR%si(`m{BM#rbx^y@>X57WJeuJaV;bX&hN2n= zyM`YDQGr??%zmBx{I*!dGTXlX-fr37zih9co47D4+j7;ck9VCsGWXBhG0A~3ghT%j z8^`I&Z82Ne67Sype9w42vy}6B6SfNmR~RlNF#P+#A1`QbSMVpG5EKlau6{1-oD!M< DS6_Q> diff --git a/python/src/com/jetbrains/pyqt/uiForm.png b/python/src/com/jetbrains/pyqt/uiForm.png deleted file mode 100644 index d5d91a05a089219209e15a8d4e535f508c6f82f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 879 zcmV-#1CacQP)nGY}7B45QRiz2=Gan zW(h>Wgbzwa{Ne|a`4;ThV6nZ-nABN7Bh1^T6-S$PYwvn{Jhx$6(fI%PJm>t*|2cX7 z1P@eGQ)BP#?d>y}OoTCpYU#ROo}8S#p3mpAgb>R6<%J$uD7fA3j%YOclhtaadRb?L zRN4S2d%jJ?sN5j#E6%N95qr_0=59zFg*+QO`^m$7p z5*Z7=9NbYX7Bj|02%6UL{TPwi&Ax7VJ=5A>aERKwake+i-XLhvL&fSw0trA z`PI;Cp{F!Wt3Vb3qQ@g&36Cqmb9?EUj=PL73zpl2iVMNkh*~O;x;yQq))k$Wv5D~4 zgQq{*#wS>E;1xyr+wa3l=;A@TQcAI>TaQ2%WqdVt27hPsxKF3BMc9k2Yo90Stg3C_ z_N1IjrQ%BfuP9&n;hGY>u$#6?4eXuAKg3}8D0cc@N0ZQq@$>~W5(&@9uTu3dwb;|$ z)0s>rr^v#O8i4TVgtG6mU9{WR%HHfhhT|iLu&?8Nn5_ht@1De#rWdet!$F#!NoaCc zPav5{ECD31SH3#_qq6_}F52dGu(zN104KhA1AErL1(T_a5p@uK?%n8b*i3KzoYuC# zav-2i|5*i)yz=<{coCT{^H{%i8$8g@Op?8Ff+GG8F z0adMX&>~6lwTX!G;+bb@OVj3 zxP9}slA2A@IW5c9Ecd`(TZdvnL*iBpE1k_)R^J4k6q?J;YU|ed{sY()i^U>#yPdK! zd$7tnN_q(lCRi(m9;V8U<9}o<4o~I0&sTBq z3t0$-APBBdDD extends Modu } public Icon getBigIcon() { - return PythonIcons.Python.Icons.Python_24; + return PythonIcons.Python.Python_24; } public Icon getNodeIcon(final boolean isOpened) { - return PythonIcons.Python.Icons.PythonClosed; + return PythonIcons.Python.PythonClosed; } } diff --git a/python/src/com/jetbrains/python/buildout/BuildoutFacetType.java b/python/src/com/jetbrains/python/buildout/BuildoutFacetType.java index 8447c8956857..721baca8787f 100644 --- a/python/src/com/jetbrains/python/buildout/BuildoutFacetType.java +++ b/python/src/com/jetbrains/python/buildout/BuildoutFacetType.java @@ -50,6 +50,6 @@ public class BuildoutFacetType extends FacetType imp final Property property = getProperty(); if (property != null) { if (property.getGetter().valueOrNull() == this) { - return PythonIcons.Python.Icons.PropertyGetter; + return PythonIcons.Python.PropertyGetter; } if (property.getSetter().valueOrNull() == this) { - return PythonIcons.Python.Icons.PropertySetter; + return PythonIcons.Python.PropertySetter; } if (property.getDeleter().valueOrNull() == this) { - return PythonIcons.Python.Icons.PropertyDeleter; + return PythonIcons.Python.PropertyDeleter; } return PlatformIcons.PROPERTY_ICON; } diff --git a/python/src/com/jetbrains/python/run/PythonConfigurationType.java b/python/src/com/jetbrains/python/run/PythonConfigurationType.java index dd1501cf292d..4832f40dad3b 100644 --- a/python/src/com/jetbrains/python/run/PythonConfigurationType.java +++ b/python/src/com/jetbrains/python/run/PythonConfigurationType.java @@ -48,7 +48,7 @@ public class PythonConfigurationType implements ConfigurationType { } public Icon getIcon() { - return PythonIcons.Python.Icons.Python; + return PythonIcons.Python.Python; } public ConfigurationFactory[] getConfigurationFactories() { diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkType.java b/python/src/com/jetbrains/python/sdk/PythonSdkType.java index c42eb430951f..4aaba6f4c176 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkType.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkType.java @@ -94,7 +94,7 @@ public class PythonSdkType extends SdkType { } public Icon getIcon() { - return PythonIcons.Python.Icons.Python; + return PythonIcons.Python.Python; } @NotNull diff --git a/python/src/com/jetbrains/python/sdk/flavors/IronPythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/IronPythonSdkFlavor.java index 8e1138db9847..7b3b32d1ba6d 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/IronPythonSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/IronPythonSdkFlavor.java @@ -84,6 +84,6 @@ public class IronPythonSdkFlavor extends PythonSdkFlavor { @Override public Icon getIcon() { - return PythonIcons.Python.Icons.Dotnet; + return PythonIcons.Python.Dotnet; } } diff --git a/python/src/com/jetbrains/python/sdk/flavors/JythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/JythonSdkFlavor.java index eca1b1776f99..8a8640481041 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/JythonSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/JythonSdkFlavor.java @@ -66,6 +66,6 @@ public class JythonSdkFlavor extends PythonSdkFlavor { @Override public Icon getIcon() { - return PythonIcons.Python.Icons.Jython; + return PythonIcons.Python.Jython; } } diff --git a/python/src/com/jetbrains/python/sdk/flavors/PyPySdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/PyPySdkFlavor.java index a56007fc8e6d..9342d32ecb6f 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/PyPySdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/PyPySdkFlavor.java @@ -77,6 +77,6 @@ public class PyPySdkFlavor extends PythonSdkFlavor { @Override public Icon getIcon() { - return PythonIcons.Python.Icons.Pypy; + return PythonIcons.Python.Pypy; } } diff --git a/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java index 5fad2e1107c8..000f67ba2d8c 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java @@ -229,6 +229,6 @@ public abstract class PythonSdkFlavor { } public Icon getIcon() { - return PythonIcons.Python.Icons.Python; + return PythonIcons.Python.Python; } } diff --git a/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java index b3790d2fc1eb..ed48bb673e4a 100644 --- a/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java +++ b/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java @@ -118,6 +118,6 @@ public class VirtualEnvSdkFlavor extends CPythonSdkFlavor { @Override public Icon getIcon() { - return PythonIcons.Python.Icons.Virtualenv; + return PythonIcons.Python.Virtualenv; } } diff --git a/python/src/com/jetbrains/python/structureView/PyStructureViewElement.java b/python/src/com/jetbrains/python/structureView/PyStructureViewElement.java index 66b4fab74450..a976ada169d7 100644 --- a/python/src/com/jetbrains/python/structureView/PyStructureViewElement.java +++ b/python/src/com/jetbrains/python/structureView/PyStructureViewElement.java @@ -275,13 +275,13 @@ public class PyStructureViewElement implements StructureViewTreeElement { icon.setIcon(normal_icon, 0); Icon overlay = null; if (myVisibility == Visibility.PRIVATE || myVisibility == Visibility.PROTECTED) { - overlay = PythonIcons.Python.Icons.Nodes.Lock; + overlay = PythonIcons.Python.Nodes.Lock; } else if (myVisibility == Visibility.PREDEFINED) { - overlay = PythonIcons.Python.Icons.Nodes.Cyan_dot; + overlay = PythonIcons.Python.Nodes.Cyan_dot; } else if (myVisibility == Visibility.INVISIBLE) { - overlay = PythonIcons.Python.Icons.Nodes.Red_inv_triangle; + overlay = PythonIcons.Python.Nodes.Red_inv_triangle; } if (overlay != null) { icon.setIcon(overlay, 1); diff --git a/python/src/com/jetbrains/python/testing/PythonTestConfigurationType.java b/python/src/com/jetbrains/python/testing/PythonTestConfigurationType.java index 3a4de2fbc86c..987c9b2b8544 100644 --- a/python/src/com/jetbrains/python/testing/PythonTestConfigurationType.java +++ b/python/src/com/jetbrains/python/testing/PythonTestConfigurationType.java @@ -121,7 +121,7 @@ public class PythonTestConfigurationType implements ConfigurationType { @Override public Icon getIcon() { - return PythonIcons.Python.Icons.PythonTests; + return PythonIcons.Python.PythonTests; } @NotNull From 0f3e4fe39709fcf6314e3d74d278482e6a1bab68 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 16 Jan 2013 16:54:27 +0400 Subject: [PATCH 6/8] fixed PY-7715 replace with augmented assignment doesn't work in case of subscription --- .../quickfix/AugmentedAssignmentQuickFix.java | 59 ++++--------------- .../AugmentAssignmentSubscription.py | 3 + .../AugmentAssignmentSubscription_after.py | 3 + .../com/jetbrains/python/PyQuickFixTest.java | 5 ++ 4 files changed, 22 insertions(+), 48 deletions(-) create mode 100644 python/testData/inspections/AugmentAssignmentSubscription.py create mode 100644 python/testData/inspections/AugmentAssignmentSubscription_after.py diff --git a/python/src/com/jetbrains/python/inspections/quickfix/AugmentedAssignmentQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/AugmentedAssignmentQuickFix.java index 919b4d3887f0..88fb994f9d7e 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/AugmentedAssignmentQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/AugmentedAssignmentQuickFix.java @@ -5,14 +5,10 @@ import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiComment; import com.intellij.psi.PsiElement; -import com.intellij.psi.tree.TokenSet; import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.python.PyBundle; -import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyAugAssignmentStatementImpl; -import com.jetbrains.python.psi.types.PyType; -import com.jetbrains.python.psi.types.TypeEvalContext; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -59,54 +55,21 @@ public class AugmentedAssignmentQuickFix implements LocalQuickFix { if ((leftExpression instanceof PyReferenceExpression || leftExpression instanceof PySubscriptionExpression)) { if (leftExpression.getText().equals(targetText)) { - if (rightExpression instanceof PyNumericLiteralExpression || rightExpression instanceof PyStringLiteralExpression || - rightExpression instanceof PyCallExpression || rightExpression instanceof PyReferenceExpression - || isPercentage(rightExpression) || isCompound(rightExpression) || isMathOperation(rightExpression, expression.getOperator())) { - - final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project); - final StringBuilder stringBuilder = new StringBuilder(); - final PsiElement psiOperator = expression.getPsiOperator(); - if (psiOperator == null) return; - stringBuilder.append(targetText).append(" "). - append(psiOperator.getText()).append("= ").append(rightExpression.getText()); - final PyAugAssignmentStatementImpl augAssignment = elementGenerator.createFromText(LanguageLevel.forElement(element), - PyAugAssignmentStatementImpl.class, stringBuilder.toString()); - for (PsiComment comment : comments) - augAssignment.add(comment); - statement.replace(augAssignment); - } + final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project); + final StringBuilder stringBuilder = new StringBuilder(); + final PsiElement psiOperator = expression.getPsiOperator(); + if (psiOperator == null) return; + stringBuilder.append(targetText).append(" "). + append(psiOperator.getText()).append("= ").append(rightExpression.getText()); + final PyAugAssignmentStatementImpl augAssignment = elementGenerator.createFromText(LanguageLevel.forElement(element), + PyAugAssignmentStatementImpl.class, stringBuilder.toString()); + for (PsiComment comment : comments) + augAssignment.add(comment); + statement.replace(augAssignment); } } } } } - private static boolean isCompound(final PyExpression rightExpression) { - if (rightExpression instanceof PyCallExpression) { - final PyType type = rightExpression.getType(TypeEvalContext.fast()); - if (type != null && type.isBuiltin(TypeEvalContext.fast()) && - ("int".equals(type.getName()) || "str".equals(type.getName()))) return true; - } - return false; - } - - private static boolean isPercentage(final PyExpression rightExpression) { - return (rightExpression instanceof PyBinaryExpression && - ((PyBinaryExpression)rightExpression).getLeftExpression() instanceof PyStringLiteralExpression && - ((PyBinaryExpression)rightExpression).getOperator() == PyTokenTypes.PERC); - } - - private static boolean isMathOperation(final PyExpression rightExpression, final PyElementType mainOperator) { - final TokenSet first = TokenSet.create(PyTokenTypes.EXP, PyTokenTypes.FLOORDIV); - final TokenSet second = TokenSet.create(PyTokenTypes.MULT, PyTokenTypes.DIV, PyTokenTypes.PERC); - final TokenSet third = TokenSet.create(PyTokenTypes.PLUS, PyTokenTypes.MINUS); - if (rightExpression instanceof PyBinaryExpression){ - final PyElementType operator = ((PyBinaryExpression)rightExpression).getOperator(); - if (third.contains(mainOperator)) - return true; - else if (second.contains(mainOperator) && (second.contains(operator) || first.contains(operator))) - return true; - } - return false; - } } diff --git a/python/testData/inspections/AugmentAssignmentSubscription.py b/python/testData/inspections/AugmentAssignmentSubscription.py new file mode 100644 index 000000000000..fd57a20495a7 --- /dev/null +++ b/python/testData/inspections/AugmentAssignmentSubscription.py @@ -0,0 +1,3 @@ +current_sum = 1 +numbers = [1, 2, 3] +current_sum = current_sum + numbers[0] \ No newline at end of file diff --git a/python/testData/inspections/AugmentAssignmentSubscription_after.py b/python/testData/inspections/AugmentAssignmentSubscription_after.py new file mode 100644 index 000000000000..30e3c4cc8121 --- /dev/null +++ b/python/testData/inspections/AugmentAssignmentSubscription_after.py @@ -0,0 +1,3 @@ +current_sum = 1 +numbers = [1, 2, 3] +current_sum += numbers[0] \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java index e0ee6d07c252..84b60a170548 100644 --- a/python/testSrc/com/jetbrains/python/PyQuickFixTest.java +++ b/python/testSrc/com/jetbrains/python/PyQuickFixTest.java @@ -241,6 +241,11 @@ public class PyQuickFixTest extends PyTestCase { PyBundle.message("QFIX.augment.assignment"), true, true); } + public void testAugmentAssignmentSubscription() { // PY-7715 + doInspectionTest("AugmentAssignmentFunction.py", PyAugmentAssignmentInspection.class, + PyBundle.message("QFIX.augment.assignment"), true, true); + } + public void testChainedComparisons() { // PY-1020 doInspectionTest("ChainedComparisons.py", PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true); From cd0e90bc700ddc6e3d2bf54cc7d5b66fa41b9997 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 16 Jan 2013 17:06:39 +0400 Subject: [PATCH 7/8] fixed PY-7699 Wrongly reported missed call to superclass constructor using prefixed/embedded class --- .../PyMissingConstructorInspection.java | 4 +++- .../innerClass.py | 18 ++++++++++++++++++ .../inspections/PyMissingConstructorTest.java | 7 +++++-- 3 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 python/testData/inspections/PyMissingConstructorInspection/innerClass.py diff --git a/python/src/com/jetbrains/python/inspections/PyMissingConstructorInspection.java b/python/src/com/jetbrains/python/inspections/PyMissingConstructorInspection.java index ed93c2f82cff..c19730ba8f35 100644 --- a/python/src/com/jetbrains/python/inspections/PyMissingConstructorInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyMissingConstructorInspection.java @@ -123,7 +123,9 @@ public class PyMissingConstructorInspection extends PyInspection { PyExpression[] args = ((PyCallExpression)qualifier).getArguments(); if (args.length > 0) { String firstArg = args[0].getText(); - if (firstArg.equals(cl.getName()) || firstArg.equals(CANONICAL_SELF+"."+ CLASS)) + final String qualifiedName = cl.getQualifiedName(); + if (firstArg.equals(cl.getName()) || firstArg.equals(CANONICAL_SELF+"."+ CLASS) || + (qualifiedName != null && qualifiedName.endsWith(firstArg))) return true; for (PyClass s : cl.iterateAncestorClasses()) { if (firstArg.equals(s.getName())) diff --git a/python/testData/inspections/PyMissingConstructorInspection/innerClass.py b/python/testData/inspections/PyMissingConstructorInspection/innerClass.py new file mode 100644 index 000000000000..92cc3c83f432 --- /dev/null +++ b/python/testData/inspections/PyMissingConstructorInspection/innerClass.py @@ -0,0 +1,18 @@ + +class Base(object): + def __init__(self, param): + print "Base", param + + +class Wrapper(object): + class Child(Base): + def __init__(self, param1, param2): + # Here PyCharm claims no super call + super(Wrapper.Child, self).__init__(param2) + print "Child", param1 + + def __init__(self): + self.child = self.Child("aaa", "bbb") + + +wrapper = Wrapper() diff --git a/python/testSrc/com/jetbrains/python/inspections/PyMissingConstructorTest.java b/python/testSrc/com/jetbrains/python/inspections/PyMissingConstructorTest.java index cf734731f38c..f575647386a7 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyMissingConstructorTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyMissingConstructorTest.java @@ -33,8 +33,11 @@ public class PyMissingConstructorTest extends PyTestCase { doTest(); } - // PY-7176 - public void testException() { + public void testException() { // PY-7176 + doTest(); + } + + public void testInnerClass() { //PY-7699 doTest(); } From 719c416cc85bb7ead5c8fb5f14b63327110fc1dd Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Wed, 16 Jan 2013 17:41:23 +0400 Subject: [PATCH 8/8] Code cleanup: IDEA's warnings have been fixed --- .../com/jetbrains/python/actions/ExecuteInConsoleAction.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java b/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java index 5112b1be49c0..94a045f49ce0 100644 --- a/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java +++ b/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java @@ -123,17 +123,15 @@ public class ExecuteInConsoleAction extends AnAction { selectConsole(project, editor, consumer); } else { - startConsole(project, editor, consumer, e.getData(LangDataKeys.MODULE)); + startConsole(project, consumer, e.getData(LangDataKeys.MODULE)); } } } private static void startConsole(final Project project, - final Editor editor, final Consumer consumer, Module context) { PydevConsoleRunner runner = RunPythonConsoleAction.runPythonConsole(project, context); - assert runner != null; runner.addConsoleListener(new PydevConsoleRunner.ConsoleListener() { @Override public void handleConsoleInitialized(LanguageConsoleViewImpl consoleView) {