Source Code Cross Referenced for ClassTypeResolver.java in  » Code-Analyzer » pmd-4.2rc1 » net » sourceforge » pmd » typeresolution » 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 » Code Analyzer » pmd 4.2rc1 » net.sourceforge.pmd.typeresolution 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
003:         */package net.sourceforge.pmd.typeresolution;
004:
005:        import java.util.ArrayList;
006:        import java.util.Collections;
007:        import java.util.HashMap;
008:        import java.util.List;
009:        import java.util.Map;
010:        import java.util.logging.Level;
011:        import java.util.logging.Logger;
012:
013:        import net.sourceforge.pmd.ast.ASTAdditiveExpression;
014:        import net.sourceforge.pmd.ast.ASTAllocationExpression;
015:        import net.sourceforge.pmd.ast.ASTAndExpression;
016:        import net.sourceforge.pmd.ast.ASTAnnotationTypeDeclaration;
017:        import net.sourceforge.pmd.ast.ASTArrayDimsAndInits;
018:        import net.sourceforge.pmd.ast.ASTBooleanLiteral;
019:        import net.sourceforge.pmd.ast.ASTCastExpression;
020:        import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
021:        import net.sourceforge.pmd.ast.ASTClassOrInterfaceType;
022:        import net.sourceforge.pmd.ast.ASTCompilationUnit;
023:        import net.sourceforge.pmd.ast.ASTConditionalAndExpression;
024:        import net.sourceforge.pmd.ast.ASTConditionalExpression;
025:        import net.sourceforge.pmd.ast.ASTConditionalOrExpression;
026:        import net.sourceforge.pmd.ast.ASTEnumDeclaration;
027:        import net.sourceforge.pmd.ast.ASTEqualityExpression;
028:        import net.sourceforge.pmd.ast.ASTExclusiveOrExpression;
029:        import net.sourceforge.pmd.ast.ASTExpression;
030:        import net.sourceforge.pmd.ast.ASTFieldDeclaration;
031:        import net.sourceforge.pmd.ast.ASTImportDeclaration;
032:        import net.sourceforge.pmd.ast.ASTInclusiveOrExpression;
033:        import net.sourceforge.pmd.ast.ASTInstanceOfExpression;
034:        import net.sourceforge.pmd.ast.ASTLiteral;
035:        import net.sourceforge.pmd.ast.ASTMultiplicativeExpression;
036:        import net.sourceforge.pmd.ast.ASTName;
037:        import net.sourceforge.pmd.ast.ASTNullLiteral;
038:        import net.sourceforge.pmd.ast.ASTPackageDeclaration;
039:        import net.sourceforge.pmd.ast.ASTPostfixExpression;
040:        import net.sourceforge.pmd.ast.ASTPreDecrementExpression;
041:        import net.sourceforge.pmd.ast.ASTPreIncrementExpression;
042:        import net.sourceforge.pmd.ast.ASTPrimaryExpression;
043:        import net.sourceforge.pmd.ast.ASTPrimaryPrefix;
044:        import net.sourceforge.pmd.ast.ASTPrimarySuffix;
045:        import net.sourceforge.pmd.ast.ASTPrimitiveType;
046:        import net.sourceforge.pmd.ast.ASTReferenceType;
047:        import net.sourceforge.pmd.ast.ASTRelationalExpression;
048:        import net.sourceforge.pmd.ast.ASTShiftExpression;
049:        import net.sourceforge.pmd.ast.ASTStatementExpression;
050:        import net.sourceforge.pmd.ast.ASTType;
051:        import net.sourceforge.pmd.ast.ASTTypeDeclaration;
052:        import net.sourceforge.pmd.ast.ASTUnaryExpression;
053:        import net.sourceforge.pmd.ast.ASTUnaryExpressionNotPlusMinus;
054:        import net.sourceforge.pmd.ast.ASTVariableDeclarator;
055:        import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
056:        import net.sourceforge.pmd.ast.JavaParserVisitorAdapter;
057:        import net.sourceforge.pmd.ast.Node;
058:        import net.sourceforge.pmd.ast.SimpleNode;
059:        import net.sourceforge.pmd.ast.TypeNode;
060:
061:        //
062:        // Helpful reading:
063:        // http://www.janeg.ca/scjp/oper/promotions.html
064:        // http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html
065:        //
066:
067:        public class ClassTypeResolver extends JavaParserVisitorAdapter {
068:
069:            private static final Logger LOG = Logger
070:                    .getLogger(ClassTypeResolver.class.getName());
071:
072:            private static final Map<String, Class<?>> myPrimitiveTypes;
073:            private static final Map<String, String> myJavaLang;
074:
075:            static {
076:                // Note: Assumption here that primitives come from same parent ClassLoader regardless of what ClassLoader we are passed
077:                Map<String, Class<?>> thePrimitiveTypes = new HashMap<String, Class<?>>();
078:                thePrimitiveTypes.put("void", Void.TYPE);
079:                thePrimitiveTypes.put("boolean", Boolean.TYPE);
080:                thePrimitiveTypes.put("byte", Byte.TYPE);
081:                thePrimitiveTypes.put("char", Character.TYPE);
082:                thePrimitiveTypes.put("short", Short.TYPE);
083:                thePrimitiveTypes.put("int", Integer.TYPE);
084:                thePrimitiveTypes.put("long", Long.TYPE);
085:                thePrimitiveTypes.put("float", Float.TYPE);
086:                thePrimitiveTypes.put("double", Double.TYPE);
087:                myPrimitiveTypes = Collections
088:                        .unmodifiableMap(thePrimitiveTypes);
089:
090:                Map<String, String> theJavaLang = new HashMap<String, String>();
091:                theJavaLang.put("Boolean", "java.lang.Boolean");
092:                theJavaLang.put("Byte", "java.lang.Byte");
093:                theJavaLang.put("Character", "java.lang.Character");
094:                theJavaLang.put("CharSequence", "java.lang.CharSequence");
095:                theJavaLang.put("Class", "java.lang.Class");
096:                theJavaLang.put("ClassLoader", "java.lang.ClassLoader");
097:                theJavaLang.put("Cloneable", "java.lang.Cloneable");
098:                theJavaLang.put("Comparable", "java.lang.Comparable");
099:                theJavaLang.put("Compiler", "java.lang.Compiler");
100:                theJavaLang.put("Double", "java.lang.Double");
101:                theJavaLang.put("Float", "java.lang.Float");
102:                theJavaLang.put("InheritableThreadLocal",
103:                        "java.lang.InheritableThreadLocal");
104:                theJavaLang.put("Integer", "java.lang.Integer");
105:                theJavaLang.put("Long", "java.lang.Long");
106:                theJavaLang.put("Math", "java.lang.Math");
107:                theJavaLang.put("Number", "java.lang.Number");
108:                theJavaLang.put("Object", "java.lang.Object");
109:                theJavaLang.put("Package", "java.lang.Package");
110:                theJavaLang.put("Process", "java.lang.Process");
111:                theJavaLang.put("Runnable", "java.lang.Runnable");
112:                theJavaLang.put("Runtime", "java.lang.Runtime");
113:                theJavaLang.put("RuntimePermission",
114:                        "java.lang.RuntimePermission");
115:                theJavaLang.put("SecurityManager", "java.lang.SecurityManager");
116:                theJavaLang.put("Short", "java.lang.Short");
117:                theJavaLang.put("StackTraceElement",
118:                        "java.lang.StackTraceElement");
119:                theJavaLang.put("StrictMath", "java.lang.StrictMath");
120:                theJavaLang.put("String", "java.lang.String");
121:                theJavaLang.put("StringBuffer", "java.lang.StringBuffer");
122:                theJavaLang.put("System", "java.lang.System");
123:                theJavaLang.put("Thread", "java.lang.Thread");
124:                theJavaLang.put("ThreadGroup", "java.lang.ThreadGroup");
125:                theJavaLang.put("ThreadLocal", "java.lang.ThreadLocal");
126:                theJavaLang.put("Throwable", "java.lang.Throwable");
127:                theJavaLang.put("Void", "java.lang.Void");
128:                myJavaLang = Collections.unmodifiableMap(theJavaLang);
129:            }
130:
131:            private final PMDASMClassLoader pmdClassLoader;
132:            private Map<String, String> importedClasses;
133:            private List<String> importedOnDemand;
134:
135:            public ClassTypeResolver() {
136:                this (ClassTypeResolver.class.getClassLoader());
137:            }
138:
139:            public ClassTypeResolver(ClassLoader classLoader) {
140:                pmdClassLoader = new PMDASMClassLoader(classLoader);
141:            }
142:
143:            // FUTURE ASTCompilationUnit should not be a TypeNode.  Clean this up accordingly.
144:            public Object visit(ASTCompilationUnit node, Object data) {
145:                String className = null;
146:                try {
147:                    importedOnDemand = new ArrayList<String>();
148:                    className = getClassName(node);
149:                    if (className != null) {
150:                        populateClassName(node, className);
151:                    }
152:                } catch (ClassNotFoundException e) {
153:                    LOG.log(Level.FINE, "Could not find class " + className);
154:                } catch (NoClassDefFoundError e) {
155:                    LOG.log(Level.WARNING, "Could not find class " + className);
156:                } finally {
157:                    populateImports(node);
158:                }
159:                return super .visit(node, data);
160:            }
161:
162:            public Object visit(ASTImportDeclaration node, Object data) {
163:                ASTName importedType = (ASTName) node.jjtGetChild(0);
164:                if (importedType.getType() != null) {
165:                    node.setType(importedType.getType());
166:                } else {
167:                    populateType(node, importedType.getImage());
168:                }
169:
170:                if (node.getType() != null) {
171:                    node.setPackage(node.getType().getPackage());
172:                }
173:                return data;
174:            }
175:
176:            public Object visit(ASTTypeDeclaration node, Object data) {
177:                super .visit(node, data);
178:                rollupTypeUnary(node);
179:                return data;
180:            }
181:
182:            public Object visit(ASTClassOrInterfaceType node, Object data) {
183:                populateType(node, node.getImage());
184:                return data;
185:            }
186:
187:            public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
188:                populateType(node, node.getImage());
189:                return super .visit(node, data);
190:            }
191:
192:            public Object visit(ASTEnumDeclaration node, Object data) {
193:                populateType(node, node.getImage());
194:                return super .visit(node, data);
195:            }
196:
197:            public Object visit(ASTAnnotationTypeDeclaration node, Object data) {
198:                populateType(node, node.getImage());
199:                return super .visit(node, data);
200:            }
201:
202:            public Object visit(ASTName node, Object data) {
203:                /*
204:                 * Only doing this for nodes where getNameDeclaration is null this means
205:                 * it's not a named node, i.e. Static reference or Annotation Doing this
206:                 * for memory - TODO: Investigate if there is a valid memory concern or
207:                 * not
208:                 */
209:                if (node.getNameDeclaration() == null) {
210:                    // Skip these scenarios as there is no type to populate in these cases:
211:                    // 1) Parent is a PackageDeclaration, which is not a type
212:                    // 2) Parent is a ImportDeclaration, this is handled elsewhere.
213:                    if (!(node.jjtGetParent() instanceof  ASTPackageDeclaration || node
214:                            .jjtGetParent() instanceof  ASTImportDeclaration)) {
215:                        String name = node.getImage();
216:                        if (name.indexOf('.') != -1) {
217:                            name = name.substring(0, name.indexOf('.'));
218:                        }
219:                        populateType(node, name);
220:                    }
221:                } else {
222:                    // Carry over the type from the declaration
223:                    if (node.getNameDeclaration().getNode() instanceof  TypeNode) {
224:                        node.setType(((TypeNode) node.getNameDeclaration()
225:                                .getNode()).getType());
226:                    }
227:                }
228:                return super .visit(node, data);
229:            }
230:
231:            public Object visit(ASTFieldDeclaration node, Object data) {
232:                super .visit(node, data);
233:                rollupTypeUnary(node);
234:                return data;
235:            }
236:
237:            public Object visit(ASTVariableDeclarator node, Object data) {
238:                super .visit(node, data);
239:                rollupTypeUnary(node);
240:                return data;
241:            }
242:
243:            public Object visit(ASTVariableDeclaratorId node, Object data) {
244:                if (node == null || node.getNameDeclaration() == null) {
245:                    return super .visit(node, data);
246:                }
247:                String name = node.getNameDeclaration().getTypeImage();
248:                if (name.indexOf('.') != -1) {
249:                    name = name.substring(0, name.indexOf('.'));
250:                }
251:                populateType(node, name);
252:                return super .visit(node, data);
253:            }
254:
255:            public Object visit(ASTType node, Object data) {
256:                super .visit(node, data);
257:                rollupTypeUnary(node);
258:                return data;
259:            }
260:
261:            public Object visit(ASTReferenceType node, Object data) {
262:                super .visit(node, data);
263:                rollupTypeUnary(node);
264:                return data;
265:            }
266:
267:            public Object visit(ASTPrimitiveType node, Object data) {
268:                populateType(node, node.getImage());
269:                return super .visit(node, data);
270:            }
271:
272:            public Object visit(ASTExpression node, Object data) {
273:                super .visit(node, data);
274:                rollupTypeUnary(node);
275:                return data;
276:            }
277:
278:            public Object visit(ASTConditionalExpression node, Object data) {
279:                super .visit(node, data);
280:                if (node.isTernary()) {
281:                    // TODO Rules for Ternary are complex
282:                } else {
283:                    rollupTypeUnary(node);
284:                }
285:                return data;
286:            }
287:
288:            public Object visit(ASTConditionalOrExpression node, Object data) {
289:                populateType(node, "boolean");
290:                return super .visit(node, data);
291:            }
292:
293:            public Object visit(ASTConditionalAndExpression node, Object data) {
294:                populateType(node, "boolean");
295:                return super .visit(node, data);
296:            }
297:
298:            public Object visit(ASTInclusiveOrExpression node, Object data) {
299:                super .visit(node, data);
300:                rollupTypeBinaryNumericPromotion(node);
301:                return data;
302:            }
303:
304:            public Object visit(ASTExclusiveOrExpression node, Object data) {
305:                super .visit(node, data);
306:                rollupTypeBinaryNumericPromotion(node);
307:                return data;
308:            }
309:
310:            public Object visit(ASTAndExpression node, Object data) {
311:                super .visit(node, data);
312:                rollupTypeBinaryNumericPromotion(node);
313:                return data;
314:            }
315:
316:            public Object visit(ASTEqualityExpression node, Object data) {
317:                populateType(node, "boolean");
318:                return super .visit(node, data);
319:            }
320:
321:            public Object visit(ASTInstanceOfExpression node, Object data) {
322:                populateType(node, "boolean");
323:                return super .visit(node, data);
324:            }
325:
326:            public Object visit(ASTRelationalExpression node, Object data) {
327:                populateType(node, "boolean");
328:                return super .visit(node, data);
329:            }
330:
331:            public Object visit(ASTShiftExpression node, Object data) {
332:                super .visit(node, data);
333:                // Unary promotion on LHS is type of a shift operation
334:                rollupTypeUnaryNumericPromotion(node);
335:                return data;
336:            }
337:
338:            public Object visit(ASTAdditiveExpression node, Object data) {
339:                super .visit(node, data);
340:                rollupTypeBinaryNumericPromotion(node);
341:                return data;
342:            }
343:
344:            public Object visit(ASTMultiplicativeExpression node, Object data) {
345:                super .visit(node, data);
346:                rollupTypeBinaryNumericPromotion(node);
347:                return data;
348:            }
349:
350:            public Object visit(ASTUnaryExpression node, Object data) {
351:                super .visit(node, data);
352:                rollupTypeUnaryNumericPromotion(node);
353:                return data;
354:            }
355:
356:            public Object visit(ASTPreIncrementExpression node, Object data) {
357:                super .visit(node, data);
358:                rollupTypeUnary(node);
359:                return data;
360:            }
361:
362:            public Object visit(ASTPreDecrementExpression node, Object data) {
363:                super .visit(node, data);
364:                rollupTypeUnary(node);
365:                return data;
366:            }
367:
368:            public Object visit(ASTUnaryExpressionNotPlusMinus node, Object data) {
369:                super .visit(node, data);
370:                if ("!".equals(node.getImage())) {
371:                    populateType(node, "boolean");
372:                } else {
373:                    rollupTypeUnary(node);
374:                }
375:                return data;
376:            }
377:
378:            public Object visit(ASTPostfixExpression node, Object data) {
379:                super .visit(node, data);
380:                rollupTypeUnary(node);
381:                return data;
382:            }
383:
384:            public Object visit(ASTCastExpression node, Object data) {
385:                super .visit(node, data);
386:                rollupTypeUnary(node);
387:                return data;
388:            }
389:
390:            public Object visit(ASTPrimaryExpression node, Object data) {
391:                super .visit(node, data);
392:                if (node.jjtGetNumChildren() == 1) {
393:                    rollupTypeUnary(node);
394:                } else {
395:                    // TODO OMG, this is complicated.  PrimaryExpression, PrimaryPrefix and PrimarySuffix are all related.
396:                }
397:                return data;
398:            }
399:
400:            public Object visit(ASTPrimaryPrefix node, Object data) {
401:                super .visit(node, data);
402:                if (node.getImage() == null) {
403:                    rollupTypeUnary(node);
404:                } else {
405:                    // TODO OMG, this is complicated.  PrimaryExpression, PrimaryPrefix and PrimarySuffix are all related.
406:                }
407:                return data;
408:            }
409:
410:            public Object visit(ASTPrimarySuffix node, Object data) {
411:                super .visit(node, data);
412:                // TODO OMG, this is complicated.  PrimaryExpression, PrimaryPrefix and PrimarySuffix are all related.
413:                return data;
414:            }
415:
416:            public Object visit(ASTNullLiteral node, Object data) {
417:                // No explicit type
418:                return super .visit(node, data);
419:            }
420:
421:            public Object visit(ASTBooleanLiteral node, Object data) {
422:                populateType(node, "boolean");
423:                return super .visit(node, data);
424:            }
425:
426:            public Object visit(ASTLiteral node, Object data) {
427:                super .visit(node, data);
428:                if (node.jjtGetNumChildren() != 0) {
429:                    rollupTypeUnary(node);
430:                } else {
431:                    if (node.isIntLiteral()) {
432:                        String image = node.getImage();
433:                        if (image.endsWith("l") || image.endsWith("L")) {
434:                            populateType(node, "long");
435:                        } else {
436:                            try {
437:                                Integer.decode(image);
438:                                populateType(node, "int");
439:                            } catch (NumberFormatException e) {
440:                                // Bad literal, 'long' requires use of 'l' or 'L' suffix.
441:                            }
442:                        }
443:                    } else if (node.isFloatLiteral()) {
444:                        String image = node.getImage();
445:                        if (image.endsWith("f") || image.endsWith("F")) {
446:                            populateType(node, "float");
447:                        } else if (image.endsWith("d") || image.endsWith("D")) {
448:                            populateType(node, "double");
449:                        } else {
450:                            try {
451:                                Double.parseDouble(image);
452:                                populateType(node, "double");
453:                            } catch (NumberFormatException e) {
454:                                // Bad literal, 'float' requires use of 'f' or 'F' suffix.
455:                            }
456:                        }
457:                    } else if (node.isCharLiteral()) {
458:                        populateType(node, "char");
459:                    } else if (node.isStringLiteral()) {
460:                        populateType(node, "java.lang.String");
461:                    } else {
462:                        throw new IllegalStateException(
463:                                "PMD error, unknown literal type!");
464:                    }
465:                }
466:                return data;
467:            }
468:
469:            public Object visit(ASTAllocationExpression node, Object data) {
470:                super .visit(node, data);
471:
472:                if ((node.jjtGetNumChildren() >= 2 && node.jjtGetChild(1) instanceof  ASTArrayDimsAndInits)
473:                        || (node.jjtGetNumChildren() >= 3 && node
474:                                .jjtGetChild(2) instanceof  ASTArrayDimsAndInits)) {
475:                    //
476:                    // Classes for Array types cannot be found directly using reflection.
477:                    // As far as I can tell you have to create an array instance of the necessary
478:                    // dimensionality, and then ask for the type from the instance.  OMFG that's ugly.
479:                    //
480:
481:                    // TODO Need to create utility method to allow array type creation which will use
482:                    // caching to avoid repeated object creation.
483:                    // TODO Modify Parser to tell us array dimensions count.
484:                    // TODO Parser seems to do some work to handle arrays in certain case already.
485:                    // Examine those to figure out what's going on, make sure _all_ array scenarios
486:                    // are ultimately covered.  Appears to use a Dimensionable interface to handle
487:                    // only a part of the APIs (not bump), but is implemented several times, so
488:                    // look at refactoring to eliminate duplication.  Dimensionable is also used
489:                    // on AccessNodes for some scenarios, need to account for that.  Might be
490:                    // missing some TypeNode candidates we can add to the AST and have to deal
491:                    // with here (e.g. FormalParameter)?  Plus some existing usages may be
492:                    // incorrect.
493:                } else {
494:                    rollupTypeUnary(node);
495:                }
496:                return data;
497:            }
498:
499:            public Object visit(ASTStatementExpression node, Object data) {
500:                super .visit(node, data);
501:                rollupTypeUnary(node);
502:                return data;
503:            }
504:
505:            // Roll up the type based on type of the first child node.
506:            private void rollupTypeUnary(TypeNode typeNode) {
507:                if (typeNode instanceof  SimpleNode) {
508:                    SimpleNode simpleNode = (SimpleNode) typeNode;
509:                    if (simpleNode.jjtGetNumChildren() >= 1) {
510:                        Node child = simpleNode.jjtGetChild(0);
511:                        if (child instanceof  TypeNode) {
512:                            typeNode.setType(((TypeNode) child).getType());
513:                        }
514:                    }
515:                }
516:            }
517:
518:            // Roll up the type based on type of the first child node using Unary Numeric Promotion per JLS 5.6.1
519:            private void rollupTypeUnaryNumericPromotion(TypeNode typeNode) {
520:                if (typeNode instanceof  SimpleNode) {
521:                    SimpleNode simpleNode = (SimpleNode) typeNode;
522:                    if (simpleNode.jjtGetNumChildren() >= 1) {
523:                        Node child = simpleNode.jjtGetChild(0);
524:                        if (child instanceof  TypeNode) {
525:                            Class<?> type = ((TypeNode) child).getType();
526:                            if (type != null) {
527:                                if ("byte".equals(type.getName())
528:                                        || "short".equals(type.getName())
529:                                        || "char".equals(type.getName())) {
530:                                    populateType(typeNode, "int");
531:                                } else {
532:                                    typeNode.setType(((TypeNode) child)
533:                                            .getType());
534:                                }
535:                            }
536:                        }
537:                    }
538:                }
539:            }
540:
541:            // Roll up the type based on type of the first and second child nodes using Binary Numeric Promotion per JLS 5.6.2
542:            private void rollupTypeBinaryNumericPromotion(TypeNode typeNode) {
543:                if (typeNode instanceof  SimpleNode) {
544:                    SimpleNode simpleNode = (SimpleNode) typeNode;
545:                    if (simpleNode.jjtGetNumChildren() >= 2) {
546:                        Node child1 = simpleNode.jjtGetChild(0);
547:                        Node child2 = simpleNode.jjtGetChild(1);
548:                        if (child1 instanceof  TypeNode
549:                                && child2 instanceof  TypeNode) {
550:                            Class<?> type1 = ((TypeNode) child1).getType();
551:                            Class<?> type2 = ((TypeNode) child2).getType();
552:                            if (type1 != null && type2 != null) {
553:                                // Yeah, String is not numeric, but easiest place to handle it, only affects ASTAdditiveExpression
554:                                if ("java.lang.String".equals(type1.getName())
555:                                        || "java.lang.String".equals(type2
556:                                                .getName())) {
557:                                    populateType(typeNode, "java.lang.String");
558:                                } else if ("boolean".equals(type1.getName())
559:                                        || "boolean".equals(type2.getName())) {
560:                                    populateType(typeNode, "boolean");
561:                                } else if ("double".equals(type1.getName())
562:                                        || "double".equals(type2.getName())) {
563:                                    populateType(typeNode, "double");
564:                                } else if ("float".equals(type1.getName())
565:                                        || "float".equals(type2.getName())) {
566:                                    populateType(typeNode, "float");
567:                                } else if ("long".equals(type1.getName())
568:                                        || "long".equals(type2.getName())) {
569:                                    populateType(typeNode, "long");
570:                                } else {
571:                                    populateType(typeNode, "int");
572:                                }
573:                            } else if (type1 != null || type2 != null) {
574:                                // If one side is known to be a String, then the result is a String
575:                                // Yeah, String is not numeric, but easiest place to handle it, only affects ASTAdditiveExpression
576:                                if ((type1 != null && "java.lang.String"
577:                                        .equals(type1.getName()))
578:                                        || (type2 != null && "java.lang.String"
579:                                                .equals(type2.getName()))) {
580:                                    populateType(typeNode, "java.lang.String");
581:                                }
582:                            }
583:                        }
584:                    }
585:                }
586:            }
587:
588:            private void populateType(TypeNode node, String className) {
589:
590:                String qualifiedName = className;
591:                Class<?> myType = myPrimitiveTypes.get(className);
592:                if (myType == null && importedClasses != null) {
593:                    if (importedClasses.containsKey(className)) {
594:                        qualifiedName = importedClasses.get(className);
595:                    } else if (importedClasses.containsValue(className)) {
596:                        qualifiedName = className;
597:                    }
598:                    if (qualifiedName != null) {
599:                        try {
600:                            /*
601:                             * TODO - the map right now contains just class names. if we
602:                             * use a map of classname/class then we don't have to hit
603:                             * the class loader for every type - much faster
604:                             */
605:                            myType = pmdClassLoader.loadClass(qualifiedName);
606:                        } catch (ClassNotFoundException e) {
607:                            myType = processOnDemand(qualifiedName);
608:                        } catch (NoClassDefFoundError e) {
609:                            myType = processOnDemand(qualifiedName);
610:                        }
611:                    }
612:                }
613:                if (myType != null) {
614:                    node.setType(myType);
615:                }
616:            }
617:
618:            /**
619:             * Check whether the supplied class name exists.
620:             */
621:            public boolean classNameExists(String fullyQualifiedClassName) {
622:                try {
623:                    pmdClassLoader.loadClass(fullyQualifiedClassName);
624:                    return true; //Class found
625:                } catch (ClassNotFoundException e) {
626:                    return false;
627:                }
628:            }
629:
630:            private Class<?> processOnDemand(String qualifiedName) {
631:                for (String entry : importedOnDemand) {
632:                    try {
633:                        return pmdClassLoader.loadClass(entry + "."
634:                                + qualifiedName);
635:                    } catch (Throwable e) {
636:                    }
637:                }
638:                return null;
639:            }
640:
641:            private String getClassName(ASTCompilationUnit node) {
642:                ASTClassOrInterfaceDeclaration classDecl = node
643:                        .getFirstChildOfType(ASTClassOrInterfaceDeclaration.class);
644:                if (classDecl == null) {
645:                    return null; // Happens if this compilation unit only contains an enum
646:                }
647:                if (node.declarationsAreInDefaultPackage()) {
648:                    return classDecl.getImage();
649:                }
650:                ASTPackageDeclaration pkgDecl = node.getPackageDeclaration();
651:                importedOnDemand.add(pkgDecl.getPackageNameImage());
652:                return pkgDecl.getPackageNameImage() + "."
653:                        + classDecl.getImage();
654:            }
655:
656:            /**
657:             * If the outer class wasn't found then we'll get in here
658:             *
659:             * @param node
660:             */
661:            private void populateImports(ASTCompilationUnit node) {
662:                List<ASTImportDeclaration> theImportDeclarations = node
663:                        .findChildrenOfType(ASTImportDeclaration.class);
664:                importedClasses = new HashMap<String, String>();
665:
666:                // go through the imports
667:                for (ASTImportDeclaration anImportDeclaration : theImportDeclarations) {
668:                    String strPackage = anImportDeclaration.getPackageName();
669:                    if (anImportDeclaration.isImportOnDemand()) {
670:                        importedOnDemand.add(strPackage);
671:                    } else if (!anImportDeclaration.isImportOnDemand()) {
672:                        String strName = anImportDeclaration.getImportedName();
673:                        importedClasses.put(strName, strName);
674:                        importedClasses.put(strName.substring(strPackage
675:                                .length() + 1), strName);
676:                    }
677:                }
678:
679:                importedClasses.putAll(myJavaLang);
680:            }
681:
682:            private void populateClassName(ASTCompilationUnit node,
683:                    String className) throws ClassNotFoundException {
684:                node.setType(pmdClassLoader.loadClass(className));
685:                importedClasses = pmdClassLoader.getImportedClasses(className);
686:            }
687:
688:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.