Search in sources :

Example 6 with PsiFragment

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);
}
Also used : PsiFragment(com.intellij.dupLocator.util.PsiFragment) MultiChildDescriptor(com.intellij.dupLocator.equivalence.MultiChildDescriptor) SingleChildDescriptor(com.intellij.dupLocator.equivalence.SingleChildDescriptor) PsiElement(com.intellij.psi.PsiElement)

Example 7 with PsiFragment

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));
}
Also used : PsiFragment(com.intellij.dupLocator.util.PsiFragment) PsiElement(com.intellij.psi.PsiElement)

Example 8 with PsiFragment

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);
}
Also used : PsiFragment(com.intellij.dupLocator.util.PsiFragment) PsiElement(com.intellij.psi.PsiElement) LeafElement(com.intellij.psi.impl.source.tree.LeafElement)

Example 9 with PsiFragment

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));
}
Also used : PsiFragment(com.intellij.dupLocator.util.PsiFragment)

Example 10 with PsiFragment

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);
    }
}
Also used : PsiFragment(com.intellij.dupLocator.util.PsiFragment) PsiElement(com.intellij.psi.PsiElement)

Aggregations

PsiFragment (com.intellij.dupLocator.util.PsiFragment)11 PsiElement (com.intellij.psi.PsiElement)7 LeafElement (com.intellij.psi.impl.source.tree.LeafElement)3 VirtualFile (com.intellij.openapi.vfs.VirtualFile)2 PsiFile (com.intellij.psi.PsiFile)2 TIntObjectHashMap (gnu.trove.TIntObjectHashMap)2 DuplicatesProfile (com.intellij.dupLocator.DuplicatesProfile)1 DuplocatorState (com.intellij.dupLocator.DuplocatorState)1 LightDuplicateProfile (com.intellij.dupLocator.LightDuplicateProfile)1 MultiChildDescriptor (com.intellij.dupLocator.equivalence.MultiChildDescriptor)1 SingleChildDescriptor (com.intellij.dupLocator.equivalence.SingleChildDescriptor)1 FragmentsCollector (com.intellij.dupLocator.treeHash.FragmentsCollector)1 FileASTNode (com.intellij.lang.FileASTNode)1 LighterAST (com.intellij.lang.LighterAST)1 LighterASTNode (com.intellij.lang.LighterASTNode)1 TreeBackedLighterAST (com.intellij.lang.TreeBackedLighterAST)1 PathMacroManager (com.intellij.openapi.components.PathMacroManager)1 Document (com.intellij.openapi.editor.Document)1 Project (com.intellij.openapi.project.Project)1 Ref (com.intellij.openapi.util.Ref)1