type casts in relevant method chain completion: various renames

This commit is contained in:
Dmitry Batkovich
2017-09-25 12:32:11 +03:00
parent eb9fd79648
commit 614810f8cd
13 changed files with 184 additions and 243 deletions
@@ -179,13 +179,13 @@ class CompilerReferenceReader {
return myIndex;
}
TObjectIntHashMap<LightRef> getTypeCastsInside(@NotNull LightRef.LightClassHierarchyElementDef toType, @NotNull TIntHashSet ids) throws StorageException {
TObjectIntHashMap<LightRef> getTypeCasts(@NotNull LightRef.LightClassHierarchyElementDef castType, @NotNull TIntHashSet fileIds) throws StorageException {
TObjectIntHashMap<LightRef> typeCastStats = new TObjectIntHashMap<>();
myIndex.get(CompilerIndices.BACK_CAST).getData(toType).forEach(new ValueContainer.ContainerAction<Collection<LightRef>>() {
myIndex.get(CompilerIndices.BACK_CAST).getData(castType).forEach(new ValueContainer.ContainerAction<Collection<LightRef>>() {
@Override
public boolean perform(int id, Collection<LightRef> value) {
if (!ids.contains(id)) return true;
for (LightRef ref : value) {
public boolean perform(int id, Collection<LightRef> values) {
if (!fileIds.contains(id)) return true;
for (LightRef ref : values) {
if (!typeCastStats.adjustValue(ref, 1)) {
typeCastStats.put(ref, 1);
}
@@ -16,7 +16,8 @@
package com.intellij.compiler.backwardRefs;
import com.intellij.compiler.CompilerReferenceService;
import com.intellij.compiler.chainsSearch.SignatureAndOccurrences;
import com.intellij.compiler.chainsSearch.MethodRefAndOccurrences;
import com.intellij.compiler.chainsSearch.context.ChainCompletionContext;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -34,8 +35,9 @@ public abstract class CompilerReferenceServiceEx extends CompilerReferenceServic
}
@NotNull
public abstract SortedSet<SignatureAndOccurrences> findMethodReferenceOccurrences(@NotNull String rawReturnType,
@SignatureData.IteratorKind byte iteratorKind)
public abstract SortedSet<MethodRefAndOccurrences> findMethodReferenceOccurrences(@NotNull String rawReturnType,
@SignatureData.IteratorKind byte iteratorKind,
@NotNull ChainCompletionContext context)
throws ReferenceIndexUnavailableException;
@Nullable
@@ -20,8 +20,9 @@ import com.intellij.compiler.backwardRefs.view.CompilerReferenceFindUsagesTestIn
import com.intellij.compiler.backwardRefs.view.CompilerReferenceHierarchyTestInfo;
import com.intellij.compiler.backwardRefs.view.DirtyScopeTestInfo;
import com.intellij.compiler.chainsSearch.ChainSearchMagicConstants;
import com.intellij.compiler.chainsSearch.MethodIncompleteSignature;
import com.intellij.compiler.chainsSearch.SignatureAndOccurrences;
import com.intellij.compiler.chainsSearch.MethodCall;
import com.intellij.compiler.chainsSearch.MethodRefAndOccurrences;
import com.intellij.compiler.chainsSearch.context.ChainCompletionContext;
import com.intellij.compiler.server.BuildManager;
import com.intellij.compiler.server.BuildManagerListener;
import com.intellij.lang.injection.InjectedLanguageManager;
@@ -222,8 +223,9 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceServiceEx imp
@NotNull
@Override
public SortedSet<SignatureAndOccurrences> findMethodReferenceOccurrences(@NotNull String rawReturnType,
@SignatureData.IteratorKind byte iteratorKind) {
public SortedSet<MethodRefAndOccurrences> findMethodReferenceOccurrences(@NotNull String rawReturnType,
@SignatureData.IteratorKind byte iteratorKind,
@NotNull ChainCompletionContext context) {
try {
myReadDataLock.lock();
try {
@@ -242,15 +244,15 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceServiceEx imp
.distinct()
.map(r -> {
int count = myReader.getOccurrenceCount(r);
return count <= 1 ? null : new SignatureAndOccurrences(
new MethodIncompleteSignature((LightRef.JavaLightMethodRef)r, sd, this),
return count <= 1 ? null : new MethodRefAndOccurrences(
new MethodCall((LightRef.JavaLightMethodRef)r, sd, context),
count);
}))
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(x -> x.getSignature(), Collectors.summarizingInt(x -> x.getOccurrenceCount())))
.entrySet()
.stream()
.map(e -> new SignatureAndOccurrences(e.getKey(), (int)e.getValue().getSum()))
.map(e -> new MethodRefAndOccurrences(e.getKey(), (int)e.getValue().getSum()))
.collect(Collectors.toCollection(TreeSet::new));
}
finally {
@@ -280,7 +282,7 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceServiceEx imp
LightRef.LightClassHierarchyElementDef owner = method.getOwner();
TObjectIntHashMap<LightRef> typeCasts = myReader.getTypeCastsInside(owner, ids);
TObjectIntHashMap<LightRef> typeCasts = myReader.getTypeCasts(owner, ids);
LightRef[] best = {null};
int[] bestFileCount = {0};
@@ -28,11 +28,11 @@ import java.util.*;
public class ChainSearcher {
@NotNull
public static List<CallChain> search(int pathMaximalLength,
ChainSearchTarget searchTarget,
int maxResultSize,
ChainCompletionContext context,
CompilerReferenceServiceEx compilerReferenceServiceEx) {
public static List<OperationChain> search(int pathMaximalLength,
ChainSearchTarget searchTarget,
int maxResultSize,
ChainCompletionContext context,
CompilerReferenceServiceEx compilerReferenceServiceEx) {
SearchInitializer initializer = createInitializer(searchTarget, compilerReferenceServiceEx, context);
return search(compilerReferenceServiceEx, initializer, pathMaximalLength, maxResultSize, context);
}
@@ -41,54 +41,49 @@ public class ChainSearcher {
private static SearchInitializer createInitializer(ChainSearchTarget target,
CompilerReferenceServiceEx referenceServiceEx,
ChainCompletionContext context) {
SortedSet<SignatureAndOccurrences> methods = null;
SortedSet<MethodRefAndOccurrences> methods = Collections.emptySortedSet();
for (byte kind : target.getArrayKind()) {
SortedSet<SignatureAndOccurrences> currentMethods =
referenceServiceEx.findMethodReferenceOccurrences(target.getClassQName(), kind);
if (methods == null) {
methods = currentMethods;
} else {
methods = unionSortedSet(currentMethods, methods);
}
SortedSet<MethodRefAndOccurrences> currentMethods = referenceServiceEx.findMethodReferenceOccurrences(target.getClassQName(), kind, context);
methods = methods == null ? currentMethods : unionSortedSet(currentMethods, methods);
}
return new SearchInitializer(methods, context);
}
@NotNull
private static List<CallChain> search(CompilerReferenceServiceEx referenceServiceEx,
SearchInitializer initializer,
int chainMaxLength,
int maxResultSize,
ChainCompletionContext context) {
LinkedList<CallChain> q = initializer.getChainQueue();
private static List<OperationChain> search(CompilerReferenceServiceEx referenceServiceEx,
SearchInitializer initializer,
int chainMaxLength,
int maxResultSize,
ChainCompletionContext context) {
LinkedList<OperationChain> q = initializer.getChainQueue();
List<CallChain> result = new ArrayList<>();
List<OperationChain> result = new ArrayList<>();
while (!q.isEmpty()) {
ProgressManager.checkCanceled();
CallChain currentChain = q.poll();
RefChainOperation headSignature = currentChain.getHeadSignature();
OperationChain currentChain = q.poll();
RefChainOperation head = currentChain.getHead();
if (addChainIfTerminal(currentChain, result, chainMaxLength, context)) continue;
// otherwise try to find chain continuation
boolean updated = false;
SortedSet<SignatureAndOccurrences> candidates = referenceServiceEx.findMethodReferenceOccurrences(headSignature.getOwner1(), SignatureData.ZERO_DIM);
LightRef ref1 = headSignature.getRef1();
for (SignatureAndOccurrences candidate : candidates) {
SortedSet<MethodRefAndOccurrences> candidates = referenceServiceEx.findMethodReferenceOccurrences(head.getQualifierRawName(), SignatureData.ZERO_DIM, context);
LightRef ref = head.getLightRef();
for (MethodRefAndOccurrences candidate : candidates) {
if (candidate.getOccurrenceCount() * ChainSearchMagicConstants.FILTER_RATIO < currentChain.getChainWeight()) {
break;
}
MethodIncompleteSignature sign = candidate.getSignature();
if ((sign.isStatic() || !sign.getOwner().equals(context.getTarget().getClassQName())) &&
(!(ref1 instanceof LightRef.JavaLightMethodRef) ||
referenceServiceEx
.mayHappen(candidate.getSignature().getRef(), ref1, ChainSearchMagicConstants.METHOD_PROBABILITY_THRESHOLD))) {
MethodCall sign = candidate.getSignature();
if ((sign.isStatic() || !sign.getQualifierRawName().equals(context.getTarget().getClassQName())) &&
(!(ref instanceof LightRef.JavaLightMethodRef) ||
referenceServiceEx.mayHappen(candidate.getSignature().getLightRef(), ref, ChainSearchMagicConstants.METHOD_PROBABILITY_THRESHOLD))) {
CallChain continuation = currentChain.continuation(candidate.getSignature(), candidate.getOccurrenceCount(), context);
OperationChain
continuation = currentChain.continuationWithMethod(candidate.getSignature(), candidate.getOccurrenceCount(), context);
if (continuation != null) {
boolean stopChain =
candidate.getSignature().isStatic() || context.hasQualifier(context.resolvePsiClass(candidate.getSignature().getOwnerRef()));
candidate.getSignature().isStatic() || context.hasQualifier(context.resolvePsiClass(candidate.getSignature().getQualifierDef()));
if (stopChain) {
addChainIfNotPresent(continuation, result);
}
@@ -100,11 +95,12 @@ public class ChainSearcher {
}
}
if (ref1 instanceof LightRef.JavaLightMethodRef) {
if (ref instanceof LightRef.JavaLightMethodRef) {
LightRef.LightClassHierarchyElementDef def =
referenceServiceEx.mayCallOfTypeCast((LightRef.JavaLightMethodRef)ref1, ChainSearchMagicConstants.METHOD_PROBABILITY_THRESHOLD);
referenceServiceEx.mayCallOfTypeCast((LightRef.JavaLightMethodRef)ref, ChainSearchMagicConstants.METHOD_PROBABILITY_THRESHOLD);
if (def != null) {
CallChain continuation = currentChain.continuationWithCast(new TypeCast(def, ((MethodIncompleteSignature)headSignature).getOwnerRef(), referenceServiceEx, 0), context);
OperationChain
continuation = currentChain.continuationWithCast(new TypeCast(def, head.getQualifierDef(), referenceServiceEx), context);
if (continuation != null) {
q.addFirst(continuation);
updated = true;
@@ -126,17 +122,18 @@ public class ChainSearcher {
/**
* To reduce false-positives we add a method to result only if its qualifier can be occurred together with context variables.
*/
private static void addChainIfQualifierCanBeOccurredInContext(CallChain currentChain,
List<CallChain> result,
private static void addChainIfQualifierCanBeOccurredInContext(OperationChain currentChain,
List<OperationChain> result,
ChainCompletionContext context,
CompilerReferenceServiceEx referenceServiceEx) {
RefChainOperation signature = currentChain.getLastMethodSign();
RefChainOperation signature = currentChain.getHeadMethodCall();
// type cast + introduced qualifier: it's too complex chain
if (currentChain.hasCast()) return;
if (!context.getTarget().getClassQName().equals(((MethodIncompleteSignature)signature).getOwner())) {
if (!context.getTarget().getClassQName().equals(signature.getQualifierRawName())) {
Set<LightRef> references = context.getContextClassReferences();
boolean isRelevantQualifier = false;
for (LightRef ref: references) {
if (referenceServiceEx.mayHappen(((MethodIncompleteSignature)signature).getOwnerRef(), ref, ChainSearchMagicConstants.VAR_PROBABILITY_THRESHOLD)) {
if (referenceServiceEx.mayHappen(signature.getQualifierDef(), ref, ChainSearchMagicConstants.VAR_PROBABILITY_THRESHOLD)) {
isRelevantQualifier = true;
break;
}
@@ -148,12 +145,12 @@ public class ChainSearcher {
}
}
private static boolean addChainIfTerminal(CallChain currentChain, List<CallChain> result, int pathMaximalLength,
private static boolean addChainIfTerminal(OperationChain currentChain, List<OperationChain> result, int pathMaximalLength,
ChainCompletionContext context) {
RefChainOperation signature = currentChain.getLastMethodSign();
RefChainOperation head = currentChain.getHeadSignature();
if (((MethodIncompleteSignature)signature).isStatic() ||
context.hasQualifier(context.resolvePsiClass(head.getOwnerRef1())) ||
RefChainOperation signature = currentChain.getHeadMethodCall();
RefChainOperation head = currentChain.getHead();
if (((MethodCall)signature).isStatic() ||
context.hasQualifier(context.resolvePsiClass(head.getQualifierDef())) ||
currentChain.length() >= pathMaximalLength) {
addChainIfNotPresent(currentChain, result);
return true;
@@ -161,7 +158,7 @@ public class ChainSearcher {
return false;
}
private static void addChainIfNotPresent(CallChain newChain, List<CallChain> result) {
private static void addChainIfNotPresent(OperationChain newChain, List<OperationChain> result) {
if (result.isEmpty()) {
result.add(newChain);
return;
@@ -169,8 +166,8 @@ public class ChainSearcher {
boolean doAdd = true;
IntStack indicesToRemove = new IntStack();
for (int i = 0; i < result.size(); i++) {
CallChain chain = result.get(i);
CallChain.CompareResult r = CallChain.compare(chain, newChain);
OperationChain chain = result.get(i);
OperationChain.CompareResult r = OperationChain.compare(chain, newChain);
switch (r) {
case LEFT_CONTAINS_RIGHT:
indicesToRemove.push(i);
@@ -41,7 +41,7 @@ import java.util.stream.Collectors;
public class MethodChainLookupRangingHelper {
@NotNull
public static LookupElement toLookupElement(CallChain chain,
public static LookupElement toLookupElement(OperationChain chain,
ChainCompletionContext context) {
int unreachableParametersCount = 0;
int matchedParametersInContext = 0;
@@ -17,16 +17,16 @@ package com.intellij.compiler.chainsSearch;
import org.jetbrains.annotations.NotNull;
public class SignatureAndOccurrences implements Comparable<SignatureAndOccurrences> {
private final MethodIncompleteSignature mySignature;
public class MethodRefAndOccurrences implements Comparable<MethodRefAndOccurrences> {
private final MethodCall mySignature;
private final int myOccurrences;
public SignatureAndOccurrences(final MethodIncompleteSignature signature, final int occurrences) {
public MethodRefAndOccurrences(final MethodCall signature, final int occurrences) {
mySignature = signature;
myOccurrences = occurrences;
}
public MethodIncompleteSignature getSignature() {
public MethodCall getSignature() {
return mySignature;
}
@@ -35,7 +35,7 @@ public class SignatureAndOccurrences implements Comparable<SignatureAndOccurrenc
}
@Override
public int compareTo(@NotNull final SignatureAndOccurrences that) {
public int compareTo(@NotNull final MethodRefAndOccurrences that) {
final int sub = -getOccurrenceCount() + that.getOccurrenceCount();
if (sub != 0) {
return sub;
@@ -31,19 +31,19 @@ import java.util.Set;
import java.util.stream.Collectors;
public class CallChain {
public class OperationChain {
@NotNull
private final ChainOperation[] myReverseOperations;
private final RefChainOperation mySignature;
private final MethodIncompleteSignature myLastMethodSign;
private final RefChainOperation myHeadOperation;
private final MethodCall myHeadMethodCall;
private final int myWeight;
private final PsiClass myQualifierClass;
@Nullable
public static CallChain create(@NotNull MethodIncompleteSignature signature,
int weight,
@NotNull ChainCompletionContext context) {
PsiClass qualifier = context.resolvePsiClass(signature.getOwnerRef());
public static OperationChain create(@NotNull MethodCall signature,
int weight,
@NotNull ChainCompletionContext context) {
PsiClass qualifier = context.resolvePsiClass(signature.getQualifierDef());
if (qualifier == null || (!signature.isStatic() && InheritanceUtil.isInheritorOrSelf(context.getTarget().getTargetClass(), qualifier, true))) {
return null;
}
@@ -58,18 +58,18 @@ public class CallChain {
return null;
}
classes.add(contextClass);
return new CallChain(qualifier, new ChainOperation[] {new ChainOperation.MethodCall(methods)}, signature, signature, weight);
return new OperationChain(qualifier, new ChainOperation[] {new ChainOperation.MethodCall(methods)}, signature, signature, weight);
}
public CallChain(@NotNull PsiClass qualifierClass,
@NotNull ChainOperation[] reverseOperations,
RefChainOperation signature,
MethodIncompleteSignature lastMethodSign,
int weight) {
private OperationChain(@NotNull PsiClass qualifierClass,
@NotNull ChainOperation[] reverseOperations,
RefChainOperation signature,
MethodCall headMethodSign,
int weight) {
myQualifierClass = qualifierClass;
myReverseOperations = reverseOperations;
mySignature = signature;
myLastMethodSign = lastMethodSign;
myHeadOperation = signature;
myHeadMethodCall = headMethodSign;
myWeight = weight;
}
@@ -77,13 +77,14 @@ public class CallChain {
return Arrays.stream(myReverseOperations).anyMatch(op -> op instanceof ChainOperation.TypeCast);
}
public MethodIncompleteSignature getLastMethodSign() {
return myLastMethodSign;
@NotNull
public MethodCall getHeadMethodCall() {
return myHeadMethodCall;
}
@NotNull
public RefChainOperation getHeadSignature() {
return mySignature;
public RefChainOperation getHead() {
return myHeadOperation;
}
public int length() {
@@ -107,28 +108,30 @@ public class CallChain {
return myWeight;
}
public CallChain continuation(@NotNull MethodIncompleteSignature signature,
int weight,
@NotNull ChainCompletionContext context) {
CallChain head = create(signature, weight, context);
@Nullable
OperationChain continuationWithMethod(@NotNull MethodCall signature,
int weight,
@NotNull ChainCompletionContext context) {
OperationChain head = create(signature, weight, context);
if (head == null) return null;
ChainOperation[] newReverseOperations = new ChainOperation[length() + 1];
System.arraycopy(myReverseOperations, 0, newReverseOperations, 0, myReverseOperations.length);
newReverseOperations[length()] = head.getPath()[0];
return new CallChain(head.getQualifierClass(), newReverseOperations, head.getHeadSignature(), signature, Math.min(weight, getChainWeight()));
return new OperationChain(head.getQualifierClass(), newReverseOperations, head.getHead(), signature, Math.min(weight, getChainWeight()));
}
public CallChain continuationWithCast(@NotNull TypeCast cast,
@NotNull ChainCompletionContext context) {
PsiClass operand = context.resolvePsiClass(cast.getOperandRef());
@Nullable
OperationChain continuationWithCast(@NotNull TypeCast cast,
@NotNull ChainCompletionContext context) {
PsiClass operand = context.resolvePsiClass(cast.getLightRef());
PsiClass castType = context.resolvePsiClass(cast.getCastTypeRef());
if (operand == null || castType == null) return null;
ChainOperation[] newReverseOperations = new ChainOperation[length() + 1];
System.arraycopy(myReverseOperations, 0, newReverseOperations, 0, myReverseOperations.length);
newReverseOperations[length()] = new ChainOperation.TypeCast(operand, castType);
return new CallChain(operand, newReverseOperations, cast, myLastMethodSign, getChainWeight());
return new OperationChain(operand, newReverseOperations, cast, myHeadMethodCall, getChainWeight());
}
@Override
@@ -138,7 +141,7 @@ public class CallChain {
}
@SuppressWarnings("ConstantConditions")
public static CompareResult compare(@NotNull CallChain left, @NotNull CallChain right) {
public static CompareResult compare(@NotNull OperationChain left, @NotNull OperationChain right) {
if (left.length() == 0 || right.length() == 0) {
throw new IllegalStateException("chains can't be empty");
}
@@ -1,25 +0,0 @@
/*
* Copyright 2000-2017 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.compiler.chainsSearch;
import org.jetbrains.jps.backwardRefs.LightRef;
public interface RefChainOperation {
String getOwner1();
LightRef.LightClassHierarchyElementDef getOwnerRef1();
LightRef getRef1();
}
@@ -16,73 +16,74 @@
package com.intellij.compiler.chainsSearch
import com.intellij.compiler.backwardRefs.CompilerReferenceServiceEx
import com.intellij.compiler.chainsSearch.context.ChainCompletionContext
import com.intellij.compiler.chainsSearch.context.ChainSearchTarget
import com.intellij.openapi.project.Project
import com.intellij.psi.*
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.PsiArrayType
import com.intellij.psi.PsiClassType
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiModifier
import com.intellij.psi.util.PsiUtil
import org.jetbrains.jps.backwardRefs.LightRef
import org.jetbrains.jps.backwardRefs.SignatureData
import java.util.function.Predicate
class MethodIncompleteSignature(val ref: LightRef.JavaLightMethodRef,
private val signatureData: SignatureData,
private val refService: CompilerReferenceServiceEx): RefChainOperation {
override fun getOwnerRef1(): LightRef.LightClassHierarchyElementDef {
return ownerRef
sealed class RefChainOperation {
abstract val qualifierRawName: String
abstract val qualifierDef: LightRef.LightClassHierarchyElementDef
abstract val lightRef: LightRef
}
class TypeCast(override val lightRef: LightRef.LightClassHierarchyElementDef,
val castTypeRef: LightRef.LightClassHierarchyElementDef,
refService: CompilerReferenceServiceEx): RefChainOperation() {
override val qualifierRawName
get() = operandName.value
override val qualifierDef
get() = lightRef
private val operandName = lazy(LazyThreadSafetyMode.NONE) {
refService.getName(lightRef.name)
}
}
override fun getOwner1(): String {
return owner
}
class MethodCall(override val lightRef: LightRef.JavaLightMethodRef,
private val signatureData: SignatureData,
private val context: ChainCompletionContext): RefChainOperation() {
override fun getRef1(): LightRef {
return ref
}
companion object {
private companion object {
val CONSTRUCTOR_METHOD_NAME = "<init>"
}
val name: String by lazy(LazyThreadSafetyMode.NONE) {
refService.getName(ref.name)
override val qualifierRawName: String
get() = owner.value
override val qualifierDef: LightRef.LightClassHierarchyElementDef
get() = lightRef.owner
private val name = lazy(LazyThreadSafetyMode.NONE) {
context.refService.getName(lightRef.name)
}
val ownerRef = ref.owner
val owner: String by lazy(LazyThreadSafetyMode.NONE) {
refService.getName(ref.owner.name)
private val owner = lazy(LazyThreadSafetyMode.NONE) {
context.refService.getName(lightRef.owner.name)
}
private val rawReturnType: String by lazy(LazyThreadSafetyMode.NONE) {
refService.getName(signatureData.rawReturnType)
private val rawReturnType = lazy(LazyThreadSafetyMode.NONE) {
context.refService.getName(signatureData.rawReturnType)
}
private val parameterCount: Int
get() = ref.parameterCount
val isStatic: Boolean
get() = signatureData.isStatic
//TODO remove
fun resolveQualifier(project: Project,
resolveScope: GlobalSearchScope,
accessValidator: Predicate<PsiMember>): PsiClass? {
val clazz = JavaPsiFacade.getInstance(project).findClass(owner, resolveScope)
return if (clazz != null && accessValidator.test(clazz)) clazz else null
}
fun resolve(project: Project,
resolveScope: GlobalSearchScope,
accessValidator: Predicate<PsiMember>): Array<PsiMethod> {
if (CONSTRUCTOR_METHOD_NAME == name) {
fun resolve(): Array<PsiMethod> {
if (CONSTRUCTOR_METHOD_NAME == name.value) {
return PsiMethod.EMPTY_ARRAY
}
val aClass = resolveQualifier(project, resolveScope, accessValidator) ?: return PsiMethod.EMPTY_ARRAY
return aClass.findMethodsByName(name, true)
val aClass = context.resolvePsiClass(qualifierDef) ?: return PsiMethod.EMPTY_ARRAY
return aClass.findMethodsByName(name.value, true)
.filter { it.hasModifierProperty(PsiModifier.STATIC) == isStatic }
.filter { !it.isDeprecated }
.filter { accessValidator.test(it) }
.filter { context.accessValidator().test(it) }
.filter {
val returnType = it.returnType
when (signatureData.iteratorKind) {
@@ -90,7 +91,7 @@ class MethodIncompleteSignature(val ref: LightRef.JavaLightMethodRef,
when (returnType) {
is PsiArrayType -> {
val componentType = returnType.componentType
componentType is PsiClassType && componentType.resolve()?.qualifiedName == rawReturnType
componentType is PsiClassType && componentType.resolve()?.qualifiedName == rawReturnType.value
}
else -> false
}
@@ -98,11 +99,11 @@ class MethodIncompleteSignature(val ref: LightRef.JavaLightMethodRef,
SignatureData.ITERATOR_ONE_DIM -> {
val iteratorKind = ChainSearchTarget.getIteratorKind(PsiUtil.resolveClassInClassTypeOnly(returnType))
when {
iteratorKind != null -> PsiUtil.resolveClassInClassTypeOnly(PsiUtil.substituteTypeParameter(returnType, iteratorKind, 0, false))?.qualifiedName == rawReturnType
iteratorKind != null -> PsiUtil.resolveClassInClassTypeOnly(PsiUtil.substituteTypeParameter(returnType, iteratorKind, 0, false))?.qualifiedName == rawReturnType.value
else -> false
}
}
SignatureData.ZERO_DIM -> returnType is PsiClassType && returnType.resolve()?.qualifiedName == rawReturnType
SignatureData.ZERO_DIM -> returnType is PsiClassType && returnType.resolve()?.qualifiedName == rawReturnType.value
else -> throw IllegalStateException("kind is unsupported ${signatureData.iteratorKind}")
}
}
@@ -114,23 +115,23 @@ class MethodIncompleteSignature(val ref: LightRef.JavaLightMethodRef,
if (this === other) return true
if (other?.javaClass != javaClass) return false
other as MethodIncompleteSignature
other as MethodCall
if (ref.owner != other.ref.owner) return false
if (ref.name != other.ref.name) return false
if (lightRef.owner != other.lightRef.owner) return false
if (lightRef.name != other.lightRef.name) return false
if (signatureData != other.signatureData) return false
return true
}
override fun hashCode(): Int {
var result = ref.owner.hashCode()
result = 31 * result + ref.name.hashCode()
var result = lightRef.owner.hashCode()
result = 31 * result + lightRef.name.hashCode()
result = 31 * result + signatureData.hashCode()
return result
}
override fun toString(): String {
return owner + (if (isStatic) "" else "#") + name + "(" + parameterCount + ")"
return qualifierRawName + (if (isStatic) "." else "#") + name + "(" + lightRef.parameterCount + ")"
}
}
}
@@ -21,39 +21,39 @@ import java.util.*;
public class SearchInitializer {
private final ChainCompletionContext myContext;
private final LinkedList<CallChain> myQueue;
private final LinkedHashMap<MethodIncompleteSignature, CallChain> myChains;
private final LinkedList<OperationChain> myQueue;
private final LinkedHashMap<MethodCall, OperationChain> myChains;
public SearchInitializer(SortedSet<SignatureAndOccurrences> indexValues,
public SearchInitializer(SortedSet<MethodRefAndOccurrences> indexValues,
ChainCompletionContext context) {
myContext = context;
int size = indexValues.size();
List<CallChain> chains = new ArrayList<>(size);
List<OperationChain> chains = new ArrayList<>(size);
populateFrequentlyUsedMethod(indexValues, chains);
myQueue = new LinkedList<>();
myChains = new LinkedHashMap<>(chains.size());
for (CallChain chain : chains) {
MethodIncompleteSignature signature = (MethodIncompleteSignature)chain.getHeadSignature();
for (OperationChain chain : chains) {
MethodCall signature = (MethodCall)chain.getHead();
myQueue.add(chain);
myChains.put(signature, chain);
}
}
public LinkedList<CallChain> getChainQueue() {
public LinkedList<OperationChain> getChainQueue() {
return myQueue;
}
public LinkedHashMap<MethodIncompleteSignature, CallChain> getChains() {
public LinkedHashMap<MethodCall, OperationChain> getChains() {
return myChains;
}
private void populateFrequentlyUsedMethod(SortedSet<SignatureAndOccurrences> signatures,
List<CallChain> chains) {
private void populateFrequentlyUsedMethod(SortedSet<MethodRefAndOccurrences> signatures,
List<OperationChain> chains) {
int bestOccurrences = -1;
for (SignatureAndOccurrences indexValue : signatures) {
CallChain callChain = CallChain.create(indexValue.getSignature(), indexValue.getOccurrenceCount(), myContext);
if (callChain != null) {
chains.add(callChain);
for (MethodRefAndOccurrences indexValue : signatures) {
OperationChain operationChain = OperationChain.create(indexValue.getSignature(), indexValue.getOccurrenceCount(), myContext);
if (operationChain != null) {
chains.add(operationChain);
int occurrences = indexValue.getOccurrenceCount();
if (bestOccurrences == -1) {
bestOccurrences = occurrences;
@@ -1,44 +0,0 @@
/*
* Copyright 2000-2017 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.compiler.chainsSearch
import com.intellij.compiler.backwardRefs.CompilerReferenceServiceEx
import org.jetbrains.jps.backwardRefs.LightRef
class TypeCast(val operandRef: LightRef.LightClassHierarchyElementDef,
val castTypeRef: LightRef.LightClassHierarchyElementDef,
refService: CompilerReferenceServiceEx,
val occurrences: Int): RefChainOperation {
override fun getOwnerRef1(): LightRef.LightClassHierarchyElementDef {
return operandRef
}
override fun getOwner1(): String {
return operandName
}
override fun getRef1(): LightRef {
return operandRef
}
val operandName: String by lazy(LazyThreadSafetyMode.NONE) {
refService.getName(operandRef.name)
}
val castTypeName: String by lazy(LazyThreadSafetyMode.NONE) {
refService.getName(castTypeRef.name)
}
}
@@ -22,7 +22,7 @@ import com.intellij.compiler.backwardRefs.CompilerReferenceServiceEx;
import com.intellij.compiler.backwardRefs.ReferenceIndexUnavailableException;
import com.intellij.compiler.chainsSearch.ChainSearchMagicConstants;
import com.intellij.compiler.chainsSearch.ChainSearcher;
import com.intellij.compiler.chainsSearch.CallChain;
import com.intellij.compiler.chainsSearch.OperationChain;
import com.intellij.compiler.chainsSearch.MethodChainLookupRangingHelper;
import com.intellij.compiler.chainsSearch.context.ChainCompletionContext;
import com.intellij.compiler.chainsSearch.context.ChainSearchTarget;
@@ -92,13 +92,13 @@ public class MethodChainCompletionContributor extends CompletionContributor {
private static List<LookupElement> searchForLookups(ChainCompletionContext context) {
CompilerReferenceServiceEx methodsUsageIndexReader = (CompilerReferenceServiceEx)CompilerReferenceService.getInstance(context.getProject());
ChainSearchTarget target = context.getTarget();
List<CallChain> searchResult =
List<OperationChain> searchResult =
ChainSearcher.search(ChainSearchMagicConstants.MAX_CHAIN_SIZE,
target,
ChainSearchMagicConstants.MAX_SEARCH_RESULT_SIZE,
context,
methodsUsageIndexReader);
int maxWeight = searchResult.stream().mapToInt(CallChain::getChainWeight).max().orElse(0);
int maxWeight = searchResult.stream().mapToInt(OperationChain::getChainWeight).max().orElse(0);
return searchResult
.stream()
@@ -17,7 +17,7 @@ package com.intellij.compiler.chainsSearch.context;
import com.intellij.compiler.CompilerReferenceService;
import com.intellij.compiler.backwardRefs.CompilerReferenceServiceEx;
import com.intellij.compiler.chainsSearch.MethodIncompleteSignature;
import com.intellij.compiler.chainsSearch.MethodCall;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.NotNullLazyValue;
@@ -68,7 +68,7 @@ public class ChainCompletionContext {
@NotNull
private final TIntObjectHashMap<PsiClass> myQualifierClassResolver;
@NotNull
private final Map<MethodIncompleteSignature, PsiMethod[]> myResolver;
private final Map<MethodCall, PsiMethod[]> myResolver;
@NotNull
private final CompilerReferenceServiceEx myRefServiceEx;
@@ -98,7 +98,7 @@ public class ChainCompletionContext {
myProject = context.getProject();
myResolveHelper = PsiResolveHelper.SERVICE.getInstance(myProject);
myQualifierClassResolver = new TIntObjectHashMap<>();
myResolver = FactoryMap.createMap(sign -> sign.resolve(myProject, myResolveScope, accessValidator()));
myResolver = FactoryMap.createMap(sign -> sign.resolve());
myRefServiceEx = (CompilerReferenceServiceEx)CompilerReferenceService.getInstance(myProject);
}
@@ -119,6 +119,11 @@ public class ChainCompletionContext {
return false;
}
@NotNull
public CompilerReferenceServiceEx getRefService() {
return myRefServiceEx;
}
@NotNull
public PsiElement getContextPsi() {
return myContext;
@@ -182,11 +187,11 @@ public class ChainCompletionContext {
}
@NotNull
public PsiMethod[] resolve(MethodIncompleteSignature sign) {
public PsiMethod[] resolve(MethodCall sign) {
return myResolver.get(sign);
}
private Predicate<PsiMember> accessValidator() {
public Predicate<PsiMember> accessValidator() {
return m -> myResolveHelper.isAccessible(m, myContext, null);
}