mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
implementation of methods chain completion indexing on jps
This commit is contained in:
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.api.index;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.api.ClassFileIndexerFactory;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public abstract class ClassFilesIndexConfigure<K, V> {
|
||||
|
||||
public abstract String getIndexCanonicalName();
|
||||
|
||||
public abstract int getIndexVersion();
|
||||
|
||||
public abstract Class<? extends ClassFileIndexerFactory> getIndexerBuilderClass();
|
||||
|
||||
public abstract ClassFilesIndexReaderBase<K, V> createIndexReader(final Project project);
|
||||
|
||||
public void prepareToIndexing(final Project project) {
|
||||
ClassFilesIndexReaderBase.checkIndexAndRecreateIfNeed(project, getIndexVersion(), getIndexCanonicalName());
|
||||
}
|
||||
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.api.index;
|
||||
|
||||
import com.intellij.compiler.compilerOutputIndex.impl.MethodsUsageIndexConfigure;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.registry.RegistryValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public enum ClassFilesIndexFeature {
|
||||
METHOD_CHAINS_COMPLETION("completion.enable.relevant.method.chain.suggestions", MethodsUsageIndexConfigure.INSTANCE);
|
||||
|
||||
@NotNull
|
||||
private final String myKey;
|
||||
@NotNull
|
||||
private final Collection<? extends MethodsUsageIndexConfigure> myRequiredIndicesConfigures;
|
||||
|
||||
ClassFilesIndexFeature(@NotNull final String key,
|
||||
@NotNull final Collection<? extends MethodsUsageIndexConfigure> requiredIndicesConfigures) {
|
||||
myKey = key;
|
||||
myRequiredIndicesConfigures = requiredIndicesConfigures;
|
||||
}
|
||||
|
||||
ClassFilesIndexFeature(@NotNull final String key, @NotNull final MethodsUsageIndexConfigure requiredConfigure) {
|
||||
this(key, Collections.<MethodsUsageIndexConfigure>singleton(requiredConfigure));
|
||||
}
|
||||
|
||||
public RegistryValue getRegistryValue() {
|
||||
return Registry.get(myKey);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getKey() {
|
||||
return myKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* is feature enabled by registry key
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return Registry.is(myKey);
|
||||
}
|
||||
|
||||
public void enable() {
|
||||
getRegistryValue().setValue(true);
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
getRegistryValue().setValue(false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<? extends MethodsUsageIndexConfigure> getRequiredIndicesConfigures() {
|
||||
return myRequiredIndicesConfigures;
|
||||
}
|
||||
}
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.api.index;
|
||||
|
||||
import com.intellij.compiler.compilerOutputIndex.impl.MethodsUsageIndexConfigure;
|
||||
import com.intellij.openapi.compiler.CompileContext;
|
||||
import com.intellij.openapi.compiler.CompileTask;
|
||||
import com.intellij.openapi.compiler.CompilerManager;
|
||||
import com.intellij.openapi.components.AbstractProjectComponent;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.registry.RegistryValue;
|
||||
import com.intellij.openapi.util.registry.RegistryValueListener;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class ClassFilesIndexFeaturesHolder extends AbstractProjectComponent {
|
||||
private final Map<ClassFilesIndexConfigure, ClassFilesIndexReaderBase> myEnabledIndexReaders =
|
||||
new HashMap<ClassFilesIndexConfigure, ClassFilesIndexReaderBase>();
|
||||
private final Map<ClassFilesIndexFeature, FeatureState> myEnabledFeatures = new HashMap<ClassFilesIndexFeature, FeatureState>();
|
||||
|
||||
public static ClassFilesIndexFeaturesHolder getInstance(final Project project) {
|
||||
return project.getComponent(ClassFilesIndexFeaturesHolder.class);
|
||||
}
|
||||
|
||||
protected ClassFilesIndexFeaturesHolder(final Project project) {
|
||||
super(project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void projectOpened() {
|
||||
for (final ClassFilesIndexFeature feature : ClassFilesIndexFeature.values()) {
|
||||
final RegistryValue registryValue = feature.getRegistryValue();
|
||||
registryValue.addListener(new RegistryValueListener.Adapter() {
|
||||
@Override
|
||||
public void afterValueChanged(final RegistryValue rawValue) {
|
||||
if (!rawValue.asBoolean() && myEnabledFeatures.containsKey(feature)) {
|
||||
disposeFeature(feature);
|
||||
}
|
||||
}
|
||||
}, myProject);
|
||||
}
|
||||
final CompilerManager compilerManager = CompilerManager.getInstance(myProject);
|
||||
compilerManager.addBeforeTask(new CompileTask() {
|
||||
@Override
|
||||
public boolean execute(final CompileContext context) {
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public synchronized boolean enableFeatureIfNeed(final ClassFilesIndexFeature feature) {
|
||||
if (!feature.isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
FeatureState state = myEnabledFeatures.get(feature);
|
||||
if (state == null) {
|
||||
state = initializeFeature(feature);
|
||||
}
|
||||
return state == FeatureState.AVAILABLE;
|
||||
}
|
||||
|
||||
public synchronized void visitEnabledConfigures(final Processor<ClassFilesIndexConfigure> availableConfiguresVisitor,
|
||||
final Processor<ClassFilesIndexConfigure> notAvailableConfiguresVisitor) {
|
||||
for (final ClassFilesIndexConfigure configure : myEnabledIndexReaders.keySet()) {
|
||||
availableConfiguresVisitor.process(configure);
|
||||
}
|
||||
for (final ClassFilesIndexFeature feature : ClassFilesIndexFeature.values()) {
|
||||
if (feature.isEnabled() && !myEnabledFeatures.containsKey(feature)) {
|
||||
for (final MethodsUsageIndexConfigure configure : feature.getRequiredIndicesConfigures()) {
|
||||
if (!myEnabledIndexReaders.containsKey(configure)) {
|
||||
notAvailableConfiguresVisitor.process(configure);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void disposeFeature(final ClassFilesIndexFeature featureToRemove) {
|
||||
for (final MethodsUsageIndexConfigure requiredConfigure : featureToRemove.getRequiredIndicesConfigures()) {
|
||||
boolean needClose = true;
|
||||
for (final ClassFilesIndexFeature enabledFeature : myEnabledFeatures.keySet()) {
|
||||
if (!enabledFeature.equals(featureToRemove) && enabledFeature.getRequiredIndicesConfigures().contains(requiredConfigure)) {
|
||||
needClose = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (needClose) {
|
||||
final ClassFilesIndexReaderBase readerToClose = myEnabledIndexReaders.remove(requiredConfigure);
|
||||
readerToClose.close();
|
||||
}
|
||||
}
|
||||
myEnabledFeatures.remove(featureToRemove);
|
||||
}
|
||||
|
||||
private synchronized FeatureState initializeFeature(final ClassFilesIndexFeature feature) {
|
||||
if (myEnabledFeatures.containsKey(feature)) {
|
||||
throw new IllegalStateException(String.format("feature %s already contains", feature.getKey()));
|
||||
}
|
||||
final Map<MethodsUsageIndexConfigure, ClassFilesIndexReaderBase> newIndices =
|
||||
new HashMap<MethodsUsageIndexConfigure, ClassFilesIndexReaderBase>();
|
||||
FeatureState newFeatureState = FeatureState.AVAILABLE;
|
||||
for (final MethodsUsageIndexConfigure requiredConfigure : feature.getRequiredIndicesConfigures()) {
|
||||
boolean isIndexAlreadyLoaded = false;
|
||||
for (final ClassFilesIndexFeature enabledFeature : myEnabledFeatures.keySet()) {
|
||||
if (enabledFeature.getRequiredIndicesConfigures().contains(requiredConfigure)) {
|
||||
isIndexAlreadyLoaded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isIndexAlreadyLoaded) {
|
||||
final ClassFilesIndexReaderBase reader = requiredConfigure.createIndexReader(myProject);
|
||||
newIndices.put(requiredConfigure, reader);
|
||||
if (reader.isEmpty()) {
|
||||
newFeatureState = FeatureState.NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
myEnabledIndexReaders.putAll(newIndices);
|
||||
myEnabledFeatures.put(feature, newFeatureState);
|
||||
return newFeatureState;
|
||||
}
|
||||
|
||||
private synchronized void close() {
|
||||
for (final ClassFilesIndexReaderBase reader : myEnabledIndexReaders.values()) {
|
||||
reader.close();
|
||||
}
|
||||
myEnabledIndexReaders.clear();
|
||||
myEnabledFeatures.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void projectClosed() {
|
||||
close();
|
||||
}
|
||||
|
||||
/**
|
||||
* try to find index with corresponding class only in currently enabled indexes
|
||||
*/
|
||||
@Nullable
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends ClassFilesIndexReaderBase> T getAvailableIndexReader(final Class<T> tClass) {
|
||||
final String indexReaderClassName = tClass.getCanonicalName();
|
||||
for (final ClassFilesIndexReaderBase reader : myEnabledIndexReaders.values()) {
|
||||
if (reader.getClass().getCanonicalName().equals(indexReaderClassName)) {
|
||||
return (T)reader;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException(String.format("index reader for class %s not found", indexReaderClassName));
|
||||
}
|
||||
|
||||
public Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
private enum FeatureState {
|
||||
AVAILABLE,
|
||||
NOT_AVAILABLE
|
||||
}
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.api.index;
|
||||
|
||||
import com.intellij.compiler.server.BuildManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
import com.intellij.util.io.PersistentHashMap;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.api.ClassFilesIndexStorage;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.api.IndexState;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public abstract class ClassFilesIndexReaderBase<K, V> {
|
||||
|
||||
private final static Logger LOG = Logger.getInstance(ClassFilesIndexReaderBase.class);
|
||||
@Nullable
|
||||
protected final ClassFilesIndexStorage<K, V> myIndex;
|
||||
|
||||
|
||||
public static boolean checkIndexAndRecreateIfNeed(final Project project, final int currentVersion, final String canonicalIndexName) {
|
||||
final File projectBuildSystemDirectory = BuildManager.getInstance().getProjectSystemDirectory(project);
|
||||
assert projectBuildSystemDirectory != null;
|
||||
final File versionFile = new File(ClassFilesIndexStorage.getIndexDir(canonicalIndexName, projectBuildSystemDirectory), "version");
|
||||
final File indexDir = ClassFilesIndexStorage.getIndexDir(canonicalIndexName, projectBuildSystemDirectory);
|
||||
if (versionFile.exists() &&
|
||||
!versionDiffers(projectBuildSystemDirectory, canonicalIndexName, currentVersion) &&
|
||||
IndexState.load(indexDir) == IndexState.EXIST) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
recreateIndex(canonicalIndexName, currentVersion, projectBuildSystemDirectory, indexDir);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All inheritors MUST have constructor with only one parameter - Project
|
||||
*/
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
protected ClassFilesIndexReaderBase(final KeyDescriptor<K> keyDescriptor,
|
||||
final DataExternalizer<V> valueExternalizer,
|
||||
final String canonicalIndexName,
|
||||
final int indexVersion,
|
||||
final Project project) {
|
||||
if (checkIndexAndRecreateIfNeed(project, indexVersion, canonicalIndexName)) {
|
||||
ClassFilesIndexStorage<K, V> index = null;
|
||||
IOException exception = null;
|
||||
final File projectBuildSystemDirectory = BuildManager.getInstance().getProjectSystemDirectory(project);
|
||||
final File indexDir = ClassFilesIndexStorage.getIndexDir(canonicalIndexName, projectBuildSystemDirectory);
|
||||
try {
|
||||
index = new ClassFilesIndexStorage<K, V>(indexDir, keyDescriptor, valueExternalizer);
|
||||
}
|
||||
catch (final IOException e) {
|
||||
exception = e;
|
||||
PersistentHashMap.deleteFilesStartingWith(ClassFilesIndexStorage.getIndexFile(indexDir));
|
||||
}
|
||||
if (exception != null) {
|
||||
recreateIndex(canonicalIndexName, indexVersion, projectBuildSystemDirectory, indexDir);
|
||||
myIndex = null;
|
||||
}
|
||||
else {
|
||||
myIndex = index;
|
||||
}
|
||||
}
|
||||
else {
|
||||
myIndex = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void recreateIndex(final String canonicalIndexName,
|
||||
final int indexVersion,
|
||||
final File projectBuildSystemDirectory,
|
||||
final File indexDir) {
|
||||
if (indexDir.exists()) {
|
||||
FileUtil.delete(indexDir);
|
||||
}
|
||||
try {
|
||||
FileUtil.writeToFile(new File(ClassFilesIndexStorage.getIndexDir(canonicalIndexName, projectBuildSystemDirectory), "version"), String.valueOf(
|
||||
indexVersion));
|
||||
}
|
||||
catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
IndexState.NOT_EXIST.save(indexDir);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return myIndex == null;
|
||||
}
|
||||
|
||||
public final void close() {
|
||||
if (myIndex != null) {
|
||||
try {
|
||||
myIndex.close();
|
||||
}
|
||||
catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void delete() {
|
||||
try {
|
||||
if (myIndex != null) {
|
||||
myIndex.delete();
|
||||
}
|
||||
}
|
||||
catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static File getVersionFile(final File projectBuildSystemDirectory, final String canonicalIndexName) {
|
||||
return new File(ClassFilesIndexStorage.getIndexDir(canonicalIndexName, projectBuildSystemDirectory), "version");
|
||||
}
|
||||
|
||||
private static boolean versionDiffers(final File projectBuildSystemDirectory, final String canonicalIndexName, final int currentVersion) {
|
||||
final File versionFile = getVersionFile(projectBuildSystemDirectory, canonicalIndexName);
|
||||
if (!versionFile.exists()) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(FileUtil.loadFile(versionFile)) != currentVersion;
|
||||
}
|
||||
catch (final IOException e) {
|
||||
LOG.error("error while reading version file " + versionFile.getAbsolutePath());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.api.index;
|
||||
|
||||
import com.intellij.compiler.server.BuildProcessParametersProvider;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.api.ClassFilesIndicesBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class ClassFilesIndexerBuilderParametersProvider extends BuildProcessParametersProvider {
|
||||
private final ClassFilesIndexFeaturesHolder myIndicesHolder;
|
||||
|
||||
protected ClassFilesIndexerBuilderParametersProvider(final ClassFilesIndexFeaturesHolder indicesHolder) {
|
||||
myIndicesHolder = indicesHolder;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> getVMArguments() {
|
||||
final List<String> args = new ArrayList<String>();
|
||||
myIndicesHolder.visitEnabledConfigures(
|
||||
new Processor<ClassFilesIndexConfigure>() {
|
||||
@Override
|
||||
public boolean process(final ClassFilesIndexConfigure availableConfigure) {
|
||||
final String className = availableConfigure.getIndexerBuilderClass().getCanonicalName();
|
||||
args.add(className);
|
||||
return true;
|
||||
}
|
||||
}, new Processor<ClassFilesIndexConfigure>() {
|
||||
@Override
|
||||
public boolean process(final ClassFilesIndexConfigure notAvailableConfigure) {
|
||||
final String className = notAvailableConfigure.getIndexerBuilderClass().getCanonicalName();
|
||||
args.add(className);
|
||||
notAvailableConfigure.prepareToIndexing(myIndicesHolder.getProject());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
if (args.size() != 0) {
|
||||
final String serializedArgs = StringUtil.join(args, ";");
|
||||
return Collections.singletonList("-D" + ClassFilesIndicesBuilder.PROPERTY_NAME + "=" + serializedArgs);
|
||||
}
|
||||
else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+26
-12
@@ -1,17 +1,31 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.search;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch;
|
||||
|
||||
import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.context.ContextRelevantStaticMethod;
|
||||
import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
|
||||
import com.intellij.compilerOutputIndex.impl.MethodsUsageIndex;
|
||||
import com.intellij.compilerOutputIndex.impl.UsageIndexValue;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.context.ChainCompletionContext;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.context.ContextRelevantStaticMethod;
|
||||
import com.intellij.compiler.compilerOutputIndex.impl.MethodsUsageIndexReader;
|
||||
import com.intellij.compiler.compilerOutputIndex.impl.UsageIndexValue;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodIncompleteSignature;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -20,13 +34,13 @@ import java.util.*;
|
||||
*/
|
||||
public class CachedRelevantStaticMethodSearcher {
|
||||
private final HashMap<MethodIncompleteSignature, PsiMethod> myCachedResolveResults = new HashMap<MethodIncompleteSignature, PsiMethod>();
|
||||
private final MethodsUsageIndex myIndex;
|
||||
private final MethodsUsageIndexReader myIndexReader;
|
||||
private final JavaPsiFacade myJavaPsiFacade;
|
||||
private final GlobalSearchScope myAllScope;
|
||||
private final GlobalSearchScope myResolveScope;
|
||||
|
||||
public CachedRelevantStaticMethodSearcher(final Project project, final GlobalSearchScope resolveScope) {
|
||||
myIndex = MethodsUsageIndex.getInstance(project);
|
||||
myIndexReader = MethodsUsageIndexReader.getInstance(project);
|
||||
myJavaPsiFacade = JavaPsiFacade.getInstance(project);
|
||||
myAllScope = GlobalSearchScope.allScope(project);
|
||||
myResolveScope = resolveScope;
|
||||
@@ -41,8 +55,8 @@ public class CachedRelevantStaticMethodSearcher {
|
||||
completionContext.getTargetQName().equals(resultQualifiedClassName)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final TreeSet<UsageIndexValue> indexValues = myIndex.getValues(resultQualifiedClassName);
|
||||
if (indexValues != null) {
|
||||
final TreeSet<UsageIndexValue> indexValues = myIndexReader.getMethods(resultQualifiedClassName);
|
||||
if (!indexValues.isEmpty()) {
|
||||
int occurrences = 0;
|
||||
final List<ContextRelevantStaticMethod> relevantMethods = new ArrayList<ContextRelevantStaticMethod>();
|
||||
for (final UsageIndexValue indexValue : extractStaticMethods(indexValues)) {
|
||||
@@ -52,7 +66,7 @@ public class CachedRelevantStaticMethodSearcher {
|
||||
method = myCachedResolveResults.get(methodInvocation);
|
||||
}
|
||||
else {
|
||||
final PsiMethod[] methods = methodInvocation.resolveNotDeprecated(myJavaPsiFacade, myAllScope);
|
||||
final PsiMethod[] methods = completionContext.resolveNotDeprecated(methodInvocation);
|
||||
method = MethodChainsSearchUtil
|
||||
.getMethodWithMinNotPrimitiveParameters(methods, Collections.singleton(completionContext.getTargetQName()));
|
||||
myCachedResolveResults.put(methodInvocation, method);
|
||||
+16
-1
@@ -1,4 +1,19 @@
|
||||
package com.intellij.codeInsight.completion.methodChains;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtilRt;
|
||||
import com.intellij.psi.CommonClassNames;
|
||||
+16
-1
@@ -1,4 +1,19 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.search;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
+53
-45
@@ -1,8 +1,23 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.search;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch;
|
||||
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
|
||||
import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
|
||||
import com.intellij.compilerOutputIndex.impl.UsageIndexValue;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.context.ChainCompletionContext;
|
||||
import com.intellij.compiler.compilerOutputIndex.impl.MethodsUsageIndexReader;
|
||||
import com.intellij.compiler.compilerOutputIndex.impl.UsageIndexValue;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
@@ -12,8 +27,8 @@ import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.FactoryMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodIncompleteSignature;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -27,37 +42,32 @@ public final class ChainsSearcher {
|
||||
private static final Logger LOG = Logger.getInstance(ChainsSearcher.class);
|
||||
private static final double NEXT_METHOD_IN_CHAIN_RATIO = 1.5;
|
||||
|
||||
public static List<MethodsChain> search(final MethodChainsSearchService searchService,
|
||||
public static List<MethodsChain> search(final MethodsUsageIndexReader indexReader,
|
||||
final String targetQName,
|
||||
final Set<String> contextQNames,
|
||||
final int maxResultSize,
|
||||
final int pathMaximalLength,
|
||||
final FactoryMap<MethodIncompleteSignature, PsiMethod[]> resolver,
|
||||
final Set<String> excludedParamsTypesQNames,
|
||||
final ChainCompletionContext context) {
|
||||
final SearchInitializer initializer = createInitializer(targetQName, resolver, searchService, excludedParamsTypesQNames);
|
||||
return search(searchService, initializer, contextQNames, pathMaximalLength, maxResultSize, resolver, targetQName,
|
||||
excludedParamsTypesQNames, context);
|
||||
final SearchInitializer initializer = createInitializer(targetQName, indexReader, context.getExcludedQNames(), context);
|
||||
return search(indexReader, initializer, contextQNames, pathMaximalLength, maxResultSize, targetQName, context);
|
||||
}
|
||||
|
||||
private static SearchInitializer createInitializer(final String targetQName,
|
||||
final FactoryMap<MethodIncompleteSignature, PsiMethod[]> resolver,
|
||||
final MethodChainsSearchService searchService,
|
||||
final Set<String> excludedParamsTypesQNames) {
|
||||
return new SearchInitializer(searchService.getMethods(targetQName), resolver, targetQName, excludedParamsTypesQNames);
|
||||
final MethodsUsageIndexReader indexReader,
|
||||
final Set<String> excludedParamsTypesQNames,
|
||||
final ChainCompletionContext context) {
|
||||
return new SearchInitializer(indexReader.getMethods(targetQName), targetQName, excludedParamsTypesQNames, context);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<MethodsChain> search(final MethodChainsSearchService searchService,
|
||||
private static List<MethodsChain> search(final MethodsUsageIndexReader indexReader,
|
||||
final SearchInitializer initializer,
|
||||
final Set<String> toSet,
|
||||
final int pathMaximalLength,
|
||||
final int maxResultSize,
|
||||
final FactoryMap<MethodIncompleteSignature, PsiMethod[]> resolver,
|
||||
final String targetQName,
|
||||
final Set<String> excludedParamsTypesQNames,
|
||||
final ChainCompletionContext context) {
|
||||
final Set<String> allExcludedNames = MethodChainsSearchUtil.unionToHashSet(excludedParamsTypesQNames, targetQName);
|
||||
final Set<String> allExcludedNames = MethodChainsSearchUtil.unionToHashSet(context.getExcludedQNames(), targetQName);
|
||||
final SearchInitializer.InitResult initResult = initializer.init(Collections.<String>emptySet());
|
||||
|
||||
final Map<MethodIncompleteSignature, MethodsChain> knownDistance = initResult.getChains();
|
||||
@@ -70,18 +80,18 @@ public final class ChainsSearcher {
|
||||
@Override
|
||||
public WeightAware<Pair<MethodIncompleteSignature, MethodsChain>> fun(
|
||||
final WeightAware<MethodIncompleteSignature> methodIncompleteSignatureWeightAware) {
|
||||
final MethodIncompleteSignature
|
||||
underlying =
|
||||
methodIncompleteSignatureWeightAware
|
||||
.getUnderlying();
|
||||
return new WeightAware<Pair<MethodIncompleteSignature, MethodsChain>>(
|
||||
new Pair<MethodIncompleteSignature, MethodsChain>(
|
||||
underlying, new MethodsChain(
|
||||
context.resolveNotDeprecated(
|
||||
underlying),
|
||||
methodIncompleteSignatureWeightAware
|
||||
.getUnderlying(),
|
||||
new MethodsChain(resolver.get(
|
||||
methodIncompleteSignatureWeightAware
|
||||
.getUnderlying()),
|
||||
methodIncompleteSignatureWeightAware
|
||||
.getWeight(),
|
||||
methodIncompleteSignatureWeightAware
|
||||
.getUnderlying()
|
||||
.getOwner())),
|
||||
.getWeight(),
|
||||
underlying.getOwner())),
|
||||
methodIncompleteSignatureWeightAware
|
||||
.getWeight());
|
||||
}
|
||||
@@ -94,7 +104,7 @@ public final class ChainsSearcher {
|
||||
}
|
||||
}
|
||||
|
||||
final ResultHolder result = new ResultHolder(context);
|
||||
final ResultHolder result = new ResultHolder(context.getPsiManager());
|
||||
while (!q.isEmpty()) {
|
||||
ProgressManager.checkCanceled();
|
||||
final WeightAware<Pair<MethodIncompleteSignature, MethodsChain>> currentVertex = q.poll();
|
||||
@@ -108,7 +118,7 @@ public final class ChainsSearcher {
|
||||
result.add(currentVertex.getUnderlying().getSecond());
|
||||
continue;
|
||||
}
|
||||
final SortedSet<UsageIndexValue> nextMethods = searchService.getMethods(currentVertexUnderlying.getFirst().getOwner());
|
||||
final SortedSet<UsageIndexValue> nextMethods = indexReader.getMethods(currentVertexUnderlying.getFirst().getOwner());
|
||||
final MaxSizeTreeSet<WeightAware<MethodIncompleteSignature>> currentSignatures =
|
||||
new MaxSizeTreeSet<WeightAware<MethodIncompleteSignature>>(maxResultSize);
|
||||
for (final UsageIndexValue indexValue : nextMethods) {
|
||||
@@ -119,16 +129,14 @@ public final class ChainsSearcher {
|
||||
final MethodsChain knownVertexMethodsChain = knownDistance.get(vertex);
|
||||
if ((knownVertexMethodsChain == null || knownVertexMethodsChain.getChainWeight() < vertexDistance)) {
|
||||
if (currentSignatures.isEmpty() || currentSignatures.last().getWeight() < vertexDistance) {
|
||||
final MethodIncompleteSignature methodInvocation = indexValue.getMethodIncompleteSignature();
|
||||
final PsiMethod[] psiMethods = resolver.get(methodInvocation);
|
||||
if (psiMethods.length != 0 && MethodChainsSearchUtil.checkParametersForTypesQNames(psiMethods, allExcludedNames)) {
|
||||
final MethodsChain newBestMethodsChain =
|
||||
currentVertexMethodsChain.addEdge(psiMethods, indexValue.getMethodIncompleteSignature().getOwner(), vertexDistance);
|
||||
if (newBestMethodsChain.size() <= pathMaximalLength - 1) {
|
||||
currentSignatures
|
||||
.add(new WeightAware<MethodIncompleteSignature>(indexValue.getMethodIncompleteSignature(), vertexDistance));
|
||||
if (currentVertexMethodsChain.size() < pathMaximalLength - 1) {
|
||||
final MethodIncompleteSignature methodInvocation = indexValue.getMethodIncompleteSignature();
|
||||
final PsiMethod[] psiMethods = context.resolveNotDeprecated(methodInvocation);
|
||||
if (psiMethods.length != 0 && MethodChainsSearchUtil.checkParametersForTypesQNames(psiMethods, allExcludedNames)) {
|
||||
final MethodsChain newBestMethodsChain = currentVertexMethodsChain.addEdge(psiMethods, indexValue.getMethodIncompleteSignature().getOwner(), vertexDistance);
|
||||
currentSignatures.add(new WeightAware<MethodIncompleteSignature>(indexValue.getMethodIncompleteSignature(), vertexDistance));
|
||||
knownDistance.put(vertex, newBestMethodsChain);
|
||||
}
|
||||
knownDistance.put(vertex, newBestMethodsChain);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,7 +149,7 @@ public final class ChainsSearcher {
|
||||
if (!currentSignatures.isEmpty()) {
|
||||
boolean isBreak = false;
|
||||
for (final WeightAware<MethodIncompleteSignature> sign : currentSignatures) {
|
||||
final PsiMethod[] resolved = resolver.get(sign.getUnderlying());
|
||||
final PsiMethod[] resolved = context.resolveNotDeprecated(sign.getUnderlying());
|
||||
if (!isBreak) {
|
||||
if (sign.getWeight() * NEXT_METHOD_IN_CHAIN_RATIO > currentVertex.getWeight()) {
|
||||
final boolean stopChain = sign.getUnderlying().isStatic() || toSet.contains(sign.getUnderlying().getOwner());
|
||||
@@ -193,10 +201,10 @@ public final class ChainsSearcher {
|
||||
|
||||
private static class ResultHolder {
|
||||
private final List<MethodsChain> myResult;
|
||||
private final ChainCompletionContext myContext;
|
||||
private final PsiManager myContext;
|
||||
|
||||
private ResultHolder(final ChainCompletionContext context) {
|
||||
myContext = context;
|
||||
private ResultHolder(final PsiManager psiManager) {
|
||||
myContext = psiManager;
|
||||
myResult = new ArrayList<MethodsChain>();
|
||||
}
|
||||
|
||||
@@ -286,8 +294,8 @@ public final class ChainsSearcher {
|
||||
});
|
||||
}
|
||||
|
||||
private static List<MethodsChain> findSimilar(final List<MethodsChain> chains, final ChainCompletionContext context) {
|
||||
final ResultHolder resultHolder = new ResultHolder(context);
|
||||
private static List<MethodsChain> findSimilar(final List<MethodsChain> chains, final PsiManager psiManager) {
|
||||
final ResultHolder resultHolder = new ResultHolder(psiManager);
|
||||
for (final MethodsChain chain : chains) {
|
||||
resultHolder.add(chain);
|
||||
}
|
||||
+16
-3
@@ -1,6 +1,20 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.search;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch;
|
||||
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -10,7 +24,6 @@ import java.util.*;
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class MaxSizeTreeSet<E> implements NavigableSet<E> {
|
||||
|
||||
@NotNull
|
||||
private final NavigableSet<E> myUnderlying;
|
||||
private final int myMaxSize;
|
||||
+17
-5
@@ -1,9 +1,21 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.search;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch;
|
||||
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiParameter;
|
||||
import com.intellij.psi.PsiParameterList;
|
||||
import com.intellij.psi.PsiPrimitiveType;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
+18
-4
@@ -1,6 +1,20 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.search;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch;
|
||||
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
@@ -85,7 +99,7 @@ public class MethodsChain {
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public static CompareResult compare(final MethodsChain left, final MethodsChain right, final ChainCompletionContext context) {
|
||||
public static CompareResult compare(final MethodsChain left, final MethodsChain right, final PsiManager psiManager) {
|
||||
if (left.size() == 0) {
|
||||
return CompareResult.RIGHT_CONTAINS_LEFT;
|
||||
}
|
||||
@@ -113,7 +127,7 @@ public class MethodsChain {
|
||||
}
|
||||
|
||||
|
||||
return hasBaseMethod(left.getPath().get(0), right.getPath().get(0), PsiManager.getInstance(context.getProject()))
|
||||
return hasBaseMethod(left.getPath().get(0), right.getPath().get(0), psiManager)
|
||||
? CompareResult.EQUAL
|
||||
: CompareResult.NOT_EQUAL;
|
||||
}
|
||||
+26
-11
@@ -1,16 +1,30 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.search;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch;
|
||||
|
||||
import com.intellij.codeInsight.NullableNotNullManager;
|
||||
import com.intellij.codeInsight.completion.JavaChainLookupElement;
|
||||
import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.context.ContextRelevantStaticMethod;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.context.ContextRelevantVariableGetter;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.lookup.ChainCompletionNewVariableLookupElement;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.lookup.WeightableChainLookupElement;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.GetterLookupSubLookupElement;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.VariableSubLookupElement;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.context.ChainCompletionContext;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.context.ContextRelevantStaticMethod;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.context.ContextRelevantVariableGetter;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.ChainCompletionNewVariableLookupElement;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.WeightableChainLookupElement;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.sub.GetterLookupSubLookupElement;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.sub.SubLookupElement;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.sub.VariableSubLookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.VariableLookupItem;
|
||||
import com.intellij.psi.*;
|
||||
@@ -24,7 +38,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.codeInsight.completion.methodChains.completion.lookup.ChainCompletionLookupElementUtil.createLookupElement;
|
||||
import static com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.ChainCompletionLookupElementUtil.createLookupElement;
|
||||
import static com.intellij.psi.CommonClassNames.JAVA_LANG_STRING;
|
||||
|
||||
/**
|
||||
@@ -159,6 +173,7 @@ public class MethodsChainLookupRangingHelper {
|
||||
matchedParametersInContext++;
|
||||
continue;
|
||||
}
|
||||
//todo
|
||||
final ContextRelevantStaticMethod contextRelevantStaticMethod =
|
||||
ContainerUtil.getFirstItem(context.getRelevantStaticMethods(typeQName, weight), null);
|
||||
if (contextRelevantStaticMethod != null) {
|
||||
+17
-2
@@ -1,6 +1,21 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.search;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch;
|
||||
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.context.ChainCompletionContext;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiParameter;
|
||||
import com.intellij.psi.PsiPrimitiveType;
|
||||
+36
-25
@@ -1,9 +1,25 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.search;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch;
|
||||
|
||||
import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
|
||||
import com.intellij.compilerOutputIndex.impl.UsageIndexValue;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.context.ChainCompletionContext;
|
||||
import com.intellij.compiler.compilerOutputIndex.impl.UsageIndexValue;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.util.containers.FactoryMap;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodIncompleteSignature;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -13,18 +29,16 @@ import java.util.*;
|
||||
public class SearchInitializer {
|
||||
private final static int CHAIN_SEARCH_MAGIC_RATIO = 12;
|
||||
|
||||
private final List<WeightAware<MethodIncompleteSignature>> myVertices;
|
||||
private final LinkedHashMap<MethodIncompleteSignature, MethodsChain> myChains;
|
||||
private final FactoryMap<MethodIncompleteSignature, PsiMethod[]> myResolver;
|
||||
private final LinkedHashMap<MethodIncompleteSignature, Pair<MethodsChain, Integer>> myChains;
|
||||
private final ChainCompletionContext myContext;
|
||||
|
||||
public SearchInitializer(final SortedSet<UsageIndexValue> indexValues,
|
||||
final FactoryMap<MethodIncompleteSignature, PsiMethod[]> resolver,
|
||||
final String targetQName,
|
||||
final Set<String> excludedParamsTypesQNames) {
|
||||
myResolver = resolver;
|
||||
final Set<String> excludedParamsTypesQNames,
|
||||
final ChainCompletionContext context) {
|
||||
myContext = context;
|
||||
final int size = indexValues.size();
|
||||
myVertices = new ArrayList<WeightAware<MethodIncompleteSignature>>(size);
|
||||
myChains = new LinkedHashMap<MethodIncompleteSignature, MethodsChain>(size);
|
||||
myChains = new LinkedHashMap<MethodIncompleteSignature, Pair<MethodsChain, Integer>>(size);
|
||||
add(indexValues, MethodChainsSearchUtil.unionToHashSet(excludedParamsTypesQNames, targetQName));
|
||||
}
|
||||
|
||||
@@ -45,30 +59,27 @@ public class SearchInitializer {
|
||||
|
||||
private boolean add(final UsageIndexValue indexValue, final Set<String> excludedParamsTypesQNames) {
|
||||
final MethodIncompleteSignature methodInvocation = indexValue.getMethodIncompleteSignature();
|
||||
final PsiMethod[] psiMethods = myResolver.get(methodInvocation);
|
||||
final PsiMethod[] psiMethods = myContext.resolveNotDeprecated(methodInvocation);
|
||||
if (psiMethods.length != 0 && MethodChainsSearchUtil.checkParametersForTypesQNames(psiMethods, excludedParamsTypesQNames)) {
|
||||
final int occurrences = indexValue.getOccurrences();
|
||||
final MethodsChain methodsChain = new MethodsChain(psiMethods, occurrences, indexValue.getMethodIncompleteSignature().getOwner());
|
||||
myChains.put(methodInvocation, methodsChain);
|
||||
myVertices.add(new WeightAware<MethodIncompleteSignature>(methodInvocation, occurrences));
|
||||
myChains.put(methodInvocation, Pair.create(methodsChain, occurrences));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public InitResult init(final Set<String> excludedEdgeNames) {
|
||||
final int size = myVertices.size();
|
||||
final int size = myChains.size();
|
||||
final List<WeightAware<MethodIncompleteSignature>> initedVertexes = new ArrayList<WeightAware<MethodIncompleteSignature>>(size);
|
||||
final LinkedHashMap<MethodIncompleteSignature, MethodsChain> initedChains =
|
||||
new LinkedHashMap<MethodIncompleteSignature, MethodsChain>(size);
|
||||
final Iterator<Map.Entry<MethodIncompleteSignature, MethodsChain>> chainsIterator = myChains.entrySet().iterator();
|
||||
for (final WeightAware<MethodIncompleteSignature> vertex : myVertices) {
|
||||
final Map.Entry<MethodIncompleteSignature, MethodsChain> chainEntry = chainsIterator.next();
|
||||
final MethodIncompleteSignature method = vertex.getUnderlying();
|
||||
if (!excludedEdgeNames.contains(method.getName())) {
|
||||
initedVertexes.add(vertex);
|
||||
final MethodsChain methodsChain = chainEntry.getValue();
|
||||
initedChains.put(chainEntry.getKey(), methodsChain);
|
||||
for (final Map.Entry<MethodIncompleteSignature, Pair<MethodsChain, Integer>> entry : myChains.entrySet()) {
|
||||
final MethodIncompleteSignature signature = entry.getKey();
|
||||
if (!excludedEdgeNames.contains(signature.getName())) {
|
||||
initedVertexes.add(new WeightAware<MethodIncompleteSignature>(entry.getKey(), entry.getValue().getSecond()));
|
||||
final MethodsChain methodsChain = entry.getValue().getFirst();
|
||||
initedChains.put(signature, methodsChain);
|
||||
}
|
||||
}
|
||||
return new InitResult(initedVertexes, initedChains);
|
||||
@@ -92,4 +103,4 @@ public class SearchInitializer {
|
||||
return myChains;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
-1
@@ -1,4 +1,19 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.completion;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch.completion;
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionInitializationContext;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
+34
-32
@@ -1,16 +1,31 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.completion;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch.completion;
|
||||
|
||||
import com.intellij.codeInsight.completion.*;
|
||||
import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.context.ContextUtil;
|
||||
import com.intellij.codeInsight.completion.methodChains.search.ChainsSearcher;
|
||||
import com.intellij.codeInsight.completion.methodChains.search.MethodChainsSearchService;
|
||||
import com.intellij.codeInsight.completion.methodChains.search.MethodsChain;
|
||||
import com.intellij.codeInsight.completion.methodChains.search.MethodsChainLookupRangingHelper;
|
||||
import com.intellij.compiler.compilerOutputIndex.api.index.ClassFilesIndexFeature;
|
||||
import com.intellij.compiler.compilerOutputIndex.api.index.ClassFilesIndexFeaturesHolder;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.ChainCompletionStringUtil;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.ChainsSearcher;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.MethodsChain;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.MethodsChainLookupRangingHelper;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.context.ChainCompletionContext;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.context.ContextUtil;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexFeature;
|
||||
import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
|
||||
import com.intellij.compiler.compilerOutputIndex.impl.MethodsUsageIndexReader;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
@@ -21,7 +36,6 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.FactoryMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -41,7 +55,9 @@ public class MethodsChainsCompletionContributor extends CompletionContributor {
|
||||
|
||||
@Override
|
||||
public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
|
||||
if (parameters.getInvocationCount() >= INVOCATIONS_THRESHOLD && CompilerOutputIndexFeature.METHOD_CHAINS_COMPLETION.isEnabled()) {
|
||||
if (parameters.getInvocationCount() >= INVOCATIONS_THRESHOLD
|
||||
&& ClassFilesIndexFeaturesHolder.getInstance(parameters.getPosition().getProject())
|
||||
.enableFeatureIfNeed(ClassFilesIndexFeature.METHOD_CHAINS_COMPLETION)) {
|
||||
super.fillCompletionVariants(parameters, result);
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
result.stopHere();
|
||||
@@ -80,9 +96,9 @@ public class MethodsChainsCompletionContributor extends CompletionContributor {
|
||||
private static List<LookupElement> searchForLookups(final String targetClassQName,
|
||||
final Set<String> contextRelevantTypes,
|
||||
final ChainCompletionContext completionContext) {
|
||||
final MethodChainsSearchService searchService = new MethodChainsSearchService(completionContext.getProject());
|
||||
final MethodsUsageIndexReader methodsUsageIndexReader = MethodsUsageIndexReader.getInstance(completionContext.getProject());
|
||||
final List<MethodsChain> searchResult =
|
||||
searchChains(targetClassQName, contextRelevantTypes, MAX_SEARCH_RESULT_SIZE, MAX_CHAIN_SIZE, completionContext, searchService);
|
||||
searchChains(targetClassQName, contextRelevantTypes, MAX_SEARCH_RESULT_SIZE, MAX_CHAIN_SIZE, completionContext, methodsUsageIndexReader);
|
||||
if (searchResult.size() < MAX_SEARCH_RESULT_SIZE) {
|
||||
final PsiClass aClass = JavaPsiFacade.getInstance(completionContext.getProject())
|
||||
.findClass(targetClassQName, GlobalSearchScope.allScope(completionContext.getProject()));
|
||||
@@ -95,10 +111,10 @@ public class MethodsChainsCompletionContributor extends CompletionContributor {
|
||||
final List<MethodsChain> inheritorFilteredSearchResult = new SmartList<MethodsChain>();
|
||||
//noinspection ConstantConditions
|
||||
for (final MethodsChain chain : searchChains(inheritorQName, contextRelevantTypes, MAX_SEARCH_RESULT_SIZE, MAX_CHAIN_SIZE,
|
||||
completionContext, searchService)) {
|
||||
completionContext, methodsUsageIndexReader)) {
|
||||
boolean insert = true;
|
||||
for (final MethodsChain baseChain : searchResult) {
|
||||
final MethodsChain.CompareResult r = MethodsChain.compare(baseChain, chain, completionContext);
|
||||
final MethodsChain.CompareResult r = MethodsChain.compare(baseChain, chain, completionContext.getPsiManager());
|
||||
if (r != MethodsChain.CompareResult.NOT_EQUAL) {
|
||||
insert = false;
|
||||
break;
|
||||
@@ -195,21 +211,7 @@ public class MethodsChainsCompletionContributor extends CompletionContributor {
|
||||
final int maxResultSize,
|
||||
final int maxChainSize,
|
||||
final ChainCompletionContext context,
|
||||
final MethodChainsSearchService searchService) {
|
||||
return ChainsSearcher.search(searchService, targetQName, contextVarsQNames, maxResultSize, maxChainSize,
|
||||
createNotDeprecatedMethodsResolver(JavaPsiFacade.getInstance(context.getProject()),
|
||||
context.getResolveScope()), context.getExcludedQNames(), context);
|
||||
final MethodsUsageIndexReader methodsUsageIndexReader) {
|
||||
return ChainsSearcher.search(methodsUsageIndexReader, targetQName, contextVarsQNames, maxResultSize, maxChainSize, context);
|
||||
}
|
||||
|
||||
private static FactoryMap<MethodIncompleteSignature, PsiMethod[]> createNotDeprecatedMethodsResolver(final JavaPsiFacade javaPsiFacade,
|
||||
final GlobalSearchScope scope) {
|
||||
return new FactoryMap<MethodIncompleteSignature, PsiMethod[]>() {
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiMethod[] create(final MethodIncompleteSignature signature) {
|
||||
return signature.resolveNotDeprecated(javaPsiFacade, scope);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
+3
-3
@@ -13,12 +13,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInsight.completion.methodChains.completion;
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch.completion;
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionLocation;
|
||||
import com.intellij.codeInsight.completion.CompletionWeigher;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.lookup.WeightableChainLookupElement;
|
||||
import com.intellij.codeInsight.completion.methodChains.search.ChainRelevance;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.WeightableChainLookupElement;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.ChainRelevance;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
+17
-2
@@ -1,6 +1,21 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.completion.lookup;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup;
|
||||
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.sub.SubLookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.psi.PsiKeyword;
|
||||
+17
-2
@@ -1,9 +1,24 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.completion.lookup;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup;
|
||||
|
||||
import com.intellij.codeInsight.completion.InsertionContext;
|
||||
import com.intellij.codeInsight.completion.JavaMethodCallElement;
|
||||
import com.intellij.codeInsight.completion.StaticallyImportable;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.sub.SubLookupElement;
|
||||
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
+16
-2
@@ -1,6 +1,20 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.completion.lookup;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup;
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionInitializationContext;
|
||||
import com.intellij.codeInsight.completion.InsertionContext;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementDecorator;
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup;
|
||||
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.ChainRelevance;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementDecorator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public final class WeightableChainLookupElement extends LookupElementDecorator<LookupElement> {
|
||||
private final ChainRelevance myChainRelevance;
|
||||
|
||||
public WeightableChainLookupElement(final @NotNull LookupElement delegate, final ChainRelevance relevance) {
|
||||
super(delegate);
|
||||
myChainRelevance = relevance;
|
||||
}
|
||||
|
||||
public ChainRelevance getChainRelevance() {
|
||||
return myChainRelevance;
|
||||
}
|
||||
}
|
||||
+16
-1
@@ -1,4 +1,19 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.completion.lookup.sub;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.sub;
|
||||
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
+17
-2
@@ -1,6 +1,21 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.completion.lookup.sub;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.sub;
|
||||
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.lookup.ChainCompletionLookupElementUtil;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.ChainCompletionLookupElementUtil;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.sub;
|
||||
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public interface SubLookupElement {
|
||||
|
||||
void doImport(final PsiJavaFile javaFile);
|
||||
|
||||
String getInsertString();
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.sub;
|
||||
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
import com.intellij.psi.PsiVariable;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class VariableSubLookupElement implements SubLookupElement {
|
||||
|
||||
private final String myVarName;
|
||||
|
||||
public VariableSubLookupElement(final PsiVariable variable) {
|
||||
myVarName = variable.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doImport(final PsiJavaFile javaFile) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInsertString() {
|
||||
return myVarName;
|
||||
}
|
||||
}
|
||||
+34
-2
@@ -1,15 +1,34 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.completion.context;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch.context;
|
||||
|
||||
import com.intellij.codeInsight.completion.methodChains.search.CachedRelevantStaticMethodSearcher;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.CachedRelevantStaticMethodSearcher;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.openapi.util.UserDataHolder;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiVariable;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.containers.FactoryMap;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodIncompleteSignature;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -35,6 +54,8 @@ public class ChainCompletionContext {
|
||||
private final Set<String> myExcludedQNames;
|
||||
private final GlobalSearchScope myResolveScope;
|
||||
private final Project myProject;
|
||||
private final PsiManager myPsiManager;
|
||||
private final FactoryMap<MethodIncompleteSignature, PsiMethod[]> myNotDeprecatedMethodsResolver;
|
||||
|
||||
private final NotNullLazyValue<Set<String>> contextTypesQNames = new NotNullLazyValue<Set<String>>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -70,6 +91,8 @@ public class ChainCompletionContext {
|
||||
myExcludedQNames = excludedQNames;
|
||||
myResolveScope = resolveScope;
|
||||
myProject = project;
|
||||
myPsiManager = PsiManager.getInstance(project);
|
||||
myNotDeprecatedMethodsResolver = MethodIncompleteSignatureResolver.create(JavaPsiFacade.getInstance(project), resolveScope);
|
||||
myStaticMethodSearcher = new CachedRelevantStaticMethodSearcher(project, resolveScope);
|
||||
}
|
||||
|
||||
@@ -146,6 +169,15 @@ public class ChainCompletionContext {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
public PsiManager getPsiManager() {
|
||||
return myPsiManager;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiMethod[] resolveNotDeprecated(final MethodIncompleteSignature methodIncompleteSignature) {
|
||||
return myNotDeprecatedMethodsResolver.get(methodIncompleteSignature);
|
||||
}
|
||||
|
||||
private static <T> HashSet<T> unionToHashSet(final Collection<T>... collections) {
|
||||
final HashSet<T> res = new HashSet<T>();
|
||||
for (final Collection<T> set : collections) {
|
||||
+16
-1
@@ -1,4 +1,19 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.completion.context;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch.context;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
+19
-4
@@ -1,8 +1,23 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.completion.context;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch.context;
|
||||
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.StaticMethodSubLookupElement;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.VariableSubLookupElement;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.sub.StaticMethodSubLookupElement;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.sub.SubLookupElement;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.sub.VariableSubLookupElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiVariable;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
+18
-3
@@ -1,9 +1,24 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.completion.context;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch.context;
|
||||
|
||||
import com.intellij.codeInsight.completion.JavaChainLookupElement;
|
||||
import com.intellij.codeInsight.completion.JavaMethodCallElement;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.GetterLookupSubLookupElement;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.sub.GetterLookupSubLookupElement;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.sub.SubLookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.VariableLookupItem;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
+17
-2
@@ -1,4 +1,19 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.completion.context;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch.context;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -15,7 +30,7 @@ import java.util.*;
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class ContextUtil {
|
||||
public final class ContextUtil {
|
||||
@Nullable
|
||||
public static ChainCompletionContext createContext(final @Nullable PsiType variableType,
|
||||
final @Nullable String variableName,
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.chainsSearch.context;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.containers.FactoryMap;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodIncompleteSignature;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
final class MethodIncompleteSignatureResolver {
|
||||
private MethodIncompleteSignatureResolver() {}
|
||||
|
||||
public static FactoryMap<MethodIncompleteSignature, PsiMethod[]> create(final JavaPsiFacade javaPsiFacade, final GlobalSearchScope scope) {
|
||||
return new FactoryMap<MethodIncompleteSignature, PsiMethod[]>() {
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiMethod[] create(final MethodIncompleteSignature signature) {
|
||||
return resolveNotDeprecated(signature, javaPsiFacade, scope);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static PsiMethod[] resolveNotDeprecated(final MethodIncompleteSignature signature,
|
||||
final JavaPsiFacade javaPsiFacade,
|
||||
final GlobalSearchScope scope) {
|
||||
if (MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME.equals(signature.getName())) {
|
||||
return PsiMethod.EMPTY_ARRAY;
|
||||
}
|
||||
final PsiClass aClass = javaPsiFacade.findClass(signature.getOwner(), scope);
|
||||
if (aClass == null) {
|
||||
return PsiMethod.EMPTY_ARRAY;
|
||||
}
|
||||
final PsiMethod[] methods = aClass.findMethodsByName(signature.getName(), true);
|
||||
final List<PsiMethod> filtered = new ArrayList<PsiMethod>(methods.length);
|
||||
for (final PsiMethod method : methods) {
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC) == signature.isStatic()) {
|
||||
final PsiType returnType = method.getReturnType();
|
||||
if (returnType != null && returnType.equalsToText(signature.getReturnType())) {
|
||||
filtered.add(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filtered.size() > 1) {
|
||||
Collections.sort(filtered, new Comparator<PsiMethod>() {
|
||||
@Override
|
||||
public int compare(final PsiMethod o1, final PsiMethod o2) {
|
||||
return o1.getParameterList().getParametersCount() - o2.getParameterList().getParametersCount();
|
||||
}
|
||||
});
|
||||
}
|
||||
return filtered.toArray(new PsiMethod[filtered.size()]);
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.impl;
|
||||
|
||||
import com.intellij.compiler.compilerOutputIndex.api.index.ClassFilesIndexConfigure;
|
||||
import com.intellij.compiler.compilerOutputIndex.api.index.ClassFilesIndexReaderBase;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.api.ClassFileIndexerFactory;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodIncompleteSignature;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodsUsageIndexerFactory;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodsUsageIndexer;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class MethodsUsageIndexConfigure extends ClassFilesIndexConfigure<String, TObjectIntHashMap<MethodIncompleteSignature>> {
|
||||
|
||||
public static final MethodsUsageIndexConfigure INSTANCE = new MethodsUsageIndexConfigure();
|
||||
|
||||
@Override
|
||||
public String getIndexCanonicalName() {
|
||||
return MethodsUsageIndexer.METHODS_USAGE_INDEX_CANONICAL_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndexVersion() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends ClassFileIndexerFactory> getIndexerBuilderClass() {
|
||||
return MethodsUsageIndexerFactory.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassFilesIndexReaderBase<String, TObjectIntHashMap<MethodIncompleteSignature>> createIndexReader(final Project project) {
|
||||
return new MethodsUsageIndexReader(project, getIndexCanonicalName(), getIndexVersion());
|
||||
}
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.impl;
|
||||
|
||||
import com.intellij.compiler.compilerOutputIndex.api.index.ClassFilesIndexFeaturesHolder;
|
||||
import com.intellij.compiler.compilerOutputIndex.api.index.ClassFilesIndexReaderBase;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import gnu.trove.TObjectIntProcedure;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.classFilesIndex.TObjectIntHashMapExternalizer;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodIncompleteSignature;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.TreeSet;
|
||||
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class MethodsUsageIndexReader extends ClassFilesIndexReaderBase<String, TObjectIntHashMap<MethodIncompleteSignature>> {
|
||||
|
||||
public static MethodsUsageIndexReader getInstance(final Project project) {
|
||||
final MethodsUsageIndexReader instance =
|
||||
ClassFilesIndexFeaturesHolder.getInstance(project).getAvailableIndexReader(MethodsUsageIndexReader.class);
|
||||
if (instance == null) {
|
||||
throw new RuntimeException("couldn't get instance");
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public MethodsUsageIndexReader(final Project project, final String canonicalIndexName, final int version) {
|
||||
//noinspection ConstantConditions
|
||||
super(new EnumeratorStringDescriptor(),
|
||||
new TObjectIntHashMapExternalizer<MethodIncompleteSignature>(MethodIncompleteSignature.createDataExternalizer()),
|
||||
canonicalIndexName, version, project);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TreeSet<UsageIndexValue> getMethods(final String key) {
|
||||
assert myIndex != null;
|
||||
final Collection<TObjectIntHashMap<MethodIncompleteSignature>> unReducedValues = myIndex.getData(key);
|
||||
|
||||
final TObjectIntHashMap<MethodIncompleteSignature> rawValues = new TObjectIntHashMap<MethodIncompleteSignature>();
|
||||
for (final TObjectIntHashMap<MethodIncompleteSignature> unReducedValue : unReducedValues) {
|
||||
unReducedValue.forEachEntry(new TObjectIntProcedure<MethodIncompleteSignature>() {
|
||||
@Override
|
||||
public boolean execute(final MethodIncompleteSignature sign, final int occurrences) {
|
||||
if (!rawValues.adjustValue(sign, occurrences)) {
|
||||
rawValues.put(sign, occurrences);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final TreeSet<UsageIndexValue> values = new TreeSet<UsageIndexValue>();
|
||||
rawValues.forEachEntry(new TObjectIntProcedure<MethodIncompleteSignature>() {
|
||||
@Override
|
||||
public boolean execute(MethodIncompleteSignature sign, int occurrences) {
|
||||
values.add(new UsageIndexValue(sign.toExternalRepresentation(), occurrences));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return values;
|
||||
}
|
||||
|
||||
}
|
||||
+17
-22
@@ -1,11 +1,22 @@
|
||||
package com.intellij.compilerOutputIndex.impl;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compiler.compilerOutputIndex.impl;
|
||||
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodIncompleteSignature;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
@@ -27,22 +38,6 @@ public class UsageIndexValue implements Comparable<UsageIndexValue> {
|
||||
return myMethodIncompleteSignature;
|
||||
}
|
||||
|
||||
public static DataExternalizer<UsageIndexValue> createDataExternalizer() {
|
||||
final DataExternalizer<MethodIncompleteSignature> methodInvocationDataExternalizer = MethodIncompleteSignature.createKeyDescriptor();
|
||||
return new DataExternalizer<UsageIndexValue>() {
|
||||
@Override
|
||||
public void save(final DataOutput out, final UsageIndexValue value) throws IOException {
|
||||
methodInvocationDataExternalizer.save(out, value.myMethodIncompleteSignature);
|
||||
out.writeInt(value.myOccurrences);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UsageIndexValue read(final DataInput in) throws IOException {
|
||||
return new UsageIndexValue(methodInvocationDataExternalizer.read(in), in.readInt());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.completion.lookup;
|
||||
|
||||
import com.intellij.codeInsight.completion.methodChains.search.ChainRelevance;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementDecorator;
|
||||
import com.intellij.codeInsight.lookup.LookupElementPresentation;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public final class WeightableChainLookupElement extends LookupElementDecorator<LookupElement> {
|
||||
private final ChainRelevance myChainRelevance;
|
||||
|
||||
public WeightableChainLookupElement(final @NotNull LookupElement delegate, final ChainRelevance relevance) {
|
||||
super(delegate);
|
||||
myChainRelevance = relevance;
|
||||
}
|
||||
|
||||
public ChainRelevance getChainRelevance() {
|
||||
return myChainRelevance;
|
||||
}
|
||||
}
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.completion.lookup.sub;
|
||||
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public interface SubLookupElement {
|
||||
|
||||
void doImport(final PsiJavaFile javaFile);
|
||||
|
||||
String getInsertString();
|
||||
}
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.completion.lookup.sub;
|
||||
|
||||
import com.intellij.psi.PsiJavaFile;
|
||||
import com.intellij.psi.PsiVariable;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class VariableSubLookupElement implements SubLookupElement {
|
||||
|
||||
private final String myVarName;
|
||||
|
||||
public VariableSubLookupElement(final PsiVariable variable) {
|
||||
myVarName = variable.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doImport(final PsiJavaFile javaFile) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInsertString() {
|
||||
return myVarName;
|
||||
}
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.search;
|
||||
|
||||
import com.intellij.compilerOutputIndex.impl.MethodsUsageIndex;
|
||||
import com.intellij.compilerOutputIndex.impl.UsageIndexValue;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class MethodChainsSearchService {
|
||||
private final static SortedSet EMPTY_SORTED_SET = new TreeSet();
|
||||
|
||||
private final MethodsUsageIndex myMethodsUsageIndex;
|
||||
private final Project myProject;
|
||||
|
||||
public MethodChainsSearchService(final Project project) {
|
||||
myMethodsUsageIndex = MethodsUsageIndex.getInstance(project);
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
public Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@SuppressWarnings("unchecked")
|
||||
public SortedSet<UsageIndexValue> getMethods(final String targetQName) {
|
||||
final TreeSet<UsageIndexValue> value = myMethodsUsageIndex.getValues(targetQName);
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
return EMPTY_SORTED_SET;
|
||||
}
|
||||
|
||||
public PsiManager getPsiManager() {
|
||||
return PsiManager.getInstance(getProject());
|
||||
}
|
||||
}
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
package com.intellij.codeInsight.completion.methodChains.search;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class WeightAware<V> implements Comparable<WeightAware<V>> {
|
||||
private final V myUnderlying;
|
||||
private final int myWeight;
|
||||
|
||||
public WeightAware(final V underlying, final int weight) {
|
||||
myUnderlying = underlying;
|
||||
myWeight = weight;
|
||||
}
|
||||
|
||||
public V getUnderlying() {
|
||||
return myUnderlying;
|
||||
}
|
||||
|
||||
public int getWeight() {
|
||||
return myWeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull final WeightAware<V> that) {
|
||||
final int sub = -getWeight() + that.getWeight();
|
||||
if (sub != 0) {
|
||||
return sub;
|
||||
}
|
||||
return myUnderlying.hashCode() - that.myUnderlying.hashCode();
|
||||
}
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.api.descriptor;
|
||||
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class ArrayListDataExternalizer<E> implements DataExternalizer<List<E>> {
|
||||
private final DataExternalizer<E> myDataExternalizer;
|
||||
|
||||
public ArrayListDataExternalizer(final DataExternalizer<E> dataExternalizer) {
|
||||
myDataExternalizer = dataExternalizer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(final DataOutput out, final List<E> list) throws IOException {
|
||||
out.writeInt(list.size());
|
||||
for (final E element : list) {
|
||||
myDataExternalizer.save(out, element);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<E> read(final DataInput in) throws IOException {
|
||||
final int size = in.readInt();
|
||||
final ArrayList<E> list = new ArrayList<E>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
list.add(myDataExternalizer.read(in));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.api.descriptor;
|
||||
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class HashSetDataExternalizer<K> implements DataExternalizer<Set<K>> {
|
||||
private final DataExternalizer<K> myDataExternalizer;
|
||||
|
||||
public HashSetDataExternalizer(final DataExternalizer<K> myDataExternalizer) {
|
||||
this.myDataExternalizer = myDataExternalizer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(final DataOutput out, final Set<K> set) throws IOException {
|
||||
out.writeInt(set.size());
|
||||
for (final K k : set) {
|
||||
myDataExternalizer.save(out, k);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashSet<K> read(final DataInput in) throws IOException {
|
||||
final int size = in.readInt();
|
||||
final HashSet<K> set = new HashSet<K>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
set.add(myDataExternalizer.read(in));
|
||||
}
|
||||
return set;
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.api.fs;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.asm4.Opcodes;
|
||||
import org.jetbrains.asm4.Type;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public final class AsmUtil implements Opcodes {
|
||||
|
||||
private AsmUtil() {}
|
||||
|
||||
public static boolean isStaticMethodDeclaration(final int access) {
|
||||
return (access & Opcodes.ACC_STATIC) != 0;
|
||||
}
|
||||
|
||||
public static String getQualifiedClassName(final String name) {
|
||||
return asJavaInnerClassQName(Type.getObjectType(name).getClassName());
|
||||
}
|
||||
|
||||
public static String getReturnType(final String desc) {
|
||||
return asJavaInnerClassQName(Type.getReturnType(desc).getClassName());
|
||||
}
|
||||
|
||||
public static String[] getQualifiedClassNames(final String[] classNames, final String... yetAnotherClassNames) {
|
||||
final List<String> qualifiedClassNames = new ArrayList<String>(classNames.length + yetAnotherClassNames.length);
|
||||
for (final String className : classNames) {
|
||||
qualifiedClassNames.add(getQualifiedClassName(className));
|
||||
}
|
||||
for (final String className : yetAnotherClassNames) {
|
||||
if (className != null) {
|
||||
qualifiedClassNames.add(getQualifiedClassName(className));
|
||||
}
|
||||
}
|
||||
return ArrayUtil.toStringArray(qualifiedClassNames);
|
||||
}
|
||||
|
||||
public static String[] getParamsTypes(final String desc) {
|
||||
final Type[] types = Type.getArgumentTypes(desc);
|
||||
final String[] typesAsString = new String[types.length];
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
typesAsString[i] = types[i].getClassName();
|
||||
}
|
||||
return typesAsString;
|
||||
}
|
||||
|
||||
private static String asJavaInnerClassQName(final String byteCodeClassQName) {
|
||||
return StringUtil.replaceChar(byteCodeClassQName, '$', '.');
|
||||
}
|
||||
|
||||
//char
|
||||
//double
|
||||
//float
|
||||
//int
|
||||
//long
|
||||
//short
|
||||
//boolean
|
||||
//byte
|
||||
//void
|
||||
//Object
|
||||
//String
|
||||
//Class
|
||||
private static final Set<String> ASM_PRIMITIVE_TYPES = ContainerUtil.newHashSet("C", "D", "F", "I", "J", "S", "Z", "B", "V",
|
||||
"Ljava/lang/Object;",
|
||||
"Ljava/lang/String;",
|
||||
"Ljava/lang/Class;");
|
||||
|
||||
public static boolean isPrimitive(final String asmType) {
|
||||
return ASM_PRIMITIVE_TYPES.contains(asmType);
|
||||
}
|
||||
|
||||
public static boolean isPrimitiveOrArray(final String asmType) {
|
||||
if (asmType.startsWith("[")) {
|
||||
return true;
|
||||
}
|
||||
return isPrimitive(asmType);
|
||||
}
|
||||
}
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.api.fs;
|
||||
|
||||
import com.intellij.openapi.compiler.CompilerPaths;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public final class CompilerOutputFilesUtil {
|
||||
|
||||
private CompilerOutputFilesUtil() {}
|
||||
|
||||
public final static String CLASS_FILES_SUFFIX = ".class";
|
||||
|
||||
public static void iterateProjectClassFiles(@NotNull final Project project, @NotNull final Consumer<File> fileConsumer) {
|
||||
for (final Module module : ModuleManager.getInstance(project).getModules()) {
|
||||
iterateModuleClassFiles(module, fileConsumer);
|
||||
}
|
||||
}
|
||||
|
||||
public static void iterateModuleClassFiles(@NotNull final Module module, @NotNull final Consumer<File> fileConsumer) {
|
||||
final VirtualFile moduleOutputDirectory = CompilerPaths.getModuleOutputDirectory(module, false);
|
||||
if (moduleOutputDirectory == null) {
|
||||
return;
|
||||
}
|
||||
final String canonicalPath = moduleOutputDirectory.getCanonicalPath();
|
||||
if (canonicalPath == null) {
|
||||
return;
|
||||
}
|
||||
final File root = new File(canonicalPath);
|
||||
iterateClassFilesOverRoot(root, fileConsumer);
|
||||
}
|
||||
|
||||
public static void iterateClassFilesOverRoot(@NotNull final File file, final Consumer<File> fileConsumer) {
|
||||
iterateClassFilesOverRoot(file, fileConsumer, new HashSet<File>());
|
||||
}
|
||||
|
||||
private static void iterateClassFilesOverRoot(@NotNull final File file, final Consumer<File> fileConsumer, final Set<File> visited) {
|
||||
if (file.isDirectory()) {
|
||||
final File[] files = file.listFiles();
|
||||
if (files != null) {
|
||||
for (final File childFile : files) {
|
||||
if (visited.add(childFile)) {
|
||||
iterateClassFilesOverRoot(childFile.getAbsoluteFile(), fileConsumer, visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (file.getName().endsWith(CLASS_FILES_SUFFIX)) {
|
||||
fileConsumer.consume(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.api.fs;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.Consumer;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public interface FileVisitorService {
|
||||
|
||||
interface Visitor {
|
||||
void visit(File file);
|
||||
}
|
||||
|
||||
void visit(final Consumer<File> visitor);
|
||||
|
||||
class ProjectClassFiles implements FileVisitorService {
|
||||
private final Project myProject;
|
||||
|
||||
public ProjectClassFiles(final Project project) {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(final Consumer<File> visitor) {
|
||||
CompilerOutputFilesUtil.iterateProjectClassFiles(myProject, visitor);
|
||||
}
|
||||
}
|
||||
|
||||
class DirectoryClassFiles implements FileVisitorService {
|
||||
private final File myDir;
|
||||
|
||||
public DirectoryClassFiles(final File dir) {
|
||||
if (!dir.isDirectory()) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
myDir = dir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(final Consumer<File> visitor) {
|
||||
//noinspection ConstantConditions
|
||||
for (final File file : myDir.listFiles()) {
|
||||
if (file.getName().endsWith(CompilerOutputFilesUtil.CLASS_FILES_SUFFIX)) {
|
||||
visitor.consume(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-170
@@ -1,170 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.api.indexer;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Factory;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.ThrowableComputable;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.indexing.*;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.IOUtil;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
import com.intellij.util.io.PersistentHashMap;
|
||||
import org.jetbrains.asm4.tree.ClassNode;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static com.intellij.util.indexing.IndexInfrastructure.*;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public abstract class CompilerOutputBaseIndex<K, V> {
|
||||
public final static ExtensionPointName<CompilerOutputBaseIndex> EXTENSION_POINT_NAME =
|
||||
ExtensionPointName.create("com.intellij.java.compilerOutputIndex");
|
||||
|
||||
private final static Logger LOG = Logger.getInstance(CompilerOutputBaseIndex.class);
|
||||
private final KeyDescriptor<K> myKeyDescriptor;
|
||||
private final DataExternalizer<V> myValueExternalizer;
|
||||
protected volatile MapReduceIndex<K, V, ClassNode> myIndex;
|
||||
|
||||
protected final Project myProject;
|
||||
|
||||
protected volatile AtomicBoolean myInitialized = new AtomicBoolean(false);
|
||||
|
||||
public CompilerOutputBaseIndex(final KeyDescriptor<K> keyDescriptor, final DataExternalizer<V> valueExternalizer, final Project project) {
|
||||
myProject = project;
|
||||
myKeyDescriptor = keyDescriptor;
|
||||
myValueExternalizer = valueExternalizer;
|
||||
}
|
||||
|
||||
public final boolean initIfNeed() {
|
||||
if (myInitialized.compareAndSet(false, true)) {
|
||||
final MapReduceIndex<K, V, ClassNode> index;
|
||||
final Ref<Boolean> rewriteIndex = new Ref<Boolean>(false);
|
||||
try {
|
||||
final ID<K, V> indexId = getIndexId();
|
||||
if (!IndexInfrastructure.getIndexRootDir(indexId).exists()) {
|
||||
rewriteIndex.set(true);
|
||||
}
|
||||
final File storageFile = getStorageFile(indexId);
|
||||
final MapIndexStorage<K, V> indexStorage = IOUtil.openCleanOrResetBroken(
|
||||
new ThrowableComputable<MapIndexStorage<K, V>, IOException>() {
|
||||
@Override
|
||||
public MapIndexStorage<K, V> compute() throws IOException {
|
||||
return new MapIndexStorage<K, V>(storageFile, myKeyDescriptor, myValueExternalizer, 1024);
|
||||
}
|
||||
},
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
IOUtil.deleteAllFilesStartingWith(storageFile);
|
||||
rewriteIndex.set(true);
|
||||
}
|
||||
}
|
||||
);
|
||||
index = new MapReduceIndex<K, V, ClassNode>(indexId, getIndexer(), indexStorage);
|
||||
index.setInputIdToDataKeysIndex(new Factory<PersistentHashMap<Integer, Collection<K>>>() {
|
||||
@Override
|
||||
public PersistentHashMap<Integer, Collection<K>> create() {
|
||||
try {
|
||||
return IOUtil.openCleanOrResetBroken(
|
||||
new ThrowableComputable<PersistentHashMap<Integer, Collection<K>>, IOException>() {
|
||||
@Override
|
||||
public PersistentHashMap<Integer, Collection<K>> compute() throws IOException {
|
||||
return FileBasedIndexImpl.createIdToDataKeysIndex(indexId, myKeyDescriptor, new MemoryIndexStorage<K, V>(indexStorage));
|
||||
}
|
||||
},
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FileUtil.delete(getInputIndexStorageFile(getIndexId()));
|
||||
rewriteIndex.set(true);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException("couldn't create index", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
final File versionFile = getVersionFile(indexId);
|
||||
if (versionFile.exists()) {
|
||||
if (versionDiffers(versionFile, getVersion())) {
|
||||
rewriteVersion(versionFile, getVersion());
|
||||
rewriteIndex.set(true);
|
||||
try {
|
||||
LOG.info("clearing index for updating index version");
|
||||
index.clear();
|
||||
}
|
||||
catch (StorageException e) {
|
||||
LOG.error("couldn't clear index for reinitializing", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (versionFile.createNewFile()) {
|
||||
rewriteVersion(versionFile, getVersion());
|
||||
rewriteIndex.set(true);
|
||||
}
|
||||
else {
|
||||
LOG.error(String.format("problems while access to index version file to index %s ", indexId));
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error("couldn't initialize index", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
myIndex = index;
|
||||
return rewriteIndex.get();
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract ID<K, V> getIndexId();
|
||||
|
||||
protected abstract int getVersion();
|
||||
|
||||
protected abstract DataIndexer<K, V, ClassNode> getIndexer();
|
||||
|
||||
public final void closeIfInitialized() {
|
||||
if (myInitialized.get()) {
|
||||
if (myIndex != null) {
|
||||
try {
|
||||
myIndex.flush();
|
||||
}
|
||||
catch (StorageException ignored) {
|
||||
}
|
||||
myIndex.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void update(final int id, final ClassNode inputData) {
|
||||
final Boolean result = myIndex.update(id, inputData).compute();
|
||||
if (result == Boolean.FALSE) throw new RuntimeException();
|
||||
}
|
||||
|
||||
public final void clearIfInitialized() {
|
||||
if (myInitialized.get()) {
|
||||
try {
|
||||
myIndex.clear();
|
||||
}
|
||||
catch (StorageException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected final ID<K, V> generateIndexId(final String indexName) {
|
||||
return CompilerOutputIndexUtil.generateIndexId(indexName, myProject);
|
||||
}
|
||||
}
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compilerOutputIndex.api.indexer;
|
||||
|
||||
import com.intellij.compilerOutputIndex.impl.MethodsUsageIndex;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.registry.RegistryValue;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public enum CompilerOutputIndexFeature {
|
||||
METHOD_CHAINS_COMPLETION("completion.enable.relevant.method.chain.suggestions", ContainerUtil
|
||||
.<Class<? extends CompilerOutputBaseIndex>>newArrayList(MethodsUsageIndex.class));
|
||||
|
||||
@NotNull
|
||||
private final String myKey;
|
||||
@NotNull
|
||||
private final Collection<Class<? extends CompilerOutputBaseIndex>> myRequiredIndexes;
|
||||
|
||||
CompilerOutputIndexFeature(@NotNull final String key,
|
||||
@NotNull final Collection<Class<? extends CompilerOutputBaseIndex>> requiredIndexes) {
|
||||
myKey = key;
|
||||
myRequiredIndexes = requiredIndexes;
|
||||
}
|
||||
|
||||
CompilerOutputIndexFeature(@NotNull final String key, @NotNull final Class<? extends CompilerOutputBaseIndex> requiredIndex) {
|
||||
this(key, Collections.<Class<? extends CompilerOutputBaseIndex>>singleton(requiredIndex));
|
||||
}
|
||||
|
||||
public RegistryValue getRegistryValue() {
|
||||
return Registry.get(myKey);
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return Registry.is(myKey);
|
||||
}
|
||||
|
||||
public void enable() {
|
||||
getRegistryValue().setValue(true);
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
getRegistryValue().setValue(false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<Class<? extends CompilerOutputBaseIndex>> getRequiredIndexes() {
|
||||
return myRequiredIndexes;
|
||||
}
|
||||
}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.api.indexer;
|
||||
|
||||
import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.indexing.ID;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public final class CompilerOutputIndexUtil {
|
||||
private CompilerOutputIndexUtil() {}
|
||||
|
||||
public static <K, V> ID<K, V> generateIndexId(final String indexName, final Project project) {
|
||||
final String hash = Integer.toHexString(project.getBasePath().hashCode());
|
||||
return ID.create(String.format("compilerOutputIndex.%s.%s", indexName, hash));
|
||||
}
|
||||
}
|
||||
-387
@@ -1,387 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.api.indexer;
|
||||
|
||||
import com.intellij.compilerOutputIndex.api.fs.CompilerOutputFilesUtil;
|
||||
import com.intellij.compilerOutputIndex.api.fs.FileVisitorService;
|
||||
import com.intellij.openapi.compiler.CompilationStatusAdapter;
|
||||
import com.intellij.openapi.compiler.CompilerManager;
|
||||
import com.intellij.openapi.components.AbstractProjectComponent;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.ThrowableComputable;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.registry.RegistryValue;
|
||||
import com.intellij.openapi.util.registry.RegistryValueListener;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.containers.ConcurrentHashSet;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.indexing.ID;
|
||||
import com.intellij.util.indexing.IndexInfrastructure;
|
||||
import com.intellij.util.io.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
import org.jetbrains.asm4.ClassReader;
|
||||
import org.jetbrains.asm4.Opcodes;
|
||||
import org.jetbrains.asm4.tree.ClassNode;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class CompilerOutputIndexer extends AbstractProjectComponent {
|
||||
private final static Logger LOG = Logger.getInstance(CompilerOutputIndexer.class);
|
||||
|
||||
public final static String TITLE = "Compiler output indexer in progress...";
|
||||
|
||||
private final Map<String, CompilerOutputBaseIndex> myIndexTypeQNameToIndex = new HashMap<String, CompilerOutputBaseIndex>();
|
||||
private volatile PersistentHashMap<String, Long> myFileTimestampsIndex;
|
||||
private volatile PersistentEnumeratorDelegate<String> myFileEnumerator;
|
||||
|
||||
private final Lock myLock = new ReentrantLock();
|
||||
private final AtomicBoolean myInProgress = new AtomicBoolean(false);
|
||||
@SuppressWarnings("SetReplaceableByEnumSet")
|
||||
private final Set<CompilerOutputIndexFeature> myCurrentEnabledFeatures = new ConcurrentHashSet<CompilerOutputIndexFeature>();
|
||||
private final AtomicBoolean myInitialized = new AtomicBoolean(false);
|
||||
|
||||
public static CompilerOutputIndexer getInstance(final Project project) {
|
||||
return project.getComponent(CompilerOutputIndexer.class);
|
||||
}
|
||||
|
||||
protected CompilerOutputIndexer(final Project project) {
|
||||
super(project);
|
||||
}
|
||||
|
||||
private ID<String, Long> getFileTimestampsIndexId() {
|
||||
return CompilerOutputIndexUtil.generateIndexId("ProjectCompilerOutputClassFilesTimestamps", myProject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void projectOpened() {
|
||||
for (final CompilerOutputIndexFeature feature : CompilerOutputIndexFeature.values()) {
|
||||
final RegistryValue registryValue = feature.getRegistryValue();
|
||||
registryValue.addListener(new RegistryValueListener.Adapter() {
|
||||
@Override
|
||||
public void afterValueChanged(final RegistryValue rawValue) {
|
||||
final Collection<Class<? extends CompilerOutputBaseIndex>> requiredIndexes = feature.getRequiredIndexes();
|
||||
if (rawValue.asBoolean()) {
|
||||
if (myCurrentEnabledFeatures.add(feature)) {
|
||||
if (myCurrentEnabledFeatures.size() == 1) {
|
||||
doEnable();
|
||||
}
|
||||
addIndexes(requiredIndexes);
|
||||
}
|
||||
}
|
||||
else {
|
||||
removeIndexes(requiredIndexes);
|
||||
myCurrentEnabledFeatures.remove(feature);
|
||||
}
|
||||
}
|
||||
}, myProject);
|
||||
if (registryValue.asBoolean()) {
|
||||
if (myCurrentEnabledFeatures.add(feature)) {
|
||||
if (myCurrentEnabledFeatures.size() == 1) {
|
||||
doEnable();
|
||||
}
|
||||
addIndexes(feature.getRequiredIndexes());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CompilerOutputBaseIndex[] getAllIndexes() {
|
||||
return Extensions.getExtensions(CompilerOutputBaseIndex.EXTENSION_POINT_NAME, myProject);
|
||||
}
|
||||
|
||||
private void addIndexes(final Collection<Class<? extends CompilerOutputBaseIndex>> indexes) {
|
||||
final Collection<CompilerOutputBaseIndex> indexesToReindex = new ArrayList<CompilerOutputBaseIndex>();
|
||||
for (final Class<? extends CompilerOutputBaseIndex> indexClass : indexes) {
|
||||
final String canonicalName = indexClass.getCanonicalName();
|
||||
if (!myIndexTypeQNameToIndex.containsKey(canonicalName)) {
|
||||
final CompilerOutputBaseIndex index = Extensions.findExtension(CompilerOutputBaseIndex.EXTENSION_POINT_NAME, myProject, indexClass);
|
||||
myIndexTypeQNameToIndex.put(canonicalName, index);
|
||||
if (index.initIfNeed()) {
|
||||
indexesToReindex.add(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!indexesToReindex.isEmpty()) {
|
||||
if (myInProgress.compareAndSet(false, true)) {
|
||||
ProgressManager.getInstance().run(new Task.Backgroundable(myProject, TITLE) {
|
||||
@Override
|
||||
public void onCancel() {
|
||||
myInProgress.set(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
myInProgress.set(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(@NotNull final ProgressIndicator indicator) {
|
||||
reindex(new FileVisitorService.ProjectClassFiles(CompilerOutputIndexer.this.myProject), indexesToReindex, true, indicator);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeIndexes(final Collection<Class<? extends CompilerOutputBaseIndex>> indexes) {
|
||||
final Set<Class<? extends CompilerOutputBaseIndex>> toRemove = ContainerUtil.newHashSet(indexes);
|
||||
for (final CompilerOutputIndexFeature feature : CompilerOutputIndexFeature.values()) {
|
||||
if (feature.getRegistryValue().asBoolean()) {
|
||||
for (final Class<? extends CompilerOutputBaseIndex> aClass : feature.getRequiredIndexes()) {
|
||||
toRemove.remove(aClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (final Class aClass : toRemove) {
|
||||
myIndexTypeQNameToIndex.remove(aClass.getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
private void doEnable() {
|
||||
if (myInitialized.compareAndSet(false, true)) {
|
||||
initTimestampIndex();
|
||||
final File storageFile =
|
||||
IndexInfrastructure.getStorageFile(CompilerOutputIndexUtil.generateIndexId("compilerOutputIndexFileId.enum", myProject));
|
||||
|
||||
try {
|
||||
myFileEnumerator = IOUtil.openCleanOrResetBroken(new ThrowableComputable<PersistentEnumeratorDelegate<String>, IOException>() {
|
||||
@Override
|
||||
public PersistentEnumeratorDelegate<String> compute() throws IOException {
|
||||
return new PersistentEnumeratorDelegate<String>(storageFile, new EnumeratorStringDescriptor(), 2048);
|
||||
}
|
||||
}, storageFile);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
CompilerManager.getInstance(myProject).addCompilationStatusListener(new CompilationStatusAdapter() {
|
||||
@Override
|
||||
public void fileGenerated(final String outputRoot, final String relativePath) {
|
||||
if (StringUtil.endsWith(relativePath, CompilerOutputFilesUtil.CLASS_FILES_SUFFIX) && !myCurrentEnabledFeatures.isEmpty()) {
|
||||
try {
|
||||
doIndexing(new File(outputRoot, relativePath), myIndexTypeQNameToIndex.values(), false, null);
|
||||
}
|
||||
catch (ProcessCanceledException e0) {
|
||||
throw e0;
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, myProject);
|
||||
}
|
||||
}
|
||||
|
||||
private void initTimestampIndex() {
|
||||
final File storageFile = IndexInfrastructure.getStorageFile(getFileTimestampsIndexId());
|
||||
try {
|
||||
myFileTimestampsIndex = IOUtil.openCleanOrResetBroken(
|
||||
new ThrowableComputable<PersistentHashMap<String, Long>, IOException>() {
|
||||
@Override
|
||||
public PersistentHashMap<String, Long> compute() throws IOException {
|
||||
return new PersistentHashMap<String, Long>(storageFile,
|
||||
new EnumeratorStringDescriptor(), new DataExternalizer<Long>() {
|
||||
@Override
|
||||
public void save(final DataOutput out, final Long value) throws IOException {
|
||||
out.writeLong(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long read(final DataInput in) throws IOException {
|
||||
return in.readLong();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
FileUtil.delete(IndexInfrastructure.getIndexRootDir(getFileTimestampsIndexId()));
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("Timestamps index not initialized", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void reindex(final FileVisitorService visitorService, final @NotNull ProgressIndicator indicator) {
|
||||
reindex(visitorService, myIndexTypeQNameToIndex.values(), false, indicator);
|
||||
}
|
||||
|
||||
private void reindex(final FileVisitorService visitorService,
|
||||
final @NotNull Collection<CompilerOutputBaseIndex> indexes,
|
||||
final boolean force,
|
||||
final @NotNull ProgressIndicator indicator) {
|
||||
myLock.lock();
|
||||
try {
|
||||
indicator.setText(TITLE);
|
||||
visitorService.visit(new Consumer<File>() {
|
||||
@Override
|
||||
public void consume(final File file) {
|
||||
try {
|
||||
doIndexing(file, indexes, force, indicator);
|
||||
}
|
||||
catch (ProcessCanceledException e0) {
|
||||
throw e0;
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
finally {
|
||||
myLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
|
||||
private void doIndexing(@NotNull final File file,
|
||||
@NotNull final Collection<CompilerOutputBaseIndex> indexes,
|
||||
final boolean force,
|
||||
@Nullable final ProgressIndicator indicator) {
|
||||
final String filePath;
|
||||
try {
|
||||
filePath = file.getCanonicalPath();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
return;
|
||||
}
|
||||
final Long timestamp;
|
||||
ProgressManager.checkCanceled();
|
||||
final long currentTimeStamp = file.lastModified();
|
||||
if (force || (timestamp = getTimestamp(filePath)) == null || timestamp != currentTimeStamp) {
|
||||
putTimestamp(filePath, currentTimeStamp);
|
||||
final ClassNode inputData = new ClassNode(Opcodes.ASM4);
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = new FileInputStream(file);
|
||||
final ClassReader reader = new ClassReader(is);
|
||||
reader.accept(inputData, ClassReader.EXPAND_FRAMES);
|
||||
}
|
||||
catch (IOException e) {
|
||||
removeTimestamp(filePath);
|
||||
return;
|
||||
}
|
||||
finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (indicator != null) {
|
||||
indicator.setText2(filePath);
|
||||
}
|
||||
final int id = myFileEnumerator.enumerate(filePath);
|
||||
for (final CompilerOutputBaseIndex index : indexes) {
|
||||
index.update(id, inputData);
|
||||
}
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
LOG.error(String.format("can't index file: %s", file.getAbsolutePath()), e);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(String.format("can't index file: %s", file.getAbsolutePath()), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
try {
|
||||
myFileTimestampsIndex.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
initTimestampIndex();
|
||||
for (final CompilerOutputBaseIndex index : getAllIndexes()) {
|
||||
index.clearIfInitialized();
|
||||
}
|
||||
}
|
||||
|
||||
private void removeTimestamp(final String fileId) {
|
||||
try {
|
||||
myFileTimestampsIndex.remove(fileId);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Long getTimestamp(final String fileName) {
|
||||
try {
|
||||
return myFileTimestampsIndex.get(fileName);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
|
||||
private void putTimestamp(final String fileName, final long timestamp) {
|
||||
try {
|
||||
myFileTimestampsIndex.put(fileName, timestamp);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void projectClosed() {
|
||||
if (myInitialized.get()) {
|
||||
for (final CompilerOutputBaseIndex index : getAllIndexes()) {
|
||||
index.closeIfInitialized();
|
||||
}
|
||||
try {
|
||||
myFileTimestampsIndex.close();
|
||||
myFileEnumerator.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public void removeIndexes() {
|
||||
for (final CompilerOutputBaseIndex index : getAllIndexes()) {
|
||||
FileUtil.delete(IndexInfrastructure.getIndexRootDir(index.getIndexId()));
|
||||
}
|
||||
FileUtil.delete(IndexInfrastructure.getIndexRootDir(getFileTimestampsIndexId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* try to find index with corresponding class only in currently enabled indexes
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends CompilerOutputBaseIndex> T getIndex(final Class<T> tClass) {
|
||||
final CompilerOutputBaseIndex index = myIndexTypeQNameToIndex.get(tClass.getCanonicalName());
|
||||
if (index == null) {
|
||||
throw new RuntimeException(String.format("index class with name %s not found", tClass.getName()));
|
||||
}
|
||||
return (T)index;
|
||||
}
|
||||
}
|
||||
-56
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.compilerOutputIndex.impl;
|
||||
|
||||
import com.google.common.collect.HashMultiset;
|
||||
import com.google.common.collect.Multiset;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class GuavaHashMultiSetExternalizer<K> implements DataExternalizer<Multiset<K>> {
|
||||
private final DataExternalizer<K> myKeyDataExternalizer;
|
||||
|
||||
public GuavaHashMultiSetExternalizer(final DataExternalizer<K> keyDataExternalizer) {
|
||||
myKeyDataExternalizer = keyDataExternalizer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(final DataOutput out, final Multiset<K> multiset) throws IOException {
|
||||
final Set<Multiset.Entry<K>> entries = multiset.entrySet();
|
||||
out.writeInt(entries.size());
|
||||
for (final Multiset.Entry<K> entry : entries) {
|
||||
myKeyDataExternalizer.save(out, entry.getElement());
|
||||
out.writeInt(entry.getCount());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Multiset<K> read(final DataInput in) throws IOException {
|
||||
final int size = in.readInt();
|
||||
final Multiset<K> multiset = HashMultiset.create(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
multiset.add(myKeyDataExternalizer.read(in), in.readInt());
|
||||
}
|
||||
return multiset;
|
||||
}
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.impl;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class MethodIncompleteSignatureChain {
|
||||
private final List<MethodIncompleteSignature> myMethodIncompleteSignatures;
|
||||
|
||||
public MethodIncompleteSignatureChain(final List<MethodIncompleteSignature> methodIncompleteSignatures) {
|
||||
myMethodIncompleteSignatures = methodIncompleteSignatures;
|
||||
}
|
||||
|
||||
public List<MethodIncompleteSignature> list() {
|
||||
return myMethodIncompleteSignatures;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return myMethodIncompleteSignatures.isEmpty();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public MethodIncompleteSignature getFirstInvocation() {
|
||||
final int size = myMethodIncompleteSignatures.size();
|
||||
return size == 0 ? null : myMethodIncompleteSignatures.get(0);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public MethodIncompleteSignature getLastInvocation() {
|
||||
final int size = myMethodIncompleteSignatures.size();
|
||||
return size == 0 ? null : myMethodIncompleteSignatures.get(size -1);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return myMethodIncompleteSignatures.size();
|
||||
}
|
||||
|
||||
public MethodIncompleteSignature get(final int index) {
|
||||
return myMethodIncompleteSignatures.get(index);
|
||||
}
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
package com.intellij.compilerOutputIndex.impl;
|
||||
|
||||
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.CompilerOutputBaseIndex;
|
||||
import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ModifiableRootModel;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.ModuleRootModel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.indexing.DataIndexer;
|
||||
import com.intellij.util.indexing.ID;
|
||||
import com.intellij.util.indexing.StorageException;
|
||||
import com.intellij.util.indexing.ValueContainer;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.asm4.ClassVisitor;
|
||||
import org.jetbrains.asm4.MethodVisitor;
|
||||
import org.jetbrains.asm4.Opcodes;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.asm4.tree.ClassNode;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeSet;
|
||||
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class MethodsUsageIndex extends CompilerOutputBaseIndex<String, Multiset<MethodIncompleteSignature>> {
|
||||
|
||||
public static MethodsUsageIndex getInstance(final Project project) {
|
||||
return CompilerOutputIndexer.getInstance(project).getIndex(MethodsUsageIndex.class);
|
||||
}
|
||||
|
||||
public MethodsUsageIndex(final Project project) {
|
||||
super(new EnumeratorStringDescriptor(),
|
||||
new GuavaHashMultiSetExternalizer<MethodIncompleteSignature>(MethodIncompleteSignature.createKeyDescriptor()), project);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DataIndexer<String, Multiset<MethodIncompleteSignature>, ClassNode> getIndexer() {
|
||||
return new DataIndexer<String, Multiset<MethodIncompleteSignature>, ClassNode>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<String, Multiset<MethodIncompleteSignature>> map(final ClassNode inputData) {
|
||||
final Map<String, Multiset<MethodIncompleteSignature>> map = new HashMap<String, Multiset<MethodIncompleteSignature>>();
|
||||
final MethodVisitor methodVisitor = new MethodVisitor(Opcodes.ASM4) {
|
||||
@Override
|
||||
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
|
||||
final Type returnType = Type.getReturnType(desc);
|
||||
if (MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME.equals(name) ||
|
||||
AsmUtil.isPrimitiveOrArray(returnType.getDescriptor())) {
|
||||
return;
|
||||
}
|
||||
final String returnClassName = returnType.getInternalName();
|
||||
final boolean isStatic = opcode == Opcodes.INVOKESTATIC;
|
||||
if (!owner.equals(returnClassName) || isStatic) {
|
||||
addToIndex(map, returnClassName, new MethodIncompleteSignature(owner, returnClassName, name, isStatic));
|
||||
}
|
||||
}
|
||||
};
|
||||
inputData.accept(new ClassVisitor(Opcodes.ASM4) {
|
||||
@Override
|
||||
public MethodVisitor visitMethod(final int access,
|
||||
final String name,
|
||||
final String desc,
|
||||
final String signature,
|
||||
final String[] exceptions) {
|
||||
return methodVisitor;
|
||||
}
|
||||
});
|
||||
return map;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ID<String, Multiset<MethodIncompleteSignature>> getIndexId() {
|
||||
return generateIndexId("MethodsUsage");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getVersion() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public TreeSet<UsageIndexValue> getValues(final String 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 (final StorageException e) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private static void addToIndex(final Map<String, Multiset<MethodIncompleteSignature>> map,
|
||||
final String internalClassName,
|
||||
final MethodIncompleteSignature mi) {
|
||||
final String className = AsmUtil.getQualifiedClassName(internalClassName);
|
||||
Multiset<MethodIncompleteSignature> occurrences = map.get(className);
|
||||
if (occurrences == null) {
|
||||
occurrences = HashMultiset.create();
|
||||
map.put(className, occurrences);
|
||||
}
|
||||
occurrences.add(mi);
|
||||
}
|
||||
|
||||
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().toExternalRepresentation(), entry.getCount()));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
|
||||
|
||||
class PsiMethod implements PsiElement {
|
||||
}
|
||||
|
||||
interface PsiElement {
|
||||
}
|
||||
|
||||
class PsiClass {
|
||||
public PsiMethod findMethodByName(String methodName) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class TestCompletion {
|
||||
|
||||
PsiClass c;
|
||||
|
||||
public void method() {
|
||||
PsiElement element = <caret>
|
||||
}
|
||||
}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class TestIndex {
|
||||
|
||||
public void statMethod(PsiClass c) {
|
||||
c.findMethodByName("asd");
|
||||
c.findMethodByName("asd");
|
||||
c.findMethodByName("asd");
|
||||
c.findMethodByName("asd");
|
||||
}
|
||||
}
|
||||
|
||||
class PsiMethod implements PsiElement {
|
||||
}
|
||||
|
||||
interface PsiElement {
|
||||
}
|
||||
|
||||
class PsiClass {
|
||||
public PsiMethod findMethodByName(String methodName) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
|
||||
|
||||
class PsiMethod implements PsiElement {
|
||||
}
|
||||
|
||||
interface PsiElement {
|
||||
}
|
||||
|
||||
class PsiClass {
|
||||
public PsiMethod findMethodByName(String methodName) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class TestCompletion {
|
||||
|
||||
PsiClass c;
|
||||
|
||||
public void method() {
|
||||
PsiElement element = <caret>
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class TestIndex {
|
||||
|
||||
public void statMethod(PsiClass c) {
|
||||
c.findMethodByName("asd");
|
||||
c.findMethodByName("asd");
|
||||
c.findMethodByName("asd");
|
||||
c.findMethodByName("asd");
|
||||
}
|
||||
}
|
||||
|
||||
class PsiMethod implements PsiElement {
|
||||
}
|
||||
|
||||
interface PsiElement {
|
||||
}
|
||||
|
||||
class PsiClass {
|
||||
public PsiMethod findMethodByName(String methodName) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
import java.jang.String;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
|
||||
class PsiElement {
|
||||
}
|
||||
|
||||
class PsiClass extends PsiElement {
|
||||
}
|
||||
|
||||
class PsiElementFactory {
|
||||
public PsiClass createClass() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class TestCompletion {
|
||||
|
||||
public void method(PsiElementFactory f) {
|
||||
PsiElement e = <caret>
|
||||
}
|
||||
}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class TestIndex {
|
||||
|
||||
public void statMethod(PsiElementFactory f) {
|
||||
f.createClass();
|
||||
f.createClass();
|
||||
f.createClass();
|
||||
f.createClass();
|
||||
f.createClass();
|
||||
f.createClass();
|
||||
}
|
||||
}
|
||||
|
||||
class PsiElement {
|
||||
}
|
||||
|
||||
class PsiClass extends PsiElement {
|
||||
}
|
||||
|
||||
class PsiElementFactory {
|
||||
public PsiClass createClass() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+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.
|
||||
*/
|
||||
import java.jang.String;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
|
||||
class PsiElement {
|
||||
}
|
||||
|
||||
class PsiClass extends PsiElement {
|
||||
}
|
||||
|
||||
class PsiElementFactory {
|
||||
public PsiClass createClass() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class TestCompletion {
|
||||
|
||||
public void method(PsiElementFactory f) {
|
||||
PsiElement e = <caret>
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
*/
|
||||
public class TestIndex {
|
||||
|
||||
public void statMethod(PsiElementFactory f) {
|
||||
f.createClass();
|
||||
f.createClass();
|
||||
f.createClass();
|
||||
f.createClass();
|
||||
f.createClass();
|
||||
f.createClass();
|
||||
}
|
||||
}
|
||||
|
||||
class PsiElement {
|
||||
}
|
||||
|
||||
class PsiClass extends PsiElement {
|
||||
}
|
||||
|
||||
class PsiElementFactory {
|
||||
public PsiClass createClass() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+51
-13
@@ -1,30 +1,68 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.openapi.compiler.CompilerMessage;
|
||||
import com.intellij.openapi.compiler.CompilerMessageCategory;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.CompilerTester;
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
|
||||
import com.sun.tools.javac.Main;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public abstract class AbstractCompilerAwareTest extends JavaCodeInsightFixtureTestCase {
|
||||
protected final File compileData(final String testCaseName, final String fileToCompile) {
|
||||
final File compilerOutput = getCompilerOutputPath(testCaseName);
|
||||
assertEquals(Main.compile(
|
||||
new String[]{"-g:vars", "-d", compilerOutput.getAbsolutePath(), String.format("%s/%s/%s", getTestDataPath(), testCaseName, fileToCompile)}), 0);
|
||||
return compilerOutput;
|
||||
private CompilerTester myCompilerTester;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myCompilerTester = new CompilerTester(true, myModule);
|
||||
}
|
||||
|
||||
private static File getCompilerOutputPath(final String testCaseName) {
|
||||
try {
|
||||
return FileUtil.createTempDirectory(testCaseName, "_compiled");
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
myCompilerTester.tearDown();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
protected final void compileAndIndexData(final String... fileNames) {
|
||||
final VirtualFile[] filesToCompile =
|
||||
ContainerUtil.map2Array(ContainerUtil.list(fileNames), new VirtualFile[fileNames.length], new Function<String, VirtualFile>() {
|
||||
@Override
|
||||
public VirtualFile fun(final String fileName) {
|
||||
try {
|
||||
return myFixture.addFileToProject(fileName, FileUtil.loadFile(new File(getTestDataPath() + getName() + "/" + fileName)))
|
||||
.getVirtualFile();
|
||||
}
|
||||
catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
for (final CompilerMessage compilerMessage : myCompilerTester.rebuild()) {
|
||||
assertNotSame(CompilerMessageCategory.ERROR, compilerMessage.getCategory());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+32
-37
@@ -1,19 +1,16 @@
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.MethodsChainsCompletionContributor;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.lookup.ChainCompletionMethodCallLookupElement;
|
||||
import com.intellij.codeInsight.completion.methodChains.completion.lookup.WeightableChainLookupElement;
|
||||
import com.intellij.codeInsight.completion.methodChains.search.ChainRelevance;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.compilerOutputIndex.api.fs.FileVisitorService;
|
||||
import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexFeature;
|
||||
import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
|
||||
import com.intellij.compiler.compilerOutputIndex.api.index.ClassFilesIndexFeature;
|
||||
import com.intellij.compiler.compilerOutputIndex.api.index.ClassFilesIndexFeaturesHolder;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.ChainRelevance;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.MethodsChainsCompletionContributor;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.ChainCompletionMethodCallLookupElement;
|
||||
import com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.lookup.WeightableChainLookupElement;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.mock.MockProgressIndicator;
|
||||
import com.intellij.util.SmartList;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -22,19 +19,18 @@ import java.util.List;
|
||||
public class MethodChainsCompletionTest extends AbstractCompilerAwareTest {
|
||||
private final static String TEST_INDEX_FILE_NAME = "TestIndex.java";
|
||||
private final static String TEST_COMPLETION_FILE_NAME = "TestCompletion.java";
|
||||
|
||||
private final static String BEFORE_COMPLETION_FILE = "BeforeCompletion.java";
|
||||
private final static String AFTER_COMPLETION_FILE = "AfterCompletion.java";
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
CompilerOutputIndexFeature.METHOD_CHAINS_COMPLETION.enable();
|
||||
ClassFilesIndexFeature.METHOD_CHAINS_COMPLETION.enable();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
CompilerOutputIndexFeature.METHOD_CHAINS_COMPLETION.disable();
|
||||
ClassFilesIndexFeature.METHOD_CHAINS_COMPLETION.disable();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@@ -52,7 +48,8 @@ public class MethodChainsCompletionTest extends AbstractCompilerAwareTest {
|
||||
|
||||
public void testStaticMethod() {
|
||||
final List<WeightableChainLookupElement> elements = doCompletion();
|
||||
assertAdvisorLookupElementEquals("getInstance", 0, 2, 1, 0, assertOneElement(elements));
|
||||
assertSize(2, elements);
|
||||
assertAdvisorLookupElementEquals("getInstance", 0, 2, 1, 0, elements.get(0));
|
||||
}
|
||||
|
||||
public void testStaticMethodAndMethod() {
|
||||
@@ -86,12 +83,13 @@ public class MethodChainsCompletionTest extends AbstractCompilerAwareTest {
|
||||
assertOneElement(doCompletion());
|
||||
}
|
||||
|
||||
public void testMethodReturnsSubclassOfTargetClassNotShowed2() {
|
||||
assertEmpty(doCompletion());
|
||||
public void testMethodReturnsSubclassOfTargetClassShowed2() {
|
||||
assertOneElement(doCompletion());
|
||||
}
|
||||
|
||||
public void testResultsForSuperClassesNotShowed() {
|
||||
assertEmpty(doCompletion());
|
||||
public void testResultsForSuperClassesShowed() {
|
||||
// if no other elements found we search by super classes
|
||||
assertOneElement(doCompletion());
|
||||
}
|
||||
|
||||
public void testInnerClasses() {
|
||||
@@ -108,8 +106,9 @@ public class MethodChainsCompletionTest extends AbstractCompilerAwareTest {
|
||||
}
|
||||
|
||||
public void testBigrams3() {
|
||||
final List<WeightableChainLookupElement> collection = doCompletion();
|
||||
assertAdvisorLookupElementEquals("getInstance().findFile().findElementAt", 2, 8, 3, 0, assertOneElement(collection));
|
||||
final List<WeightableChainLookupElement> elements = doCompletion();
|
||||
assertSize(2, elements);
|
||||
assertAdvisorLookupElementEquals("getInstance().findFile().findElementAt", 2, 8, 3, 0, elements.get(0));
|
||||
}
|
||||
|
||||
public void testMethodWithNoQualifiedVariableInContext() {
|
||||
@@ -217,18 +216,24 @@ public class MethodChainsCompletionTest extends AbstractCompilerAwareTest {
|
||||
}
|
||||
|
||||
private void doTestRendering() {
|
||||
PropertiesComponent.getInstance(getProject()).setValue(ChainCompletionMethodCallLookupElement.PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION, String.valueOf(true));
|
||||
indexCompiledData(compileData(getName(), TEST_INDEX_FILE_NAME));
|
||||
final ClassFilesIndexFeaturesHolder indicesHolder = ClassFilesIndexFeaturesHolder.getInstance(getProject());
|
||||
PropertiesComponent.getInstance(getProject())
|
||||
.setValue(ChainCompletionMethodCallLookupElement.PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION, String.valueOf(true));
|
||||
indicesHolder.projectOpened();
|
||||
compileAndIndexData(TEST_INDEX_FILE_NAME);
|
||||
myFixture.configureByFiles(getBeforeCompletionFilePath());
|
||||
myFixture.complete(CompletionType.BASIC, MethodsChainsCompletionContributor.INVOCATIONS_THRESHOLD);
|
||||
PropertiesComponent.getInstance(getProject()).setValue(ChainCompletionMethodCallLookupElement.PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION, String.valueOf(false));
|
||||
PropertiesComponent.getInstance(getProject())
|
||||
.setValue(ChainCompletionMethodCallLookupElement.PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION, String.valueOf(false));
|
||||
myFixture.checkResultByFile(getAfterCompletionFilePath());
|
||||
indicesHolder.projectClosed();
|
||||
}
|
||||
|
||||
private List<WeightableChainLookupElement> doCompletion() {
|
||||
final ClassFilesIndexFeaturesHolder indicesHolder = ClassFilesIndexFeaturesHolder.getInstance(getProject());
|
||||
try {
|
||||
indexCompiledData(compileData(getName(), TEST_INDEX_FILE_NAME));
|
||||
|
||||
indicesHolder.projectOpened();
|
||||
compileAndIndexData(TEST_INDEX_FILE_NAME);
|
||||
final LookupElement[] allLookupElements = runCompletion();
|
||||
final List<WeightableChainLookupElement> targetLookupElements = new SmartList<WeightableChainLookupElement>();
|
||||
for (final LookupElement lookupElement : allLookupElements) {
|
||||
@@ -236,30 +241,20 @@ public class MethodChainsCompletionTest extends AbstractCompilerAwareTest {
|
||||
targetLookupElements.add((WeightableChainLookupElement)lookupElement);
|
||||
}
|
||||
}
|
||||
|
||||
return targetLookupElements;
|
||||
}
|
||||
finally {
|
||||
final CompilerOutputIndexer indexer = CompilerOutputIndexer.getInstance(getProject());
|
||||
indexer.projectClosed();
|
||||
indexer.removeIndexes();
|
||||
indicesHolder.projectClosed();
|
||||
}
|
||||
}
|
||||
|
||||
private LookupElement[] runCompletion() {
|
||||
myFixture.configureByFiles(getTestCompletionFilePath());
|
||||
final LookupElement[] lookupElements = myFixture.complete(CompletionType.BASIC, MethodsChainsCompletionContributor.INVOCATIONS_THRESHOLD);
|
||||
final LookupElement[] lookupElements =
|
||||
myFixture.complete(CompletionType.BASIC, MethodsChainsCompletionContributor.INVOCATIONS_THRESHOLD);
|
||||
return lookupElements == null ? LookupElement.EMPTY_ARRAY : lookupElements;
|
||||
}
|
||||
|
||||
private void indexCompiledData(final File compilerOutput) {
|
||||
final FileVisitorService.DirectoryClassFiles visitorService = new FileVisitorService.DirectoryClassFiles(compilerOutput);
|
||||
final CompilerOutputIndexer indexer = CompilerOutputIndexer.getInstance(getProject());
|
||||
indexer.projectOpened();
|
||||
indexer.clear();
|
||||
indexer.reindex(visitorService, new MockProgressIndicator());
|
||||
}
|
||||
|
||||
private String getTestCompletionFilePath() {
|
||||
return getName() + "/" + TEST_COMPLETION_FILE_NAME;
|
||||
}
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
org.jetbrains.jps.classFilesIndex.indexer.impl.MethodsUsageIndexerFactory
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.jetbrains.jps.classFilesIndex;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.asm4.Type;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class AsmUtil {
|
||||
private AsmUtil() {}
|
||||
|
||||
public static String getQualifiedClassName(final String name) {
|
||||
return StringUtil.replaceChar(Type.getObjectType(name).getClassName(), '$', '.');
|
||||
}
|
||||
|
||||
//char
|
||||
//double
|
||||
//float
|
||||
//int
|
||||
//long
|
||||
//short
|
||||
//boolean
|
||||
//byte
|
||||
//void
|
||||
//Object
|
||||
//String
|
||||
//Class
|
||||
private static final Set<String> ASM_PRIMITIVE_TYPES = ContainerUtil
|
||||
.newHashSet("C", "D", "F", "I", "J", "S", "Z", "B", "V", "Ljava/lang/Object;", "Ljava/lang/String;", "Ljava/lang/Class;");
|
||||
|
||||
public static boolean isPrimitiveOrArray(final String asmType) {
|
||||
if (asmType.startsWith("[")) {
|
||||
return true;
|
||||
}
|
||||
return ASM_PRIMITIVE_TYPES.contains(asmType);
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.jetbrains.jps.classFilesIndex;
|
||||
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import gnu.trove.TObjectIntProcedure;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class TObjectIntHashMapExternalizer<K> implements DataExternalizer<TObjectIntHashMap<K>> {
|
||||
private final DataExternalizer<K> myKeyDataExternalizer;
|
||||
|
||||
public TObjectIntHashMapExternalizer(final DataExternalizer<K> keyDataExternalizer) {
|
||||
myKeyDataExternalizer = keyDataExternalizer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(final DataOutput out, final TObjectIntHashMap<K> map) throws IOException {
|
||||
out.writeInt(map.size());
|
||||
try {
|
||||
map.forEachEntry(new TObjectIntProcedure<K>() {
|
||||
@Override
|
||||
public boolean execute(final K key, final int value) {
|
||||
try {
|
||||
myKeyDataExternalizer.save(out, key);
|
||||
out.writeInt(value);
|
||||
}
|
||||
catch (final IOException e) {
|
||||
throw new IoExceptionRuntimeWrapperException(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (final IoExceptionRuntimeWrapperException e) {
|
||||
throw e.getIoException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TObjectIntHashMap<K> read(final DataInput in) throws IOException {
|
||||
final int size = in.readInt();
|
||||
final TObjectIntHashMap<K> map = new TObjectIntHashMap<K>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
map.put(myKeyDataExternalizer.read(in), in.readInt());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static class IoExceptionRuntimeWrapperException extends RuntimeException {
|
||||
private final IOException myIoException;
|
||||
|
||||
private IoExceptionRuntimeWrapperException(final IOException ioException) {
|
||||
myIoException = ioException;
|
||||
}
|
||||
|
||||
public IOException getIoException() {
|
||||
return myIoException;
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.jetbrains.jps.classFilesIndex.indexer.api;
|
||||
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.asm4.ClassReader;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public abstract class ClassFileIndexer<K, V> {
|
||||
private final String myIndexCanonicalName;
|
||||
|
||||
public ClassFileIndexer(final String indexCanonicalName) {
|
||||
myIndexCanonicalName = indexCanonicalName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public abstract Map<K, V> map(ClassReader inputData);
|
||||
|
||||
public abstract KeyDescriptor<K> getKeyDescriptor();
|
||||
|
||||
public abstract DataExternalizer<V> getDataExternalizer();
|
||||
|
||||
public String getIndexCanonicalName() {
|
||||
return myIndexCanonicalName;
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.jetbrains.jps.classFilesIndex.indexer.api;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public interface ClassFileIndexerFactory<K, V> {
|
||||
|
||||
ClassFileIndexer<K, V> create();
|
||||
|
||||
}
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.jetbrains.jps.classFilesIndex.indexer.api;
|
||||
|
||||
import com.intellij.util.containers.SLRUCache;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
import com.intellij.util.io.PersistentHashMap;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
* <p/>
|
||||
* synchronization only on write actions
|
||||
*/
|
||||
public class ClassFilesIndexStorage<K, V> {
|
||||
private static final String INDEX_FILE_NAME = "index";
|
||||
private static final int INITIAL_INDEX_SIZE = 16 * 1024;
|
||||
private static final int CACHE_QUEUES_SIZE = 16 * 1024;
|
||||
|
||||
private final File myIndexFile;
|
||||
private final KeyDescriptor<K> myKeyDescriptor;
|
||||
private final DataExternalizer<V> myValueExternalizer;
|
||||
private final Lock myWriteLock = new ReentrantLock();
|
||||
private PersistentHashMap<K, CompiledDataValueContainer<V>> myMap;
|
||||
@SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized") private SLRUCache<K, CompiledDataValueContainer<V>> myCache;
|
||||
|
||||
public ClassFilesIndexStorage(final File indexDir, final KeyDescriptor<K> keyDescriptor, final DataExternalizer<V> valueExternalizer)
|
||||
throws IOException {
|
||||
myIndexFile = getIndexFile(indexDir);
|
||||
myKeyDescriptor = keyDescriptor;
|
||||
myValueExternalizer = valueExternalizer;
|
||||
initialize();
|
||||
}
|
||||
|
||||
private void initialize() throws IOException {
|
||||
myMap = new PersistentHashMap<K, CompiledDataValueContainer<V>>(myIndexFile, myKeyDescriptor,
|
||||
createValueContainerExternalizer(myValueExternalizer),
|
||||
INITIAL_INDEX_SIZE);
|
||||
myCache = new SLRUCache<K, CompiledDataValueContainer<V>>(CACHE_QUEUES_SIZE, CACHE_QUEUES_SIZE) {
|
||||
@NotNull
|
||||
@Override
|
||||
public CompiledDataValueContainer<V> createValue(final K key) {
|
||||
try {
|
||||
final CompiledDataValueContainer<V> valueContainer = myMap.get(key);
|
||||
if (valueContainer != null) {
|
||||
return valueContainer;
|
||||
}
|
||||
}
|
||||
catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return new CompiledDataValueContainer<V>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDropFromCache(final K key, final CompiledDataValueContainer<V> value) {
|
||||
try {
|
||||
myMap.put(key, value);
|
||||
}
|
||||
catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Collection<V> getData(final K key) {
|
||||
return myCache.get(key).getValues();
|
||||
}
|
||||
|
||||
public void putData(final K key, final V value, final String inputId) {
|
||||
try {
|
||||
myWriteLock.lock();
|
||||
final CompiledDataValueContainer<V> container = myCache.get(key);
|
||||
container.putValue(inputId, value);
|
||||
}
|
||||
finally {
|
||||
myWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void delete() throws IOException {
|
||||
try {
|
||||
myWriteLock.lock();
|
||||
doDelete();
|
||||
}
|
||||
finally {
|
||||
myWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void doDelete() throws IOException {
|
||||
close();
|
||||
PersistentHashMap.deleteFilesStartingWith(myIndexFile);
|
||||
}
|
||||
|
||||
public void clear() throws IOException {
|
||||
try {
|
||||
myWriteLock.lock();
|
||||
doDelete();
|
||||
initialize();
|
||||
}
|
||||
finally {
|
||||
myWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
try {
|
||||
myWriteLock.lock();
|
||||
myCache.clear();
|
||||
}
|
||||
finally {
|
||||
myWriteLock.unlock();
|
||||
}
|
||||
myMap.force();
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
flush();
|
||||
myMap.close();
|
||||
}
|
||||
|
||||
public static class CompiledDataValueContainer<V> {
|
||||
private final THashMap<String, V> myUnderlying;
|
||||
|
||||
private CompiledDataValueContainer(final THashMap<String, V> map) {
|
||||
myUnderlying = map;
|
||||
}
|
||||
|
||||
private CompiledDataValueContainer() {
|
||||
this(new THashMap<String, V>());
|
||||
}
|
||||
|
||||
private void putValue(final String inputId, final V value) {
|
||||
myUnderlying.put(inputId, value);
|
||||
}
|
||||
|
||||
public Collection<V> getValues() {
|
||||
return myUnderlying.values();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static File getIndexFile(final File indexDir) {
|
||||
return new File(indexDir, INDEX_FILE_NAME);
|
||||
}
|
||||
|
||||
public static File getIndexDir(final String indexName, final File projectSystemBuildDirectory) {
|
||||
return new File(projectSystemBuildDirectory, "compiler.output.data.indices/" + indexName);
|
||||
}
|
||||
|
||||
private static <V> DataExternalizer<CompiledDataValueContainer<V>> createValueContainerExternalizer(final DataExternalizer<V> valueExternalizer) {
|
||||
final DataExternalizer<String> stringDataExternalizer = new EnumeratorStringDescriptor();
|
||||
return new DataExternalizer<CompiledDataValueContainer<V>>() {
|
||||
@Override
|
||||
public void save(final DataOutput out, final CompiledDataValueContainer<V> value) throws IOException {
|
||||
final THashMap<String, V> underlying = value.myUnderlying;
|
||||
out.writeInt(underlying.size());
|
||||
for (final Map.Entry<String, V> entry : underlying.entrySet()) {
|
||||
stringDataExternalizer.save(out, entry.getKey());
|
||||
valueExternalizer.save(out, entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompiledDataValueContainer<V> read(final DataInput in) throws IOException {
|
||||
final THashMap<String, V> map = new THashMap<String, V>();
|
||||
final int size = in.readInt();
|
||||
for (int i = 0; i < size; i++) {
|
||||
map.put(stringDataExternalizer.read(in), valueExternalizer.read(in));
|
||||
}
|
||||
return new CompiledDataValueContainer<V>(map);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.jetbrains.jps.classFilesIndex.indexer.api;
|
||||
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.io.PersistentHashMap;
|
||||
import org.jetbrains.asm4.ClassReader;
|
||||
import org.jetbrains.jps.incremental.CompileContext;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class ClassFilesIndexWriter<K, V> {
|
||||
private final ClassFileIndexer<K, V> myIndexer;
|
||||
private final boolean myEmpty;
|
||||
protected final ClassFilesIndexStorage<K, V> myIndex;
|
||||
|
||||
protected ClassFilesIndexWriter(final ClassFileIndexer<K, V> indexer, final CompileContext compileContext) {
|
||||
myIndexer = indexer;
|
||||
final File storageDir = getIndexRoot(compileContext);
|
||||
final Set<String> containingFileNames = listFiles(storageDir);
|
||||
if (!containingFileNames.contains("version") || !containingFileNames.contains("state")) {
|
||||
throw new IllegalStateException("version or state file for index " + indexer.getIndexCanonicalName() + " not found in " + storageDir.getAbsolutePath());
|
||||
}
|
||||
ClassFilesIndexStorage<K, V> index = null;
|
||||
IOException exception = null;
|
||||
for (int attempt = 0; attempt < 2; attempt++) {
|
||||
try {
|
||||
index = new ClassFilesIndexStorage<K, V>(storageDir, myIndexer.getKeyDescriptor(), myIndexer.getDataExternalizer());
|
||||
break;
|
||||
}
|
||||
catch (final IOException e) {
|
||||
exception = e;
|
||||
PersistentHashMap.deleteFilesStartingWith(ClassFilesIndexStorage.getIndexFile(storageDir));
|
||||
}
|
||||
}
|
||||
if (index == null) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
myIndex = index;
|
||||
myEmpty = IndexState.EXIST != IndexState.load(storageDir) || exception != null;
|
||||
IndexState.CORRUPTED.save(storageDir);
|
||||
}
|
||||
|
||||
private static Set<String> listFiles(final File dir) {
|
||||
final String[] containingFileNames = dir.list();
|
||||
return containingFileNames == null ? Collections.<String>emptySet() : ContainerUtil.newHashSet(containingFileNames);
|
||||
}
|
||||
|
||||
private File getIndexRoot(final CompileContext compileContext) {
|
||||
final File rootFile = compileContext.getProjectDescriptor().dataManager.getDataPaths().getDataStorageRoot();
|
||||
return ClassFilesIndexStorage.getIndexDir(myIndexer.getIndexCanonicalName(), rootFile);
|
||||
}
|
||||
|
||||
public final boolean isEmpty() {
|
||||
return myEmpty;
|
||||
}
|
||||
|
||||
public final void close(final CompileContext compileContext) {
|
||||
try {
|
||||
myIndex.close();
|
||||
IndexState.EXIST.save(getIndexRoot(compileContext));
|
||||
}
|
||||
catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public final void update(final String id, final ClassReader inputData) {
|
||||
for (final Map.Entry<K, V> e : myIndexer.map(inputData).entrySet()) {
|
||||
myIndex.putData(e.getKey(), e.getValue(), id);
|
||||
}
|
||||
}
|
||||
}
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.jetbrains.jps.classFilesIndex.indexer.api;
|
||||
|
||||
import com.intellij.compiler.instrumentation.InstrumentationClassFinder;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.ClassReader;
|
||||
import org.jetbrains.asm4.ClassWriter;
|
||||
import org.jetbrains.jps.ModuleChunk;
|
||||
import org.jetbrains.jps.builders.java.JavaBuilderUtil;
|
||||
import org.jetbrains.jps.incremental.BinaryContent;
|
||||
import org.jetbrains.jps.incremental.CompileContext;
|
||||
import org.jetbrains.jps.incremental.CompiledClass;
|
||||
import org.jetbrains.jps.incremental.instrumentation.BaseInstrumentingBuilder;
|
||||
import org.jetbrains.jps.incremental.messages.ProgressMessage;
|
||||
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
|
||||
import org.jetbrains.jps.model.module.JpsModule;
|
||||
import org.jetbrains.jps.service.JpsServiceManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class ClassFilesIndicesBuilder extends BaseInstrumentingBuilder {
|
||||
public static final Logger LOG = Logger.getInstance(ClassFilesIndicesBuilder.class);
|
||||
private static final String PRESENTABLE_NAME = "Class-files indexer";
|
||||
private static final String PROGRESS_MESSAGE = "Indexing class-files...";
|
||||
public static final String PROPERTY_NAME = "intellij.compiler.output.index";
|
||||
|
||||
private final Collection<ClassFilesIndexWriter> myAlreadyExistIndexWriters = new ArrayList<ClassFilesIndexWriter>();
|
||||
private final Collection<ClassFilesIndexWriter> myNewIndexWriters = new ArrayList<ClassFilesIndexWriter>();
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void buildStarted(final CompileContext context) {
|
||||
|
||||
super.buildStarted(context);
|
||||
final boolean isEnabled = isEnabled();
|
||||
LOG.info("class files data index " + (isEnabled ? "enabled" : "disabled"));
|
||||
if (!isEnabled) {
|
||||
return;
|
||||
}
|
||||
final Set<String> enabledIndicesBuilders = ContainerUtil.newHashSet(System.getProperty(PROPERTY_NAME).split(";"));
|
||||
final Iterable<ClassFileIndexerFactory> extensions = JpsServiceManager.getInstance().getExtensions(ClassFileIndexerFactory.class);
|
||||
for (final ClassFileIndexerFactory builder : extensions) {
|
||||
if (enabledIndicesBuilders.contains(builder.getClass().getName())) {
|
||||
final ClassFilesIndexWriter indexWriter = new ClassFilesIndexWriter(builder.create(), context);
|
||||
if (indexWriter.isEmpty()) {
|
||||
myNewIndexWriters.add(indexWriter);
|
||||
}
|
||||
else {
|
||||
myAlreadyExistIndexWriters.add(indexWriter);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
LOG.info(String.format("class files indexing: %d indices, %d new",
|
||||
myNewIndexWriters.size() + myAlreadyExistIndexWriters.size(),
|
||||
myNewIndexWriters.size()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildFinished(final CompileContext context) {
|
||||
super.buildFinished(context);
|
||||
if (!isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (JavaBuilderUtil.isForcedRecompilationAllJavaModules(context)) {
|
||||
final long ms = System.currentTimeMillis();
|
||||
final int[] counter = {0};
|
||||
iterateProjectClassFiles(new Processor<File>() {
|
||||
@SuppressWarnings("ALL")
|
||||
@Override
|
||||
public boolean process(final File file) {
|
||||
if (file.getName().endsWith(".class")) {
|
||||
counter[0]++;
|
||||
final ClassReader inputData;
|
||||
FileInputStream is = null;
|
||||
try {
|
||||
is = new FileInputStream(file);
|
||||
inputData = new ClassReader(is);
|
||||
}
|
||||
catch (final IOException e) {
|
||||
LOG.error("couldn't open file " + file.getAbsolutePath(), e);
|
||||
return true;
|
||||
}
|
||||
finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
}
|
||||
catch (final IOException e) {
|
||||
LOG.error("couldn't open file " + file.getAbsolutePath(), e);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
context.processMessage(new ProgressMessage(PROGRESS_MESSAGE + file.getName()));
|
||||
for (final ClassFilesIndexWriter index : myNewIndexWriters) {
|
||||
index.update(file.getPath(), inputData);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, context);
|
||||
for (final ClassFilesIndexWriter index : myNewIndexWriters) {
|
||||
index.close(context);
|
||||
}
|
||||
LOG.info("new indices created on " + counter[0] + " class files in " + (System.currentTimeMillis() - ms) + " ms");
|
||||
}
|
||||
for (final ClassFilesIndexWriter index : myAlreadyExistIndexWriters) {
|
||||
index.close(context);
|
||||
}
|
||||
|
||||
LOG.info("class files indexing finished");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected BinaryContent instrument(final CompileContext context,
|
||||
final CompiledClass compiled,
|
||||
final ClassReader reader,
|
||||
final ClassWriter writer,
|
||||
final InstrumentationClassFinder finder) {
|
||||
for (final ClassFilesIndexWriter index : myAlreadyExistIndexWriters) {
|
||||
index.update(compiled.getOutputFile().getPath(), reader);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canInstrument(final CompiledClass compiledClass, final int classFileVersion) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled(final CompileContext context, final ModuleChunk chunk) {
|
||||
return isEnabled();
|
||||
}
|
||||
|
||||
private static boolean isEnabled() {
|
||||
return System.getProperty(PROPERTY_NAME) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getProgressMessage() {
|
||||
return PROGRESS_MESSAGE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getPresentableName() {
|
||||
return PRESENTABLE_NAME;
|
||||
}
|
||||
|
||||
public static void iterateProjectClassFiles(@NotNull final Processor<File> fileProcessor, @NotNull final CompileContext context) {
|
||||
final JpsJavaExtensionService javaExtensionService = JpsJavaExtensionService.getInstance();
|
||||
for (final JpsModule module : context.getProjectDescriptor().getProject().getModules()) {
|
||||
final File outputDirectory = javaExtensionService.getOutputDirectory(module, false);
|
||||
if (outputDirectory != null) {
|
||||
FileUtil.processFilesRecursively(outputDirectory, fileProcessor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.jetbrains.jps.classFilesIndex.indexer.api;
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public enum IndexState {
|
||||
CORRUPTED,
|
||||
NOT_EXIST,
|
||||
EXIST;
|
||||
|
||||
private static final String STATE_FILE_NAME = "state";
|
||||
|
||||
public void save(final File indexDir) {
|
||||
final File indexStateFile = new File(indexDir, STATE_FILE_NAME);
|
||||
try {
|
||||
FileUtil.writeToFile(indexStateFile, String.valueOf(this));
|
||||
}
|
||||
catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static IndexState load(final File indexDir) {
|
||||
try {
|
||||
final File indexStateFile = new File(indexDir, STATE_FILE_NAME);
|
||||
if (!indexStateFile.exists()) {
|
||||
NOT_EXIST.save(indexDir);
|
||||
return NOT_EXIST;
|
||||
}
|
||||
final String fileString = FileUtil.loadFile(indexStateFile);
|
||||
for (final IndexState indexState : values()) {
|
||||
if (String.valueOf(indexState).equals(fileString)) {
|
||||
return indexState;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Invalid state: " + fileString);
|
||||
}
|
||||
catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
-89
@@ -1,27 +1,34 @@
|
||||
package com.intellij.compilerOutputIndex.impl;
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.jetbrains.jps.classFilesIndex.indexer.impl;
|
||||
|
||||
import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.classFilesIndex.AsmUtil;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class MethodIncompleteSignature {
|
||||
|
||||
public static final String CONSTRUCTOR_METHOD_NAME = "<init>";
|
||||
|
||||
@NotNull
|
||||
@@ -72,83 +79,6 @@ public class MethodIncompleteSignature {
|
||||
return myStatic;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiMethod[] resolveNotDeprecated(final JavaPsiFacade javaPsiFacade, final GlobalSearchScope scope) {
|
||||
return notDeprecated(resolve(javaPsiFacade, scope));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiMethod[] resolve(final JavaPsiFacade javaPsiFacade, final GlobalSearchScope scope) {
|
||||
if (CONSTRUCTOR_METHOD_NAME.equals(getName())) {
|
||||
return PsiMethod.EMPTY_ARRAY;
|
||||
}
|
||||
final PsiClass aClass = javaPsiFacade.findClass(getOwner(), scope);
|
||||
if (aClass == null) {
|
||||
return PsiMethod.EMPTY_ARRAY;
|
||||
}
|
||||
final PsiMethod[] methods = aClass.findMethodsByName(getName(), true);
|
||||
final List<PsiMethod> filtered = new ArrayList<PsiMethod>(methods.length);
|
||||
for (final PsiMethod method : methods) {
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC) == isStatic()) {
|
||||
final PsiType returnType = method.getReturnType();
|
||||
if (returnType != null && returnType.equalsToText(getReturnType())) {
|
||||
filtered.add(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filtered.size() > 1) {
|
||||
Collections.sort(filtered, new Comparator<PsiMethod>() {
|
||||
@Override
|
||||
public int compare(final PsiMethod o1, final PsiMethod o2) {
|
||||
return o1.getParameterList().getParametersCount() - o2.getParameterList().getParametersCount();
|
||||
}
|
||||
});
|
||||
}
|
||||
return filtered.toArray(new PsiMethod[filtered.size()]);
|
||||
}
|
||||
|
||||
public static KeyDescriptor<MethodIncompleteSignature> createKeyDescriptor() {
|
||||
final EnumeratorStringDescriptor stringDescriptor = new EnumeratorStringDescriptor();
|
||||
return new KeyDescriptor<MethodIncompleteSignature>() {
|
||||
@Override
|
||||
public void save(final DataOutput out, final MethodIncompleteSignature value) throws IOException {
|
||||
stringDescriptor.save(out, value.getOwner());
|
||||
stringDescriptor.save(out, value.getReturnType());
|
||||
stringDescriptor.save(out, value.getName());
|
||||
out.writeBoolean(value.isStatic());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodIncompleteSignature read(final DataInput in) throws IOException {
|
||||
return new MethodIncompleteSignature(stringDescriptor.read(in), stringDescriptor.read(in), stringDescriptor.read(in),
|
||||
in.readBoolean());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHashCode(final MethodIncompleteSignature value) {
|
||||
return value.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEqual(final MethodIncompleteSignature val1, final MethodIncompleteSignature val2) {
|
||||
return val1.equals(val2);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiMethod[] notDeprecated(@NotNull final PsiMethod[] methods) {
|
||||
final List<PsiMethod> filtered = ContainerUtil.filter(methods, NOT_DEPRECATED_CONDITION);
|
||||
return filtered.toArray(new PsiMethod[filtered.size()]);
|
||||
}
|
||||
|
||||
private final static Condition<PsiMethod> NOT_DEPRECATED_CONDITION = new Condition<PsiMethod>() {
|
||||
@Override
|
||||
public boolean value(final PsiMethod method) {
|
||||
return !method.isDeprecated();
|
||||
}
|
||||
};
|
||||
|
||||
public final static Comparator<MethodIncompleteSignature> COMPARATOR = new Comparator<MethodIncompleteSignature>() {
|
||||
@Override
|
||||
public int compare(final MethodIncompleteSignature o1, final MethodIncompleteSignature o2) {
|
||||
@@ -174,6 +104,25 @@ public class MethodIncompleteSignature {
|
||||
}
|
||||
};
|
||||
|
||||
public static DataExternalizer<MethodIncompleteSignature> createDataExternalizer() {
|
||||
final EnumeratorStringDescriptor stringDescriptor = new EnumeratorStringDescriptor();
|
||||
return new DataExternalizer<MethodIncompleteSignature>() {
|
||||
@Override
|
||||
public void save(final DataOutput out, final MethodIncompleteSignature value) throws IOException {
|
||||
stringDescriptor.save(out, value.getOwner());
|
||||
stringDescriptor.save(out, value.getReturnType());
|
||||
stringDescriptor.save(out, value.getName());
|
||||
out.writeBoolean(value.isStatic());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodIncompleteSignature read(final DataInput in) throws IOException {
|
||||
return new MethodIncompleteSignature(stringDescriptor.read(in), stringDescriptor.read(in), stringDescriptor.read(in),
|
||||
in.readBoolean());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.jetbrains.jps.classFilesIndex.indexer.impl;
|
||||
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.EnumDataDescriptor;
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class MethodUsageIndexKey {
|
||||
@NotNull
|
||||
private final String myQualifiedClassName;
|
||||
@NotNull
|
||||
private final KeyRole myRole;
|
||||
|
||||
public MethodUsageIndexKey(@NotNull final String qualifiedClassName, @NotNull final KeyRole role) {
|
||||
myQualifiedClassName = qualifiedClassName;
|
||||
myRole = role;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getQualifiedClassName() {
|
||||
return myQualifiedClassName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public KeyRole getRole() {
|
||||
return myRole;
|
||||
}
|
||||
|
||||
public enum KeyRole {
|
||||
RETURN_TYPE,
|
||||
QUALIFIER;
|
||||
|
||||
private static final DataExternalizer<KeyRole> DATA_EXTERNALIZER = new EnumDataDescriptor<KeyRole>(KeyRole.class);
|
||||
}
|
||||
|
||||
|
||||
public static KeyDescriptor<MethodUsageIndexKey> createKeyDescriptor() {
|
||||
final DataExternalizer<String> stringDataExternalizer = new EnumeratorStringDescriptor();
|
||||
return new KeyDescriptor<MethodUsageIndexKey>() {
|
||||
@Override
|
||||
public void save(final DataOutput out, final MethodUsageIndexKey value) throws IOException {
|
||||
stringDataExternalizer.save(out, value.getQualifiedClassName());
|
||||
KeyRole.DATA_EXTERNALIZER.save(out, value.getRole());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodUsageIndexKey read(final DataInput in) throws IOException {
|
||||
return new MethodUsageIndexKey(stringDataExternalizer.read(in), KeyRole.DATA_EXTERNALIZER.read(in));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHashCode(final MethodUsageIndexKey value) {
|
||||
return value.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEqual(final MethodUsageIndexKey val1, final MethodUsageIndexKey val2) {
|
||||
return val1.equals(val2);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof MethodUsageIndexKey)) return false;
|
||||
|
||||
final MethodUsageIndexKey that = (MethodUsageIndexKey)o;
|
||||
|
||||
if (!myQualifiedClassName.equals(that.myQualifiedClassName)) return false;
|
||||
if (myRole != that.myRole) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = myQualifiedClassName.hashCode();
|
||||
result = 31 * result + myRole.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.jetbrains.jps.classFilesIndex.indexer.impl;
|
||||
|
||||
import com.intellij.util.containers.FactoryMap;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.*;
|
||||
import org.jetbrains.jps.classFilesIndex.AsmUtil;
|
||||
import org.jetbrains.jps.classFilesIndex.TObjectIntHashMapExternalizer;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.api.ClassFileIndexer;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.api.ClassFilesIndicesBuilder;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class MethodsUsageIndexer extends ClassFileIndexer<String, TObjectIntHashMap<MethodIncompleteSignature>> {
|
||||
public static final String METHODS_USAGE_INDEX_CANONICAL_NAME = "MethodsUsageIndex";
|
||||
|
||||
public MethodsUsageIndexer() {
|
||||
super(METHODS_USAGE_INDEX_CANONICAL_NAME);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<String, TObjectIntHashMap<MethodIncompleteSignature>> map(final ClassReader inputData) {
|
||||
final Map<String, TObjectIntHashMap<MethodIncompleteSignature>> map = new HashMap<String, TObjectIntHashMap<MethodIncompleteSignature>>();
|
||||
final MethodVisitor methodVisitor = new MethodVisitor(Opcodes.ASM4) {
|
||||
@Override
|
||||
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
|
||||
final Type returnType = Type.getReturnType(desc);
|
||||
if (MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME.equals(name) || AsmUtil.isPrimitiveOrArray(returnType.getDescriptor())) {
|
||||
return;
|
||||
}
|
||||
final boolean isStatic = opcode == Opcodes.INVOKESTATIC;
|
||||
final String returnClassName = returnType.getInternalName();
|
||||
if (!owner.equals(returnClassName) || isStatic) {
|
||||
addToIndex(map, returnClassName, new MethodIncompleteSignature(owner, returnClassName, name, isStatic));
|
||||
}
|
||||
}
|
||||
};
|
||||
inputData.accept(new ClassVisitor(Opcodes.ASM4) {
|
||||
@Override
|
||||
public MethodVisitor visitMethod(final int access,
|
||||
final String name,
|
||||
final String desc,
|
||||
final String signature,
|
||||
final String[] exceptions) {
|
||||
return methodVisitor;
|
||||
}
|
||||
}, ClassReader.EXPAND_FRAMES);
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyDescriptor<String> getKeyDescriptor() {
|
||||
return new EnumeratorStringDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataExternalizer<TObjectIntHashMap<MethodIncompleteSignature>> getDataExternalizer() {
|
||||
return new TObjectIntHashMapExternalizer<MethodIncompleteSignature>(MethodIncompleteSignature.createDataExternalizer());
|
||||
}
|
||||
|
||||
private void addToIndex(final Map<String, TObjectIntHashMap<MethodIncompleteSignature>> map,
|
||||
final String internalClassName,
|
||||
final MethodIncompleteSignature mi) {
|
||||
final String className = myQualifiedClassNameResolver.get(internalClassName);
|
||||
TObjectIntHashMap<MethodIncompleteSignature> occurrences = map.get(className);
|
||||
if (occurrences == null) {
|
||||
occurrences = new TObjectIntHashMap<MethodIncompleteSignature>();
|
||||
map.put(className, occurrences);
|
||||
}
|
||||
if (!occurrences.increment(mi)) {
|
||||
occurrences.put(mi, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
|
||||
private final FactoryMap<String, String> myQualifiedClassNameResolver = new FactoryMap<String, String>() {
|
||||
@Nullable
|
||||
@Override
|
||||
protected String create(final String internalClassName) {
|
||||
return AsmUtil.getQualifiedClassName(internalClassName);
|
||||
}
|
||||
};
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.jetbrains.jps.classFilesIndex.indexer.impl;
|
||||
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.api.ClassFileIndexer;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.api.ClassFileIndexerFactory;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class MethodsUsageIndexerFactory implements ClassFileIndexerFactory<String, TObjectIntHashMap<MethodIncompleteSignature>> {
|
||||
@Override
|
||||
public ClassFileIndexer<String, TObjectIntHashMap<MethodIncompleteSignature>> create() {
|
||||
return new MethodsUsageIndexer();
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.builders.BuildTargetType;
|
||||
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
|
||||
import org.jetbrains.jps.builders.java.ResourcesTargetType;
|
||||
import org.jetbrains.jps.classFilesIndex.indexer.api.ClassFilesIndicesBuilder;
|
||||
import org.jetbrains.jps.incremental.instrumentation.NotNullInstrumentingBuilder;
|
||||
import org.jetbrains.jps.incremental.instrumentation.RmiStubsGenerator;
|
||||
import org.jetbrains.jps.incremental.java.JavaBuilder;
|
||||
@@ -45,7 +46,10 @@ public class JavaBuilderService extends BuilderService {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<? extends ModuleLevelBuilder> createModuleLevelBuilders() {
|
||||
return Arrays.asList(new JavaBuilder(SharedThreadPool.getInstance()), new NotNullInstrumentingBuilder(), new RmiStubsGenerator());
|
||||
return Arrays.asList(new JavaBuilder(SharedThreadPool.getInstance()),
|
||||
new NotNullInstrumentingBuilder(),
|
||||
new RmiStubsGenerator(),
|
||||
new ClassFilesIndicesBuilder());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
</component>
|
||||
|
||||
<component>
|
||||
<implementation-class>com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer</implementation-class>
|
||||
<implementation-class>com.intellij.compiler.compilerOutputIndex.api.index.ClassFilesIndexFeaturesHolder</implementation-class>
|
||||
</component>
|
||||
</project-components>
|
||||
|
||||
@@ -233,9 +233,6 @@
|
||||
<extensionPoint name="psi.clsDecompiledFileProvider"
|
||||
interface="com.intellij.psi.ClsFileDecompiledPsiFileProvider"/>
|
||||
|
||||
<extensionPoint name="java.compilerOutputIndex" area="IDEA_PROJECT"
|
||||
interface="com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex"/>
|
||||
|
||||
<extensionPoint name="vetoSPICondition" interface="com.intellij.openapi.util.Condition"/>
|
||||
|
||||
<extensionPoint name="testStatusListener" interface="com.intellij.execution.testframework.TestStatusListener"/>
|
||||
@@ -1462,11 +1459,10 @@
|
||||
|
||||
<gotoDeclarationHandler implementation="com.intellij.codeInsight.navigation.actions.GotoLambdaParameterHandler"/>
|
||||
|
||||
<java.compilerOutputIndex implementation="com.intellij.compilerOutputIndex.impl.MethodsUsageIndex"/>
|
||||
<completion.contributor language="JAVA" id="methodsChainsCompletionContributor" order="first"
|
||||
implementationClass="com.intellij.codeInsight.completion.methodChains.completion.MethodsChainsCompletionContributor"/>
|
||||
implementationClass="com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.MethodsChainsCompletionContributor"/>
|
||||
<weigher order="first" key="completion" id="methodsChains"
|
||||
implementationClass="com.intellij.codeInsight.completion.methodChains.completion.MethodsChainsWeigher"/>
|
||||
implementationClass="com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.MethodsChainsWeigher"/>
|
||||
|
||||
<applicationService serviceInterface="org.jetbrains.generate.tostring.template.TemplatesManager"
|
||||
serviceImplementation="org.jetbrains.generate.tostring.template.TemplatesManager"/>
|
||||
|
||||
@@ -392,6 +392,8 @@
|
||||
<moduleRendererFactory implementation="com.intellij.ide.util.DefaultModuleRendererFactory" order="last"/>
|
||||
<projectStructure.sourceRootEditHandler implementation="com.intellij.openapi.roots.ui.configuration.JavaResourceRootEditHandler"/>
|
||||
<projectStructure.sourceRootEditHandler implementation="com.intellij.openapi.roots.ui.configuration.JavaTestResourceRootEditHandler"/>
|
||||
|
||||
<buildProcess.parametersProvider implementation="com.intellij.compiler.compilerOutputIndex.api.index.ClassFilesIndexerBuilderParametersProvider"/>
|
||||
</extensions>
|
||||
|
||||
<xi:include href="/META-INF/xdebugger.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
Reference in New Issue
Block a user