a72a85827bab119838883618c395366a293fcac9
[idea/community.git] / java / java-analysis-impl / src / com / intellij / codeInspection / reference / RefMethodImpl.java
1 /*
2  * Copyright 2000-2015 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.intellij.codeInspection.reference;
17
18 import com.intellij.codeInsight.ExceptionUtil;
19 import com.intellij.openapi.application.ApplicationManager;
20 import com.intellij.openapi.util.Comparing;
21 import com.intellij.psi.*;
22 import com.intellij.psi.search.GlobalSearchScope;
23 import com.intellij.psi.util.*;
24 import com.intellij.util.IncorrectOperationException;
25 import com.intellij.util.SmartList;
26 import org.jetbrains.annotations.NonNls;
27 import org.jetbrains.annotations.NotNull;
28 import org.jetbrains.annotations.Nullable;
29
30 import java.util.*;
31
32 /**
33  * @author max
34  * Date: Oct 21, 2001
35  */
36 public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
37   private static final List<RefMethod> EMPTY_METHOD_LIST = Collections.emptyList();
38   private static final RefParameter[] EMPTY_PARAMS_ARRAY = new RefParameter[0];
39
40   private static final int IS_APPMAIN_MASK = 0x10000;
41   private static final int IS_LIBRARY_OVERRIDE_MASK = 0x20000;
42   private static final int IS_CONSTRUCTOR_MASK = 0x40000;
43   private static final int IS_ABSTRACT_MASK = 0x80000;
44   private static final int IS_BODY_EMPTY_MASK = 0x100000;
45   private static final int IS_ONLY_CALLS_SUPER_MASK = 0x200000;
46   private static final int IS_RETURN_VALUE_USED_MASK = 0x400000;
47
48   private static final int IS_TEST_METHOD_MASK = 0x4000000;
49   private static final int IS_CALLED_ON_SUBCLASS_MASK = 0x8000000;
50
51   private static final String RETURN_VALUE_UNDEFINED = "#";
52
53   private List<RefMethod> mySuperMethods;
54   private List<RefMethod> myDerivedMethods;
55   private List<String> myUnThrownExceptions;
56
57   private RefParameter[] myParameters;
58   private String myReturnValueTemplate;
59   protected final RefClass myOwnerClass;
60
61   RefMethodImpl(@NotNull RefClass ownerClass, PsiMethod method, RefManager manager) {
62     super(method, manager);
63
64     ((RefClassImpl)ownerClass).add(this);
65
66     myOwnerClass = ownerClass;
67   }
68
69   // To be used only from RefImplicitConstructor.
70   protected RefMethodImpl(@NotNull String name, @NotNull RefClass ownerClass) {
71     super(name, ownerClass);
72     myOwnerClass = ownerClass;
73     ((RefClassImpl)ownerClass).add(this);
74
75     addOutReference(getOwnerClass());
76     ((RefClassImpl)getOwnerClass()).addInReference(this);
77
78     setConstructor(true);
79   }
80
81   @Override
82   public void add(@NotNull RefEntity child) {
83     if (child instanceof RefParameter) {
84       return;
85     }
86     super.add(child);
87   }
88
89   @Override
90   public List<RefEntity> getChildren() {
91     List<RefEntity> superChildren = super.getChildren();
92     if (myParameters == null) return superChildren;
93     if (superChildren == null || superChildren.isEmpty()) return Arrays.<RefEntity>asList(myParameters);
94     
95     List<RefEntity> allChildren = new ArrayList<RefEntity>(superChildren.size() + myParameters.length);
96     allChildren.addAll(superChildren);
97     Collections.addAll(allChildren, myParameters);
98     return allChildren;
99   }
100
101   @Override
102   protected void initialize() {
103     final PsiMethod method = (PsiMethod)getElement();
104     LOG.assertTrue(method != null);
105     setConstructor(method.isConstructor());
106     final PsiType returnType = method.getReturnType();
107     setFlag(returnType == null || 
108             PsiType.VOID.equals(returnType) || 
109             returnType.equalsToText(CommonClassNames.JAVA_LANG_VOID), IS_RETURN_VALUE_USED_MASK);
110
111     if (!isReturnValueUsed()) {
112       myReturnValueTemplate = RETURN_VALUE_UNDEFINED;
113     }
114
115     if (isConstructor()) {
116       addReference(getOwnerClass(), getOwnerClass().getElement(), method, false, true, null);
117     }
118
119     if (getOwnerClass().isInterface()) {
120       setAbstract(false);
121     } else {
122       setAbstract(method.hasModifierProperty(PsiModifier.ABSTRACT));
123     }
124
125
126     setAppMain(isAppMain(method, this));
127     setLibraryOverride(method.hasModifierProperty(PsiModifier.NATIVE));
128
129     initializeSuperMethods(method);
130     if (isExternalOverride()) {
131       ((RefClassImpl)getOwnerClass()).addLibraryOverrideMethod(this);
132     }
133
134     @NonNls final String name = method.getName();
135     if (getOwnerClass().isTestCase() && name.startsWith("test")) {
136       setTestMethod(true);
137     }
138
139     PsiParameter[] paramList = method.getParameterList().getParameters();
140     if (paramList.length > 0){
141       myParameters = new RefParameterImpl[paramList.length];
142       for (int i = 0; i < paramList.length; i++) {
143         PsiParameter parameter = paramList[i];
144         myParameters[i] = getRefJavaManager().getParameterReference(parameter, i);
145       }
146     }
147
148     if (method.hasModifierProperty(PsiModifier.NATIVE)) {
149       updateReturnValueTemplate(null);
150       updateThrowsList(null);
151     }
152     collectUncaughtExceptions(method);
153   }
154
155   private static boolean isAppMain(PsiMethod psiMethod, RefMethod refMethod) {
156     if (!refMethod.isStatic()) return false;
157     if (!PsiType.VOID.equals(psiMethod.getReturnType())) return false;
158
159     PsiMethod appMainPattern = ((RefMethodImpl)refMethod).getRefJavaManager().getAppMainPattern();
160     if (MethodSignatureUtil.areSignaturesEqual(psiMethod, appMainPattern)) return true;
161
162     PsiMethod appPremainPattern = ((RefMethodImpl)refMethod).getRefJavaManager().getAppPremainPattern();
163     if (MethodSignatureUtil.areSignaturesEqual(psiMethod, appPremainPattern)) return true;
164
165     PsiMethod appAgentmainPattern = ((RefMethodImpl)refMethod).getRefJavaManager().getAppAgentmainPattern();
166     return MethodSignatureUtil.areSignaturesEqual(psiMethod, appAgentmainPattern);
167   }
168
169   private void checkForSuperCall(PsiMethod method) {
170     if (isConstructor()) {
171       PsiCodeBlock body = method.getBody();
172       if (body == null) return;
173       PsiStatement[] statements = body.getStatements();
174       boolean isBaseExplicitlyCalled = false;
175       if (statements.length > 0) {
176         PsiStatement first = statements[0];
177         if (first instanceof PsiExpressionStatement) {
178           PsiExpression firstExpression = ((PsiExpressionStatement) first).getExpression();
179           if (firstExpression instanceof PsiMethodCallExpression) {
180             PsiExpression qualifierExpression = ((PsiMethodCallExpression)firstExpression).getMethodExpression().getQualifierExpression();
181             if (qualifierExpression instanceof PsiReferenceExpression) {
182               @NonNls String text = qualifierExpression.getText();
183               if ("super".equals(text) || text.equals("this")) {
184                 isBaseExplicitlyCalled = true;
185               }
186             }
187           }
188         }
189       }
190
191       if (!isBaseExplicitlyCalled) {
192         for (RefClass superClass : getOwnerClass().getBaseClasses()) {
193           RefMethodImpl superDefaultConstructor = (RefMethodImpl)superClass.getDefaultConstructor();
194
195           if (superDefaultConstructor != null) {
196             superDefaultConstructor.addInReference(this);
197             addOutReference(superDefaultConstructor);
198           }
199         }
200       }
201     }
202   }
203
204   @Override
205   @NotNull
206   public Collection<RefMethod> getSuperMethods() {
207     if (mySuperMethods == null) return EMPTY_METHOD_LIST;
208     if (mySuperMethods.size() > 10) {
209       LOG.info("method: " + getName() + " owner:" + getOwnerClass().getQualifiedName());
210     }
211     if (getRefManager().isOfflineView()) {
212       LOG.debug("Should not traverse graph offline");
213     }
214     return mySuperMethods;
215   }
216
217   @Override
218   @NotNull
219   public Collection<RefMethod> getDerivedMethods() {
220     if (myDerivedMethods == null) return EMPTY_METHOD_LIST;
221     return myDerivedMethods;
222   }
223
224   @Override
225   public boolean isBodyEmpty() {
226     return checkFlag(IS_BODY_EMPTY_MASK);
227   }
228
229   @Override
230   public boolean isOnlyCallsSuper() {
231     return checkFlag(IS_ONLY_CALLS_SUPER_MASK);
232   }
233
234   @Override
235   public boolean hasBody() {
236     return !isAbstract() && !getOwnerClass().isInterface() || !isBodyEmpty();
237   }
238
239   private void initializeSuperMethods(PsiMethod method) {
240     if (getRefManager().isOfflineView()) return;
241     for (PsiMethod psiSuperMethod : method.findSuperMethods()) {
242       if (getRefManager().belongsToScope(psiSuperMethod)) {
243         RefMethodImpl refSuperMethod = (RefMethodImpl)getRefManager().getReference(psiSuperMethod);
244         if (refSuperMethod != null) {
245           addSuperMethod(refSuperMethod);
246           refSuperMethod.markExtended(this);
247         }
248       }
249       else {
250         setLibraryOverride(true);
251       }
252     }
253   }
254
255   public void addSuperMethod(RefMethodImpl refSuperMethod) {
256     if (!getSuperMethods().contains(refSuperMethod) && !refSuperMethod.getSuperMethods().contains(this)) {
257       if (mySuperMethods == null){
258         mySuperMethods = new ArrayList<RefMethod>(1);
259       }
260       mySuperMethods.add(refSuperMethod);
261     }
262   }
263
264   public void markExtended(RefMethodImpl method) {
265     if (!getDerivedMethods().contains(method) && !method.getDerivedMethods().contains(this)) {
266       if (myDerivedMethods == null) {
267         myDerivedMethods = new ArrayList<RefMethod>(1);
268       }
269       myDerivedMethods.add(method);
270     }
271   }
272
273   @Override
274   @NotNull
275   public RefParameter[] getParameters() {
276     if (myParameters == null) return EMPTY_PARAMS_ARRAY;
277     return myParameters;
278   }
279
280   @Override
281   public void buildReferences() {
282     // Work on code block to find what we're referencing...
283     PsiMethod method = (PsiMethod) getElement();
284     if (method == null) return;
285     PsiCodeBlock body = method.getBody();
286     final RefJavaUtil refUtil = RefJavaUtil.getInstance();
287     refUtil.addReferences(method, this, body);
288     refUtil.addReferences(method, this, method.getModifierList());
289     checkForSuperCall(method);
290     setOnlyCallsSuper(refUtil.isMethodOnlyCallsSuper(method));
291
292     setBodyEmpty(isOnlyCallsSuper() || !isExternalOverride() && (body == null || body.getStatements().length == 0));
293
294     refUtil.addTypeReference(method, method.getReturnType(), getRefManager(), this);
295
296     for (RefParameter parameter : getParameters()) {
297       refUtil.setIsFinal(parameter, parameter.getElement().hasModifierProperty(PsiModifier.FINAL));
298     }
299
300     getRefManager().fireBuildReferences(this);
301   }
302
303   private void collectUncaughtExceptions(@NotNull PsiMethod method) {
304     if (isExternalOverride()) return;
305     if (getRefManager().isOfflineView()) return;
306     @NonNls final String name = method.getName();
307     if (getOwnerClass().isTestCase() && name.startsWith("test")) return;
308
309     if (getSuperMethods().isEmpty()) {
310       PsiClassType[] throwsList = method.getThrowsList().getReferencedTypes();
311       if (throwsList.length > 0) {
312         myUnThrownExceptions = throwsList.length == 1 ? new SmartList<String>() : new ArrayList<String>(throwsList.length);
313         for (final PsiClassType type : throwsList) {
314           PsiClass aClass = type.resolve();
315           String fqn = aClass == null ? null : aClass.getQualifiedName();
316           if (fqn != null) {
317             myUnThrownExceptions.add(fqn);
318           }
319         }
320       }
321     }
322
323     final PsiCodeBlock body = method.getBody();
324     if (body == null) return;
325
326     final Collection<PsiClassType> exceptionTypes = ExceptionUtil.collectUnhandledExceptions(body, method, false);
327     for (final PsiClassType exceptionType : exceptionTypes) {
328       updateThrowsList(exceptionType);
329     }
330   }
331
332   public void removeUnThrownExceptions(PsiClass unThrownException) {
333     if (myUnThrownExceptions != null) {
334       myUnThrownExceptions.remove(unThrownException.getQualifiedName());
335     }
336   }
337
338   @Override
339   public void accept(@NotNull final RefVisitor visitor) {
340     if (visitor instanceof RefJavaVisitor) {
341       ApplicationManager.getApplication().runReadAction(() -> ((RefJavaVisitor)visitor).visitMethod(RefMethodImpl.this));
342     } else {
343       super.accept(visitor);
344     }
345   }
346
347   @Override
348   public boolean isExternalOverride() {
349     return isLibraryOverride(new HashSet<RefMethod>());
350   }
351
352   private boolean isLibraryOverride(@NotNull Collection<RefMethod> processed) {
353     if (!processed.add(this)) return false;
354
355     if (checkFlag(IS_LIBRARY_OVERRIDE_MASK)) return true;
356     for (RefMethod superMethod : getSuperMethods()) {
357       if (((RefMethodImpl)superMethod).isLibraryOverride(processed)) {
358         setFlag(true, IS_LIBRARY_OVERRIDE_MASK);
359         return true;
360       }
361     }
362
363     return false;
364   }
365
366   @Override
367   public boolean isAppMain() {
368     return checkFlag(IS_APPMAIN_MASK);
369   }
370
371   @Override
372   public boolean isAbstract() {
373     return checkFlag(IS_ABSTRACT_MASK);
374   }
375
376   @Override
377   public boolean hasSuperMethods() {
378     return !getSuperMethods().isEmpty() || isExternalOverride();
379   }
380
381   @Override
382   public boolean isReferenced() {
383     // Directly called from somewhere..
384     for (RefElement refCaller : getInReferences()) {
385       if (!getDerivedMethods().contains(refCaller)) return true;
386     }
387
388     // Library override probably called from library code.
389     return isExternalOverride();
390   }
391
392   @Override
393   public boolean hasSuspiciousCallers() {
394     // Directly called from somewhere..
395     for (RefElement refCaller : getInReferences()) {
396       if (((RefElementImpl)refCaller).isSuspicious() && !getDerivedMethods().contains(refCaller)) return true;
397     }
398
399     // Library override probably called from library code.
400     if (isExternalOverride()) return true;
401
402     // Class isn't instantiated. Most probably we have problem with class, not method.
403     if (!isStatic() && !isConstructor()) {
404       if (((RefClassImpl)getOwnerClass()).isSuspicious()) return true;
405
406       // Is an override. Probably called via reference to base class.
407       for (RefMethod refSuper : getSuperMethods()) {
408         if (((RefMethodImpl)refSuper).isSuspicious()) return true;
409       }
410     }
411
412     return false;
413   }
414
415   @Override
416   public boolean isConstructor() {
417     return checkFlag(IS_CONSTRUCTOR_MASK);
418   }
419
420   @Override
421   public RefClass getOwnerClass() {
422     return (RefClass) getOwner();
423   }
424
425   @NotNull
426   @Override
427   public String getName() {
428     if (isValid()) {
429       final String[] result = new String[1];
430       final Runnable runnable = () -> {
431         PsiMethod psiMethod = (PsiMethod) getElement();
432         if (psiMethod instanceof SyntheticElement) {
433           result[0] = psiMethod.getName();
434         }
435         else {
436           result[0] = PsiFormatUtil.formatMethod(psiMethod,
437                                                  PsiSubstitutor.EMPTY,
438                                                  PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS,
439                                                  PsiFormatUtilBase.SHOW_TYPE
440           );
441         }
442       };
443
444       ApplicationManager.getApplication().runReadAction(runnable);
445
446       return result[0];
447     } else {
448       return super.getName();
449     }
450   }
451
452   @Override
453   public String getExternalName() {
454     final String[] result = new String[1];
455     final Runnable runnable = () -> {
456       final PsiMethod psiMethod = (PsiMethod)getElement();
457       LOG.assertTrue(psiMethod != null);
458       result[0] = PsiFormatUtil.getExternalName(psiMethod, true, Integer.MAX_VALUE);
459     };
460
461     ApplicationManager.getApplication().runReadAction(runnable);
462
463     return result[0];
464   }
465
466   @Nullable
467   public static RefMethod methodFromExternalName(RefManager manager, String externalName) {
468     return (RefMethod) manager.getReference(findPsiMethod(PsiManager.getInstance(manager.getProject()), externalName));
469   }
470
471   @Nullable
472   public static PsiMethod findPsiMethod(PsiManager manager, String externalName) {
473     final int spaceIdx = externalName.indexOf(' ');
474     final String className = externalName.substring(0, spaceIdx);
475     final PsiClass psiClass = ClassUtil.findPsiClass(manager, className);
476     if (psiClass == null) return null;
477     try {
478       PsiElementFactory factory = JavaPsiFacade.getInstance(psiClass.getProject()).getElementFactory();
479       String methodSignature = externalName.substring(spaceIdx + 1);
480       PsiMethod patternMethod = factory.createMethodFromText(methodSignature, psiClass);
481       return psiClass.findMethodBySignature(patternMethod, false);
482     } catch (IncorrectOperationException e) {
483       // Do nothing. Returning null is acceptable in this case.
484       return null;
485     }
486   }
487
488   @Override
489   public void referenceRemoved() {
490     if (getOwnerClass() != null) {
491       ((RefClassImpl)getOwnerClass()).methodRemoved(this);
492     }
493
494     super.referenceRemoved();
495
496     for (RefMethod superMethod : getSuperMethods()) {
497       superMethod.getDerivedMethods().remove(this);
498     }
499
500     for (RefMethod subMethod : getDerivedMethods()) {
501       subMethod.getSuperMethods().remove(this);
502     }
503
504     ArrayList<RefElement> deletedRefs = new ArrayList<RefElement>();
505     for (RefParameter parameter : getParameters()) {
506       getRefManager().removeRefElement(parameter, deletedRefs);
507     }
508   }
509
510   @Override
511   public boolean isSuspicious() {
512     if (isConstructor() && PsiModifier.PRIVATE.equals(getAccessModifier()) && getParameters().length == 0 && getOwnerClass().getConstructors().size() == 1) return false;
513     return super.isSuspicious();
514   }
515
516   public void setReturnValueUsed(boolean value) {
517     if (checkFlag(IS_RETURN_VALUE_USED_MASK) == value) return;
518     setFlag(value, IS_RETURN_VALUE_USED_MASK);
519     for (RefMethod refSuper : getSuperMethods()) {
520       ((RefMethodImpl)refSuper).setReturnValueUsed(value);
521     }
522   }
523
524   @Override
525   public boolean isReturnValueUsed() {
526     return checkFlag(IS_RETURN_VALUE_USED_MASK);
527   }
528
529   public void updateReturnValueTemplate(PsiExpression expression) {
530     if (myReturnValueTemplate == null) return;
531
532     if (!getSuperMethods().isEmpty()) {
533       for (final RefMethod refMethod : getSuperMethods()) {
534         RefMethodImpl refSuper = (RefMethodImpl)refMethod;
535         refSuper.updateReturnValueTemplate(expression);
536       }
537     }else {
538       String newTemplate = null;
539       final RefJavaUtil refUtil = RefJavaUtil.getInstance();
540       if (expression instanceof PsiLiteralExpression) {
541         PsiLiteralExpression psiLiteralExpression = (PsiLiteralExpression) expression;
542         newTemplate = psiLiteralExpression.getText();
543       } else if (expression instanceof PsiReferenceExpression) {
544         PsiReferenceExpression referenceExpression = (PsiReferenceExpression) expression;
545         PsiElement resolved = referenceExpression.resolve();
546         if (resolved instanceof PsiField) {
547           PsiField psiField = (PsiField) resolved;
548           if (psiField.hasModifierProperty(PsiModifier.STATIC) &&
549               psiField.hasModifierProperty(PsiModifier.FINAL) &&
550               refUtil.compareAccess(refUtil.getAccessModifier(psiField), getAccessModifier()) >= 0) {
551             newTemplate = PsiFormatUtil.formatVariable(psiField, PsiFormatUtilBase.SHOW_NAME |
552                                                                  PsiFormatUtilBase.SHOW_CONTAINING_CLASS |
553                                                                  PsiFormatUtilBase.SHOW_FQ_NAME, PsiSubstitutor.EMPTY);
554           }
555         }
556       } else if (refUtil.isCallToSuperMethod(expression, (PsiMethod) getElement())) return;
557
558       //noinspection StringEquality
559       if (myReturnValueTemplate == RETURN_VALUE_UNDEFINED) {
560         myReturnValueTemplate = newTemplate;
561       } else if (!Comparing.equal(myReturnValueTemplate, newTemplate)) {
562         myReturnValueTemplate = null;
563       }
564     }
565   }
566
567   public void updateParameterValues(PsiExpression[] args) {
568     if (isExternalOverride()) return;
569
570     if (!getSuperMethods().isEmpty()) {
571       for (RefMethod refSuper : getSuperMethods()) {
572         ((RefMethodImpl)refSuper).updateParameterValues(args);
573       }
574     } else {
575       final RefParameter[] params = getParameters();
576       if (params.length <= args.length && params.length > 0) {
577         for (int i = 0; i < args.length; i++) {
578           RefParameter refParameter;
579           if (params.length <= i){
580             refParameter = params[params.length - 1];
581           } else {
582             refParameter = params[i];
583           }
584           ((RefParameterImpl)refParameter).updateTemplateValue(args[i]);
585         }
586       }
587     }
588   }
589
590   @Override
591   public String getReturnValueIfSame() {
592     //noinspection StringEquality
593     if (myReturnValueTemplate == RETURN_VALUE_UNDEFINED) return null;
594     return myReturnValueTemplate;
595   }
596
597   public void updateThrowsList(PsiClassType exceptionType) {
598     if (!getSuperMethods().isEmpty()) {
599       for (RefMethod refSuper : getSuperMethods()) {
600         ((RefMethodImpl)refSuper).updateThrowsList(exceptionType);
601       }
602     }
603     else if (myUnThrownExceptions != null) {
604       if (exceptionType == null) {
605         myUnThrownExceptions = null;
606         return;
607       }
608       PsiClass exceptionClass = exceptionType.resolve();
609       JavaPsiFacade facade = JavaPsiFacade.getInstance(myManager.getProject());
610       for (int i = myUnThrownExceptions.size() - 1; i >= 0; i--) {
611         String exceptionFqn = myUnThrownExceptions.get(i);
612         PsiClass classType = facade.findClass(exceptionFqn, GlobalSearchScope.allScope(getRefManager().getProject()));
613         if (InheritanceUtil.isInheritorOrSelf(exceptionClass, classType, true) ||
614             InheritanceUtil.isInheritorOrSelf(classType, exceptionClass, true)) {
615           myUnThrownExceptions.remove(i);
616         }
617       }
618
619       if (myUnThrownExceptions.isEmpty()) myUnThrownExceptions = null;
620     }
621   }
622
623   @Override
624   @Nullable
625   public PsiClass[] getUnThrownExceptions() {
626     if (getRefManager().isOfflineView()) {
627       LOG.debug("Should not traverse graph offline");
628     }
629     if (myUnThrownExceptions == null) return null;
630     JavaPsiFacade facade = JavaPsiFacade.getInstance(myManager.getProject());
631     List<PsiClass> result = new ArrayList<PsiClass>(myUnThrownExceptions.size());
632     for (String exception : myUnThrownExceptions) {
633       PsiClass element = facade.findClass(exception, GlobalSearchScope.allScope(myManager.getProject()));
634       if (element != null) result.add(element);
635     }
636     return result.toArray(new PsiClass[result.size()]);
637   }
638
639
640   public void setLibraryOverride(boolean libraryOverride) {
641     setFlag(libraryOverride, IS_LIBRARY_OVERRIDE_MASK);
642   }
643
644   private void setAppMain(boolean appMain) {
645     setFlag(appMain, IS_APPMAIN_MASK);
646   }
647
648   private void setAbstract(boolean anAbstract) {
649     setFlag(anAbstract, IS_ABSTRACT_MASK);
650   }
651
652   public void setBodyEmpty(boolean bodyEmpty) {
653     setFlag(bodyEmpty, IS_BODY_EMPTY_MASK);
654   }
655
656   private void setOnlyCallsSuper(boolean onlyCallsSuper) {
657     setFlag(onlyCallsSuper, IS_ONLY_CALLS_SUPER_MASK);
658   }
659
660
661
662   private void setConstructor(boolean constructor) {
663     setFlag(constructor, IS_CONSTRUCTOR_MASK);
664   }
665
666   @Override
667   public boolean isTestMethod() {
668     return checkFlag(IS_TEST_METHOD_MASK);
669   }
670
671   private void setTestMethod(boolean testMethod){
672     setFlag(testMethod, IS_TEST_METHOD_MASK);
673   }
674
675   @Override
676   public PsiModifierListOwner getElement() {
677     return (PsiModifierListOwner)super.getElement();
678   }
679
680   @Override
681   public boolean isCalledOnSubClass() {
682     return checkFlag(IS_CALLED_ON_SUBCLASS_MASK);
683   }
684
685   public void setCalledOnSubClass(boolean isCalledOnSubClass){
686     setFlag(isCalledOnSubClass, IS_CALLED_ON_SUBCLASS_MASK);
687   }
688
689 }