method chain completion: simplify old code

This commit is contained in:
Dmitry Batkovich
2017-05-16 21:20:53 +03:00
parent 2576d32217
commit eaeffca0b8
5 changed files with 26 additions and 101 deletions
@@ -59,65 +59,41 @@ public class ChainSearcher {
int pathMaximalLength,
int maxResultSize,
ChainCompletionContext context) {
Map<MethodIncompleteSignature, MethodChain> knownDistance = initializer.getChains();
LinkedList<MethodChain> q = initializer.getChainQueue();
List<MethodChain> result = new ArrayList<>();
while (!q.isEmpty()) {
ProgressManager.checkCanceled();
MethodChain currentVertex = q.poll();
MethodIncompleteSignature headSignature = currentVertex.getHeadSignature();
MethodChain currentVertexMethodChain = knownDistance.get(headSignature);
if (currentVertex.getChainWeight() != currentVertexMethodChain.getChainWeight()) {
continue;
}
MethodChain currentChain = q.poll();
MethodIncompleteSignature headSignature = currentChain.getHeadSignature();
// interrupt a chain if a head method is static or has suitable qualifier
if (headSignature.isStatic() || context.hasQualifier(context.resolveQualifierClass(headSignature))) {
addChainIfNotPresent(currentVertex, result);
// interrupt a chain if it can be terminal
if (headSignature.isStatic() ||
context.hasQualifier(context.resolveQualifierClass(headSignature)) ||
currentChain.length() >= pathMaximalLength) {
addChainIfNotPresent(currentChain, result);
continue;
}
// otherwise try to find chain continuation
boolean updated = false;
SortedSet<SignatureAndOccurrences> candidates = referenceServiceEx.findMethodReferenceOccurrences(headSignature.getOwner(), SignatureData.ZERO_DIM);
MaxSizeTreeSet<SignatureAndOccurrences> chosenCandidates = new MaxSizeTreeSet<>(maxResultSize);
for (SignatureAndOccurrences candidate : candidates) {
if (candidate.getOccurrenceCount() * ChainSearchMagicConstants.FILTER_RATIO < currentVertex.getChainWeight()) {
if (candidate.getOccurrenceCount() * ChainSearchMagicConstants.FILTER_RATIO < currentChain.getChainWeight()) {
break;
}
MethodIncompleteSignature sign = candidate.getSignature();
if (sign.isStatic() || !sign.getOwner().equals(context.getTarget().getClassQName())) {
int vertexDistance = Math.min(currentVertex.getChainWeight(), candidate.getOccurrenceCount());
MethodChain knownVertexMethodChain = knownDistance.get(sign);
if ((knownVertexMethodChain == null || knownVertexMethodChain.getChainWeight() < vertexDistance)) {
if ((chosenCandidates.isEmpty() || chosenCandidates.last().getOccurrenceCount() < vertexDistance) && currentVertexMethodChain.size() < pathMaximalLength - 1) {
MethodChain newBestMethodChain = currentVertexMethodChain.continuation(candidate.getSignature(), vertexDistance, context);
if (newBestMethodChain != null) {
chosenCandidates.add(new SignatureAndOccurrences(candidate.getSignature(), vertexDistance));
knownDistance.put(sign, newBestMethodChain);
}
if ((sign.isStatic() || !sign.getOwner().equals(context.getTarget().getClassQName())) &&
referenceServiceEx.mayHappen(candidate.getSignature().getRef(), headSignature.getRef(), ChainSearchMagicConstants.PROBABILITY_THRESHOLD)) {
MethodChain continuation = currentChain.continuation(candidate.getSignature(), candidate.getOccurrenceCount(), context);
if (continuation != null) {
boolean stopChain = candidate.getSignature().isStatic() || context.hasQualifier(context.resolveQualifierClass(candidate.getSignature()));
if (stopChain) {
addChainIfNotPresent(continuation, result);
}
}
else {
break;
}
}
}
boolean updated = false;
if (!chosenCandidates.isEmpty()) {
for (SignatureAndOccurrences candidate : chosenCandidates) {
if (referenceServiceEx.mayHappen(candidate.getSignature().getRef(), headSignature.getRef(), ChainSearchMagicConstants.PROBABILITY_THRESHOLD)) {
MethodChain continuation = currentVertex.continuation(candidate.getSignature(), candidate.getOccurrenceCount(), context);
if (continuation != null) {
boolean stopChain = candidate.getSignature().isStatic() || context.hasQualifier(context.resolveQualifierClass(candidate.getSignature()));
if (stopChain) {
addChainIfNotPresent(continuation, result);
}
else {
q.addFirst(continuation);
}
else {
q.addFirst(continuation);
}
updated = true;
}
@@ -126,7 +102,7 @@ public class ChainSearcher {
// continuation is not found -> add this chain as result
if (!updated && !context.getTarget().getClassQName().equals(headSignature.getOwner())) {
addChainIfNotPresent(currentVertex, result);
addChainIfNotPresent(currentChain, result);
}
if (result.size() > maxResultSize) {
@@ -1,46 +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 java.util.Comparator;
import java.util.TreeSet;
/**
* @author Dmitry Batkovich
*/
public class MaxSizeTreeSet<E extends Comparable<E>> extends TreeSet<E> {
private final int myMaxSize;
public MaxSizeTreeSet(int maxSize) {
myMaxSize = maxSize;
}
public boolean add(final E e) {
if (size() == myMaxSize) {
//noinspection ConstantConditions
final Comparator<? super E> comparator = comparator();
if ((comparator == null ? e.compareTo(last()) : comparator.compare(e, last())) < 0) {
final boolean isAdded = super.add(e);
if (isAdded) {
pollLast();
return true;
}
}
return false;
}
return super.add(e);
}
}
@@ -72,7 +72,7 @@ public class MethodChain {
return mySignature;
}
public int size() {
public int length() {
return myRevertedPath.size();
}
@@ -80,11 +80,6 @@ public class MethodChain {
return myQualifierClass;
}
@NotNull
public List<PsiMethod[]> getRevertedPath() {
return myRevertedPath;
}
@NotNull
public PsiMethod[] getFirst() {
return myRevertedPath.get(0);
@@ -118,10 +113,10 @@ public class MethodChain {
@SuppressWarnings("ConstantConditions")
public static CompareResult compare(@NotNull MethodChain left, @NotNull MethodChain right) {
if (left.size() == 0) {
if (left.length() == 0) {
return CompareResult.RIGHT_CONTAINS_LEFT;
}
if (right.size() == 0) {
if (right.length() == 0) {
return CompareResult.LEFT_CONTAINS_RIGHT;
}
Iterator<PsiMethod[]> leftIterator = left.myRevertedPath.iterator();
@@ -41,8 +41,8 @@ public class MethodChainLookupRangingHelper {
@Nullable
public static LookupElement chainToWeightableLookupElement(MethodChain chain,
ChainCompletionContext context) {
int chainSize = chain.size();
assert chainSize != 0;
int chainLength = chain.length();
assert chainLength != 0;
int lastMethodWeight = chain.getChainWeight();
int unreachableParametersCount = 0;
int notMatchedStringVars = 0;
@@ -93,7 +93,7 @@ public class MethodChainLookupRangingHelper {
}
ChainRelevance relevance =
new ChainRelevance(chainSize,
new ChainRelevance(chainLength,
lastMethodWeight,
unreachableParametersCount,
notMatchedStringVars,
@@ -95,7 +95,7 @@ public class MethodChainsCompletionTest extends AbstractCompilerAwareTest {
}
public void testMethodsWithParametersInContext() {
assertAdvisorLookupElementEquals("getInstance().findFile().findElementAt", 0, 5, 3, 0, assertOneElement(doCompletion()));
assertAdvisorLookupElementEquals("getInstance().findFile().findElementAt", 0, 5, 3, 0, doCompletion().get(0));
}
public void testChainsWithIndependentCallings() {