KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > javacore > parser > MDRParser


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.javacore.parser;
21
22 import java.lang.reflect.Modifier JavaDoc;
23 import java.util.*;
24 import javax.jmi.reflect.RefFeatured;
25 import org.netbeans.api.java.classpath.ClassPath;
26 import org.netbeans.api.mdr.MDRepository;
27 import org.netbeans.jmi.javamodel.*;
28 import org.netbeans.lib.java.parser.*;
29 import org.netbeans.modules.javacore.ClassIndex;
30 import org.netbeans.modules.javacore.JMManager;
31 import org.netbeans.modules.javacore.internalapi.JavaMetamodel;
32 import org.netbeans.modules.javacore.internalapi.JavaModelUtil;
33 import org.netbeans.modules.javacore.jmiimpl.javamodel.*;
34 import org.openide.filesystems.FileObject;
35 import org.openide.util.RequestProcessor;
36 import org.openide.ErrorManager;
37
38 /**
39  *
40  * @author Tomas Hurka
41  */

42 public class MDRParser extends ASTProvider {
43     
44     private Map semanticInfo;
45     private ClassPath classPath;
46     private JMManager manager;
47     private JavaPackageClass jpckClass;
48     private JavaClassClassImpl jclsClass;
49     private TypeClass typeClass;
50     private JavaEnumClassImpl enumClass;
51     private AnnotationTypeClassImpl annotClass;
52     private ClassDefinition currentClass;
53     private Feature currentFeature;
54     private String JavaDoc jpck;
55     private Stack typeScopeInfo;
56     private Stack variableScope;
57     private Scope enumSwitchScope;
58     private ClassIndex index;
59     private TreeMap attributionToDo;
60     private List localSuperInfo;
61     private MDRepository rep;
62     private Scope staticImpScope;
63     private int javaFeatures;
64     private boolean running;
65     private boolean resolveClassName;
66     private static final boolean DEBUG=false;
67     private static Map superInfoMap=new HashMap();
68     private static final ModifiersInfo NO_MODIFIERS = new ModifiersInfo(0, null);
69     private static final RequestProcessor PARSE_AFTER_SCAN_RP = new RequestProcessor("Parse-After-Scan Request Processor"); // NOI18N
70

71     // enum modifier
72
public static final int M_ENUM = 0x00004000;
73     // annotation modifier
74
public static final int M_ANNOTATION = 0x00002000;
75     // feature mofid to position bounds map
76
public Map mofidToBounds;
77     // start and end offsets of guarded blocks
78
public int[] guardedBlocksBorders;
79
80     public MDRParser(Resource r,FileObject fobj) {
81         super(r,fobj);
82         init();
83     }
84
85     public MDRParser(Resource r, FileObject fobj, String JavaDoc sourceText, boolean isFromDoc) {
86         super(r,fobj,sourceText, isFromDoc);
87         init();
88     }
89     
90     private void init() {
91         JavaModelPackage srcExtent=(JavaModelPackage)getResource().refImmediatePackage();
92
93         jpckClass=srcExtent.getJavaPackage();
94         jclsClass=(JavaClassClassImpl)srcExtent.getJavaClass();
95         typeClass=srcExtent.getType();
96         enumClass=(JavaEnumClassImpl)srcExtent.getJavaEnum();
97         annotClass=(AnnotationTypeClassImpl)srcExtent.getAnnotationType();
98         index=ClassIndex.getIndex(srcExtent);
99         semanticInfo=new HashMap();
100         typeScopeInfo=new Stack();
101         variableScope=new Stack();
102         attributionToDo = getAttributionToDoMap();
103         localSuperInfo=new ArrayList();
104         manager=(JMManager)JavaMetamodel.getManager();
105         rep=JavaMetamodel.getDefaultRepository();
106     }
107     
108     private static void reparseAfterScan(final FileObject fobj) {
109         PARSE_AFTER_SCAN_RP.post(new Runnable JavaDoc() {
110             public void run() {
111                 JMManager manager=(JMManager)JavaMetamodel.getManager();
112                 if (manager.waitScanFinished()) {
113                     manager.addModified(fobj);
114                     JavaMetamodel.getDefaultRepository().beginTrans(true);
115                     JavaMetamodel.getDefaultRepository().endTrans(false);
116                 }
117             }
118         });
119     }
120     
121     private static TreeMap getAttributionToDoMap() {
122         return new TreeMap(new Comparator() {
123             public int compare(Object JavaDoc o1, Object JavaDoc o2) {
124                 int i1 = ((ASTree) o1).getFirstToken(), i2 = ((ASTree) o2).getFirstToken();
125                 if (i1 < i2)
126                     return -1;
127                 if (i1 > i2)
128                     return 1;
129                 // i1 == i2
130
i1 = ((ASTree) o1).getLastToken();
131                 i2 = ((ASTree) o2).getLastToken();
132                 if (i1 < i2)
133                     return 1;
134                 if (i1 > i2)
135                     return -1;
136                 return 0;
137                 
138             }
139         });
140     }
141
142     public Object JavaDoc getSemanticInfo(ASTree tree, Element element) {
143         boolean wasSafe;
144         Object JavaDoc info = semanticInfo.get(tree);
145         
146         if (info == null) {
147             if (!attributionToDo.isEmpty()) {
148                 for (Iterator it = attributionToDo.keySet().iterator(); it.hasNext();) {
149                     ASTree tmp = (ASTree) it.next();
150                     if (tmp.getFirstToken() > tree.getFirstToken()) {
151                         break;
152                     }
153                     if (tmp.getLastToken() >= tree.getLastToken()) {
154                         doAttribution();
155                         info = semanticInfo.get(tree);
156                         break;
157                     }
158                 }
159             }
160             if (info == null) {
161                 return null;
162             }
163         }
164         wasSafe=JMManager.getTransactionMutex().isSafeTrans();
165         manager.setSafeTrans(true);
166         try {
167             return getModelElement(tree,element,info);
168         } finally {
169             manager.setSafeTrans(wasSafe);
170         }
171     }
172     
173     private void doAttribution() {
174         TreeMap map = attributionToDo;
175         attributionToDo = getAttributionToDoMap();
176         for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
177             Map.Entry entry = (Map.Entry) it.next();
178             Element el = (Element) entry.getValue();
179             
180             if (el.isValid()) {
181                 enterBody(el, (ASTree) entry.getKey());
182             }
183         }
184     }
185     
186     public void prepareForAttribution(MetadataElement feature, ASTree featureTree) {
187         attributionToDo.put(featureTree, feature);
188     }
189
190     private synchronized void enterBody(Element element,ASTree elementTree) {
191         boolean wasSafe;
192         
193         if (running) {
194             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL,new Exception JavaDoc("Recursion in enterBody")); // NOI18N
195
return;
196         }
197         running=true;
198         wasSafe=JMManager.getTransactionMutex().isSafeTrans();
199         manager.setSafeTrans(true);
200         if (JMManager.PERF_DEBUG) try {
201             Feature f=JavaModelUtil.getDeclaringFeature(element);
202             System.err.println("Attributing method: " + f.getDeclaringClass().getName() + '.' + f.getName() + '.' + elementTree.getFirstToken()); // NOI18N
203
} catch (NullPointerException JavaDoc e) {
204             // ignore
205
}
206         long time = System.currentTimeMillis();
207         try {
208             Feature feature=JavaModelUtil.getDeclaringFeature(element);
209             classPath=manager.getClassPath();
210             currentClass=feature.getDeclaringClass();
211             computeScope(currentClass);
212             semanticInfo.put(elementTree, element);
213             currentFeature=feature;
214             processASTBody(elementTree);
215             typeScopeInfo.pop();
216             variableScope.pop();
217         } finally {
218             superInfoMap.keySet().removeAll(localSuperInfo);
219             localSuperInfo.clear();
220             typeScopeInfo.clear();
221             variableScope.clear();
222             currentFeature=null;
223             currentClass=null;
224             manager.setSafeTrans(wasSafe);
225             running=false;
226         }
227         if (JMManager.PERF_DEBUG) System.out.println(" finished: " + (System.currentTimeMillis() - time) + "ms"); // NOI18N
228
}
229     
230     public synchronized ResourceInfo enterMembers() {
231         boolean wasSafe;
232
233         if (running) {
234             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL,new Exception JavaDoc("Recursion in enterMembers")); // NOI18N
235
return null;
236         }
237         running=true;
238         wasSafe=JMManager.getTransactionMutex().isSafeTrans();
239         manager.setSafeTrans(true);
240         try {
241             classPath=manager.getClassPath();
242             ASTree topNode=getASTree();
243  
244             if (topNode!=null) {
245                 if (DEBUG) System.out.println("Parsing :"+fobj.getPath()); // NOI18N
246
if (getPackage("java.lang")==null) { // no JDK found // NOI18N
247
reparseAfterScan(getFileObject());
248                 }
249                 return (ResourceInfo) processAST(topNode);
250             }
251         } finally {
252             superInfoMap.keySet().removeAll(localSuperInfo);
253             localSuperInfo.clear();
254             manager.setSafeTrans(wasSafe);
255             running=false;
256         }
257         return null;
258     }
259     
260     public int getJavaFeatures() {
261         return javaFeatures;
262     }
263     
264     private void computeScope(ClassDefinition jcls) {
265         Scope classScope;
266         Scope varScope;
267         
268         if (jcls==null) {
269             Resource rsc=getResource();
270             
271             classScope=Scope.createTypeScope(rsc,classPath);
272             varScope=new Scope(null);
273             staticImpScope=Scope.createStaticImpScope(rsc);
274         } else if (jcls instanceof JavaClassImpl && ((JavaClassImpl)jcls).isTransient() && ((JavaClassImpl)jcls).getDeclaringClass()==null) { // local class
275
ASTree[] jclsSubASTs=((MetadataElement)jcls).getASTree().getSubTrees(); // Local class AST parts
276
Token firstToken=getToken(jclsSubASTs[jclsSubASTs.length-1].getFirstToken()); // first token '{' of local class
277
Scope localscope[]=(Scope[])semanticInfo.get(firstToken);
278            
279            classScope=new Scope(localscope[0]);
280            varScope=new Scope(localscope[1]);
281            classScope.addMember(Scope.createMemberTypeScope(jcls,this));
282            varScope.addMember(Scope.createFieldScope(jcls));
283         } else if (jcls instanceof JavaClass) {
284             JavaClass javaClass=((JavaClass)jcls);
285             ClassDefinition decl=javaClass.getDeclaringClass();
286             Iterator typeParIt;
287             
288             computeScope(decl);
289             classScope=new Scope((Scope)typeScopeInfo.pop());
290             varScope=new Scope((Scope)variableScope.pop());
291
292             classScope.addMember(Scope.createMemberTypeScope(jcls,this));
293             varScope.addMember(Scope.createFieldScope(jcls));
294             typeParIt=javaClass.getTypeParameters().iterator();
295             while(typeParIt.hasNext()) {
296                 TypeParameter tp=(TypeParameter)typeParIt.next();
297                 
298                 classScope.addMember(new TypeParamScope(tp));
299             }
300         } else {
301            ASTree parentAST=((MetadataElement)jcls).getASTree(); // CLASS_BODY_DECLARATIONS
302
Token firstToken=getToken(parentAST.getFirstToken()); // first token '{' of anonymous class
303
Scope anonscope[]=(Scope[])semanticInfo.get(firstToken);
304            
305            classScope=new Scope(anonscope[0]);
306            varScope=new Scope(anonscope[1]);
307            classScope.addMember(Scope.createMemberTypeScope(jcls,this));
308            varScope.addMember(Scope.createFieldScope(jcls));
309         }
310         typeScopeInfo.push(classScope);
311         variableScope.push(varScope);
312     }
313     
314     private JavaPackage getPackage(String JavaDoc packId) {
315         return jpckClass.resolvePackage(packId);
316     }
317
318     Object JavaDoc processAST(ASTree tree) {
319         return processAST(tree,null);
320     }
321     
322     Object JavaDoc processAST(ASTree tree,String JavaDoc fqn) {
323         ASTree parts[];
324         int i,treeType;
325         
326         if (tree==null)
327             return null;
328         parts=tree.getSubTrees();
329         treeType=tree.getType();
330         switch (treeType) {
331             case COMPILATION_UNIT: {
332                 Object JavaDoc topClasses;
333                 ElementInfo[] importList;
334                 
335                 typeScopeInfo.push(new Scope(null));
336                 processAST(parts[0]);
337                 jpck=getResource().getPackageName();
338                 importList=(ElementInfo[]) processAST(parts[1]); // imports;
339
typeScopeInfo.pop();
340                 typeScopeInfo.push(Scope.createTypeScope(jpck,classPath,importList));
341                 topClasses=processAST(parts[2],jpck); // declarations
342
typeScopeInfo.pop();
343                 return new ResourceInfo(tree, treeType, getResource(), (ClassInfo[]) topClasses, importList);
344             }
345             case PACKAGE_DECLARATION:
346                 return resolveTypeName(parts[1]);
347             case SINGLE_TYPE_IMPORT:
348             case TYPE_IMPORT_ON_DEMAND: {
349                 String JavaDoc id;
350                 
351                 if (treeType==SINGLE_TYPE_IMPORT && parts[0]!=null) { // static single type import
352
id=resolveStaticImport(parts[1]);
353                 } else {
354                     id=((NameRef)resolveTypeName(parts[1])).name;
355                 }
356                 return new ElementInfo(tree, treeType, id);
357             }
358             case IMPORT_DECLARATIONS: {
359                 ElementInfo imports[] = null;
360                 if (parts != null) {
361                     imports = new ElementInfo[parts.length];
362                     for (i = 0; i < imports.length; i++) {
363                         imports[i] = (ElementInfo) processAST(parts[i]);
364                     }
365                 }
366                 return imports;
367             }
368             case TYPE_DECLARATIONS: {
369                 ClassInfo classes[]=null;
370                 
371                 if (parts!=null) {
372                     ASTree filtered[]=filterParts(parts);
373                     
374                     for (i=0;i<filtered.length;i++) {
375                         resolveSuperTypes(filtered[i],fqn);
376                     }
377                     classes=new ClassInfo[filtered.length];
378                     for (i=0;i<classes.length;i++) {
379                         classes[i]=(ClassInfo)processAST(filtered[i],fqn);
380                     }
381                 }
382                 return classes;
383             }
384             case ENUM_CONSTANT: {
385                 return new FeatureInfo(tree, treeType, getText(parts[0]), 0, null);
386             }
387             case ENUM_CONSTANTS: {
388                 ElementInfo constants[] = null;
389                 if (parts != null) {
390                     ASTree filtered[] = filterParts(parts);
391
392                     constants = new ElementInfo[filtered.length];
393                     for (i=0;i<filtered.length;i++) {
394                         constants[i] = (ElementInfo) processAST(filtered[i], fqn);
395                     }
396                 }
397                 return constants;
398             }
399             case ANNOTATION_TYPE_BODY_DECLARATIONS:
400             case ENUM_BODY_DECLARATIONS:
401             case INTERFACE_MEMBER_DECLARATIONS:
402             case CLASS_BODY_DECLARATIONS: {
403                 FeatureInfo features[] = null;
404                 if (parts != null) {
405                     ASTree filtered[]=filterParts(parts);
406                     
407                     for (i=0;i<filtered.length;i++)
408                         resolveSuperTypes(filtered[i],fqn);
409                     ArrayList tempFeatures = new ArrayList(filtered.length);
410                     for (i=0;i<filtered.length;i++) {
411                         Object JavaDoc temp = processAST(filtered[i], fqn);
412                         if (temp instanceof FieldInfo[]) {
413                             tempFeatures.addAll(Arrays.asList((Object JavaDoc[]) temp));
414                         } else {
415                             tempFeatures.add(temp);
416                         }
417                     }
418                     features = (FeatureInfo[]) tempFeatures.toArray(new FeatureInfo[tempFeatures.size()]);
419                 }
420                 return features;
421             }
422             case ENUM_DECLARATION: {
423                 ModifiersInfo modInfo=getModifiers(parts[0]); // modifiers and annotations
424
int modifiers= modInfo != NO_MODIFIERS ? modInfo.modifiers : getDeprecated(tree);
425                 ASTree body=parts[3]; // class body
426
ASTree ifacesAST=parts[2];
427                 EnumInfo enumInfo;
428                 FeatureInfo features[];
429                 ElementInfo constants[];
430                 String JavaDoc currentFqn;
431                 NameRef interfaces[]=null;
432                 Scope classScope=new Scope((Scope)typeScopeInfo.peek());
433
434                 JavaEnum jcls = (JavaEnum) semanticInfo.get(tree);
435
436                 currentFqn=jcls.getName();
437                 classScope.addMember(Scope.createMemberTypeScope(jcls,this));
438
439                 typeScopeInfo.push(classScope);
440                 modifiers |= M_ENUM;
441                 javaFeatures|=ResourceImpl.HAS_ENUMS;
442                 if (ifacesAST != null)
443                     interfaces = (NameRef[]) semanticInfo.get(ifacesAST);
444                 ASTree enumConsts = body.getSubTrees()[0];
445                 ASTree bodyDecls = body.getSubTrees()[1];
446                 constants = enumConsts == null ? null : (ElementInfo[]) processAST(enumConsts, currentFqn);
447                 features = bodyDecls == null ? null : (FeatureInfo[]) processAST(bodyDecls, currentFqn);
448                 enumInfo = new EnumInfo(tree, treeType, currentFqn, modifiers, features, interfaces, constants, modInfo.annotations);
449                 typeScopeInfo.pop();
450                 return enumInfo;
451             }
452             case ANNOTATION_TYPE_DECLARATION: {
453                 ModifiersInfo modInfo=getModifiers(parts[0]); // modifiers and annotations
454
int modifiers= modInfo != NO_MODIFIERS ? modInfo.modifiers : getDeprecated(tree);
455                 ASTree body=parts[2]; // class body
456
AnnotationTypeInfo annTypeInfo;
457                 FeatureInfo features[];
458                 String JavaDoc currentFqn;
459                 String JavaDoc interfaces[]=null;
460                 Scope classScope=new Scope((Scope)typeScopeInfo.peek());
461                 AnnotationType annType = (AnnotationType) semanticInfo.get(tree);
462                 
463                 javaFeatures|=ResourceImpl.HAS_ANNOTATIONTYPES;
464                 currentFqn = annType.getName();
465                 classScope.addMember(Scope.createMemberTypeScope(annType, this));
466                 typeScopeInfo.push(classScope);
467                 features = (FeatureInfo[]) processAST(body, currentFqn);
468                 annTypeInfo = new AnnotationTypeInfo(tree, treeType, currentFqn, modifiers, features, modInfo.annotations);
469                 typeScopeInfo.pop();
470                 return annTypeInfo;
471             }
472             case INTERFACE_DECLARATION:
473             case CLASS_DECLARATION: {
474                 ModifiersInfo modInfo=getModifiers(parts[0]); // modifiers and annotations
475
int modifiers= modInfo != NO_MODIFIERS ? modInfo.modifiers : getDeprecated(tree);
476                 ASTree body=parts[5]; // class body
477
ASTree ifacesAST=parts[4];
478                 TypeParamInfo[] typeParams=(TypeParamInfo[])processAST(parts[2]);
479                 ClassInfo clsInfo;
480                 FeatureInfo features[];
481                 String JavaDoc currentFqn;
482                 NameRef sclass=(NameRef)semanticInfo.get(parts[1]);
483                 NameRef interfaces[]=null;
484                 Scope classScope=new Scope((Scope)typeScopeInfo.peek());
485                 
486                 JavaClass jcls=(JavaClass)semanticInfo.get(tree);
487
488                 currentFqn=jcls.getName();
489                 classScope.addMember(Scope.createMemberTypeScope(jcls,this));
490
491                 typeScopeInfo.push(classScope);
492                 if (treeType==INTERFACE_DECLARATION)
493                     modifiers |= Modifier.INTERFACE;
494                 if (ifacesAST!=null)
495                     interfaces=(NameRef[])semanticInfo.get(ifacesAST);
496                 typeParams = (TypeParamInfo[]) processAST(parts[2],currentFqn);
497                 features=(FeatureInfo[])processAST(body,currentFqn);
498                 clsInfo=new ClassInfo(tree, treeType, currentFqn, modifiers, features, sclass, interfaces, typeParams, modInfo.annotations);
499                 typeScopeInfo.pop();
500                 return clsInfo;
501             }
502             case CONSTRUCTOR_DECLARATION:
503             case METHOD_DECLARATION: {
504                 ModifiersInfo modInfo=getModifiers(parts[0]); // modifiers and annotations
505
int modifiers= modInfo != NO_MODIFIERS ? modInfo.modifiers : getDeprecated(tree);
506                 TypeRef type;
507                 Object JavaDoc header[];
508                 TypeParamRef exceptions[]=null;
509
510 // semanticInfo.put(tree, bhFeature);
511
TypeParamInfo[] typeParams = (TypeParamInfo[]) processAST(parts[1]);
512                 type=resolveTypeName(parts[2]); // type
513
header=(Object JavaDoc[])processAST(parts[3]); // header 0 - ID, 1 - params, 2 - dims
514
ASTree exsAST=parts[4]; // exceptions
515
String JavaDoc name=null;
516                 ParameterInfo pars[]=(ParameterInfo[])header[1];
517                 
518                 if (treeType==METHOD_DECLARATION) {
519                     name=(String JavaDoc)header[0];
520                 }
521                 if (exsAST!=null) {
522                     ASTree[] exIds=exsAST.getSubTrees();
523                     
524                     exceptions=new TypeParamRef[exIds.length];
525                     for (i=0;i<exIds.length;i++) {
526                         exceptions[i]=(TypeParamRef)resolveTypeName(exIds[i]);
527                     }
528                 }
529                 return new MethodInfo(tree, treeType, name, modifiers, type == null ? null : fullType(type, header[2]), pars, exceptions, typeParams, modInfo.annotations);
530             }
531             case CONSTRUCTOR_DECLARATOR:
532             case VARIABLE_DECLARATOR: {
533                 return new Object JavaDoc[] {processAST(parts[0]),processAST(parts[1])};
534             }
535             case METHOD_DECLARATOR: {
536                 return new Object JavaDoc[] {processAST(parts[0]), processAST(parts[1]), processAST(parts[2])};
537             } case FORMAL_PARAMETER_LIST: {
538                 ParameterInfo pars[]=new ParameterInfo[parts.length];
539                 
540                 for (i=0;i<pars.length;i++)
541                     pars[i]=(ParameterInfo)processAST(parts[i],fqn);
542                 return pars;
543             }
544             case FORMAL_PARAMETER: {
545                 ModifiersInfo modInfo=getModifiers(parts[0]); // final and annotations
546
boolean isFinal=false;
547                 TypeRef type=resolveTypeName(parts[1]);
548                 Object JavaDoc decl[]=(Object JavaDoc[])processAST(parts[3]); // VARIABLE_DECLARATOR
549
TypeRef varType=fullType(type,decl[1]); // dims
550
String JavaDoc name=(String JavaDoc)decl[0];
551                 
552                 if (modInfo!=null)
553                     isFinal=Modifier.isFinal(modInfo.modifiers);
554                 return new ParameterInfo(tree, treeType, name, isFinal, varType, parts[2] != null, modInfo.annotations);
555             }
556             case TYPE_PARAMETER_LIST: {
557                 TypeParamInfo typeParams[] = new TypeParamInfo[parts.length];
558                 
559                 javaFeatures|=ResourceImpl.HAS_GENERICS;
560                 createTypeParametrScope(tree);
561                 for (i = 0; i < typeParams.length; i++) {
562                     typeParams[i] = (TypeParamInfo) processAST(parts[i]);
563                 }
564                 return typeParams;
565             }
566             case TYPE_PARAMETER: {
567                 String JavaDoc name = (String JavaDoc) processAST(parts[0]);
568                 TypeParamRef[] bounds = (TypeParamRef[]) processAST(parts[1]);
569                 
570                 return new TypeParamInfo(tree, tree.getType(), name, bounds);
571             }
572             case BOUND_LIST: {
573                 TypeParamRef[] result = new TypeParamRef[parts.length];
574                 for (i = 0; i < parts.length; i++) {
575                     result[i] = (TypeParamRef)resolveTypeName(parts[i]);
576                 }
577                 return result;
578             }
579             case TYPE_ARGUMENTS: {
580                 Object JavaDoc[] result=new Object JavaDoc[parts.length];
581                 
582                 javaFeatures|=ResourceImpl.HAS_GENERICS;
583                 for (i=0;i<parts.length;i++) {
584                     ASTree argAST=parts[i];
585                     
586                     if (argAST.getType()==IDENTIFIER)
587                         result[i]=resolveTypeName(argAST);
588                     else
589                         result[i]=processAST(argAST);
590                 }
591                 return result;
592             }
593             case FIELD_DECLARATION: {
594                 ModifiersInfo modInfo=getModifiers(parts[0]); // modifiers and annotations
595
int modifiers= modInfo != NO_MODIFIERS ? modInfo.modifiers : getDeprecated(tree);
596                 TypeRef type=resolveTypeName(parts[1]); // type
597
ASTree varDeclsTree=parts[2];
598                 Object JavaDoc decls[]=(Object JavaDoc[])processAST(varDeclsTree); // VARIABLE_DECLARATORS
599

600                 if (varDeclsTree.getType()==VARIABLE_DECLARATOR) {
601                     TypeRef varType=fullType(type,decls[1]);
602                     String JavaDoc name=(String JavaDoc)decls[0];
603                     return new FieldInfo(tree, treeType, name, modifiers, varType, FieldInfo.SINGLE_FIELD_INDEX, modInfo.annotations);
604                 } else { // VARIABLE_DECLARATORS
605
FieldInfo[] fields = new FieldInfo[decls.length];
606                     ASTree[] children = varDeclsTree.getSubTrees();
607                     for (i=0;i<decls.length;i++) {
608                         Object JavaDoc decl[]=(Object JavaDoc[])decls[i];
609                         fields[i] = new FieldInfo(children[i], FIELD_DECLARATION, (String JavaDoc) decl[0], modifiers, fullType(type,decl[1]), i, modInfo.annotations);
610                     }
611                     return new FieldGroupInfo(tree, VARIABLE_DECLARATORS, modifiers, type, fields, modInfo.annotations);
612                 }
613             }
614             case ANNOTATION_ATTRIBUTE_DECLARATION: {
615                 ModifiersInfo modInfo=getModifiers(parts[0]); // modifiers and annotations
616
int modifiers= modInfo != NO_MODIFIERS ? modInfo.modifiers : getDeprecated(tree);
617                 TypeRef type=resolveTypeName(parts[1]); // type
618
String JavaDoc name=(String JavaDoc)processAST(parts[2]); // name
619
AnnotationValueInfo defaultValue=(AnnotationValueInfo)processAST(parts[3]);
620                 return new AttributeInfo(tree, treeType, name, modifiers, type, defaultValue, modInfo.annotations);
621             }
622             case INSTANCE_INITIALIZER:
623             case STATIC_INITIALIZER: {
624                 ASTree modTree=parts[0]; // modifiers
625
ModifiersInfo modInfo=getModifiers(parts[0]); // modifiers and annotations
626
int modifiers=modInfo.modifiers;
627                 
628 // semanticInfo.put(tree,initializer);
629
return new FeatureInfo(tree, treeType, null, modifiers, modInfo.annotations);
630             }
631             case ANNOTATION: {
632                 NameRef name=(NameRef)resolveTypeName(parts[0]);
633                 ASTree pAST=parts[1];
634                 ASTree[] pairsAST=pAST!=null?pAST.getSubTrees():new ASTree[0];
635                 AnnotationValueInfo[] attributePairs=new AnnotationValueInfo[pairsAST.length];
636                 
637                 javaFeatures|=ResourceImpl.HAS_ANNOTATION;
638                 for (i=0;i<attributePairs.length;i++) {
639                     ASTree[] valueASTs=pairsAST[i].getSubTrees();
640                     String JavaDoc pairName=(String JavaDoc)processAST(valueASTs[0]);
641                     ASTree valueAST=valueASTs[1];
642                     int valueType=valueAST.getType();
643                     AnnotationValueInfo attributePair;
644                     
645                     if (valueType==ASTreeTypes.ANNOTATION) {
646                         Object JavaDoc ann=processAST(valueAST);
647                         attributePair=new AnnotationValueInfo(pairsAST[i],AnnotationValueInfo.ANNOTATIONVALUE_ANNOTATION,pairName,ann);
648                     } else if (valueType==ASTreeTypes.ARRAY_INITIALIZER) {
649                         Object JavaDoc[] ann=getArray(processAST(valueAST));
650                         attributePair=new AnnotationValueInfo(pairsAST[i],AnnotationValueInfo.ANNOTATIONVALUE_ARRAY,pairName,ann);
651                     } else {
652                         String JavaDoc ann=getText(valueAST);
653                         attributePair=new AnnotationValueInfo(pairsAST[i],AnnotationValueInfo.ANNOTATIONVALUE_STRING,pairName,ann);
654                     }
655                     attributePairs[i]=attributePair;
656                 }
657                 return new AnnotationInfo(tree,treeType,name,attributePairs);
658             }
659             case REFERENCE_TYPE: {
660                 ASTree dim=parts[1];
661                 ASTree typeAST=parts[0];
662                 TypeRef t;
663                 
664                 if (typeAST.getType()!=PRIMITIVE_TYPE)
665                     t=resolveTypeName(typeAST);
666                 else
667                     t=(TypeRef)processAST(typeAST);
668                 if (dim!=null && t!=null) {
669                     int dimension=((Integer JavaDoc)processAST(dim)).intValue();
670                     
671                     t=new ArrayRef((PrimitiveTypeRef)t,dimension);
672                 }
673                 return t;
674             }
675             case PRIMITIVE_TYPE: {
676                 return getPrimitiveType(parts[0]);
677             }
678             
679             case DIMS: {
680                 return new Integer JavaDoc((tree.getLastToken()-tree.getFirstToken()+1)/2);
681             }
682             case WILDCARD: {
683                 boolean isLower;
684                 ASTree lowerAST=parts[0];
685                 TypeRef bound;
686                 
687                 if (lowerAST==null)
688                     return new WildCardRef(false,null);
689                 isLower=lowerAST.getType()==EXTENDS;
690                 bound=resolveTypeName(parts[1]);
691                 return new WildCardRef(isLower,bound);
692             }
693             case MULTI_PART_ID: {
694                 ASTree parent=parts[0];
695                 ASTree nameAST=parts[1];
696                 String JavaDoc name=(String JavaDoc)processAST(nameAST);
697                 TypeParamRef parentRef;
698                 Object JavaDoc sInfo=null;
699                 Object JavaDoc[] args;
700                 TypeParamRef ref=null;
701                 
702                 if (parent!=null) {
703                     Object JavaDoc parentInfo;
704                     
705                     if (parent.getType()==IDENTIFIER)
706                         parentRef=(TypeParamRef)resolveTypeName(parent);
707                     else
708                         parentRef=(TypeParamRef)processAST(parent);
709                     parentInfo=semanticInfo.get(parent);
710                     if (parentInfo instanceof String JavaDoc && ((String JavaDoc)parentInfo).charAt(0)=='*') { // package
711
NameRef pckRef=(NameRef)parentRef;
712                         String JavaDoc pckName=pckRef.name.concat(".").concat(name); // NOI18N
713

714                         sInfo=getPackage(pckName);
715                         if (sInfo!=null)
716                             ref=new NameRef(pckName);
717                     }
718                     args=getArray(processAST(parts[2]));
719                     if (sInfo==null) {
720                         TypeRef[] argRef=new TypeRef[args.length];
721
722                         System.arraycopy(args, 0, argRef, 0, args.length);
723                         sInfo=ref=new NameRef(name,parentRef,argRef);
724                     }
725                     storeSemanticInfo(nameAST, sInfo);
726                 } else {
727                     args=getArray(processAST(parts[2]));
728                     TypeParamRef nameRef=(TypeParamRef)resolveTypeName(nameAST);
729                     TypeRef[] argRef=new TypeRef[args.length];
730
731                     System.arraycopy(args, 0, argRef, 0, args.length);
732                     sInfo=ref=new NameRef(nameRef.name,null,argRef);
733                 }
734                 storeSemanticInfo(tree, sInfo);
735                 return ref;
736             }
737             case IDENTIFIER:
738                 return ((Token)tree).getValue();
739                 
740             case MODIFIERS: {
741                 int modifiers=0,annCount=0;
742                 AnnotationInfo[] infos = new AnnotationInfo[parts.length];
743                 for (i=0;i<parts.length;i++) {
744                     ASTree modTree=parts[i];
745                     if (modTree.getType()==ASTreeTypes.ANNOTATION) {
746                         AnnotationInfo ai = (AnnotationInfo) processAST(modTree);
747                         infos[annCount++] = ai;
748                         if (ai.type.name.equals("Deprecated") || ai.type.name.equals("java.lang.Deprecated")) // NOI18N
749
modifiers|=FeatureImpl.DEPRECATED;
750                     }
751                     else {
752                         Token tok = (Token)modTree;
753                         modifiers|=((Integer JavaDoc)(tok).getValue()).intValue();
754                         if (tok.getDeprecatedFlag())
755                             modifiers|=FeatureImpl.DEPRECATED;
756                     }
757                 }
758                 AnnotationInfo[] annArray=new AnnotationInfo[annCount];
759                 System.arraycopy(infos,0,annArray,0,annCount);
760                 return new ModifiersInfo(modifiers,annArray);
761             } case DEFAULT_VALUE: {
762                 return new AnnotationValueInfo(tree, AnnotationValueInfo.ANNOTATIONVALUE_STRING, null, null);
763             }
764                 
765             default: {
766                 if (parts!=null) {
767                     Object JavaDoc val=null;
768                     Object JavaDoc valArr[]=null;
769                     int arrIndex=0;
770                     
771                     for (i=0;i<parts.length;i++) {
772                         Object JavaDoc ret=processAST(parts[i]);
773                         
774                         if (ret!=null) {
775                             if (val==null)
776                                 val=ret;
777                             else if (arrIndex==0) {
778                                 valArr=new Object JavaDoc[parts.length-i+1];
779                                 valArr[0]=val;
780                                 valArr[1]=ret;
781                                 arrIndex=2;
782                             } else
783                                 valArr[arrIndex++]=ret;
784                         }
785                     }
786                     return arrIndex==0?val:valArr;
787                 }
788             }
789         }
790         return null;
791     }
792
793     private String JavaDoc resolveStaticImport(ASTree mpid) {
794         String JavaDoc id=null;
795
796         if (mpid!=null) {
797             ASTree[] mpiparts=mpid.getSubTrees();
798
799             if (mpiparts!=null) {
800                 NameRef parentRef=(NameRef)resolveTypeName(mpiparts[0]);
801                 ASTree nameAST=mpiparts[1];
802                 String JavaDoc name=(String JavaDoc)processAST(nameAST);
803                 JavaClass jcls=(JavaClass)((SemiPersistentElement)getResource()).resolveType(parentRef);
804                 Feature feature=null;
805
806                 if (jcls!=null) {
807                     Object JavaDoc[] features=jcls.getFeatures().toArray();
808
809                     for(int i=0;i<features.length;i++) {
810                         Feature f=(Feature)features[i];
811
812                         if (name.equals(f.getName())) {
813                             feature=f;
814                             break;
815                         }
816                     }
817                 }
818                 storeSemanticInfo(mpid, feature);
819                 storeSemanticInfo(nameAST, feature);
820                 id=parentRef.name.concat(".").concat(name); // NOI18N
821
}
822         }
823         return id;
824     }
825     
826     private Object JavaDoc getModelElement(ASTree tree,Element mdrElement,Object JavaDoc symbolInfo) {
827         if (symbolInfo instanceof String JavaDoc) {
828             String JavaDoc strInfo=(String JavaDoc)symbolInfo;
829             char firstChar=strInfo.charAt(0);
830             String JavaDoc name;
831             
832             switch(firstChar) {
833                 case '*':
834                 case '@':
835                 case '<':
836                 case '^':
837                     name=strInfo.substring(1);
838                     break;
839                 default:
840                     return typeClass.resolve(strInfo);
841             }
842             switch (firstChar) {
843                 case '*':
844                     return getPackage(name);
845                 case '@':
846                     return resolveClass(name);
847                 case '<':
848                     return resolveTypeParameter(tree,name);
849                 case '^':
850                     return rep.getByMofId(name);
851             }
852             return null;
853         }
854         if (symbolInfo.getClass().equals(TypeParamRef.class)) {
855             TypeParamRef tpRef=(TypeParamRef)symbolInfo;
856             
857             return ((MetadataElement)mdrElement).resolveType(tpRef);
858         }
859         if (symbolInfo instanceof TypeRef) {
860             if (mdrElement==null)
861                 mdrElement=getResource();
862             Type el=((MetadataElement)mdrElement).resolveType((TypeRef)symbolInfo);
863             
864             if (el instanceof ParameterizedType)
865                 return ((ParameterizedType)el).getDefinition();
866             if (el instanceof ParameterizedTypeImpl.Wrapper) {
867                 ParameterizedTypeImpl.Wrapper w=(ParameterizedTypeImpl.Wrapper)el;
868                 return (Element)w.getWrappedObject();
869             }
870             return el;
871         }
872         if (symbolInfo instanceof FieldRefInfo) {
873             FieldRefInfo fref=(FieldRefInfo)symbolInfo;
874             ClassDefinition javaClass=(ClassDefinition)getModelElement(null,null,fref.declClass);
875             Feature f;
876             
877             if (javaClass==null)
878                 return null;
879             f=(Feature)rep.getByMofId(fref.mofid);
880             if (f!=null) {
881                 JavaClass declClass=(JavaClass)f.getDeclaringClass();
882
883                 if (declClass.equals(javaClass))
884                     return f;
885             }
886             
887             String JavaDoc name=fref.name;
888             if (fref instanceof CallableRefInfo) {
889                 CallableRefInfo c=(CallableRefInfo)fref;
890                 Object JavaDoc features[]=javaClass.getContents().toArray();
891                 if (name==null) { // CONSTRUCTOR IMPLEMENTATION
892
for (int i=0;i<features.length;i++) {
893                         ClassMember element = (ClassMember)features[i];
894                         if ((element instanceof Constructor) && (parametersMatch((CallableFeature) element, c.parTypes))) {
895                             return element;
896                         }
897                     }
898                 } else { // Method
899
for (int i=0;i<features.length;i++) {
900                         ClassMember element = (ClassMember)features[i];
901                         if (!(element instanceof Method)) {
902                             continue;
903                         }
904                         if (!name.equals(element.getName())) {
905                             continue;
906                         }
907                         if (parametersMatch((CallableFeature) element, c.parTypes)) {
908                             return element;
909                         }
910                     }
911                 }
912             } else { // Field
913
Object JavaDoc features[]=javaClass.getFeatures().toArray();
914                 for (int i=0;i<features.length;i++) {
915                     ClassMember element = (ClassMember)features[i];
916                     if (!(element instanceof Field)) {
917                         continue;
918                     }
919                     if (name.equals(element.getName())) {
920                         return element;
921                     }
922                 }
923             }
924             ErrorManager.getDefault().log(ErrorManager.WARNING, fref+" not found in "+getResource().getName());
925             return null;
926         }
927         if (symbolInfo instanceof LocalVarRefInfo) {
928             LocalVarRefInfo localvar=(LocalVarRefInfo)symbolInfo;
929             
930             if (localvar.var==null) {
931                 Collection topCollection=Collections.singletonList(getResource());
932                 localvar.var=(Variable)getModelElement(topCollection,localvar.varDeclAST);
933             }
934             return localvar.var;
935         }
936         if (!(symbolInfo instanceof MetadataElement) || ((MetadataElement)symbolInfo).isTransient())
937             return symbolInfo;
938         JMManager.getLog().log("Invalid type :"+symbolInfo); // NOI18N
939
return null;
940     }
941
942     private TypeParameter resolveTypeParameter(ASTree tree,String JavaDoc name) {
943         int firstToken=tree.getFirstToken();
944         int lastToken=tree.getLastToken();
945         int i;
946         TypeParameter tp=null;
947         Iterator elIterator=Collections.singletonList(getResource()).iterator();
948         
949         while (elIterator.hasNext()) {
950             MetadataElement el=(MetadataElement)elIterator.next();
951             ASTree t=el.getASTree();
952             
953             if (t==tree)
954                 return tp;
955             if (firstToken>=t.getFirstToken() && lastToken<=t.getLastToken()) {
956                 if (el instanceof GenericElement) {
957                     Iterator tpIt=((GenericElement)el).getTypeParameters().iterator();
958                     
959                     while(tpIt.hasNext()) {
960                         TypeParameter p=(TypeParameter)tpIt.next();
961                         
962                         if (p.getName().equals(name)) {
963                             tp=p;
964                         }
965                     }
966                 }
967                 elIterator=el.getChildren().iterator();
968             }
969         }
970         return null;
971     }
972     
973     private JavaClass resolveClass(TypeParamRef name) {
974         SemiPersistentElement res=(SemiPersistentElement)getResource();
975         JavaClass jcls=(JavaClass)res.resolveType(name);
976         
977         if (jcls instanceof ParameterizedType)
978             return ((ParameterizedType)jcls).getDefinition();
979         return jcls;
980     }
981     
982     private JavaClass resolveClass(String JavaDoc name) {
983         JavaClass javaClass = (JavaClass) jclsClass.resolveClass(name, true);
984         if (javaClass == null) {
985             // it is acceptable that the class was not resolved in case of opening a single file (from unopened project)
986
// this is because in that case javac uses its standard class reader to do the attribution
987
// let's log a message but do not throw an exception
988
if (DEBUG) ErrorManager.getDefault().log(ErrorManager.USER, "Class " + name + " could not be resolved.");
989         }
990         return javaClass;
991     }
992
993     /**
994      * Looks for the model element for the specified ASTree. Method is called
995      * recursively to its subtrees.
996      *
997      * @param elements root object where to start find
998      * @param findingTree tree for which we looking for the element
999      * @return found element for the tree
1000     */

1001    private MetadataElement getModelElement(Collection elements, ASTree findingTree) {
1002        if (elements == null || elements.isEmpty())
1003            return null;
1004        int firstToken = findingTree.getFirstToken();
1005        int lastToken = findingTree.getLastToken();
1006        for (Iterator it = elements.iterator(); it.hasNext(); ) {
1007            MetadataElement element = (MetadataElement) it.next();
1008            ASTree elementTree = element.getASTree();
1009            if (elementTree == findingTree) {
1010                // we have found it!
1011
return element;
1012            } else if (elementTree.getFirstToken() <= firstToken && elementTree.getLastToken() >= lastToken) {
1013                // the element is in child tree, look for it recursively
1014
MetadataElement result = getModelElement(element.getChildren(), findingTree);
1015                if (result == null) {
1016                    // seems that for the provided collection of elements there isn't
1017
// tree provided in findingTree parameter.
1018
throw new IllegalArgumentException JavaDoc("Tree not found! (Tree type = " + // NOI18N
1019
findingTree.getType() + "; Bounds: " + firstToken + ", " + lastToken + // NOI18N
1020
"; Element type: " + elementTree.getType() + "; Bounds: " + elementTree.getFirstToken() + ", " + elementTree.getLastToken() + // NOI18N
1021
")"); // NOI18N
1022
}
1023                return result;
1024            }
1025        }
1026        return null;
1027    }
1028
1029    public boolean isVariableAccess(ASTree tree) {
1030        if (tree == null) {
1031            //66918
1032
return false;
1033        }
1034        if (!attributionToDo.isEmpty()) {
1035            doAttribution();
1036        }
1037        Object JavaDoc info = semanticInfo.get(tree);
1038        if (info == null) {
1039            if (tree.getType() == MULTI_PART_ID) {
1040                return isVariableAccess(tree.getSubTrees()[0]);
1041            } else {
1042                return false;
1043            }
1044        }
1045        if (info.getClass().equals(FieldRefInfo.class) || info instanceof LocalVarRefInfo)
1046            return true;
1047        if (info instanceof String JavaDoc) {
1048            String JavaDoc id=(String JavaDoc)info;
1049            Object JavaDoc jmiObject;
1050            
1051            if (id.charAt(0)!='^')
1052                return false;
1053            jmiObject=getSemanticInfo(tree, null);
1054            return jmiObject instanceof Variable;
1055        }
1056        return false;
1057    }
1058
1059    /**
1060     * Checks wheter parameters names match. Takes callable feature parameters
1061     * and symbolInfo parameters and compares them. If all the type names and
1062     * they order is the same, returns true. Otherwise it returns false.
1063     *
1064     * @param callableFeature feature with parameters.
1065     * @param symbolInfo info with array of string representing
1066     * parameter type names.
1067     * @return true, parameters' types match
1068     */

1069    static boolean parametersMatch(CallableFeature callableFeature, TypeRef[] parTypes) {
1070        Object JavaDoc[] params=callableFeature.getParameters().toArray();
1071        
1072        if (params.length != parTypes.length)
1073            return false; // if the size of list and array differs, continue
1074
for (int i=0;i<params.length;i++) {
1075            // check the parameters that they are the same
1076
ParameterImpl par = (ParameterImpl)params[i];
1077            ParameterInfo parInfo = (ParameterInfo) par.getElementInfo();
1078            if (!parTypes[i++].equals(parInfo.type)) {
1079                return false;
1080            }
1081        }
1082        return true;
1083    }
1084    
1085    void createTypeParametrScope(ASTree typeParsAST) {
1086        ASTree[] typeParams;
1087        int i;
1088        Scope currentScope;
1089        
1090        if (typeParsAST==null)
1091            return;
1092        if (typeParsAST.getType()!=TYPE_PARAMETER_LIST)
1093            throw new IllegalArgumentException JavaDoc("Type "+typeParsAST.getType()); // NOI18N
1094
typeParams=typeParsAST.getSubTrees();
1095        currentScope=(Scope)typeScopeInfo.peek();
1096        for (i = 0; i < typeParams.length; i++) {
1097            ASTree typeParAST=typeParams[i];
1098            String JavaDoc name = (String JavaDoc) processAST(typeParAST.getSubTrees()[0]);
1099
1100            currentScope.addMember(new TypeParamScope(name));
1101        }
1102    }
1103    
1104    void resolveSuperTypes(ASTree classTree,String JavaDoc fqn) {
1105        int treeType=classTree.getType();
1106
1107        typeScopeInfo.push(new Scope((Scope)typeScopeInfo.peek()));
1108        switch (treeType) {
1109            case ENUM_DECLARATION: {
1110                int i;
1111                ASTree parts[]=classTree.getSubTrees();
1112                String JavaDoc name=(String JavaDoc)processAST(parts[1]); // class name
1113
ASTree ifacesAST=parts[2]; // interfaces
1114
NameRef interfaces[];
1115                List interJcls=Collections.EMPTY_LIST;
1116                NameRef sclass;
1117                String JavaDoc currentFqn=fqn.length()==0?name:fqn.concat(".").concat(name); // NOI18N
1118
JavaClass superJcls = null;
1119                
1120                sclass=NameRef.java_lang_Enum;
1121                semanticInfo.put(parts[1],sclass);
1122                if (ifacesAST!=null) {
1123                    ASTree ifaces[]=ifacesAST.getSubTrees();
1124                    
1125                    interfaces=new NameRef[ifaces.length];
1126                    interJcls=new ArrayList();
1127
1128                    for (i=0;i<ifaces.length;i++) {
1129                        interfaces[i]=(NameRef)resolveTypeName(ifaces[i]);
1130                        interJcls.add(resolveClass(interfaces[i]));
1131                    }
1132                    semanticInfo.put(ifacesAST,interfaces);
1133                }
1134                if (semanticInfo.get(classTree)==null) {
1135                    JavaClass jcls = getClassByFqn(currentFqn);
1136
1137                    // INDEX INCONSISTENCY RECOVERY
1138
if (jcls == null) {
1139                        JMManager.getLog().log("Enum not found in index: " + currentFqn + ". Recovering...");
1140                        Thread.dumpStack();
1141                        jcls = enumClass.create(currentFqn, 0, false);
1142                        setParent(jcls,fqn);
1143                    } else if (!(jcls instanceof JavaEnum)) {
1144                        JMManager.getLog().log(ErrorManager.INFORMATIONAL,"Wrong type of object found in index. Expected: JavaEnum, found: " + jcls.getClass().getName());
1145                        JMManager.getLog().log(ErrorManager.INFORMATIONAL,"Recovering...");
1146                        Thread.dumpStack();
1147                        JavaClass oldCls = jcls;
1148                        jcls = enumClass.create(currentFqn, oldCls.getModifiers(), false);
1149                        swapChild(oldCls, jcls);
1150                    }
1151                    // -----------------------------
1152
semanticInfo.put(classTree, jcls);
1153                }
1154                if (sclass!=null)
1155                    superJcls=resolveClass(sclass);
1156                superInfoMap.put(currentFqn,new SuperInfo(superJcls,interJcls));
1157                localSuperInfo.add(currentFqn);
1158                break;
1159            }
1160            case ANNOTATION_TYPE_DECLARATION:
1161            case INTERFACE_DECLARATION:
1162            case CLASS_DECLARATION:
1163                int i;
1164                ASTree parts[]=classTree.getSubTrees();
1165                String JavaDoc name=(String JavaDoc)processAST(parts[1]); // class name
1166
ASTree superclassAST; // extends
1167
ASTree ifacesAST; // interfaces
1168
NameRef interfaces[];
1169                List interJcls=Collections.EMPTY_LIST;
1170                NameRef sclass=null;
1171                String JavaDoc currentFqn=fqn.length()==0?name:fqn.concat(".").concat(name); // NOI18N
1172
JavaClass superJcls=null;
1173
1174                if (treeType==ANNOTATION_TYPE_DECLARATION) {
1175                    superclassAST=null;
1176                    ifacesAST=null;
1177                    sclass=NameRef.java_lang_Annotation;
1178                } else {
1179                    createTypeParametrScope(parts[2]); // type parameters
1180
superclassAST=parts[3]; // extends
1181
ifacesAST=parts[4]; // interfaces
1182
if (superclassAST!=null) {
1183                        sclass=(NameRef)resolveTypeName(superclassAST.getSubTrees()[0]);
1184                    } else if (!(name.equals("Object") && jpck.equals("java.lang")) && treeType==CLASS_DECLARATION) // NOI18N
1185
sclass=NameRef.java_lang_Object;
1186                }
1187                if (sclass!=null) {
1188                    semanticInfo.put(parts[1],sclass);
1189                }
1190                if (ifacesAST!=null) {
1191                    ASTree[] ifaces=ifacesAST.getSubTrees();
1192                    
1193                    interfaces=new NameRef[ifaces.length];
1194                    interJcls=new ArrayList();
1195                    
1196                    for (i=0;i<ifaces.length;i++) {
1197                        interfaces[i]=(NameRef)resolveTypeName(ifaces[i]);
1198                        interJcls.add(resolveClass(interfaces[i]));
1199                    }
1200                    semanticInfo.put(ifacesAST,interfaces);
1201                }
1202                if (semanticInfo.get(classTree)==null) {
1203                    JavaClass jcls = getClassByFqn(currentFqn);
1204
1205                    // INDEX INCONSISTENCY RECOVERY
1206
if (jcls == null) {
1207                        JMManager.getLog().notify(ErrorManager.INFORMATIONAL,new Exception JavaDoc((treeType == ANNOTATION_TYPE_DECLARATION ? "Annotation" : "Class") + " not found in index: " + currentFqn + ". Recovering...")); // NOI18N
1208
if (treeType == ANNOTATION_TYPE_DECLARATION) {
1209                            jcls = annotClass.create(currentFqn, 0, false);
1210                        } else {
1211                            jcls = jclsClass.create(currentFqn, 0, null, null, false);
1212                        }
1213                        setParent(jcls,fqn);
1214                    } else if (treeType == ANNOTATION_TYPE_DECLARATION && !(jcls instanceof AnnotationType)) {
1215                        JMManager.getLog().log(ErrorManager.WARNING, "Wrong type of object found in index. Expected: AnnotationType, found: " + jcls.getClass().getName());
1216                        JMManager.getLog().notify(ErrorManager.INFORMATIONAL,new Exception JavaDoc("Recovering...")); // NOI18N
1217
JavaClass oldCls = jcls;
1218                        jcls = annotClass.create(currentFqn, oldCls.getModifiers(), false);
1219                        swapChild(oldCls, jcls);
1220                    } else if (treeType != ANNOTATION_TYPE_DECLARATION && (jcls instanceof AnnotationType || jcls instanceof JavaEnum)) {
1221                        JMManager.getLog().log(ErrorManager.WARNING, "Wrong type of object found in index. Expected: JavaClass, found: " + jcls.getClass().getName());
1222                        JMManager.getLog().notify(ErrorManager.INFORMATIONAL,new Exception JavaDoc("Recovering...")); // NOI18N
1223
JavaClass oldCls = jcls;
1224                        jcls = jclsClass.create(currentFqn, oldCls.getModifiers(), null, null, false);
1225                        swapChild(oldCls, jcls);
1226                    }
1227                    // -----------------------------
1228

1229                    semanticInfo.put(classTree, jcls);
1230                }
1231                if (sclass!=null)
1232                    superJcls=resolveClass(sclass);
1233                superInfoMap.put(currentFqn,new SuperInfo(superJcls,interJcls));
1234                localSuperInfo.add(currentFqn);
1235        }
1236        typeScopeInfo.pop();
1237    }
1238    
1239    // ---------------- METHODS USED FOR INDEX INCONSISTENCY RECOVERY -----------------------------
1240
private JavaClass getClassByFqn(String JavaDoc currentFqn) {
1241        JavaClass jcls = null;
1242        Collection classes = index.getClassesByFqn(currentFqn);
1243        for (Iterator it = classes.iterator(); it.hasNext();) {
1244            JavaClass tmp = (JavaClass) it.next();
1245            if (tmp.isValid() && getResource().equals(tmp.getResource())) {
1246                jcls = tmp;
1247                break;
1248            }
1249        }
1250        return jcls;
1251    }
1252    
1253    
1254    private void swapChild(JavaClass oldType, JavaClass newType) {
1255        RefFeatured parent = oldType.refImmediateComposite();
1256        if (parent instanceof ResourceImpl) {
1257            ListIterator it;
1258            for (it = ((ResourceImpl) parent).getPersistentClassifiers().listIterator(); it.hasNext();) {
1259                JavaClass cls = (JavaClass) it.next();
1260                if (cls.equals(oldType)) {
1261                    it.set(newType);
1262                    oldType.refDelete();
1263                    if (((ResourceImpl) parent).classifiersInited()) {
1264                        ((ResourceImpl) parent).reinitClassifiers();
1265                    }
1266                    return;
1267                }
1268            }
1269            JMManager.getLog().log("Old type wasn't found in classifiers of its parent resource. Adding newType to the end of the resource classifiers list...");
1270            it.add(newType);
1271            oldType.refDelete();
1272            return;
1273        } else if (parent instanceof JavaClassImpl) {
1274            JavaClassImpl enclosingClass = (JavaClassImpl) parent;
1275            boolean contentsInited = enclosingClass.contentsInited();
1276            boolean contentsEmpty = enclosingClass.getPersistentContents().isEmpty();
1277            if (contentsInited || !contentsEmpty) {
1278                ListIterator it;
1279                for (it = enclosingClass.getPersistentContents().listIterator(); it.hasNext();) {
1280                    Element cls = (Element) it.next();
1281                    if (cls.equals(oldType)) {
1282                        it.set(newType);
1283                        oldType.refDelete();
1284                        if (contentsInited) {
1285                            enclosingClass.reinitContents();
1286                        }
1287                        return;
1288                    }
1289                }
1290                JMManager.getLog().log("Old type wasn't found in classifiers of its parent resource. Adding newType to the end of the resource classifiers list...");
1291                it.add(newType);
1292            } else {
1293                ((JavaClassImpl) newType).setParentClass(enclosingClass);
1294            }
1295            ((JavaClassImpl) oldType).setParentClass(null);
1296            oldType.refDelete();
1297            return;
1298        }
1299        JMManager.getLog().log("Parent of newType has not been set since parent of the oldType is: " + parent.getClass().getName());
1300    }
1301    
1302    private void setParent(JavaClass jcls,String JavaDoc fqn) {
1303        if (fqn.equals(jpck)) {
1304            ResourceImpl res = (ResourceImpl) getResource();
1305            res.getPersistentClassifiers().add(jcls);
1306            if (res.classifiersInited()) {
1307                res.reinitClassifiers();
1308            }
1309        } else {
1310            JavaClassImpl enclosingClass = (JavaClassImpl) getClassByFqn(fqn);
1311            if (enclosingClass == null) {
1312                JMManager.getLog().log("Could not find parent class: " + fqn);
1313                JMManager.getLog().log("Setting resource as a parent...");
1314                ResourceImpl res = (ResourceImpl) getResource();
1315                res.getPersistentClassifiers().add(jcls);
1316                if (res.classifiersInited()) {
1317                    res.reinitClassifiers();
1318                }
1319            } else {
1320                boolean contentsInited = enclosingClass.contentsInited();
1321                boolean contentsEmpty = enclosingClass.getPersistentContents().isEmpty();
1322                if (contentsInited || !contentsEmpty) {
1323                    enclosingClass.getPersistentContents().add(jcls);
1324                    if (contentsInited) {
1325                        enclosingClass.reinitContents();
1326                    }
1327                } else {
1328                    ((JavaClassImpl) jcls).setParentClass(enclosingClass);
1329                }
1330            }
1331        }
1332    }
1333    // --------------------------------------------------------------------------------------------
1334

1335    ModifiersInfo getModifiers(ASTree t) {
1336        ModifiersInfo nfo = (ModifiersInfo)processAST(t);
1337        return nfo == null ? NO_MODIFIERS : nfo;
1338    }
1339    
1340    /** Returns deprecated modifier if first tree token has deprecated flag. */
1341    private int getDeprecated(ASTree t) {
1342        Token tok = getToken(t.getFirstToken());
1343        return tok.getDeprecatedFlag() ? FeatureImpl.DEPRECATED : 0;
1344    }
1345    
1346    public static TypeRef fullType(Object JavaDoc t,Object JavaDoc dims) {
1347        TypeRef td=(TypeRef)t;
1348        
1349        if (dims!=null) {
1350            int dimension=((Integer JavaDoc)dims).intValue();
1351            
1352            if (td instanceof ArrayRef) {
1353                ArrayRef aref=(ArrayRef)td;
1354                return new ArrayRef(aref.parent,aref.dimCount+dimension);
1355            }
1356            else
1357                return new ArrayRef((PrimitiveTypeRef)td,dimension);
1358        }
1359        return td;
1360    }
1361
1362    Type fullType(Type td,Object JavaDoc dims) {
1363        if (dims!=null) {
1364            int i;
1365            int dimension=((Integer JavaDoc)dims).intValue();
1366            ArrayClass arrayClass=((JavaModelPackage)td.refImmediatePackage()).getArray();
1367            
1368            for (i=0;i<dimension;i++)
1369                td=arrayClass.resolveArray(td);
1370        }
1371        return td;
1372    }
1373    
1374    private static Object JavaDoc[] getArray(Object JavaDoc obj) {
1375        if (obj==null)
1376            return new Object JavaDoc[0];
1377        if (obj.getClass().isArray())
1378            return (Object JavaDoc[])obj;
1379        return new Object JavaDoc[]{obj};
1380    }
1381    
1382    TypeRef resolveTypeName(ASTree typeAST) {
1383        if (typeAST!=null) {
1384            int treeType=typeAST.getType();
1385
1386            if (treeType==IDENTIFIER) {
1387                Object JavaDoc name=resolveTypeName((String JavaDoc)processAST(typeAST));
1388                String JavaDoc fqn;
1389                
1390                storeSemanticInfo(typeAST,name);
1391                if (name instanceof TypeRef)
1392                    return (TypeRef)name;
1393                if (name instanceof Type)
1394                    return SemiPersistentElement.typeToTypeRef((Type)name);
1395                if (name instanceof JavaPackage)
1396                    fqn=((JavaPackage)name).getName();
1397                else
1398                    fqn=(String JavaDoc)name;
1399                return new NameRef(fqn,null,null);
1400            } else {
1401                return (TypeRef)processAST(typeAST);
1402            }
1403        }
1404        return null;
1405    }
1406    
1407    Object JavaDoc resolveTypeName(String JavaDoc simpleName) {
1408        Object JavaDoc ref;
1409        Scope currentScope=(Scope)typeScopeInfo.peek();
1410        String JavaDoc name;
1411        
1412        ref=currentScope.lookup(simpleName);
1413        if (ref==null) { // package
1414
JavaPackage jpck=getPackage(simpleName);
1415            
1416            if (jpck!=null)
1417                return jpck;
1418            return simpleName; // -- unresolved
1419
}
1420        return ref;
1421    }
1422    
1423    private PrimitiveTypeRef getPrimitiveType(ASTree tree) {
1424        switch(tree.getType()) {
1425            case BYTE:
1426                return PrimitiveTypeRef.BYTE;
1427            case SHORT:
1428                return PrimitiveTypeRef.SHORT;
1429            case INT:
1430                return PrimitiveTypeRef.INT;
1431            case LONG:
1432                return PrimitiveTypeRef.LONG;
1433            case CHAR:
1434                return PrimitiveTypeRef.CHAR;
1435            case FLOAT:
1436                return PrimitiveTypeRef.FLOAT;
1437            case DOUBLE:
1438                return PrimitiveTypeRef.DOUBLE;
1439            case BOOLEAN:
1440                return PrimitiveTypeRef.BOOLEAN;
1441            case VOID:
1442                return PrimitiveTypeRef.VOID;
1443        }
1444        ErrorManager.getDefault().log(ErrorManager.ERROR, "Unknown type "+tree.getType()); // NOI18N
1445
return null;
1446    }
1447    
1448    JavaClass getSuperClass(ClassDefinition jcls) {
1449        SuperInfo info=(SuperInfo)superInfoMap.get(jcls.getName());
1450        JavaClass superClass;
1451        
1452        if (info!=null)
1453            return info.superClass;
1454        if (getResource().equals(jcls.getResource())) {
1455            JMManager.getLog().log(ErrorManager.INFORMATIONAL,"Unresolved superclass for "+jcls.getName()); // NOI18N
1456
return null;
1457        }
1458        superClass=jcls.getSuperClass();
1459        if(superClass instanceof ParameterizedType) {
1460            return ((ParameterizedType)superClass).getDefinition();
1461        }
1462        return superClass;
1463    }
1464    
1465    Collection getInterfaces(ClassDefinition jcls) {
1466        SuperInfo info=(SuperInfo)superInfoMap.get(jcls.getName());
1467        
1468        if (info!=null)
1469            return info.interfaces;
1470        if (getResource().equals(jcls.getResource())) {
1471            JMManager.getLog().log(ErrorManager.INFORMATIONAL,"Unresolved Interface for "+jcls.getName()); // NOI18N
1472
return Collections.EMPTY_LIST;
1473        }
1474        return jcls.getInterfaces();
1475    }
1476
1477    private Type processASTBody(ASTree tree) {
1478        ASTree parts[];
1479        int i,treeType;
1480        Type td=null;
1481        
1482        if (tree==null)
1483            return null;
1484        parts=tree.getSubTrees();
1485        treeType=tree.getType();
1486        switch (treeType) {
1487            case COMPILATION_UNIT:
1488                typeScopeInfo.push(Scope.createTypeScope(getResource(),classPath));
1489                processASTBody(parts[2]); // declarations
1490
typeScopeInfo.pop();
1491                break;
1492            case ANNOTATION_TYPE_DECLARATION:
1493            case ENUM_DECLARATION:
1494            case INTERFACE_DECLARATION:
1495            case CLASS_DECLARATION: {
1496                ClassDefinition savedCurrentClass=currentClass;
1497                
1498                currentClass=(ClassDefinition)semanticInfo.get(tree);
1499                if (currentClass!=null) {
1500                    Scope classScope=new Scope((Scope)typeScopeInfo.peek());
1501                    Scope varScope=new Scope((Scope)variableScope.peek());
1502
1503                    classScope.addMember(Scope.createMemberTypeScope(currentClass,this));
1504                    varScope.addMember(Scope.createFieldScope(currentClass));
1505                    typeScopeInfo.push(classScope);
1506                    variableScope.push(varScope);
1507                    if (treeType == ENUM_DECLARATION) {
1508                        ASTree enumBodyDecls = parts[3].getSubTrees()[1];
1509                        if (enumBodyDecls != null) {
1510                            processASTBody(enumBodyDecls);
1511                        }
1512                    } else if (treeType == ANNOTATION_TYPE_DECLARATION) {
1513                        processASTBody(parts[2]);
1514                    } else {
1515                        processASTBody(parts[5]); // body
1516
}
1517                    variableScope.pop();
1518                    typeScopeInfo.pop();
1519                } else {
1520                    Scope currTypeScope=(Scope)typeScopeInfo.peek();
1521                    Scope currVarScope=(Scope)variableScope.peek();
1522                    JavaClassImpl locClass=createTransientClasses(tree,null);
1523                    ClassInfo locClassInfo;
1524                    Token firstBodyToken; // left bracket "{" // NOI18N
1525

1526                    currTypeScope.addMember(new LocalClassScope(locClass));
1527                    resolveSuperTypes(tree, "");
1528                    locClassInfo=(ClassInfo)processAST(tree);
1529                    locClass.updatePersistent(locClassInfo);
1530                    locClass.setElementInfo(locClassInfo);
1531                    firstBodyToken=getToken(parts[parts.length-1].getFirstToken());
1532                    semanticInfo.put(firstBodyToken,new Scope[]{(Scope)currTypeScope.clone(),(Scope)currVarScope.clone()});
1533                }
1534                currentClass=savedCurrentClass;
1535                break;
1536            }
1537            case FIELD_DECLARATION: {
1538                ASTree varDeclsTree=parts[2];
1539                
1540                if (varDeclsTree.getType()==VARIABLE_DECLARATOR) {
1541                    processASTBody(varDeclsTree.getSubTrees()[2]); //initializer
1542
} else {
1543                    ASTree varDeclsTreeArray[]=varDeclsTree.getSubTrees();
1544                    
1545                    for (i=0;i<varDeclsTreeArray.length;i++) {
1546                        ASTree varDeclTree=varDeclsTreeArray[i];
1547                        
1548                        processASTBody(varDeclTree.getSubTrees()[2]); //initializer
1549
}
1550                }
1551                break;
1552            }
1553            case ENUM_CONSTANT: {
1554                ASTree identifier = parts[0];
1555                ASTree initValue = parts[1];
1556                ASTree anonymousClass = parts[2];
1557                List parTypes;
1558                
1559                parTypes=getArgumetsTypes(initValue); // arguments
1560
usesMethod(null,currentClass,parTypes,identifier,false);
1561                if (anonymousClass!=null) {
1562                    createAnonClass(anonymousClass, (JavaClass) currentClass, null);
1563                }
1564                break;
1565            }
1566            case CONSTRUCTOR_DECLARATION:
1567            case METHOD_DECLARATION: {
1568                CallableFeature bhFeature=(CallableFeature)semanticInfo.get(tree);
1569                Scope methodVarScope=new Scope((Scope)variableScope.peek());
1570                Scope methodTypeScope=new Scope((Scope)typeScopeInfo.peek());
1571                Iterator parIt=bhFeature.getParameters().iterator();
1572                Iterator typeParIt=bhFeature.getTypeParameters().iterator();
1573
1574                while(parIt.hasNext()) {
1575                    Parameter fp=(Parameter)parIt.next();
1576                    
1577                    methodVarScope.addMember(new LocalVarScope(fp));
1578                }
1579                while(typeParIt.hasNext()) {
1580                    TypeParameter tp=(TypeParameter)typeParIt.next();
1581
1582                    methodTypeScope.addMember(new TypeParamScope(tp));
1583                }
1584                variableScope.push(methodVarScope);
1585                typeScopeInfo.push(methodTypeScope);
1586                processASTBody(parts[5]); // body
1587
typeScopeInfo.pop();
1588                variableScope.pop();
1589                break;
1590            }
1591            case INSTANCE_INITIALIZER:
1592            case STATIC_INITIALIZER: {
1593                variableScope.push(new Scope((Scope)variableScope.peek()));
1594                typeScopeInfo.push(new Scope((Scope)typeScopeInfo.peek()));
1595                processASTBody(parts[1]); // body
1596
typeScopeInfo.pop();
1597                variableScope.pop();
1598                break;
1599            }
1600            case FORMAL_PARAMETER: {
1601                ParameterInfo par=(ParameterInfo)processAST(tree);
1602                Scope currVarScope=(Scope)variableScope.peek();
1603                Type type=((SemiPersistentElement)currentFeature).resolveType(par.type);
1604                LocalVarRefInfo ref=new LocalVarRefInfo(tree,type);
1605                currVarScope.addMember(new LocalVarScope(par.name,ref));
1606                storeSemanticInfo(tree,par);
1607                break;
1608            }
1609            case SWITCH_BLOCK:
1610            case CATCH_CLAUSE:
1611            case BLOCK_STATEMENTS:
1612                if (parts!=null && parts.length>0) {
1613                    boolean createVarScope=treeType!=BLOCK_STATEMENTS
1614            || getToken(tree.getFirstToken()).getType()==L_CURLY;
1615                    
1616                    if (createVarScope)
1617                        variableScope.push(((Scope)variableScope.peek()).clone());
1618                    for (i=0;i<parts.length;i++)
1619                        processASTBody(parts[i]);
1620                    if (createVarScope)
1621                        variableScope.pop();
1622                }
1623                break;
1624            case LOCAL_VARIABLE_DECLARATION: {
1625                Scope currVarScope=(Scope)variableScope.peek();
1626                ASTree modifiers=parts[0];
1627                ModifiersInfo modInfo=getModifiers(modifiers); // final and annotations
1628
Type type=resolveClassName(parts[1]); // type
1629
ASTree varDeclsTree=parts[2];
1630                Object JavaDoc names[]=getArray(processAST(varDeclsTree));
1631                ASTree varDeclsTreeArray[];
1632                
1633                if (modifiers!=null) {
1634                    Boolean JavaDoc isFinal=Boolean.valueOf(Modifier.isFinal(modInfo.modifiers));
1635                    AnnotationInfo[] ann=modInfo.annotations;
1636
1637                    semanticInfo.put(modifiers, new Object JavaDoc[]{isFinal,ann});
1638                }
1639                usesType(type,tree);
1640                if (varDeclsTree.getType()==VARIABLE_DECLARATOR) {
1641                    varDeclsTreeArray=new ASTree[]{varDeclsTree};
1642                    names=new Object JavaDoc[]{names};
1643                } else
1644                    varDeclsTreeArray=varDeclsTree.getSubTrees();
1645                for (i=0;i<names.length;i++) {
1646                    Object JavaDoc name[]=(Object JavaDoc[])names[i];
1647                    Type varType=fullType(type,name[1]); // dims
1648
String JavaDoc varName=(String JavaDoc)name[0];
1649                    ASTree varDecl=varDeclsTreeArray[i];
1650                    
1651                    if (names.length>1)
1652                        usesType(varType, varDecl);
1653                    currVarScope.addMember(new LocalVarScope(varName,new LocalVarRefInfo(varDecl,varType)));
1654                    processASTBody(varDecl.getSubTrees()[2]); //initializer
1655
}
1656                break;
1657            }
1658            case FOR_STATEMENT: {
1659                ASTree initAST=parts[0];
1660                Scope forScope=null;
1661                
1662                if (initAST!=null && initAST.getType()==LOCAL_VARIABLE_DECLARATION) {
1663                    forScope=new Scope((Scope)variableScope.peek());
1664                    variableScope.push(forScope);
1665                }
1666                for (i=0;i<parts.length;i++)
1667                    processASTBody(parts[i]);
1668                if (forScope!=null)
1669                    variableScope.pop();
1670                break;
1671            }
1672            case FOR_EACH_STATEMENT: {
1673                variableScope.push(((Scope)variableScope.peek()).clone());
1674                for (i=0;i<parts.length;i++)
1675                    processASTBody(parts[i]);
1676                variableScope.pop();
1677                break;
1678            }
1679            case SWITCH_STATEMENT: {
1680                Type switchExpression=TypeClassImpl.getRawType(processASTBody(parts[0]));
1681                boolean enumSwitch=switchExpression instanceof JavaEnum;
1682                Scope oldEnumScope=enumSwitchScope;
1683                
1684                if (enumSwitch) {
1685                    enumSwitchScope=Scope.createFieldScope((JavaEnum)switchExpression);
1686                } else
1687                    enumSwitchScope=null;
1688                processASTBody(parts[1]);
1689                enumSwitchScope=oldEnumScope;
1690                break;
1691            }
1692            case SWITCH_LABEL: {
1693                if (enumSwitchScope!=null)
1694                   variableScope.push(enumSwitchScope);
1695                processASTBody(parts[0]);
1696                if (enumSwitchScope!=null)
1697                   variableScope.pop();
1698                break;
1699            }
1700            case PRIMARY_CLASS: {
1701                Type classType=resolveClassName(parts[0]);
1702
1703                return jclsClass.resolveClass("java.lang.Class", false); // NOI18N
1704
}
1705            case PRIMARY_THIS: {
1706                if (parts!=null)
1707                    td=resolveClassName(parts[0]);
1708                else
1709                    td=currentClass;
1710                break;
1711            }
1712            case INT_LIT:
1713            case FLOAT_LIT:
1714            case BOOL_LIT:
1715            case CHAR_LIT:
1716            case STRING_LIT:
1717            case NULL_LIT: {
1718                String JavaDoc typeText;
1719                Object JavaDoc value=((Token)tree).getValue();
1720                
1721                switch (treeType) {
1722                    case INT_LIT:
1723                        if (value instanceof Long JavaDoc)
1724                            typeText="long"; // NOI18N
1725
else
1726                            typeText="int"; // NOI18N
1727
break;
1728                    case FLOAT_LIT:
1729                        if (value instanceof Double JavaDoc)
1730                            typeText="double"; // NOI18N
1731
else
1732                            typeText="float"; // NOI18N
1733
break;
1734                    case BOOL_LIT:
1735                        typeText="boolean"; // NOI18N
1736
break;
1737                    case CHAR_LIT:
1738                        typeText="char"; // NOI18N
1739
break;
1740                    case STRING_LIT:
1741                        return resolveClass("java.lang.String"); // NOI18N
1742
case NULL_LIT:
1743                        return resolveClass("java.lang.Object"); // NOI18N
1744
default:
1745                        ErrorManager.getDefault().log(ErrorManager.ERROR, "Unknown Literal: "+treeType); // NOI18N
1746
return null;
1747                }
1748                return typeClass.resolve(typeText);
1749            }
1750            case CLASS_INSTANCE_CREATION_EXPRESSION: {
1751                ASTree primaryAST=parts[0];
1752                ASTree classIdAST=parts[2];
1753                ASTree anonymousClass=parts[4];
1754                List parTypes;
1755                NameRef cls = null;
1756                
1757                if (primaryAST==null) {
1758                    td=resolveClassName(classIdAST);
1759                    if (classIdAST.getType()==MULTI_PART_ID) {
1760                        cls = (NameRef) processAST(classIdAST);
1761                    }
1762                } else {
1763                    JavaClass jcls=(JavaClass)resolvePrimaryWithSuper(primaryAST,false, treeType);
1764                    
1765                    if (jcls!=null) {
1766                        Object JavaDoc type=getMemberOf(jcls, (Token)classIdAST);
1767                        
1768                        if (type instanceof JavaClass) {
1769                            td=(JavaClass)type;
1770                            usesType(td, classIdAST);
1771                        }
1772                    }
1773                }
1774                parTypes=getArgumetsTypes(parts[3]); // arguments
1775
if (td!=null) {
1776                    usesMethod(null,(JavaClass)td,parTypes,tree,false);
1777                    if (anonymousClass!=null) {
1778                        createAnonClass(anonymousClass, (JavaClass) td, cls);
1779                    }
1780                }
1781                break;
1782            }
1783            case ARRAY_CREATION_EXPRESSION: {
1784                ASTree elemTypeAST=parts[0];
1785                Type elemType=resolveClassName(elemTypeAST);
1786                
1787                if (elemType!=null) {
1788                    ASTree dimsExprAST=parts[1];
1789                    ASTree dimsAST=parts[2];
1790                    int dims=getDimExprsDimenstion(dimsExprAST);
1791                    Integer JavaDoc dimsVal=(Integer JavaDoc)processAST(dimsAST);
1792                    
1793                    if (dimsVal!=null)
1794                        dims+=dimsVal.intValue();
1795                    if (dims>0) {
1796                        ArrayClass arrayClass=((JavaModelPackage)elemType.refImmediatePackage()).getArray();
1797                   
1798                        for (i=0;i<dims;i++)
1799                            elemType=arrayClass.resolveArray(elemType);
1800                    }
1801                    usesType(elemType,tree);
1802                }
1803                for (i=1;i<parts.length;i++)
1804                    processASTBody(parts[i]);
1805                td=elemType;
1806                break;
1807            }
1808            case FIELD_ACCESS: {
1809                ClassDefinition jcls;
1810                Token fieldId=(Token)parts[2];
1811                String JavaDoc fieldName=(String JavaDoc)fieldId.getValue();
1812                Field field;
1813                boolean hasSuper=parts[1]!=null;
1814                
1815                if (DEBUG) System.out.print("\nField "+fieldName); // NOI18N
1816
jcls=resolvePrimaryWithSuper(parts[0],hasSuper, treeType);
1817                if (jcls==null || jcls instanceof UnresolvedClass)
1818                    return null;
1819                if (DEBUG && jcls instanceof JavaClass) System.out.print(" of class "+jcls.getName()+" is of type "); // NOI18N
1820
field=(Field)Scope.createFieldScope(jcls).lookup(fieldName);
1821                if (field!=null) {
1822                    td=field.getType();
1823                    usesField(field, fieldId);
1824                    storeSemanticInfo(tree,field);
1825                    if (td instanceof JavaClass)
1826                        if (DEBUG) System.out.print(td.getName());
1827                        else if (td instanceof PrimitiveType)
1828                            if (DEBUG) System.out.print(((PrimitiveType)td).getKind());
1829                }
1830                break;
1831            }
1832            case METHOD_INVOCATION: {
1833                ASTree pTree=parts[0];
1834                Token methodId=(Token)parts[3];
1835                String JavaDoc methodName=(String JavaDoc)methodId.getValue();
1836                boolean hasSuper=parts[1]!=null;
1837                ClassDefinition jcls;
1838                List parTypes;
1839                
1840                if (DEBUG) System.out.print("\nMethod "+methodName); // NOI18N
1841
jcls=resolvePrimaryWithSuper(pTree,hasSuper, treeType);
1842                if (jcls!=null)
1843                    if (DEBUG && jcls instanceof JavaClass) System.out.print(" of class "+jcls.getName()); // NOI18N
1844
parTypes=getArgumetsTypes(parts[4]); // arguments
1845
if (jcls!=null) {
1846                    boolean impicitThis= pTree==null && !hasSuper;
1847                    td=usesMethod(methodName,jcls,parTypes,tree,impicitThis);
1848                }
1849                break;
1850            }
1851            case EXPLICIT_CONSTRUCTOR_INVOCATION: {
1852                ASTree pTree=parts[0];
1853                boolean hasSuper=parts[2].getType()==SUPER;
1854                ClassDefinition jcls;
1855                List parTypes;
1856                
1857                jcls=resolvePrimaryWithSuper(pTree,hasSuper, treeType);
1858                if (jcls!=null)
1859                    if (DEBUG && jcls instanceof JavaClass) System.out.print(" of class "+jcls.getName()); // NOI18N
1860
parTypes=getArgumetsTypes(parts[3]); // arguments
1861
if (jcls!=null) {
1862                    td=usesMethod(null,jcls,parTypes,tree,false);
1863                }
1864                break;
1865            }
1866            case ARRAY_ACCESS: {
1867                ASTree arrTypeAST=parts[0];
1868                
1869                td=processASTBody(arrTypeAST); // array type
1870
processASTBody(parts[1]); // expression
1871
if (td!=null) {
1872                    if (td instanceof UnresolvedClass)
1873                        td=null;
1874                    else if (td instanceof Array)
1875                        td=((Array)td).getType();
1876                }
1877                break;
1878            }
1879            case POSTFIX_EXPRESSION: {
1880                ASTree fieldAccess=parts[0];
1881                
1882                td=processASTBody(fieldAccess);
1883                for (i=1;i<parts.length;i++)
1884                    processASTBody(parts[i]);
1885                break;
1886            }
1887            case PREFIX_EXPRESSION:
1888                td=processASTBody(parts[1]);
1889                break;
1890            case COMPLEX_EXPRESSION:
1891                td=processASTBody(parts[0]);
1892                break;
1893            case CAST_EXPRESSION: {
1894                ASTree typeTree=parts[0]; // type
1895
int type=typeTree.getType();
1896                
1897                if (type==POSTFIX_EXPRESSION) {
1898                    typeTree=typeTree.getSubTrees()[0];
1899                    type=typeTree.getType();
1900                }
1901                if (type!=PRIMITIVE_TYPE && type!=MULTI_PART_ID && type!=IDENTIFIER && type!=REFERENCE_TYPE)
1902                    return null; // invalid typecast
1903
td=resolveClassName(typeTree); // type
1904
processASTBody(parts[1]); // expression
1905
break;
1906            }
1907            case INFIX_EXPRESSION: {
1908                int operatorType=parts[1].getType();
1909                Type leftType=processASTBody(parts[0]);
1910                Type rightType;
1911                
1912                if (operatorType==INSTANCEOF)
1913                    rightType=resolveClassName(parts[2]);
1914                else
1915                    rightType=processASTBody(parts[2]);
1916                switch (operatorType) {
1917                    case LT:
1918                    case LTE:
1919                    case GT:
1920                    case GTE:
1921                    case EQ:
1922                    case NEQ:
1923                    case BOOL_AND:
1924                    case BOOL_OR:
1925                    case INSTANCEOF:
1926                        td=typeClass.resolve("boolean"); // NOI18N
1927
break;
1928                    case PLUS:
1929                        // String +
1930
if (leftType instanceof ClassDefinition || rightType instanceof ClassDefinition) {
1931                            td=resolveClass("java.lang.String"); // NOI18N
1932
break;
1933                        }
1934                        // fall through
1935
case MULTI:
1936                    case DIV:
1937                    case MOD:
1938                    case MINUS:
1939                    case AND:
1940                    case OR:
1941                    case XOR:
1942                        td=computeType(leftType,rightType);
1943                        break;
1944                    case L_SHIFT:
1945                    case R_SHIFT:
1946                    case UR_SHIFT:
1947                        if (leftType==null || !"long".equals(leftType.getName())) // NOI18N
1948
td=typeClass.resolve("int"); // NOI18N
1949
else
1950                            td=typeClass.resolve("long"); // NOI18N
1951
break;
1952                    default:
1953                        ErrorManager.getDefault().log(ErrorManager.WARNING,"Unknown operator "+operatorType+" in "+getText(tree));
1954                }
1955                break;
1956            }
1957            case CONDITIONAL_EXPRESSION: {
1958                processASTBody(parts[0]);
1959                td=processASTBody(parts[1]);
1960                processASTBody(parts[2]);
1961                break;
1962            }
1963            case ASSIGNMENT: {
1964                ASTree leftTree=parts[0];
1965                
1966                td=processASTBody(leftTree);
1967                processASTBody(parts[2]);
1968                break;
1969            }
1970            case REFERENCE_TYPE: {
1971                ASTree dim=parts[1];
1972                
1973                td=processASTBody(parts[0]);
1974                if (dim!=null) {
1975                    td=fullType(td,processAST(dim));
1976                }
1977                break;
1978            }
1979            case PRIMITIVE_TYPE:
1980                td=(Type)((SemiPersistentElement)getResource()).resolveType(getPrimitiveType(parts[0]));
1981                break;
1982            case MULTI_PART_ID:
1983            case IDENTIFIER: {
1984                Object JavaDoc type=processMultiPartId(tree,parts);
1985                if (type instanceof Type)
1986                    td=(Type)type;
1987                else
1988                    return null;
1989                if (DEBUG) {
1990                    System.out.print(" is of type "); // NOI18N
1991
if (td instanceof JavaClass)
1992                        System.out.print(td.getName());
1993                    else if (td instanceof PrimitiveType)
1994                        System.out.print(((PrimitiveType)td).getKind());
1995                }
1996                break;
1997            }
1998            default:
1999                if (parts!=null) {
2000                    for (i=0;i<parts.length;i++)
2001                        processASTBody(parts[i]);
2002                }
2003        }
2004        usesType(td,tree);
2005        return td;
2006    }
2007    
2008    private JavaClassImpl createTransientClasses(ASTree tree,JavaClass parent) {
2009        ASTree[] parts;
2010        int treeType;
2011        
2012        if (tree==null)
2013            return null;
2014        parts=tree.getSubTrees();
2015        treeType=tree.getType();
2016        switch (treeType) {
2017            case ENUM_DECLARATION:
2018            case ANNOTATION_TYPE_DECLARATION:
2019            case INTERFACE_DECLARATION:
2020            case CLASS_DECLARATION: {
2021                String JavaDoc name=(String JavaDoc)processAST(parts[1]); // class name
2022
String JavaDoc currentFqn=parent==null?name:parent.getName().concat(".").concat(name); // NOI18N
2023
ASTree body;
2024                JavaClass jcls;
2025                
2026                if (treeType==ENUM_DECLARATION) {
2027                    body=parts[3];
2028                    jcls = enumClass.create(currentFqn, M_ENUM, true);
2029                } else if (treeType==ANNOTATION_TYPE_DECLARATION) {
2030                    body=parts[2];
2031                    jcls = annotClass.create(currentFqn, M_ANNOTATION, true);
2032                } else {
2033                    int mods=0;
2034                    
2035                    if (treeType==INTERFACE_DECLARATION)
2036                        mods=Modifier.INTERFACE;
2037                    body=parts[5];
2038                    jcls = jclsClass.create(currentFqn, mods, null,null, true);
2039                }
2040                if (parent!=null)
2041                    ((JavaClassImpl)jcls).setParentClass((JavaClassImpl)parent);
2042                semanticInfo.put(tree,jcls);
2043                createTransientClasses(body,jcls);
2044                return (JavaClassImpl)jcls;
2045            }
2046            case ANNOTATION_TYPE_BODY_DECLARATIONS:
2047            case ENUM_BODY_DECLARATIONS:
2048            case INTERFACE_MEMBER_DECLARATIONS:
2049            case CLASS_BODY_DECLARATIONS: {
2050                int i;
2051                
2052                for (i=0;i<parts.length;i++)
2053                    createTransientClasses(parts[i],parent);
2054                break;
2055            }
2056        }
2057        return null;
2058    }
2059    
2060    private void createAnonClass(ASTree anonymousClass, JavaClass superClass, NameRef cls) {
2061        FeatureInfo features[];
2062        ClassInfo clsInfo;
2063        Scope classScope=new Scope((Scope)typeScopeInfo.peek());
2064        NameRef[] ifcs=null;
2065        Token firstToken=getToken(anonymousClass.getFirstToken());
2066
2067        if (cls==null) {
2068            cls = (NameRef)SemiPersistentElement.typeToTypeRef(superClass);
2069        }
2070        classScope.addMember(Scope.createMemberTypeScope(superClass,this));
2071        typeScopeInfo.push(classScope);
2072        createTransientClasses(anonymousClass, null);
2073        features=(FeatureInfo[])processAST(anonymousClass,"");
2074        if (superClass.isInterface()) {
2075            ifcs = new NameRef[] {cls};
2076            cls = NameRef.java_lang_Object;
2077        }
2078        clsInfo=new ClassInfo(anonymousClass, anonymousClass.getType(), null, 0, features, cls, ifcs, null, ElementInfo.EMPTY_ANNOTATIONS); // todo-anotation
2079
semanticInfo.put(firstToken,new Scope[]{classScope,(Scope)variableScope.peek()});
2080        typeScopeInfo.pop();
2081        semanticInfo.put(anonymousClass,clsInfo);
2082    }
2083    
2084    private Object JavaDoc processIdentifier(Token identifier) {
2085        Object JavaDoc type=resolveName(identifier);
2086        Variable refField=null;
2087
2088        if (DEBUG) System.out.print("\nID:"+identifier.getValue()); // NOI18N
2089
if (type==null)
2090            return null;
2091        if (type instanceof Variable) {
2092            refField=(Variable)type;
2093            type=refField.getType();
2094            usesField(refField,identifier);
2095        } else {
2096            storeSemanticInfo(identifier,type);
2097            if (type instanceof LocalVarRefInfo) {
2098                type=((LocalVarRefInfo)type).type;
2099            }
2100        }
2101        return type;
2102    }
2103    
2104    private Object JavaDoc processMultiPartId(ASTree tree,ASTree[] parts) {
2105        if (tree.getType()==IDENTIFIER)
2106            return processIdentifier((Token)tree);
2107        
2108        if (tree.getType() == ARRAY_CREATION_EXPRESSION) {
2109            ASTree elemTypeAST=parts[0];
2110            Type elemType=resolveClassName(elemTypeAST);
2111
2112            if (elemType!=null) {
2113                ASTree dimsExprAST=parts[1];
2114                ASTree dimsAST=parts[2];
2115                int dims=getDimExprsDimenstion(dimsExprAST);
2116                Integer JavaDoc dimsVal=(Integer JavaDoc)processAST(dimsAST);
2117
2118                if (dimsVal!=null)
2119                    dims+=dimsVal.intValue();
2120                if (dims>0) {
2121                    ArrayClass arrayClass=((JavaModelPackage)elemType.refImmediatePackage()).getArray();
2122
2123                    for (int i=0; i<dims; i++)
2124                        elemType=arrayClass.resolveArray(elemType);
2125                }
2126                usesType(elemType,tree);
2127            }
2128            for (int i=1;i<parts.length;i++)
2129                processASTBody(parts[i]);
2130            return elemType;
2131        }
2132        
2133        ASTree parent=parts[0];
2134        Object JavaDoc type;
2135        Token member=(Token)parts[1];
2136        Variable refField=null;
2137        
2138        if (parent!=null) {
2139            type=processMultiPartId(parent,parent.getSubTrees());
2140            if (!(type instanceof PrimitiveType)) {
2141                if (DEBUG) System.out.print("."+member.getValue()); // NOI18N
2142
type=getMemberOf(type,member);
2143            } else
2144                type=null;
2145        } else {
2146            type=processIdentifier(member);
2147        }
2148        if (type!=null) {
2149            if (type instanceof Field) {
2150                refField=(Field)type;
2151                type=refField.getType();
2152                usesField(refField,member);
2153            } else {
2154                storeSemanticInfo(member,type);
2155                if (type instanceof LocalVarRefInfo) {
2156                    type=((LocalVarRefInfo)type).type;
2157                }
2158            }
2159            if (refField!=null) {
2160                usesField(refField,tree);
2161            } else
2162                storeSemanticInfo(tree,type);
2163        }
2164        processASTBody(parts[2]);
2165        return type;
2166    }
2167
2168    private Object JavaDoc getMemberOf(Object JavaDoc element,Token id) {
2169        String JavaDoc member=(String JavaDoc)id.getValue();
2170        
2171        if (element instanceof ClassDefinition) {
2172            ClassDefinition jcls=(ClassDefinition)element;
2173            Object JavaDoc memberFeature=null;
2174            
2175            if (!resolveClassName) {
2176                memberFeature=Scope.createFieldScope(jcls).lookup(member);
2177            }
2178            if (memberFeature==null) {
2179                memberFeature=Scope.createMemberTypeScope(jcls, this).lookup(member);
2180                if (jcls!=null && memberFeature instanceof String JavaDoc)
2181                    memberFeature=resolveClass((String JavaDoc)memberFeature);
2182            }
2183            if (memberFeature==null && resolveClassName) { // Unresolved class
2184
memberFeature=jclsClass.resolve(jcls.getName()+"."+member);
2185            }
2186            return memberFeature;
2187        }
2188        if (element instanceof JavaPackage) {
2189            String JavaDoc fqn=((JavaPackage)element).getName().concat(".").concat(member); // NOI18N
2190
JavaClass jcls;
2191            
2192            jcls=resolveClass(fqn);
2193            if (jcls!=null)
2194                return jcls;
2195            return getPackage(fqn);
2196        }
2197        if (element instanceof Array) {
2198            if (member.equals("length")) // NOI18N
2199
return typeClass.resolve("int"); // NOI18N
2200
return null;
2201        }
2202        return null;
2203    }
2204    
2205    private Object JavaDoc resolveName(Token id) {
2206        Object JavaDoc je;
2207        Scope typeScope;
2208        String JavaDoc simpleName=(String JavaDoc)id.getValue();
2209        
2210        if (!resolveClassName) {
2211            Scope varScope=(Scope)variableScope.peek();
2212        
2213            je=varScope.lookup(simpleName);
2214            if (je!=null)
2215                return je;
2216        }
2217        je=staticImpScope.lookup(simpleName);
2218        if (je!=null)
2219            return je;
2220        typeScope=(Scope)typeScopeInfo.peek();
2221        je=typeScope.lookup(simpleName);
2222        if (je!=null && je instanceof String JavaDoc)
2223            je=resolveClass((String JavaDoc)je);
2224        if (je==null)
2225            je=resolveClass(simpleName);
2226        if (je!=null)
2227            return je;
2228        je=getPackage(simpleName);
2229        if (je!=null)
2230            return je;
2231        if (DEBUG)
2232            System.out.println("Unresolved class: "+simpleName); // NOI18N
2233
return typeClass.resolve(simpleName); // simpleName unresolved
2234
}
2235        
2236    private ClassDefinition resolvePrimaryWithSuper(ASTree primaryTree,boolean hasSuper, int parentTreeType) {
2237        ClassDefinition jcls;
2238        
2239        if (primaryTree!=null) {
2240            Type type;
2241            
2242            if (!hasSuper || parentTreeType==EXPLICIT_CONSTRUCTOR_INVOCATION)
2243                type=processASTBody(primaryTree);
2244            else
2245                type=resolveClassName(primaryTree);
2246            if (type instanceof ClassDefinition)
2247                jcls=(ClassDefinition)type;
2248            else {
2249                if (DEBUG)
2250                    System.out.println("Strange type: "+type+" "+type.getName()); // NOI18N
2251
jcls=jclsClass.resolveClass("java.lang.Object",false); // NOI18N
2252
}
2253        }
2254        else
2255            jcls=currentClass;
2256        if (hasSuper && jcls!=null) {
2257            jcls=jcls.getSuperClass();
2258        }
2259        return jcls;
2260    }
2261    
2262    private List getArgumetsTypes(ASTree argListTree) {
2263        List parTypes=new ArrayList();
2264        
2265        if (argListTree!=null) {
2266            if (argListTree.getType()==ARGUMENT_LIST) {
2267                ASTree argsAST[]=argListTree.getSubTrees();
2268                int i;
2269                
2270                for (i=0;i<argsAST.length;i++)
2271                    addArgumentToList(parTypes,argsAST[i]);
2272            }
2273            else
2274                addArgumentToList(parTypes,argListTree);
2275        }
2276        return parTypes;
2277    }
2278    
2279    private Type resolveClassName(ASTree tree) {
2280        Type type;
2281
2282        resolveClassName=true;
2283        type=processASTBody(tree);
2284        resolveClassName=false;
2285        return type;
2286    }
2287    
2288    private void addArgumentToList(List list,ASTree argExpr) {
2289        Type argType=processASTBody(argExpr);
2290        
2291        if (argType==null)
2292            argType=typeClass.resolve("void"); // NOI18N
2293
list.add(argType);
2294    }
2295    
2296    
2297    private int getDimExprsDimenstion(ASTree dimexprs) {
2298        if (dimexprs==null)
2299            return 0;
2300        if (dimexprs.getType()==DIM_EXPRS)
2301            return dimexprs.getSubTrees().length;
2302        return 1;
2303    }
2304    
2305    private Type computeType(Type left,Type right) {
2306        if (left==null) return right;
2307        if (right==null) return left;
2308        if ((left instanceof PrimitiveType) && (right instanceof PrimitiveType)) {
2309            PrimitiveTypeKind leftKind=((PrimitiveType)left).getKind();
2310            PrimitiveTypeKind rightKind=((PrimitiveType)right).getKind();
2311            
2312            if (leftKind.equals(PrimitiveTypeKindEnum.DOUBLE)) return left;
2313            if (rightKind.equals(PrimitiveTypeKindEnum.DOUBLE)) return right;
2314            if (leftKind.equals(PrimitiveTypeKindEnum.FLOAT)) return left;
2315            if (rightKind.equals(PrimitiveTypeKindEnum.FLOAT)) return right;
2316            if (leftKind.equals(PrimitiveTypeKindEnum.LONG)) return left;
2317            if (rightKind.equals(PrimitiveTypeKindEnum.LONG)) return right;
2318            return typeClass.resolve("int"); // NOI18N
2319
}
2320        ErrorManager.getDefault().log(ErrorManager.WARNING,"Invalid types "+left.getName()+" "+right.getName());
2321        return null;
2322    }
2323    
2324    private void usesField(Variable field,ASTree id) {
2325        storeSemanticInfo(id,field);
2326    }
2327    
2328    private void usesType(Type td,ASTree id) {
2329        storeSemanticInfo(id,td);
2330    }
2331    
2332    private CallableFeature findMethod(ClassDefinition jcls,String JavaDoc name,List parameters) {
2333        if (jcls!=null && !(jcls instanceof UnresolvedClass)) {
2334            Object JavaDoc methods=null;
2335            
2336            if (name==null) { // construtor
2337
Object JavaDoc features[]=jcls.getContents().toArray();
2338                List constructors=new ArrayList();
2339                
2340                for (int i=0;i<features.length;i++) {
2341                    Object JavaDoc feature=features[i];
2342                    
2343                    if (feature instanceof Constructor) {
2344                        constructors.add(feature);
2345                        methods=feature;
2346                    }
2347                }
2348                if (constructors.size()>1)
2349                    methods=constructors;
2350            } else {
2351                MethodScope methodScope=Scope.createMethodScope(jcls);
2352            
2353                methods=methodScope.lookup(name);
2354            }
2355            if (methods instanceof List) {
2356                List methodList=(List)methods;
2357                CallableFeature[] methodArr=(CallableFeature[])methodList.toArray(new CallableFeature[methodList.size()]);
2358                CallableFeature closest=methodArr[0];
2359                Type[] parTypes=(Type[])parameters.toArray(new Type[parameters.size()]);
2360                int parDiff=computeParDiff(closest,parTypes.length);
2361                int parDistance=-1;
2362                int i;
2363                boolean isAccessible=false;
2364                
2365                if (parDiff==0)
2366                    isAccessible=isAccessible(closest);
2367                for (i=1;i<methodArr.length;i++) {
2368                    int localParDist;
2369                    CallableFeature candidate=methodArr[i];
2370                    int localParDiff=computeParDiff(candidate,parTypes.length);
2371
2372                    if (localParDiff>0) {
2373                        if (localParDiff<parDiff) {
2374                            parDiff=localParDiff;
2375                            closest=candidate;
2376                        }
2377                        continue;
2378                    }
2379                    if (parDiff>0) {
2380                        parDiff=0;
2381                        closest=candidate;
2382                        isAccessible=isAccessible(candidate);
2383                        continue;
2384                    }
2385                    if (!isAccessible(candidate))
2386                        continue;
2387                    if (!isAccessible) {
2388                        closest=candidate;
2389                        isAccessible=true;
2390                        continue;
2391                    }
2392                    if (parDistance==-1) {
2393                        parDistance=isApplicable(closest,parTypes);
2394                        if (parDistance==0)
2395                            return closest;
2396                    }
2397                    localParDist=isApplicable(candidate,parTypes);
2398                    if (localParDist==0)
2399                        return candidate;
2400                    if (localParDist==Integer.MAX_VALUE)
2401                        continue;
2402                    if (localParDist<parDistance) {
2403                        parDistance=localParDist;
2404                        closest=candidate;
2405                        continue;
2406                    }
2407                    if (localParDist==parDistance) {
2408                        int canDiff=isApplicable(closest,candidate);
2409                        
2410                        if (canDiff==Integer.MAX_VALUE)
2411                            continue;
2412                        if (canDiff>0) {
2413                            closest=candidate;
2414                            continue;
2415                        }
2416                        if (!Modifier.isAbstract(candidate.getModifiers()) && Modifier.isAbstract(closest.getModifiers())) {
2417                            closest=candidate;
2418                            continue;
2419                        }
2420                    }
2421                }
2422                return closest;
2423            }
2424            return (CallableFeature)methods;
2425        }
2426        return null;
2427    }
2428    
2429    private int isApplicable(CallableFeature method,CallableFeature bestSoFar) {
2430        List parTypes=new ArrayList();
2431        Object JavaDoc[] pars=bestSoFar.getParameters().toArray();
2432        
2433        for (int i=0;i<pars.length;i++) {
2434            Parameter p=(Parameter)pars[i];
2435            
2436            parTypes.add(p.getType());
2437        }
2438        return isApplicable(method,(Type[])parTypes.toArray(new Type[parTypes.size()]));
2439    }
2440    
2441    private int isApplicable(CallableFeature method,Type[] pars) {
2442        Object JavaDoc mpars[]=method.getParameters().toArray();
2443        int p,diff=0;
2444        boolean varArg=false;
2445        Type methodType=null;
2446        
2447        for (p=0;p<pars.length;p++) {
2448            int localDiff;
2449            
2450            if (p<mpars.length) {
2451                Parameter par=(Parameter)mpars[p];
2452                methodType=par.getType();
2453            }
2454            localDiff=subType(pars[p],methodType);
2455            if (localDiff==Integer.MAX_VALUE)
2456                return localDiff;
2457            diff+=localDiff;
2458        }
2459        return diff;
2460    }
2461    
2462    private int subType(Type sub,Type type) {
2463        if (sub==type)
2464            return 0;
2465        if (type.getName().equals(sub.getName()))
2466            return 0;
2467        if (sub instanceof ClassDefinition && type instanceof ClassDefinition)
2468            return ((ClassDefinition)sub).isSubTypeOf((ClassDefinition)type)?1:Integer.MAX_VALUE;
2469        return Integer.MAX_VALUE;
2470    }
2471    
2472    private int computeParDiff(CallableFeature method,int parNum) {
2473        Object JavaDoc[] mpars=method.getParameters().toArray();
2474        int plen=mpars.length;
2475        boolean varArg=false;
2476        
2477        if (plen>0) {
2478            Parameter lastPar=(Parameter)mpars[plen-1];
2479            varArg=lastPar.isVarArg();
2480        }
2481        if (varArg && (plen<parNum || plen==(parNum+1)))
2482            return 0;
2483        return Math.abs(parNum-plen);
2484    }
2485    
2486    private boolean isAccessible(CallableFeature method) {
2487        int mods=method.getModifiers();
2488        boolean samePackage;
2489        
2490        if (Modifier.isPublic(mods))
2491            return true;
2492        if (Modifier.isPrivate(mods)) {
2493            return method.getResource().equals(getResource());
2494        }
2495        samePackage=method.getResource().getPackageName().equals(getResource().getPackageName());
2496        if (!Modifier.isProtected(mods))
2497            return samePackage;
2498        //protected
2499
if (samePackage)
2500            return true;
2501        return currentClass.isSubTypeOf(method.getDeclaringClass());
2502    }
2503    
2504    private Type usesMethod(String JavaDoc name,ClassDefinition desc,List parameters,ASTree id,boolean implicitThis) {
2505        CallableFeature ref=findMethod(desc,name,parameters);
2506        Type type=null;
2507        
2508        if (ref==null && implicitThis && desc!=null) {
2509            if (desc instanceof JavaClass)
2510                type=usesMethod(name,((JavaClass)desc).getDeclaringClass(),parameters,id,true);
2511            else {
2512                Element immComposite=desc;
2513                
2514                do {
2515                    immComposite=(Element)immComposite.refImmediateComposite();
2516                } while (immComposite!=null && !(immComposite instanceof ClassDefinition));
2517                type=usesMethod(name,(ClassDefinition)immComposite,parameters,id,true);
2518            }
2519            if (type==null && name!=null) { // static import
2520
String JavaDoc className=(String JavaDoc)staticImpScope.lookup(name.concat("(")); // NOI18N
2521

2522                if (className!=null) {
2523                    JavaClass jcls=resolveClass(className);
2524                    
2525                    if (jcls!=null)
2526                        return usesMethod(name,jcls,parameters,id,false);
2527                }
2528            }
2529            return type;
2530        }
2531        if (DEBUG) {
2532            if (desc instanceof JavaClass) System.out.print("Class "+desc.getName()+"."+name+"()"); // NOI18N
2533
if (ref!=null)
2534                System.out.println(" resolved to "+ref.getDeclaringClass().getName()+"."+ref.getName()+"()"); // NOI18N
2535
else
2536                System.out.println(" unresloved"); // NOI18N
2537
}
2538        if (ref!=null) {
2539            storeSemanticInfo(id,ref);
2540            type=ref.getType();
2541        }
2542        return type;
2543    }
2544
2545    private void storeSemanticInfo(ASTree tree,Object JavaDoc ref) {
2546        Object JavaDoc indirectRef;
2547        
2548        if (tree==null || ref==null || semanticInfo.get(tree)!=null)
2549            return;
2550        if (ref instanceof Element)
2551            indirectRef=getElementId((Element)ref);
2552        else
2553            indirectRef=ref;
2554        semanticInfo.put(tree,indirectRef);
2555    }
2556
2557    private Object JavaDoc getElementId(Element el) {
2558        String JavaDoc name=null;
2559        
2560        if (el instanceof ParameterizedType) {
2561            return getElementId(((ParameterizedType)el).getDefinition());
2562        }
2563        if (el instanceof ParameterizedTypeImpl.Wrapper) {
2564            ParameterizedTypeImpl.Wrapper w=(ParameterizedTypeImpl.Wrapper)el;
2565            return getElementId((Element)w.getWrappedObject());
2566        }
2567        // todo: MaM = make this code cleaner (these if statements are hard to read), should add LocalRef for referencing local classes
2568
if ((el instanceof UnresolvedClass) || (el instanceof TypeParameter) || (el instanceof Type && (!(el instanceof ClassDefinition && el instanceof MetadataElement && ((MetadataElement) el).isTransient())))) {
2569            SemiPersistentElement spel=(SemiPersistentElement)currentClass;
2570            
2571            if (spel==null)
2572                spel=(SemiPersistentElement)getResource();
2573            return spel.typeToTypeRef((Type)el);
2574        }
2575        if (el instanceof Parameter || (el instanceof MetadataElement && ((MetadataElement)el).isTransient())) {
2576            return "^".concat(el.refMofId()); // NOI18N
2577
}
2578        if (el instanceof NamedElement) {
2579            name=((NamedElement)el).getName();
2580        }
2581        if (el instanceof JavaPackage) {
2582            return "*".concat(name); // NOI18N
2583
}
2584        if (el instanceof Field) {
2585            Field f=(Field)el;
2586            return new FieldRefInfo((TypeRef)getElementId(f.getDeclaringClass()),name,f.refMofId());
2587        }
2588        if (el instanceof CallableFeature) {
2589            CallableFeature fe=(CallableFeature)el;
2590            Object JavaDoc[] pars=fe.getParameters().toArray();
2591            TypeRef parTypes[]=new TypeRef[pars.length];
2592            int i;
2593            
2594            for (i=0;i<parTypes.length;i++) {
2595                Parameter p=(Parameter)pars[i];
2596                
2597                parTypes[i]=(TypeRef)getElementId(p.getType());
2598            }
2599            return new CallableRefInfo((TypeRef)getElementId(fe.getDeclaringClass()),name,parTypes,fe.refMofId());
2600        }
2601        JMManager.getLog().log("Invalid type "+el); // NOI18N
2602
if (el instanceof NamedElement)
2603            JMManager.getLog().log("Name "+name); // NOI18N
2604
return null;
2605    }
2606    
2607    private static class FieldRefInfo {
2608        private TypeRef declClass;
2609        private String JavaDoc name;
2610        private String JavaDoc mofid;
2611        
2612        FieldRefInfo(TypeRef decl,String JavaDoc n,String JavaDoc id) {
2613            declClass=decl;
2614            name=n;
2615            mofid=id;
2616        }
2617    }
2618    
2619    private static class CallableRefInfo extends FieldRefInfo {
2620        private TypeRef[] parTypes;
2621        
2622        CallableRefInfo(TypeRef decl,String JavaDoc n,TypeRef[] pt,String JavaDoc id) {
2623            super(decl,n,id);
2624            parTypes=pt;
2625        }
2626    }
2627    
2628    private static class LocalVarRefInfo {
2629        private Type type;
2630        private ASTree varDeclAST;
2631        private Variable var;
2632        
2633        LocalVarRefInfo(ASTree decl,Type t) {
2634            varDeclAST=decl;
2635            type=t;
2636        }
2637    }
2638    
2639    private static class SuperInfo {
2640        private JavaClass superClass;
2641        private List interfaces;
2642        
2643        SuperInfo(JavaClass jcls,List ifaces) {
2644            superClass=jcls;
2645            interfaces=ifaces;
2646        }
2647    }
2648    
2649    private static class ModifiersInfo {
2650        private int modifiers;
2651        private AnnotationInfo[] annotations;
2652        
2653        ModifiersInfo(int mods,AnnotationInfo[] anns) {
2654            modifiers=mods;
2655            annotations=anns;
2656        }
2657    }
2658 }
2659
Popular Tags