From 7c961a7efe944b322ac17b5fbadfb57dca571f33 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Thu, 5 Dec 2013 17:34:30 +0400 Subject: [PATCH] implementation of methods chain completion indexing on jps --- .../api/index/ClassFilesIndexConfigure.java | 38 ++ .../api/index/ClassFilesIndexFeature.java | 76 ++++ .../index/ClassFilesIndexFeaturesHolder.java | 179 ++++++++ .../api/index/ClassFilesIndexReaderBase.java | 153 +++++++ ...FilesIndexerBuilderParametersProvider.java | 69 ++++ .../CachedRelevantStaticMethodSearcher.java | 38 +- .../ChainCompletionStringUtil.java | 17 +- .../chainsSearch}/ChainRelevance.java | 17 +- .../chainsSearch}/ChainsSearcher.java | 98 +++-- .../chainsSearch}/MaxSizeTreeSet.java | 19 +- .../chainsSearch}/MethodChainsSearchUtil.java | 22 +- .../chainsSearch}/MethodsChain.java | 22 +- .../MethodsChainLookupRangingHelper.java | 37 +- .../chainsSearch}/ParametersMatcher.java | 19 +- .../chainsSearch}/SearchInitializer.java | 61 +-- .../CompletionContributorPatternUtil.java | 17 +- .../MethodsChainsCompletionContributor.java | 66 +-- .../completion/MethodsChainsWeigher.java | 6 +- .../ChainCompletionLookupElementUtil.java | 19 +- ...hainCompletionMethodCallLookupElement.java | 19 +- ...ainCompletionNewVariableLookupElement.java | 18 +- .../lookup/WeightableChainLookupElement.java | 37 ++ .../sub/GetterLookupSubLookupElement.java | 17 +- .../sub/StaticMethodSubLookupElement.java | 19 +- .../lookup/sub/SubLookupElement.java | 28 ++ .../lookup/sub/VariableSubLookupElement.java | 40 ++ .../context/ChainCompletionContext.java | 36 +- .../ChainCompletionContextStringUtil.java | 17 +- .../context/ContextRelevantStaticMethod.java | 23 +- .../ContextRelevantVariableGetter.java | 21 +- .../chainsSearch}/context/ContextUtil.java | 19 +- .../MethodIncompleteSignatureResolver.java | 75 ++++ .../impl/MethodsUsageIndexConfigure.java | 53 +++ .../impl/MethodsUsageIndexReader.java | 82 ++++ .../impl/UsageIndexValue.java | 39 +- .../lookup/WeightableChainLookupElement.java | 23 -- .../lookup/sub/SubLookupElement.java | 13 - .../lookup/sub/VariableSubLookupElement.java | 25 -- .../search/MethodChainsSearchService.java | 43 -- .../methodChains/search/WeightAware.java | 33 -- .../descriptor/ArrayListDataExternalizer.java | 38 -- .../descriptor/HashSetDataExternalizer.java | 38 -- .../compilerOutputIndex/api/fs/AsmUtil.java | 85 ---- .../api/fs/CompilerOutputFilesUtil.java | 64 --- .../api/fs/FileVisitorService.java | 53 --- .../api/indexer/CompilerOutputBaseIndex.java | 170 -------- .../indexer/CompilerOutputIndexFeature.java | 70 ---- .../api/indexer/CompilerOutputIndexUtil.java | 17 - .../api/indexer/CompilerOutputIndexer.java | 387 ------------------ .../impl/GuavaHashMultiSetExternalizer.java | 56 --- .../impl/MethodIncompleteSignatureChain.java | 44 -- .../impl/MethodsUsageIndex.java | 135 ------ .../TestCompletion.java | 25 -- .../TestIndex.java | 24 -- .../TestCompletion.java | 41 ++ .../TestIndex.java | 40 ++ .../TestCompletion.java | 24 -- .../TestIndex.java | 26 -- .../TestCompletion.java | 39 ++ .../TestIndex.java | 42 ++ .../completion/AbstractCompilerAwareTest.java | 64 ++- .../MethodChainsCompletionTest.java | 69 ++-- ...sIndex.indexer.api.ClassFileIndexerFactory | 1 + .../jps/classFilesIndex/AsmUtil.java | 55 +++ .../TObjectIntHashMapExternalizer.java | 80 ++++ .../indexer/api/ClassFileIndexer.java | 45 ++ .../indexer/api/ClassFileIndexerFactory.java | 25 ++ .../indexer/api/ClassFilesIndexStorage.java | 202 +++++++++ .../indexer/api/ClassFilesIndexWriter.java | 93 +++++ .../indexer/api/ClassFilesIndicesBuilder.java | 189 +++++++++ .../indexer/api/IndexState.java | 62 +++ .../impl/MethodIncompleteSignature.java | 127 ++---- .../indexer/impl/MethodUsageIndexKey.java | 105 +++++ .../indexer/impl/MethodsUsageIndexer.java | 107 +++++ .../impl/MethodsUsageIndexerFactory.java | 30 ++ .../jps/incremental/JavaBuilderService.java | 6 +- resources/src/META-INF/IdeaPlugin.xml | 10 +- resources/src/idea/RichPlatformPlugin.xml | 2 + 78 files changed, 2615 insertions(+), 1728 deletions(-) create mode 100644 java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexConfigure.java create mode 100644 java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexFeature.java create mode 100644 java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexFeaturesHolder.java create mode 100644 java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexReaderBase.java create mode 100644 java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexerBuilderParametersProvider.java rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains/search => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/CachedRelevantStaticMethodSearcher.java (76%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/ChainCompletionStringUtil.java (83%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains/search => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/ChainRelevance.java (82%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains/search => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/ChainsSearcher.java (77%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains/search => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/MaxSizeTreeSet.java (86%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains/search => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/MethodChainsSearchUtil.java (76%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains/search => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/MethodsChain.java (87%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains/search => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/MethodsChainLookupRangingHelper.java (87%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains/search => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/ParametersMatcher.java (79%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains/search => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/SearchInitializer.java (58%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/completion/CompletionContributorPatternUtil.java (70%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/completion/MethodsChainsCompletionContributor.java (79%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/completion/MethodsChainsWeigher.java (82%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/completion/lookup/ChainCompletionLookupElementUtil.java (71%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/completion/lookup/ChainCompletionMethodCallLookupElement.java (82%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/completion/lookup/ChainCompletionNewVariableLookupElement.java (88%) create mode 100644 java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/WeightableChainLookupElement.java rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/completion/lookup/sub/GetterLookupSubLookupElement.java (55%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/completion/lookup/sub/StaticMethodSubLookupElement.java (67%) create mode 100644 java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/sub/SubLookupElement.java create mode 100644 java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/sub/VariableSubLookupElement.java rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains/completion => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/context/ChainCompletionContext.java (78%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains/completion => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/context/ChainCompletionContextStringUtil.java (62%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains/completion => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/context/ContextRelevantStaticMethod.java (57%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains/completion => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/context/ContextRelevantVariableGetter.java (52%) rename java/{java-impl/src/com/intellij/codeInsight/completion/methodChains/completion => compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch}/context/ContextUtil.java (93%) create mode 100644 java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/MethodIncompleteSignatureResolver.java create mode 100644 java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/impl/MethodsUsageIndexConfigure.java create mode 100644 java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/impl/MethodsUsageIndexReader.java rename java/{java-impl/src/com/intellij => compiler/impl/src/com/intellij/compiler}/compilerOutputIndex/impl/UsageIndexValue.java (60%) delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/WeightableChainLookupElement.java delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/SubLookupElement.java delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/VariableSubLookupElement.java delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchService.java delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/WeightAware.java delete mode 100644 java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/ArrayListDataExternalizer.java delete mode 100644 java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashSetDataExternalizer.java delete mode 100644 java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/AsmUtil.java delete mode 100644 java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/CompilerOutputFilesUtil.java delete mode 100644 java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/FileVisitorService.java delete mode 100644 java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java delete mode 100644 java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexFeature.java delete mode 100644 java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexUtil.java delete mode 100644 java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java delete mode 100644 java/java-impl/src/com/intellij/compilerOutputIndex/impl/GuavaHashMultiSetExternalizer.java delete mode 100644 java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignatureChain.java delete mode 100644 java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodsUsageIndex.java delete mode 100644 java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassNotShowed2/TestCompletion.java delete mode 100644 java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassNotShowed2/TestIndex.java create mode 100644 java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassShowed2/TestCompletion.java create mode 100644 java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassShowed2/TestIndex.java delete mode 100644 java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesNotShowed/TestCompletion.java delete mode 100644 java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesNotShowed/TestIndex.java create mode 100644 java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesShowed/TestCompletion.java create mode 100644 java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesShowed/TestIndex.java create mode 100644 jps/jps-builders/src/META-INF/services/org.jetbrains.jps.classFilesIndex.indexer.api.ClassFileIndexerFactory create mode 100644 jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/AsmUtil.java create mode 100644 jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/TObjectIntHashMapExternalizer.java create mode 100644 jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFileIndexer.java create mode 100644 jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFileIndexerFactory.java create mode 100644 jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndexStorage.java create mode 100644 jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndexWriter.java create mode 100644 jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndicesBuilder.java create mode 100644 jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/IndexState.java rename {java/java-impl/src/com/intellij/compilerOutputIndex => jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer}/impl/MethodIncompleteSignature.java (58%) create mode 100644 jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodUsageIndexKey.java create mode 100644 jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodsUsageIndexer.java create mode 100644 jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodsUsageIndexerFactory.java diff --git a/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexConfigure.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexConfigure.java new file mode 100644 index 000000000000..0fe4f51f7b41 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexConfigure.java @@ -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 { + + public abstract String getIndexCanonicalName(); + + public abstract int getIndexVersion(); + + public abstract Class getIndexerBuilderClass(); + + public abstract ClassFilesIndexReaderBase createIndexReader(final Project project); + + public void prepareToIndexing(final Project project) { + ClassFilesIndexReaderBase.checkIndexAndRecreateIfNeed(project, getIndexVersion(), getIndexCanonicalName()); + } + +} diff --git a/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexFeature.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexFeature.java new file mode 100644 index 000000000000..c882349b78f2 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexFeature.java @@ -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 myRequiredIndicesConfigures; + + ClassFilesIndexFeature(@NotNull final String key, + @NotNull final Collection requiredIndicesConfigures) { + myKey = key; + myRequiredIndicesConfigures = requiredIndicesConfigures; + } + + ClassFilesIndexFeature(@NotNull final String key, @NotNull final MethodsUsageIndexConfigure requiredConfigure) { + this(key, Collections.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 getRequiredIndicesConfigures() { + return myRequiredIndicesConfigures; + } +} diff --git a/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexFeaturesHolder.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexFeaturesHolder.java new file mode 100644 index 000000000000..5d5ff0c11c98 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexFeaturesHolder.java @@ -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 myEnabledIndexReaders = + new HashMap(); + private final Map myEnabledFeatures = new HashMap(); + + 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 availableConfiguresVisitor, + final Processor 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 newIndices = + new HashMap(); + 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 getAvailableIndexReader(final Class 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 + } +} diff --git a/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexReaderBase.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexReaderBase.java new file mode 100644 index 000000000000..934e106f6ab8 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexReaderBase.java @@ -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 { + + private final static Logger LOG = Logger.getInstance(ClassFilesIndexReaderBase.class); + @Nullable + protected final ClassFilesIndexStorage 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 keyDescriptor, + final DataExternalizer valueExternalizer, + final String canonicalIndexName, + final int indexVersion, + final Project project) { + if (checkIndexAndRecreateIfNeed(project, indexVersion, canonicalIndexName)) { + ClassFilesIndexStorage index = null; + IOException exception = null; + final File projectBuildSystemDirectory = BuildManager.getInstance().getProjectSystemDirectory(project); + final File indexDir = ClassFilesIndexStorage.getIndexDir(canonicalIndexName, projectBuildSystemDirectory); + try { + index = new ClassFilesIndexStorage(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; + } + } + +} diff --git a/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexerBuilderParametersProvider.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexerBuilderParametersProvider.java new file mode 100644 index 000000000000..11e6fe456656 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/api/index/ClassFilesIndexerBuilderParametersProvider.java @@ -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 getVMArguments() { + final List args = new ArrayList(); + myIndicesHolder.visitEnabledConfigures( + new Processor() { + @Override + public boolean process(final ClassFilesIndexConfigure availableConfigure) { + final String className = availableConfigure.getIndexerBuilderClass().getCanonicalName(); + args.add(className); + return true; + } + }, new Processor() { + @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(); + } + } + +} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedRelevantStaticMethodSearcher.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/CachedRelevantStaticMethodSearcher.java similarity index 76% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedRelevantStaticMethodSearcher.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/CachedRelevantStaticMethodSearcher.java index ef11e727c959..e8c3d4e3b347 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedRelevantStaticMethodSearcher.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/CachedRelevantStaticMethodSearcher.java @@ -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 myCachedResolveResults = new HashMap(); - 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 indexValues = myIndex.getValues(resultQualifiedClassName); - if (indexValues != null) { + final TreeSet indexValues = myIndexReader.getMethods(resultQualifiedClassName); + if (!indexValues.isEmpty()) { int occurrences = 0; final List relevantMethods = new ArrayList(); 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); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/ChainCompletionStringUtil.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/ChainCompletionStringUtil.java similarity index 83% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/ChainCompletionStringUtil.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/ChainCompletionStringUtil.java index 688fadaf613c..a46ddae23a4b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/ChainCompletionStringUtil.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/ChainCompletionStringUtil.java @@ -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; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainRelevance.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/ChainRelevance.java similarity index 82% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainRelevance.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/ChainRelevance.java index 0aa7231ead1d..0ba1289fee7a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainRelevance.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/ChainRelevance.java @@ -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; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainsSearcher.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/ChainsSearcher.java similarity index 77% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainsSearcher.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/ChainsSearcher.java index 5ecba096b7bb..0270631d1df3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainsSearcher.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/ChainsSearcher.java @@ -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 search(final MethodChainsSearchService searchService, + public static List search(final MethodsUsageIndexReader indexReader, final String targetQName, final Set contextQNames, final int maxResultSize, final int pathMaximalLength, - final FactoryMap resolver, - final Set 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 resolver, - final MethodChainsSearchService searchService, - final Set excludedParamsTypesQNames) { - return new SearchInitializer(searchService.getMethods(targetQName), resolver, targetQName, excludedParamsTypesQNames); + final MethodsUsageIndexReader indexReader, + final Set excludedParamsTypesQNames, + final ChainCompletionContext context) { + return new SearchInitializer(indexReader.getMethods(targetQName), targetQName, excludedParamsTypesQNames, context); } @NotNull - private static List search(final MethodChainsSearchService searchService, + private static List search(final MethodsUsageIndexReader indexReader, final SearchInitializer initializer, final Set toSet, final int pathMaximalLength, final int maxResultSize, - final FactoryMap resolver, final String targetQName, - final Set excludedParamsTypesQNames, final ChainCompletionContext context) { - final Set allExcludedNames = MethodChainsSearchUtil.unionToHashSet(excludedParamsTypesQNames, targetQName); + final Set allExcludedNames = MethodChainsSearchUtil.unionToHashSet(context.getExcludedQNames(), targetQName); final SearchInitializer.InitResult initResult = initializer.init(Collections.emptySet()); final Map knownDistance = initResult.getChains(); @@ -70,18 +80,18 @@ public final class ChainsSearcher { @Override public WeightAware> fun( final WeightAware methodIncompleteSignatureWeightAware) { + final MethodIncompleteSignature + underlying = + methodIncompleteSignatureWeightAware + .getUnderlying(); return new WeightAware>( new Pair( + 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> currentVertex = q.poll(); @@ -108,7 +118,7 @@ public final class ChainsSearcher { result.add(currentVertex.getUnderlying().getSecond()); continue; } - final SortedSet nextMethods = searchService.getMethods(currentVertexUnderlying.getFirst().getOwner()); + final SortedSet nextMethods = indexReader.getMethods(currentVertexUnderlying.getFirst().getOwner()); final MaxSizeTreeSet> currentSignatures = new MaxSizeTreeSet>(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(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(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 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 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(); } @@ -286,8 +294,8 @@ public final class ChainsSearcher { }); } - private static List findSimilar(final List chains, final ChainCompletionContext context) { - final ResultHolder resultHolder = new ResultHolder(context); + private static List findSimilar(final List chains, final PsiManager psiManager) { + final ResultHolder resultHolder = new ResultHolder(psiManager); for (final MethodsChain chain : chains) { resultHolder.add(chain); } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MaxSizeTreeSet.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/MaxSizeTreeSet.java similarity index 86% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MaxSizeTreeSet.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/MaxSizeTreeSet.java index 535cf090df2c..dc278970864c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MaxSizeTreeSet.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/MaxSizeTreeSet.java @@ -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 implements NavigableSet { - @NotNull private final NavigableSet myUnderlying; private final int myMaxSize; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchUtil.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/MethodChainsSearchUtil.java similarity index 76% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchUtil.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/MethodChainsSearchUtil.java index ae0df9554dc4..4d7a73296780 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchUtil.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/MethodChainsSearchUtil.java @@ -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; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChain.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/MethodsChain.java similarity index 87% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChain.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/MethodsChain.java index a4b055b7e458..8da26d3c3617 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChain.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/MethodsChain.java @@ -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; } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChainLookupRangingHelper.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/MethodsChainLookupRangingHelper.java similarity index 87% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChainLookupRangingHelper.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/MethodsChainLookupRangingHelper.java index 0389f76b35fb..56667cd92f7c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChainLookupRangingHelper.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/MethodsChainLookupRangingHelper.java @@ -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) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ParametersMatcher.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/ParametersMatcher.java similarity index 79% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ParametersMatcher.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/ParametersMatcher.java index fd4d5d7c2d0b..a25bde60f9b8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ParametersMatcher.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/ParametersMatcher.java @@ -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; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/SearchInitializer.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/SearchInitializer.java similarity index 58% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/SearchInitializer.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/SearchInitializer.java index 54e6d01767e2..7b1fd2b90f21 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/SearchInitializer.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/SearchInitializer.java @@ -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> myVertices; - private final LinkedHashMap myChains; - private final FactoryMap myResolver; + private final LinkedHashMap> myChains; + private final ChainCompletionContext myContext; public SearchInitializer(final SortedSet indexValues, - final FactoryMap resolver, final String targetQName, - final Set excludedParamsTypesQNames) { - myResolver = resolver; + final Set excludedParamsTypesQNames, + final ChainCompletionContext context) { + myContext = context; final int size = indexValues.size(); - myVertices = new ArrayList>(size); - myChains = new LinkedHashMap(size); + myChains = new LinkedHashMap>(size); add(indexValues, MethodChainsSearchUtil.unionToHashSet(excludedParamsTypesQNames, targetQName)); } @@ -45,30 +59,27 @@ public class SearchInitializer { private boolean add(final UsageIndexValue indexValue, final Set 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(methodInvocation, occurrences)); + myChains.put(methodInvocation, Pair.create(methodsChain, occurrences)); return true; } return false; } public InitResult init(final Set excludedEdgeNames) { - final int size = myVertices.size(); + final int size = myChains.size(); final List> initedVertexes = new ArrayList>(size); final LinkedHashMap initedChains = new LinkedHashMap(size); - final Iterator> chainsIterator = myChains.entrySet().iterator(); - for (final WeightAware vertex : myVertices) { - final Map.Entry 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> entry : myChains.entrySet()) { + final MethodIncompleteSignature signature = entry.getKey(); + if (!excludedEdgeNames.contains(signature.getName())) { + initedVertexes.add(new WeightAware(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; } } -} +} \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/CompletionContributorPatternUtil.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/CompletionContributorPatternUtil.java similarity index 70% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/CompletionContributorPatternUtil.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/CompletionContributorPatternUtil.java index f020afa18141..3ac278fc3e17 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/CompletionContributorPatternUtil.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/CompletionContributorPatternUtil.java @@ -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; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsCompletionContributor.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/MethodsChainsCompletionContributor.java similarity index 79% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsCompletionContributor.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/MethodsChainsCompletionContributor.java index 9b602dc63dfa..a7be2c7cc2a7 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsCompletionContributor.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/MethodsChainsCompletionContributor.java @@ -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 searchForLookups(final String targetClassQName, final Set contextRelevantTypes, final ChainCompletionContext completionContext) { - final MethodChainsSearchService searchService = new MethodChainsSearchService(completionContext.getProject()); + final MethodsUsageIndexReader methodsUsageIndexReader = MethodsUsageIndexReader.getInstance(completionContext.getProject()); final List 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 inheritorFilteredSearchResult = new SmartList(); //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 createNotDeprecatedMethodsResolver(final JavaPsiFacade javaPsiFacade, - final GlobalSearchScope scope) { - return new FactoryMap() { - @Nullable - @Override - protected PsiMethod[] create(final MethodIncompleteSignature signature) { - return signature.resolveNotDeprecated(javaPsiFacade, scope); - } - }; - } - } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsWeigher.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/MethodsChainsWeigher.java similarity index 82% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsWeigher.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/MethodsChainsWeigher.java index 57293cae1e12..7b6551fb2b0a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsWeigher.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/MethodsChainsWeigher.java @@ -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; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionLookupElementUtil.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/ChainCompletionLookupElementUtil.java similarity index 71% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionLookupElementUtil.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/ChainCompletionLookupElementUtil.java index 65be8928c5d9..a8315728aaf3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionLookupElementUtil.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/ChainCompletionLookupElementUtil.java @@ -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; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionMethodCallLookupElement.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/ChainCompletionMethodCallLookupElement.java similarity index 82% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionMethodCallLookupElement.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/ChainCompletionMethodCallLookupElement.java index f7a62d6ccc02..8a1b641905ff 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionMethodCallLookupElement.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/ChainCompletionMethodCallLookupElement.java @@ -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; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionNewVariableLookupElement.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/ChainCompletionNewVariableLookupElement.java similarity index 88% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionNewVariableLookupElement.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/ChainCompletionNewVariableLookupElement.java index b775640edbdb..3f1343349e77 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionNewVariableLookupElement.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/ChainCompletionNewVariableLookupElement.java @@ -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; diff --git a/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/WeightableChainLookupElement.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/WeightableChainLookupElement.java new file mode 100644 index 000000000000..68fb531edfa0 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/WeightableChainLookupElement.java @@ -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 { + private final ChainRelevance myChainRelevance; + + public WeightableChainLookupElement(final @NotNull LookupElement delegate, final ChainRelevance relevance) { + super(delegate); + myChainRelevance = relevance; + } + + public ChainRelevance getChainRelevance() { + return myChainRelevance; + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/GetterLookupSubLookupElement.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/sub/GetterLookupSubLookupElement.java similarity index 55% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/GetterLookupSubLookupElement.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/sub/GetterLookupSubLookupElement.java index e6b84107c6be..03fc9349c8d3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/GetterLookupSubLookupElement.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/sub/GetterLookupSubLookupElement.java @@ -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; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/StaticMethodSubLookupElement.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/sub/StaticMethodSubLookupElement.java similarity index 67% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/StaticMethodSubLookupElement.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/sub/StaticMethodSubLookupElement.java index 88d8b01529c0..1807db61bd02 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/StaticMethodSubLookupElement.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/sub/StaticMethodSubLookupElement.java @@ -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; diff --git a/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/sub/SubLookupElement.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/sub/SubLookupElement.java new file mode 100644 index 000000000000..5840af7398c4 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/sub/SubLookupElement.java @@ -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(); +} diff --git a/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/sub/VariableSubLookupElement.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/sub/VariableSubLookupElement.java new file mode 100644 index 000000000000..38e0e2e5790a --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/completion/lookup/sub/VariableSubLookupElement.java @@ -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 + */ +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; + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContext.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/ChainCompletionContext.java similarity index 78% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContext.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/ChainCompletionContext.java index bb8d92d0839f..8d7903639518 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContext.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/ChainCompletionContext.java @@ -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 myExcludedQNames; private final GlobalSearchScope myResolveScope; private final Project myProject; + private final PsiManager myPsiManager; + private final FactoryMap myNotDeprecatedMethodsResolver; private final NotNullLazyValue> contextTypesQNames = new NotNullLazyValue>() { @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 HashSet unionToHashSet(final Collection... collections) { final HashSet res = new HashSet(); for (final Collection set : collections) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContextStringUtil.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/ChainCompletionContextStringUtil.java similarity index 62% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContextStringUtil.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/ChainCompletionContextStringUtil.java index a9b1903ea803..41ed087d3b71 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContextStringUtil.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/ChainCompletionContextStringUtil.java @@ -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; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantStaticMethod.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/ContextRelevantStaticMethod.java similarity index 57% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantStaticMethod.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/ContextRelevantStaticMethod.java index 23b1c26be7f4..561c9d9144f8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantStaticMethod.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/ContextRelevantStaticMethod.java @@ -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; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantVariableGetter.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/ContextRelevantVariableGetter.java similarity index 52% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantVariableGetter.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/ContextRelevantVariableGetter.java index fec1cfd6b61e..8fa1e5a40193 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantVariableGetter.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/ContextRelevantVariableGetter.java @@ -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; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextUtil.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/ContextUtil.java similarity index 93% rename from java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextUtil.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/ContextUtil.java index da17e4d659e2..fe7a49c85be5 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextUtil.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/ContextUtil.java @@ -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, diff --git a/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/MethodIncompleteSignatureResolver.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/MethodIncompleteSignatureResolver.java new file mode 100644 index 000000000000..3a659baef1d6 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/chainsSearch/context/MethodIncompleteSignatureResolver.java @@ -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 create(final JavaPsiFacade javaPsiFacade, final GlobalSearchScope scope) { + return new FactoryMap() { + @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 filtered = new ArrayList(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() { + @Override + public int compare(final PsiMethod o1, final PsiMethod o2) { + return o1.getParameterList().getParametersCount() - o2.getParameterList().getParametersCount(); + } + }); + } + return filtered.toArray(new PsiMethod[filtered.size()]); + } +} diff --git a/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/impl/MethodsUsageIndexConfigure.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/impl/MethodsUsageIndexConfigure.java new file mode 100644 index 000000000000..087d195d1bc0 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/impl/MethodsUsageIndexConfigure.java @@ -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> { + + 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 getIndexerBuilderClass() { + return MethodsUsageIndexerFactory.class; + } + + @Override + public ClassFilesIndexReaderBase> createIndexReader(final Project project) { + return new MethodsUsageIndexReader(project, getIndexCanonicalName(), getIndexVersion()); + } +} diff --git a/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/impl/MethodsUsageIndexReader.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/impl/MethodsUsageIndexReader.java new file mode 100644 index 000000000000..11ccf7ede0ad --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/impl/MethodsUsageIndexReader.java @@ -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 + */ +public class MethodsUsageIndexReader extends ClassFilesIndexReaderBase> { + + 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.createDataExternalizer()), + canonicalIndexName, version, project); + } + + @NotNull + public TreeSet getMethods(final String key) { + assert myIndex != null; + final Collection> unReducedValues = myIndex.getData(key); + + final TObjectIntHashMap rawValues = new TObjectIntHashMap(); + for (final TObjectIntHashMap unReducedValue : unReducedValues) { + unReducedValue.forEachEntry(new TObjectIntProcedure() { + @Override + public boolean execute(final MethodIncompleteSignature sign, final int occurrences) { + if (!rawValues.adjustValue(sign, occurrences)) { + rawValues.put(sign, occurrences); + } + return true; + } + }); + } + + final TreeSet values = new TreeSet(); + rawValues.forEachEntry(new TObjectIntProcedure() { + @Override + public boolean execute(MethodIncompleteSignature sign, int occurrences) { + values.add(new UsageIndexValue(sign.toExternalRepresentation(), occurrences)); + return true; + } + }); + return values; + } + +} diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/UsageIndexValue.java b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/impl/UsageIndexValue.java similarity index 60% rename from java/java-impl/src/com/intellij/compilerOutputIndex/impl/UsageIndexValue.java rename to java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/impl/UsageIndexValue.java index f99a0dea18c6..2af22971d5a3 100644 --- a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/UsageIndexValue.java +++ b/java/compiler/impl/src/com/intellij/compiler/compilerOutputIndex/impl/UsageIndexValue.java @@ -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 { return myMethodIncompleteSignature; } - public static DataExternalizer createDataExternalizer() { - final DataExternalizer methodInvocationDataExternalizer = MethodIncompleteSignature.createKeyDescriptor(); - return new DataExternalizer() { - @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; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/WeightableChainLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/WeightableChainLookupElement.java deleted file mode 100644 index 16ee64688c41..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/WeightableChainLookupElement.java +++ /dev/null @@ -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 { - private final ChainRelevance myChainRelevance; - - public WeightableChainLookupElement(final @NotNull LookupElement delegate, final ChainRelevance relevance) { - super(delegate); - myChainRelevance = relevance; - } - - public ChainRelevance getChainRelevance() { - return myChainRelevance; - } -} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/SubLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/SubLookupElement.java deleted file mode 100644 index 7046012d4017..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/SubLookupElement.java +++ /dev/null @@ -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(); -} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/VariableSubLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/VariableSubLookupElement.java deleted file mode 100644 index 894f10b8d15d..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/VariableSubLookupElement.java +++ /dev/null @@ -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 - */ -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; - } -} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchService.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchService.java deleted file mode 100644 index 587945d53fea..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchService.java +++ /dev/null @@ -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 - */ -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 getMethods(final String targetQName) { - final TreeSet value = myMethodsUsageIndex.getValues(targetQName); - if (value != null) { - return value; - } - return EMPTY_SORTED_SET; - } - - public PsiManager getPsiManager() { - return PsiManager.getInstance(getProject()); - } -} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/WeightAware.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/WeightAware.java deleted file mode 100644 index 7fd682457348..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/WeightAware.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.intellij.codeInsight.completion.methodChains.search; - -import org.jetbrains.annotations.NotNull; - -/** - * @author Dmitry Batkovich - */ -public class WeightAware implements Comparable> { - 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 that) { - final int sub = -getWeight() + that.getWeight(); - if (sub != 0) { - return sub; - } - return myUnderlying.hashCode() - that.myUnderlying.hashCode(); - } -} diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/ArrayListDataExternalizer.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/ArrayListDataExternalizer.java deleted file mode 100644 index ac45d255b280..000000000000 --- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/ArrayListDataExternalizer.java +++ /dev/null @@ -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 - */ -public class ArrayListDataExternalizer implements DataExternalizer> { - private final DataExternalizer myDataExternalizer; - - public ArrayListDataExternalizer(final DataExternalizer dataExternalizer) { - myDataExternalizer = dataExternalizer; - } - - @Override - public void save(final DataOutput out, final List list) throws IOException { - out.writeInt(list.size()); - for (final E element : list) { - myDataExternalizer.save(out, element); - } - } - - @Override - public ArrayList read(final DataInput in) throws IOException { - final int size = in.readInt(); - final ArrayList list = new ArrayList(size); - for (int i = 0; i < size; i++) { - list.add(myDataExternalizer.read(in)); - } - return list; - } -} diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashSetDataExternalizer.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashSetDataExternalizer.java deleted file mode 100644 index fbc538e8554d..000000000000 --- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashSetDataExternalizer.java +++ /dev/null @@ -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 implements DataExternalizer> { - private final DataExternalizer myDataExternalizer; - - public HashSetDataExternalizer(final DataExternalizer myDataExternalizer) { - this.myDataExternalizer = myDataExternalizer; - } - - @Override - public void save(final DataOutput out, final Set set) throws IOException { - out.writeInt(set.size()); - for (final K k : set) { - myDataExternalizer.save(out, k); - } - } - - @Override - public HashSet read(final DataInput in) throws IOException { - final int size = in.readInt(); - final HashSet set = new HashSet(size); - for (int i = 0; i < size; i++) { - set.add(myDataExternalizer.read(in)); - } - return set; - } -} diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/AsmUtil.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/AsmUtil.java deleted file mode 100644 index 0ed09484e3ad..000000000000 --- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/AsmUtil.java +++ /dev/null @@ -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 - */ -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 qualifiedClassNames = new ArrayList(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 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); - } -} diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/CompilerOutputFilesUtil.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/CompilerOutputFilesUtil.java deleted file mode 100644 index ef4137079f95..000000000000 --- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/CompilerOutputFilesUtil.java +++ /dev/null @@ -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 - */ -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 fileConsumer) { - for (final Module module : ModuleManager.getInstance(project).getModules()) { - iterateModuleClassFiles(module, fileConsumer); - } - } - - public static void iterateModuleClassFiles(@NotNull final Module module, @NotNull final Consumer 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 fileConsumer) { - iterateClassFilesOverRoot(file, fileConsumer, new HashSet()); - } - - private static void iterateClassFilesOverRoot(@NotNull final File file, final Consumer fileConsumer, final Set 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); - } - } - } -} diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/FileVisitorService.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/FileVisitorService.java deleted file mode 100644 index 9a7f00be3dc3..000000000000 --- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/FileVisitorService.java +++ /dev/null @@ -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 - */ -public interface FileVisitorService { - - interface Visitor { - void visit(File file); - } - - void visit(final Consumer visitor); - - class ProjectClassFiles implements FileVisitorService { - private final Project myProject; - - public ProjectClassFiles(final Project project) { - myProject = project; - } - - @Override - public void visit(final Consumer 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 visitor) { - //noinspection ConstantConditions - for (final File file : myDir.listFiles()) { - if (file.getName().endsWith(CompilerOutputFilesUtil.CLASS_FILES_SUFFIX)) { - visitor.consume(file); - } - } - } - } -} - diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java deleted file mode 100644 index cf4de2562378..000000000000 --- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java +++ /dev/null @@ -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 { - public final static ExtensionPointName EXTENSION_POINT_NAME = - ExtensionPointName.create("com.intellij.java.compilerOutputIndex"); - - private final static Logger LOG = Logger.getInstance(CompilerOutputBaseIndex.class); - private final KeyDescriptor myKeyDescriptor; - private final DataExternalizer myValueExternalizer; - protected volatile MapReduceIndex myIndex; - - protected final Project myProject; - - protected volatile AtomicBoolean myInitialized = new AtomicBoolean(false); - - public CompilerOutputBaseIndex(final KeyDescriptor keyDescriptor, final DataExternalizer valueExternalizer, final Project project) { - myProject = project; - myKeyDescriptor = keyDescriptor; - myValueExternalizer = valueExternalizer; - } - - public final boolean initIfNeed() { - if (myInitialized.compareAndSet(false, true)) { - final MapReduceIndex index; - final Ref rewriteIndex = new Ref(false); - try { - final ID indexId = getIndexId(); - if (!IndexInfrastructure.getIndexRootDir(indexId).exists()) { - rewriteIndex.set(true); - } - final File storageFile = getStorageFile(indexId); - final MapIndexStorage indexStorage = IOUtil.openCleanOrResetBroken( - new ThrowableComputable, IOException>() { - @Override - public MapIndexStorage compute() throws IOException { - return new MapIndexStorage(storageFile, myKeyDescriptor, myValueExternalizer, 1024); - } - }, - new Runnable() { - @Override - public void run() { - IOUtil.deleteAllFilesStartingWith(storageFile); - rewriteIndex.set(true); - } - } - ); - index = new MapReduceIndex(indexId, getIndexer(), indexStorage); - index.setInputIdToDataKeysIndex(new Factory>>() { - @Override - public PersistentHashMap> create() { - try { - return IOUtil.openCleanOrResetBroken( - new ThrowableComputable>, IOException>() { - @Override - public PersistentHashMap> compute() throws IOException { - return FileBasedIndexImpl.createIdToDataKeysIndex(indexId, myKeyDescriptor, new MemoryIndexStorage(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 getIndexId(); - - protected abstract int getVersion(); - - protected abstract DataIndexer 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 generateIndexId(final String indexName) { - return CompilerOutputIndexUtil.generateIndexId(indexName, myProject); - } -} diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexFeature.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexFeature.java deleted file mode 100644 index 7a8169fc1a74..000000000000 --- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexFeature.java +++ /dev/null @@ -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 - .>newArrayList(MethodsUsageIndex.class)); - - @NotNull - private final String myKey; - @NotNull - private final Collection> myRequiredIndexes; - - CompilerOutputIndexFeature(@NotNull final String key, - @NotNull final Collection> requiredIndexes) { - myKey = key; - myRequiredIndexes = requiredIndexes; - } - - CompilerOutputIndexFeature(@NotNull final String key, @NotNull final Class requiredIndex) { - this(key, Collections.>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> getRequiredIndexes() { - return myRequiredIndexes; - } -} diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexUtil.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexUtil.java deleted file mode 100644 index 3ca255162ec3..000000000000 --- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexUtil.java +++ /dev/null @@ -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 ID 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)); - } -} diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java deleted file mode 100644 index fed4c02502b0..000000000000 --- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java +++ /dev/null @@ -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 myIndexTypeQNameToIndex = new HashMap(); - private volatile PersistentHashMap myFileTimestampsIndex; - private volatile PersistentEnumeratorDelegate myFileEnumerator; - - private final Lock myLock = new ReentrantLock(); - private final AtomicBoolean myInProgress = new AtomicBoolean(false); - @SuppressWarnings("SetReplaceableByEnumSet") - private final Set myCurrentEnabledFeatures = new ConcurrentHashSet(); - 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 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> 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> indexes) { - final Collection indexesToReindex = new ArrayList(); - for (final Class 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> indexes) { - final Set> toRemove = ContainerUtil.newHashSet(indexes); - for (final CompilerOutputIndexFeature feature : CompilerOutputIndexFeature.values()) { - if (feature.getRegistryValue().asBoolean()) { - for (final Class 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, IOException>() { - @Override - public PersistentEnumeratorDelegate compute() throws IOException { - return new PersistentEnumeratorDelegate(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, IOException>() { - @Override - public PersistentHashMap compute() throws IOException { - return new PersistentHashMap(storageFile, - new EnumeratorStringDescriptor(), new DataExternalizer() { - @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 indexes, - final boolean force, - final @NotNull ProgressIndicator indicator) { - myLock.lock(); - try { - indicator.setText(TITLE); - visitorService.visit(new Consumer() { - @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 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 getIndex(final Class 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; - } -} diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/GuavaHashMultiSetExternalizer.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/GuavaHashMultiSetExternalizer.java deleted file mode 100644 index fe36071af30a..000000000000 --- a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/GuavaHashMultiSetExternalizer.java +++ /dev/null @@ -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 implements DataExternalizer> { - private final DataExternalizer myKeyDataExternalizer; - - public GuavaHashMultiSetExternalizer(final DataExternalizer keyDataExternalizer) { - myKeyDataExternalizer = keyDataExternalizer; - } - - @Override - public void save(final DataOutput out, final Multiset multiset) throws IOException { - final Set> entries = multiset.entrySet(); - out.writeInt(entries.size()); - for (final Multiset.Entry entry : entries) { - myKeyDataExternalizer.save(out, entry.getElement()); - out.writeInt(entry.getCount()); - } - } - - @Override - public Multiset read(final DataInput in) throws IOException { - final int size = in.readInt(); - final Multiset multiset = HashMultiset.create(size); - for (int i = 0; i < size; i++) { - multiset.add(myKeyDataExternalizer.read(in), in.readInt()); - } - return multiset; - } -} diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignatureChain.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignatureChain.java deleted file mode 100644 index a11e731f3d34..000000000000 --- a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignatureChain.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.intellij.compilerOutputIndex.impl; - -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -/** - * @author Dmitry Batkovich - */ -public class MethodIncompleteSignatureChain { - private final List myMethodIncompleteSignatures; - - public MethodIncompleteSignatureChain(final List methodIncompleteSignatures) { - myMethodIncompleteSignatures = methodIncompleteSignatures; - } - - public List 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); - } -} diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodsUsageIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodsUsageIndex.java deleted file mode 100644 index 78a63bd41a17..000000000000 --- a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodsUsageIndex.java +++ /dev/null @@ -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 - */ -public class MethodsUsageIndex extends CompilerOutputBaseIndex> { - - 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.createKeyDescriptor()), project); - } - - @Override - protected DataIndexer, ClassNode> getIndexer() { - return new DataIndexer, ClassNode>() { - @NotNull - @Override - public Map> map(final ClassNode inputData) { - final Map> map = new HashMap>(); - 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> getIndexId() { - return generateIndexId("MethodsUsage"); - } - - @Override - protected int getVersion() { - return 1; - } - - public TreeSet getValues(final String key) { - try { - final ValueContainer> valueContainer = myIndex.getData(key); - final Multiset rawValues = HashMultiset.create(); - valueContainer.forEach(new ValueContainer.ContainerAction>() { - @Override - public boolean perform(final int id, final Multiset values) { - for (final Multiset.Entry 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> map, - final String internalClassName, - final MethodIncompleteSignature mi) { - final String className = AsmUtil.getQualifiedClassName(internalClassName); - Multiset occurrences = map.get(className); - if (occurrences == null) { - occurrences = HashMultiset.create(); - map.put(className, occurrences); - } - occurrences.add(mi); - } - - private static TreeSet rawValuesToValues(final Multiset rawValues) { - final TreeSet values = new TreeSet(); - for (final Multiset.Entry entry : rawValues.entrySet()) { - values.add(new UsageIndexValue(entry.getElement().toExternalRepresentation(), entry.getCount())); - } - return values; - } -} diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassNotShowed2/TestCompletion.java b/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassNotShowed2/TestCompletion.java deleted file mode 100644 index 2b9ce1560f24..000000000000 --- a/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassNotShowed2/TestCompletion.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @author Dmitry Batkovich - */ - - -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 = - } -} diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassNotShowed2/TestIndex.java b/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassNotShowed2/TestIndex.java deleted file mode 100644 index 95e4761d3489..000000000000 --- a/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassNotShowed2/TestIndex.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @author Dmitry Batkovich - */ -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; - } -} diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassShowed2/TestCompletion.java b/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassShowed2/TestCompletion.java new file mode 100644 index 000000000000..491d3793836c --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassShowed2/TestCompletion.java @@ -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 + */ + + +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 = + } +} diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassShowed2/TestIndex.java b/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassShowed2/TestIndex.java new file mode 100644 index 000000000000..4e2c417b12f0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassShowed2/TestIndex.java @@ -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 + */ +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; + } +} diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesNotShowed/TestCompletion.java b/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesNotShowed/TestCompletion.java deleted file mode 100644 index 8fdad22c3b4d..000000000000 --- a/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesNotShowed/TestCompletion.java +++ /dev/null @@ -1,24 +0,0 @@ -import java.jang.String; - -/** - * @author Dmitry Batkovich - */ - -class PsiElement { -} - -class PsiClass extends PsiElement { -} - -class PsiElementFactory { - public PsiClass createClass() { - return null; - } -} - -public class TestCompletion { - - public void method(PsiElementFactory f) { - PsiElement e = - } -} diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesNotShowed/TestIndex.java b/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesNotShowed/TestIndex.java deleted file mode 100644 index 85376beb8c57..000000000000 --- a/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesNotShowed/TestIndex.java +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @author Dmitry Batkovich - */ -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; - } -} diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesShowed/TestCompletion.java b/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesShowed/TestCompletion.java new file mode 100644 index 000000000000..885d23431d09 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesShowed/TestCompletion.java @@ -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 + */ + +class PsiElement { +} + +class PsiClass extends PsiElement { +} + +class PsiElementFactory { + public PsiClass createClass() { + return null; + } +} + +public class TestCompletion { + + public void method(PsiElementFactory f) { + PsiElement e = + } +} diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesShowed/TestIndex.java b/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesShowed/TestIndex.java new file mode 100644 index 000000000000..0dd1f15d68fe --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesShowed/TestIndex.java @@ -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 + */ +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; + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/AbstractCompilerAwareTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/AbstractCompilerAwareTest.java index ec1fa5138a34..a733b8aba822 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/AbstractCompilerAwareTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/AbstractCompilerAwareTest.java @@ -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() { + @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()); } } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/MethodChainsCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/MethodChainsCompletionTest.java index f52ec11a844c..680625c38ebf 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/MethodChainsCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/MethodChainsCompletionTest.java @@ -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 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 collection = doCompletion(); - assertAdvisorLookupElementEquals("getInstance().findFile().findElementAt", 2, 8, 3, 0, assertOneElement(collection)); + final List 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 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 targetLookupElements = new SmartList(); 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; } diff --git a/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.classFilesIndex.indexer.api.ClassFileIndexerFactory b/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.classFilesIndex.indexer.api.ClassFileIndexerFactory new file mode 100644 index 000000000000..0376d9ebbb94 --- /dev/null +++ b/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.classFilesIndex.indexer.api.ClassFileIndexerFactory @@ -0,0 +1 @@ +org.jetbrains.jps.classFilesIndex.indexer.impl.MethodsUsageIndexerFactory diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/AsmUtil.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/AsmUtil.java new file mode 100644 index 000000000000..dd74d665e362 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/AsmUtil.java @@ -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 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); + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/TObjectIntHashMapExternalizer.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/TObjectIntHashMapExternalizer.java new file mode 100644 index 000000000000..c75414079b86 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/TObjectIntHashMapExternalizer.java @@ -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 implements DataExternalizer> { + private final DataExternalizer myKeyDataExternalizer; + + public TObjectIntHashMapExternalizer(final DataExternalizer keyDataExternalizer) { + myKeyDataExternalizer = keyDataExternalizer; + } + + @Override + public void save(final DataOutput out, final TObjectIntHashMap map) throws IOException { + out.writeInt(map.size()); + try { + map.forEachEntry(new TObjectIntProcedure() { + @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 read(final DataInput in) throws IOException { + final int size = in.readInt(); + final TObjectIntHashMap map = new TObjectIntHashMap(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; + } + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFileIndexer.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFileIndexer.java new file mode 100644 index 000000000000..b35bbca93a3a --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFileIndexer.java @@ -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 { + private final String myIndexCanonicalName; + + public ClassFileIndexer(final String indexCanonicalName) { + myIndexCanonicalName = indexCanonicalName; + } + + @NotNull + public abstract Map map(ClassReader inputData); + + public abstract KeyDescriptor getKeyDescriptor(); + + public abstract DataExternalizer getDataExternalizer(); + + public String getIndexCanonicalName() { + return myIndexCanonicalName; + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFileIndexerFactory.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFileIndexerFactory.java new file mode 100644 index 000000000000..cc06cbe9a21f --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFileIndexerFactory.java @@ -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 { + + ClassFileIndexer create(); + +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndexStorage.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndexStorage.java new file mode 100644 index 000000000000..115a3605384e --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndexStorage.java @@ -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 + *

+ * synchronization only on write actions + */ +public class ClassFilesIndexStorage { + 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 myKeyDescriptor; + private final DataExternalizer myValueExternalizer; + private final Lock myWriteLock = new ReentrantLock(); + private PersistentHashMap> myMap; + @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized") private SLRUCache> myCache; + + public ClassFilesIndexStorage(final File indexDir, final KeyDescriptor keyDescriptor, final DataExternalizer valueExternalizer) + throws IOException { + myIndexFile = getIndexFile(indexDir); + myKeyDescriptor = keyDescriptor; + myValueExternalizer = valueExternalizer; + initialize(); + } + + private void initialize() throws IOException { + myMap = new PersistentHashMap>(myIndexFile, myKeyDescriptor, + createValueContainerExternalizer(myValueExternalizer), + INITIAL_INDEX_SIZE); + myCache = new SLRUCache>(CACHE_QUEUES_SIZE, CACHE_QUEUES_SIZE) { + @NotNull + @Override + public CompiledDataValueContainer createValue(final K key) { + try { + final CompiledDataValueContainer valueContainer = myMap.get(key); + if (valueContainer != null) { + return valueContainer; + } + } + catch (final IOException e) { + throw new RuntimeException(e); + } + return new CompiledDataValueContainer(); + } + + @Override + protected void onDropFromCache(final K key, final CompiledDataValueContainer value) { + try { + myMap.put(key, value); + } + catch (final IOException e) { + throw new RuntimeException(e); + } + } + }; + } + + public Collection 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 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 { + private final THashMap myUnderlying; + + private CompiledDataValueContainer(final THashMap map) { + myUnderlying = map; + } + + private CompiledDataValueContainer() { + this(new THashMap()); + } + + private void putValue(final String inputId, final V value) { + myUnderlying.put(inputId, value); + } + + public Collection 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 DataExternalizer> createValueContainerExternalizer(final DataExternalizer valueExternalizer) { + final DataExternalizer stringDataExternalizer = new EnumeratorStringDescriptor(); + return new DataExternalizer>() { + @Override + public void save(final DataOutput out, final CompiledDataValueContainer value) throws IOException { + final THashMap underlying = value.myUnderlying; + out.writeInt(underlying.size()); + for (final Map.Entry entry : underlying.entrySet()) { + stringDataExternalizer.save(out, entry.getKey()); + valueExternalizer.save(out, entry.getValue()); + } + } + + @Override + public CompiledDataValueContainer read(final DataInput in) throws IOException { + final THashMap map = new THashMap(); + final int size = in.readInt(); + for (int i = 0; i < size; i++) { + map.put(stringDataExternalizer.read(in), valueExternalizer.read(in)); + } + return new CompiledDataValueContainer(map); + } + }; + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndexWriter.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndexWriter.java new file mode 100644 index 000000000000..aded53895000 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndexWriter.java @@ -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 { + private final ClassFileIndexer myIndexer; + private final boolean myEmpty; + protected final ClassFilesIndexStorage myIndex; + + protected ClassFilesIndexWriter(final ClassFileIndexer indexer, final CompileContext compileContext) { + myIndexer = indexer; + final File storageDir = getIndexRoot(compileContext); + final Set 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 index = null; + IOException exception = null; + for (int attempt = 0; attempt < 2; attempt++) { + try { + index = new ClassFilesIndexStorage(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 listFiles(final File dir) { + final String[] containingFileNames = dir.list(); + return containingFileNames == null ? Collections.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 e : myIndexer.map(inputData).entrySet()) { + myIndex.putData(e.getKey(), e.getValue(), id); + } + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndicesBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndicesBuilder.java new file mode 100644 index 000000000000..9159ee3222a7 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndicesBuilder.java @@ -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 myAlreadyExistIndexWriters = new ArrayList(); + private final Collection myNewIndexWriters = new ArrayList(); + + @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 enabledIndicesBuilders = ContainerUtil.newHashSet(System.getProperty(PROPERTY_NAME).split(";")); + final Iterable 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() { + @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 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); + } + } + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/IndexState.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/IndexState.java new file mode 100644 index 000000000000..ba371f9067d1 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/IndexState.java @@ -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); + } + } +} diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignature.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodIncompleteSignature.java similarity index 58% rename from java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignature.java rename to jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodIncompleteSignature.java index c0904bc3e36e..0aac2186f984 100644 --- a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignature.java +++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodIncompleteSignature.java @@ -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 + * @author Dmitry Batkovich */ public class MethodIncompleteSignature { - public static final String CONSTRUCTOR_METHOD_NAME = ""; @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 filtered = new ArrayList(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() { - @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 createKeyDescriptor() { - final EnumeratorStringDescriptor stringDescriptor = new EnumeratorStringDescriptor(); - return new KeyDescriptor() { - @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 filtered = ContainerUtil.filter(methods, NOT_DEPRECATED_CONDITION); - return filtered.toArray(new PsiMethod[filtered.size()]); - } - - private final static Condition NOT_DEPRECATED_CONDITION = new Condition() { - @Override - public boolean value(final PsiMethod method) { - return !method.isDeprecated(); - } - }; - public final static Comparator COMPARATOR = new Comparator() { @Override public int compare(final MethodIncompleteSignature o1, final MethodIncompleteSignature o2) { @@ -174,6 +104,25 @@ public class MethodIncompleteSignature { } }; + public static DataExternalizer createDataExternalizer() { + final EnumeratorStringDescriptor stringDescriptor = new EnumeratorStringDescriptor(); + return new DataExternalizer() { + @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; diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodUsageIndexKey.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodUsageIndexKey.java new file mode 100644 index 000000000000..65eb0e44005b --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodUsageIndexKey.java @@ -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 DATA_EXTERNALIZER = new EnumDataDescriptor(KeyRole.class); + } + + + public static KeyDescriptor createKeyDescriptor() { + final DataExternalizer stringDataExternalizer = new EnumeratorStringDescriptor(); + return new KeyDescriptor() { + @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; + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodsUsageIndexer.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodsUsageIndexer.java new file mode 100644 index 000000000000..85ebcfaa91c1 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodsUsageIndexer.java @@ -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> { + public static final String METHODS_USAGE_INDEX_CANONICAL_NAME = "MethodsUsageIndex"; + + public MethodsUsageIndexer() { + super(METHODS_USAGE_INDEX_CANONICAL_NAME); + } + + @NotNull + @Override + public Map> map(final ClassReader inputData) { + final Map> map = new HashMap>(); + 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 getKeyDescriptor() { + return new EnumeratorStringDescriptor(); + } + + @Override + public DataExternalizer> getDataExternalizer() { + return new TObjectIntHashMapExternalizer(MethodIncompleteSignature.createDataExternalizer()); + } + + private void addToIndex(final Map> map, + final String internalClassName, + final MethodIncompleteSignature mi) { + final String className = myQualifiedClassNameResolver.get(internalClassName); + TObjectIntHashMap occurrences = map.get(className); + if (occurrences == null) { + occurrences = new TObjectIntHashMap(); + map.put(className, occurrences); + } + if (!occurrences.increment(mi)) { + occurrences.put(mi, 1); + } + } + + @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") + private final FactoryMap myQualifiedClassNameResolver = new FactoryMap() { + @Nullable + @Override + protected String create(final String internalClassName) { + return AsmUtil.getQualifiedClassName(internalClassName); + } + }; +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodsUsageIndexerFactory.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodsUsageIndexerFactory.java new file mode 100644 index 000000000000..670ddaeea957 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodsUsageIndexerFactory.java @@ -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> { + @Override + public ClassFileIndexer> create() { + return new MethodsUsageIndexer(); + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/JavaBuilderService.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/JavaBuilderService.java index 66ba66cfe7f2..7d2cc2868a2c 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/JavaBuilderService.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/JavaBuilderService.java @@ -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 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 diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index c5e14812f17d..8edad7802cdf 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -44,7 +44,7 @@ - com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer + com.intellij.compiler.compilerOutputIndex.api.index.ClassFilesIndexFeaturesHolder @@ -233,9 +233,6 @@ - - @@ -1462,11 +1459,10 @@ - + implementationClass="com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.MethodsChainsCompletionContributor"/> + implementationClass="com.intellij.compiler.compilerOutputIndex.chainsSearch.completion.MethodsChainsWeigher"/> diff --git a/resources/src/idea/RichPlatformPlugin.xml b/resources/src/idea/RichPlatformPlugin.xml index f3f1ecef1216..0e8ee2995e76 100644 --- a/resources/src/idea/RichPlatformPlugin.xml +++ b/resources/src/idea/RichPlatformPlugin.xml @@ -392,6 +392,8 @@ + +