use of com.intellij.dupLocator.util.PsiFragment in project intellij-community by JetBrains.
the class TreeHasherBase method computeHash.
private TreeHashResult computeHash(PsiElement element, PsiFragment parent, EquivalenceDescriptor descriptor, NodeSpecificHasher hasher) {
final NodeSpecificHasherBase ssrHasher = (NodeSpecificHasherBase) hasher;
final PsiElement element2 = DuplocatorUtil.skipNodeIfNeccessary(element, descriptor, ssrHasher.getNodeFilter());
final boolean canSkip = element2 != element;
final PsiFragment fragment = buildFragment(hasher, element, 0);
if (parent != null) {
fragment.setParent(parent);
}
int hash = canSkip ? 0 : hasher.getNodeHash(element);
int cost = hasher.getNodeCost(element);
for (SingleChildDescriptor childDescriptor : descriptor.getSingleChildDescriptors()) {
final Couple<Integer> childHashResult = computeHash(childDescriptor, fragment, hasher);
hash = hash * 31 + childHashResult.first;
cost += childHashResult.second;
}
for (MultiChildDescriptor childDescriptor : descriptor.getMultiChildDescriptors()) {
final Couple<Integer> childHashResult = computeHash(childDescriptor, fragment, hasher);
hash = hash * 31 + childHashResult.first;
cost += childHashResult.second;
}
for (Object constant : descriptor.getConstants()) {
final int constantHash = constant != null ? constant.hashCode() : 0;
hash = hash * 31 + constantHash;
}
for (PsiElement[] codeBlock : descriptor.getCodeBlocks()) {
final List<PsiElement> filteredBlock = filter(codeBlock, ssrHasher);
final TreeHashResult childHashResult = hashCodeBlock(filteredBlock, fragment, hasher);
hash = hash * 31 + childHashResult.getHash();
cost += childHashResult.getCost();
}
if (myCallback != null) {
myCallback.add(hash, cost, fragment);
}
return new TreeHashResult(hash, cost, fragment);
}
use of com.intellij.dupLocator.util.PsiFragment in project intellij-community by JetBrains.
the class TreeHashingUtils method hashCodeBlockForIndexing.
protected static TreeHashResult hashCodeBlockForIndexing(AbstractTreeHasher treeHasher, FragmentsCollector callBack, List<? extends PsiElement> statements, PsiFragment upper, NodeSpecificHasher hasher) {
final int statementsSize = statements.size();
if (statementsSize > 0) {
final PsiFragment fragment = treeHasher.buildFragment(hasher, statements, 0, statementsSize - 1);
fragment.setParent(upper);
int cost = 0;
int hash = 0;
for (PsiElement statement : statements) {
final TreeHashResult res = treeHasher.hash(statement, null, hasher);
hash = hash * 31 + res.getHash();
cost += res.getCost();
}
TreeHashResult result = new TreeHashResult(hash, cost, treeHasher.buildFragment(hasher, statements, 0, statementsSize - 1));
if (callBack != null && statementsSize > 1)
callBack.add(hash, cost, fragment);
return result;
}
return new TreeHashResult(1, 0, treeHasher.buildFragment(hasher, statements, 0, statementsSize - 1));
}
use of com.intellij.dupLocator.util.PsiFragment in project intellij-community by JetBrains.
the class TreeHashingUtils method computeElementHashForIndexing.
static TreeHashResult computeElementHashForIndexing(AbstractTreeHasher base, FragmentsCollector callBack, PsiElement root, PsiFragment upper, NodeSpecificHasher hasher) {
final List<PsiElement> children = hasher.getNodeChildren(root);
final PsiFragment fragment = base.buildFragment(hasher, root, base.getCost(root));
if (upper != null) {
fragment.setParent(upper);
}
final int size = children.size();
if (size == 0 && !(root instanceof LeafElement)) {
// contains only whitespaces and other unmeaning children
return new TreeHashResult(0, hasher.getNodeCost(root), fragment);
}
final int discardCost = base.getDiscardCost(root);
int c = hasher.getNodeCost(root);
int h = hasher.getNodeHash(root);
for (int i = 0; i < size; i++) {
PsiElement child = children.get(i);
final TreeHashResult res = base.hash(child, fragment, hasher);
int childCost = res.getCost();
c += childCost;
if (childCost > discardCost || !base.ignoreChildHash(child)) {
h += res.getHash();
}
}
if (base.shouldAnonymize(root, hasher)) {
h = 0;
}
if (callBack != null) {
callBack.add(h, c, fragment);
}
return new TreeHashResult(h, c, fragment);
}
use of com.intellij.dupLocator.util.PsiFragment in project intellij-community by JetBrains.
the class AbstractTreeHasher method hashCodeBlock.
/**
* Creates PsiFragments using given statements with their hashes
*/
protected TreeHashResult hashCodeBlock(final List<? extends PsiElement> statements, final PsiFragment upper, final NodeSpecificHasher hasher, boolean forceHash) {
final int statementsSize = statements.size();
if (statementsSize == 1) {
return hash(statements.get(0), upper, hasher);
}
if (statementsSize > 0) {
// Here we compute all the possible code fragments using statements
if (statementsSize < 20 || forceHash) {
//todo should be configurable
final PsiFragment[] frags = new PsiFragment[statementsSize];
final PsiFragment fragment = buildFragment(hasher, statements, 0, statementsSize - 1);
fragment.setParent(upper);
// Fill all the statements costs and hashes
final int[] hashes = new int[statementsSize];
final int[] costs = new int[statementsSize];
for (int i = 0; i < statementsSize; i++) {
final TreeHashResult res = hash(statements.get(i), null, hasher);
hashes[i] = res.getHash();
costs[i] = res.getCost();
frags[i] = res.getFragment();
}
if (myCallBack != null) {
//parent(end) = [beg, end]
final PsiFragment[] parents = new PsiFragment[statementsSize];
for (int beg = 0; beg < statementsSize; beg++) {
int hash = 0;
int cost = 0;
for (int end = beg; end < statementsSize && end - beg < 20; end++) {
hash = 31 * hash + hashes[end];
cost += costs[end];
final PsiFragment curr = beg == end ? frags[beg] : beg == 0 && end == statementsSize - 1 ? fragment : buildFragment(hasher, statements, beg, end);
if (beg > 0) {
//[beg, end].setParent([beg - 1, end])
curr.setParent(parents[end]);
}
parents[end] = curr;
if (end > beg) {
//[beg, end - 1].setParent([beg, end])
parents[end - 1].setParent(curr);
}
myCallBack.add(hash, cost, curr);
}
}
}
return new TreeHashResult(vector(hashes, 31), vector(costs), fragment);
}
}
return new TreeHashResult(1, 0, buildFragment(hasher, statements, 0, statementsSize - 1));
}
use of com.intellij.dupLocator.util.PsiFragment in project intellij-community by JetBrains.
the class DuplocatorHashCallback method forceAdd.
private void forceAdd(int hash, int cost, PsiFragment frag) {
if (frag == null) {
//fake fragment
myDuplicates.put(hash, new ArrayList<>());
return;
}
frag.setCost(cost);
List<List<PsiFragment>> fragments = myDuplicates.get(hash);
if (fragments == null) {
if (!myReadOnly) {
//do not add new hashcodes
List<List<PsiFragment>> list = new ArrayList<>();
List<PsiFragment> listf = new ArrayList<>();
listf.add(frag);
list.add(listf);
myDuplicates.put(hash, list);
}
return;
}
boolean found = false;
final PsiElement[] elements = frag.getElements();
int discardCost = 0;
if (myDiscardCost >= 0) {
discardCost = myDiscardCost;
} else {
final DuplocatorState state = DuplocatorUtil.getDuplocatorState(frag);
if (state != null) {
discardCost = state.getDiscardCost();
}
}
for (Iterator<List<PsiFragment>> i = fragments.iterator(); i.hasNext() && !found; ) {
List<PsiFragment> fi = i.next();
PsiFragment aFrag = fi.get(0);
if (aFrag.isEqual(elements, discardCost)) {
boolean skipNew = false;
for (Iterator<PsiFragment> frags = fi.iterator(); frags.hasNext() && !skipNew; ) {
final PsiFragment old = frags.next();
if (frag.intersectsWith(old)) {
if (old.getCost() < frag.getCost() || frag.contains(old)) {
frags.remove();
} else {
skipNew = true;
}
}
}
if (!skipNew)
fi.add(frag);
found = true;
}
}
if (!found) {
List<PsiFragment> newFrags = new ArrayList<>();
newFrags.add(frag);
fragments.add(newFrags);
}
}
Aggregations