mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
type casts in relevant method chain completion: various renames
This commit is contained in:
+5
-5
@@ -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);
|
||||
}
|
||||
|
||||
+5
-3
@@ -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
|
||||
|
||||
+10
-8
@@ -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);
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+5
-5
@@ -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;
|
||||
+32
-29
@@ -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();
|
||||
}
|
||||
+54
-53
@@ -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)
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -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()
|
||||
|
||||
+10
-5
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user