diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java new file mode 100644 index 000000000000..ca4f2e170414 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java @@ -0,0 +1,157 @@ +/* + * Copyright 2000-2010 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.codeInsight.CodeInsightUtil; +import com.intellij.codeInsight.ExpectedTypeInfo; +import com.intellij.codeInsight.lookup.AutoCompletionPolicy; +import com.intellij.codeInsight.lookup.LookupElementDecorator; +import com.intellij.codeInsight.lookup.LookupItem; +import com.intellij.codeInsight.lookup.PsiTypeLookupItem; +import com.intellij.openapi.util.Condition; +import com.intellij.psi.*; +import com.intellij.psi.filters.getters.ExpectedTypesGetter; +import com.intellij.psi.statistics.JavaStatisticsManager; +import com.intellij.psi.statistics.StatisticsInfo; +import com.intellij.psi.statistics.StatisticsManager; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; +import com.intellij.util.Consumer; +import com.intellij.util.ProcessingContext; +import com.intellij.util.Processor; +import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.List; + +/** +* @author peter +*/ +public class JavaInheritorsGetter extends CompletionProvider { + public void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext matchingContext, @NotNull final CompletionResultSet result) { + final PsiElement identifierCopy = parameters.getPosition(); + final PsiFile file = parameters.getOriginalFile(); + + final List expectedClassTypes = new SmartList(); + final List expectedArrayTypes = new SmartList(); + final List infos = new SmartList(); + + ContainerUtil.addAll(infos, JavaSmartCompletionContributor.getExpectedTypes(parameters)); + for (PsiType type : ExpectedTypesGetter.getExpectedTypes(identifierCopy, true)) { + if (type instanceof PsiClassType) { + final PsiClassType classType = (PsiClassType)type; + if (classType.resolve() != null) { + expectedClassTypes.add(classType); + } + } + else if (type instanceof PsiArrayType) { + expectedArrayTypes.add((PsiArrayType)type); + } + } + + + for (final PsiArrayType type : expectedArrayTypes) { + final LookupItem item = PsiTypeLookupItem.createLookupItem(JavaCompletionUtil.eliminateWildcards(type), identifierCopy); + if (item.getObject() instanceof PsiClass) { + JavaCompletionUtil.setShowFQN(item); + } + item.setInsertHandler(new DefaultInsertHandler()); //braces & shortening + result.addElement(JavaSmartCompletionContributor.decorate(item, infos)); + } + + processInheritors(parameters, identifierCopy, file, expectedClassTypes, new Consumer() { + public void consume(final PsiType type) { + addExpectedType(result, type, parameters, infos); + } + }, result.getPrefixMatcher()); + } + + private static void addExpectedType(final CompletionResultSet result, final PsiType type, final CompletionParameters parameters, Collection infos) { + if (!JavaCompletionUtil.hasAccessibleConstructor(type)) return; + + final PsiClass psiClass = PsiUtil.resolveClassInType(type); + if (psiClass == null) return; + + final PsiClass parentClass = psiClass.getContainingClass(); + if (parentClass != null && !psiClass.hasModifierProperty(PsiModifier.STATIC) && + !PsiTreeUtil.isAncestor(parentClass, parameters.getPosition(), false) && + !(parentClass.getContainingFile().equals(parameters.getOriginalFile()) && + parentClass.getTextRange().contains(parameters.getOffset()))) { + return; + } + + final LookupItem item = PsiTypeLookupItem.createLookupItem(JavaCompletionUtil.eliminateWildcards(type), parameters.getPosition()); + JavaCompletionUtil.setShowFQN(item); + + if (psiClass.isInterface() || psiClass.hasModifierProperty(PsiModifier.ABSTRACT)) { + item.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE); + item.setAttribute(LookupItem.INDICATE_ANONYMOUS, ""); + } + + result.addElement(JavaSmartCompletionContributor.decorate(type instanceof PsiClassType ? LookupElementDecorator + .withInsertHandler(item, ConstructorInsertHandler.SMART_INSTANCE) : item, infos)); + } + + public static void processInheritors(final CompletionParameters parameters, final PsiElement identifierCopy, final PsiFile file, final Collection expectedClassTypes, + final Consumer consumer, final PrefixMatcher matcher) { + //quick + for (final PsiClassType type : expectedClassTypes) { + consumer.consume(type); + + final PsiClassType.ClassResolveResult baseResult = JavaCompletionUtil.originalize(type).resolveGenerics(); + final PsiClass baseClass = baseResult.getElement(); + if (baseClass == null) return; + + final PsiSubstitutor baseSubstitutor = baseResult.getSubstitutor(); + + final THashSet statVariants = new THashSet(); + final Processor processor = CodeInsightUtil.createInheritorsProcessor(parameters.getPosition(), type, 0, false, + statVariants, baseClass, baseSubstitutor); + final StatisticsInfo[] statisticsInfos = + StatisticsManager.getInstance().getAllValues(JavaStatisticsManager.getAfterNewKey(type)); + for (final StatisticsInfo statisticsInfo : statisticsInfos) { + final String value = statisticsInfo.getValue(); + if (value.startsWith(JavaStatisticsManager.CLASS_PREFIX)) { + final String qname = value.substring(JavaStatisticsManager.CLASS_PREFIX.length()); + final PsiClass psiClass = JavaPsiFacade.getInstance(file.getProject()).findClass(qname, file.getResolveScope()); + if (psiClass != null && !PsiTreeUtil.isAncestor(file, psiClass, true) && !processor.process(psiClass)) break; + } + } + + for (final PsiType variant : statVariants) { + consumer.consume(variant); + } + } + + //long + final Condition shortNameCondition = new Condition() { + public boolean value(String s) { + return matcher.prefixMatches(s); + } + }; + for (final PsiClassType type : expectedClassTypes) { + final PsiClass psiClass = type.resolve(); + if (psiClass != null && !psiClass.hasModifierProperty(PsiModifier.FINAL)) { + for (final PsiType psiType : CodeInsightUtil.addSubtypes(type, identifierCopy, false, shortNameCondition)) { + consumer.consume(psiType); + } + } + } + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java index 14b75b19909d..20316778ad7e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java @@ -18,7 +18,6 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.*; import com.intellij.codeInsight.ExceptionUtil; import com.intellij.codeInsight.lookup.*; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.patterns.ElementPattern; @@ -38,9 +37,6 @@ import com.intellij.psi.filters.types.AssignableToFilter; import com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference; import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.javadoc.PsiDocTag; -import com.intellij.psi.statistics.JavaStatisticsManager; -import com.intellij.psi.statistics.StatisticsInfo; -import com.intellij.psi.statistics.StatisticsManager; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; @@ -141,16 +137,17 @@ public class JavaSmartCompletionContributor extends CompletionContributor { } } - processInheritors(parameters, position, position.getContainingFile(), expectedClassTypes, new Consumer() { - public void consume(PsiType type) { - final PsiClass psiClass = PsiUtil.resolveClassInType(type); - if (psiClass == null) return; + JavaInheritorsGetter + .processInheritors(parameters, position, position.getContainingFile(), expectedClassTypes, new Consumer() { + public void consume(PsiType type) { + final PsiClass psiClass = PsiUtil.resolveClassInType(type); + if (psiClass == null) return; - if (expectedClassTypes.contains(type)) return; + if (expectedClassTypes.contains(type)) return; - result.addElement(createInstanceofLookupElement(psiClass, parameterizedTypes)); - } - }, result.getPrefixMatcher()); + result.addElement(createInstanceofLookupElement(psiClass, parameterizedTypes)); + } + }, result.getPrefixMatcher()); } }); @@ -321,59 +318,22 @@ public class JavaSmartCompletionContributor extends CompletionContributor { } } else { final List typeList = Collections.singletonList((PsiClassType)TypeConversionUtil.typeParameterErasure(targetParameter)); - processInheritors(parameters, context, parameters.getOriginalFile(), typeList, new Consumer() { - public void consume(final PsiType type) { - final PsiClass psiClass = PsiUtil.resolveClassInType(type); - if (psiClass == null) return; + JavaInheritorsGetter + .processInheritors(parameters, context, parameters.getOriginalFile(), typeList, new Consumer() { + public void consume(final PsiType type) { + final PsiClass psiClass = PsiUtil.resolveClassInType(type); + if (psiClass == null) return; - resultSet.addElement(TailTypeDecorator.withTail(new JavaPsiClassReferenceElement(psiClass), tail)); - } - }, resultSet.getPrefixMatcher()); + resultSet.addElement(TailTypeDecorator.withTail(new JavaPsiClassReferenceElement(psiClass), tail)); + } + }, resultSet.getPrefixMatcher()); } } }); - extend(CompletionType.SMART, AFTER_NEW, new CompletionProvider(false) { - public void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext matchingContext, @NotNull final CompletionResultSet result) { - final PsiElement identifierCopy = parameters.getPosition(); - final PsiFile file = parameters.getOriginalFile(); - - final List expectedClassTypes = new SmartList(); - final List expectedArrayTypes = new SmartList(); - final List infos = new SmartList(); - - ContainerUtil.addAll(infos, getExpectedTypes(parameters)); - for (PsiType type : ExpectedTypesGetter.getExpectedTypes(identifierCopy, true)) { - if (type instanceof PsiClassType) { - final PsiClassType classType = (PsiClassType)type; - if (classType.resolve() != null) { - expectedClassTypes.add(classType); - } - } - else if (type instanceof PsiArrayType) { - expectedArrayTypes.add((PsiArrayType)type); - } - } - - - for (final PsiArrayType type : expectedArrayTypes) { - final LookupItem item = PsiTypeLookupItem.createLookupItem(JavaCompletionUtil.eliminateWildcards(type), identifierCopy); - if (item.getObject() instanceof PsiClass) { - JavaCompletionUtil.setShowFQN(item); - } - item.setInsertHandler(new DefaultInsertHandler()); //braces & shortening - result.addElement(decorate(item, infos)); - } - - processInheritors(parameters, identifierCopy, file, expectedClassTypes, new Consumer() { - public void consume(final PsiType type) { - addExpectedType(result, type, parameters, infos); - } - }, result.getPrefixMatcher()); - } - }); + extend(CompletionType.SMART, AFTER_NEW, new JavaInheritorsGetter()); } public static SmartCompletionDecorator decorate(LookupElement lookupElement, Collection infos) { @@ -438,53 +398,6 @@ public class JavaSmartCompletionContributor extends CompletionContributor { } - public static void processInheritors(final CompletionParameters parameters, final PsiElement identifierCopy, final PsiFile file, final Collection expectedClassTypes, - final Consumer consumer, final PrefixMatcher matcher) { - //quick - for (final PsiClassType type : expectedClassTypes) { - consumer.consume(type); - - final PsiClassType.ClassResolveResult baseResult = JavaCompletionUtil.originalize(type).resolveGenerics(); - final PsiClass baseClass = baseResult.getElement(); - if (baseClass == null) return; - - final PsiSubstitutor baseSubstitutor = baseResult.getSubstitutor(); - - final THashSet statVariants = new THashSet(); - final Processor processor = CodeInsightUtil.createInheritorsProcessor(parameters.getPosition(), type, 0, false, - statVariants, baseClass, baseSubstitutor); - final StatisticsInfo[] statisticsInfos = - StatisticsManager.getInstance().getAllValues(JavaStatisticsManager.getAfterNewKey(type)); - for (final StatisticsInfo statisticsInfo : statisticsInfos) { - final String value = statisticsInfo.getValue(); - if (value.startsWith(JavaStatisticsManager.CLASS_PREFIX)) { - final String qname = value.substring(JavaStatisticsManager.CLASS_PREFIX.length()); - final PsiClass psiClass = JavaPsiFacade.getInstance(file.getProject()).findClass(qname, file.getResolveScope()); - if (psiClass != null && !PsiTreeUtil.isAncestor(file, psiClass, true) && !processor.process(psiClass)) break; - } - } - - for (final PsiType variant : statVariants) { - consumer.consume(variant); - } - } - - //long - final Condition shortNameCondition = new Condition() { - public boolean value(String s) { - return matcher.prefixMatches(s); - } - }; - for (final PsiClassType type : expectedClassTypes) { - final PsiClass psiClass = type.resolve(); - if (psiClass != null && !psiClass.hasModifierProperty(PsiModifier.FINAL)) { - for (final PsiType psiType : CodeInsightUtil.addSubtypes(type, identifierCopy, false, shortNameCondition)) { - consumer.consume(psiType); - } - } - } - } - public static ExpectedTypeInfo[] getExpectedTypes(final CompletionParameters parameters) { final PsiElement position = parameters.getPosition(); if (psiElement().withParent(psiElement(PsiReferenceExpression.class).withParent(PsiThrowStatement.class)).accepts(position)) { @@ -508,31 +421,6 @@ public class JavaSmartCompletionContributor extends CompletionContributor { return ExpectedTypesProvider.getExpectedTypes(expression, true, parameters.getCompletionType() == CompletionType.SMART, false); } - private static void addExpectedType(final CompletionResultSet result, final PsiType type, final CompletionParameters parameters, Collection infos) { - if (!JavaCompletionUtil.hasAccessibleConstructor(type)) return; - - final PsiClass psiClass = PsiUtil.resolveClassInType(type); - if (psiClass == null) return; - - final PsiClass parentClass = psiClass.getContainingClass(); - if (parentClass != null && !psiClass.hasModifierProperty(PsiModifier.STATIC) && - !PsiTreeUtil.isAncestor(parentClass, parameters.getPosition(), false) && - !(parentClass.getContainingFile().equals(parameters.getOriginalFile()) && - parentClass.getTextRange().contains(parameters.getOffset()))) { - return; - } - - final LookupItem item = PsiTypeLookupItem.createLookupItem(JavaCompletionUtil.eliminateWildcards(type), parameters.getPosition()); - JavaCompletionUtil.setShowFQN(item); - - if (psiClass.isInterface() || psiClass.hasModifierProperty(PsiModifier.ABSTRACT)) { - item.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE); - item.setAttribute(LookupItem.INDICATE_ANONYMOUS, ""); - } - - result.addElement(decorate(type instanceof PsiClassType ? LookupElementDecorator.withInsertHandler(item, ConstructorInsertHandler.SMART_INSTANCE) : item, infos)); - } - static Set completeReference(final PsiElement element, PsiReference reference, final ElementFilter filter, final boolean acceptClasses, CompletionParameters parameters) { if (reference instanceof PsiMultiReference) { reference = ContainerUtil.findInstance(((PsiMultiReference) reference).getReferences(), PsiJavaReference.class); @@ -606,5 +494,4 @@ public class JavaSmartCompletionContributor extends CompletionContributor { } context.setDummyIdentifier("xxx"); } - } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java index 3fe6d901eb38..eaeeb3489b12 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java @@ -330,7 +330,7 @@ public class GroovyCompletionContributor extends CompletionContributor { result.addElement(item); } - JavaSmartCompletionContributor.processInheritors(parameters, identifierCopy, file, expectedClassTypes, new Consumer() { + JavaInheritorsGetter.processInheritors(parameters, identifierCopy, file, expectedClassTypes, new Consumer() { public void consume(final PsiType type) { addExpectedType(result, type, identifierCopy); }