mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
methods chains completion on one index
This commit is contained in:
@@ -1,20 +0,0 @@
|
||||
package com.intellij.codeInsight.completion.methodChains;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public final class Constants {
|
||||
|
||||
private Constants() {
|
||||
}
|
||||
|
||||
/**
|
||||
* magic numbers
|
||||
*/
|
||||
public static final int SINGLETON_MAGIC_RATIO = 100;
|
||||
|
||||
public static final int SINGLETON_MAGIC_RATIO2 = 5;
|
||||
|
||||
public static final int CHAIN_SEARCH_MAGIC_RATIO = 12;
|
||||
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.impl;
|
||||
|
||||
import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
|
||||
import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
|
||||
import org.jetbrains.asm4.ClassReader;
|
||||
import org.jetbrains.asm4.ClassVisitor;
|
||||
import org.jetbrains.asm4.MethodVisitor;
|
||||
import org.jetbrains.asm4.Opcodes;
|
||||
import org.jetbrains.asm4.tree.ClassNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class ClassFileData {
|
||||
private final List<MethodData> myMethodDatas;
|
||||
|
||||
public ClassFileData(final ClassNode classNode) {
|
||||
this(classNode, true);
|
||||
}
|
||||
|
||||
public ClassFileData(final ClassNode classNode, final boolean checkForPrimitiveReturn) {
|
||||
myMethodDatas = new ArrayList<MethodData>();
|
||||
classNode.accept(new ClassVisitor(Opcodes.ASM4) {
|
||||
@Override
|
||||
public MethodVisitor visitMethod(final int access,
|
||||
final String name,
|
||||
final String desc,
|
||||
final String signature,
|
||||
final String[] exceptions) {
|
||||
final MethodDataAccumulator methodDataAccumulator = new MethodDataAccumulator(checkForPrimitiveReturn);
|
||||
myMethodDatas.add(methodDataAccumulator.getMethodData());
|
||||
return methodDataAccumulator;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public List<MethodData> getMethodDatas() {
|
||||
return myMethodDatas;
|
||||
}
|
||||
|
||||
public static class MethodData {
|
||||
private final List<MethodInsnSignature> myMethodInsnSignatures = new ArrayList<MethodInsnSignature>();
|
||||
|
||||
private void addSign(final MethodInsnSignature signature) {
|
||||
myMethodInsnSignatures.add(signature);
|
||||
}
|
||||
|
||||
public List<MethodInsnSignature> getMethodInsnSignatures() {
|
||||
return myMethodInsnSignatures;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MethodDataAccumulator extends MethodVisitor {
|
||||
private final MethodData myMethodData = new MethodData();
|
||||
private final boolean myCheckForPrimitiveReturn;
|
||||
|
||||
public MethodDataAccumulator(final boolean checkForPrimitiveReturn) {
|
||||
super(Opcodes.ASM4);
|
||||
myCheckForPrimitiveReturn = checkForPrimitiveReturn;
|
||||
}
|
||||
|
||||
private MethodData getMethodData() {
|
||||
return myMethodData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
|
||||
if (MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME.equals(name)) {
|
||||
return;
|
||||
}
|
||||
final String ownerClassName = AsmUtil.getQualifiedClassName(owner);
|
||||
if (ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(ownerClassName)) {
|
||||
return;
|
||||
}
|
||||
if (myCheckForPrimitiveReturn) {
|
||||
final String returnType = AsmUtil.getReturnType(desc);
|
||||
if (ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(returnType)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
myMethodData.addSign(new MethodInsnSignature(opcode, owner, name, desc));
|
||||
}
|
||||
}
|
||||
|
||||
public static class MethodInsnSignature {
|
||||
private final int myOpcode;
|
||||
private final String myOwner;
|
||||
private final String myName;
|
||||
private final String myDesc;
|
||||
|
||||
private MethodInsnSignature(final int opcode, final String owner, final String name, final String desc) {
|
||||
myOpcode = opcode;
|
||||
myOwner = owner;
|
||||
myName = name;
|
||||
myDesc = desc;
|
||||
}
|
||||
|
||||
public int getOpcode() {
|
||||
return myOpcode;
|
||||
}
|
||||
|
||||
public String getOwner() {
|
||||
return myOwner;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return myDesc;
|
||||
}
|
||||
}
|
||||
}
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.impl;
|
||||
|
||||
import com.google.common.collect.HashMultiset;
|
||||
import com.google.common.collect.Multiset;
|
||||
import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.indexing.StorageException;
|
||||
import com.intellij.util.indexing.ValueContainer;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public abstract class CompilerOutputBaseGramsIndex<K> extends CompilerOutputBaseIndex<K, Multiset<MethodIncompleteSignature>> {
|
||||
|
||||
protected CompilerOutputBaseGramsIndex(final KeyDescriptor<K> keyDescriptor, final Project project) {
|
||||
super(keyDescriptor, new GuavaHashMultiSetExternalizer<MethodIncompleteSignature>(MethodIncompleteSignature.createKeyDescriptor()), project);
|
||||
}
|
||||
|
||||
public TreeSet<UsageIndexValue> getValues(final K key) {
|
||||
try {
|
||||
final ValueContainer<Multiset<MethodIncompleteSignature>> valueContainer = myIndex.getData(key);
|
||||
final Multiset<MethodIncompleteSignature> rawValues = HashMultiset.create();
|
||||
valueContainer.forEach(new ValueContainer.ContainerAction<Multiset<MethodIncompleteSignature>>() {
|
||||
@Override
|
||||
public boolean perform(final int id, final Multiset<MethodIncompleteSignature> values) {
|
||||
for (final Multiset.Entry<MethodIncompleteSignature> entry : values.entrySet()) {
|
||||
rawValues.add(entry.getElement(), entry.getCount());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return rawValuesToValues(rawValues);
|
||||
} catch (StorageException e) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private static TreeSet<UsageIndexValue> rawValuesToValues(final Multiset<MethodIncompleteSignature> rawValues) {
|
||||
final TreeSet<UsageIndexValue> values = new TreeSet<UsageIndexValue>();
|
||||
for (final Multiset.Entry<MethodIncompleteSignature> entry : rawValues.entrySet()) {
|
||||
values.add(new UsageIndexValue(entry.getElement(), entry.getCount()));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.impl.bigram;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class Bigram<E> extends Pair<E, E> {
|
||||
public Bigram(@NotNull final E first, @NotNull final E second) {
|
||||
super(first, second);
|
||||
}
|
||||
|
||||
public Bigram<E> swap() {
|
||||
return new Bigram<E>(second, first);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s - %s", first, second);
|
||||
}
|
||||
}
|
||||
-87
@@ -1,87 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.impl.bigram;
|
||||
|
||||
import com.google.common.collect.HashMultiset;
|
||||
import com.google.common.collect.Multiset;
|
||||
import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
|
||||
import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
|
||||
import com.intellij.compilerOutputIndex.impl.ClassFileData;
|
||||
import com.intellij.compilerOutputIndex.impl.CompilerOutputBaseGramsIndex;
|
||||
import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
|
||||
import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignatureChain;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.indexing.DataIndexer;
|
||||
import com.intellij.util.indexing.ID;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.asm4.ClassReader;
|
||||
import org.jetbrains.asm4.Opcodes;
|
||||
import org.jetbrains.asm4.tree.ClassNode;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class BigramMethodsUsageIndex extends CompilerOutputBaseGramsIndex<MethodIncompleteSignature> {
|
||||
public static BigramMethodsUsageIndex getInstance(final Project project) {
|
||||
return CompilerOutputIndexer.getInstance(project).getIndex(BigramMethodsUsageIndex.class);
|
||||
}
|
||||
|
||||
public BigramMethodsUsageIndex( final Project project) {
|
||||
super(MethodIncompleteSignature.createKeyDescriptor(), project);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ID<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>> getIndexId() {
|
||||
return generateIndexId("BigramMethodsUsage");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getVersion() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataIndexer<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>,ClassNode> getIndexer() {
|
||||
//
|
||||
// not fair way, but works fast
|
||||
//
|
||||
return new DataIndexer<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>, ClassNode>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>> map(final ClassNode inputData) {
|
||||
final Map<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>> map =
|
||||
new HashMap<MethodIncompleteSignature, Multiset<MethodIncompleteSignature>>();
|
||||
for (final ClassFileData.MethodData data : new ClassFileData(inputData).getMethodDatas()) {
|
||||
final SimpleBigramsExtractor extractor = new SimpleBigramsExtractor(new SimpleBigramsExtractor.BigramMethodIncompleteSignatureProcessor() {
|
||||
@Override
|
||||
public void process(final Bigram<MethodIncompleteSignature> bigram) {
|
||||
final MethodIncompleteSignature secondGram = bigram.getSecond();
|
||||
Multiset<MethodIncompleteSignature> occurrences = map.get(secondGram);
|
||||
if (occurrences == null) {
|
||||
occurrences = HashMultiset.create();
|
||||
map.put(secondGram, occurrences);
|
||||
}
|
||||
occurrences.add(bigram.getFirst());
|
||||
}
|
||||
});
|
||||
for (final ClassFileData.MethodInsnSignature ms : data.getMethodInsnSignatures()) {
|
||||
final List<MethodIncompleteSignature> methodInvocations = new SmartList<MethodIncompleteSignature>();
|
||||
final String ownerClassName = AsmUtil.getQualifiedClassName(ms.getOwner());
|
||||
final String returnType = AsmUtil.getReturnType(ms.getDesc());
|
||||
|
||||
if (ms.getName().equals(MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME)) {
|
||||
methodInvocations.add(MethodIncompleteSignature.constructor(ownerClassName));
|
||||
}
|
||||
else {
|
||||
methodInvocations.add(new MethodIncompleteSignature(ownerClassName, returnType, ms.getName(), ms.getOpcode() == Opcodes.INVOKESTATIC));
|
||||
}
|
||||
extractor.addChain(new MethodIncompleteSignatureChain(methodInvocations));
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.impl.bigram;
|
||||
|
||||
import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
|
||||
import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignatureChain;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
class SimpleBigramsExtractor {
|
||||
private final Map<String, MethodIncompleteSignature> myHolder = new HashMap<String, MethodIncompleteSignature>();
|
||||
private final BigramMethodIncompleteSignatureProcessor myProcessor;
|
||||
|
||||
public SimpleBigramsExtractor(final BigramMethodIncompleteSignatureProcessor processor) {
|
||||
myProcessor = processor;
|
||||
}
|
||||
|
||||
public void addChain(final MethodIncompleteSignatureChain chain) {
|
||||
if (chain.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final MethodIncompleteSignature firstInvocation = chain.getFirstInvocation();
|
||||
assert firstInvocation != null;
|
||||
final MethodIncompleteSignature head = firstInvocation.isStatic() ? null : myHolder.get(firstInvocation.getOwner());
|
||||
for (final Bigram<MethodIncompleteSignature> bigram : toBigrams(head, chain)) {
|
||||
myProcessor.process(bigram);
|
||||
}
|
||||
final MethodIncompleteSignature lastInvocation = chain.getLastInvocation();
|
||||
assert lastInvocation != null;
|
||||
myHolder.put(lastInvocation.getReturnType(), lastInvocation);
|
||||
}
|
||||
|
||||
private static Collection<Bigram<MethodIncompleteSignature>> toBigrams(final @Nullable MethodIncompleteSignature head,
|
||||
final @NotNull MethodIncompleteSignatureChain chain) {
|
||||
MethodIncompleteSignature currentLast = null;
|
||||
if (head != null) {
|
||||
currentLast = head;
|
||||
}
|
||||
final List<Bigram<MethodIncompleteSignature>> bigrams = new ArrayList<Bigram<MethodIncompleteSignature>>(chain.size());
|
||||
for (final MethodIncompleteSignature current : chain.list()) {
|
||||
if (currentLast != null) {
|
||||
bigrams.add(new Bigram<MethodIncompleteSignature>(currentLast, current));
|
||||
}
|
||||
currentLast = current;
|
||||
}
|
||||
return bigrams;
|
||||
}
|
||||
|
||||
public interface BigramMethodIncompleteSignatureProcessor {
|
||||
void process(Bigram<MethodIncompleteSignature> bigram);
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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.
|
||||
*/
|
||||
interface PsiManager {
|
||||
|
||||
}
|
||||
interface PsiElement {
|
||||
PsiManager getManager();
|
||||
}
|
||||
interface PsiClass extends PsiElement {
|
||||
}
|
||||
interface PsiMethod extends PsiElement {
|
||||
PsiClass getContainingClass();
|
||||
}
|
||||
interface PsiMethodCallExpression extends PsiElement {
|
||||
PsiMethod resolveMethod();
|
||||
}
|
||||
public class TestCompletion {
|
||||
|
||||
public void method() {
|
||||
PsiManager m = <caret>
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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.
|
||||
*/
|
||||
public class TestIndex {
|
||||
|
||||
public void statMethod(PsiMethodCallExpression e) {
|
||||
e.resolveMethod().getContainingClass().getManager();
|
||||
e.resolveMethod().getContainingClass().getManager();
|
||||
e.resolveMethod().getContainingClass().getManager();
|
||||
e.resolveMethod().getContainingClass().getManager();
|
||||
e.resolveMethod().getContainingClass().getManager();
|
||||
}
|
||||
}
|
||||
interface PsiManager {
|
||||
|
||||
}
|
||||
interface PsiElement {
|
||||
PsiManager getManager();
|
||||
}
|
||||
interface PsiClass extends PsiElement {
|
||||
}
|
||||
interface PsiMethod extends PsiElement {
|
||||
PsiClass getContainingClass();
|
||||
}
|
||||
interface PsiMethodCallExpression extends PsiElement {
|
||||
PsiMethod resolveMethod();
|
||||
}
|
||||
Reference in New Issue
Block a user