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
.guess
.GuessManager
;
19 import com
.intellij
.codeInsight
.lookup
.*;
20 import com
.intellij
.codeInsight
.lookup
.KeywordLookupItem
;
21 import com
.intellij
.codeInsight
.lookup
.VariableLookupItem
;
22 import com
.intellij
.codeInsight
.template
.SmartCompletionContextType
;
23 import com
.intellij
.codeInsight
.template
.impl
.TemplateImpl
;
24 import com
.intellij
.codeInsight
.template
.impl
.TemplateSettings
;
25 import com
.intellij
.openapi
.application
.ApplicationManager
;
26 import com
.intellij
.openapi
.util
.Computable
;
27 import com
.intellij
.patterns
.PsiJavaPatterns
;
28 import static com
.intellij
.patterns
.PsiJavaPatterns
.psiClass
;
29 import static com
.intellij
.patterns
.PsiJavaPatterns
.psiElement
;
30 import static com
.intellij
.patterns
.StandardPatterns
.not
;
31 import com
.intellij
.psi
.*;
32 import com
.intellij
.psi
.filters
.ContextGetter
;
33 import com
.intellij
.psi
.filters
.element
.ExcludeDeclaredFilter
;
34 import com
.intellij
.psi
.filters
.getters
.ClassLiteralGetter
;
35 import com
.intellij
.psi
.filters
.getters
.FilterGetter
;
36 import com
.intellij
.psi
.filters
.getters
.MembersGetter
;
37 import com
.intellij
.psi
.filters
.getters
.ThisGetter
;
38 import com
.intellij
.psi
.scope
.BaseScopeProcessor
;
39 import com
.intellij
.psi
.scope
.ElementClassFilter
;
40 import com
.intellij
.psi
.scope
.util
.PsiScopesUtil
;
41 import com
.intellij
.psi
.util
.PsiTreeUtil
;
42 import com
.intellij
.util
.Consumer
;
43 import com
.intellij
.util
.IncorrectOperationException
;
44 import com
.intellij
.util
.ProcessingContext
;
45 import org
.jetbrains
.annotations
.NotNull
;
46 import org
.jetbrains
.annotations
.Nullable
;
53 public class BasicExpressionCompletionContributor
extends ExpressionSmartCompletionContributor
{
55 private static void addKeyword(final CompletionResultSet result
, final PsiElement element
, final String s
) {
56 result
.addElement(createKeywordLookupItem(element
, s
));
59 public static LookupElement
createKeywordLookupItem(final PsiElement element
, final String s
) {
60 return ApplicationManager
.getApplication().runReadAction(new Computable
<LookupItem
>() {
61 public LookupItem
compute() {
63 final PsiKeyword keyword
= JavaPsiFacade
.getInstance(element
.getProject()).getElementFactory().createKeyword(s
);
64 return new KeywordLookupItem(keyword
, element
).setAutoCompletionPolicy(AutoCompletionPolicy
.GIVE_CHANCE_TO_OVERWRITE
);
66 catch (IncorrectOperationException e
) {
67 throw new RuntimeException(e
);
74 public BasicExpressionCompletionContributor() {
75 extend(PsiJavaPatterns
.psiElement().afterLeaf(
76 PsiJavaPatterns
.psiElement().withText(".").afterLeaf(
77 PsiJavaPatterns
.psiElement().withParent(
78 PsiJavaPatterns
.psiElement().referencing(psiClass())))), new CompletionProvider
<JavaSmartCompletionParameters
>() {
79 public void addCompletions(@NotNull final JavaSmartCompletionParameters parameters
, final ProcessingContext context
, @NotNull final CompletionResultSet result
) {
80 final PsiElement element
= parameters
.getPosition();
81 addKeyword(result
, element
, PsiKeyword
.CLASS
);
82 addKeyword(result
, element
, PsiKeyword
.THIS
);
87 extend(not(psiElement().afterLeaf(".")), new CollectionsUtilityMethodsProvider());
89 extend(not(psiElement().afterLeaf(".")), new CompletionProvider
<JavaSmartCompletionParameters
>() {
90 protected void addCompletions(@NotNull final JavaSmartCompletionParameters parameters
, final ProcessingContext context
, @NotNull final CompletionResultSet result
) {
91 final PsiElement position
= parameters
.getPosition();
92 final PsiType expectedType
= parameters
.getExpectedType();
93 final FilterGetter baseGetter
= new FilterGetter(new ContextGetter() {
94 public Object
[] get(final PsiElement context
, final CompletionContext completionContext
) {
95 return new Object
[]{expectedType
};
97 }, new ExcludeDeclaredFilter(ElementClassFilter
.CLASS
));
98 for (final LookupElement element
: ClassLiteralGetter
.getClassLiterals(position
, null, result
.getPrefixMatcher(), baseGetter
)) {
99 result
.addElement(element
);
102 for (final TemplateImpl template
: TemplateSettings
.getInstance().getTemplates()) {
103 if (!template
.isDeactivated() && template
.getTemplateContext().isEnabled(new SmartCompletionContextType())) {
104 result
.addElement(new SmartCompletionTemplateItem(template
, position
));
108 addKeyword(result
, position
, PsiKeyword
.TRUE
);
109 addKeyword(result
, position
, PsiKeyword
.FALSE
);
111 final PsiElement parent
= position
.getParent();
112 if (parent
!= null && !(parent
.getParent() instanceof PsiSwitchLabelStatement
)) {
113 MembersGetter
.addMembers(parameters
.getPosition(), expectedType
, result
);
114 if (!parameters
.getDefaultType().equals(expectedType
)) {
115 MembersGetter
.addMembers(parameters
.getPosition(), parameters
.getDefaultType(), result
);
118 for (final PsiExpression expression
: ThisGetter
.getThisExpressionVariants(position
)) {
119 result
.addElement(new ExpressionLookupItem(expression
));
123 processDataflowExpressionTypes(position
, expectedType
, result
.getPrefixMatcher(), new Consumer
<LookupElement
>() {
124 public void consume(LookupElement decorator
) {
125 result
.addElement(decorator
);
133 public static void processDataflowExpressionTypes(PsiElement position
, @Nullable PsiType expectedType
, final PrefixMatcher matcher
, Consumer
<LookupElement
> consumer
) {
134 final PsiExpression context
= PsiTreeUtil
.getParentOfType(position
, PsiExpression
.class);
135 if (context
== null) return;
137 final Map
<PsiExpression
,PsiType
> map
= GuessManager
.getInstance(position
.getProject()).getControlFlowExpressionTypes(context
);
142 PsiScopesUtil
.treeWalkUp(new BaseScopeProcessor() {
143 public boolean execute(PsiElement element
, ResolveState state
) {
144 if (element
instanceof PsiLocalVariable
) {
145 if (!matcher
.prefixMatches(((PsiLocalVariable
)element
).getName())) {
149 final PsiExpression expression
= ((PsiLocalVariable
)element
).getInitializer();
150 if (expression
instanceof PsiTypeCastExpression
) {
151 PsiTypeCastExpression typeCastExpression
= (PsiTypeCastExpression
)expression
;
152 final PsiExpression operand
= typeCastExpression
.getOperand();
153 if (operand
!= null) {
154 final PsiType dfaCasted
= map
.get(operand
);
155 if (dfaCasted
!= null && dfaCasted
.equals(typeCastExpression
.getType())) {
163 }, context
, context
.getContainingFile());
165 for (final PsiExpression expression
: map
.keySet()) {
166 final PsiType castType
= map
.get(expression
);
167 final PsiType baseType
= expression
.getType();
168 if (expectedType
== null || (expectedType
.isAssignableFrom(castType
) && (baseType
== null || !expectedType
.isAssignableFrom(baseType
)))) {
169 consumer
.consume(CastingLookupElementDecorator
.createCastingElement(expressionToLookupElement(expression
), castType
));
175 private static LookupElement
expressionToLookupElement(@NotNull PsiExpression expression
) {
176 if (expression
instanceof PsiReferenceExpression
) {
177 final PsiReferenceExpression refExpr
= (PsiReferenceExpression
)expression
;
178 if (!refExpr
.isQualified()) {
179 final PsiElement target
= refExpr
.resolve();
180 if (target
instanceof PsiVariable
) {
181 final VariableLookupItem item
= new VariableLookupItem((PsiVariable
)target
);
182 item
.setSubstitutor(PsiSubstitutor
.EMPTY
);
187 if (expression
instanceof PsiMethodCallExpression
) {
188 final PsiMethodCallExpression call
= (PsiMethodCallExpression
)expression
;
189 if (!call
.getMethodExpression().isQualified()) {
190 final PsiMethod method
= call
.resolveMethod();
191 if (method
!= null) {
192 return new JavaMethodCallElement(method
);
197 return new ExpressionLookupItem(expression
);