Source Code Cross Referenced for IDChain.java in  » IDE » tIDE » tide » classsyntax » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE » tIDE » tide.classsyntax 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package tide.classsyntax;
0002:
0003:        import tide.syntaxtree.ParserResult;
0004:        import japa.parser.ast.ImportDeclaration;
0005:        import snow.html.HTMLUtils;
0006:        import tide.utils.ParsedID;
0007:        import tide.sources.FileItem;
0008:        import snow.texteditor.*;
0009:        import tide.syntaxtree.SearchFunctions;
0010:        import tide.sources.TypeLocator;
0011:        import tide.project.ClassFilesManager;
0012:        import tide.editor.MainEditorFrame;
0013:        import tide.project.ProjClass;
0014:        import tide.utils.SyntaxUtils;
0015:        import tide.syntaxtree.SimplifiedSyntaxTree2;
0016:        import javaparser.*;
0017:        import java.util.*;
0018:        import java.lang.reflect.*;
0019:        import java.util.regex.Pattern;
0020:
0021:        /** Resolves the types for a parsed ID chain as in
0022:         *  <pre>  "frame.add("  => "javax.swing.jframe" and method "add"</pre>
0023:         * Is called for completion purposes with an ID parsed before a "." or a "(".
0024:         *
0025:         * TODO: lazy search for local variables when no syntax tree available.
0026:         */
0027:        public final class IDChain {
0028:            // also contains info about preceeding item ("new", " ", "(", "{", "import", "\""...)
0029:            public final ParsedID pid;
0030:            public final FileItem source;
0031:            // let know what was pressed to trigger this resolver. The pid cannot know it because it
0032:            // has not been entered yet in the document. In case of "(" this allow to know that we
0033:            // are in a method or a constructor at the last chain element
0034:            public final String enteredItem;
0035:            public final SimpleDocument doc;
0036:            public final int posInSource;
0037:
0038:            private TypeInterface deepestTypeAtPos = null;
0039:            private String[] splittedChain;
0040:
0041:            // the recognized chain
0042:            public final List<IDChainElement> chain = new ArrayList<IDChainElement>();
0043:            private boolean isValid = true;
0044:
0045:            private final SingleClassLoader scl;
0046:
0047:            private int numberOfEltsTakenAsFirst = 1;
0048:            private final boolean constructorMode; // iff new preceeds
0049:            private boolean isConstructorAlreadyFound = false; // only one can appear, for example in "new Throwable().printStackTrace()", the second is a method !
0050:
0051:            /** @param enteredItem  is "." or "(" it allow to determine if the last element is a field or a method or constructor.
0052:             *   because the elt is not already in the document and then not in pid.
0053:             */
0054:            public IDChain(ParsedID pid, FileItem source, SimpleDocument doc,
0055:                    int posInSource, String enteredItem, SingleClassLoader scl) {
0056:                this .pid = pid;
0057:                this .source = source;
0058:                this .doc = doc;
0059:                this .posInSource = posInSource;
0060:                this .enteredItem = enteredItem;
0061:                this .scl = scl;
0062:
0063:                this .constructorMode = pid.precedingItem.equals("new");
0064:
0065:                //System.out.println("\n=== Parsing "+pid);
0066:
0067:                // parse the chain...
0068:                parseChain();
0069:            }
0070:
0071:            /** Parses the whole chain.
0072:             */
0073:            private void parseChain() {
0074:                String idchainStr = pid.identifierChain;
0075:                if (enteredItem.equals("(")) {
0076:                    idchainStr = idchainStr + "()";
0077:                }
0078:
0079:                splittedChain = idchainStr.split(Pattern.quote(".")); // BAD, do it manually...
0080:
0081:                int n = 0;
0082:                IDChainElement ide;
0083:
0084:                if (pid.precedingItem != null
0085:                        && pid.precedingItem.endsWith("\"")) {
0086:                    System.out.println("special string mode: chain="
0087:                            + splittedChain.length);
0088:                    ide = new IDChainElement(this , "java.lang.String", null,
0089:                            false, true); // equals "new String(""))."
0090:                    chain.add(ide);
0091:                    ide.setTypeWithParamsAndResolve("java.lang.String");
0092:                    //ide.setIsDirectClassCall();
0093:                    isValid = true;
0094:                }
0095:
0096:                il: for (String idi : splittedChain) {
0097:                    if (idi.trim().length() == 0)
0098:                        continue il; // occurs !
0099:
0100:                    // fetch preparsed type vars
0101:                    String typeVars = null;
0102:                    if (idi.indexOf("{TV:") >= 0) {
0103:                        int st = idi.indexOf("{TV:");
0104:                        int en = idi.indexOf('}', st + 1);
0105:                        if (en >= 0) {
0106:                            String tn = idi.substring(st + 4, en);
0107:
0108:                            typeVars = pid.typeVariablesReplacements.get(tn); // without < >
0109:                            debugOut("typeVars=" + typeVars + " for " + tn
0110:                                    + " in " + idi + ", map="
0111:                                    + pid.typeVariablesReplacements);
0112:                            // remove the type variables from the idi
0113:                            idi = idi.substring(0, st) + idi.substring(en + 1);
0114:                            //debugOut("idi="+idi);
0115:                        }
0116:                    }
0117:
0118:                    // fetch preparsed class cast info
0119:                    boolean isClassCast = false; // since [April2007]
0120:                    if (idi.startsWith("{C:")) {
0121:                        int st = idi.indexOf("{C:");
0122:                        int en = idi.indexOf('}', st + 1);
0123:                        String cn = pid.castsReplacements.get(idi.substring(
0124:                                st + 3, en));
0125:
0126:                        isClassCast = true;
0127:                        idi = idi.substring(0, st) + cn + idi.substring(en + 1);
0128:                    }
0129:
0130:                    // sometimes (when type vars are in casts), a cast remains in idi
0131:                    if (idi.indexOf('<') > 0) {
0132:                        if (typeVars != null) {
0133:                            new Throwable("strange " + idi
0134:                                    + " already has type vars " + typeVars)
0135:                                    .printStackTrace();
0136:                        }
0137:                        int st = idi.indexOf('<');
0138:                        int en = SyntaxUtils
0139:                                .matchingEndBrace(idi, st, '<', '>');
0140:                        if (en > 0) {
0141:                            typeVars = idi.substring(st + 1, en);
0142:                            idi = idi.substring(0, st) + idi.substring(en + 1);
0143:                        }
0144:                    }
0145:
0146:                    n++;
0147:                    debugOut("Parse id element: " + idi
0148:                            + (isClassCast ? ", iscast" : ""));
0149:                    if (!SyntaxUtils.isValidIdentifier(idi)) {
0150:                        isValid = false;
0151:                        debugOut("### not valid id: " + idi);
0152:                        //new Throwable().printStackTrace();
0153:                        return;
0154:                    }
0155:
0156:                    ide = null;
0157:                    if (n == 1) // first
0158:                    {
0159:                        // maybe take more than one idi ! when absolute refs as in "javax.swing.JFrame"
0160:                        boolean enforceMethod = (n >= splittedChain.length && enteredItem
0161:                                .equals("("));
0162:                        ide = locateFirstElement(idi, enforceMethod, false,
0163:                                isClassCast); // no approximation here !
0164:                    } else {
0165:                        // ignore because was taken in account in the first elt.
0166:                        if (n <= numberOfEltsTakenAsFirst) {
0167:                            debugOut("Ignore " + idi);
0168:                            continue il;
0169:                        }
0170:
0171:                        //
0172:                        boolean enforceMethod = (n + numberOfEltsTakenAsFirst
0173:                                - 1 >= splittedChain.length && enteredItem
0174:                                .equals("("));
0175:
0176:                        ide = locateNextElement(idi, enforceMethod, isClassCast);
0177:                    }
0178:
0179:                    if (ide == null) {
0180:                        debugOut("### ide is null => not valid chain");
0181:                        isValid = false;
0182:                        return;
0183:                    }
0184:
0185:                    if (typeVars != null) {
0186:                        ide.setTypeParameters(typeVars);
0187:                    }
0188:
0189:                    chain.add(ide);
0190:
0191:                } // end of chain loop
0192:            }
0193:
0194:            /** @return null if none. Used in the completion and popups.
0195:             */
0196:            public IDChainElement getLastChainComponent() {
0197:                if (chain.isEmpty())
0198:                    return null;
0199:                return chain.get(chain.size() - 1);
0200:            }
0201:
0202:            /** Field is also used for direct class call.
0203:             *  Method is also used for Constructors.
0204:             */
0205:            public FileItem getDeclaringClassForMethodOrField(
0206:                    IDChainElement methodOrField) {
0207:                if (methodOrField.getKind() == ElementKind.Method) {
0208:                    return getDeclaringClassForMethod(methodOrField);
0209:                } else if (methodOrField.getKind() == ElementKind.Field) {
0210:                    return getDeclaringClassForField(methodOrField);
0211:                }
0212:                return null;
0213:            }
0214:
0215:            /** May return null if not found or on errors.
0216:             *  reference field receives the reflected object, if found.
0217:             *  The field may be a direct inner class call, as in test.A$CCC  [Feb2008]
0218:             */
0219:            public FileItem getDeclaringClassForField(final IDChainElement field) {
0220:                if (field.reflectedObject != null) {
0221:                    if (field.reflectedObject instanceof  Field) {
0222:                        Field f = (Field) field.reflectedObject;
0223:                        try {
0224:                            return this .locateTypeExact(f.getDeclaringClass()
0225:                                    .getName());
0226:                        } catch (Exception ex) {
0227:                            ex.printStackTrace();
0228:                        }
0229:                    } else {
0230:                        debugOut("ERR: not a field: " + field);
0231:                    }
0232:                }
0233:
0234:                RType ret = new RType();
0235:
0236:                int pos = chain.indexOf(field);
0237:
0238:                // simple case, the source where this chain was issued is the class declaring the method or field
0239:                if (pos == 0 || chain.isEmpty()) {
0240:                    ret.fitem = source;
0241:                } else if (pos == -1) {
0242:                    // called from IDChainElement, if not already added, this is the previous = last component
0243:                    IDChainElement parent = chain.get(chain.size() - 1);
0244:                    ret.copyFrom(parent.resolvedType_);
0245:                } else {
0246:                    IDChainElement parent = chain.get(pos - 1);
0247:                    ret.copyFrom(parent.resolvedType_);
0248:                }
0249:
0250:                try {
0251:                    if (!ret.isResolved()) {
0252:                        throw new NullPointerException(
0253:                                "getDeclaringClassForField(" + field.getName()
0254:                                        + ") is not resolved (pos=" + pos
0255:                                        + ", " + field + ")");
0256:                    }
0257:
0258:                    Class cla = ret.rclass;
0259:                    if (cla == null) {
0260:                        cla = scl.findClass(ret.fitem.getJavaName());
0261:                    }
0262:
0263:                    if (cla != null) {
0264:                        for (Field f : cla.getFields()) {
0265:                            if (f.getName().startsWith(field.getName())) {
0266:                                // remember !
0267:                                field.reflectedObject = f;
0268:                                return this .locateTypeExact(f
0269:                                        .getDeclaringClass().getName());
0270:                            }
0271:                        }
0272:
0273:                        // not found, try inner classes
0274:                        for (Class ci : cla.getDeclaredClasses()) {
0275:                            System.out.println("Looking at " + ci.getName());
0276:                            if (ci.getName().endsWith(field.getName())) {
0277:                                System.out.println("Found !");
0278:                                field.resolvedType_.rclass = ci; // ??
0279:                                field.setIsDirectClassCall(); // yeah, it solves some wrong a-priori suppositions
0280:                                // returns null, no problem in case of inner classes, because they are not FileItem's...
0281:                            }
0282:                        }
0283:
0284:                        // declared fields... and in super (TODO...)
0285:                        debugOut("getDeclaringClassForField: "
0286:                                + field.getName() + " not found in " + cla);
0287:                        debugOut("  rtype=" + field.resolvedType_);
0288:                        debugOut("  ret = " + ret);
0289:                        //new Throwable().printStackTrace();
0290:
0291:                    }
0292:                } catch (Exception e) {
0293:                    e.printStackTrace();
0294:                } catch (Error e) {
0295:                    e.printStackTrace();
0296:                } // VerifyError
0297:
0298:                return ret.fitem;
0299:            }
0300:
0301:            /** The class declaring the method, taken from the previous chain component.
0302:             *  [Mar2008]: was not ok for method that has a field as parent...
0303:             */
0304:            public FileItem getDeclaringClassForMethod(IDChainElement method) {
0305:                if (method.reflectedObject != null) {
0306:                    if (method.reflectedObject instanceof  Method) {
0307:                        Method met = (Method) method.reflectedObject;
0308:                        try {
0309:                            return this .locateTypeExact(met.getDeclaringClass()
0310:                                    .getName());
0311:                        } catch (Exception ex) {
0312:                            ex.printStackTrace();
0313:                        }
0314:                    } else {
0315:                        debugOut("ERR: REF not a method: " + method);
0316:                    }
0317:                }
0318:
0319:                FileItem fit = null;
0320:
0321:                IDChainElement parent = null;
0322:                int pos = chain.indexOf(method);
0323:
0324:                // simple case, the source where this chain was issued is the class declaring the method or field
0325:                if (pos == 0 || chain.isEmpty()) {
0326:                    fit = source;
0327:                } else if (pos == -1) {
0328:                    // called from IDChainElement, if not already added, this is the previous = last component
0329:                    parent = chain.get(chain.size() - 1);
0330:                    fit = parent.resolvedType_.fitem;
0331:                } else {
0332:                    parent = chain.get(pos - 1);
0333:                    //System.out.println("Parent is "+parent);
0334:                    //System.out.println("Parent type = "+parent.resolvedType_);
0335:                    fit = parent.resolvedType_.fitem;
0336:                }
0337:
0338:                Class cla = null;
0339:                if (parent != null) {
0340:                    cla = parent.resolvedType_.rclass;
0341:                }
0342:
0343:                if (fit != null && cla == null) {
0344:                    try {
0345:                        cla = scl.findClass(fit.getJavaName()); // not loading !
0346:                    } catch (Exception e) {
0347:                        e.printStackTrace();
0348:                    } catch (Error e) {
0349:                        e.printStackTrace();
0350:                    } // sometimes VerifyError !!
0351:                }
0352:
0353:                if (cla != null) {
0354:                    try {
0355:                        //ClassUtils.lookAtSource(cla);   // prints signatures, ...
0356:                        if (cla != null) {
0357:                            for (Method m : cla.getMethods()) {
0358:                                if (m.getName().startsWith(method.getName())) {
0359:                                    // remember
0360:                                    method.reflectedObject = m;
0361:                                    return this .locateTypeExact(m
0362:                                            .getDeclaringClass().getName());
0363:                                }
0364:                            }
0365:                        }
0366:                    } catch (Exception e) {
0367:                        e.printStackTrace();
0368:                    } catch (Error e) {
0369:                        e.printStackTrace();
0370:                    } // sometimes VerifyError !!
0371:                } else {
0372:                    System.out.println("NO FileItem for method " + method);
0373:                    //new Throwable().printStackTrace();
0374:                }
0375:
0376:                return fit;
0377:            }
0378:
0379:            /** use for later types (not the first of a chain).
0380:             *  they may be located outside imports scope, for example
0381:             *  when resolving a method declared in some parent.
0382:             */
0383:            private FileItem locateTypeGeneralApprox(String name) {
0384:                return TypeLocator.searchTypeForName(name, true, true); // ignore case & ends with
0385:            }
0386:
0387:            /** To use when one knows the type (class) name exactely, as in javax.swing.JFrame
0388:             */
0389:            private FileItem locateTypeExact(String exactJavaName) {
0390:                return TypeLocator.locateQuick(exactJavaName);
0391:            }
0392:
0393:            /** To use for the first element (that lies in the source).
0394:             */
0395:            public FileItem locateTypeUsingImports(final String name) {
0396:                final String _name = SyntaxUtils.removeAllArrayPartsAtEnd(name);
0397:
0398:                FileItem it = TypeLocator.locateUsingImports(source, _name);
0399:
0400:                if (it == null) {
0401:                    //NO return locateTypeGeneralApprox(name);
0402:                }
0403:
0404:                return it;
0405:                /*
0406:                 // convenience, use the approximate search for this.
0407:
0408:                 //return locateTypeGeneralApprox(name);
0409:
0410:                 // old
0411:                 final SimplifiedSyntaxTree2 sst = source.getSimplifiedSyntaxTreeIfAlreadyMade();
0412:                 if(sst!=null)
0413:                 {
0414:                 System.out.println("Looking approx for "+name);
0415:                 // convenience, use the approximate search for this.
0416:                 return locateTypeGeneralApprox(name);
0417:                 }
0418:                 else
0419:                 {
0420:                 return TypeLocator.locateUsingImports(source, name);
0421:                 }*/
0422:            }
0423:
0424:            /** To use for the first element (that lies in the source).
0425:             */
0426:            public FileItem locateTypeUsingStaticImports(String name,
0427:                    boolean isMethod, SingleClassLoader scl) {
0428:                name = SyntaxUtils.removeAllArrayPartsAtEnd(name);
0429:
0430:                if (source.getParserResultIfAlreadyMade() != null
0431:                        && source.getParserResultIfAlreadyMade().compilationUnit != null) {
0432:                    return TypeLocator.locateUsingStaticImports(source
0433:                            .getParserResultIfAlreadyMade(), scl, name,
0434:                            isMethod, source.getPackageName());
0435:                }
0436:                return null;
0437:                /* OLD
0438:                SimplifiedSyntaxTree2 sst = source.getSimplifiedSyntaxTreeIfAlreadyMade();
0439:                if(sst==null) return null;
0440:                ParserTreeNode importsNode = sst.importsNode;
0441:                return TypeLocator.locateUsingStaticImports(importsNode, scl, name, isMethod, source.getPackageName());
0442:                 */
0443:            }
0444:
0445:            /** Advantage: also finds the inner classes !
0446:             *   @param name is for example "String"
0447:             *   @return for example "java.lang.String" or null if not found, with "$" for inner classes ! (???)
0448:             */
0449:            private String locateClassUsingImports(String name) {
0450:                name = SyntaxUtils.removeAllArrayPartsAtEnd(name);
0451:                debugOut("locateClassUsingImports(" + name + ")");
0452:
0453:                ClassFilesManager cfm = MainEditorFrame.instance
0454:                        .getActualProject().getClassFilesManager();
0455:                // when proj not fully loaded
0456:                if (cfm == null)
0457:                    return null;
0458:
0459:                //1) direct match:
0460:                ProjClass pc = cfm.getClassExact(name);
0461:                if (pc != null)
0462:                    return pc.getJavaName();
0463:
0464:                // 2) try to locate the class as an inner class or the source !
0465:                String cn = this .source.getJavaName() + "$" + name; // full resolved !
0466:                pc = cfm.getClassExact(cn);
0467:                if (pc != null)
0468:                    return cn; // with the $
0469:
0470:                pc = cfm.getClassExact("java.lang." + name);
0471:                if (pc != null)
0472:                    return pc.getJavaName();
0473:
0474:                // 3) try using imports...
0475:                /*OLD
0476:                SimplifiedSyntaxTree2 sst = source.getSimplifiedSyntaxTreeIfAlreadyMade();
0477:                if(sst!=null)
0478:                {
0479:                    ParserTreeNode importsNode = sst.importsNode;
0480:                    for(int i=0; i<importsNode.getChildCount(); i++)
0481:                    {
0482:                       String im = ((ImportNode) importsNode.getChildNodeAt(i)).getImportName();
0483:                       // either "xxx.yyy.*" or "xxx.yyy.Z"
0484:                       if(im.endsWith(".*"))
0485:                       {
0486:                          pc = cfm.getClassExact(im.substring(0,im.length()-2)+"."+name);
0487:                          if(pc!=null) return pc.getJavaName();
0488:                       }
0489:                       else
0490:                       {
0491:                          if(im.endsWith("."+name)) // THE DOT IS important, otherwise ZipFile will complete for File!
0492:                          {
0493:                            pc = cfm.getClassExact(im);
0494:                            if(pc!=null) return pc.getJavaName();
0495:                          }
0496:                       }
0497:                    }
0498:                }*/
0499:
0500:                final ParserResult pr = source.getParserResultIfAlreadyMade();
0501:                if (pr != null && pr.compilationUnit != null
0502:                        && pr.compilationUnit.imports != null) {
0503:                    for (final ImportDeclaration it : pr.compilationUnit.imports) {
0504:                        if (it.isAsterisk) {
0505:                            pc = cfm.getClassExact("" + it.name + "." + name);
0506:                            if (pc != null)
0507:                                return pc.getJavaName();
0508:                        } else {
0509:                            String im = "" + it.name;
0510:                            if (im.endsWith("." + name)) // THE DOT IS important, otherwise ZipFile will complete for File!
0511:                            {
0512:                                pc = cfm.getClassExact(im);
0513:                                if (pc != null)
0514:                                    return pc.getJavaName();
0515:                            }
0516:                        }
0517:
0518:                    }
0519:                }
0520:
0521:                //TODO: look in package
0522:
0523:                // not found, sorry...
0524:                // maybe perform an approximate search,
0525:                // name ending with, and then with name appxox equals (edit distance, soudex, metaphone, ...)
0526:                return null;
0527:
0528:            }
0529:
0530:            private String removeArgAndArrayPartAtEnd(String name) {
0531:                int pos = name.indexOf('(');
0532:                if (pos > 0)
0533:                    name = name.substring(0, pos);
0534:                pos = name.indexOf('[');
0535:                if (pos > 0)
0536:                    name = name.substring(0, pos);
0537:                return name;
0538:            }
0539:
0540:            /** The most difficult and important... based on the syntax tree, if available
0541:             *   also uses the imports to locate the correct type !
0542:             * @param allowAproximateSearch  should be false. If not found, a right click in the editor will also
0543:             *   propose adding mising imports...
0544:             */
0545:            private IDChainElement locateFirstElement(final String name_,
0546:                    boolean enforceMethod, boolean allowAproximateSearch,
0547:                    boolean isClassCast) {
0548:                MainEditorFrame.debugOut("Locate first elt: " + name_ + " (em:"
0549:                        + enforceMethod + ")");
0550:                IDChainElement ide = createIDElement(name_, enforceMethod);
0551:                ide.isClassCast = isClassCast;
0552:                SimplifiedSyntaxTree2 sst = source
0553:                        .getSimplifiedSyntaxTreeIfAlreadyMade();
0554:
0555:                final String nameToSearch = removeArgAndArrayPartAtEnd(name_); // was remo only array !
0556:                if (sst == null) {
0557:                    // todo: locate lazy ?? use regex and other string searches
0558:                    debugOut("no syntax tree");
0559:                } else {
0560:                    //ParserTreeNode importsNode = sst.importsNode;
0561:                    final int[] lineCol = DocumentUtils.getLineColumnNumbers(
0562:                            doc, posInSource);
0563:                    //final int col = DocumentUtils.getColumnNumber(doc, posInSource);
0564:                    deepestTypeAtPos = sst.getDeepestTypeAt(lineCol[0] + 1,
0565:                            lineCol[1] + 1, true);
0566:                    //System.out.println("Deepest type: " + deepestTypeAtPos.getTypeName());
0567:                    //getFirstNodeBeforePosition or getNodeTokenContaining
0568:                    String type = null; // not found now !
0569:
0570:                    if (pid.precedingItem.equals("\"")) {
0571:                        type = "java.lang.String";
0572:                    }
0573:
0574:                    // 0) special cases: this and super and class
0575:                    if (type == null && nameToSearch.equals("this")) {
0576:                        if (deepestTypeAtPos != null) {
0577:                            if (source.getPackageName().length() > 0) {
0578:                                // [Feb2008]: made correct !
0579:                                //System.out.println("deepestTypeAtPos="+deepestTypeAtPos.getTypeSimpleName());  // "ClassA"
0580:                                //System.out.println("source="+source.getJavaPartName()+ " ("+source.getJavaName()+")");           // test.ClassA
0581:
0582:                                if (deepestTypeAtPos.getTypeSimpleName()
0583:                                        .equals(source.getJavaPartName())) {
0584:                                    // ok if we are IN the toppest class
0585:                                    type = source.getPackageName()
0586:                                            + "."
0587:                                            + deepestTypeAtPos
0588:                                                    .getTypeSimpleName();
0589:                                } else {
0590:                                    type = source.getJavaName()
0591:                                            + "$"
0592:                                            + deepestTypeAtPos
0593:                                                    .getTypeSimpleName();
0594:                                }
0595:
0596:                                //System.out.println(""+source.getPackageName()+"  +   "+deepestTypeAtPos.getTypeSimpleName());
0597:                            } else {
0598:                                type = deepestTypeAtPos.getTypeSimpleName(); // todo: maybe false if inner chained classes
0599:                            }
0600:                        } else {
0601:                            debugOut("No deepest type found => using src instead of deepest type for this");
0602:                            type = source.getJavaName();
0603:                        }
0604:
0605:                        if (name_.indexOf('(') > 0) {
0606:                            ide.setIsConstructorCall(type);
0607:                        }
0608:
0609:                        //System.out.println("type found for \"this\" = "+type);
0610:                    } else if (type == null && nameToSearch.equals("super")) {
0611:                        if (deepestTypeAtPos != null) {
0612:                            if (deepestTypeAtPos instanceof  ClassNode) {
0613:                                ClassNode cn = (ClassNode) deepestTypeAtPos;
0614:                                if (cn.extendsText != null) {
0615:                                    type = cn.extendsText;
0616:                                } else {
0617:                                    //System.out.println("No deepest type found => using this insteadof super");
0618:                                    type = "java.lang.Object";
0619:                                }
0620:                            } else {
0621:                                MainEditorFrame
0622:                                        .debugOut("Cannot find super from not classnode "
0623:                                                + deepestTypeAtPos);
0624:                            }
0625:                        } else {
0626:                            type = source.getJavaName();
0627:                            // TODO: locate super through class !
0628:                        }
0629:
0630:                        if (name_.indexOf('(') > 0) {
0631:                            ide.setIsConstructorCall(type);
0632:                        }
0633:
0634:                    }
0635:
0636:                    if (ide.getKind() == ElementKind.Constructor) {
0637:                        String typeName = nameToSearch;
0638:                        int pos = typeName.indexOf('(');
0639:                        if (pos >= 0) {
0640:                            typeName = typeName.substring(0, pos);
0641:                        }
0642:                        // localize !
0643:                        type = this .locateClassUsingImports(typeName);
0644:                    }
0645:
0646:                    // 1) local variables (loc decl, in bloks, in loops, ...)
0647:                    // this search backward and only for variables preceeding !
0648:                    if (type == null) {
0649:                        if (sst.getRawParserResult() != null) {
0650:                            RAWParserTreeNode found = TreeUtils
0651:                                    .getTokenNodeAtOrAfterPosition(sst
0652:                                            .getRawParserResult(),
0653:                                            lineCol[0] + 1, // [Dec2007]: added "+1" because completion was not available for elements on the line after method param variable  !
0654:                                            lineCol[1]);
0655:                            //System.out.println("Some node near: "+found);
0656:                            type = TreeUtils.searchTypeForVariableName(found,
0657:                                    nameToSearch,
0658:                                    ide.getKind() == ElementKind.Method);
0659:
0660:                            if (type == null) {
0661:                                debugOut("   is not a variable name.");
0662:                            }
0663:                        } else {
0664:                            debugOut("No raw syntax tree => cannot detect local variables");
0665:                        }
0666:                    }
0667:
0668:                    boolean met = enforceMethod
0669:                            || ide.getKind() == ElementKind.Method
0670:                            || ide.getKind() == ElementKind.Constructor;
0671:
0672:                    if (type == null) {
0673:                        // 2) methods or fields "frame"
0674:
0675:                        type = searchForTypeOfMethodOrField(ide, sst, met, !met); // either field or method, we know.  (or cons or stat class)
0676:
0677:                        if (type == null) {
0678:                            debugOut("   "
0679:                                    + ide.getName()
0680:                                    + " is not a field or method in this syntax tree (m="
0681:                                    + met + ")");
0682:
0683:                            // [Feb2008], yeah, finds inner classes !
0684:                            for (TypeNode tn : sst.getAllTopLevelTypes()) {
0685:                                if (tn.getJavaFullName().endsWith(nameToSearch)) {
0686:                                    debugOut("      Candidate: toplevel type "
0687:                                            + tn.getJavaFullName() + " for "
0688:                                            + nameToSearch);
0689:                                    //return tn.getJavaFullName();
0690:                                    //type = tn.getJavaFullName();
0691:                                    if (ide.getKind() == ElementKind.Method
0692:                                            || ide.getKind() == ElementKind.Field) // Now we knows that this was NOT a method call but a direct class call.  "CCC."
0693:                                    {
0694:                                        ide.setIsDirectClassCall();
0695:                                    }
0696:                                    //System.out.println(""+ ide.resolvedType_);
0697:                                    ide.resolvedType_.rclass = scl.findClass(tn
0698:                                            .getJavaFullName());
0699:                                    //System.out.println("RTYPE of elt: "+ ide.resolvedType_);
0700:                                }
0701:                            }
0702:
0703:                        }
0704:                    }
0705:
0706:                    // [May2007]: use reflection
0707:                    if (type == null) {
0708:                        String deepestTypeName = source.getJavaName();
0709:                        if (deepestTypeAtPos != null) {
0710:                            if (source.getPackageName().length() > 0) {
0711:                                deepestTypeName = source.getPackageName() + "."
0712:                                        + deepestTypeAtPos.getTypeSimpleName(); // todo: chained inner classes
0713:                            } else {
0714:                                deepestTypeName = deepestTypeAtPos
0715:                                        .getTypeSimpleName();
0716:                            }
0717:                        }
0718:                        Class this Cl = getClassForName(deepestTypeName);
0719:                        if (this Cl != null) {
0720:                            if (met) {
0721:                                type = ClassUtils.getTypeForMethodInClass(
0722:                                        this Cl, ide.getName(), null); // TODO: pass type params
0723:                            } else {
0724:                                //
0725:                                Class typeCl = ClassUtils
0726:                                        .getTypeForFieldInClass(this Cl, ide
0727:                                                .getName());
0728:                                if (typeCl != null) {
0729:                                    type = typeCl.getName();
0730:                                    ide.resolvedType_.rclass = typeCl;
0731:                                    // Here some are erroneous marked as Field instead of Class call... (TODO).
0732:                                }
0733:                            }
0734:
0735:                            if (type == null) {
0736:                                debugOut("   "
0737:                                        + ide.getName()
0738:                                        + " is not a field or method in this class.");
0739:                            }
0740:                        } else {
0741:                            debugOut("   class not found for deepestTypeName="
0742:                                    + deepestTypeName);
0743:                        }
0744:                    }
0745:
0746:                    if (type == null) {
0747:                        // 3) absolute referenced type, for example "javax.swing.JFrame"
0748:                        // TODO: use splittedChain and tell what remains !
0749:                        final StringBuilder id = new StringBuilder(nameToSearch);
0750:                        tl: for (int i = 1; i < splittedChain.length; i++) {
0751:                            id.append(".");
0752:                            id.append(splittedChain[i]);
0753:                            FileItem fi = TypeLocator.searchTypeForName(id
0754:                                    .toString(), false, false); // exact look
0755:                            if (fi != null) {
0756:                                type = fi.getJavaName();
0757:                                numberOfEltsTakenAsFirst = i + 1;
0758:                                //System.out.println("Absolute type found: "+type);
0759:                                ide.setIsDirectClassCall();
0760:                                ide.resolvedType_.fitem = fi;
0761:                                break tl;
0762:                            }
0763:                        }
0764:                    }
0765:
0766:                    if (type == null) {
0767:                        // 4) raw type (class), for example "JFrame"
0768:                        FileItem fi = this .locateTypeUsingImports(nameToSearch);
0769:
0770:                        if (fi != null) {
0771:                            //System.out.println("Type found (using imp): "+fi);
0772:                            //BAD ide.setIsDirectClassCall();    // [Nov2007]: ERROR: some project constructors are here !
0773:
0774:                            if (this .isConstructorMode()) {
0775:                                // what ix  "new XXX.YYY.ZZZ()" ??
0776:                                ide.setIsConstructorCall(fi.getJavaName());
0777:                            } else {
0778:                                ide.setIsDirectClassCall();
0779:                            }
0780:
0781:                            type = fi.getJavaName();
0782:                            ide.resolvedType_.fitem = fi;
0783:                        }
0784:                    }
0785:
0786:                    // try to locate the class from classmanager (finds also inner classes !)
0787:                    //  TODO: finds corresponding FileItem ?
0788:                    if (type == null) {
0789:                        type = this .locateClassUsingImports(nameToSearch);
0790:                        if (type != null) {
0791:                            debugOut("Type found (using imp cla): " + type);
0792:                            //BAD[Nov2007]: ide.setIsDirectClassCall();
0793:
0794:                            if (this .isConstructorMode()) {
0795:                                // what ix  "new XXX.YYY.ZZZ()" ??
0796:                                ide.setIsConstructorCall(type);
0797:                            } else {
0798:                                ide.setIsDirectClassCall();
0799:                            }
0800:
0801:                            try {
0802:                                ide.reflectedObject = scl.findClass(type); // not load !
0803:                            } catch (Exception e) {
0804:                                e.printStackTrace();
0805:                            }
0806:                        }
0807:                    }
0808:
0809:                    if (type == null) {
0810:                        // 5) static imports ! [April2007] TODO: test
0811:                        //  ok, they may be overridden by methods in 2...
0812:                        FileItem fi = this .locateTypeUsingStaticImports(
0813:                                nameToSearch, enforceMethod, scl);
0814:
0815:                        if (fi != null) {
0816:                            type = fi.getJavaName();
0817:                            //ide.resolvedType = fi;
0818:
0819:                            IDChainElement parent = new IDChainElement(this , fi
0820:                                    .getJavaName(), null, false, false);
0821:                            parent.setIsDirectClassCall();
0822:                            parent.resolvedType_.fitem = fi;
0823:
0824:                            // insert
0825:                            this .chain.add(0, parent);
0826:                        }
0827:                    }
0828:
0829:                    if (type == null) {
0830:                        // 6) package part, as for example "javax"
0831:                        //   ?? may be present in several archives !! => the ui, later, resolves...
0832:                        FileItem fi = TypeLocator
0833:                                .locateFirstPackage(nameToSearch);
0834:                        if (fi != null) {
0835:                            //System.out.println("Package found: "+type);
0836:                            ide.setIsPackagePart(fi);
0837:                            return ide;
0838:                        }
0839:                    }
0840:
0841:                    // 7) approximate
0842:                    if (type == null && allowAproximateSearch) {
0843:                        // approx
0844:                        FileItem fi = TypeLocator.searchTypeForName(
0845:                                nameToSearch, false, true); // ending with
0846:                        if (fi != null) {
0847:                            debugOut("Approx type found: " + type);
0848:                            ide.setIsDirectClassCall();
0849:                            type = fi.getJavaName();
0850:                            ide.resolvedType_.fitem = fi;
0851:                        }
0852:                    }
0853:
0854:                    debugOut("type found for first ID chain elt "
0855:                            + nameToSearch + " = " + type);
0856:
0857:                    ide.setTypeWithParamsAndResolve(type);
0858:
0859:                    if (!ide.isResolved()) {
0860:                        debugOut("### not resolved type for " + nameToSearch);
0861:                        isValid = false;
0862:                    }
0863:                }
0864:
0865:                return ide;
0866:            }
0867:
0868:            /** TODO.
0869:             */
0870:            private String locateSuperType(final String type) {
0871:                debugOut("Todo: locate super type");
0872:                // TODO
0873:                return type;
0874:            }
0875:
0876:            public static void debugOut(String s) {
0877:                MainEditorFrame.debugOut(s);
0878:            }
0879:
0880:            /** Called only on subsequent chain elements, not for the first.
0881:             *   Uses the previous element to know the type.
0882:             */
0883:            private IDChainElement locateNextElement(final String name,
0884:                    boolean enforceMethod, boolean isClassCast) {
0885:                IDChainElement previous = getLastChainComponent(); // null if first !!
0886:                IDChainElement ide = createIDElement(name, enforceMethod);
0887:                ide.isClassCast = isClassCast;
0888:
0889:                String type = null;
0890:
0891:                if (ide.getName().equals("this")) {
0892:                    ide.setTypeName(previous.getTypeMaybeResolved());
0893:                    if (previous.resolvedType_ != null) {
0894:                        ide.resolvedType_.copyFrom(previous.resolvedType_);
0895:                    }
0896:                } else if (ide.getName().equals("super")) {
0897:                    String super Type = locateSuperType(previous
0898:                            .getTypeMaybeResolved());
0899:                    ide.setTypeName(super Type);
0900:                    ide.resolvedType_.fitem = TypeLocator
0901:                            .locateQuick(super Type);
0902:                } else if (ide.getName().equals("class")) {
0903:                    type = "java.lang.Class<" + previous.getTypeMaybeResolved()
0904:                            + ">";
0905:                    //ide.setTypeName( "java.lang.Class" );
0906:                    //ide.setTypeParameters("HELLOO");
0907:                    //ide.resolvedType = TypeLocator.locateQuick("java.lang.Class");
0908:                } else {
0909:                    //TODO
0910:                    debugOut("Search for chain element " + name
0911:                            + " ( previous type = "
0912:                            + previous.getTypeMaybeResolved() + ")");
0913:                    try {
0914:                        // if the previous was a package part:
0915:                        if (previous.getKind() == ElementKind.PackageNameFragment) {
0916:                            String st = previous.resolvedType_.getJavaName()
0917:                                    + "." + name;
0918:                            // just look if one, at least exists. Maybe not the correct later (in the full name), but
0919:                            //  now it's sufficient to know the fragment is ok (Ex: several libs defines "javax")
0920:                            FileItem pi = TypeLocator.locateFirstPackage(st);
0921:                            //System.out.println("Locate "+st+": "+pi);
0922:                            if (pi != null) {
0923:                                ide.setIsPackagePart(pi);
0924:                                return ide; // OK
0925:                            }
0926:
0927:                            // try as class ?
0928:                            // no, cause this was already tryed in the locatefirstelement above !
0929:
0930:                        }
0931:
0932:                        // search based on the guessed new type
0933:                        //
0934:                        Class previousCt = getClassForType(previous);
0935:                        if (previousCt == null) {
0936:                            // no chance
0937:                            debugOut("locateNextElement aborted: null class for previous element "
0938:                                    + previous);
0939:                        }
0940:
0941:                        if (ide.getKind() == ElementKind.Method) {
0942:                            if (ide.reflectedObject != null) // don't happens
0943:                            {
0944:                                Method me = (Method) ide.reflectedObject;
0945:                                type = me.getReturnType().getName();
0946:                                debugOut("Reflected method return type = "
0947:                                        + me.getGenericReturnType());
0948:                            } else {
0949:                                debugOut("### null previous reflected ="
0950:                                        + previous);
0951:                                type = ClassUtils.getTypeForMethodInClass(
0952:                                        previousCt, ide.getName(), previous
0953:                                                .getTypeParameters());
0954:                            }
0955:                        } else if (ide.getKind() == ElementKind.Field) {
0956:                            if (ide.reflectedObject != null) {
0957:                                type = ((Field) ide.reflectedObject).getType()
0958:                                        .getName();
0959:                            } else {
0960:                                Class typeCl = ClassUtils
0961:                                        .getTypeForFieldInClass(previousCt, ide
0962:                                                .getName());
0963:                                if (typeCl != null) {
0964:                                    type = typeCl.getName();
0965:                                    ide.resolvedType_.rclass = typeCl;
0966:                                }
0967:                            }
0968:                        } else if (ide.getKind() == ElementKind.Class) {
0969:                            type = ide.getName();
0970:                        } else if (ide.getKind() == ElementKind.Constructor) {
0971:                            // new JFrame() give a JFrame back !
0972:                            type = ide.getName();
0973:                            if (previous != null) {
0974:                                type = previous.getName() + "." + type; // [14Dec2006]: resolve !!
0975:                            }
0976:                            System.out.println("Constructor type is " + type); // ?? Point2D.Double ?
0977:                        } else {
0978:                            // ???
0979:                        }
0980:                    } catch (Exception e) {
0981:                        e.printStackTrace();
0982:                    }
0983:                }
0984:
0985:                ide.setTypeWithParamsAndResolve(type);
0986:                if (type == null) {
0987:                    debugOut("### Type null => not valid");
0988:                    isValid = false;
0989:                }
0990:
0991:                return ide;
0992:            }
0993:
0994:            public Class getClassForType(IDChainElement ide) {
0995:                String jn = ide.getTypeMaybeResolved();
0996:
0997:                if (ide.reflectedObject instanceof  Class) {
0998:                    return (Class) ide.reflectedObject;
0999:                }
1000:
1001:                if (!ide.resolvedType_.isResolved()) {
1002:                    MainEditorFrame.debugOut("### Not resolved : " + jn);
1003:                    //return null; ??
1004:                }
1005:
1006:                if (jn == null)
1007:                    return null; // [Sep2007]
1008:
1009:                return getClassForName(jn);
1010:            }
1011:
1012:            /** javax.swing.JTree => assoc class. null on exceptions.
1013:             */
1014:            public Class getClassForName(String jn) {
1015:                try {
1016:                    return scl.findClass(jn); // not load !
1017:                } catch (Exception e) {
1018:                    e.printStackTrace();
1019:                }
1020:                return null;
1021:            }
1022:
1023:            /** Used for the first element, in the parser tree.
1024:             *  Also looks for inner classes and top level types and constructors.
1025:             * (other are find via reflection) (TODO: ameliorate...)
1026:             */
1027:            private String searchForTypeOfMethodOrField(IDChainElement ide,
1028:                    SimplifiedSyntaxTree2 sst, boolean methods, boolean fields) {
1029:                String nameToSearch = SyntaxUtils.removeAllArrayPartsAtEnd(ide
1030:                        .getName());
1031:                debugOut("  Search for members named " + nameToSearch + " (m="
1032:                        + methods + ", f=" + fields + ")");
1033:
1034:                List<TypeNode> tns = sst.getAllTopLevelTypes(); //TODO: use cache from SourceFile's dependencies
1035:                for (TypeNode tn : tns) {
1036:                    debugOut("      looking in " + tn.getJavaFullName());
1037:                    String name = SearchFunctions.searchTypeForMethodOrField(
1038:                            nameToSearch, tn, methods, fields);
1039:                    if (name != null)
1040:                        return name;
1041:                }
1042:                /*
1043:                // not found ! [Feb2008]: look if it is one of the type name !
1044:                   MOVED IN THE CALLER for more control
1045:                for(TypeNode tn : tns)
1046:                {
1047:                   if(tn.getJavaFullName().endsWith(nameToSearch))
1048:                   {
1049:                      debugOut("      Candidate: toplevel type "+tn.getJavaFullName());
1050:                      return tn.getJavaFullName();
1051:                   }
1052:                }*/
1053:
1054:                // not found !
1055:                return null;
1056:            }
1057:
1058:            /** If new preceeds the id.
1059:             *  as in new Throwable("Hello").printStackTrace();
1060:             *  or   new javax.swing.JFrame("Hello")
1061:             * as you see, the constructor may NOT be the elt at chain end !
1062:             * so use the last element kind to know the kind of the chain, NOT this.
1063:             * This, if true, means that the first "(" is a constructor, all next "(" are
1064:             * method calles
1065:             */
1066:            public boolean isConstructorMode() {
1067:                return constructorMode;
1068:            }
1069:
1070:            public boolean isValid() {
1071:                return isValid;
1072:            }
1073:
1074:            @Override
1075:            public String toString() {
1076:                StringBuilder sb = new StringBuilder();
1077:                sb.append("IDChain");
1078:                if (!isValid)
1079:                    sb.append(" (INVALID)");
1080:                sb.append(" for " + pid + "\n at " + source.getJavaName()
1081:                        + ", posStart=" + posInSource + ":");
1082:                for (IDChainElement id : chain) {
1083:                    sb.append("\n   idelt: " + id);
1084:                }
1085:                return sb.toString();
1086:            }
1087:
1088:            public String toStringHTML() {
1089:                StringBuilder sb = new StringBuilder();
1090:                sb.append("<html><body><p>");
1091:                sb.append(HTMLUtils.convertCharsToHTML(pid.toString()));
1092:                sb.append("</p>in ");
1093:                sb.append(source.getJavaName());
1094:                sb.append(", posStart=");
1095:                sb.append(posInSource);
1096:                if (!isValid)
1097:                    sb.append(", <b>INVALID</b>");
1098:                sb.append("<br>");
1099:
1100:                for (IDChainElement id : chain) {
1101:                    sb.append("<br>");
1102:                    sb.append(HTMLUtils.convertCharsToHTML(id.toString()));
1103:                }
1104:                sb.append("</body></html>");
1105:                return sb.toString();
1106:            }
1107:
1108:            private IDChainElement createIDElement(String name,
1109:                    boolean enforceMethod) {
1110:                boolean isMethod = name.indexOf('(') >= 0;
1111:                boolean enforceConstructor = isConstructorMode()
1112:                        && !isConstructorAlreadyFound
1113:                        && (isMethod || enforceMethod);
1114:
1115:                if (enforceConstructor)
1116:                    isConstructorAlreadyFound = true;
1117:
1118:                if (name.endsWith("(")) {
1119:                    name = name.substring(0, name.length() - 1);
1120:                    return new IDChainElement(this , name, "", enforceMethod,
1121:                            enforceConstructor);
1122:                }
1123:
1124:                int pos = name.indexOf('(');
1125:
1126:                if (pos > 0) {
1127:                    String args = name.substring(pos + 1, name.length() - 1);
1128:                    name = name.substring(0, pos);
1129:                    return new IDChainElement(this , name, args, enforceMethod,
1130:                            enforceConstructor);
1131:                }
1132:                return new IDChainElement(this, name, null, enforceMethod,
1133:                        enforceConstructor);
1134:            }
1135:
1136:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.