NPE in Fabrique fixed (FBQ-10315)
[fedora-idea.git] / source / com / intellij / codeInsight / completion / scope / CompletionProcessor.java
blobb61d7c71b8531ad1a0a535bc7b4199912a7598ff
1 package com.intellij.codeInsight.completion.scope;
3 import com.intellij.codeInsight.CodeInsightSettings;
4 import com.intellij.codeInsight.completion.CompletionUtil;
5 import com.intellij.psi.*;
6 import com.intellij.psi.filters.ElementFilter;
7 import com.intellij.psi.impl.source.resolve.ResolveUtil;
8 import com.intellij.psi.infos.CandidateInfo;
9 import com.intellij.psi.javadoc.PsiDocComment;
10 import com.intellij.psi.scope.BaseScopeProcessor;
11 import com.intellij.psi.scope.ElementClassHint;
12 import com.intellij.psi.util.PsiUtil;
14 import java.util.*;
16 /**
17 * Created by IntelliJ IDEA.
18 * User: ik
19 * Date: 20.01.2003
20 * Time: 16:13:27
21 * To change this template use Options | File Templates.
23 public class CompletionProcessor extends BaseScopeProcessor
24 implements ElementClassHint{
25 private final String myPrefix;
26 private boolean myStatic = false;
27 private final Set<Object> myResultNames = new HashSet<Object>();
28 private final List<CompletionElement> myResults;
29 private final PsiElement myElement;
30 private PsiElement myScope;
31 private CodeInsightSettings mySettings = null;
32 private final ElementFilter myFilter;
33 private boolean myMembersFlag = false;
34 private PsiType myQualifierType = null;
35 private PsiClass myQualifierClass = null;
37 private CompletionProcessor(String prefix, PsiElement element, List<CompletionElement> container, ElementFilter filter){
38 mySettings = CodeInsightSettings.getInstance();
39 myPrefix = prefix;
40 myResults = container;
41 myElement = element;
42 myFilter = filter;
43 myScope = element;
44 if (ResolveUtil.findParentContextOfClass(myElement, PsiDocComment.class, false) != null)
45 myMembersFlag = true;
46 while(myScope != null && !(myScope instanceof PsiFile || myScope instanceof PsiClass)){
47 myScope = myScope.getContext();
50 PsiElement elementParent = element.getContext();
51 if (elementParent instanceof PsiReferenceExpression) {
52 PsiExpression qualifier = ((PsiReferenceExpression)elementParent).getQualifierExpression();
53 if (qualifier instanceof PsiSuperExpression) {
54 myQualifierClass = ResolveUtil.getContextClass(myElement);
55 if (myQualifierClass != null) {
56 myQualifierType = myElement.getManager().getElementFactory().createType(myQualifierClass);
59 else if (qualifier != null) {
60 myQualifierType = qualifier.getType();
61 myQualifierClass = PsiUtil.resolveClassInType(myQualifierType);
66 public CompletionProcessor(String prefix, PsiElement element, ElementFilter filter){
67 this(prefix, element, new ArrayList<CompletionElement>(), filter);
71 public void handleEvent(Event event, Object associated){
72 if(event == Event.START_STATIC){
73 myStatic = true;
75 if(event == Event.CHANGE_LEVEL){
76 myMembersFlag = true;
80 public boolean execute(PsiElement element, PsiSubstitutor substitutor){
81 if(!(element instanceof PsiClass) && element instanceof PsiModifierListOwner){
82 PsiModifierListOwner modifierListOwner = (PsiModifierListOwner)element;
83 if(myStatic){
84 if(!modifierListOwner.hasModifierProperty(PsiModifier.STATIC)){
85 // we don't need non static method in static context.
86 return true;
89 else{
90 if(!mySettings.SHOW_STATIC_AFTER_INSTANCE
91 && modifierListOwner.hasModifierProperty(PsiModifier.STATIC)
92 && !myMembersFlag){
93 // according settings we don't need to process such fields/methods
94 return true;
98 final PsiElement elementParent = myElement.getParent();
99 if(element instanceof PsiPackage){
100 if(!mySettings.LIST_PACKAGES_IN_CODE && myScope instanceof PsiClass){
101 if(!(elementParent instanceof PsiJavaCodeReferenceElement
102 && ((PsiJavaCodeReferenceElement)elementParent).isQualified())) {
103 return true;
108 PsiResolveHelper resolveHelper = myElement.getManager().getResolveHelper();
109 if(!(element instanceof PsiMember) || resolveHelper.isAccessible(((PsiMember)element), myElement, myQualifierClass)){
110 final String name = PsiUtil.getName(element);
111 if(CompletionUtil.checkName(name, myPrefix) && myFilter.isClassAcceptable(element.getClass())
112 && myFilter.isAcceptable(new CandidateInfo(element, substitutor), myElement))
113 add(new CompletionElement(myQualifierType, element, substitutor));
115 return true;
118 private void add(CompletionElement element){
119 if(!myResultNames.contains(element.getUniqueId())){
120 myResultNames.add(element.getUniqueId());
121 myResults.add(element);
125 public Collection getResults(){
126 return myResults;
129 public boolean shouldProcess(Class elementClass){
130 return myFilter.isClassAcceptable(elementClass);