From 863b1a495b24c2d3c85a0a83699fec2ed4d45629 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Wed, 30 Jan 2013 12:27:53 +0100 Subject: [PATCH 1/2] merging HashingStrategy and EqualityPolicy interfaces --- .../intellij/util/containers/SLRUCache.java | 4 +-- .../com/intellij/util/containers/SLRUMap.java | 6 ++-- ...shingStrategy.java => EqualityPolicy.java} | 31 ++++++++++--------- .../util/containers/hash/HashUtil.java | 4 +-- .../util/containers/hash/LinkedHashMap.java | 20 ++++++------ .../com/intellij/util/io/EqualityPolicy.java | 8 +++-- .../intellij/util/io/PersistentHashMap.java | 10 +++--- 7 files changed, 43 insertions(+), 40 deletions(-) rename platform/util/src/com/intellij/util/containers/hash/{HashingStrategy.java => EqualityPolicy.java} (55%) diff --git a/platform/util/src/com/intellij/util/containers/SLRUCache.java b/platform/util/src/com/intellij/util/containers/SLRUCache.java index 7c966af7d8a3..07c605474e4c 100644 --- a/platform/util/src/com/intellij/util/containers/SLRUCache.java +++ b/platform/util/src/com/intellij/util/containers/SLRUCache.java @@ -19,7 +19,7 @@ */ package com.intellij.util.containers; -import com.intellij.util.containers.hash.HashingStrategy; +import com.intellij.util.containers.hash.EqualityPolicy; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,7 +28,7 @@ public abstract class SLRUCache extends SLRUMap { super(protectedQueueSize, probationalQueueSize); } - protected SLRUCache(final int protectedQueueSize, final int probationalQueueSize, HashingStrategy hashingStrategy) { + protected SLRUCache(final int protectedQueueSize, final int probationalQueueSize, EqualityPolicy hashingStrategy) { super(protectedQueueSize, probationalQueueSize, hashingStrategy); } diff --git a/platform/util/src/com/intellij/util/containers/SLRUMap.java b/platform/util/src/com/intellij/util/containers/SLRUMap.java index dff8e4bef9e8..e3ff76265e42 100644 --- a/platform/util/src/com/intellij/util/containers/SLRUMap.java +++ b/platform/util/src/com/intellij/util/containers/SLRUMap.java @@ -20,7 +20,7 @@ package com.intellij.util.containers; import com.intellij.util.Consumer; -import com.intellij.util.containers.hash.HashingStrategy; +import com.intellij.util.containers.hash.EqualityPolicy; import com.intellij.util.containers.hash.LinkedHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -41,10 +41,10 @@ public class SLRUMap { private static final int FACTOR = Integer.getInteger("idea.slru.factor", 1); public SLRUMap(final int protectedQueueSize, final int probationalQueueSize) { - this(protectedQueueSize, probationalQueueSize, (HashingStrategy)HashingStrategy.CANONICAL); + this(protectedQueueSize, probationalQueueSize, (EqualityPolicy)EqualityPolicy.CANONICAL); } - public SLRUMap(final int protectedQueueSize, final int probationalQueueSize, HashingStrategy hashingStrategy) { + public SLRUMap(final int protectedQueueSize, final int probationalQueueSize, EqualityPolicy hashingStrategy) { myProtectedQueueSize = protectedQueueSize * FACTOR; myProbationalQueueSize = probationalQueueSize * FACTOR; diff --git a/platform/util/src/com/intellij/util/containers/hash/HashingStrategy.java b/platform/util/src/com/intellij/util/containers/hash/EqualityPolicy.java similarity index 55% rename from platform/util/src/com/intellij/util/containers/hash/HashingStrategy.java rename to platform/util/src/com/intellij/util/containers/hash/EqualityPolicy.java index 8aed99385eee..138997faa951 100644 --- a/platform/util/src/com/intellij/util/containers/hash/HashingStrategy.java +++ b/platform/util/src/com/intellij/util/containers/hash/EqualityPolicy.java @@ -15,34 +15,35 @@ */ package com.intellij.util.containers.hash; -public interface HashingStrategy { - HashingStrategy IDENTITY = new HashingStrategy() { + +public interface EqualityPolicy { + EqualityPolicy IDENTITY = new EqualityPolicy() { + @Override - public int computeHashCode(Object object) { - return System.identityHashCode(object); + public int getHashCode(Object value) { + return System.identityHashCode(value); } @Override - public boolean equals(Object o1, Object o2) { - return o1 == o2; + public boolean isEqual(Object val1, Object val2) { + return val1 == val2; } }; - HashingStrategy CANONICAL = new HashingStrategy() { + EqualityPolicy CANONICAL = new EqualityPolicy() { + @Override - public int computeHashCode(Object object) { - return object != null ? object.hashCode() : 0; + public int getHashCode(Object value) { + return value != null ? value.hashCode() : 0; } @Override - public boolean equals(Object o1, Object o2) { - return o1 != null ? o1.equals(o2) : o2 == null; + public boolean isEqual(Object val1, Object val2) { + return val1 != null ? val1.equals(val2) : val2 == null; } }; + int getHashCode(T value); - int computeHashCode(T object); - - boolean equals(T o1, T o2); - + boolean isEqual(T val1, T val2); } diff --git a/platform/util/src/com/intellij/util/containers/hash/HashUtil.java b/platform/util/src/com/intellij/util/containers/hash/HashUtil.java index dc996f026676..17497dc6d6d0 100644 --- a/platform/util/src/com/intellij/util/containers/hash/HashUtil.java +++ b/platform/util/src/com/intellij/util/containers/hash/HashUtil.java @@ -35,9 +35,9 @@ class HashUtil { } - public static int hash(Object key, HashingStrategy hashingStrategy) { + public static int hash(Object key, EqualityPolicy hashingStrategy) { - return key == null ? 0 : hashingStrategy.computeHashCode(key) & 0x7fffffff; + return key == null ? 0 : hashingStrategy.getHashCode(key) & 0x7fffffff; } diff --git a/platform/util/src/com/intellij/util/containers/hash/LinkedHashMap.java b/platform/util/src/com/intellij/util/containers/hash/LinkedHashMap.java index b154e23fe89b..6090c8a7599e 100644 --- a/platform/util/src/com/intellij/util/containers/hash/LinkedHashMap.java +++ b/platform/util/src/com/intellij/util/containers/hash/LinkedHashMap.java @@ -28,7 +28,7 @@ public class LinkedHashMap extends AbstractMap implements Map private int capacity; private int size; private final float loadFactor; - private final HashingStrategy hashingStrategy; + private final EqualityPolicy hashingStrategy; public LinkedHashMap() { @@ -40,14 +40,14 @@ public class LinkedHashMap extends AbstractMap implements Map } public LinkedHashMap(int capacity, float loadFactor) { - this(capacity, loadFactor, (HashingStrategy)HashingStrategy.CANONICAL); + this(capacity, loadFactor, (EqualityPolicy)EqualityPolicy.CANONICAL); } - public LinkedHashMap(HashingStrategy hashingStrategy) { + public LinkedHashMap(EqualityPolicy hashingStrategy) { this(0, HashUtil.DEFAULT_LOAD_FACTOR, hashingStrategy); } - public LinkedHashMap(int capacity, float loadFactor, HashingStrategy hashingStrategy) { + public LinkedHashMap(int capacity, float loadFactor, EqualityPolicy hashingStrategy) { this.loadFactor = loadFactor; this.hashingStrategy = hashingStrategy; clear(capacity); @@ -72,7 +72,7 @@ public class LinkedHashMap extends AbstractMap implements Map for (Entry e = table[index]; e != null; e = e.hashNext) { final K entryKey; - if (e.keyHash == hash && ((entryKey = e.key) == key || hashingStrategy.equals(entryKey, (K)key))) { + if (e.keyHash == hash && ((entryKey = e.key) == key || hashingStrategy.isEqual(entryKey, (K)key))) { moveToTop(e); return e.value; @@ -87,7 +87,7 @@ public class LinkedHashMap extends AbstractMap implements Map final int index = hash % table.length; for (Entry e = table[index]; e != null; e = e.hashNext) { final K entryKey; - if (e.keyHash == hash && ((entryKey = e.key) == key || hashingStrategy.equals(entryKey, key))) { + if (e.keyHash == hash && ((entryKey = e.key) == key || hashingStrategy.isEqual(entryKey, key))) { moveToTop(e); return e.setValue(value); } @@ -132,7 +132,7 @@ public class LinkedHashMap extends AbstractMap implements Map return null; } K entryKey; - if (e.keyHash == hash && ((entryKey = e.key) == key || hashingStrategy.equals(entryKey, (K)key))) { + if (e.keyHash == hash && ((entryKey = e.key) == key || hashingStrategy.isEqual(entryKey, (K)key))) { table[index] = e.hashNext; } else { @@ -142,7 +142,7 @@ public class LinkedHashMap extends AbstractMap implements Map if (e == null) { return null; } - if (e.keyHash == hash && ((entryKey = e.key) == key || hashingStrategy.equals(entryKey, (K)key))) { + if (e.keyHash == hash && ((entryKey = e.key) == key || hashingStrategy.isEqual(entryKey, (K)key))) { last.hashNext = e.hashNext; break; } @@ -271,8 +271,8 @@ public class LinkedHashMap extends AbstractMap implements Map private abstract class LinkedHashIterator implements Iterator { - private Entry e = top; - private Entry last; + private LinkedHashMap.Entry e = top; + private LinkedHashMap.Entry last; public boolean hasNext() { return e != null; diff --git a/platform/util/src/com/intellij/util/io/EqualityPolicy.java b/platform/util/src/com/intellij/util/io/EqualityPolicy.java index 36f5c4157bd3..e1396cdc99e0 100644 --- a/platform/util/src/com/intellij/util/io/EqualityPolicy.java +++ b/platform/util/src/com/intellij/util/io/EqualityPolicy.java @@ -15,8 +15,10 @@ */ package com.intellij.util.io; -public interface EqualityPolicy { - int getHashCode(T value); - boolean isEqual(T val1, T val2); +@Deprecated +/** + * Use {@link com.intellij.util.containers.hash.EqualityPolicy} directly + */ +public interface EqualityPolicy extends com.intellij.util.containers.hash.EqualityPolicy{ } diff --git a/platform/util/src/com/intellij/util/io/PersistentHashMap.java b/platform/util/src/com/intellij/util/io/PersistentHashMap.java index 1ebe352e0ed1..6d7a75cca1b4 100644 --- a/platform/util/src/com/intellij/util/io/PersistentHashMap.java +++ b/platform/util/src/com/intellij/util/io/PersistentHashMap.java @@ -23,7 +23,7 @@ import com.intellij.util.CommonProcessors; import com.intellij.util.Processor; import com.intellij.util.containers.LimitedPool; import com.intellij.util.containers.SLRUCache; -import com.intellij.util.containers.hash.HashingStrategy; +import com.intellij.util.containers.hash.EqualityPolicy; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -180,15 +180,15 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } private SLRUCache createAppendCache(final KeyDescriptor keyDescriptor) { - final HashingStrategy hashingStrategy = new HashingStrategy() { + final EqualityPolicy hashingStrategy = new EqualityPolicy() { @Override - public int computeHashCode(Key object) { + public int getHashCode(Key object) { return keyDescriptor.getHashCode(object); } @Override - public boolean equals(Key o1, Key o2) { - return keyDescriptor.isEqual(o1, o2); + public boolean isEqual(Key val1, Key val2) { + return keyDescriptor.isEqual(val1, val2); } }; return new SLRUCache(16 * 1024, 4 * 1024, hashingStrategy) { From 23d936db66f1754ee816eecd48ca39be1bf6f0a5 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 30 Jan 2013 15:50:28 +0400 Subject: [PATCH 2/2] method refs: attempt to use parent to infer constructor type (IDEA-98846) --- .../source/resolve/PsiResolveHelperImpl.java | 15 +++++++++--- ...onstructorNonAbstractAbstractExpected.java | 23 +++++++++++++++++++ .../lambda/MethodRefHighlightingTest.java | 4 ++++ 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ConstructorNonAbstractAbstractExpected.java diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java index 32d9942bedd0..56354792d451 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java @@ -221,7 +221,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper { if (nullPassed && currentSubstitution == null) return RAW_INFERENCE; } else if (argumentType instanceof PsiMethodReferenceType) { final PsiMethodReferenceExpression referenceExpression = ((PsiMethodReferenceType)argumentType).getExpression(); - currentSubstitution = inferConstraintFromFunctionalInterfaceMethod(typeParameter, referenceExpression, partialSubstitutor.substitute(parameterType)); + currentSubstitution = inferConstraintFromFunctionalInterfaceMethod(typeParameter, referenceExpression, partialSubstitutor.substitute(parameterType), partialSubstitutor, policy); } else { currentSubstitution = getSubstitutionForTypeParameterConstraint(typeParameter, parameterType, @@ -608,7 +608,9 @@ public class PsiResolveHelperImpl implements PsiResolveHelper { @Nullable private static Pair inferConstraintFromFunctionalInterfaceMethod(final PsiTypeParameter typeParam, final PsiMethodReferenceExpression methodReferenceExpression, - final PsiType functionalInterfaceType) { + final PsiType functionalInterfaceType, + final PsiSubstitutor partialSubstitutor, + final ParameterTypeInferencePolicy policy) { final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); final PsiMethod functionalInterfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult); if (functionalInterfaceMethod != null) { @@ -669,7 +671,14 @@ public class PsiResolveHelperImpl implements PsiResolveHelper { } else { argType = methReferenceResolveResult.getSubstitutor().substitute(subst.substitute(method.getReturnType())); } - return getSubstitutionForTypeParameterConstraint(typeParam, functionalInterfaceReturnType, argType, true, PsiUtil.getLanguageLevel(functionalInterfaceMethod)); + final Pair typeParameterConstraint = + getSubstitutionForTypeParameterConstraint(typeParam, functionalInterfaceReturnType, argType, true, PsiUtil.getLanguageLevel(functionalInterfaceMethod)); + if (typeParameterConstraint != null && typeParameterConstraint.getSecond() != ConstraintType.EQUALS && method.isConstructor()) { + final Pair constraintFromParent = + inferMethodTypeParameterFromParent(typeParam, partialSubstitutor, methodReferenceExpression.getParent().getParent(), policy); + if (constraintFromParent != null && constraintFromParent.getSecond() == ConstraintType.EQUALS) return constraintFromParent; + } + return typeParameterConstraint; } } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ConstructorNonAbstractAbstractExpected.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ConstructorNonAbstractAbstractExpected.java new file mode 100644 index 000000000000..86d8bea66f7d --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ConstructorNonAbstractAbstractExpected.java @@ -0,0 +1,23 @@ +import java.util.ArrayList; +import java.util.List; + +public class IDEA99970 { + public static Collector toCollection(Supplier collectionFactory) { + return null; + } + + public static Collector> toList() { + return toCollection(ArrayList::new); + } + + public static Collector> toList1() { + return toCollection(ArrayList::new); + } + +} + +interface Supplier { + public T get(); +} + +interface Collector {} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java index 00a5787e3ab1..997e0d563f1c 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java @@ -167,6 +167,10 @@ public class MethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testConstructorNonAbstractAbstractExpected() throws Exception { + doTest(); + } + private void doTest() throws Exception { doTest(false); }