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
.CodeInsightSettings
;
19 import com
.intellij
.codeInsight
.ExpectedTypeInfo
;
20 import com
.intellij
.codeInsight
.ExpectedTypeInfoImpl
;
21 import com
.intellij
.codeInsight
.completion
.impl
.CamelHumpMatcher
;
22 import com
.intellij
.codeInsight
.completion
.scope
.CompletionElement
;
23 import com
.intellij
.codeInsight
.completion
.scope
.JavaCompletionProcessor
;
24 import com
.intellij
.codeInsight
.generation
.OverrideImplementUtil
;
25 import com
.intellij
.codeInsight
.guess
.GuessManager
;
26 import com
.intellij
.codeInsight
.lookup
.*;
27 import com
.intellij
.featureStatistics
.FeatureUsageTracker
;
28 import com
.intellij
.openapi
.diagnostic
.Logger
;
29 import com
.intellij
.openapi
.editor
.Document
;
30 import com
.intellij
.openapi
.project
.Project
;
31 import com
.intellij
.openapi
.util
.*;
32 import com
.intellij
.openapi
.util
.text
.StringUtil
;
33 import static com
.intellij
.patterns
.PlatformPatterns
.psiElement
;
34 import com
.intellij
.patterns
.PsiElementPattern
;
35 import com
.intellij
.patterns
.PsiJavaPatterns
;
36 import com
.intellij
.psi
.*;
37 import com
.intellij
.psi
.codeStyle
.*;
38 import com
.intellij
.psi
.filters
.ElementFilter
;
39 import com
.intellij
.psi
.filters
.AndFilter
;
40 import com
.intellij
.psi
.filters
.ClassFilter
;
41 import com
.intellij
.psi
.filters
.element
.ExcludeDeclaredFilter
;
42 import com
.intellij
.psi
.filters
.element
.ExcludeSillyAssignment
;
43 import com
.intellij
.psi
.html
.HtmlTag
;
44 import com
.intellij
.psi
.impl
.source
.PsiImmediateClassType
;
45 import com
.intellij
.psi
.infos
.CandidateInfo
;
46 import com
.intellij
.psi
.infos
.ClassCandidateInfo
;
47 import com
.intellij
.psi
.javadoc
.PsiDocToken
;
48 import com
.intellij
.psi
.scope
.BaseScopeProcessor
;
49 import com
.intellij
.psi
.scope
.ElementClassHint
;
50 import com
.intellij
.psi
.scope
.NameHint
;
51 import com
.intellij
.psi
.scope
.ElementClassFilter
;
52 import com
.intellij
.psi
.statistics
.JavaStatisticsManager
;
53 import com
.intellij
.psi
.tree
.IElementType
;
54 import com
.intellij
.psi
.util
.*;
55 import com
.intellij
.psi
.xml
.XmlToken
;
56 import com
.intellij
.psi
.xml
.XmlTokenType
;
57 import com
.intellij
.util
.ArrayUtil
;
58 import com
.intellij
.util
.NullableFunction
;
59 import com
.intellij
.util
.PairFunction
;
60 import com
.intellij
.util
.containers
.HashMap
;
61 import gnu
.trove
.THashSet
;
62 import org
.jetbrains
.annotations
.NonNls
;
63 import org
.jetbrains
.annotations
.NotNull
;
64 import org
.jetbrains
.annotations
.Nullable
;
68 public class JavaCompletionUtil
{
69 private static final Logger LOG
= Logger
.getInstance("#com.intellij.codeInsight.completion.JavaCompletionUtil");
70 public static final Key
<PairFunction
<PsiExpression
, CompletionParameters
, PsiType
>> DYNAMIC_TYPE_EVALUATOR
= Key
.create("DYNAMIC_TYPE_EVALUATOR");
72 static final Key
<PsiType
> QUALIFIER_TYPE_ATTR
= Key
.create("qualifierType"); // SmartPsiElementPointer to PsiType of "qualifier"
74 public static final String GET_PREFIX
= "get";
76 public static final String SET_PREFIX
= "set";
78 public static final String IS_PREFIX
= "is";
79 private static final int MAX_SCOPE_SIZE_TO_SEARCH_UNRESOLVED
= 50000;
80 public static final OffsetKey LPAREN_OFFSET
= OffsetKey
.create("lparen");
81 public static final OffsetKey RPAREN_OFFSET
= OffsetKey
.create("rparen");
82 public static final OffsetKey ARG_LIST_END_OFFSET
= OffsetKey
.create("argListEnd");
83 static final NullableLazyKey
<ExpectedTypeInfo
[], CompletionLocation
> EXPECTED_TYPES
= NullableLazyKey
.create("expectedTypes", new NullableFunction
<CompletionLocation
, ExpectedTypeInfo
[]>() {
85 public ExpectedTypeInfo
[] fun(final CompletionLocation location
) {
86 return JavaSmartCompletionContributor
.getExpectedTypes(location
.getCompletionParameters());
89 private static final PsiElementPattern
.Capture
<PsiElement
> LEFT_PAREN
= psiElement(JavaTokenType
.LPARENTH
).andOr(psiElement().withParent(
90 PsiExpressionList
.class), psiElement().afterLeaf(".", PsiKeyword
.NEW
));
92 public static final Key
<Boolean
> SUPER_METHOD_PARAMETERS
= Key
.create("SUPER_METHOD_PARAMETERS");
95 public static Set
<PsiType
> getExpectedTypes(final CompletionParameters parameters
) {
96 final PsiExpression expr
= PsiTreeUtil
.getContextOfType(parameters
.getPosition(), PsiExpression
.class, true);
98 final ExpectedTypeInfo
[] expectedInfos
= JavaSmartCompletionContributor
.getExpectedTypes(parameters
);
99 if(expectedInfos
!= null){
100 final Set
<PsiType
> set
= new THashSet
<PsiType
>();
101 for (final ExpectedTypeInfo expectedInfo
: expectedInfos
) {
102 set
.add(expectedInfo
.getType());
110 static final NullableLazyKey
<PsiMethod
, CompletionLocation
> POSITION_METHOD
= NullableLazyKey
.create("positionMethod", new NullableFunction
<CompletionLocation
, PsiMethod
>() {
111 public PsiMethod
fun(final CompletionLocation location
) {
112 return PsiTreeUtil
.getParentOfType(location
.getCompletionParameters().getPosition(), PsiMethod
.class, false);
115 public static final Key
<List
<PsiMethod
>> ALL_METHODS_ATTRIBUTE
= Key
.create("allMethods");
117 public static void completeLocalVariableName(Set
<LookupElement
> set
, PrefixMatcher matcher
, PsiVariable var
){
118 FeatureUsageTracker
.getInstance().triggerFeatureUsed("editing.completion.variable.name");
119 final JavaCodeStyleManager codeStyleManager
= JavaCodeStyleManager
.getInstance(var
.getProject());
120 final VariableKind variableKind
= codeStyleManager
.getVariableKind(var
);
122 String propertyName
= null;
123 if (variableKind
== VariableKind
.PARAMETER
) {
124 final PsiMethod method
= PsiTreeUtil
.getParentOfType(var
, PsiMethod
.class);
125 propertyName
= PropertyUtil
.getPropertyName(method
);
128 final PsiType type
= var
.getType();
129 SuggestedNameInfo suggestedNameInfo
= codeStyleManager
.suggestVariableName(variableKind
, propertyName
, null, type
);
130 final String
[] suggestedNames
= suggestedNameInfo
.names
;
131 tunePreferencePolicy(LookupItemUtil
.addLookupItems(set
, suggestedNames
, matcher
), suggestedNameInfo
);
133 if (type
.equalsToText(CommonClassNames
.JAVA_LANG_OBJECT
) && matcher
.prefixMatches("object")) {
134 set
.add(LookupElementBuilder
.create("object"));
136 if (type
.equalsToText(CommonClassNames
.JAVA_LANG_STRING
) && matcher
.prefixMatches("string")) {
137 set
.add(LookupElementBuilder
.create("string"));
142 suggestedNameInfo
= new SuggestedNameInfo(getOverlappedNameVersions(matcher
.getPrefix(), suggestedNames
, "")) {
143 public void nameChoosen(String name
) {
147 tunePreferencePolicy(LookupItemUtil
.addLookupItems(set
, suggestedNameInfo
.names
, matcher
), suggestedNameInfo
);
149 PsiElement parent
= PsiTreeUtil
.getParentOfType(var
, PsiCodeBlock
.class);
150 if(parent
== null) parent
= PsiTreeUtil
.getParentOfType(var
, PsiMethod
.class);
151 tunePreferencePolicy(LookupItemUtil
.addLookupItems(set
, getUnresolvedReferences(parent
, false), matcher
), suggestedNameInfo
);
152 final String
[] nameSuggestions
=
153 JavaStatisticsManager
.getNameSuggestions(type
, JavaStatisticsManager
.getContext(var
), matcher
.getPrefix());
154 tunePreferencePolicy(LookupItemUtil
.addLookupItems(set
, nameSuggestions
, matcher
), suggestedNameInfo
);
157 public static void completeFieldName(Set
<LookupElement
> set
, PsiVariable var
, final PrefixMatcher matcher
){
158 FeatureUsageTracker
.getInstance().triggerFeatureUsed("editing.completion.variable.name");
160 JavaCodeStyleManager codeStyleManager
= JavaCodeStyleManager
.getInstance(var
.getProject());
161 final VariableKind variableKind
= JavaCodeStyleManager
.getInstance(var
.getProject()).getVariableKind(var
);
163 final String prefix
= matcher
.getPrefix();
164 if (PsiType
.VOID
.equals(var
.getType()) || prefix
.startsWith(IS_PREFIX
) ||
165 prefix
.startsWith(GET_PREFIX
) ||
166 prefix
.startsWith(SET_PREFIX
)) {
167 completeVariableNameForRefactoring(var
.getProject(), set
, matcher
, var
.getType(), variableKind
);
171 SuggestedNameInfo suggestedNameInfo
= codeStyleManager
.suggestVariableName(variableKind
, null, null, var
.getType());
172 final String
[] suggestedNames
= suggestedNameInfo
.names
;
173 tunePreferencePolicy(LookupItemUtil
.addLookupItems(set
, suggestedNames
, matcher
), suggestedNameInfo
);
176 // use suggested names as suffixes
177 final String requiredSuffix
= codeStyleManager
.getSuffixByVariableKind(variableKind
);
178 if(variableKind
!= VariableKind
.STATIC_FINAL_FIELD
){
179 for (int i
= 0; i
< suggestedNames
.length
; i
++)
180 suggestedNames
[i
] = codeStyleManager
.variableNameToPropertyName(suggestedNames
[i
], variableKind
);
184 suggestedNameInfo
= new SuggestedNameInfo(getOverlappedNameVersions(prefix
, suggestedNames
, requiredSuffix
)) {
185 public void nameChoosen(String name
) {
189 tunePreferencePolicy(LookupItemUtil
.addLookupItems(set
, suggestedNameInfo
.names
, matcher
), suggestedNameInfo
);
192 tunePreferencePolicy(LookupItemUtil
.addLookupItems(set
, JavaStatisticsManager
.getNameSuggestions(var
.getType(), JavaStatisticsManager
.getContext(var
), matcher
.getPrefix()), matcher
), suggestedNameInfo
);
193 tunePreferencePolicy(LookupItemUtil
.addLookupItems(set
, getUnresolvedReferences(var
.getParent(), false),
194 matcher
), suggestedNameInfo
);
197 public static void completeMethodName(Set
<LookupElement
> set
, PsiElement element
, final PrefixMatcher matcher
){
198 if(element
instanceof PsiMethod
) {
199 final PsiMethod method
= (PsiMethod
)element
;
200 if (method
.isConstructor()) {
201 final PsiClass containingClass
= method
.getContainingClass();
202 final String name
= containingClass
.getName();
203 if (StringUtil
.isNotEmpty(name
)) {
204 LookupItemUtil
.addLookupItem(set
, name
, matcher
);
210 PsiClass ourClassParent
= PsiTreeUtil
.getParentOfType(element
, PsiClass
.class);
211 if (ourClassParent
== null) return;
212 LookupItemUtil
.addLookupItems(set
, getUnresolvedReferences(ourClassParent
, true), matcher
);
214 if(!((PsiModifierListOwner
)element
).hasModifierProperty(PsiModifier
.PRIVATE
)){
215 LookupItemUtil
.addLookupItems(set
, getOverides(ourClassParent
, PsiUtil
.getTypeByPsiElement(element
)),
217 LookupItemUtil
.addLookupItems(set
, getImplements(ourClassParent
, PsiUtil
.getTypeByPsiElement(element
)),
220 LookupItemUtil
.addLookupItems(set
, getPropertiesHandlersNames(
222 ((PsiModifierListOwner
)element
).hasModifierProperty(PsiModifier
.STATIC
),
223 PsiUtil
.getTypeByPsiElement(element
), element
), matcher
);
226 public static PsiType
getQualifierType(LookupItem item
) {
227 return item
.getUserData(QUALIFIER_TYPE_ATTR
);
230 public static void completeVariableNameForRefactoring(Project project
, Set
<LookupElement
> set
, String prefix
, PsiType varType
, VariableKind varKind
) {
231 completeVariableNameForRefactoring(project
, set
, new CamelHumpMatcher(prefix
), varType
, varKind
);
234 public static void completeVariableNameForRefactoring(Project project
, Set
<LookupElement
> set
, PrefixMatcher matcher
, PsiType varType
, VariableKind varKind
) {
235 JavaCodeStyleManager codeStyleManager
= JavaCodeStyleManager
.getInstance(project
);
236 SuggestedNameInfo suggestedNameInfo
= codeStyleManager
.suggestVariableName(varKind
, null, null, varType
);
237 final String
[] strings
= completeVariableNameForRefactoring(codeStyleManager
, matcher
, varType
, varKind
, suggestedNameInfo
);
238 tunePreferencePolicy(LookupItemUtil
.addLookupItems(set
, strings
, matcher
), suggestedNameInfo
);
241 public static String
[] completeVariableNameForRefactoring(JavaCodeStyleManager codeStyleManager
, final PsiType varType
,
242 final VariableKind varKind
,
243 SuggestedNameInfo suggestedNameInfo
) {
244 return completeVariableNameForRefactoring(codeStyleManager
, new CamelHumpMatcher(""), varType
, varKind
, suggestedNameInfo
);
247 public static String
[] completeVariableNameForRefactoring(JavaCodeStyleManager codeStyleManager
, final PrefixMatcher matcher
, final PsiType varType
,
248 final VariableKind varKind
,
249 SuggestedNameInfo suggestedNameInfo
) {
250 Set
<String
> result
= new LinkedHashSet
<String
>();
251 final String
[] suggestedNames
= suggestedNameInfo
.names
;
252 for (final String suggestedName
: suggestedNames
) {
253 if (matcher
.prefixMatches(suggestedName
)) {
254 result
.add(suggestedName
);
258 if (result
.isEmpty() && PsiType
.VOID
!= varType
) {
259 // use suggested names as suffixes
260 final String requiredSuffix
= codeStyleManager
.getSuffixByVariableKind(varKind
);
261 final String prefix
= matcher
.getPrefix();
262 final boolean isMethodPrefix
= prefix
.startsWith(IS_PREFIX
) || prefix
.startsWith(GET_PREFIX
) || prefix
.startsWith(SET_PREFIX
);
263 if (varKind
!= VariableKind
.STATIC_FINAL_FIELD
|| isMethodPrefix
) {
264 for (int i
= 0; i
< suggestedNames
.length
; i
++) {
265 suggestedNames
[i
] = codeStyleManager
.variableNameToPropertyName(suggestedNames
[i
], varKind
);
269 result
.addAll(Arrays
.asList(getOverlappedNameVersions(prefix
, suggestedNames
, requiredSuffix
)));
273 return result
.toArray(new String
[result
.size()]);
276 private static void tunePreferencePolicy(final List
<LookupElement
> list
, final SuggestedNameInfo suggestedNameInfo
) {
277 final InsertHandler insertHandler
= new InsertHandler() {
278 public void handleInsert(final InsertionContext context
, final LookupElement item
) {
279 suggestedNameInfo
.nameChoosen(item
.getLookupString());
283 for (int i
= 0; i
< list
.size(); i
++) {
284 LookupElement item
= list
.get(i
);
285 if (item
instanceof LookupItem
) {
286 ((LookupItem
)item
).setPriority(list
.size() - i
).setInsertHandler(insertHandler
);
291 public static String
[] getOverlappedNameVersions(final String prefix
, final String
[] suggestedNames
, String suffix
) {
292 final List
<String
> newSuggestions
= new ArrayList
<String
>();
293 int longestOverlap
= 0;
295 for (String suggestedName
: suggestedNames
) {
296 if (suggestedName
.toUpperCase().startsWith(prefix
.toUpperCase())) {
297 newSuggestions
.add(suggestedName
);
298 longestOverlap
= prefix
.length();
301 suggestedName
= String
.valueOf(Character
.toUpperCase(suggestedName
.charAt(0))) + suggestedName
.substring(1);
302 final int overlap
= getOverlap(suggestedName
, prefix
);
304 if (overlap
< longestOverlap
) continue;
306 if (overlap
> longestOverlap
) {
307 newSuggestions
.clear();
308 longestOverlap
= overlap
;
311 String suggestion
= prefix
.substring(0, prefix
.length() - overlap
) + suggestedName
;
313 final int lastIndexOfSuffix
= suggestion
.lastIndexOf(suffix
);
314 if (lastIndexOfSuffix
>= 0 && suffix
.length() < suggestion
.length() - lastIndexOfSuffix
) {
315 suggestion
= suggestion
.substring(0, lastIndexOfSuffix
) + suffix
;
318 if (!newSuggestions
.contains(suggestion
)) {
319 newSuggestions
.add(suggestion
);
322 return newSuggestions
.toArray(new String
[newSuggestions
.size()]);
325 static int getOverlap(final String propertyName
, final String prefix
) {
327 int propertyNameLen
= propertyName
.length();
328 int prefixLen
= prefix
.length();
329 for (int j
= 1; j
< prefixLen
&& j
< propertyNameLen
; j
++) {
330 if (prefix
.substring(prefixLen
- j
).equals(propertyName
.substring(0, j
))) {
337 public static PsiType
eliminateWildcards(PsiType type
) {
338 return eliminateWildcardsInner(type
, true);
341 static PsiType
eliminateWildcardsInner(PsiType type
, final boolean eliminateInTypeArguments
) {
342 if (eliminateInTypeArguments
&& type
instanceof PsiClassType
) {
343 PsiClassType classType
= ((PsiClassType
)type
);
344 JavaResolveResult resolveResult
= classType
.resolveGenerics();
345 PsiClass aClass
= (PsiClass
)resolveResult
.getElement();
346 if (aClass
!= null) {
347 PsiManager manager
= aClass
.getManager();
348 PsiTypeParameter
[] typeParams
= aClass
.getTypeParameters();
349 Map
<PsiTypeParameter
, PsiType
> map
= new HashMap
<PsiTypeParameter
, PsiType
>();
350 for (PsiTypeParameter typeParam
: typeParams
) {
351 PsiType substituted
= resolveResult
.getSubstitutor().substitute(typeParam
);
352 if (substituted
instanceof PsiWildcardType
) {
353 substituted
= ((PsiWildcardType
)substituted
).getBound();
354 if (substituted
== null) substituted
= PsiType
.getJavaLangObject(manager
, aClass
.getResolveScope());
356 map
.put(typeParam
, substituted
);
359 PsiElementFactory factory
= JavaPsiFacade
.getInstance(manager
.getProject()).getElementFactory();
360 PsiSubstitutor substitutor
= factory
.createSubstitutor(map
);
361 type
= factory
.createType(aClass
, substitutor
);
364 else if (type
instanceof PsiArrayType
) {
365 return eliminateWildcardsInner(((PsiArrayType
)type
).getComponentType(), false).createArrayType();
367 else if (type
instanceof PsiWildcardType
) {
368 return ((PsiWildcardType
)type
).getExtendsBound();
373 public static String
[] getOverides(final PsiClass parent
, final PsiType typeByPsiElement
) {
374 final List
<String
> overides
= new ArrayList
<String
>();
375 final Collection
<CandidateInfo
> methodsToOverrideImplement
= OverrideImplementUtil
.getMethodsToOverrideImplement(parent
, true);
376 for (final CandidateInfo candidateInfo
: methodsToOverrideImplement
) {
377 final PsiElement element
= candidateInfo
.getElement();
378 if (Comparing
.equal(typeByPsiElement
, PsiUtil
.getTypeByPsiElement(element
)) && element
instanceof PsiNamedElement
) {
379 overides
.add(((PsiNamedElement
)element
).getName());
382 return ArrayUtil
.toStringArray(overides
);
385 public static String
[] getImplements(final PsiClass parent
, final PsiType typeByPsiElement
) {
386 final List
<String
> overides
= new ArrayList
<String
>();
387 final Collection
<CandidateInfo
> methodsToOverrideImplement
= OverrideImplementUtil
.getMethodsToOverrideImplement(parent
, false);
388 for (final CandidateInfo candidateInfo
: methodsToOverrideImplement
) {
389 final PsiElement element
= candidateInfo
.getElement();
390 if (Comparing
.equal(typeByPsiElement
,PsiUtil
.getTypeByPsiElement(element
)) && element
instanceof PsiNamedElement
) {
391 overides
.add(((PsiNamedElement
)element
).getName());
394 return ArrayUtil
.toStringArray(overides
);
397 public static String
[] getPropertiesHandlersNames(final PsiClass psiClass
,
398 final boolean staticContext
,
399 final PsiType varType
,
400 final PsiElement element
) {
401 class Change
implements Runnable
{
402 private String
[] result
;
405 final List
<String
> propertyHandlers
= new ArrayList
<String
>();
406 final PsiField
[] fields
= psiClass
.getFields();
408 for (final PsiField field
: fields
) {
409 if (field
== element
) continue;
410 final PsiModifierList modifierList
= field
.getModifierList();
411 if (staticContext
&& (modifierList
!= null && !modifierList
.hasModifierProperty(PsiModifier
.STATIC
))) continue;
413 if (field
.getType().equals(varType
)) {
414 final String getterName
= PropertyUtil
.suggestGetterName(field
.getProject(), field
);
415 if ((psiClass
.findMethodsByName(getterName
, true).length
== 0 ||
416 psiClass
.findMethodBySignature(PropertyUtil
.generateGetterPrototype(field
), true) == null)) {
417 propertyHandlers
.add(getterName
);
421 if (PsiType
.VOID
.equals(varType
)) {
422 final String setterName
= PropertyUtil
.suggestSetterName(field
.getProject(), field
);
423 if ((psiClass
.findMethodsByName(setterName
, true).length
== 0 ||
424 psiClass
.findMethodBySignature(PropertyUtil
.generateSetterPrototype(field
), true) == null)) {
425 propertyHandlers
.add(setterName
);
429 result
= ArrayUtil
.toStringArray(propertyHandlers
);
432 final Change result
= new Change();
433 element
.getManager().performActionWithFormatterDisabled(result
);
434 return result
.result
;
437 public static boolean isInExcludedPackage(@NotNull final PsiClass psiClass
) {
438 final String name
= psiClass
.getQualifiedName();
439 if (name
== null) return false;
440 CodeInsightSettings cis
= CodeInsightSettings
.getInstance();
441 for (String excluded
: cis
.EXCLUDED_PACKAGES
) {
442 if (name
.equals(excluded
) || name
.startsWith(excluded
+ ".")) {
450 public static PsiField
getOriginalElement(@NotNull PsiField field
) {
451 final PsiClass cls
= field
.getContainingClass();
453 final PsiClass newParent
= getOriginalElement(cls
);
454 if (newParent
!= cls
) {
455 final PsiField original
= newParent
.findFieldByName(field
.getName(), false);
456 if (original
!= null) {
465 public static PsiTypeParameter
getOriginalElement(@NotNull PsiTypeParameter param
) {
466 final PsiClass parent
= PsiTreeUtil
.getParentOfType(param
, PsiClass
.class, true, PsiMethod
.class);
467 if (parent
!= null) {
468 final PsiClass newParent
= getOriginalElement(parent
);
469 if (newParent
!= parent
) {
470 for (PsiTypeParameter parameter
: newParent
.getTypeParameters()) {
471 if (parameter
.getName().equals(param
.getName())) {
481 public static PsiClass
getOriginalElement(@NotNull PsiClass cls
) {
482 final PsiClass containingClass
= cls
.getContainingClass();
483 if (containingClass
!= null) {
484 final PsiClass newParent
= getOriginalElement(containingClass
);
485 if (newParent
!= containingClass
) {
486 return findClassByName(cls
, newParent
.getInnerClasses());
490 final PsiFile containingFile
= cls
.getContainingFile();
491 if (containingFile
instanceof PsiClassOwner
) {
492 return findClassByName(cls
, ((PsiClassOwner
)containingFile
.getOriginalFile()).getClasses());
498 private static PsiClass
findClassByName(PsiClass defResult
, PsiClass
[] classes
) {
499 String name
= defResult
.getName();
500 if (name
== null) return defResult
;
502 for (PsiClass candidate
: classes
) {
503 if (name
.equals(candidate
.getName())) {
510 @SuppressWarnings({"unchecked"})
512 public static <T
extends PsiType
> T
originalize(@NotNull T type
) {
513 if (!type
.isValid()) {
517 return (T
)type
.accept(new PsiTypeVisitor
<PsiType
>() {
519 public PsiType
visitArrayType(final PsiArrayType arrayType
) {
520 return new PsiArrayType(originalize(arrayType
.getComponentType()));
523 public PsiType
visitCapturedWildcardType(final PsiCapturedWildcardType capturedWildcardType
) {
524 return PsiCapturedWildcardType
.create(originalize(capturedWildcardType
.getWildcard()), capturedWildcardType
.getContext());
527 public PsiType
visitClassType(final PsiClassType classType
) {
528 final PsiClassType
.ClassResolveResult classResolveResult
= classType
.resolveGenerics();
529 final PsiClass psiClass
= classResolveResult
.getElement();
530 final PsiSubstitutor substitutor
= classResolveResult
.getSubstitutor();
531 if (psiClass
== null) return classType
;
533 LOG
.assertTrue(psiClass
.isValid());
535 return new PsiImmediateClassType(getOriginalElement(psiClass
), originalize(substitutor
));
538 public PsiType
visitEllipsisType(final PsiEllipsisType ellipsisType
) {
539 return new PsiEllipsisType(originalize(ellipsisType
.getComponentType()));
542 public PsiType
visitPrimitiveType(final PsiPrimitiveType primitiveType
) {
543 return primitiveType
;
546 public PsiType
visitType(final PsiType type
) {
550 public PsiType
visitWildcardType(final PsiWildcardType wildcardType
) {
551 final PsiType bound
= wildcardType
.getBound();
552 final PsiManager manager
= wildcardType
.getManager();
553 if (bound
== null) return PsiWildcardType
.createUnbounded(manager
);
554 return wildcardType
.isExtends() ? PsiWildcardType
.createExtends(manager
, bound
) : PsiWildcardType
.createSuper(manager
, bound
);
560 private static PsiSubstitutor
originalize(@Nullable final PsiSubstitutor substitutor
) {
561 if (substitutor
== null) return null;
563 PsiSubstitutor originalSubstitutor
= PsiSubstitutor
.EMPTY
;
564 for (final Map
.Entry
<PsiTypeParameter
, PsiType
> entry
: substitutor
.getSubstitutionMap().entrySet()) {
565 final PsiType value
= entry
.getValue();
566 originalSubstitutor
= originalSubstitutor
.put(getOriginalElement(entry
.getKey()), value
== null ?
null : originalize(value
));
568 return originalSubstitutor
;
571 public static String
[] getUnresolvedReferences(final PsiElement parentOfType
, final boolean referenceOnMethod
) {
572 if (parentOfType
!= null && parentOfType
.getTextLength() > MAX_SCOPE_SIZE_TO_SEARCH_UNRESOLVED
) return ArrayUtil
.EMPTY_STRING_ARRAY
;
573 final List
<String
> unresolvedRefs
= new ArrayList
<String
>();
575 if (parentOfType
!= null) {
576 parentOfType
.accept(new JavaRecursiveElementWalkingVisitor() {
577 @Override public void visitReferenceExpression(PsiReferenceExpression reference
) {
578 final PsiElement parent
= reference
.getParent();
579 if (parent
instanceof PsiReference
) return;
580 if (referenceOnMethod
&& parent
instanceof PsiMethodCallExpression
&&
581 reference
== ((PsiMethodCallExpression
)parent
).getMethodExpression()) {
582 if (reference
.resolve() == null && reference
.getReferenceName() != null) unresolvedRefs
.add(reference
.getReferenceName());
584 else if (!referenceOnMethod
&& !(parent
instanceof PsiMethodCallExpression
) &&reference
.resolve() == null && reference
.getReferenceName() != null) {
585 unresolvedRefs
.add(reference
.getReferenceName());
590 return ArrayUtil
.toStringArray(unresolvedRefs
);
593 public static void initOffsets(final PsiFile file
, final Project project
, final OffsetMap offsetMap
){
594 int selectionEndOffset
= offsetMap
.getOffset(CompletionInitializationContext
.SELECTION_END_OFFSET
);
596 PsiElement element
= file
.findElementAt(selectionEndOffset
);
597 if (element
== null) return;
599 if (LEFT_PAREN
.accepts(element
)) {
600 selectionEndOffset
--;
601 element
= file
.findElementAt(selectionEndOffset
);
602 if (element
== null) return;
605 final PsiReference reference
= file
.findReferenceAt(selectionEndOffset
);
606 if(reference
!= null) {
607 if(reference
instanceof PsiJavaCodeReferenceElement
){
608 offsetMap
.addOffset(CompletionInitializationContext
.IDENTIFIER_END_OFFSET
, element
.getParent().getTextRange().getEndOffset());
611 offsetMap
.addOffset(CompletionInitializationContext
.IDENTIFIER_END_OFFSET
,
612 reference
.getElement().getTextRange().getStartOffset() + reference
.getRangeInElement().getEndOffset());
615 element
= file
.findElementAt(offsetMap
.getOffset(CompletionInitializationContext
.IDENTIFIER_END_OFFSET
));
617 else if (isWord(element
)){
618 if(element
instanceof PsiIdentifier
&& element
.getParent() instanceof PsiJavaCodeReferenceElement
){
619 offsetMap
.addOffset(CompletionInitializationContext
.IDENTIFIER_END_OFFSET
, element
.getParent().getTextRange().getEndOffset());
622 offsetMap
.addOffset(CompletionInitializationContext
.IDENTIFIER_END_OFFSET
, element
.getTextRange().getEndOffset());
625 element
= file
.findElementAt(offsetMap
.getOffset(CompletionInitializationContext
.IDENTIFIER_END_OFFSET
));
626 if (element
== null) return;
629 if (element
instanceof PsiWhiteSpace
&&
630 ( !element
.textContains('\n') ||
631 CodeStyleSettingsManager
.getInstance(project
).getCurrentSettings().METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE
634 element
= file
.findElementAt(element
.getTextRange().getEndOffset());
637 if (LEFT_PAREN
.accepts(element
)) {
638 offsetMap
.addOffset(LPAREN_OFFSET
, element
.getTextRange().getStartOffset());
639 PsiElement list
= element
.getParent();
640 PsiElement last
= list
.getLastChild();
641 if (last
instanceof PsiJavaToken
&& ((PsiJavaToken
)last
).getTokenType() == JavaTokenType
.RPARENTH
) {
642 offsetMap
.addOffset(RPAREN_OFFSET
, last
.getTextRange().getStartOffset());
646 offsetMap
.addOffset(ARG_LIST_END_OFFSET
, list
.getTextRange().getEndOffset());
651 static boolean isWord(PsiElement element
) {
652 if (element
instanceof PsiIdentifier
){
655 else if (element
instanceof PsiKeyword
){
658 else if (element
instanceof PsiJavaToken
){
659 final String text
= element
.getText();
660 if(PsiKeyword
.TRUE
.equals(text
)) return true;
661 if(PsiKeyword
.FALSE
.equals(text
)) return true;
662 if(PsiKeyword
.NULL
.equals(text
)) return true;
665 else if (element
instanceof PsiDocToken
) {
666 IElementType tokenType
= ((PsiDocToken
)element
).getTokenType();
667 return tokenType
== JavaDocTokenType
.DOC_TAG_VALUE_TOKEN
|| tokenType
== JavaDocTokenType
.DOC_TAG_NAME
;
669 else if (element
instanceof XmlToken
) {
670 IElementType tokenType
= ((XmlToken
)element
).getTokenType();
671 return tokenType
== XmlTokenType
.XML_TAG_NAME
||
672 tokenType
== XmlTokenType
.XML_NAME
||
673 tokenType
== XmlTokenType
.XML_ATTRIBUTE_VALUE_TOKEN
||
674 // html data chars contains whitespaces
675 (tokenType
== XmlTokenType
.XML_DATA_CHARACTERS
&& !(element
.getParent() instanceof HtmlTag
));
682 public static void resetParensInfo(final OffsetMap offsetMap
) {
683 offsetMap
.removeOffset(LPAREN_OFFSET
);
684 offsetMap
.removeOffset(RPAREN_OFFSET
);
685 offsetMap
.removeOffset(ARG_LIST_END_OFFSET
);
686 offsetMap
.removeOffset(CompletionInitializationContext
.IDENTIFIER_END_OFFSET
);
690 public static List
<?
extends PsiElement
> getAllPsiElements(final LookupElement item
) {
691 List
<PsiMethod
> allMethods
= item
.getUserData(ALL_METHODS_ATTRIBUTE
);
692 if (allMethods
!= null) return allMethods
;
693 if (item
.getObject() instanceof PsiElement
) return Arrays
.asList((PsiElement
)item
.getObject());
698 private static PsiType
getPsiType(final Object o
) {
699 if (o
instanceof PsiVariable
) {
700 return ((PsiVariable
)o
).getType();
702 else if (o
instanceof PsiMethod
) {
703 return ((PsiMethod
)o
).getReturnType();
705 else if (o
instanceof PsiClass
) {
706 final PsiClass psiClass
= (PsiClass
)o
;
707 return JavaPsiFacade
.getInstance(psiClass
.getProject()).getElementFactory().createType(psiClass
);
709 else if (o
instanceof PsiExpression
) {
710 return ((PsiExpression
)o
).getType();
715 public static int getNameEndMatchingDegree(final String name
, ExpectedTypeInfo
[] expectedInfos
, String prefix
) {
717 if (name
!= null && expectedInfos
!= null) {
718 if (prefix
.equals(name
)) {
719 res
= Integer
.MAX_VALUE
;
721 final List
<String
> words
= NameUtil
.nameToWordsLowerCase(name
);
722 final List
<String
> wordsNoDigits
= NameUtil
.nameToWordsLowerCase(truncDigits(name
));
723 int max1
= calcMatch(words
, 0, expectedInfos
);
724 max1
= calcMatch(wordsNoDigits
, max1
, expectedInfos
);
732 static String
truncDigits(String name
){
733 int count
= name
.length() - 1;
735 char c
= name
.charAt(count
);
736 if (!Character
.isDigit(c
)) break;
739 return name
.substring(0, count
+ 1);
742 static int calcMatch(final List
<String
> words
, int max
, ExpectedTypeInfo
[] myExpectedInfos
) {
743 for (ExpectedTypeInfo myExpectedInfo
: myExpectedInfos
) {
744 String expectedName
= ((ExpectedTypeInfoImpl
)myExpectedInfo
).expectedName
;
745 if (expectedName
== null) continue;
746 max
= calcMatch(expectedName
, words
, max
);
747 max
= calcMatch(truncDigits(expectedName
), words
, max
);
752 static int calcMatch(final String expectedName
, final List
<String
> words
, int max
) {
753 if (expectedName
== null) return max
;
755 String
[] expectedWords
= NameUtil
.nameToWords(expectedName
);
756 int limit
= Math
.min(words
.size(), expectedWords
.length
);
757 for (int i
= 0; i
< limit
; i
++) {
758 String word
= words
.get(words
.size() - i
- 1);
759 String expectedWord
= expectedWords
[expectedWords
.length
- i
- 1];
760 if (word
.equalsIgnoreCase(expectedWord
)) {
761 max
= Math
.max(max
, i
+ 1);
771 static String
getLookupObjectName(Object o
) {
772 if (o
instanceof PsiVariable
) {
773 final PsiVariable variable
= (PsiVariable
)o
;
774 JavaCodeStyleManager codeStyleManager
= JavaCodeStyleManager
.getInstance(variable
.getProject());
775 VariableKind variableKind
= codeStyleManager
.getVariableKind(variable
);
776 return codeStyleManager
.variableNameToPropertyName(variable
.getName(), variableKind
);
778 if (o
instanceof PsiMethod
) {
779 return ((PsiMethod
)o
).getName();
785 public static PsiType
getLookupElementType(final LookupElement element
) {
786 final TypedLookupItem typed
= element
.as(TypedLookupItem
.class);
788 return typed
.getType();
792 final PsiType qualifierType
= getPsiType(element
.getObject());
793 final LookupItem lookupItem
= element
.as(LookupItem
.class);
794 if (lookupItem
!= null) {
795 final PsiSubstitutor substitutor
= (PsiSubstitutor
)lookupItem
.getAttribute(LookupItem
.SUBSTITUTOR
);
796 if (substitutor
!= null) {
797 return substitutor
.substitute(qualifierType
);
800 return qualifierType
;
804 public static PsiType
getQualifiedMemberReferenceType(@Nullable PsiType qualifierType
, @NotNull final PsiMember member
) {
805 final ClassCandidateInfo info
= TypeConversionUtil
.splitType(qualifierType
, member
);
810 final PsiClass element
= info
.getElement();
811 assert element
!= null;
813 final Ref
<PsiSubstitutor
> subst
= Ref
.create(PsiSubstitutor
.EMPTY
);
814 class MyProcessor
extends BaseScopeProcessor
implements NameHint
, ElementClassHint
{
815 public boolean execute(PsiElement element
, ResolveState state
) {
816 if (element
== member
) {
817 subst
.set(state
.get(PsiSubstitutor
.KEY
));
822 public String
getName(ResolveState state
) {
823 return member
.getName();
826 public boolean shouldProcess(DeclaractionKind kind
) {
827 return member
instanceof PsiEnumConstant ? kind
== DeclaractionKind
.ENUM_CONST
:
828 member
instanceof PsiField ? kind
== DeclaractionKind
.FIELD
:
829 kind
== DeclaractionKind
.METHOD
;
833 public <T
> T
getHint(Key
<T
> hintKey
) {
834 return hintKey
== NameHint
.KEY
|| hintKey
== ElementClassHint
.KEY ?
(T
)this : null;
838 element
.processDeclarations(new MyProcessor(), ResolveState
.initial().put(PsiSubstitutor
.KEY
, info
.getSubstitutor()), null, member
);
840 PsiType rawType
= member
instanceof PsiField ?
((PsiField
) member
).getType() : ((PsiMethod
) member
).getReturnType();
841 return subst
.get().substitute(rawType
);
844 public static Set
<LookupElement
> processJavaReference(PsiElement element
, PsiJavaReference javaReference
, ElementFilter elementFilter
,
845 final boolean checkAccess
, @Nullable final PrefixMatcher matcher
, CompletionParameters parameters
) {
846 final THashSet
<LookupElement
> set
= new THashSet
<LookupElement
>();
847 final Condition
<String
> nameCondition
= matcher
== null ?
null : new Condition
<String
>() {
848 public boolean value(String s
) {
849 return matcher
.prefixMatches(s
);
852 final JavaCompletionProcessor processor
= new JavaCompletionProcessor(element
, elementFilter
, checkAccess
, nameCondition
);
853 javaReference
.processVariants(processor
);
854 final Collection
<CompletionElement
> plainResults
= processor
.getResults();
856 final PsiType qualifierType
= processor
.getQualifierType();
857 PsiType castedQualifierType
= addQualifierCastingVariants(javaReference
, processor
, set
, parameters
);
859 boolean mayHighlight
= qualifierType
!= null && (castedQualifierType
== null || !qualifierType
.isAssignableFrom(castedQualifierType
));
861 for (CompletionElement completionElement
: plainResults
) {
862 LookupElement item
= createLookupElement(completionElement
, qualifierType
);
864 set
.add(mayHighlight ?
highlightIfNeeded(qualifierType
, item
) : item
);
872 private static PsiType
addQualifierCastingVariants(PsiJavaReference javaReference
, JavaCompletionProcessor processor
, THashSet
<LookupElement
> set
, CompletionParameters parameters
) {
873 if (javaReference
instanceof PsiReferenceExpression
) {
874 final PsiReferenceExpression refExpr
= (PsiReferenceExpression
)javaReference
;
875 final PsiExpression qualifier
= refExpr
.getQualifierExpression();
876 if (qualifier
!= null) {
877 final Project project
= qualifier
.getProject();
878 final PairFunction
<PsiExpression
, CompletionParameters
, PsiType
> evaluator
= refExpr
.getContainingFile().getCopyableUserData(DYNAMIC_TYPE_EVALUATOR
);
880 if (evaluator
!= null) {
881 type
= evaluator
.fun(qualifier
, parameters
);
884 type
= GuessManager
.getInstance(project
).getControlFlowExpressionType(qualifier
);
889 return addQualifierCastingVariants(processor
, refExpr
, type
, set
);
896 private static PsiType
addQualifierCastingVariants(JavaCompletionProcessor processor
, PsiReferenceExpression refExpr
,
898 THashSet
<LookupElement
> set
) {
899 Project project
= refExpr
.getProject();
901 PsiExpression qualifier
= refExpr
.getQualifierExpression();
902 assert qualifier
!= null;
903 final String newText
= "((" + castTo
.getCanonicalText() + ") " + qualifier
.getText() + ")." + refExpr
.getReferenceName();
904 final PsiExpression newRef
= JavaPsiFacade
.getElementFactory(project
).createExpressionFromText(newText
, refExpr
);
905 ((PsiReferenceExpression
)newRef
).processVariants(processor
);
907 final LookupElement castItem
= PsiTypeLookupItem
.createLookupItem(castTo
);
909 for (CompletionElement completionElement
: processor
.getResults()) {
910 final LookupElement item
= createLookupElement(completionElement
, castTo
);
912 set
.add(highlightIfNeeded(castTo
, castQualifier(project
, item
, castItem
)));
918 private static LookupElementDecorator
<LookupElement
> castQualifier(final Project project
, LookupElement item
, final LookupElement to
) {
919 return LookupElementDecorator
.withInsertHandler(item
, new InsertHandlerDecorator
<LookupElement
>() {
920 public void handleInsert(InsertionContext context
, LookupElementDecorator
<LookupElement
> item
) {
921 final Document document
= context
.getEditor().getDocument();
922 PsiDocumentManager
.getInstance(project
).commitDocument(document
);
923 final PsiFile file
= context
.getFile();
924 final PsiReferenceExpression ref
=
925 PsiTreeUtil
.findElementOfClassAtOffset(file
, context
.getStartOffset(), PsiReferenceExpression
.class, false);
927 final PsiElement qualifier
= ref
.getQualifier();
928 if (qualifier
!= null) {
929 final CodeStyleSettings settings
= CodeStyleSettingsManager
.getSettings(project
);
931 final String parenSpace
= settings
.SPACE_WITHIN_PARENTHESES ?
" " : "";
932 document
.insertString(qualifier
.getTextRange().getEndOffset(), parenSpace
+ ")");
934 final String spaceWithin
= settings
.SPACE_WITHIN_CAST_PARENTHESES ?
" " : "";
935 final String prefix
= "(" + parenSpace
+ "(" + spaceWithin
;
936 final String spaceAfter
= settings
.SPACE_AFTER_TYPE_CAST ?
" " : "";
937 final int exprStart
= qualifier
.getTextRange().getStartOffset();
938 document
.insertString(exprStart
, prefix
+ spaceWithin
+ ")" + spaceAfter
);
940 CompletionUtil
.emulateInsertion(context
, exprStart
+ prefix
.length(), to
, (char)0);
944 item
.getDelegate().handleInsert(context
);
949 private static LookupElement
highlightIfNeeded(@NotNull PsiType qualifierType
, @NotNull LookupElement item
) {
950 Object o
= item
.getObject();
951 if (qualifierType
instanceof PsiArrayType
) {
952 if (o
instanceof PsiField
|| o
instanceof PsiMethod
) { //length and clone()
953 PsiElement parent
= ((PsiElement
)o
).getParent();
954 if (parent
instanceof PsiClass
&& parent
.getContainingFile().getVirtualFile() == null) { //yes, they're a bit dummy
955 return highlight(item
);
959 else if (qualifierType
instanceof PsiClassType
) {
960 PsiClass qualifierClass
= ((PsiClassType
)qualifierType
).resolve();
961 if (o
instanceof PsiField
|| o
instanceof PsiMethod
|| o
instanceof PsiClass
) {
962 PsiElement parent
= ((PsiElement
)o
).getParent();
963 if (parent
!= null && parent
.equals(qualifierClass
)) {
964 return highlight(item
);
971 private static LookupElementDecorator
<LookupElement
> highlight(LookupElement decorator
) {
972 return LookupElementDecorator
.withRenderer(decorator
, new LookupElementRenderer
<LookupElementDecorator
<LookupElement
>>() {
974 public void renderElement(LookupElementDecorator
<LookupElement
> element
, LookupElementPresentation presentation
) {
975 element
.getDelegate().renderElement(presentation
);
976 presentation
.setItemTextBold(true);
981 private static LookupItem
<?
> createLookupElement(CompletionElement completionElement
, PsiType qualifierType
) {
982 Object completion
= completionElement
.getElement();
983 assert !(completion
instanceof LookupElement
);
986 LookupElement _ret
= LookupItemUtil
.objectToLookupItem(completion
);
987 if (_ret
== null || !(_ret
instanceof LookupItem
)) return null;
989 LookupItem
<?
> ret
= (LookupItem
<?
>)_ret
;
990 final PsiSubstitutor substitutor
= completionElement
.getSubstitutor();
991 if (substitutor
!= null) {
992 ret
.setAttribute(LookupItem
.SUBSTITUTOR
, substitutor
);
994 ret
.putUserData(QUALIFIER_TYPE_ATTR
, qualifierType
);
999 public static boolean hasAccessibleConstructor(PsiType type
) {
1000 if (type
instanceof PsiArrayType
) return true;
1002 final PsiClass psiClass
= PsiUtil
.resolveClassInType(type
);
1003 if (psiClass
== null) return false;
1005 if (!(psiClass
instanceof PsiCompiledElement
)) return true;
1007 final PsiMethod
[] methods
= psiClass
.getConstructors();
1008 if (methods
.length
== 0) return true;
1010 for (final PsiMethod method
: methods
) {
1011 if (!method
.hasModifierProperty(PsiModifier
.PRIVATE
)) return true;
1016 public static LookupItem
qualify(final LookupItem ret
) {
1017 final PsiMember completionElement
= (PsiMember
)ret
.getObject();
1018 final PsiClass containingClass
= completionElement
.getContainingClass();
1019 if (containingClass
!= null) {
1020 final String className
= containingClass
.getName();
1021 ret
.setLookupString(className
+ "." + ret
.getLookupString());
1023 return ret
.forceQualify();
1026 public static LookupItem
setShowFQN(final LookupItem ret
) {
1027 final PsiClass psiClass
= (PsiClass
)ret
.getObject();
1028 @NonNls String packageName
= PsiFormatUtil
.getPackageDisplayName(psiClass
);
1030 final String tailText
= (String
)ret
.getAttribute(LookupItem
.TAIL_TEXT_ATTR
);
1031 ret
.setAttribute(LookupItem
.TAIL_TEXT_ATTR
, StringUtil
.notNullize(tailText
) + " (" + packageName
+ ")");
1032 ret
.setAttribute(LookupItem
.TAIL_TEXT_SMALL_ATTR
, "");
1037 static PsiElement
getQualifier(final PsiElement element
) {
1038 return element
instanceof PsiJavaCodeReferenceElement ?
((PsiJavaCodeReferenceElement
)element
).getQualifier() : null;
1041 public static boolean containsMethodCalls(@Nullable final PsiElement qualifier
) {
1042 if (qualifier
== null) return false;
1043 if (qualifier
instanceof PsiMethodCallExpression
) return true;
1044 return containsMethodCalls(getQualifier(qualifier
));
1048 static ElementFilter
recursionFilter(PsiElement element
) {
1049 if (com
.intellij
.patterns
.PsiJavaPatterns
.psiElement().afterLeaf(PsiKeyword
.RETURN
).inside(PsiReturnStatement
.class).accepts(element
)) {
1050 return new ExcludeDeclaredFilter(ElementClassFilter
.METHOD
);
1053 if (com
.intellij
.patterns
.PsiJavaPatterns
.psiElement().inside(
1055 PsiJavaPatterns
.psiElement(PsiAssignmentExpression
.class),
1056 PsiJavaPatterns
.psiElement(PsiVariable
.class))).
1057 andNot(com
.intellij
.patterns
.PsiJavaPatterns
.psiElement().afterLeaf(".")).accepts(element
)) {
1058 return new AndFilter(new ExcludeSillyAssignment(),
1059 new ExcludeDeclaredFilter(new ClassFilter(PsiVariable
.class)));