update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / codeInsight / completion / JavaClassNameCompletionContributor.java
blobbb289250e89f020cc6a99147bacc4928bfc231ab
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.codeInsight.completion;
18 import com.intellij.codeInsight.ExpectedTypeInfo;
19 import com.intellij.codeInsight.ExpectedTypesProvider;
20 import com.intellij.openapi.application.ApplicationManager;
21 import com.intellij.openapi.project.Project;
22 import com.intellij.openapi.util.Computable;
23 import com.intellij.openapi.util.text.StringUtil;
24 import com.intellij.openapi.editor.Editor;
25 import com.intellij.openapi.actionSystem.IdeActions;
26 import com.intellij.patterns.PsiJavaElementPattern;
27 import static com.intellij.patterns.PsiJavaPatterns.psiElement;
28 import com.intellij.psi.*;
29 import com.intellij.psi.filters.ClassFilter;
30 import com.intellij.psi.filters.TrueFilter;
31 import com.intellij.psi.filters.classes.ThisOrAnyInnerFilter;
32 import com.intellij.psi.filters.element.ExcludeDeclaredFilter;
33 import com.intellij.psi.filters.types.AssignableFromFilter;
34 import com.intellij.psi.statistics.StatisticsInfo;
35 import com.intellij.psi.statistics.StatisticsManager;
36 import com.intellij.psi.util.PsiTreeUtil;
37 import com.intellij.psi.util.PsiUtil;
38 import com.intellij.util.ProcessingContext;
39 import com.intellij.lang.StdLanguages;
40 import com.intellij.lang.LangBundle;
41 import org.jetbrains.annotations.NotNull;
43 /**
44 * @author peter
46 public class JavaClassNameCompletionContributor extends CompletionContributor {
47 private static final PsiJavaElementPattern.Capture<PsiElement> AFTER_THROW_NEW = psiElement().afterLeaf(
48 psiElement().withText(PsiKeyword.NEW).afterLeaf(PsiKeyword.THROW));
49 private static final PsiJavaElementPattern.Capture<PsiElement> AFTER_NEW = psiElement().afterLeaf(PsiKeyword.NEW);
50 private static final PsiJavaElementPattern.Capture<PsiElement> IN_TYPE_PARAMETER =
51 psiElement().afterLeaf(PsiKeyword.EXTENDS, PsiKeyword.SUPER, "&").withParent(
52 psiElement(PsiReferenceList.class).withParent(PsiTypeParameter.class));
53 private static final PsiJavaElementPattern.Capture<PsiElement> INSIDE_METHOD_THROWS_CLAUSE = psiElement().afterLeaf(PsiKeyword.THROWS, ",").inside(
54 PsiMethod.class).andNot(psiElement().inside(PsiCodeBlock.class)).andNot(psiElement().inside(PsiParameterList.class));
56 public JavaClassNameCompletionContributor() {
57 extend(CompletionType.CLASS_NAME, psiElement(), new CompletionProvider<CompletionParameters>(false) {
58 public void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext matchingContext, @NotNull final CompletionResultSet result) {
59 PsiElement insertedElement = parameters.getPosition();
60 String prefix = result.getPrefixMatcher().getPrefix();
62 final PsiFile file = parameters.getOriginalFile();
63 final Project project = file.getProject();
65 AllClassesGetter getter = new AllClassesGetter(TrueFilter.INSTANCE);
66 boolean afterNew = AFTER_NEW.accepts(insertedElement);
67 if (AFTER_THROW_NEW.accepts(insertedElement)) {
68 getter = new AllClassesGetter(new AssignableFromFilter("java.lang.Throwable"));
70 else if (IN_TYPE_PARAMETER.accepts(insertedElement)) {
71 getter = new AllClassesGetter(new ExcludeDeclaredFilter(new ClassFilter(PsiTypeParameter.class)));
73 else if (INSIDE_METHOD_THROWS_CLAUSE.accepts(insertedElement)) {
74 getter = new AllClassesGetter(new ThisOrAnyInnerFilter(new AssignableFromFilter("java.lang.Throwable")));
77 final StatisticsInfo[] infos =
78 StatisticsManager.getInstance().getAllValues(JavaCompletionStatistician.CLASS_NAME_COMPLETION_PREFIX + StringUtil.capitalsOnly(prefix));
79 for (final StatisticsInfo info : infos) {
80 final PsiClass[] classes = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass[]>() {
81 public PsiClass[] compute() {
82 return JavaPsiFacade.getInstance(project).findClasses(info.getValue(), file.getResolveScope());
84 });
85 for (final PsiClass psiClass : classes) {
86 final boolean isExcluded = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
87 public Boolean compute() {
88 return JavaCompletionUtil.isInExcludedPackage(psiClass);
90 }).booleanValue();
91 if (!isExcluded) {
92 result.addElement(AllClassesGetter.createLookupItem(psiClass));
97 if (afterNew) {
98 final PsiExpression expr = PsiTreeUtil.getContextOfType(insertedElement, PsiExpression.class, true);
99 if (expr != null) {
100 ApplicationManager.getApplication().runReadAction(new Runnable() {
101 public void run() {
102 for (final ExpectedTypeInfo info : ExpectedTypesProvider.getInstance(project).getExpectedTypes(expr, true)) {
103 final PsiType type = info.getType();
104 final PsiClass psiClass = PsiUtil.resolveClassInType(type);
105 if (psiClass != null) {
106 result.addElement(AllClassesGetter.createLookupItem(psiClass));
108 final PsiType defaultType = info.getDefaultType();
109 if (!defaultType.equals(type)) {
110 final PsiClass defClass = PsiUtil.resolveClassInType(defaultType);
111 if (defClass != null) {
112 result.addElement(AllClassesGetter.createLookupItem(defClass));
121 getter.getClasses(insertedElement, result, parameters.getOffset(), parameters.getInvocationCount() == 1);
127 public String advertise(@NotNull final CompletionParameters parameters) {
128 if (shouldShowSecondSmartCompletionHint(parameters) &&
129 CompletionUtil.shouldShowFeature(parameters, CodeCompletionFeatures.SECOND_CLASS_NAME_COMPLETION)) {
130 return CompletionBundle.message("completion.class.name.hint.2", getActionShortcut(IdeActions.ACTION_CLASS_NAME_COMPLETION));
133 return null;
136 @Override
137 public String handleEmptyLookup(@NotNull final CompletionParameters parameters, final Editor editor) {
138 if (!(parameters.getOriginalFile() instanceof PsiJavaFile)) return null;
140 if (shouldShowSecondSmartCompletionHint(parameters)) {
141 return LangBundle.message("completion.no.suggestions") +
142 "; " +
143 StringUtil.decapitalize(
144 CompletionBundle.message("completion.class.name.hint.2", getActionShortcut(IdeActions.ACTION_CLASS_NAME_COMPLETION)));
147 return null;
150 private static boolean shouldShowSecondSmartCompletionHint(final CompletionParameters parameters) {
151 return parameters.getCompletionType() == CompletionType.CLASS_NAME &&
152 parameters.getInvocationCount() == 1 &&
153 parameters.getOriginalFile().getLanguage() == StdLanguages.JAVA;