From b56b6cc01baa3b39b5e428779292382fb3a0c457 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Tue, 14 Jan 2014 18:42:21 +0400 Subject: [PATCH 01/25] Added Python 3.4 modules to the stdlib modules list --- python/helpers/tools/stdlib_packages.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/python/helpers/tools/stdlib_packages.txt b/python/helpers/tools/stdlib_packages.txt index 619651ebbec9..2ee4b5d22705 100644 --- a/python/helpers/tools/stdlib_packages.txt +++ b/python/helpers/tools/stdlib_packages.txt @@ -6,6 +6,7 @@ argparse array ast asynchat +asyncio asyncore atexit audiodev @@ -68,6 +69,8 @@ dummy_thread dummy_threading email encodings +ensurepip +enum errno exceptions fcntl @@ -150,6 +153,7 @@ os os2emxpath ossaudiodev parser +pathlib pdb pickle pickletools @@ -194,6 +198,7 @@ robotparser runpy sched select +selectors sets sgmllib sha @@ -219,6 +224,7 @@ sre_parse ssl stat statcache +statistics statvfs string StringIO @@ -254,6 +260,7 @@ token tokenize trace traceback +tracemalloc tty turtle turtledemo From e2db1eaa5ff52151f47d772c5d4b96045402b0b2 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Thu, 16 Jan 2014 16:49:05 +0400 Subject: [PATCH 02/25] Fixed code insight for returning 'self' in base class methods (PY-10977, PY-11413) If a method of a base class returns a value of this class, then it is cast to a derived class this method has been invoked on. This cast is considered safe, since it cannot result in false positives. --- .../python/psi/impl/PyFunctionImpl.java | 51 +++++++++++++------ .../psi/impl/PyTargetExpressionImpl.java | 4 +- .../contextManagerSubclass.py | 12 +++++ .../returnSelfInSuperClass.py | 13 +++++ .../PyUnresolvedReferencesInspectionTest.java | 10 ++++ 5 files changed, 72 insertions(+), 18 deletions(-) create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/contextManagerSubclass.py create mode 100644 python/testData/inspections/PyUnresolvedReferencesInspection/returnSelfInSuperClass.py diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java index 3f438437190e..35585068c7b4 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java @@ -174,29 +174,28 @@ public class PyFunctionImpl extends PyPresentableElementImpl imp @Nullable @Override public PyType getReturnType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) { - final PyType type = getGenericReturnType(context, callSite); - + PyType type = getGenericReturnType(context, callSite); if (callSite == null) { return type; } final PyTypeChecker.AnalyzeCallResults results = PyTypeChecker.analyzeCallSite(callSite, context); - if (PyTypeChecker.hasGenerics(type, context)) { if (results != null) { final Map substitutions = PyTypeChecker.unifyGenericCall(this, results.getReceiver(), results.getArguments(), context); - if (substitutions != null) { - return PyTypeChecker.substitute(type, substitutions, context); - } + type = substitutions != null ? PyTypeChecker.substitute(type, substitutions, context) : null; } - return null; + else { + type = null; + } + } + if (results != null) { + type = replaceSelf(type, results.getReceiver(), context); } if (results != null && isDynamicallyEvaluated(results.getArguments().values(), context)) { return PyUnionType.createWeakType(type); } - else { - return type; - } + return type; } @Nullable @@ -205,16 +204,36 @@ public class PyFunctionImpl extends PyPresentableElementImpl imp */ public PyType getReturnTypeWithoutCallSite(@NotNull TypeEvalContext context, @Nullable PyExpression receiver) { - final PyType type = getGenericReturnType(context, null); + PyType type = getGenericReturnType(context, null); if (PyTypeChecker.hasGenerics(type, context)) { - final Map substitutions = - PyTypeChecker.unifyGenericCall(this, receiver, Maps.newHashMap(), context); + final Map substitutions = PyTypeChecker.unifyGenericCall(this, receiver, + Maps.newHashMap(), + context); if (substitutions != null) { - return PyTypeChecker.substitute(type, substitutions, context); + type = PyTypeChecker.substitute(type, substitutions, context); + } + else { + type = null; } - return null; } - return type; + return replaceSelf(type, receiver, context); + } + + @Nullable + private PyType replaceSelf(@Nullable PyType returnType, @Nullable PyExpression receiver, @NotNull TypeEvalContext context) { + if (receiver != null) { + // TODO: Currently we substitute only simple subclass types, but we could handle union and collection types as well + if (returnType instanceof PyClassType) { + final PyClassType returnClassType = (PyClassType)returnType; + if (returnClassType.getPyClass() == getContainingClass()) { + final PyType receiverType = context.getType(receiver); + if (receiverType instanceof PyClassType && PyTypeChecker.match(returnType, receiverType, context)) { + return receiverType; + } + } + } + } + return returnType; } private static boolean isDynamicallyEvaluated(@NotNull Collection parameters, @NotNull TypeEvalContext context) { diff --git a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java index fd49c2543cc7..ae2e30f28f0a 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyTargetExpressionImpl.java @@ -241,8 +241,8 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl Date: Thu, 16 Jan 2014 17:06:46 +0400 Subject: [PATCH 03/25] Python skeletons class members provider now can provide new overridden members It is useful for overloading method signatures in subclasses. --- ...erridingAncestorsClassMembersProvider.java | 22 +++++++++++++++++++ .../PyUserSkeletonsClassMembersProvider.java | 3 ++- .../python/psi/types/PyClassTypeImpl.java | 16 ++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 python/psi-api/src/com/jetbrains/python/psi/types/PyOverridingAncestorsClassMembersProvider.java diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyOverridingAncestorsClassMembersProvider.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyOverridingAncestorsClassMembersProvider.java new file mode 100644 index 000000000000..07b53091aba1 --- /dev/null +++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyOverridingAncestorsClassMembersProvider.java @@ -0,0 +1,22 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jetbrains.python.psi.types; + +/** + * @author vlan + */ +public interface PyOverridingAncestorsClassMembersProvider extends PyClassMembersProvider { +} diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java index a35d8fd74444..5ac7fc10751c 100644 --- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java @@ -22,6 +22,7 @@ import com.jetbrains.python.psi.PyFunction; import com.jetbrains.python.psi.PyTargetExpression; import com.jetbrains.python.psi.types.PyClassMembersProviderBase; import com.jetbrains.python.psi.types.PyClassType; +import com.jetbrains.python.psi.types.PyOverridingAncestorsClassMembersProvider; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,7 +34,7 @@ import java.util.List; /** * @author vlan */ -public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderBase { +public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderBase implements PyOverridingAncestorsClassMembersProvider { @NotNull @Override public Collection getMembers(@NotNull PyClassType classType, PsiElement location) { diff --git a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java index 7be077f8bc17..672dbe495e84 100644 --- a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java +++ b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java @@ -198,6 +198,11 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { return ResolveResultList.to(classMember); } + classMember = resolveByOverridingAncestorsMembersProviders(this, name, location); + if (classMember != null) { + return ResolveResultList.to(classMember); + } + if (inherited) { for (PyClassLikeType type : myClass.getAncestorTypes(context)) { if (type instanceof PyClassType) { @@ -329,6 +334,17 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { return null; } + @Nullable + private static PsiElement resolveByOverridingAncestorsMembersProviders(PyClassType type, String name, @Nullable PyExpression location) { + for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) { + if (provider instanceof PyOverridingAncestorsClassMembersProvider) { + final PsiElement resolveResult = provider.resolveMember(type, name, location); + if (resolveResult != null) return resolveResult; + } + } + return null; + } + @Nullable private static PsiElement resolveInner(@NotNull PyClass cls, boolean isDefinition, From b8a5d1e191a5d592b9cb7e4c77bd3d43340c70d5 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Thu, 16 Jan 2014 17:52:39 +0400 Subject: [PATCH 04/25] Added 'inherited' parameter to PyClass.findProperty() --- .../src/com/jetbrains/python/psi/PyClass.java | 4 +++- .../python/documentation/PyDocumentationBuilder.java | 2 +- .../PyAttributeOutsideInitInspection.java | 2 +- .../inspections/PyPropertyAccessInspection.java | 2 +- .../PyUnresolvedReferencesInspection.java | 2 +- .../com/jetbrains/python/psi/impl/PyClassImpl.java | 12 +++++++----- .../python/psi/impl/PyReferenceExpressionImpl.java | 2 +- .../jetbrains/python/psi/types/PyClassTypeImpl.java | 2 +- .../com/jetbrains/python/PyClassicPropertyTest.java | 6 +++--- .../jetbrains/python/PyDecoratedPropertyTest.java | 4 ++-- python/testSrc/com/jetbrains/python/PyStubsTest.java | 6 +++--- 11 files changed, 24 insertions(+), 20 deletions(-) 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 e1084e826741..6bad8d10a6f8 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyClass.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyClass.java @@ -136,11 +136,13 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefine /** * Finds a property with the specified name in the class or one of its ancestors. * + * * @param name of the property + * @param inherited * @return descriptor of property accessors, or null if such property does not exist. */ @Nullable - Property findProperty(@NotNull String name); + Property findProperty(@NotNull String name, boolean inherited); /** * Apply a processor to every method, looking at superclasses in method resolution order as needed. diff --git a/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java b/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java index ec4becc5cc1f..4c3432c7e84a 100644 --- a/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java +++ b/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java @@ -95,7 +95,7 @@ class PyDocumentationBuilder { PyType type = context.getType(qual); if (type instanceof PyClassType) { cls = ((PyClassType)type).getPyClass(); - Property property = cls.findProperty(elementName); + Property property = cls.findProperty(elementName, true); if (property != null) { is_property = true; final AccessDirection dir = AccessDirection.of((PyElement)outer); diff --git a/python/src/com/jetbrains/python/inspections/PyAttributeOutsideInitInspection.java b/python/src/com/jetbrains/python/inspections/PyAttributeOutsideInitInspection.java index c94ab8daaafb..791a1b52d38b 100644 --- a/python/src/com/jetbrains/python/inspections/PyAttributeOutsideInitInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyAttributeOutsideInitInspection.java @@ -100,7 +100,7 @@ public class PyAttributeOutsideInitInspection extends PyInspection { for (Map.Entry attribute : attributes.entrySet()) { String attributeName = attribute.getKey(); if (attributeName == null) continue; - final Property property = containingClass.findProperty(attributeName); + final Property property = containingClass.findProperty(attributeName, true); if (!attributesInInit.containsKey(attributeName) && property == null) { registerProblem(attribute.getValue(), PyBundle.message("INSP.attribute.$0.outside.init", attributeName), new PyMoveAttributeToInitQuickFix()); diff --git a/python/src/com/jetbrains/python/inspections/PyPropertyAccessInspection.java b/python/src/com/jetbrains/python/inspections/PyPropertyAccessInspection.java index 425c58519486..8e48067578cb 100644 --- a/python/src/com/jetbrains/python/inspections/PyPropertyAccessInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyPropertyAccessInspection.java @@ -86,7 +86,7 @@ public class PyPropertyAccessInspection extends PyInspection { property = myPropertyCache.get(key); } else { - property = cls.findProperty(name); + property = cls.findProperty(name, true); } myPropertyCache.put(key, property); // we store nulls, too, to know that a property does not exist if (property != null) { diff --git a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java index 4005b42dccdc..998530a016b3 100644 --- a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java @@ -695,7 +695,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection { if (overridesGetAttr(cls, myTypeEvalContext)) { return true; } - if (cls.findProperty(name) != null) { + if (cls.findProperty(name, true) != null) { return true; } if (PyUtil.hasUnresolvedAncestors(cls, myTypeEvalContext)) { diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index 0a9959d23f64..47fb3470a972 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -585,7 +585,7 @@ public class PyClassImpl extends PyPresentableElementImpl implement @Nullable @Override - public Property findProperty(@NotNull final String name) { + public Property findProperty(@NotNull final String name, boolean inherited) { Property property = findLocalProperty(name); if (property != null) { return property; @@ -593,10 +593,12 @@ public class PyClassImpl extends PyPresentableElementImpl implement if (findMethodByName(name, false) != null || findClassAttribute(name, false) != null) { return null; } - for (PyClass aClass : getAncestorClasses()) { - final Property ancestorProperty = ((PyClassImpl)aClass).findLocalProperty(name); - if (ancestorProperty != null) { - return ancestorProperty; + if (inherited) { + for (PyClass aClass : getAncestorClasses()) { + final Property ancestorProperty = ((PyClassImpl)aClass).findLocalProperty(name); + if (ancestorProperty != null) { + return ancestorProperty; + } } } return null; diff --git a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java index 7b778a527635..d5a95533afa1 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java @@ -264,7 +264,7 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere if (qualifierType instanceof PyClassType) { final PyClassType classType = (PyClassType)qualifierType; PyClass pyClass = classType.getPyClass(); - Property property = pyClass.findProperty(name); + Property property = pyClass.findProperty(name, true); if (property != null) { if (classType.isDefinition()) { return Ref.create(PyBuiltinCache.getInstance(pyClass).getObjectType(PyNames.PROPERTY)); diff --git a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java index 672dbe495e84..29ea2bb4a4c0 100644 --- a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java +++ b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java @@ -156,7 +156,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { } if (resolveContext.allowProperties()) { - Property property = myClass.findProperty(name); + Property property = myClass.findProperty(name, true); if (property != null) { Maybe accessor = property.getByDirection(direction); if (accessor.isDefined()) { diff --git a/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java b/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java index 7947ffb6dc46..2e55003cddd0 100644 --- a/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java +++ b/python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java @@ -38,7 +38,7 @@ public class PyClassicPropertyTest extends PyTestCase { public void testV1() throws Exception { Property p; Maybe accessor; - p = myClass.findProperty("v1"); + p = myClass.findProperty("v1", true); assertNotNull(p); assertNull(p.getDoc()); PyTargetExpression site = p.getDefinitionSite(); @@ -62,7 +62,7 @@ public class PyClassicPropertyTest extends PyTestCase { public void testV2() throws Exception { Property p; Maybe accessor; - p = myClass.findProperty("v2"); + p = myClass.findProperty("v2", true); assertNotNull(p); assertEquals("doc of v2", p.getDoc()); PyTargetExpression site = p.getDefinitionSite(); @@ -86,7 +86,7 @@ public class PyClassicPropertyTest extends PyTestCase { public void testV3() throws Exception { Maybe accessor; - Property p = myClass.findProperty("v3"); + Property p = myClass.findProperty("v3", true); assertNotNull(p); assertNull(p.getDoc()); PyTargetExpression site = p.getDefinitionSite(); diff --git a/python/testSrc/com/jetbrains/python/PyDecoratedPropertyTest.java b/python/testSrc/com/jetbrains/python/PyDecoratedPropertyTest.java index 414c3558d948..ac9f83afce6a 100644 --- a/python/testSrc/com/jetbrains/python/PyDecoratedPropertyTest.java +++ b/python/testSrc/com/jetbrains/python/PyDecoratedPropertyTest.java @@ -35,7 +35,7 @@ public class PyDecoratedPropertyTest extends PyTestCase { Property p; Maybe accessor; final String name = "w1"; - p = myClass.findProperty(name); + p = myClass.findProperty(name, true); assertNotNull(p); assertNull(p.getDoc()); assertNull(p.getDefinitionSite()); @@ -60,7 +60,7 @@ public class PyDecoratedPropertyTest extends PyTestCase { Property p; Maybe accessor; final String name = "w2"; - p = myClass.findProperty(name); + p = myClass.findProperty(name, true); assertNotNull(p); assertNull(p.getDoc()); assertNull(p.getDefinitionSite()); diff --git a/python/testSrc/com/jetbrains/python/PyStubsTest.java b/python/testSrc/com/jetbrains/python/PyStubsTest.java index 6ad2dc4bff16..7706dd7c9ef8 100644 --- a/python/testSrc/com/jetbrains/python/PyStubsTest.java +++ b/python/testSrc/com/jetbrains/python/PyStubsTest.java @@ -118,12 +118,12 @@ public class PyStubsTest extends PyTestCase { pyClass = classes.get(1); assertEquals("BarClass", pyClass.getName()); - Property prop = pyClass.findProperty("value"); + Property prop = pyClass.findProperty("value", true); Maybe maybe_function = prop.getGetter(); assertTrue(maybe_function.isDefined()); assertEquals(pyClass.getMethods()[0], maybe_function.value()); - Property setvalueProp = pyClass.findProperty("setvalue"); + Property setvalueProp = pyClass.findProperty("setvalue", true); Maybe setter = setvalueProp.getSetter(); assertTrue(setter.isDefined()); assertEquals("__set", setter.value().getName()); @@ -131,7 +131,7 @@ public class PyStubsTest extends PyTestCase { // properties by decorator pyClass = classes.get(2); assertEquals("BazClass", pyClass.getName()); - prop = pyClass.findProperty("x"); + prop = pyClass.findProperty("x", true); maybe_function = prop.getGetter(); assertTrue(maybe_function.isDefined()); assertEquals(pyClass.getMethods()[0], maybe_function.value()); From dbd00aea479ad2d443f4f3e4838ee3731e59d9c5 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Thu, 16 Jan 2014 18:00:42 +0400 Subject: [PATCH 05/25] Extracted PyClassTypeImpl.findProperty() --- .../python/psi/types/PyClassTypeImpl.java | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java index 29ea2bb4a4c0..e9768237df02 100644 --- a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java +++ b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java @@ -23,6 +23,7 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiInvalidElementAccessException; @@ -156,22 +157,9 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { } if (resolveContext.allowProperties()) { - Property property = myClass.findProperty(name, true); - if (property != null) { - Maybe accessor = property.getByDirection(direction); - if (accessor.isDefined()) { - Callable accessor_code = accessor.value(); - ResolveResultList ret = new ResolveResultList(); - if (accessor_code != null) ret.poke(accessor_code, RatedResolveResult.RATE_NORMAL); - PyTargetExpression site = property.getDefinitionSite(); - if (site != null) ret.poke(site, RatedResolveResult.RATE_LOW); - if (ret.size() > 0) { - return ret; - } - else { - return null; - } // property is found, but the required accessor is explicitly absent - } + final Ref resultRef = findProperty(name, direction, true); + if (resultRef != null) { + return resultRef.get(); } } @@ -256,6 +244,28 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { return Collections.emptyList(); } + private Ref findProperty(String name, AccessDirection direction, boolean inherited) { + Ref resultRef = null; + Property property = myClass.findProperty(name, inherited); + if (property != null) { + Maybe accessor = property.getByDirection(direction); + if (accessor.isDefined()) { + Callable accessor_code = accessor.value(); + ResolveResultList ret = new ResolveResultList(); + if (accessor_code != null) ret.poke(accessor_code, RatedResolveResult.RATE_NORMAL); + PyTargetExpression site = property.getDefinitionSite(); + if (site != null) ret.poke(site, RatedResolveResult.RATE_LOW); + if (ret.size() > 0) { + resultRef = Ref.create(ret); + } + else { + resultRef = Ref.create(); + } // property is found, but the required accessor is explicitly absent + } + } + return resultRef; + } + @Nullable private PyClassType getMetaclassType() { final PyClass metaClass = PyUtil.getMetaClass(myClass); From 687755b978cfc0eabe66f73ee6a74fb097ab6918 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Thu, 16 Jan 2014 18:01:37 +0400 Subject: [PATCH 06/25] Simplified always true condition --- .../com/jetbrains/python/psi/types/PyClassTypeImpl.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java index e9768237df02..e475429e0143 100644 --- a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java +++ b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java @@ -230,12 +230,10 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { for (PyClassLikeType type : myClass.getAncestorTypes(context)) { if (type instanceof PyClassType) { final PyClass pyClass = ((PyClassType)type).getPyClass(); - if (pyClass != null) { - PsiElement superMember = resolveByMembersProviders(new PyClassTypeImpl(pyClass, isDefinition()), name, location); + PsiElement superMember = resolveByMembersProviders(new PyClassTypeImpl(pyClass, isDefinition()), name, location); - if (superMember != null) { - return ResolveResultList.to(superMember); - } + if (superMember != null) { + return ResolveResultList.to(superMember); } } } From 8e8019c3961dced13c472931dd598b98fa39f989 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Fri, 17 Jan 2014 16:42:55 +0400 Subject: [PATCH 07/25] Nullity annotations --- .../src/com/jetbrains/python/psi/impl/PyTypeProvider.java | 2 +- .../src/com/jetbrains/python/psi/types/PyTypeProviderBase.java | 2 +- .../jetbrains/python/psi/impl/PyReferenceExpressionImpl.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java b/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java index 38a0ee670050..b4e5be8753d3 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java +++ b/python/psi-api/src/com/jetbrains/python/psi/impl/PyTypeProvider.java @@ -30,7 +30,7 @@ public interface PyTypeProvider { ExtensionPointName EP_NAME = ExtensionPointName.create("Pythonid.typeProvider"); @Nullable - PyType getReferenceExpressionType(PyReferenceExpression referenceExpression, TypeEvalContext context); + PyType getReferenceExpressionType(@NotNull PyReferenceExpression referenceExpression, @NotNull TypeEvalContext context); @Nullable PyType getReferenceType(@NotNull PsiElement referenceTarget, TypeEvalContext context, @Nullable PsiElement anchor); 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 dc20bad8f36f..0792b5083542 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,7 +80,7 @@ public class PyTypeProviderBase implements PyTypeProvider { }; @Override - public PyType getReferenceExpressionType(PyReferenceExpression referenceExpression, TypeEvalContext context) { + public PyType getReferenceExpressionType(@NotNull PyReferenceExpression referenceExpression, @NotNull TypeEvalContext context) { return null; } diff --git a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java index d5a95533afa1..455d4c597e71 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java @@ -291,7 +291,7 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere } @Nullable - private PyType getTypeFromProviders(TypeEvalContext context) { + private PyType getTypeFromProviders(@NotNull TypeEvalContext context) { for (PyTypeProvider provider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) { try { final PyType type = provider.getReferenceExpressionType(this, context); From c69719b357c292c2ac856346dc55d8bce723f239 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Fri, 17 Jan 2014 18:43:51 +0400 Subject: [PATCH 08/25] RecentProjectManager -> applicationService --- .../intellij/ide/RecentProjectsManager.java | 5 +- .../ide/RecentDirectoryProjectsManagerEx.java | 5 +- .../ide/RecentDirectoryProjectsManager.java | 5 +- .../ide/RecentProjectsManagerBase.java | 203 +++++++++--------- .../project/impl/ProjectManagerImpl.java | 9 +- .../src/META-INF/PlatformLangPlugin.xml | 3 + .../src/META-INF/PlatformPlugin.xml | 3 + .../src/componentSets/PlatformComponents.xml | 6 +- .../componentSets/PlatformLangComponents.xml | 4 - resources/src/idea/RichPlatformPlugin.xml | 10 +- 10 files changed, 129 insertions(+), 124 deletions(-) diff --git a/java/idea-ui/src/com/intellij/ide/RecentProjectsManager.java b/java/idea-ui/src/com/intellij/ide/RecentProjectsManager.java index 0e3079558437..6ac07343357a 100644 --- a/java/idea-ui/src/com/intellij/ide/RecentProjectsManager.java +++ b/java/idea-ui/src/com/intellij/ide/RecentProjectsManager.java @@ -21,7 +21,6 @@ import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.components.StoragePathMacros; import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManager; import com.intellij.util.messages.MessageBus; import org.jetbrains.annotations.NotNull; @@ -34,8 +33,8 @@ import org.jetbrains.annotations.NotNull; )} ) public class RecentProjectsManager extends RecentProjectsManagerBase { - public RecentProjectsManager(final ProjectManager projectManager, final MessageBus messageBus) { - super(projectManager, messageBus); + public RecentProjectsManager(MessageBus messageBus) { + super(messageBus); } protected String getProjectPath(@NotNull Project project) { diff --git a/platform/lang-impl/src/com/intellij/ide/RecentDirectoryProjectsManagerEx.java b/platform/lang-impl/src/com/intellij/ide/RecentDirectoryProjectsManagerEx.java index 7a2bd3f81eed..21207519fb6b 100644 --- a/platform/lang-impl/src/com/intellij/ide/RecentDirectoryProjectsManagerEx.java +++ b/platform/lang-impl/src/com/intellij/ide/RecentDirectoryProjectsManagerEx.java @@ -20,7 +20,6 @@ import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.components.StoragePathMacros; import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManager; import com.intellij.platform.ModuleAttachProcessor; import com.intellij.util.messages.MessageBus; import org.jetbrains.annotations.NotNull; @@ -37,8 +36,8 @@ import org.jetbrains.annotations.NotNull; )} ) public class RecentDirectoryProjectsManagerEx extends RecentDirectoryProjectsManager { - public RecentDirectoryProjectsManagerEx(ProjectManager projectManager, MessageBus messageBus) { - super(projectManager, messageBus); + public RecentDirectoryProjectsManagerEx(MessageBus messageBus) { + super(messageBus); } @NotNull diff --git a/platform/platform-impl/src/com/intellij/ide/RecentDirectoryProjectsManager.java b/platform/platform-impl/src/com/intellij/ide/RecentDirectoryProjectsManager.java index bdae0170338d..4189b6adf98b 100644 --- a/platform/platform-impl/src/com/intellij/ide/RecentDirectoryProjectsManager.java +++ b/platform/platform-impl/src/com/intellij/ide/RecentDirectoryProjectsManager.java @@ -20,7 +20,6 @@ import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.components.StoragePathMacros; import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; @@ -42,8 +41,8 @@ import org.jetbrains.annotations.Nullable; )} ) public class RecentDirectoryProjectsManager extends RecentProjectsManagerBase { - public RecentDirectoryProjectsManager(ProjectManager projectManager, MessageBus messageBus) { - super(projectManager, messageBus); + public RecentDirectoryProjectsManager(MessageBus messageBus) { + super(messageBus); } @Nullable diff --git a/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java b/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java index 3c46db280b43..e77e289f1740 100644 --- a/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java +++ b/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java @@ -21,9 +21,11 @@ import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.Separator; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; -import com.intellij.openapi.project.ProjectManagerAdapter; +import com.intellij.openapi.project.ProjectManagerListener; import com.intellij.openapi.project.impl.ProjectImpl; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Ref; @@ -33,6 +35,7 @@ import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.impl.SystemDock; import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame; +import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBus; import org.jetbrains.annotations.NotNull; @@ -44,16 +47,35 @@ import java.util.*; /** * @author yole */ -public abstract class RecentProjectsManagerBase implements PersistentStateComponent { +public abstract class RecentProjectsManagerBase implements ProjectManagerListener, PersistentStateComponent { public static RecentProjectsManagerBase getInstance() { - return ApplicationManager.getApplication().getComponent(RecentProjectsManagerBase.class); + return ServiceManager.getService(RecentProjectsManagerBase.class); } public static class State { - public List recentPaths = new ArrayList(); - public List openPaths = new ArrayList(); - public Map names = new HashMap(); + public List recentPaths = ContainerUtil.newArrayList(); + public List openPaths = ContainerUtil.newArrayList(); + public Map names = ContainerUtil.newLinkedHashMap(); public String lastPath; + + void validateRecentProjects() { + //noinspection StatementWithEmptyBody + while (recentPaths.remove(null)) ; + Collection displayNames = names.values(); + //noinspection StatementWithEmptyBody + while (displayNames.remove("")) ; + + while (recentPaths.size() > Registry.intValue("ide.max.recent.projects")) { + int index = recentPaths.size() - 1; + names.remove(recentPaths.get(index)); + recentPaths.remove(index); + } + } + + void removePath(String path) { + recentPaths.remove(path); + names.remove(path); + } } private final Object myStateLock = new Object(); @@ -61,14 +83,13 @@ public abstract class RecentProjectsManagerBase implements PersistentStateCompon private final Map myNameCache = Collections.synchronizedMap(new HashMap()); - public RecentProjectsManagerBase(ProjectManager projectManager, MessageBus messageBus) { - projectManager.addProjectManagerListener(new MyProjectManagerListener()); + protected RecentProjectsManagerBase(MessageBus messageBus) { messageBus.connect().subscribe(AppLifecycleListener.TOPIC, new MyAppLifecycleListener()); } public State getState() { synchronized (myStateLock) { - validateRecentProjects(); + myState.validateRecentProjects(); return myState; } } @@ -88,37 +109,16 @@ public abstract class RecentProjectsManagerBase implements PersistentStateCompon } } - private void validateRecentProjects() { - synchronized (myStateLock) { - for (Iterator i = myState.recentPaths.iterator(); i.hasNext();) { - String s = (String)i.next(); - - if (s == null) { - i.remove(); - } - } - while (myState.recentPaths.size() > Registry.intValue("ide.max.recent.projects")) { - final int index = myState.recentPaths.size() - 1; - myState.names.remove(myState.recentPaths.get(index)); - myState.recentPaths.remove(index); - } - } - } - public void removePath(final String path) { if (path == null) return; synchronized (myStateLock) { if (SystemInfo.isFileSystemCaseSensitive) { - myState.recentPaths.remove(path); - myState.names.remove(path); + myState.removePath(path); } else { - Iterator i = myState.recentPaths.iterator(); - while (i.hasNext()) { - String p = i.next(); + for (String p : ArrayUtil.toStringArray(myState.recentPaths)) { if (path.equalsIgnoreCase(p)) { - myState.names.remove(p); - i.remove(); + myState.removePath(path); } } } @@ -137,13 +137,16 @@ public abstract class RecentProjectsManagerBase implements PersistentStateCompon if (openProjects.length == 0) { myState.lastPath = null; myState.openPaths = Collections.emptyList(); - } else { + } + else { myState.lastPath = getProjectPath(openProjects[openProjects.length - 1]); - myState.openPaths = new ArrayList(); + myState.openPaths = ContainerUtil.newArrayList(); for (Project openProject : openProjects) { - final String path = getProjectPath(openProject); - ContainerUtil.addIfNotNull(myState.openPaths, path); - myState.names.put(path, getProjectDisplayName(openProject)); + String path = getProjectPath(openProject); + if (path != null) { + myState.openPaths.add(path); + myState.names.put(path, getProjectDisplayName(openProject)); + } } } } @@ -157,17 +160,11 @@ public abstract class RecentProjectsManagerBase implements PersistentStateCompon private Set getDuplicateProjectNames(Set openedPaths, Set recentPaths) { Set names = ContainerUtil.newHashSet(); Set duplicates = ContainerUtil.newHashSet(); - for (String path : openedPaths) { + for (String path : ContainerUtil.concat(openedPaths, recentPaths)) { if (!names.add(getProjectName(path))) { duplicates.add(path); } } - for (String path : recentPaths) { - if (!names.add(getProjectName(path))) { - duplicates.add(path); - } - } - return duplicates; } @@ -177,17 +174,17 @@ public abstract class RecentProjectsManagerBase implements PersistentStateCompon * @return */ public AnAction[] getRecentProjectsActions(boolean addClearListItem) { - validateRecentProjects(); + final Set paths; + synchronized (myStateLock) { + myState.validateRecentProjects(); + paths = ContainerUtil.newLinkedHashSet(myState.recentPaths); + } final Set openedPaths = ContainerUtil.newHashSet(); for (Project openProject : ProjectManager.getInstance().getOpenProjects()) { ContainerUtil.addIfNotNull(openedPaths, getProjectPath(openProject)); } - final LinkedHashSet paths; - synchronized (myStateLock) { - paths = ContainerUtil.newLinkedHashSet(myState.recentPaths); - } paths.remove(null); paths.removeAll(openedPaths); @@ -220,7 +217,7 @@ public abstract class RecentProjectsManagerBase implements PersistentStateCompon list.add(action); } if (addClearListItem) { - AnAction clearListAction = new AnAction(IdeBundle.message("action.clear.list")) { + AnAction clearListAction = new DumbAwareAction(IdeBundle.message("action.clear.list")) { public void actionPerformed(AnActionEvent e) { final int rc = Messages.showOkCancelDialog(e.getData(CommonDataKeys.PROJECT), "Would you like to clear the list of recent projects?", @@ -261,34 +258,35 @@ public abstract class RecentProjectsManagerBase implements PersistentStateCompon return file.exists() && (!file.isDirectory() || new File(file, Project.DIRECTORY_STORE_FOLDER).exists()); } - private class MyProjectManagerListener extends ProjectManagerAdapter { - public void projectOpened(final Project project) { - if (ApplicationManager.getApplication().isHeadlessEnvironment()) return; - String path = getProjectPath(project); + public void projectOpened(final Project project) { + String path = getProjectPath(project); + if (path != null) { + markPathRecent(path); + } + SystemDock.updateMenu(); + } + + @Override + public final boolean canCloseProject(Project project) { + return true; + } + + @Override + public void projectClosing(Project project) { + synchronized (myStateLock) { + myState.names.put(getProjectPath(project), getProjectDisplayName(project)); + } + } + + public void projectClosed(final Project project) { + Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); + if (openProjects.length > 0) { + String path = getProjectPath(openProjects[openProjects.length - 1]); if (path != null) { markPathRecent(path); } - SystemDock.updateMenu(); - } - - @Override - public void projectClosing(Project project) { - synchronized (myStateLock) { - myState.names.put(getProjectPath(project), getProjectDisplayName(project)); - } - } - - public void projectClosed(final Project project) { - if (ApplicationManager.getApplication().isHeadlessEnvironment()) return; - Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); - if (openProjects.length > 0) { - String path = getProjectPath(openProjects[openProjects.length - 1]); - if (path != null) { - markPathRecent(path); - } - } - SystemDock.updateMenu(); } + SystemDock.updateMenu(); } @NotNull @@ -330,35 +328,46 @@ public abstract class RecentProjectsManagerBase implements PersistentStateCompon } } + protected boolean willReopenProjectOnStart() { + return GeneralSettings.getInstance().isReopenLastProject() && getLastProjectPath() != null; + } + + protected void doReopenLastProject() { + GeneralSettings generalSettings = GeneralSettings.getInstance(); + if (generalSettings.isReopenLastProject()) { + Collection openPaths; + synchronized (myStateLock) { + openPaths = ContainerUtil.newLinkedHashSet(myState.openPaths); + } + if (!openPaths.isEmpty()) { + for (String openPath : openPaths) { + if (isValidProjectPath(openPath)) { + doOpenProject(openPath, null, true); + } + } + } + else { + String lastProjectPath = getLastProjectPath(); + if (lastProjectPath != null) { + if (isValidProjectPath(lastProjectPath)) doOpenProject(lastProjectPath, null, false); + } + } + } + } + private class MyAppLifecycleListener extends AppLifecycleListener.Adapter { public void appFrameCreated(final String[] commandLineArgs, @NotNull final Ref willOpenProject) { - if (GeneralSettings.getInstance().isReopenLastProject() && getLastProjectPath() != null) { + if (!ApplicationManager.getApplication().isHeadlessEnvironment()) { + ProjectManager.getInstance().addProjectManagerListener(RecentProjectsManagerBase.this); + } + if (willReopenProjectOnStart()) { willOpenProject.set(Boolean.TRUE); } } - public void appStarting(final Project projectFromCommandLine) { + public void appStarting(Project projectFromCommandLine) { if (projectFromCommandLine != null) return; - GeneralSettings generalSettings = GeneralSettings.getInstance(); - if (generalSettings.isReopenLastProject()) { - List openPaths; - synchronized (myStateLock) { - openPaths = ContainerUtil.newArrayList(myState.openPaths); - } - if (!openPaths.isEmpty()) { - for (String openPath : openPaths) { - if (isValidProjectPath(openPath)) { - doOpenProject(openPath, null, true); - } - } - } - else { - String lastProjectPath = getLastProjectPath(); - if (lastProjectPath != null) { - if (isValidProjectPath(lastProjectPath)) doOpenProject(lastProjectPath, null, false); - } - } - } + doReopenLastProject(); } public void projectFrameClosed() { diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index ccc5db7f17f7..d32c188fdf0e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -19,6 +19,7 @@ import com.intellij.CommonBundle; import com.intellij.conversion.ConversionResult; import com.intellij.conversion.ConversionService; import com.intellij.ide.AppLifecycleListener; +import com.intellij.ide.RecentProjectsManagerBase; import com.intellij.ide.impl.ProjectUtil; import com.intellij.ide.startup.impl.StartupManagerImpl; import com.intellij.notification.NotificationsManager; @@ -58,6 +59,7 @@ import com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl; import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame; import com.intellij.util.Alarm; import com.intellij.util.ArrayUtil; +import com.intellij.util.ObjectUtils; import com.intellij.util.TimeoutUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; @@ -118,7 +120,10 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt return array; } - public ProjectManagerImpl(VirtualFileManager virtualFileManager, ProgressManager progressManager) { + /** @noinspection UnusedParameters*/ + public ProjectManagerImpl(VirtualFileManager virtualFileManager, + RecentProjectsManagerBase recentProjectsManager, + ProgressManager progressManager) { myProgressManager = progressManager; Application app = ApplicationManager.getApplication(); MessageBus messageBus = app.getMessageBus(); @@ -291,7 +296,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt @NotNull String filePath, boolean isDefault, boolean isOptimiseTestLoadSpeed) { - return isDefault ? new DefaultProject(this, "", isOptimiseTestLoadSpeed, projectName) + return isDefault ? new DefaultProject(this, "", isOptimiseTestLoadSpeed, ObjectUtils.assertNotNull(projectName)) : new ProjectImpl(this, new File(filePath).getAbsolutePath(), isOptimiseTestLoadSpeed, projectName); } diff --git a/platform/platform-resources/src/META-INF/PlatformLangPlugin.xml b/platform/platform-resources/src/META-INF/PlatformLangPlugin.xml index 426575e32eca..943f3f568d68 100644 --- a/platform/platform-resources/src/META-INF/PlatformLangPlugin.xml +++ b/platform/platform-resources/src/META-INF/PlatformLangPlugin.xml @@ -22,6 +22,9 @@ + + + + diff --git a/platform/platform-resources/src/componentSets/PlatformComponents.xml b/platform/platform-resources/src/componentSets/PlatformComponents.xml index 29037ab0a7e3..8aa305c4c939 100644 --- a/platform/platform-resources/src/componentSets/PlatformComponents.xml +++ b/platform/platform-resources/src/componentSets/PlatformComponents.xml @@ -15,10 +15,6 @@ com.intellij.openapi.project.impl.ProjectStoreClassProvider com.intellij.openapi.components.impl.stores.PlatformProjectStoreClassProvider - - com.intellij.ide.RecentProjectsManagerBase - com.intellij.ide.RecentDirectoryProjectsManager - @@ -53,7 +49,7 @@ com.intellij.platform.PlatformVcsDetector - + diff --git a/platform/platform-resources/src/componentSets/PlatformLangComponents.xml b/platform/platform-resources/src/componentSets/PlatformLangComponents.xml index 7e4cbdc677aa..dc70e3968008 100644 --- a/platform/platform-resources/src/componentSets/PlatformLangComponents.xml +++ b/platform/platform-resources/src/componentSets/PlatformLangComponents.xml @@ -15,10 +15,6 @@ com.intellij.openapi.project.impl.ProjectStoreClassProvider com.intellij.openapi.components.impl.stores.PlatformLangProjectStoreClassProvider - - com.intellij.ide.RecentProjectsManagerBase - com.intellij.ide.RecentDirectoryProjectsManagerEx - diff --git a/resources/src/idea/RichPlatformPlugin.xml b/resources/src/idea/RichPlatformPlugin.xml index ae4c6b6491e0..9313e52e266a 100644 --- a/resources/src/idea/RichPlatformPlugin.xml +++ b/resources/src/idea/RichPlatformPlugin.xml @@ -10,13 +10,6 @@ - - - com.intellij.ide.RecentProjectsManagerBase - com.intellij.ide.RecentProjectsManager - - - com.intellij.framework.detection.impl.FrameworkDetectionManager @@ -133,6 +126,9 @@ + + From ccb78726b1a06d4e5ed1319508f9a4ab575bdd32 Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Fri, 17 Jan 2014 19:04:18 +0400 Subject: [PATCH 09/25] initial ssl support --- .../intellij/execution/rmi/RemoteServer.java | 9 ++ .../execution/rmi/ssl/SslSocketFactory.java | 102 ++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 platform/util-rt/src/com/intellij/execution/rmi/ssl/SslSocketFactory.java diff --git a/platform/util-rt/src/com/intellij/execution/rmi/RemoteServer.java b/platform/util-rt/src/com/intellij/execution/rmi/RemoteServer.java index dd8ef83382cf..83ff9c3958b5 100644 --- a/platform/util-rt/src/com/intellij/execution/rmi/RemoteServer.java +++ b/platform/util-rt/src/com/intellij/execution/rmi/RemoteServer.java @@ -15,6 +15,7 @@ */ package com.intellij.execution.rmi; +import com.intellij.execution.rmi.ssl.SslSocketFactory; import org.jetbrains.annotations.Nullable; import javax.naming.Context; @@ -28,6 +29,7 @@ import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.ExportException; import java.rmi.server.UnicastRemoteObject; +import java.security.Security; import java.util.Hashtable; import java.util.Random; @@ -43,6 +45,7 @@ public class RemoteServer { protected static void start(Remote remote) throws Exception { setupRMI(); banJNDI(); + setupSSL(); if (ourRemote != null) throw new AssertionError("Already started"); ourRemote = remote; @@ -101,6 +104,12 @@ public class RemoteServer { } } + public static void setupSSL() { + if (System.getProperty(SslSocketFactory.SSL_CA_CERT_PATH) != null) { + Security.setProperty("ssl.SocketFactory.provider", "com.intellij.execution.rmi.ssl.SslSocketFactory"); + } + } + @SuppressWarnings("UnusedDeclaration") public static class Jndi implements InitialContextFactory, InvocationHandler { @Override diff --git a/platform/util-rt/src/com/intellij/execution/rmi/ssl/SslSocketFactory.java b/platform/util-rt/src/com/intellij/execution/rmi/ssl/SslSocketFactory.java new file mode 100644 index 000000000000..6bdbcab59cc8 --- /dev/null +++ b/platform/util-rt/src/com/intellij/execution/rmi/ssl/SslSocketFactory.java @@ -0,0 +1,102 @@ +package com.intellij.execution.rmi.ssl; + +import javax.net.ssl.*; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.Socket; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.UUID; + +public class SslSocketFactory extends SSLSocketFactory { + public static final String SSL_CA_CERT_PATH = "sslCaCertPath"; + private SSLSocketFactory myFactory; + + public SslSocketFactory() throws GeneralSecurityException, IOException { + super(); + SSLContext ctx = SSLContext.getInstance("TLS"); + TrustManager tm; + try { + tm = new MyX509TrustManager(); + } + catch (Exception e) { + throw new RuntimeException(e); + } + + ctx.init(new KeyManager[]{}, new TrustManager[]{tm}, null); + myFactory = ctx.getSocketFactory(); + } + + public Socket createSocket(InetAddress host, int port) throws IOException { + return myFactory.createSocket(host, port); + } + + public Socket createSocket(String host, int port) throws IOException { + return myFactory.createSocket(host, port); + } + + public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { + return myFactory.createSocket(host, port, localHost, localPort); + } + + public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { + return myFactory.createSocket(address, port, localAddress, localPort); + } + + public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException { + return myFactory.createSocket(socket, host, port, autoClose); + } + + public String[] getDefaultCipherSuites() { + return myFactory.getDefaultCipherSuites(); + } + + public String[] getSupportedCipherSuites() { + return myFactory.getSupportedCipherSuites(); + } + + private static class MyX509TrustManager implements X509TrustManager { + String serverCertFile; + X509TrustManager trustManager; + + public MyX509TrustManager() throws Exception { + serverCertFile = System.getProperty(SSL_CA_CERT_PATH); + InputStream inStream = new FileInputStream(serverCertFile); + + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + X509Certificate ca = (X509Certificate)cf.generateCertificate(inStream); + inStream.close(); + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(null); + ks.setCertificateEntry(UUID.randomUUID().toString(), ca); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ks); + for (TrustManager tm : tmf.getTrustManagers()) { + if (tm instanceof X509TrustManager) { + trustManager = (X509TrustManager)tm; + break; + } + } + if (trustManager == null) { + throw new RuntimeException("No X509TrustManager found"); + } + } + + public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { + if (trustManager == null) throw new RuntimeException("No X509TrustManager found"); + trustManager.checkServerTrusted(x509Certificates, s); + } + + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + } +} From 4113b3e9c159920ace0b75b2f9be906b11eef00e Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 17 Jan 2014 15:41:56 +0100 Subject: [PATCH 10/25] IDEA-105253 Missing icon for Thread dumps view (cherry picked from commit c78400d063778c68907b03c0e0ee1a40c99d3747) --- .../execution/ui/layout/actions/RestoreViewAction.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/RestoreViewAction.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/RestoreViewAction.java index cff9749eaf04..61676bbc7044 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/RestoreViewAction.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/RestoreViewAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,12 +17,15 @@ package com.intellij.execution.ui.layout.actions; import com.intellij.execution.ui.layout.CellTransform; +import com.intellij.icons.AllIcons; import com.intellij.idea.ActionsBundle; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.ui.content.Content; +import javax.swing.*; + public class RestoreViewAction extends AnAction { private final Content myContent; @@ -38,7 +41,8 @@ public class RestoreViewAction extends AnAction { Presentation p = e.getPresentation(); p.setText(ActionsBundle.message("action.Runner.RestoreView.text", myContent.getDisplayName())); p.setDescription(ActionsBundle.message("action.Runner.RestoreView.description")); - p.setIcon(myContent.getIcon()); + Icon icon = myContent.getIcon(); + p.setIcon(icon == null ? AllIcons.Debugger.RestoreLayout : icon); } @Override From 2e395ddc1ab3a178231e97d674656b6aa3430be9 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Fri, 17 Jan 2014 19:15:56 +0400 Subject: [PATCH 11/25] Bug fix: IDEA incorrect handle escaping. --- .../maven/compiler/MavenResourcesBuilder.java | 40 ++++++++++++------- .../maven/compiler/ResourceFilteringTest.java | 12 +++++- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenResourcesBuilder.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenResourcesBuilder.java index 8f9a7b85b9cc..13bf78686482 100644 --- a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenResourcesBuilder.java +++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenResourcesBuilder.java @@ -1,6 +1,7 @@ package org.jetbrains.jps.maven.compiler; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.builders.BuildOutputConsumer; @@ -116,7 +117,13 @@ public class MavenResourcesBuilder extends TargetBuilder resolvedProperties = resolvedPropertiesParam; final Matcher matcher = delimitersPattern.matcher(text); + + boolean hasEscapeString = !StringUtil.isEmpty(moduleConfig.escapeString); + final int groupCount = matcher.groupCount(); - final String escapeString = moduleConfig.escapeString; + int firstPropertyGroupIndex = hasEscapeString ? 3 : 0; + int last = 0; while (matcher.find()) { - if (escapeString != null) { - int escapeStringStartIndex = matcher.start() - escapeString.length(); - if (escapeStringStartIndex >= last) { - if (text.startsWith(escapeString, escapeStringStartIndex)) { - out.append(text, last, escapeStringStartIndex); - out.append(matcher.group()); - last = matcher.end(); - continue; - } - } - } - out.append(text, last, matcher.start()); last = matcher.end(); + if (hasEscapeString) { + if (matcher.group(1) != null) { + out.append(moduleConfig.escapeString).append(moduleConfig.escapeString); // double escape string + continue; + } + else if (matcher.group(2) != null) { + out.append(matcher.group(3)); // escaped value + continue; + } + } + String propertyName = null; - for (int i = 0; i < groupCount; i++) { + for (int i = firstPropertyGroupIndex; i < groupCount; i++) { propertyName = matcher.group(i + 1); if (propertyName != null) { break; diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java index efd72477bf83..80e738fa6a81 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java @@ -868,10 +868,15 @@ public abstract class ResourceFilteringTest extends MavenImportingTestCase { } public void testEscapingFiltering() throws Exception { + if (!useJps()) return; + createProjectSubFile("filters/filter.properties", "xxx=value"); createProjectSubFile("resources/file.properties", "value1=\\${xxx}\n" + - "value2=${xxx}\n"); + "value2=\\\\${xxx}\n" + + "value3=\\\\\\${xxx}\n" + + "value3=\\\\\\\\${xxx}\n" + + "value4=.\\.\\\\.\\\\\\."); importProject("test" + "project" + @@ -901,7 +906,10 @@ public abstract class ResourceFilteringTest extends MavenImportingTestCase { compileModules("project"); assertResult("target/classes/file.properties", "value1=${xxx}\n" + - "value2=value\n"); + "value2=\\\\value\n" + + "value3=\\\\${xxx}\n" + + "value3=\\\\\\\\value\n" + + "value4=.\\.\\\\.\\\\\\."); } public void testPropertyPriority() throws Exception { From 6351c3b37c3df37557d2c8ef5f15285edf89f2ae Mon Sep 17 00:00:00 2001 From: Evgeny Pasynkov Date: Fri, 17 Jan 2014 15:52:04 +0100 Subject: [PATCH 12/25] Method to process stubs without firing error when stub index is overflown (for Upsource) --- .../psi/stubs/StubProcessingHelperBase.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java b/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java index e1e7acbbd338..28a5de599c70 100644 --- a/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java +++ b/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java @@ -33,6 +33,10 @@ public abstract class StubProcessingHelperBase { } public boolean processStubsInFile(final Project project, final VirtualFile file, StubIdList value, final Processor processor) { + return processStubsInFile(project, file, value, processor, false); + } + + public boolean processStubsInFile(final Project project, final VirtualFile file, StubIdList value, final Processor processor, final boolean skipOnErrors) { StubTree stubTree = null; PsiFile _psifile = PsiManager.getInstance(project).findFile(file); @@ -66,7 +70,15 @@ public abstract class StubProcessingHelperBase { stubTree = (StubTree)objectStubTree; final List> plained = stubTree.getPlainList(); for (int i = 0, size = value.size(); i < size; i++) { - final StubElement stub = plained.get(value.get(i)); + final int stubTreeIndex = value.get(i); + if (stubTreeIndex >= plained.size()) { + if (!skipOnErrors) + onInternalError(file); + + break; + } + + final StubElement stub = plained.get(stubTreeIndex); PsiUtilCore.ensureValid(psiFile); final ASTNode tree = psiFile.findTreeForStub(stubTree, stub); @@ -76,7 +88,7 @@ public abstract class StubProcessingHelperBase { PsiUtilCore.ensureValid(psi); if (!processor.process(psi)) return false; } - else { + else if (!skipOnErrors) { String persistedStubTree = ((PsiFileStubImpl)stubTree.getRoot()).printTree(); String stubTreeJustBuilt = @@ -103,11 +115,13 @@ public abstract class StubProcessingHelperBase { for (int i = 0, size = value.size(); i < size; i++) { final int stubTreeIndex = value.get(i); if (stubTreeIndex >= plained.size()) { - final VirtualFile virtualFile = psiFile.getVirtualFile(); - StubTree stubTreeFromIndex = (StubTree)StubTreeLoader.getInstance().readFromVFile(project, file); - LOG.error(stubTreeAndIndexDoNotMatch(stubTree, psiFile, plained, virtualFile, stubTreeFromIndex)); + if (!skipOnErrors) { + final VirtualFile virtualFile = psiFile.getVirtualFile(); + StubTree stubTreeFromIndex = (StubTree)StubTreeLoader.getInstance().readFromVFile(project, file); + LOG.error(stubTreeAndIndexDoNotMatch(stubTree, psiFile, plained, virtualFile, stubTreeFromIndex)); - onInternalError(file); + onInternalError(file); + } break; } From 3594766293f139781315c83b190f46986fa612c8 Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Fri, 17 Jan 2014 19:23:31 +0400 Subject: [PATCH 13/25] IDEA-115138 Eclipse code style import: Line Wrapping / Annotations is ignored, IDEA-115200 Eclipse code style import: Line Wrapping: some categories are not applied --- .../EclipseCodeStyleSchemeImporter.java | 116 +++++++++++++++++- .../importer/EclipseImportMap.properties | 24 ++-- .../importer/EclipseXmlProfileElements.java | 21 ++++ .../import/settings/eclipse_exported.xml | 18 +-- .../eclipse/EclipseSettingsImportTest.java | 63 ++++++++-- 5 files changed, 206 insertions(+), 36 deletions(-) diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseCodeStyleSchemeImporter.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseCodeStyleSchemeImporter.java index e1e432d0368b..3e76a21c3bea 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseCodeStyleSchemeImporter.java +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseCodeStyleSchemeImporter.java @@ -154,9 +154,6 @@ public class EclipseCodeStyleSchemeImporter implements SchemeImporter #org.eclipse.jdt.core.formatter.alignment_for_conditional_expression= org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=Java:SPACE_BEFORE_FOR_PARENTHESES org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=Java: @@ -49,7 +49,7 @@ org.eclipse.jdt.core.formatter.blank_lines_after_package=Java:BLANK_LINES_AFTER_ #org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters= org.eclipse.jdt.core.formatter.continuation_indentation=Java:IndentOptions: #org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator= -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=Java:ALIGN_MULTILINE_PARAMETERS_IN_CALLS +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=Java: #org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments= #org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces= #org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk= @@ -91,8 +91,8 @@ org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized org.eclipse.jdt.core.formatter.indentation.size=Java:IndentOptions:INDENT_SIZE org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=Java:SPACE_WITHIN_EMPTY_METHOD_PARENTHESES #org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant= -org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=Java:ALIGN_MULTILINE_EXTENDS_LIST -org.eclipse.jdt.core.formatter.alignment_for_assignment=Java:ALIGN_MULTILINE_ASSIGNMENT +#org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=Java:ALIGN_MULTILINE_EXTENDS_LIST +org.eclipse.jdt.core.formatter.alignment_for_assignment=Java: org.eclipse.jdt.core.formatter.tabulation.char=Java:IndentOptions: #org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters= #org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources= @@ -107,7 +107,7 @@ org.eclipse.jdt.core.formatter.blank_lines_before_method=Java:BLANK_LINES_AROUND #org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement= #org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration= #org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body= -org.eclipse.jdt.core.formatter.alignment_for_method_declaration=Java:ALIGN_MULTILINE_PARAMETERS_IN_CALLS +#org.eclipse.jdt.core.formatter.alignment_for_method_declaration= org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=Java:SPACE_WITHIN_METHOD_CALL_PARENTHESES org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=Java:SPACE_WITHIN_TRY_PARENTHESES #org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression= @@ -150,7 +150,7 @@ org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_p #org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression= org.eclipse.jdt.core.formatter.tabulation.size=Java:IndentOptions: #org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference= -org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=Java:ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE +#org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=Java:ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE #org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block= #org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference= #org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant= @@ -193,8 +193,8 @@ org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing= +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=Java: #org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration= #org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type= org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=Java:SPACE_WITHIN_WHILE_PARENTHESES @@ -236,7 +236,7 @@ org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=Java: org.eclipse.jdt.core.formatter.blank_lines_before_imports=Java:BLANK_LINES_BEFORE_IMPORTS #org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert= #org.eclipse.jdt.core.formatter.comment.format_html= -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=Java:ALIGN_MULTILINE_THROWS_LIST +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=Java: #org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters= #org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression= #org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration= @@ -248,11 +248,11 @@ org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=Java:SPA org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=Java:SPACE_BEFORE_SYNCHRONIZED_PARENTHESES #org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression= #org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws= -org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=Java:ALIGN_MULTILINE_PARAMETERS +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=Java: org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=Java:SPACE_WITHIN_ARRAY_INITIALIZER_BRACES -org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=Java:ALIGN_MULTILINE_RESOURCES +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=Java: org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=Java:IndentOptions:SMART_TABS -#org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation= +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=Java: #org.eclipse.jdt.core.formatter.comment.format_header= #org.eclipse.jdt.core.formatter.comment.format_block_comments= #org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant= diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseXmlProfileElements.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseXmlProfileElements.java index 85158fef02a3..889c866867aa 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseXmlProfileElements.java +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseXmlProfileElements.java @@ -48,4 +48,25 @@ public interface EclipseXmlProfileElements { String OPTION_TAB_CHAR = "org.eclipse.jdt.core.formatter.tabulation.char"; String OPTION_CONTINUATION_INDENT = "org.eclipse.jdt.core.formatter.continuation_indentation"; String OPTION_TAB_SIZE = "org.eclipse.jdt.core.formatter.tabulation.size"; + + String OPTION_ALIGN_EXPR_IN_ARRAY_INITIALIZER = "org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer"; + String OPTION_ALIGN_ARGS_IN_ANNOTATION = "org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation"; + String OPTION_ALIGN_ARGS_IN_METHOD_INVOCATION = "org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation"; + String OPTION_ALIGN_SUPERCLASS_IN_TYPE_DECL = "org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration"; + String OPTION_ALIGN_INTERFACES_IN_TYPE_DECL = "org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration"; + String OPTION_ALIGN_ASSIGNMENT = "org.eclipse.jdt.core.formatter.alignment_for_assignment"; + String OPTION_ALIGN_METHOD_DECL_PARAMETERS = "org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration"; + String OPTION_ALIGN_BINARY_EXPR = "org.eclipse.jdt.core.formatter.alignment_for_binary_expression"; + String OPTION_ALIGN_THROWS_IN_METHOD_DECL = "org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration"; + String OPTION_ALIGN_RESOURCES_IN_TRY = "org.eclipse.jdt.core.formatter.alignment_for_resources_in_try"; + String OPTION_ALIGN_METHOD_DECL = "org.eclipse.jdt.core.formatter.alignment_for_method_declaration"; + + int WRAP_MASK = 0x70; + + int DO_NOT_WRAP = 0x00; + int WRAP_WHERE_NECESSARY = 0x10; + int WRAP_FIRST_OTHERS_WHERE_NECESSARY = 0x20; + int WRAP_ALL_ON_NEW_LINE_EACH = 0x30; + int WRAP_ALL_INDENT_EXCEPT_FIRST = 0x40; + int WRAP_ALL_EXCEPT_FIRST = 0x50; } diff --git a/plugins/eclipse/testData/import/settings/eclipse_exported.xml b/plugins/eclipse/testData/import/settings/eclipse_exported.xml index 37dd465540a1..bc7ffd6b01c2 100644 --- a/plugins/eclipse/testData/import/settings/eclipse_exported.xml +++ b/plugins/eclipse/testData/import/settings/eclipse_exported.xml @@ -27,7 +27,7 @@ - + @@ -42,7 +42,7 @@ - + @@ -87,7 +87,7 @@ - + @@ -190,8 +190,8 @@ - - + + @@ -234,7 +234,7 @@ - + @@ -246,12 +246,12 @@ - + - + - + diff --git a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseSettingsImportTest.java b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseSettingsImportTest.java index 3fcbfa77a409..427d4537390a 100644 --- a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseSettingsImportTest.java +++ b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseSettingsImportTest.java @@ -63,7 +63,6 @@ public class EclipseSettingsImportTest extends PlatformTestCase { EditorSettingsExternalizable editorSettings = EditorSettingsExternalizable.getInstance(); boolean currAddLineFeed = editorSettings.isEnsureNewLineAtEOF(); editorSettings.setEnsureNewLineAtEOF(true); - javaSettings.ALIGN_MULTILINE_BINARY_OPERATION = true; javaSettings.SPACE_WITHIN_TRY_PARENTHESES = true; javaSettings.SPACE_WITHIN_EMPTY_METHOD_CALL_PARENTHESES = true; javaSettings.WHILE_ON_NEW_LINE = true; @@ -76,12 +75,9 @@ public class EclipseSettingsImportTest extends PlatformTestCase { javaSettings.SPACE_WITHIN_SYNCHRONIZED_PARENTHESES = true; javaSettings.SPACE_BEFORE_QUEST = false; javaSettings.BLANK_LINES_BEFORE_IMPORTS = 0; - javaSettings.ALIGN_MULTILINE_THROWS_LIST = true; javaSettings.SPACE_AFTER_COLON = false; javaSettings.SPACE_WITHIN_FOR_PARENTHESES = true; javaSettings.SPACE_BEFORE_SYNCHRONIZED_PARENTHESES = false; - javaSettings.ALIGN_MULTILINE_PARAMETERS = true; - javaSettings.ALIGN_MULTILINE_RESOURCES = true; javaSettings.SPACE_BEFORE_SWITCH_PARENTHESES = false; javaSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES = true; javaSettings.CLASS_BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE; @@ -92,6 +88,33 @@ public class EclipseSettingsImportTest extends PlatformTestCase { javaSettings.BLANK_LINES_AFTER_IMPORTS = -1; javaSettings.KEEP_FIRST_COLUMN_COMMENT = true; javaSettings.KEEP_CONTROL_STATEMENT_IN_ONE_LINE = true; + javaSettings.FIELD_ANNOTATION_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP; + javaSettings.METHOD_ANNOTATION_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP; + javaSettings.PARAMETER_ANNOTATION_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP; + javaSettings.VARIABLE_ANNOTATION_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP; + javaSettings.CLASS_ANNOTATION_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP; + javaSettings.ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION = false; + javaSettings.ARRAY_INITIALIZER_WRAP = CommonCodeStyleSettings.WRAP_ALWAYS; + javaSettings.ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE = false; + javaSettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true; + javaSettings.CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP; + javaSettings.CALL_PARAMETERS_LPAREN_ON_NEXT_LINE = true; + javaSettings.ALIGN_MULTILINE_EXTENDS_LIST = false; + javaSettings.EXTENDS_KEYWORD_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP; + javaSettings.EXTENDS_LIST_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP; + javaSettings.ALIGN_MULTILINE_ASSIGNMENT = false; + javaSettings.ASSIGNMENT_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP; + javaSettings.ALIGN_MULTILINE_PARAMETERS = true; + javaSettings.METHOD_PARAMETERS_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP; + javaSettings.METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE = false; + javaSettings.ALIGN_MULTILINE_BINARY_OPERATION = false; + javaSettings.BINARY_OPERATION_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP; + javaSettings.ALIGN_MULTILINE_THROWS_LIST = false; + javaSettings.THROWS_KEYWORD_WRAP = CommonCodeStyleSettings.WRAP_ALWAYS; + javaSettings.THROWS_LIST_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP; + javaSettings.ALIGN_MULTILINE_RESOURCES = true; + javaSettings.RESOURCE_LIST_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP; + javaSettings.RESOURCE_LIST_LPAREN_ON_NEXT_LINE = true; indentOptions.USE_TAB_CHARACTER = false; indentOptions.SMART_TABS = false; indentOptions.TAB_SIZE = 3; @@ -122,7 +145,6 @@ public class EclipseSettingsImportTest extends PlatformTestCase { assertFalse(javaSettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS); assertEquals(0, javaSettings.BLANK_LINES_BEFORE_PACKAGE); assertFalse(javaSettings.SPACE_WITHIN_FOR_PARENTHESES); - assertFalse(javaSettings.ALIGN_MULTILINE_ASSIGNMENT); assertFalse(javaSettings.SPACE_BEFORE_METHOD_PARENTHESES); assertFalse(javaSettings.SPACE_WITHIN_CATCH_PARENTHESES); assertFalse(javaSettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES); @@ -130,7 +152,6 @@ public class EclipseSettingsImportTest extends PlatformTestCase { assertFalse(javaSettings.SPACE_AROUND_UNARY_OPERATOR); assertTrue(javaSettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE); assertFalse(editorSettings.isEnsureNewLineAtEOF()); - assertFalse(javaSettings.ALIGN_MULTILINE_BINARY_OPERATION); assertFalse(javaSettings.SPACE_WITHIN_TRY_PARENTHESES); assertFalse(javaSettings.SPACE_WITHIN_EMPTY_METHOD_CALL_PARENTHESES); assertFalse(javaSettings.WHILE_ON_NEW_LINE); @@ -143,12 +164,9 @@ public class EclipseSettingsImportTest extends PlatformTestCase { assertFalse(javaSettings.SPACE_WITHIN_SYNCHRONIZED_PARENTHESES); assertTrue(javaSettings.SPACE_BEFORE_QUEST); assertEquals(1, javaSettings.BLANK_LINES_BEFORE_IMPORTS); - assertFalse(javaSettings.ALIGN_MULTILINE_THROWS_LIST); assertTrue(javaSettings.SPACE_AFTER_COLON); assertFalse(javaSettings.SPACE_WITHIN_FOR_PARENTHESES); assertTrue(javaSettings.SPACE_BEFORE_SYNCHRONIZED_PARENTHESES); - assertFalse(javaSettings.ALIGN_MULTILINE_PARAMETERS); - assertFalse(javaSettings.ALIGN_MULTILINE_RESOURCES); assertTrue(javaSettings.SPACE_BEFORE_SWITCH_PARENTHESES); assertFalse(javaSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES); assertEquals(CommonCodeStyleSettings.END_OF_LINE, javaSettings.CLASS_BRACE_STYLE); @@ -164,6 +182,33 @@ public class EclipseSettingsImportTest extends PlatformTestCase { assertTrue(settings.FORMATTER_TAGS_ENABLED); assertEquals("@off_tag", settings.FORMATTER_OFF_TAG); assertEquals("@on_tag", settings.FORMATTER_ON_TAG); + assertEquals(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM, javaSettings.FIELD_ANNOTATION_WRAP); + assertEquals(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM, javaSettings.METHOD_ANNOTATION_WRAP); + assertEquals(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM, javaSettings.VARIABLE_ANNOTATION_WRAP); + assertEquals(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM, javaSettings.PARAMETER_ANNOTATION_WRAP); + assertEquals(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM, javaSettings.CLASS_ANNOTATION_WRAP); + assertTrue(javaSettings.ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION); + assertEquals(CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.ARRAY_INITIALIZER_WRAP); + assertTrue(javaSettings.ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE); + assertFalse(javaSettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS); + assertEquals(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM, javaSettings.CALL_PARAMETERS_WRAP); + assertFalse(javaSettings.CALL_PARAMETERS_LPAREN_ON_NEXT_LINE); + assertTrue(javaSettings.ALIGN_MULTILINE_EXTENDS_LIST); + assertEquals(CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.EXTENDS_KEYWORD_WRAP); + assertEquals(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM, javaSettings.EXTENDS_LIST_WRAP); + assertTrue(javaSettings.ALIGN_MULTILINE_ASSIGNMENT); + assertEquals(CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.ASSIGNMENT_WRAP); + assertFalse(javaSettings.ALIGN_MULTILINE_PARAMETERS); + assertEquals(CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.METHOD_PARAMETERS_WRAP); + assertTrue(javaSettings.METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE); + assertTrue(javaSettings.ALIGN_MULTILINE_BINARY_OPERATION); + assertEquals(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM, javaSettings.BINARY_OPERATION_WRAP); + assertTrue(javaSettings.ALIGN_MULTILINE_THROWS_LIST); + assertEquals(CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.THROWS_KEYWORD_WRAP); + assertEquals(CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.THROWS_LIST_WRAP); + assertFalse(javaSettings.ALIGN_MULTILINE_RESOURCES); + assertEquals(CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.RESOURCE_LIST_WRAP); + assertFalse(javaSettings.RESOURCE_LIST_LPAREN_ON_NEXT_LINE); } finally { inputStream.close(); From 0b9321bc2f16aaad2f6595fddc89d9f8e0231c06 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 17 Jan 2014 15:33:01 +0100 Subject: [PATCH 14/25] IDEA-99331 Complete Statement: incorrectly completes at statement within new array size brackets --- .../smartEnter/JavaSmartEnterProcessor.java | 1 + .../MissingArrayConstructorBracketFixer.java | 41 +++++++++++++++++++ .../ArrayInitializerRBracket.java | 5 +++ .../ArrayInitializerRBracket_after.java | 5 +++ .../codeInsight/CompleteStatementTest.java | 2 + 5 files changed, 54 insertions(+) create mode 100644 java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingArrayConstructorBracketFixer.java create mode 100644 java/java-tests/testData/codeInsight/completeStatement/ArrayInitializerRBracket.java create mode 100644 java/java-tests/testData/codeInsight/completeStatement/ArrayInitializerRBracket_after.java diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/JavaSmartEnterProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/JavaSmartEnterProcessor.java index 4d53c2c97f9d..4df807f561b2 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/JavaSmartEnterProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/JavaSmartEnterProcessor.java @@ -75,6 +75,7 @@ public class JavaSmartEnterProcessor extends SmartEnterProcessor { fixers.add(new ParenthesizedFixer()); fixers.add(new SemicolonFixer()); fixers.add(new MissingArrayInitializerBraceFixer()); + fixers.add(new MissingArrayConstructorBracketFixer()); fixers.add(new EnumFieldFixer()); //ourFixers.add(new CompletionFixer()); ourFixers = fixers.toArray(new Fixer[fixers.size()]); diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingArrayConstructorBracketFixer.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingArrayConstructorBracketFixer.java new file mode 100644 index 000000000000..51530625b39b --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingArrayConstructorBracketFixer.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.editorActions.smartEnter; + +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.JavaTokenType; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiNewExpression; +import com.intellij.util.IncorrectOperationException; + +public class MissingArrayConstructorBracketFixer implements Fixer { + @Override + public void apply(Editor editor, JavaSmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException { + if (!(psiElement instanceof PsiNewExpression)) return; + PsiNewExpression expr = (PsiNewExpression)psiElement; + int count = 0; + for (PsiElement element : expr.getChildren()) { + if (element.getNode().getElementType() == JavaTokenType.LBRACKET) { + count++; + } else if (element.getNode().getElementType() == JavaTokenType.RBRACKET) { + count--; + } + } + if (count > 0) { + editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "]"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completeStatement/ArrayInitializerRBracket.java b/java/java-tests/testData/codeInsight/completeStatement/ArrayInitializerRBracket.java new file mode 100644 index 000000000000..be3a03cd7ec0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completeStatement/ArrayInitializerRBracket.java @@ -0,0 +1,5 @@ +public class Foo { + public void fails() { + boolean[] a = new boolean[f( + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completeStatement/ArrayInitializerRBracket_after.java b/java/java-tests/testData/codeInsight/completeStatement/ArrayInitializerRBracket_after.java new file mode 100644 index 000000000000..2a09299fe603 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completeStatement/ArrayInitializerRBracket_after.java @@ -0,0 +1,5 @@ +public class Foo { + public void fails() { + boolean[] a = new boolean[f()]; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java index c1341447f2a9..1affa501c894 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java @@ -258,6 +258,8 @@ public class CompleteStatementTest extends EditorActionTestCase { public void testGenericMethodBody() throws Exception { doTest(); } + public void testArrayInitializerRBracket() throws Exception { doTest(); } + private void doTestBracesNextLineStyle() throws Exception { CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); settings.BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE; From 9ffaba92930c808cae2587d55c14cd731d865b4f Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 17 Jan 2014 16:57:25 +0100 Subject: [PATCH 15/25] IDEA-65566 Allow 'NotNull' as the default element behavior for a given class or package --- .../codeInsight/NullableNotNullManager.java | 33 +++++++++++++++++-- .../ParametersAreNonnullByDefault.java | 25 ++++++++++++++ .../DataFlowInspectionTest.java | 10 ++++++ .../com/intellij/spellchecker/jetbrains.dic | 1 + 4 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/ParametersAreNonnullByDefault.java diff --git a/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java b/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java index b1c12da627a7..f74238bb1d19 100644 --- a/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java +++ b/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java @@ -23,7 +23,7 @@ import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.JDOMExternalizableStringList; import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.PsiModifierListOwner; +import com.intellij.psi.*; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -126,11 +126,38 @@ public class NullableNotNullManager implements PersistentStateComponent } public boolean isNullable(PsiModifierListOwner owner, boolean checkBases) { - return AnnotationUtil.isAnnotated(owner, getNullables(), checkBases, false); + if (AnnotationUtil.isAnnotated(owner, getNullables(), checkBases, false)) { + return true; + } + + return owner instanceof PsiParameter && isContainerAnnotated(owner, "javax.annotation.ParametersAreNullableByDefault"); } public boolean isNotNull(PsiModifierListOwner owner, boolean checkBases) { - return AnnotationUtil.isAnnotated(owner, getNotNulls(), checkBases, false); + if (AnnotationUtil.isAnnotated(owner, getNotNulls(), checkBases, false)) { + return true; + } + + return owner instanceof PsiParameter && isContainerAnnotated(owner, "javax.annotation.ParametersAreNonnullByDefault"); + } + + private static boolean isContainerAnnotated(PsiModifierListOwner owner, String annotationFQN) { + PsiElement element = owner.getParent(); + while (element != null) { + if (element instanceof PsiModifierListOwner && + AnnotationUtil.isAnnotated((PsiModifierListOwner)element, annotationFQN, false, false)) { + return true; + } + + if (element instanceof PsiClassOwner) { + String packageName = ((PsiClassOwner)element).getPackageName(); + PsiPackage psiPackage = JavaPsiFacade.getInstance(element.getProject()).findPackage(packageName); + return psiPackage != null && AnnotationUtil.isAnnotated(psiPackage, annotationFQN, false, false); + } + + element = element.getContext(); + } + return false; } public List getNullables() { diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ParametersAreNonnullByDefault.java b/java/java-tests/testData/inspection/dataFlow/fixture/ParametersAreNonnullByDefault.java new file mode 100644 index 000000000000..7dc2e51effe4 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/ParametersAreNonnullByDefault.java @@ -0,0 +1,25 @@ +import foo.*; + +class Some { + void foo() { + NotNullClass.foo(null); + NotNullClass.foo("a"); + + NullableClass.foo(null); + NullableClass.foo("a"); + + AnotherPackageNotNull.foo(null); + AnotherPackageNotNull.foo("a"); + } + +} + +@javax.annotation.ParametersAreNonnullByDefault +class NotNullClass { + static void foo(String s) {} + +} +@javax.annotation.ParametersAreNullableByDefault +class NullableClass { + static void foo(String s) {} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java index 3abc49aaddba..69c31a6b270b 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java @@ -303,6 +303,16 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase { public void testNotEqualsTypo() { doTest(); } public void testAndEquals() { doTest(); } + + public void testParametersAreNonnullByDefault() { + myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}"); + myFixture.addClass("package javax.annotation; public @interface ParametersAreNullableByDefault {}"); + + myFixture.addClass("package foo; public class AnotherPackageNotNull { public static void foo(String s) {}}"); + myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;"); + + doTest(); + } public void _testNullCheckBeforeInstanceof() { doTest(); } // http://youtrack.jetbrains.com/issue/IDEA-113220 } diff --git a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic index 5098070dec16..697e78de64d1 100644 --- a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic +++ b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic @@ -305,6 +305,7 @@ nominvalue nomonitoring nonatomic noninfingement +nonnull nonschema noorder noparallel From a8474e6fdce4badc86daa9ff04ebac370e4533c8 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Fri, 17 Jan 2014 20:39:41 +0400 Subject: [PATCH 16/25] Return instance types for instance types of superclasses --- python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java index 35585068c7b4..8c71346575cc 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java @@ -228,7 +228,7 @@ public class PyFunctionImpl extends PyPresentableElementImpl imp if (returnClassType.getPyClass() == getContainingClass()) { final PyType receiverType = context.getType(receiver); if (receiverType instanceof PyClassType && PyTypeChecker.match(returnType, receiverType, context)) { - return receiverType; + return returnClassType.isDefinition() ? receiverType : ((PyClassType)receiverType).toInstance(); } } } From b7a28d606f62e9e4d59371b2d1044af2d868f598 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 17 Jan 2014 17:49:00 +0100 Subject: [PATCH 17/25] IDEA-119514 Tip of the day in IntellliJ IDEA mentions Webstorm --- python/resources/tips/Terminal.html | 2 +- resources-en/src/tips/Terminal.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/resources/tips/Terminal.html b/python/resources/tips/Terminal.html index 0946f5bfbc9f..fcebc658521a 100644 --- a/python/resources/tips/Terminal.html +++ b/python/resources/tips/Terminal.html @@ -5,7 +5,7 @@ -

You don't need to leave PyCharm to work with your favorite shell. Just choose +

You don't need to leave &productName; to work with your favorite shell. Just choose Tools | Open Terminal on the main menu, and enjoy using the embedded local terminal.

diff --git a/resources-en/src/tips/Terminal.html b/resources-en/src/tips/Terminal.html index 84957c7b2e8f..fcebc658521a 100644 --- a/resources-en/src/tips/Terminal.html +++ b/resources-en/src/tips/Terminal.html @@ -5,7 +5,7 @@ -

You don't need to leave WebStorm to work with your favorite shell. Just choose +

You don't need to leave &productName; to work with your favorite shell. Just choose Tools | Open Terminal on the main menu, and enjoy using the embedded local terminal.

From 40dbf8eeffe290441ad269cd8c795af43f706724 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Fri, 17 Jan 2014 20:52:05 +0400 Subject: [PATCH 18/25] Detect text or binary I/O in pathlib.Path.open() --- .../python/codeInsight/stdlib/PyStdlibTypeProvider.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java index cf6b9ef19301..c1ec4cc221a9 100644 --- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java @@ -37,7 +37,8 @@ import java.util.Set; * @author yole */ public class PyStdlibTypeProvider extends PyTypeProviderBase { - private static final Set OPEN_FUNCTIONS = ImmutableSet.of("__builtin__.open", "io.open", "os.fdopen"); + private static final Set OPEN_FUNCTIONS = ImmutableSet.of("__builtin__.open", "io.open", "os.fdopen", + "pathlib.Path.open"); private static final String BINARY_FILE_TYPE = "io.FileIO[bytes]"; private static final String TEXT_FILE_TYPE = "io.TextIOWrapper[unicode]"; From 9102f56ccfd7943d8af521977709be4fd7ba6916 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Fri, 17 Jan 2014 20:52:38 +0400 Subject: [PATCH 19/25] Handle 'mode' as a keyword argument to open() as well --- .../python/codeInsight/stdlib/PyStdlibTypeProvider.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java index c1ec4cc221a9..9e2989e09650 100644 --- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java @@ -135,7 +135,10 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase { for (Map.Entry entry : arguments.entrySet()) { final PyNamedParameter parameter = entry.getValue(); if ("mode".equals(parameter.getName())) { - final PyExpression argument = entry.getKey(); + PyExpression argument = entry.getKey(); + if (argument instanceof PyKeywordArgument) { + argument = ((PyKeywordArgument)argument).getValueExpression(); + } if (argument instanceof PyStringLiteralExpression) { mode = ((PyStringLiteralExpression)argument).getStringValue(); break; From 0a359f16ec2073854c6b170d2c8e2e5f4f4f41e5 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 17 Jan 2014 18:03:44 +0100 Subject: [PATCH 20/25] IDEA-118389 Forbid completion inside guard blocks; honor greediness --- .../completion/CodeCompletionHandlerBase.java | 3 ++- .../actions/HippieWordCompletionHandler.java | 3 ++- .../openapi/editor/impl/GuardBlockTest.java | 13 ++++++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index 00cf65981960..7017fa621fb9 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -120,7 +120,8 @@ public class CodeCompletionHandlerBase { CompletionAssertions.checkEditorValid(editor); - if (editor.isViewer() || editor.getDocument().getOffsetGuard(editor.getCaretModel().getOffset()) != null) { + int offset = editor.getCaretModel().getOffset(); + if (editor.isViewer() || editor.getDocument().getRangeGuard(offset, offset) != null) { editor.getDocument().fireReadOnlyModificationAttempt(); CodeInsightUtilBase.showReadOnlyViewWarning(editor); return; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/actions/HippieWordCompletionHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/actions/HippieWordCompletionHandler.java index 4f502326e482..645e791a753b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/actions/HippieWordCompletionHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/actions/HippieWordCompletionHandler.java @@ -55,7 +55,8 @@ public class HippieWordCompletionHandler implements CodeInsightActionHandler { public void invoke(@NotNull Project project, @NotNull final Editor editor, @NotNull PsiFile file) { if (!FileModificationService.getInstance().prepareFileForWrite(file)) return; - if (editor.isViewer() || editor.getDocument().getOffsetGuard(editor.getCaretModel().getOffset()) != null) { + int offset = editor.getCaretModel().getOffset(); + if (editor.isViewer() || editor.getDocument().getRangeGuard(offset, offset) != null) { editor.getDocument().fireReadOnlyModificationAttempt(); CodeInsightUtilBase.showReadOnlyViewWarning(editor); return; diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/GuardBlockTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/GuardBlockTest.java index 01b205322c72..d441c61209ce 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/GuardBlockTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/GuardBlockTest.java @@ -78,13 +78,24 @@ public class GuardBlockTest extends LightPlatformCodeInsightFixtureTestCase { public void testNoCompletion() throws Exception { String text = "abc abd a abx"; myFixture.configureByText("x.txt", text); - createGuard(0, myFixture.getFile().getTextLength()); + int offset = myFixture.getEditor().getCaretModel().getOffset(); + createGuard(offset - 1, myFixture.getFile().getTextLength()).setGreedyToRight(true); assertNull(myFixture.completeBasic()); myFixture.checkResult(text); + //no hippie completion myFixture.performEditorAction(IdeActions.ACTION_HIPPIE_BACKWARD_COMPLETION); assertNull(LookupManager.getInstance(getProject()).getActiveLookup()); myFixture.checkResult(text); + + //no completion at the file end + myFixture.getEditor().getCaretModel().moveToOffset(myFixture.getFile().getTextLength()); + assertNull(myFixture.completeBasic()); + myFixture.checkResult("abc abd a abx"); + + //completion at the beginning of the guard fragment + myFixture.getEditor().getCaretModel().moveToOffset(offset - 1); + assertNotNull(myFixture.completeBasic()); } } From e323fe1c8712f324e962a39dea563991eccad0d1 Mon Sep 17 00:00:00 2001 From: Shaverdova Elena Date: Fri, 17 Jan 2014 21:23:44 +0400 Subject: [PATCH 21/25] WI-13685 PhpStorm doesn't save project name CR-PS-181 (cherry picked from commit ed41c77) --- .../platform/ModuleAttachProcessor.java | 5 +++++ .../renameProject/RenameProjectHandler.java | 19 ++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/platform/ModuleAttachProcessor.java b/platform/lang-impl/src/com/intellij/platform/ModuleAttachProcessor.java index 6053d01cded8..e5f458af9293 100644 --- a/platform/lang-impl/src/com/intellij/platform/ModuleAttachProcessor.java +++ b/platform/lang-impl/src/com/intellij/platform/ModuleAttachProcessor.java @@ -161,6 +161,11 @@ public class ModuleAttachProcessor extends ProjectAttachProcessor { if (!canAttachToProject()) { return null; } + return findModuleInBaseDir(project); + } + + @Nullable + public static Module findModuleInBaseDir(Project project) { for (Module module : ModuleManager.getInstance(project).getModules()) { final VirtualFile[] roots = ModuleRootManager.getInstance(module).getContentRoots(); for (VirtualFile root : roots) { diff --git a/platform/lang-impl/src/com/intellij/platform/renameProject/RenameProjectHandler.java b/platform/lang-impl/src/com/intellij/platform/renameProject/RenameProjectHandler.java index 9baec60bca13..2d44c86723e9 100644 --- a/platform/lang-impl/src/com/intellij/platform/renameProject/RenameProjectHandler.java +++ b/platform/lang-impl/src/com/intellij/platform/renameProject/RenameProjectHandler.java @@ -33,6 +33,7 @@ import com.intellij.openapi.ui.InputValidator; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Ref; import com.intellij.platform.ModuleAttachProcessor; +import com.intellij.projectImport.ProjectAttachProcessor; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.refactoring.RefactoringBundle; @@ -101,7 +102,7 @@ public class RenameProjectHandler implements RenameHandler, TitledHandler { @Override public boolean canClose(final String inputString) { - if (!inputString.equals(myProject.getName()) && (myModule == null || myModule == ModuleAttachProcessor.getPrimaryModule(myProject))) { + if (shouldRenameProject(inputString)) { myProject.setProjectName(inputString); myProject.save(); } @@ -132,5 +133,21 @@ public class RenameProjectHandler implements RenameHandler, TitledHandler { } return true; } + + private boolean shouldRenameProject(String inputString) { + if (inputString.equals(myProject.getName())) { + return false; + } + + if (myModule == null) { + return true; + } + + if (ProjectAttachProcessor.canAttachToProject()) { + return myModule == ModuleAttachProcessor.getPrimaryModule(myProject); + } + + return myModule == ModuleAttachProcessor.findModuleInBaseDir(myProject); + } } } From 032c188cd8b34337b90eef3e1133c559ad7f0c80 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 17 Jan 2014 18:27:54 +0100 Subject: [PATCH 22/25] IDEA-119416 Smart type completion proposes nothing in String concatenation expressions --- .../com/intellij/codeInsight/ExpectedTypesProvider.java | 2 +- .../smartType/EverythingInStringConcatenation-out.java | 8 ++++++++ .../smartType/EverythingInStringConcatenation.java | 8 ++++++++ .../PreferStringsInStringConcatenation.java | 6 ++++++ .../completion/SmartTypeCompletionOrderingTest.groovy | 4 ++++ .../codeInsight/completion/SmartTypeCompletionTest.java | 1 + 6 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/EverythingInStringConcatenation-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/EverythingInStringConcatenation.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferStringsInStringConcatenation.java diff --git a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java index 3f3873d78ff9..297fd1c1c149 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java @@ -666,7 +666,7 @@ public class ExpectedTypesProvider { } else if (i == JavaTokenType.PLUS) { if (anotherType == null || anotherType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) { - myResult = ExpectedTypeInfo.EMPTY_ARRAY; + myResult = new ExpectedTypeInfo[]{createInfoImpl(PsiType.getJavaLangObject(expr.getManager(), expr.getResolveScope()), ExpectedTypeInfo.TYPE_OR_SUBTYPE, anotherType, TailType.NONE)}; } else if (PsiType.DOUBLE.isAssignableFrom(anotherType)) { myResult = new ExpectedTypeInfo[]{createInfoImpl(PsiType.DOUBLE, ExpectedTypeInfo.TYPE_OR_SUBTYPE, anotherType, TailType.NONE)}; diff --git a/java/java-tests/testData/codeInsight/completion/smartType/EverythingInStringConcatenation-out.java b/java/java-tests/testData/codeInsight/completion/smartType/EverythingInStringConcatenation-out.java new file mode 100644 index 000000000000..036e7c551ae7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/EverythingInStringConcatenation-out.java @@ -0,0 +1,8 @@ +public class Test { + + { + int abcdef = 2; + System.out.println("" + abcdef); + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/EverythingInStringConcatenation.java b/java/java-tests/testData/codeInsight/completion/smartType/EverythingInStringConcatenation.java new file mode 100644 index 000000000000..f34d7bacec6b --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/EverythingInStringConcatenation.java @@ -0,0 +1,8 @@ +public class Test { + + { + int abcdef = 2; + System.out.println("" + abc); + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferStringsInStringConcatenation.java b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferStringsInStringConcatenation.java new file mode 100644 index 000000000000..56016880dce1 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferStringsInStringConcatenation.java @@ -0,0 +1,6 @@ +class Foo { + + { + System.out.println("" + ); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy index 195a1a8854c9..e19a3ada2002 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy @@ -321,6 +321,10 @@ public class SmartTypeCompletionOrderingTest extends CompletionSortingTestCase { checkPreferredItems 0, 'type', 'Object.class' } + public void testPreferStringsInStringConcatenation() { + checkPreferredItems 0, 'toString' + } + @Override protected String getBasePath() { return JavaTestUtil.getRelativeJavaTestDataPath() + BASE_PATH; diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java index 9cf3b7dc27bc..a0555fe5f5b5 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java @@ -1020,6 +1020,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase { public void testArrayInitializerBeforeVarargs() throws Throwable { doTest(); } public void testDuplicateMembersFromSuperClass() throws Throwable { doTest(); } public void testInnerAfterNew() throws Throwable { doTest(); } + public void testEverythingInStringConcatenation() throws Throwable { doTest(); } public void testMemberImportStatically() { configureByTestName(); From 2203503e1eaed4102dd30f8ad1485017fe79b16f Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 17 Jan 2014 19:09:44 +0100 Subject: [PATCH 23/25] avoid some duplication in ExpectedTypesProvider --- .../codeInsight/ExpectedTypesProvider.java | 229 +++++++----------- 1 file changed, 83 insertions(+), 146 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java index 297fd1c1c149..40ee20780605 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java @@ -35,6 +35,7 @@ import com.intellij.psi.util.*; import com.intellij.util.ArrayUtil; import com.intellij.util.NullableFunction; import com.intellij.util.Processor; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.Stack; import gnu.trove.THashSet; @@ -84,6 +85,11 @@ public class ExpectedTypesProvider { return createInfoImpl(type, kind, defaultType, tailType); } + @NotNull + private static ExpectedTypeInfoImpl createInfoImpl(@NotNull PsiType type, PsiType defaultType) { + return createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, defaultType, TailType.NONE); + } + @NotNull private static ExpectedTypeInfoImpl createInfoImpl(@NotNull PsiType type, @ExpectedTypeInfo.Type int kind, PsiType defaultType, @NotNull TailType tailType) { return new ExpectedTypeInfoImpl(type, kind, defaultType, tailType, null, ExpectedTypeInfoImpl.NULL); @@ -216,7 +222,7 @@ public class ExpectedTypesProvider { private final boolean myUsedAfter; private final ExpectedClassProvider myClassProvider; private final boolean myVoidable; - private ExpectedTypeInfo[] myResult = ExpectedTypeInfo.EMPTY_ARRAY; + final List myResult = ContainerUtil.newArrayList(); @NonNls private static final String LENGTH_SYNTHETIC_ARRAY_FIELD = "length"; private MyParentVisitor(PsiExpression expr, @@ -233,7 +239,7 @@ public class ExpectedTypesProvider { @NotNull public ExpectedTypeInfo[] getResult() { - return myResult; + return myResult.toArray(new ExpectedTypeInfo[myResult.size()]); } @Override @@ -241,7 +247,7 @@ public class ExpectedTypesProvider { if (myExpr == method.getDefaultValue()) { final PsiType type = method.getReturnType(); if (type != null) { - myResult = new ExpectedTypeInfo[]{createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.SEMICOLON)}; + myResult.add(createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.SEMICOLON)); } } } @@ -251,7 +257,7 @@ public class ExpectedTypesProvider { if (myForCompletion) { final MyParentVisitor visitor = new MyParentVisitor(expression, myForCompletion, myClassProvider, myVoidable, myUsedAfter); expression.getParent().accept(visitor); - myResult = visitor.getResult(); + myResult.addAll(visitor.myResult); return; } @@ -259,15 +265,15 @@ public class ExpectedTypesProvider { if (referenceName != null) { final PsiElement parent = expression.getParent(); if (parent instanceof PsiMethodCallExpression) { - myResult = findClassesWithDeclaredMethod((PsiMethodCallExpression)parent, myForCompletion); + Collections.addAll(myResult, findClassesWithDeclaredMethod((PsiMethodCallExpression)parent, false)); } else if (parent instanceof PsiReferenceExpression || parent instanceof PsiVariable || parent instanceof PsiExpression) { if (LENGTH_SYNTHETIC_ARRAY_FIELD.equals(referenceName)) { - myResult = anyArrayType(); + myResult.addAll(anyArrayType()); } else { - myResult = findClassesWithDeclaredField(expression); + Collections.addAll(myResult, findClassesWithDeclaredField(expression)); } } } @@ -276,7 +282,7 @@ public class ExpectedTypesProvider { @Override public void visitExpressionStatement(PsiExpressionStatement statement) { if (myVoidable) { - myResult = new ExpectedTypeInfo[]{VOID_EXPECTED}; + myResult.add(VOID_EXPECTED); } } @@ -298,20 +304,17 @@ public class ExpectedTypesProvider { type = ((PsiAnnotationMethod)parent).getReturnType(); } if (type instanceof PsiArrayType) { - myResult = new ExpectedTypeInfo[]{createInfoImpl(((PsiArrayType)type).getComponentType(), ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.UNKNOWN)}; + myResult.add(createInfoImpl(((PsiArrayType)type).getComponentType(), type)); } } @Override public void visitNameValuePair(@NotNull PsiNameValuePair pair) { final PsiType type = getAnnotationMethodType(pair); if (type == null) return; - final ExpectedTypeInfoImpl info = createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.UNKNOWN); + myResult.add(createInfoImpl(type, type)); if (type instanceof PsiArrayType) { PsiType componentType = ((PsiArrayType)type).getComponentType(); - myResult = new ExpectedTypeInfo[]{info, createInfoImpl(componentType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, componentType, TailType.UNKNOWN)}; - } - else { - myResult = new ExpectedTypeInfo[] {info}; + myResult.add(createInfoImpl(componentType, componentType)); } } @@ -374,39 +377,27 @@ public class ExpectedTypesProvider { else { expectedName = ExpectedTypeInfoImpl.NULL; } - ExpectedTypeInfoImpl info = createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, - tailTypeSemicolon ? TailType.SEMICOLON : TailType.NONE, null, expectedName); - myResult = new ExpectedTypeInfo[]{info}; - } - else { - myResult = ExpectedTypeInfo.EMPTY_ARRAY; + myResult.add(createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, + tailTypeSemicolon ? TailType.SEMICOLON : TailType.NONE, null, expectedName)); } } @Override public void visitIfStatement(PsiIfStatement statement) { - ExpectedTypeInfoImpl info = createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, - PsiType.BOOLEAN, TailTypes.IF_RPARENTH); - myResult = new ExpectedTypeInfo[]{info}; + myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailTypes.IF_RPARENTH)); } @Override public void visitWhileStatement(PsiWhileStatement statement) { - ExpectedTypeInfoImpl info = createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, - PsiType.BOOLEAN, TailTypes.WHILE_RPARENTH); - myResult = new ExpectedTypeInfo[]{info}; + myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailTypes.WHILE_RPARENTH)); } @Override public void visitDoWhileStatement(PsiDoWhileStatement statement) { - ExpectedTypeInfoImpl info = createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, - PsiType.BOOLEAN, TailTypes.WHILE_RPARENTH); - myResult = new ExpectedTypeInfo[]{info}; + myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailTypes.WHILE_RPARENTH)); } @Override public void visitForStatement(@NotNull PsiForStatement statement) { if (myExpr.equals(statement.getCondition())) { - ExpectedTypeInfoImpl info = createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, - PsiType.BOOLEAN, TailType.SEMICOLON); - myResult = new ExpectedTypeInfo[]{info}; + myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailType.SEMICOLON)); } } @@ -414,14 +405,10 @@ public class ExpectedTypesProvider { public void visitAssertStatement(@NotNull PsiAssertStatement statement) { if (statement.getAssertDescription() == myExpr) { final PsiClassType stringType = PsiType.getJavaLangString(myExpr.getManager(), myExpr.getResolveScope()); - ExpectedTypeInfoImpl info = createInfoImpl(stringType, ExpectedTypeInfo.TYPE_STRICTLY, - stringType, TailType.SEMICOLON); - myResult = new ExpectedTypeInfo[]{info}; + myResult.add(createInfoImpl(stringType, ExpectedTypeInfo.TYPE_STRICTLY, stringType, TailType.SEMICOLON)); } else { - ExpectedTypeInfoImpl info = createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, - PsiType.BOOLEAN, TailType.SEMICOLON); - myResult = new ExpectedTypeInfo[]{info}; + myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailType.SEMICOLON)); } } @@ -430,41 +417,30 @@ public class ExpectedTypesProvider { PsiType type = statement.getIterationParameter().getType(); PsiType arrayType = type.createArrayType(); - ExpectedTypeInfoImpl info1 = createInfoImpl(arrayType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, - arrayType, TailType.NONE); + myResult.add(createInfoImpl(arrayType, arrayType)); PsiManager manager = statement.getManager(); PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); PsiClass iterableClass = JavaPsiFacade.getInstance(manager.getProject()).findClass("java.lang.Iterable", statement.getResolveScope()); - if (iterableClass == null || iterableClass.getTypeParameters().length != 1) { - myResult = new ExpectedTypeInfo[]{info1}; - } - else { + if (iterableClass != null && iterableClass.getTypeParameters().length == 1) { Map map = new HashMap(); map.put(iterableClass.getTypeParameters()[0], PsiWildcardType.createExtends(manager, type)); - PsiSubstitutor substitutor = factory.createSubstitutor(map); - PsiType iterableType = factory.createType(iterableClass, substitutor); - ExpectedTypeInfoImpl info2 = createInfoImpl(iterableType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, - iterableType, TailType.NONE); - - myResult = new ExpectedTypeInfo[]{info1, info2}; + PsiType iterableType = factory.createType(iterableClass, factory.createSubstitutor(map)); + myResult.add(createInfoImpl(iterableType, iterableType)); } } } @Override public void visitSwitchStatement(@NotNull PsiSwitchStatement statement) { - ExpectedTypeInfoImpl info = createInfoImpl(PsiType.LONG, ExpectedTypeInfo.TYPE_OR_SUBTYPE, PsiType.INT, - TailType.NONE); + myResult.add(createInfoImpl(PsiType.LONG, PsiType.INT)); if (!PsiUtil.isLanguageLevel5OrHigher(statement)) { - myResult = new ExpectedTypeInfo[]{info}; return; } PsiManager manager = statement.getManager(); PsiClassType enumType = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Enum", statement.getResolveScope()); - ExpectedTypeInfoImpl enumInfo = createInfoImpl(enumType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, enumType, TailType.NONE); - myResult = new ExpectedTypeInfo[] {info, enumInfo}; + myResult.add(createInfoImpl(enumType, enumType)); } @Override @@ -475,7 +451,7 @@ public class ExpectedTypesProvider { if (expression != null) { final PsiType type = expression.getType(); if (type != null) { - myResult = new ExpectedTypeInfo[]{createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.CASE_COLON)}; + myResult.add(createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.CASE_COLON)); } } } @@ -484,14 +460,13 @@ public class ExpectedTypesProvider { @Override public void visitSynchronizedStatement(@NotNull PsiSynchronizedStatement statement) { PsiElementFactory factory = JavaPsiFacade.getInstance(statement.getProject()).getElementFactory(); PsiType objectType = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, myExpr.getResolveScope()); - myResult = new ExpectedTypeInfo[]{createInfoImpl(objectType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, objectType, TailType.NONE)}; + myResult.add(createInfoImpl(objectType, objectType)); } @Override public void visitVariable(@NotNull PsiVariable variable) { PsiType type = variable.getType(); - ExpectedTypeInfoImpl info = createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, - variable instanceof PsiResourceVariable ? TailType.NONE : TailType.SEMICOLON, null, getPropertyName(variable)); - myResult = new ExpectedTypeInfo[]{info}; + myResult.add(createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, + variable instanceof PsiResourceVariable ? TailType.NONE : TailType.SEMICOLON, null, getPropertyName(variable))); } @Override public void visitAssignmentExpression(@NotNull PsiAssignmentExpression assignment) { @@ -507,11 +482,7 @@ public class ExpectedTypesProvider { expectedName = getPropertyName((PsiVariable)refElement); } } - ExpectedTypeInfoImpl info = createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, tailType, null, expectedName); - myResult = new ExpectedTypeInfo[]{info}; - } - else { - myResult = ExpectedTypeInfo.EMPTY_ARRAY; + myResult.add(createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, tailType, null, expectedName)); } } else { @@ -534,12 +505,9 @@ public class ExpectedTypesProvider { final int kind = assignment.getOperationTokenType() != JavaTokenType.EQ ? ExpectedTypeInfo.TYPE_STRICTLY : ExpectedTypeInfo.TYPE_OR_SUPERTYPE; - ExpectedTypeInfoImpl info = createInfoImpl(type, kind, type, TailType.NONE); - myResult = new ExpectedTypeInfo[]{info}; - return; + myResult.add(createInfoImpl(type, kind, type, TailType.NONE)); } } - myResult = ExpectedTypeInfo.EMPTY_ARRAY; } } @@ -562,7 +530,7 @@ public class ExpectedTypesProvider { if (list.getParent() instanceof PsiMethodCallExpression) { PsiMethodCallExpression methodCall = (PsiMethodCallExpression)list.getParent(); CandidateInfo[] candidates = helper.getReferencedMethodCandidates(methodCall, false); - myResult = getExpectedArgumentTypesForMethodCall(candidates, list, myExpr, myForCompletion); + Collections.addAll(myResult, getExpectedArgumentTypesForMethodCall(candidates, list, myExpr, myForCompletion)); } else if (list.getParent() instanceof PsiEnumConstant) { getExpectedArgumentsTypesForEnumConstant((PsiEnumConstant)list.getParent(), list); @@ -615,7 +583,7 @@ public class ExpectedTypesProvider { array.add(new MethodCandidateInfo(constructor, substitutor, false, false, argumentList, null, argumentList.getExpressionTypes(), null)); } CandidateInfo[] candidates = array.toArray(new CandidateInfo[array.size()]); - myResult = getExpectedArgumentTypesForMethodCall(candidates, argumentList, myExpr, myForCompletion); + Collections.addAll(myResult, getExpectedArgumentTypesForMethodCall(candidates, argumentList, myExpr, myForCompletion)); } @Override @@ -628,18 +596,19 @@ public class ExpectedTypesProvider { final MyParentVisitor visitor = new MyParentVisitor(expr, myForCompletion, myClassProvider, myVoidable, myUsedAfter); myExpr = (PsiExpression)myExpr.getParent(); expr.getParent().accept(visitor); - myResult = visitor.getResult(); + myResult.addAll(visitor.myResult); if (!(expr.getParent() instanceof PsiExpressionList)) { - for (int i = 0; i < myResult.length; i++) { - final ExpectedTypeInfo info = myResult[i]; - myResult[i] = createInfoImpl(info.getType(), info.getKind(), info.getDefaultType(), TailType.NONE, info.getCalledMethod(), - new NullableComputable() { - @Nullable - @Override - public String compute() { - return ((ExpectedTypeInfoImpl)info).getExpectedName(); + for (int i = 0; i < myResult.size(); i++) { + final ExpectedTypeInfo info = myResult.get(i); + myResult.set(i, createInfoImpl(info.getType(), info.getKind(), info.getDefaultType(), TailType.NONE, info.getCalledMethod(), + new NullableComputable() { + @Nullable + @Override + public String compute() { + return ((ExpectedTypeInfoImpl)info).getExpectedName(); + } } - }); + )); } } return; @@ -655,53 +624,39 @@ public class ExpectedTypesProvider { i == JavaTokenType.GT || i == JavaTokenType.LE || i == JavaTokenType.GE) { - if (anotherType == null) { - myResult = ExpectedTypeInfo.EMPTY_ARRAY; - } - else { - ExpectedTypeInfoImpl info = createInfoImpl(PsiType.DOUBLE, ExpectedTypeInfo.TYPE_OR_SUBTYPE, - anotherType, TailType.NONE); - myResult = new ExpectedTypeInfo[]{info}; + if (anotherType != null) { + myResult.add(createInfoImpl(PsiType.DOUBLE, anotherType)); } } else if (i == JavaTokenType.PLUS) { if (anotherType == null || anotherType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) { - myResult = new ExpectedTypeInfo[]{createInfoImpl(PsiType.getJavaLangObject(expr.getManager(), expr.getResolveScope()), ExpectedTypeInfo.TYPE_OR_SUBTYPE, anotherType, TailType.NONE)}; + myResult.add(createInfoImpl(PsiType.getJavaLangObject(expr.getManager(), expr.getResolveScope()), anotherType)); } else if (PsiType.DOUBLE.isAssignableFrom(anotherType)) { - myResult = new ExpectedTypeInfo[]{createInfoImpl(PsiType.DOUBLE, ExpectedTypeInfo.TYPE_OR_SUBTYPE, anotherType, TailType.NONE)}; + myResult.add(createInfoImpl(PsiType.DOUBLE, anotherType)); } } else if (i == JavaTokenType.EQEQ || i == JavaTokenType.NE) { - ExpectedTypeInfo info = getEqualsType(anotherExpr); - myResult = info == null ? ExpectedTypeInfo.EMPTY_ARRAY : new ExpectedTypeInfo[]{info}; + ContainerUtil.addIfNotNull(myResult, getEqualsType(anotherExpr)); } else if (i == JavaTokenType.LTLT || i == JavaTokenType.GTGT || i == JavaTokenType.GTGTGT) { - if (anotherType == null) { - myResult = ExpectedTypeInfo.EMPTY_ARRAY; - } - else { - myResult = new ExpectedTypeInfo[]{createInfoImpl(PsiType.LONG, ExpectedTypeInfo.TYPE_BETWEEN, PsiType.SHORT, TailType.NONE)}; + if (anotherType != null) { + myResult.add(createInfoImpl(PsiType.LONG, ExpectedTypeInfo.TYPE_BETWEEN, PsiType.SHORT, TailType.NONE)); } } else if (i == JavaTokenType.OROR || i == JavaTokenType.ANDAND) { - ExpectedTypeInfoImpl info = createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, - PsiType.BOOLEAN, TailType.NONE); - myResult = new ExpectedTypeInfo[]{info}; + myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailType.NONE)); } else if (i == JavaTokenType.OR || i == JavaTokenType.XOR || i == JavaTokenType.AND) { - if (anotherType == null) { - myResult = ExpectedTypeInfo.EMPTY_ARRAY; - } - else { + if (anotherType != null) { ExpectedTypeInfoImpl info; if (PsiType.BOOLEAN.equals(anotherType)) { info = createInfoImpl(anotherType, ExpectedTypeInfo.TYPE_STRICTLY, anotherType, TailType.NONE); } else { - info = createInfoImpl(PsiType.LONG, ExpectedTypeInfo.TYPE_OR_SUBTYPE, anotherType, TailType.NONE); + info = createInfoImpl(PsiType.LONG, anotherType); } - myResult = new ExpectedTypeInfo[]{info}; + myResult.add(info); } } } @@ -760,17 +715,13 @@ public class ExpectedTypesProvider { info = createInfoImpl(PsiType.LONG, ExpectedTypeInfo.TYPE_OR_SUBTYPE, PsiType.INT, tailType); } } - myResult = new ExpectedTypeInfo[]{info}; + myResult.add(info); } else if (i == JavaTokenType.PLUS || i == JavaTokenType.MINUS) { - ExpectedTypeInfoImpl info = createInfoImpl(PsiType.DOUBLE, ExpectedTypeInfo.TYPE_OR_SUBTYPE, - PsiType.INT, tailType); - myResult = new ExpectedTypeInfo[]{info}; + myResult.add(createInfoImpl(PsiType.DOUBLE, ExpectedTypeInfo.TYPE_OR_SUBTYPE, PsiType.INT, tailType)); } else if (i == JavaTokenType.EXCL) { - ExpectedTypeInfoImpl info = createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, - PsiType.BOOLEAN, tailType); - myResult = new ExpectedTypeInfo[]{info}; + myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, tailType)); } } @@ -787,10 +738,10 @@ public class ExpectedTypesProvider { info = createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUPERTYPE, PsiType.INT, TailType.NONE); } else { - info = createInfoImpl(PsiType.LONG, ExpectedTypeInfo.TYPE_OR_SUBTYPE, PsiType.INT, TailType.NONE); + info = createInfoImpl(PsiType.LONG, PsiType.INT); } } - myResult = new ExpectedTypeInfo[]{info}; + myResult.add(info); } @Override @@ -812,9 +763,7 @@ public class ExpectedTypesProvider { if (arrayType instanceof PsiArrayType) { PsiType componentType = ((PsiArrayType)arrayType).getComponentType(); - ExpectedTypeInfoImpl info = createInfoImpl(componentType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, - componentType, TailType.NONE); - myResult = new ExpectedTypeInfo[]{info}; + myResult.add(createInfoImpl(componentType, componentType)); } } @@ -822,9 +771,7 @@ public class ExpectedTypesProvider { PsiExpression[] arrayDimensions = expression.getArrayDimensions(); for (PsiExpression dimension : arrayDimensions) { if (myExpr.equals(dimension)) { - ExpectedTypeInfoImpl info = createInfoImpl(PsiType.INT, ExpectedTypeInfo.TYPE_OR_SUBTYPE, - PsiType.INT, TailType.NONE); - myResult = new ExpectedTypeInfo[]{info}; + myResult.add(createInfoImpl(PsiType.INT, PsiType.INT)); return; } } @@ -832,9 +779,7 @@ public class ExpectedTypesProvider { @Override public void visitArrayAccessExpression(@NotNull PsiArrayAccessExpression expr) { if (myExpr.equals(expr.getIndexExpression())) { - ExpectedTypeInfoImpl info = createInfoImpl(PsiType.INT, ExpectedTypeInfo.TYPE_OR_SUBTYPE, PsiType.INT, TailType.NONE) - ; //todo: special tail type - myResult = new ExpectedTypeInfo[]{info}; + myResult.add(createInfoImpl(PsiType.INT, PsiType.INT)); } else if (myExpr.equals(expr.getArrayExpression())) { if (myForCompletion) { @@ -849,14 +794,13 @@ public class ExpectedTypesProvider { parent.accept(visitor); ExpectedTypeInfo[] componentTypeInfo = visitor.getResult(); if (componentTypeInfo.length == 0) { - myResult = anyArrayType(); + myResult.addAll(anyArrayType()); } else { - myResult = new ExpectedTypeInfoImpl[componentTypeInfo.length]; for (int i = 0; i < componentTypeInfo.length; i++) { ExpectedTypeInfo compInfo = componentTypeInfo[i]; PsiType expectedArrayType = compInfo.getType().createArrayType(); - myResult[i] = createInfoImpl(expectedArrayType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, expectedArrayType, TailType.NONE); + myResult.add(createInfoImpl(expectedArrayType, expectedArrayType)); } } } @@ -870,9 +814,7 @@ public class ExpectedTypesProvider { return; } - ExpectedTypeInfo info = createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, - PsiType.BOOLEAN, TailType.NONE); - myResult = new ExpectedTypeInfo[]{info}; + myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailType.NONE)); } else if (myExpr.equals(expr.getThenExpression())) { ExpectedTypeInfo[] types = getExpectedTypes(expr, myForCompletion); @@ -887,13 +829,13 @@ public class ExpectedTypesProvider { } }); } - myResult = types; + Collections.addAll(myResult, types); } else { if (!myExpr.equals(expr.getElseExpression())) { LOG.error(Arrays.asList(expr.getChildren()) + "; " + myExpr); } - myResult = getExpectedTypes(expr, myForCompletion); + Collections.addAll(myResult, getExpectedTypes(expr, myForCompletion)); } } @@ -912,18 +854,16 @@ public class ExpectedTypesProvider { throwsTypes = new PsiClassType[]{exceptionType}; } - ExpectedTypeInfo[] infos = new ExpectedTypeInfo[throwsTypes.length]; - for (int i = 0; i < infos.length; i++) { - infos[i] = createInfoImpl( + for (int i = 0; i < throwsTypes.length; i++) { + myResult.add(createInfoImpl( myExpr instanceof PsiTypeCastExpression && myForCompletion ? throwsTypes[i] : throwableType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, throwsTypes[i], TailType.SEMICOLON - ); + )); } - myResult = infos; } } @@ -931,7 +871,7 @@ public class ExpectedTypesProvider { if (codeFragment instanceof PsiExpressionCodeFragment) { final PsiType type = ((PsiExpressionCodeFragment)codeFragment).getExpectedType(); if (type != null) { - myResult = new ExpectedTypeInfo[] {createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.NONE)}; + myResult.add(createInfoImpl(type, type)); } } } @@ -1225,16 +1165,13 @@ public class ExpectedTypesProvider { } @NotNull - private ExpectedTypeInfo[] anyArrayType() { + private List anyArrayType() { PsiType objType = PsiType.getJavaLangObject(myExpr.getManager(), myExpr.getResolveScope()).createArrayType(); - ExpectedTypeInfo info = createInfoImpl(objType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, objType, - TailType.NONE); - ExpectedTypeInfo info1 = createInfoImpl(PsiType.DOUBLE.createArrayType(), ExpectedTypeInfo.TYPE_OR_SUBTYPE, - PsiType.INT.createArrayType(), TailType.NONE); + ExpectedTypeInfo info = createInfoImpl(objType, objType); + ExpectedTypeInfo info1 = createInfoImpl(PsiType.DOUBLE.createArrayType(), PsiType.INT.createArrayType()); PsiType booleanType = PsiType.BOOLEAN.createArrayType(); - ExpectedTypeInfo info2 = createInfoImpl(booleanType, ExpectedTypeInfo.TYPE_STRICTLY, booleanType, - TailType.NONE); - return new ExpectedTypeInfo[]{info, info1, info2}; + ExpectedTypeInfo info2 = createInfoImpl(booleanType, ExpectedTypeInfo.TYPE_STRICTLY, booleanType, TailType.NONE); + return Arrays.asList(info, info1, info2); } @NotNull From 9dc5a4f50f4db5ec017d4f8f39571cbff8198cf0 Mon Sep 17 00:00:00 2001 From: Irina Megorskaya Date: Fri, 17 Jan 2014 19:29:50 +0100 Subject: [PATCH 24/25] Fix IDEA-119515 for the other IDE's --- python/resources/tips/ShowHideSideBars.html | Bin 601 -> 594 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/python/resources/tips/ShowHideSideBars.html b/python/resources/tips/ShowHideSideBars.html index b7450981f3eeadb870683e2cd7e665723c9735cb..d39e28fa2e7ba63b98a1b1918a3b393b8b4ca18d 100644 GIT binary patch delta 11 Scmcb~a*1U_0^{U##!mnok_55< delta 19 Ycmcb_a+7640wX&Yg8~RlPGI~505`b>TmS$7 From 334ca32a20e28a4dbf70492a811d43848548b781 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 17 Jan 2014 19:58:29 +0100 Subject: [PATCH 25/25] IDEA-99943 Allow to filter thread dump by a word in stacktrace --- .../intellij/unscramble/ThreadDumpPanel.java | 89 ++++++++++++++++--- .../unscramble/AnalyzeStacktraceUtil.java | 2 +- 2 files changed, 79 insertions(+), 12 deletions(-) diff --git a/java/java-impl/src/com/intellij/unscramble/ThreadDumpPanel.java b/java/java-impl/src/com/intellij/unscramble/ThreadDumpPanel.java index 4fc26a0e826a..4130d0a119a0 100644 --- a/java/java-impl/src/com/intellij/unscramble/ThreadDumpPanel.java +++ b/java/java-impl/src/com/intellij/unscramble/ThreadDumpPanel.java @@ -15,18 +15,22 @@ */ package com.intellij.unscramble; +import com.intellij.codeInsight.highlighting.HighlightManager; import com.intellij.execution.ui.ConsoleView; import com.intellij.icons.AllIcons; +import com.intellij.ide.DataManager; import com.intellij.notification.NotificationGroup; -import com.intellij.openapi.actionSystem.ActionManager; -import com.intellij.openapi.actionSystem.ActionPlaces; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.colors.EditorColors; +import com.intellij.openapi.editor.colors.EditorColorsManager; +import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.ide.CopyPasteManager; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.Splitter; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ToolWindowId; import com.intellij.ui.*; import com.intellij.ui.components.JBList; @@ -34,6 +38,7 @@ import com.intellij.util.PlatformIcons; import com.intellij.util.ui.UIUtil; import javax.swing.*; +import javax.swing.event.DocumentEvent; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; @@ -58,14 +63,16 @@ public class ThreadDumpPanel extends JPanel { private static final Icon EDT_BUSY_ICON_DAEMON = new LayeredIcon(EdtBusy, Daemon_sign); private static final Icon IO_ICON_DAEMON = new LayeredIcon(IO, Daemon_sign); private final JBList myThreadList; + private final List myThreadDump; - public ThreadDumpPanel(Project project, final ConsoleView consoleView, final DefaultActionGroup toolbarActions, final List threadDump) { + public ThreadDumpPanel(final Project project, final ConsoleView consoleView, final DefaultActionGroup toolbarActions, final List threadDump) { super(new BorderLayout()); + myThreadDump = threadDump; final ThreadState[] data = threadDump.toArray(new ThreadState[threadDump.size()]); - DefaultListModel model = new DefaultListModel(); - for (ThreadState threadState : data) { - model.addElement(threadState); - } + final DefaultListModel model = new DefaultListModel(); + + final SearchTextField filterField = new SearchTextField(); + myThreadList = new JBList(model); myThreadList.setCellRenderer(new ThreadListCellRenderer()); myThreadList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); @@ -82,18 +89,78 @@ public class ThreadDumpPanel extends JPanel { myThreadList.repaint(); } }); + + DocumentAdapter filterListener = new DocumentAdapter() { + @Override + protected void textChanged(DocumentEvent e) { + String text = filterField.getText(); + model.clear(); + for (ThreadState state : data) { + if (StringUtil.containsIgnoreCase(state.getStackTrace(), text) || StringUtil.containsIgnoreCase(state.getName(), text)) { + //noinspection unchecked + model.addElement(state); + } + } + if (!model.isEmpty()) { + myThreadList.setSelectedIndex(0); + } + myThreadList.revalidate(); + myThreadList.repaint(); + } + }; + filterField.addDocumentListener(filterListener); + filterListener.changedUpdate(null); + toolbarActions.add(new CopyToClipboardAction(threadDump, project)); toolbarActions.add(new SortThreadsAction()); //toolbarActions.add(new ShowRecentlyChanged()); add(ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, toolbarActions, false).getComponent(), BorderLayout.WEST); + + JPanel filterPanel = new JPanel(new BorderLayout()); + filterPanel.add(new JLabel("Filter:"), BorderLayout.WEST); + filterPanel.add(filterField); + + JPanel leftPanel = new JPanel(new BorderLayout()); + leftPanel.add(filterPanel, BorderLayout.NORTH); + leftPanel.add(ScrollPaneFactory.createScrollPane(myThreadList, SideBorder.LEFT | SideBorder.RIGHT), BorderLayout.CENTER); final Splitter splitter = new Splitter(false, 0.3f); - splitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myThreadList, SideBorder.LEFT | SideBorder.RIGHT)); + splitter.setFirstComponent(leftPanel); splitter.setSecondComponent(consoleView.getComponent()); add(splitter, BorderLayout.CENTER); new ListSpeedSearch(myThreadList).setComparator(new SpeedSearchComparator(false, true)); + + final Editor editor = CommonDataKeys.EDITOR.getData(DataManager.getInstance().getDataContext(consoleView.getPreferredFocusableComponent())); + assert editor != null; + editor.getDocument().addDocumentListener(new com.intellij.openapi.editor.event.DocumentAdapter() { + @Override + public void documentChanged(com.intellij.openapi.editor.event.DocumentEvent e) { + String filter = filterField.getText(); + if (StringUtil.isNotEmpty(filter)) { + highlightOccurrences(filter, project, editor); + } + } + }); + + } + + private static void highlightOccurrences(String filter, Project project, Editor editor) { + final HighlightManager highlightManager = HighlightManager.getInstance(project); + EditorColorsManager colorManager = EditorColorsManager.getInstance(); + final TextAttributes attributes = colorManager.getGlobalScheme().getAttributes(EditorColors.TEXT_SEARCH_RESULT_ATTRIBUTES); + String documentText = editor.getDocument().getText(); + int i = -1; + while (true) { + int nextOccurrence = StringUtil.indexOfIgnoreCase(documentText, filter, i + 1); + if (nextOccurrence < 0) { + break; + } + i = nextOccurrence; + highlightManager.addOccurrenceHighlight(editor, i, i + filter.length(), attributes, + HighlightManager.HIDE_BY_TEXT_CHANGE, null, null); + } } private static Icon getThreadStateIcon(final ThreadState threadState) { @@ -119,7 +186,7 @@ public class ThreadDumpPanel extends JPanel { return daemon ? RUNNING_ICON_DAEMON : Running; } - private static enum StateCode {RUN, RUN_IO, RUN_SOCKET, PAUSED, LOCKED, EDT, IDLE} + private enum StateCode {RUN, RUN_IO, RUN_SOCKET, PAUSED, LOCKED, EDT, IDLE} private static StateCode getThreadStateCode(final ThreadState state) { if (state.isSleeping()) return StateCode.PAUSED; if (state.isWaiting()) return StateCode.LOCKED; diff --git a/platform/lang-impl/src/com/intellij/unscramble/AnalyzeStacktraceUtil.java b/platform/lang-impl/src/com/intellij/unscramble/AnalyzeStacktraceUtil.java index a687669f8d5c..6bf36675a6ac 100644 --- a/platform/lang-impl/src/com/intellij/unscramble/AnalyzeStacktraceUtil.java +++ b/platform/lang-impl/src/com/intellij/unscramble/AnalyzeStacktraceUtil.java @@ -54,7 +54,7 @@ import java.awt.datatransfer.Transferable; * @author yole */ public class AnalyzeStacktraceUtil { - public static ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.analyzeStacktraceFilter"); + public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.analyzeStacktraceFilter"); private AnalyzeStacktraceUtil() { }