diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexFeature.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexFeature.java index 139f487936ba..52f77b199f04 100644 --- a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexFeature.java +++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexFeature.java @@ -33,16 +33,16 @@ public enum ClassFilesIndexFeature { @NotNull private final String myKey; @NotNull - private final Collection myRequiredIndicesConfigures; + private final Collection myRequiredIndicesConfigures; ClassFilesIndexFeature(@NotNull final String key, - @NotNull final Collection requiredIndicesConfigures) { + @NotNull final Collection requiredIndicesConfigures) { myKey = key; myRequiredIndicesConfigures = requiredIndicesConfigures; } - ClassFilesIndexFeature(@NotNull final String key, @NotNull final MethodsUsageIndexConfigure requiredConfigure) { - this(key, Collections.singleton(requiredConfigure)); + ClassFilesIndexFeature(@NotNull final String key, @NotNull final ClassFilesIndexConfigure requiredConfigure) { + this(key, Collections.singleton(requiredConfigure)); } public RegistryValue getRegistryValue() { @@ -70,7 +70,7 @@ public enum ClassFilesIndexFeature { } @NotNull - public Collection getRequiredIndicesConfigures() { + public Collection getRequiredIndicesConfigures() { return myRequiredIndicesConfigures; } } diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexFeaturesHolder.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexFeaturesHolder.java index 1b17eaaf1423..eee027c2c1e9 100644 --- a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexFeaturesHolder.java +++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexFeaturesHolder.java @@ -86,7 +86,7 @@ public class ClassFilesIndexFeaturesHolder extends AbstractProjectComponent { } for (final ClassFilesIndexFeature feature : ClassFilesIndexFeature.values()) { if (feature.isEnabled() && !myEnabledFeatures.containsKey(feature)) { - for (final MethodsUsageIndexConfigure configure : feature.getRequiredIndicesConfigures()) { + for (final ClassFilesIndexConfigure configure : feature.getRequiredIndicesConfigures()) { if (!myEnabledIndexReaders.containsKey(configure)) { notAvailableConfiguresVisitor.process(configure); } @@ -96,7 +96,7 @@ public class ClassFilesIndexFeaturesHolder extends AbstractProjectComponent { } private synchronized void disposeFeature(final ClassFilesIndexFeature featureToRemove) { - for (final MethodsUsageIndexConfigure requiredConfigure : featureToRemove.getRequiredIndicesConfigures()) { + for (final ClassFilesIndexConfigure requiredConfigure : featureToRemove.getRequiredIndicesConfigures()) { boolean needClose = true; for (final ClassFilesIndexFeature enabledFeature : myEnabledFeatures.keySet()) { if (!enabledFeature.equals(featureToRemove) && enabledFeature.getRequiredIndicesConfigures().contains(requiredConfigure)) { @@ -116,10 +116,10 @@ public class ClassFilesIndexFeaturesHolder extends AbstractProjectComponent { if (myEnabledFeatures.containsKey(feature)) { throw new IllegalStateException(String.format("feature %s already contains", feature.getKey())); } - final Map newIndices = - new HashMap(); + final Map newIndices = + new HashMap(); FeatureState newFeatureState = FeatureState.AVAILABLE; - for (final MethodsUsageIndexConfigure requiredConfigure : feature.getRequiredIndicesConfigures()) { + for (final ClassFilesIndexConfigure requiredConfigure : feature.getRequiredIndicesConfigures()) { boolean isIndexAlreadyLoaded = false; for (final ClassFilesIndexFeature enabledFeature : myEnabledFeatures.keySet()) { if (enabledFeature.getRequiredIndicesConfigures().contains(requiredConfigure)) { diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexReaderBase.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexReaderBase.java index 0cb2dd4d839c..8f6a7ebc7eb6 100644 --- a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexReaderBase.java +++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexReaderBase.java @@ -55,9 +55,6 @@ public abstract class ClassFilesIndexReaderBase { } } - /** - * All inheritors MUST have constructor with only one parameter - Project - */ @SuppressWarnings("ConstantConditions") protected ClassFilesIndexReaderBase(final KeyDescriptor keyDescriptor, final DataExternalizer valueExternalizer, @@ -149,5 +146,4 @@ public abstract class ClassFilesIndexReaderBase { return true; } } - } diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/CachedRelevantStaticMethodSearcher.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/CachedRelevantStaticMethodSearcher.java index ac6df7346449..da119b104965 100644 --- a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/CachedRelevantStaticMethodSearcher.java +++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/CachedRelevantStaticMethodSearcher.java @@ -52,7 +52,7 @@ public class CachedRelevantStaticMethodSearcher { final ChainCompletionContext completionContext) { if (resultQualifiedClassName == null || ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(resultQualifiedClassName) || - completionContext.getTargetQName().equals(resultQualifiedClassName)) { + completionContext.getTarget().equals(resultQualifiedClassName)) { return Collections.emptyList(); } final TreeSet indexValues = myIndexReader.getMethods(resultQualifiedClassName); @@ -68,7 +68,7 @@ public class CachedRelevantStaticMethodSearcher { else { final PsiMethod[] methods = completionContext.resolveNotDeprecated(methodInvocation); method = MethodChainsSearchUtil - .getMethodWithMinNotPrimitiveParameters(methods, Collections.singleton(completionContext.getTargetQName())); + .getMethodWithMinNotPrimitiveParameters(methods, Collections.singleton(completionContext.getTarget().getClassQName())); myCachedResolveResults.put(methodInvocation, method); if (method == null) { return Collections.emptyList(); diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ChainsSearcher.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ChainsSearcher.java index 339428525e7e..c040e96e1217 100644 --- a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ChainsSearcher.java +++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ChainsSearcher.java @@ -16,19 +16,19 @@ package com.intellij.compiler.classFilesIndex.chainsSearch; import com.intellij.compiler.classFilesIndex.chainsSearch.context.ChainCompletionContext; +import com.intellij.compiler.classFilesIndex.chainsSearch.context.TargetType; import com.intellij.compiler.classFilesIndex.impl.MethodsUsageIndexReader; import com.intellij.compiler.classFilesIndex.impl.UsageIndexValue; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Pair; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiManager; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiModifier; +import com.intellij.psi.*; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodIncompleteSignature; +import org.jetbrains.jps.incremental.storage.BuildDataManager; import java.util.*; @@ -42,21 +42,36 @@ 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 MethodsUsageIndexReader indexReader, - final String targetQName, + public static List search(final int pathMaximalLength, + final TargetType targetType, final Set contextQNames, final int maxResultSize, - final int pathMaximalLength, - final ChainCompletionContext context) { - final SearchInitializer initializer = createInitializer(targetQName, indexReader, context.getExcludedQNames(), context); - return search(indexReader, initializer, contextQNames, pathMaximalLength, maxResultSize, targetQName, context); + final ChainCompletionContext context, + final MethodsUsageIndexReader methodsUsageIndexReader) { + final SearchInitializer initializer = + createInitializer(targetType, + context.getExcludedQNames(), + methodsUsageIndexReader, + context); + if (initializer == null) { + return Collections.emptyList(); + } + return search(methodsUsageIndexReader, + initializer, + contextQNames, + pathMaximalLength, + maxResultSize, + targetType.getClassQName(), + context); } - private static SearchInitializer createInitializer(final String targetQName, - final MethodsUsageIndexReader indexReader, + @Nullable + private static SearchInitializer createInitializer(final TargetType target, final Set excludedParamsTypesQNames, + final MethodsUsageIndexReader methodsUsageIndexReader, final ChainCompletionContext context) { - return new SearchInitializer(indexReader.getMethods(targetQName), targetQName, excludedParamsTypesQNames, context); + final TreeSet methods = methodsUsageIndexReader.getMethods(target.getClassQName()); + return new SearchInitializer(methods, target.getClassQName(), excludedParamsTypesQNames, context); } @NotNull @@ -80,22 +95,20 @@ public final class ChainsSearcher { @Override public WeightAware> fun( final WeightAware methodIncompleteSignatureWeightAware) { - final MethodIncompleteSignature - underlying = - methodIncompleteSignatureWeightAware - .getUnderlying(); + final MethodIncompleteSignature underlying = methodIncompleteSignatureWeightAware.getUnderlying(); return new WeightAware>( new Pair( - underlying, new MethodsChain( - context.resolveNotDeprecated( - underlying), - methodIncompleteSignatureWeightAware - .getWeight(), - underlying.getOwner())), - methodIncompleteSignatureWeightAware - .getWeight()); + underlying, + new MethodsChain(context.resolveNotDeprecated(underlying), + methodIncompleteSignatureWeightAware.getWeight(), + underlying.getOwner() + ) + ), + methodIncompleteSignatureWeightAware.getWeight() + ); } - })); + } + )); int maxWeight = 0; for (final MethodsChain methodsChain : knownDistance.values()) { @@ -118,7 +131,8 @@ public final class ChainsSearcher { result.add(currentVertex.getUnderlying().getSecond()); continue; } - final SortedSet nextMethods = indexReader.getMethods(currentVertexUnderlying.getFirst().getOwner()); + final String currentReturnType = currentVertexUnderlying.getFirst().getOwner(); + final SortedSet nextMethods = indexReader.getMethods(currentReturnType); final MaxSizeTreeSet> currentSignatures = new MaxSizeTreeSet>(maxResultSize); for (final UsageIndexValue indexValue : nextMethods) { @@ -133,8 +147,10 @@ public final class ChainsSearcher { 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)); + final MethodsChain newBestMethodsChain = + currentVertexMethodsChain.addEdge(psiMethods, indexValue.getMethodIncompleteSignature().getOwner(), vertexDistance); + currentSignatures + .add(new WeightAware(indexValue.getMethodIncompleteSignature(), vertexDistance)); knownDistance.put(vertex, newBestMethodsChain); } } @@ -302,4 +318,4 @@ public final class ChainsSearcher { return resultHolder.getRawResult(); } } -} +} \ No newline at end of file diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/MethodsChainLookupRangingHelper.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/MethodsChainLookupRangingHelper.java index 46724834d765..00a0dcd72597 100644 --- a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/MethodsChainLookupRangingHelper.java +++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/MethodsChainLookupRangingHelper.java @@ -60,8 +60,7 @@ public class MethodsChainLookupRangingHelper { @SuppressWarnings("ConstantConditions") @Nullable - private static WeightableChainLookupElement chainToWeightableLookupElement(final MethodsChain chain, - final ChainCompletionContext context) { + private static LookupElement chainToWeightableLookupElement(final MethodsChain chain, final ChainCompletionContext context) { final int chainSize = chain.size(); assert chainSize != 0; final int lastMethodWeight = chain.getChainWeight(); @@ -76,7 +75,7 @@ public class MethodsChainLookupRangingHelper { for (final PsiMethod[] psiMethods : chain.getPath()) { final PsiMethod method = - MethodChainsSearchUtil.getMethodWithMinNotPrimitiveParameters(psiMethods, Collections.singleton(context.getTargetQName())); + MethodChainsSearchUtil.getMethodWithMinNotPrimitiveParameters(psiMethods, Collections.singleton(context.getTarget().getClassQName())); if (method == null) { return null; } @@ -141,52 +140,49 @@ public class MethodsChainLookupRangingHelper { for (int i = 0; i < parameters.length; i++) { final PsiParameter parameter = parameters[i]; final String typeQName = parameter.getType().getCanonicalText(); - if (typeQName != null) { - if (JAVA_LANG_STRING.equals(typeQName)) { - final PsiVariable relevantStringVar = context.findRelevantStringInContext(parameter.getName()); - if (relevantStringVar == null) { - notMatchedStringVars++; - } - else { - parametersMap.put(i, new VariableSubLookupElement(relevantStringVar)); - } + if (JAVA_LANG_STRING.equals(typeQName)) { + final PsiVariable relevantStringVar = context.findRelevantStringInContext(parameter.getName()); + if (relevantStringVar == null) { + notMatchedStringVars++; } - else if (!ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(typeQName)) { - final Collection contextVariables = context.getVariables(typeQName); - final PsiVariable contextVariable = ContainerUtil.getFirstItem(contextVariables, null); - if (contextVariable != null) { - if (contextVariables.size() == 1) parametersMap.put(i, new VariableSubLookupElement(contextVariable)); - matchedParametersInContext++; - continue; - } - final Collection relevantVariablesGetters = context.getRelevantVariablesGetters(typeQName); - final ContextRelevantVariableGetter contextVariableGetter = ContainerUtil.getFirstItem(relevantVariablesGetters, null); - if (contextVariableGetter != null) { - if (relevantVariablesGetters.size() == 1) parametersMap.put(i, contextVariableGetter.createSubLookupElement()); - matchedParametersInContext++; - continue; - } - final Collection containingClassMethods = context.getContainingClassMethods(typeQName); - final PsiMethod contextRelevantGetter = ContainerUtil.getFirstItem(containingClassMethods, null); - if (contextRelevantGetter != null) { - if (containingClassMethods.size() == 1) parametersMap.put(i, new GetterLookupSubLookupElement(method.getName())); - matchedParametersInContext++; - continue; - } - //todo - final ContextRelevantStaticMethod contextRelevantStaticMethod = - ContainerUtil.getFirstItem(context.getRelevantStaticMethods(typeQName, weight), null); - if (contextRelevantStaticMethod != null) { - // - // In most cases it is not really relevant - // - //parametersMap.put(i, contextRelevantStaticMethod.createLookupElement()); - matchedParametersInContext++; - continue; - } - if (!nullableNotNullManager.isNullable(parameter, true)) { - unreachableParametersCount++; - } + else { + parametersMap.put(i, new VariableSubLookupElement(relevantStringVar)); + } + } + else if (!ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(typeQName)) { + final Collection contextVariables = context.getVariables(typeQName); + final PsiVariable contextVariable = ContainerUtil.getFirstItem(contextVariables, null); + if (contextVariable != null) { + if (contextVariables.size() == 1) parametersMap.put(i, new VariableSubLookupElement(contextVariable)); + matchedParametersInContext++; + continue; + } + final Collection relevantVariablesGetters = context.getRelevantVariablesGetters(typeQName); + final ContextRelevantVariableGetter contextVariableGetter = ContainerUtil.getFirstItem(relevantVariablesGetters, null); + if (contextVariableGetter != null) { + if (relevantVariablesGetters.size() == 1) parametersMap.put(i, contextVariableGetter.createSubLookupElement()); + matchedParametersInContext++; + continue; + } + final Collection containingClassMethods = context.getContainingClassMethods(typeQName); + final PsiMethod contextRelevantGetter = ContainerUtil.getFirstItem(containingClassMethods, null); + if (contextRelevantGetter != null) { + if (containingClassMethods.size() == 1) parametersMap.put(i, new GetterLookupSubLookupElement(method.getName())); + matchedParametersInContext++; + continue; + } + final ContextRelevantStaticMethod contextRelevantStaticMethod = + ContainerUtil.getFirstItem(context.getRelevantStaticMethods(typeQName, weight), null); + if (contextRelevantStaticMethod != null) { + // + // In most cases it is not really relevant + // + //parametersMap.put(i, contextRelevantStaticMethod.createLookupElement()); + matchedParametersInContext++; + continue; + } + if (!nullableNotNullManager.isNullable(parameter, true)) { + unreachableParametersCount++; } } } diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ParametersMatcher.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ParametersMatcher.java index 3cdc760c5ff3..68c252907b8e 100644 --- a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ParametersMatcher.java +++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ParametersMatcher.java @@ -59,7 +59,7 @@ public final class ParametersMatcher { else { unMatched++; } - if (context.getTargetQName().equals(canonicalText) || additionalExcludedNames.contains(canonicalText)) { + if (context.getTarget().getClassQName().equals(canonicalText) || additionalExcludedNames.contains(canonicalText)) { hasTarget = true; } } diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/MethodsChainsCompletionContributor.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/MethodsChainsCompletionContributor.java index 85db0258fcd9..85ee710c8df4 100644 --- a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/MethodsChainsCompletionContributor.java +++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/MethodsChainsCompletionContributor.java @@ -1,18 +1,3 @@ -/* - * 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.classFilesIndex.chainsSearch.completion; import com.intellij.codeInsight.completion.*; @@ -22,12 +7,14 @@ import com.intellij.compiler.classFilesIndex.api.index.ClassFilesIndexFeaturesHo import com.intellij.compiler.classFilesIndex.chainsSearch.*; import com.intellij.compiler.classFilesIndex.chainsSearch.context.ChainCompletionContext; import com.intellij.compiler.classFilesIndex.chainsSearch.context.ContextUtil; +import com.intellij.compiler.classFilesIndex.chainsSearch.context.TargetType; import com.intellij.compiler.classFilesIndex.impl.MethodsUsageIndexReader; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.module.ModuleUtilCore; +import com.intellij.openapi.project.Project; import com.intellij.patterns.ElementPattern; import com.intellij.psi.*; -import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.impl.source.PsiImmediateClassType; import com.intellij.psi.search.searches.DirectClassInheritorsSearch; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.*; @@ -53,8 +40,8 @@ public class MethodsChainsCompletionContributor extends CompletionContributor { @Override public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) { - if (parameters.getInvocationCount() >= INVOCATIONS_THRESHOLD - && ClassFilesIndexFeaturesHolder.getInstance(parameters.getPosition().getProject()) + if (parameters.getInvocationCount() >= INVOCATIONS_THRESHOLD && + ClassFilesIndexFeaturesHolder.getInstance(parameters.getPosition().getProject()) .enableFeatureIfNeed(ClassFilesIndexFeature.METHOD_CHAINS_COMPLETION)) { super.fillCompletionVariants(parameters, result); } @@ -72,7 +59,6 @@ public class MethodsChainsCompletionContributor extends CompletionContributor { final ChainCompletionContext completionContext = extractContext(parameters); if (completionContext == null) return; - final String targetClassQName = completionContext.getTargetQName(); final Set contextTypesKeysSet = completionContext.getContextTypes(); final Set contextRelevantTypes = new HashSet(contextTypesKeysSet.size() + 1); for (final String type : contextTypesKeysSet) { @@ -80,9 +66,9 @@ public class MethodsChainsCompletionContributor extends CompletionContributor { contextRelevantTypes.add(type); } } - contextRelevantTypes.remove(targetClassQName); - - final List foundElements = searchForLookups(targetClassQName, contextRelevantTypes, completionContext); + final TargetType target = completionContext.getTarget(); + contextRelevantTypes.remove(target.getClassQName()); + final List elementsFoundByMethodsChainsSearch = searchForLookups(target, contextRelevantTypes, completionContext); if (!IS_UNIT_TEST_MODE) { result.runRemainingContributors(parameters, new Consumer() { @Override @@ -90,9 +76,9 @@ public class MethodsChainsCompletionContributor extends CompletionContributor { final LookupElement lookupElement = completionResult.getLookupElement(); final PsiElement lookupElementPsi = lookupElement.getPsiElement(); if (lookupElementPsi != null) { - for (final LookupElement element : foundElements) { + for (final LookupElement element : elementsFoundByMethodsChainsSearch) { if (lookupElementPsi.isEquivalentTo(element.getPsiElement())) { - foundElements.remove(element); + elementsFoundByMethodsChainsSearch.remove(element); break; } } @@ -103,45 +89,50 @@ public class MethodsChainsCompletionContributor extends CompletionContributor { } else { result.stopHere(); } - result.addAllElements(foundElements); + result.addAllElements(elementsFoundByMethodsChainsSearch); } }); } - private static List searchForLookups(final String targetClassQName, + private static List searchForLookups(final TargetType target, final Set contextRelevantTypes, final ChainCompletionContext completionContext) { - final MethodsUsageIndexReader methodsUsageIndexReader = MethodsUsageIndexReader.getInstance(completionContext.getProject()); + final Project project = completionContext.getProject(); + final MethodsUsageIndexReader methodsUsageIndexReader = MethodsUsageIndexReader.getInstance(project); final List searchResult = - searchChains(targetClassQName, contextRelevantTypes, MAX_SEARCH_RESULT_SIZE, MAX_CHAIN_SIZE, completionContext, methodsUsageIndexReader); + searchChains(target, 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())); - if (aClass != null) { - DirectClassInheritorsSearch.search(aClass).forEach(new Processor() { + if (!target.isArray()) { + final List inheritorFilteredSearchResult = new SmartList(); + final Processor consumer = new Processor() { + @Override + public boolean process(final TargetType targetType) { + for (final MethodsChain chain : searchChains(targetType, contextRelevantTypes, MAX_SEARCH_RESULT_SIZE, MAX_CHAIN_SIZE, + completionContext, methodsUsageIndexReader)) { + boolean insert = true; + for (final MethodsChain baseChain : searchResult) { + final MethodsChain.CompareResult r = MethodsChain.compare(baseChain, chain, completionContext.getPsiManager()); + if (r != MethodsChain.CompareResult.NOT_EQUAL) { + insert = false; + break; + } + } + if (insert) { + inheritorFilteredSearchResult.add(chain); + } + } + searchResult.addAll(inheritorFilteredSearchResult); + return searchResult.size() < MAX_SEARCH_RESULT_SIZE; + } + }; + DirectClassInheritorsSearch.search(((PsiClassType)target.getPsiType()).resolve()).forEach(new Processor() { @Override public boolean process(final PsiClass psiClass) { final String inheritorQName = psiClass.getQualifiedName(); - if (!StringUtil.isEmpty(inheritorQName)) { - final List inheritorFilteredSearchResult = new SmartList(); - //noinspection ConstantConditions - for (final MethodsChain chain : searchChains(inheritorQName, contextRelevantTypes, MAX_SEARCH_RESULT_SIZE, MAX_CHAIN_SIZE, - completionContext, methodsUsageIndexReader)) { - boolean insert = true; - for (final MethodsChain baseChain : searchResult) { - final MethodsChain.CompareResult r = MethodsChain.compare(baseChain, chain, completionContext.getPsiManager()); - if (r != MethodsChain.CompareResult.NOT_EQUAL) { - insert = false; - break; - } - } - if (insert) { - inheritorFilteredSearchResult.add(chain); - } - } - searchResult.addAll(inheritorFilteredSearchResult); + if (inheritorQName == null) { + return true; } - return true; + return consumer.process(new TargetType(inheritorQName, false, new PsiImmediateClassType(psiClass, PsiSubstitutor.EMPTY))); } }); } @@ -221,12 +212,12 @@ public class MethodsChainsCompletionContributor extends CompletionContributor { return filteredResult; } - private static List searchChains(final String targetQName, + private static List searchChains(final TargetType target, final Set contextVarsQNames, final int maxResultSize, final int maxChainSize, final ChainCompletionContext context, final MethodsUsageIndexReader methodsUsageIndexReader) { - return ChainsSearcher.search(methodsUsageIndexReader, targetQName, contextVarsQNames, maxResultSize, maxChainSize, context); + return ChainsSearcher.search(maxChainSize, target, contextVarsQNames, maxResultSize, context, methodsUsageIndexReader); } -} +} \ No newline at end of file diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ChainCompletionContext.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ChainCompletionContext.java index ea49f3c2cee8..7d25398e549d 100644 --- a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ChainCompletionContext.java +++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ChainCompletionContext.java @@ -19,10 +19,7 @@ import com.intellij.compiler.classFilesIndex.chainsSearch.CachedRelevantStaticMe 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.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.containers.FactoryMap; import com.intellij.util.containers.MultiMap; @@ -44,7 +41,7 @@ public class ChainCompletionContext { } }; private final PsiMethod myContextMethod; - private final String myTargetQName; + private final TargetType myTarget; private final Set myContainingClassQNames; private final MultiMap myContextVars; private final MultiMap myContainingClassGetters; @@ -72,7 +69,7 @@ public class ChainCompletionContext { } ChainCompletionContext(final PsiMethod contextMethod, - final String targetQName, + final TargetType target, final Set containingClassQNames, final MultiMap contextVars, final MultiMap containingClassGetters, @@ -82,7 +79,7 @@ public class ChainCompletionContext { final Project project, final GlobalSearchScope resolveScope) { myContextMethod = contextMethod; - myTargetQName = targetQName; + myTarget = target; myContainingClassQNames = containingClassQNames; myContextVars = contextVars; myContainingClassGetters = containingClassGetters; @@ -104,8 +101,8 @@ public class ChainCompletionContext { return myContextMethodName.getValue(); } - public String getTargetQName() { - return myTargetQName; + public TargetType getTarget() { + return myTarget; } @Nullable diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ContextUtil.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ContextUtil.java index 1ea1bf49ebba..7b79ef711b62 100644 --- a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ContextUtil.java +++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ContextUtil.java @@ -38,20 +38,18 @@ public final class ContextUtil { if (variableType == null || containingElement == null) { return null; } - if (variableType instanceof PsiClassType) { - final PsiClass aClass = ((PsiClassType)variableType).resolve(); - if (aClass != null) { - if (aClass.hasTypeParameters()) { - return null; - } - } - else { - return null; - } - } - final String targetQName = variableType.getCanonicalText(); - if (targetQName == null || targetQName.endsWith("[]")) { + final TargetType target; + if (variableType instanceof PsiClassType) { + target = TargetType.create((PsiClassType)variableType); + } + else if (variableType instanceof PsiArrayType) { + target = TargetType.create((PsiArrayType)variableType); + } + else { + return null; + } + if (target == null) { return null; } @@ -121,7 +119,7 @@ public final class ContextUtil { } } - return create(method, targetQName, contextVars, contextMethods, containingClassQNames, containingElement.getProject(), + return create(method, target, contextVars, contextMethods, containingClassQNames, containingElement.getProject(), containingElement.getResolveScope(), excludedQNames); } @@ -177,7 +175,7 @@ public final class ContextUtil { @Nullable private static ChainCompletionContext create(final PsiMethod contextMethod, - final String targetQName, + final TargetType target, final List contextVars, final List contextMethods, final Set containingClassQNames, @@ -190,12 +188,10 @@ public final class ContextUtil { final Map stringVars = new HashMap(); for (final PsiMethod method : contextMethods) { - PsiType returnType = method.getReturnType(); + final PsiType returnType = method.getReturnType(); if (returnType != null) { final String returnTypeQName = returnType.getCanonicalText(); - if (returnTypeQName != null) { - containingClassGetters.putValue(returnTypeQName, method); - } + containingClassGetters.putValue(returnTypeQName, method); } } @@ -214,13 +210,14 @@ public final class ContextUtil { final PsiClass aClass = ((PsiClassType)type).resolve(); if (aClass != null) { final String classQName = type.getCanonicalText(); - if (!targetQName.equals(classQName)) { + if (!target.getClassQName().equals(classQName)) { classQNames.add(classQName); classQNames.addAll(resolveSupersNamesRecursively(aClass)); for (final PsiMethod method : aClass.getAllMethods()) { if (method.getParameterList().getParametersCount() == 0 && method.getName().startsWith("get")) { - final String getterReturnTypeQName = method.getReturnType().getCanonicalText(); - if (getterReturnTypeQName != null) { + final PsiType returnType = method.getReturnType(); + if (returnType != null) { + final String getterReturnTypeQName = returnType.getCanonicalText(); contextVarsGetters.putValue(getterReturnTypeQName, new ContextRelevantVariableGetter(var, method)); } } @@ -230,15 +227,13 @@ public final class ContextUtil { } else { final String classQName = type.getCanonicalText(); - if (classQName != null) { - classQNames.add(classQName); - } + classQNames.add(classQName); } for (final String qName : classQNames) { classQNameToVariable.putValue(qName, var); } } - return new ChainCompletionContext(contextMethod, targetQName, containingClassQNames, classQNameToVariable, containingClassGetters, + return new ChainCompletionContext(contextMethod, target, containingClassQNames, classQNameToVariable, containingClassGetters, contextVarsGetters, stringVars, excludedQNames, project, resolveScope); } diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/MethodIncompleteSignatureResolver.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/MethodIncompleteSignatureResolver.java index e48f07272457..5a9c257b78ab 100644 --- a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/MethodIncompleteSignatureResolver.java +++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/MethodIncompleteSignatureResolver.java @@ -57,8 +57,22 @@ final class MethodIncompleteSignatureResolver { 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 (returnType != null) { + if (returnType instanceof PsiClassType) { + final PsiClass resolved = ((PsiClassType)returnType).resolve(); + if (resolved == null) { + continue; + } + final String qualifiedName = resolved.getQualifiedName(); + if (qualifiedName == null) { + continue; + } + if (qualifiedName.equals(signature.getReturnType())) { + filtered.add(method); + } + } else if (returnType.equalsToText(signature.getReturnType())) { + filtered.add(method); + } } } } diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/TargetType.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/TargetType.java new file mode 100644 index 000000000000..2d983f1e71a1 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/TargetType.java @@ -0,0 +1,84 @@ +/* + * Copyright 2000-2014 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.classFilesIndex.chainsSearch.context; + +import com.intellij.psi.*; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * @author Dmitry Batkovich + */ +public class TargetType { + + private final String myClassQName; + private final boolean myArray; + private final PsiType myPsiType; + + public TargetType(final String classQName, + final boolean isArray, + final PsiType targetType) { + myClassQName = classQName; + myArray = isArray; + myPsiType = targetType; + } + + public String getClassQName() { + return myClassQName; + } + + public boolean isArray() { + return myArray; + } + + public PsiType getPsiType() { + return myPsiType; + } + + @Nullable + public static TargetType create(final PsiArrayType arrayType) { + PsiType currentComponentType = arrayType.getComponentType(); + while (currentComponentType instanceof PsiArrayType) { + currentComponentType = ((PsiArrayType)currentComponentType).getComponentType(); + } + if (!(currentComponentType instanceof PsiClassType)) { + return null; + } + final String targetQName = arrayType.getCanonicalText(); + return new TargetType(targetQName, true, arrayType); + } + + @Nullable + public static TargetType create(final PsiClassType classType) { + final PsiClassType.ClassResolveResult resolvedGenerics = classType.resolveGenerics(); + final PsiClass resolvedClass = resolvedGenerics.getElement(); + if (resolvedClass == null) { + return null; + } + final String classQName = resolvedClass.getQualifiedName(); + if (classQName == null) { + return null; + } + if (resolvedClass.hasTypeParameters()) { + return null; + } + return new TargetType(classQName, false, classType); + } +} diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/impl/MethodsUsageIndexReader.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/impl/MethodsUsageIndexReader.java index bfcaefeb55ae..3b3adcdb8a5d 100644 --- a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/impl/MethodsUsageIndexReader.java +++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/impl/MethodsUsageIndexReader.java @@ -78,5 +78,4 @@ public class MethodsUsageIndexReader extends ClassFilesIndexReaderBase + } +} diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testArrayReturnType/TestIndex.java b/java/java-tests/testData/codeInsight/completion/methodChains/testArrayReturnType/TestIndex.java new file mode 100644 index 000000000000..9f9ce1a7b5d8 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/methodChains/testArrayReturnType/TestIndex.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +public class TestIndex { + + public void statMethod(PsiClass c) { + c.getMethods(); + c.getMethods(); + c.getMethods(); + c.getMethods(); + c.getMethods(); + c.getMethods(); + c.getMethods(); + c.getMethods(); + } +} + +class PsiMethod { +} + +interface PsiClass { + PsiMethod[] getMethods(); +} 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 a733b8aba822..2a925bf18cd0 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/AbstractCompilerAwareTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/AbstractCompilerAwareTest.java @@ -19,15 +19,16 @@ import com.intellij.openapi.compiler.CompilerMessage; import com.intellij.openapi.compiler.CompilerMessageCategory; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiManager; import com.intellij.testFramework.CompilerTester; import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase; 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 @@ -48,21 +49,16 @@ public abstract class AbstractCompilerAwareTest extends JavaCodeInsightFixtureTe } 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); - } - } - }); + try { + for (String fileName : fileNames) { + myFixture.addFileToProject(fileName, FileUtil.loadFile(new File(getTestDataPath() + getName() + "/" + fileName))).getVirtualFile(); + } + } + catch (IOException e) { + throw new RuntimeException(e); + } for (final CompilerMessage compilerMessage : myCompilerTester.rebuild()) { - assertNotSame(CompilerMessageCategory.ERROR, compilerMessage.getCategory()); + assertNotSame(compilerMessage.getMessage(), 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 0f9810321758..74e46e08eea0 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/MethodChainsCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/MethodChainsCompletionTest.java @@ -251,8 +251,7 @@ public class MethodChainsCompletionTest extends AbstractCompilerAwareTest { private LookupElement[] runCompletion() { myFixture.configureByFiles(getTestCompletionFilePath()); final LookupElement[] lookupElements = - myFixture.complete(MethodsChainsCompletionContributor.COMPLETION_TYPE, - MethodsChainsCompletionContributor.INVOCATIONS_THRESHOLD); + myFixture.complete(CompletionType.BASIC, MethodsChainsCompletionContributor.INVOCATIONS_THRESHOLD); return lookupElements == null ? LookupElement.EMPTY_ARRAY : lookupElements; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/AsmUtil.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/AsmUtil.java index dd74d665e362..4082d9542698 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/AsmUtil.java +++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/AsmUtil.java @@ -46,10 +46,12 @@ public class AsmUtil { 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; + public static boolean isPrimitiveOrArrayOfPrimitives(final String asmType) { + for (int i = 0; i < asmType.length(); i++) { + if (asmType.charAt(i) != '[') { + return ASM_PRIMITIVE_TYPES.contains(asmType.substring(i)); + } } - return ASM_PRIMITIVE_TYPES.contains(asmType); + throw new AssertionError("Illegal string: " + asmType); } } 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 index 115a3605384e..3ded5f2d6aa2 100644 --- 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 @@ -15,6 +15,8 @@ */ package org.jetbrains.jps.classFilesIndex.indexer.api; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.util.Processor; import com.intellij.util.containers.SLRUCache; import com.intellij.util.io.DataExternalizer; import com.intellij.util.io.EnumeratorStringDescriptor; @@ -27,6 +29,7 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.Collection; import java.util.Map; import java.util.concurrent.locks.Lock; 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 index aded53895000..7609feeb37d2 100644 --- 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 @@ -15,6 +15,8 @@ */ package org.jetbrains.jps.classFilesIndex.indexer.api; +import com.intellij.openapi.diagnostic.Log; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.PersistentHashMap; import org.jetbrains.asm4.ClassReader; @@ -30,6 +32,8 @@ import java.util.Set; * @author Dmitry Batkovich */ public class ClassFilesIndexWriter { + private static final Logger LOG = Logger.getInstance(ClassFilesIndexWriter.class); + private final ClassFileIndexer myIndexer; private final boolean myEmpty; protected final ClassFilesIndexStorage myIndex; @@ -43,6 +47,7 @@ public class ClassFilesIndexWriter { } ClassFilesIndexStorage index = null; IOException exception = null; + LOG.debug("start open... " + indexer.getIndexCanonicalName()); for (int attempt = 0; attempt < 2; attempt++) { try { index = new ClassFilesIndexStorage(storageDir, myIndexer.getKeyDescriptor(), myIndexer.getDataExternalizer()); @@ -53,6 +58,7 @@ public class ClassFilesIndexWriter { PersistentHashMap.deleteFilesStartingWith(ClassFilesIndexStorage.getIndexFile(storageDir)); } } + LOG.debug("opened " + indexer.getIndexCanonicalName()); if (index == null) { throw new RuntimeException(exception); } 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 index 088e9a8b1e5e..e3a95e9e57d7 100644 --- 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 @@ -36,6 +36,8 @@ import org.jetbrains.jps.service.JpsServiceManager; import java.io.File; import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; /** * @author Dmitry Batkovich @@ -46,6 +48,8 @@ public class ClassFilesIndicesBuilder extends BaseInstrumentingBuilder { private static final String PROGRESS_MESSAGE = "Indexing class-files..."; public static final String PROPERTY_NAME = "intellij.compiler.output.index"; + private final AtomicLong myMs = new AtomicLong(0); + private final AtomicInteger myFilesCount = new AtomicInteger(0); private final Collection myIndexWriters = new ArrayList(); @Override @@ -89,11 +93,13 @@ public class ClassFilesIndicesBuilder extends BaseInstrumentingBuilder { if (!isEnabled()) { return; } + final long ms = System.currentTimeMillis(); for (final ClassFilesIndexWriter index : myIndexWriters) { index.close(context); } myIndexWriters.clear(); - LOG.info("class files indexing finished"); + myMs.addAndGet(System.currentTimeMillis() - ms); + LOG.info("class files indexing finished for " + myFilesCount.get() + " files in " + myMs.get() + "ms"); } @Nullable @@ -103,9 +109,12 @@ public class ClassFilesIndicesBuilder extends BaseInstrumentingBuilder { final ClassReader reader, final ClassWriter writer, final InstrumentationClassFinder finder) { + final long ms = System.currentTimeMillis(); for (final ClassFilesIndexWriter index : myIndexWriters) { index.update(compiled.getOutputFile().getPath(), reader); } + myMs.addAndGet(System.currentTimeMillis() - ms); + myFilesCount.incrementAndGet(); return null; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodIncompleteSignature.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodIncompleteSignature.java index 0aac2186f984..98844bf9862c 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodIncompleteSignature.java +++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodIncompleteSignature.java @@ -17,6 +17,7 @@ package org.jetbrains.jps.classFilesIndex.indexer.impl; 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; @@ -79,6 +80,16 @@ public class MethodIncompleteSignature { return myStatic; } + @Override + public String toString() { + return "MethodIncompleteSignature{" + + "myOwner='" + myOwner + '\'' + + ", myReturnType='" + myReturnType + '\'' + + ", myName='" + myName + '\'' + + ", myStatic=" + myStatic + + '}'; + } + public final static Comparator COMPARATOR = new Comparator() { @Override public int compare(final MethodIncompleteSignature o1, final MethodIncompleteSignature o2) { 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 index 60c0707cba24..e4eac05f93d7 100644 --- 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 @@ -15,18 +15,15 @@ */ 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; @@ -44,12 +41,14 @@ public class MethodsUsageIndexer extends ClassFileIndexer> map(final ClassReader inputData) { - final Map> map = new HashMap>(); + 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())) { + if (MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME.equals(name) || + AsmUtil.isPrimitiveOrArrayOfPrimitives(returnType.getDescriptor())) { return; } final boolean isStatic = opcode == Opcodes.INVOKESTATIC; @@ -68,7 +67,7 @@ public class MethodsUsageIndexer extends ClassFileIndexer