Source Code Cross Referenced for JavaDebugInterpreter.java in  » IDE » DrJava » edu » rice » cs » drjava » model » repl » 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 » DrJava » edu.rice.cs.drjava.model.repl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*BEGIN_COPYRIGHT_BLOCK
002:         *
003:         * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004:         * All rights reserved.
005:         * 
006:         * Redistribution and use in source and binary forms, with or without
007:         * modification, are permitted provided that the following conditions are met:
008:         *    * Redistributions of source code must retain the above copyright
009:         *      notice, this list of conditions and the following disclaimer.
010:         *    * Redistributions in binary form must reproduce the above copyright
011:         *      notice, this list of conditions and the following disclaimer in the
012:         *      documentation and/or other materials provided with the distribution.
013:         *    * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014:         *      names of its contributors may be used to endorse or promote products
015:         *      derived from this software without specific prior written permission.
016:         * 
017:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018:         * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019:         * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020:         * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021:         * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022:         * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023:         * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024:         * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025:         * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026:         * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027:         * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028:         *
029:         * This software is Open Source Initiative approved Open Source Software.
030:         * Open Source Initative Approved is a trademark of the Open Source Initiative.
031:         * 
032:         * This file is part of DrJava.  Download the current version of this project
033:         * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034:         * 
035:         * END_COPYRIGHT_BLOCK*/
036:
037:        package edu.rice.cs.drjava.model.repl;
038:
039:        import koala.dynamicjava.interpreter.error.*;
040:        import koala.dynamicjava.interpreter.*;
041:        import koala.dynamicjava.interpreter.context.*;
042:        import koala.dynamicjava.tree.*;
043:
044:        import java.util.List;
045:        import java.util.LinkedList;
046:        import java.util.Iterator;
047:        import java.util.StringTokenizer;
048:        import java.lang.reflect.*;
049:
050:        import edu.rice.cs.drjava.model.repl.newjvm.ClassPathManager;
051:        import edu.rice.cs.util.UnexpectedException;
052:
053:        /** This class is an extension to DynamicJavaAdapter that allows us to process expressions involving the "this"
054:         *  keyword correctly in the current debug interpreter context. This allows users to debug outer classes and their
055:         *  fields using the usual Java syntax of outerclass.this. This is done by holding on to the class name of "this" 
056:         *  and by translating references to outer instance classes to field accesses in the form "this.this$N.this$N-1...".
057:         *
058:         *  This class is loaded in the Interpreter JVM, not the Main JVM.
059:         *  (Do not use DrJava's config framework here.)
060:         *
061:         * @version $Id: JavaDebugInterpreter.java 4255 2007-08-28 19:17:37Z mgricken $
062:         */
063:        public class JavaDebugInterpreter extends DynamicJavaAdapter {
064:
065:            /** This interpreter's name. */
066:            protected final String _name;
067:
068:            /** The class name of the "this" object for the currently suspended thread. */
069:            protected String _this ClassName;
070:
071:            /** The name of the package containing _this, if any. */
072:            protected String _this PackageName;
073:
074:            /** Extends IdentityVisitor to convert all instances of ThisExpressions in the tree to either QualifiedName or an
075:             *  ObjectFieldAccess
076:             */
077:            protected IdentityVisitor _translationVisitor;
078:
079:            /** Creates a new debug interpreter.
080:             *  @param name the name of the interpreter
081:             *  @param className the class name of the current context of "this"
082:             */
083:            public JavaDebugInterpreter(String name, String className) {
084:                super (new ClassPathManager());
085:                _name = name;
086:                setClassName(className);
087:                _translationVisitor = makeTranslationVisitor();
088:            }
089:
090:            /** Processes the tree before evaluating it. The translation visitor visits each node in the tree for the given
091:             *  statement or expression and converts the necessary nodes.
092:             *  @param node Tree to process
093:             */
094:            public Node processTree(Node node) {
095:                return node.acceptVisitor(_translationVisitor);
096:            }
097:
098:            public GlobalContext makeGlobalContext(TreeInterpreter i) {
099:                return new GlobalContext(i) {
100:                    public boolean exists(String name) {
101:                        return (super .exists(name))
102:                                || (_getObjectFieldAccessForField(name, this ) != null)
103:                                || (_getStaticFieldAccessForField(name, this ) != null)
104:                                || (_getReferenceTypeForField(name, this ) != null);
105:                    }
106:                };
107:            }
108:
109:            /**
110:             * Returns whether the given className corresponds to a class
111:             * that is anonymous or has an anonymous enclosing class.
112:             * @param className the className to check
113:             * @return whether the class is anonymous
114:             */
115:            private boolean hasAnonymous(String className) {
116:                StringTokenizer st = new StringTokenizer(className, "$");
117:                while (st.hasMoreElements()) {
118:                    String currToken = st.nextToken();
119:                    try {
120:                        //        Integer anonymousNum =
121:                        Integer.valueOf(currToken);
122:                        return true;
123:                    } catch (NumberFormatException nfe) {
124:                        // fall through to false because the token cannot be parsed
125:                    }
126:                }
127:                return false;
128:            }
129:
130:            /** Returns the fully qualified class name for "this". It will append the package name onto the class name
131:             *  if there is a package name.
132:             */
133:            private String _getFullyQualifiedClassNameForThis() {
134:                String cName = _this ClassName;
135:                if (!_this PackageName.equals("")) {
136:                    cName = _this PackageName + "." + cName;
137:                }
138:                return cName;
139:            }
140:
141:            private Class<?> _loadClassForThis(Context context) {
142:                try {
143:                    return context
144:                            .lookupClass(_getFullyQualifiedClassNameForThis());
145:                } catch (ClassNotFoundException e) {
146:                    throw new UnexpectedException(e);
147:                }
148:            }
149:
150:            /** Given a field, looks at enclosing classes until it finds one that contains the field. It returns the 
151:             *  ObjectFieldAccess that represents the field.
152:             *  @param field the name of the field
153:             *  @param context the context
154:             *  @return the ObjectFieldAccess that represents the field or null if it cannot find the field in any enclosing
155:             *  class.
156:             */
157:            protected ObjectFieldAccess _getObjectFieldAccessForField(
158:                    String field, Context context) {
159:                AbstractTypeChecker tc = makeTypeChecker(context);
160:                int numDollars = _getNumDollars(_this ClassName);
161:
162:                // Check if this has an anonymous inner class
163:                if (hasAnonymous(_this ClassName)) {
164:                    // Get the class
165:                    Class<?> c = _loadClassForThis(context);
166:                    Field[] fields = c.getDeclaredFields();
167:
168:                    // Check for a field that begins with this$
169:                    for (int i = 0; i < fields.length; i++) {
170:                        if (fields[i].getName().startsWith("this$")) {
171:                            String fieldName = fields[i].getName();
172:                            int lastIndex = fieldName.lastIndexOf("$");
173:                            numDollars = Integer.valueOf(
174:                                    fieldName.substring(lastIndex + 1,
175:                                            fieldName.length())).intValue() + 1;
176:                            break;
177:                        }
178:                    }
179:                }
180:                for (int i = 0; i <= numDollars; i++) {
181:                    Expression expr = _buildObjectFieldAccess(i, numDollars);
182:                    Expression newExpr = new ObjectFieldAccess(expr, field);
183:                    try {
184:                        // the type checker will tell us if it's a field
185:                        tc.visit((ObjectFieldAccess) newExpr);
186:                        return (ObjectFieldAccess) newExpr;
187:                    } catch (ExecutionError e) {
188:                        // try concatenating "val$" to the beginning of field
189:                        newExpr = new ObjectFieldAccess(expr, "val$" + field);
190:                        try {
191:                            // the type checker will tell us if it's a field
192:                            tc.visit((ObjectFieldAccess) newExpr);
193:                            return (ObjectFieldAccess) newExpr;
194:                        } catch (ExecutionError e2) {
195:                            // do nothing, try an outer class
196:                        }
197:                    }
198:                }
199:
200:                return null;
201:            }
202:
203:            /**
204:             * Given a method, looks at enclosing classes until it finds
205:             * one that contains the method. It returns the ObjectMethodCall
206:             * that represents the method.
207:             * @param method the method
208:             * @param context the context
209:             * @return the ObjectMethodCall that represents the method or null
210:             * if it cannot find the method in any enclosing class.
211:             */
212:            protected ObjectMethodCall _getObjectMethodCallForFunction(
213:                    MethodCall method, Context context) {
214:                AbstractTypeChecker tc = makeTypeChecker(context);
215:                int numDollars = _getNumDollars(_this ClassName);
216:                String methodName = method.getMethodName();
217:                List<Expression> args = method.getArguments();
218:
219:                // Check if this has an anonymous inner class
220:                if (hasAnonymous(_this ClassName)) {
221:                    // Get the class
222:                    Class<?> c = _loadClassForThis(context);
223:                    Field[] fields = c.getDeclaredFields();
224:
225:                    // Check for a field that begins with this$
226:                    for (int i = 0; i < fields.length; i++) {
227:                        if (fields[i].getName().startsWith("this$")) {
228:                            String fieldName = fields[i].getName();
229:                            int lastIndex = fieldName.lastIndexOf("$");
230:                            numDollars = Integer.valueOf(
231:                                    fieldName.substring(lastIndex + 1,
232:                                            fieldName.length())).intValue() + 1;
233:                            break;
234:                        }
235:                    }
236:                }
237:                for (int i = 0; i <= numDollars; i++) {
238:                    Expression expr = _buildObjectFieldAccess(i, numDollars);
239:                    expr = new ObjectMethodCall(expr, methodName, args, null,
240:                            0, 0, 0, 0);
241:                    try {
242:                        // the type checker will tell us if it's a field
243:                        tc.visit((ObjectMethodCall) expr);
244:                        return (ObjectMethodCall) expr;
245:                    } catch (ExecutionError e2) {
246:                        // do nothing, try an outer class
247:                    }
248:                }
249:                return null;
250:            }
251:
252:            /**
253:             * Given a field in a static context, looks at enclosing classes until it
254:             * finds one that contains the field. It returns the StaticFieldAccess
255:             * that represents the field.
256:             * @param field the name of the field
257:             * @param context the context
258:             * @return the StaticFieldAccess that represents the field or null
259:             * if it cannot find the field in any enclosing class.
260:             */
261:            protected StaticFieldAccess _getStaticFieldAccessForField(
262:                    String field, Context context) {
263:                AbstractTypeChecker tc = makeTypeChecker(context);
264:                int numDollars = _getNumDollars(_this ClassName);
265:                String currClass = _getFullyQualifiedClassNameForThis();
266:                int index = currClass.length();
267:                // iterate outward trying to find the field
268:                for (int i = 0; i <= numDollars; i++) {
269:                    currClass = currClass.substring(0, index);
270:                    ReferenceType rt = new ReferenceType(currClass);
271:                    StaticFieldAccess expr = new StaticFieldAccess(rt, field);
272:                    try {
273:                        // the type checker will tell us if it's a field
274:                        tc.visit(expr);
275:                        return expr;
276:                    } catch (ExecutionError e2) {
277:                        // try an outer class
278:                        index = currClass.lastIndexOf("$");
279:                    }
280:                }
281:                return null;
282:            }
283:
284:            /**
285:             * Given a method in a static context, looks at enclosing classes until it
286:             * finds one that contains the method. It returns the StaticMethodCall
287:             * that represents the method.
288:             * @param method the method
289:             * @param context the context
290:             * @return the StaticMethodCall that represents the method or null
291:             * if it cannot find the method in any enclosing class.
292:             */
293:            protected StaticMethodCall _getStaticMethodCallForFunction(
294:                    MethodCall method, Context context) {
295:                AbstractTypeChecker tc = makeTypeChecker(context);
296:                int numDollars = _getNumDollars(_this ClassName);
297:                String methodName = method.getMethodName();
298:                List<Expression> args = method.getArguments();
299:                String currClass = _getFullyQualifiedClassNameForThis();
300:                int index = currClass.length();
301:                // iterate outward trying to find the method
302:                for (int i = 0; i <= numDollars; i++) {
303:                    currClass = currClass.substring(0, index);
304:                    ReferenceType rt = new ReferenceType(currClass);
305:                    StaticMethodCall expr = new StaticMethodCall(rt,
306:                            methodName, args);
307:                    try {
308:                        // the type checker will tell us if it's a field
309:                        tc.visit(expr);
310:                        return expr;
311:                    } catch (ExecutionError e2) {
312:                        // try an outer class
313:                        index = currClass.lastIndexOf("$");
314:                    }
315:                }
316:                return null;
317:            }
318:
319:            /**
320:             * Given the name of an not fully qualified outer class, return the fully qualified
321:             * ReferenceType that corresponds to that class. This is called when the user
322:             * references a static field of an outer class.
323:             * @param field the name of the not fully qualified outer class
324:             * @param context the context
325:             * @return the ReferenceType that represents the field(in this case,
326:             * really a class) or null if it cannot load the corresponding class in the
327:             * class loader.
328:             */
329:            protected ReferenceType _getReferenceTypeForField(String field,
330:                    Context context) {
331:                AbstractTypeChecker tc = makeTypeChecker(context);
332:                int index = _indexOfWithinBoundaries(
333:                        _getFullyQualifiedClassNameForThis(), field);
334:                if (index != -1) {
335:                    // field may be of form outerClass$innerClass or
336:                    // package.innerClass.
337:                    // We want to match the inner most class.
338:                    int lastDollar = field.lastIndexOf("$");
339:                    int lastDot = field.lastIndexOf(".");
340:                    if (lastDollar != -1) {
341:                        field = field.substring(lastDollar + 1, field.length());
342:                    } else {
343:                        if (lastDot != -1) {
344:                            field = field
345:                                    .substring(lastDot + 1, field.length());
346:                        }
347:                    }
348:                    LinkedList<IdentifierToken> list = new LinkedList<IdentifierToken>();
349:                    StringTokenizer st = new StringTokenizer(
350:                            _getFullyQualifiedClassNameForThis(), "$.");
351:                    String currString = st.nextToken();
352:                    while (!currString.equals(field)) {
353:                        list.add(new Identifier(currString));
354:                        currString = st.nextToken();
355:                    }
356:                    list.add(new Identifier(field));
357:                    ReferenceType rt = new ReferenceType(list);
358:                    try {
359:                        // the type checker will tell us if it's a class
360:                        tc.visit(rt);
361:                        return rt;
362:                    } catch (ExecutionError e) {
363:                        return null;
364:                    }
365:                } else {
366:                    return null;
367:                }
368:            }
369:
370:            /** Sets the class name of "this", parsing out the package name. */
371:            protected void setClassName(String className) {
372:                int indexLastDot = className.lastIndexOf(".");
373:                if (indexLastDot == -1)
374:                    _this PackageName = "";
375:                else
376:                    _this PackageName = className.substring(0, indexLastDot);
377:                _this ClassName = className.substring(indexLastDot + 1);
378:            }
379:
380:            /** Helper method to convert a ThisExpression to a QualifiedName. Allows us to redefine "this" in a debug interpreter.
381:             *  @param node ThisExpression
382:             *  @return corresponding QualifiedName
383:             */
384:            protected QualifiedName _convertThisToName(ThisExpression node) {
385:                // Can't parametize this List for some reason.
386:                List<IdentifierToken> ids = new LinkedList<IdentifierToken>(); // Add parameterization <Identifier>.
387:                ids.add(new Identifier("this", node.getBeginLine(), node
388:                        .getBeginColumn(), node.getEndLine(), node
389:                        .getEndColumn()));
390:                return new QualifiedName(ids, node.getFilename(), // TODO: change getFilename to GetFileName in DynamicJava
391:                        node.getBeginLine(), node.getBeginColumn(), node
392:                                .getEndLine(), node.getEndColumn());
393:            }
394:
395:            /**
396:             * Helper method to convert a ThisExpression to a FieldAccess.
397:             * Allows us to access fields of outer classes in a debug interpreter.
398:             * @param node ThisExpression
399:             * @return corresponding FieldAccess
400:             */
401:            protected Expression _convertThisToObjectFieldAccess(
402:                    ThisExpression node) {
403:                String className = node.getClassName();
404:                int numToWalk = verifyClassName(className);
405:                int numDollars = _getNumDollars(_this ClassName);
406:                // if numToWalk == 0, just return "this"
407:                if (numToWalk == -1) {
408:                    throw new ExecutionError("malformed.expression", node);
409:                } else {
410:                    return _buildObjectFieldAccess(numToWalk, numDollars);
411:                }
412:            }
413:
414:            /**
415:             * Builds a ThisExpression that has no class name.
416:             * @return an unqualified ThisExpression
417:             */
418:            protected ThisExpression buildUnqualifiedThis() {
419:                LinkedList<IdentifierToken> ids = new LinkedList<IdentifierToken>();
420:                return new ThisExpression(ids, "", 0, 0, 0, 0);
421:            }
422:
423:            /**
424:             * Helper method to build an ObjectFieldAccess for a ThisExpression
425:             * given the number of classes to walk and the number of dollars.
426:             * @param numToWalk number of outer classes to walk through
427:             * @param numDollars numer of dollars in _thisClassName
428:             * @return a QualifiedName is numtoWalk is zero or an ObjectFieldAccess
429:             */
430:            private Expression _buildObjectFieldAccess(int numToWalk,
431:                    int numDollars) {
432:                if (numToWalk == 0) {
433:                    return _convertThisToName(buildUnqualifiedThis());
434:                } else {
435:                    return new ObjectFieldAccess(_buildObjectFieldAccess(
436:                            numToWalk - 1, numDollars), "this$"
437:                            + (numDollars - numToWalk));
438:                }
439:            }
440:
441:            /**
442:             * Returns the index of subString within string if the substring is
443:             * either bounded by the ends of string or by $'s.
444:             * @param string the super string
445:             * @param subString the subString
446:             * @return the index of string that subString begins at or -1
447:             * if subString is not in string or is not validly bounded
448:             */
449:            private int _indexOfWithinBoundaries(String string, String subString) {
450:                int index = string.indexOf(subString);
451:                if (index == -1) {
452:                    return index;
453:                }
454:                // subString is somewhere in string
455:                else {
456:                    // ends at legal boundary
457:                    if (((string.length() == subString.length() + index) || (string
458:                            .charAt(subString.length() + index) == '$'))
459:                            &&
460:                            // begins at legal boundary
461:                            ((index == 0) || (string.charAt(index - 1) == '$') || (string
462:                                    .charAt(index - 1) == '.'))) {
463:                        return index;
464:                    } else {
465:                        return -1;
466:                    }
467:                }
468:            }
469:
470:            /**
471:             * Returns the number of dollar characters in
472:             * a given String.
473:             * @param className the string to be examined
474:             * @return the number of dollars in the string
475:             */
476:            private int _getNumDollars(String className) {
477:                int numDollars = 0;
478:                int index = className.indexOf("$");
479:                while (index != -1) {
480:                    numDollars++;
481:                    index = className.indexOf("$", index + 1);
482:                }
483:                return numDollars;
484:            }
485:
486:            /**
487:             * Checks if the className passed in is a valid className.
488:             * @param className the className of the ThisExpression
489:             * @return the number of outer classes to walk out to
490:             */
491:            protected int verifyClassName(String className) {
492:                boolean hasPackage = false;
493:                if (!_this PackageName.equals("")) {
494:                    int index = className.indexOf(_this PackageName);
495:                    if (index == 0) {
496:                        hasPackage = true;
497:                        // className begins with the package name
498:                        index = _this PackageName.length() + 1;
499:                        if (index >= className.length()) {
500:                            return -1;
501:                        }
502:                        // strip off the package
503:                        className = className.substring(index, className
504:                                .length());
505:                    }
506:                }
507:
508:                className = className.replace('.', '$');
509:                int indexWithBoundaries = _indexOfWithinBoundaries(
510:                        _this ClassName, className);
511:                if ((hasPackage && indexWithBoundaries != 0)
512:                        || (indexWithBoundaries == -1)) {
513:                    return -1;
514:                } else {
515:                    return _getNumDollars(_this ClassName
516:                            .substring(indexWithBoundaries + className.length()));
517:                }
518:            }
519:
520:            /**
521:             * Converts the ThisExpression to a QualifiedName
522:             * if it has no class name or an ObjectFieldAccess
523:             * if it does.
524:             * @param node the expression to visit
525:             * @return the converted form of the node
526:             */
527:            protected Expression visitThis(ThisExpression node) {
528:                if (node.getClassName().equals("")) {
529:                    return _convertThisToName(node);
530:                } else {
531:                    return _convertThisToObjectFieldAccess(node);
532:                }
533:            }
534:
535:            /**
536:             * Makes an anonymous IdentityVisitor that overrides
537:             * visit for a ThisExpresssion to convert it to
538:             * either a QualifiedName or an ObjectFieldAccess
539:             */
540:            public IdentityVisitor makeTranslationVisitor() {
541:                return new IdentityVisitor() {
542:                    public Node visit(ThisExpression node) {
543:                        Expression e = visitThis(node);
544:                        if (e instanceof  QualifiedName) {
545:                            return visit((QualifiedName) e);
546:                        } else if (e instanceof  ObjectFieldAccess) {
547:                            return visit((ObjectFieldAccess) e);
548:                        } else {
549:                            throw new UnexpectedException(
550:                                    new IllegalArgumentException(
551:                                            "Illegal type of Expression"));
552:                        }
553:                    }
554:                };
555:            }
556:
557:            //  private Class _getClassForType(Type type, Context context) {
558:            //    Class c = (ClassProperty(NodeProperties.TYPE);
559:            //    if (c != null) {
560:            //      return c;
561:            //    }
562:            //    else if (type instanceof PrimitiveType) {
563:            //      return ((PrimitiveType)type).getValue();
564:            //    }
565:            //    else if (type instanceof ReferenceType) {
566:            //      ReferenceType rt = (ReferenceType) type;
567:            //      try {
568:            //        return context.lookupClass(rt.getRepresentation());
569:            //      }
570:            //      catch (ClassNotFoundException e) {
571:            //        rt.setProperty(NodeProperties.ERROR_STRINGS,
572:            //                       new String[] { rt.getRepresentation() });
573:            //        throw new ExecutionError("undefined.class", rt);
574:            //      }
575:            //    }
576:            //    else {
577:            //      // type should be an ArrayType
578:            //      Type eType = ((ArrayType)type).getElementType();
579:            //      c = _getClassForType(eType, context);
580:            //      return java.lang.reflect.Array.newInstance(c, 0).getClass();
581:            //    }
582:            //  }
583:
584:            /**
585:             * Factory method to make a new NameChecker that tries to find the
586:             * right scope for QualifiedNames.
587:             * @param nameContext Context for the NameVisitor
588:             * @return the visitor
589:             */
590:            public NameVisitor makeNameVisitor(final Context nameContext) {
591:                return new NameVisitor(nameContext) {
592:                    //        try {
593:                    //          return super.visit(node);
594:                    //        }
595:                    //        catch (ExecutionError e) {
596:                    //          System.out.println(e.getMessage());
597:                    //          if (e.getMessage().startsWith("Redefinition of")) {
598:                    //            Type type = node.getType();
599:                    //            String name = node.getName();
600:                    //            Class oldClass = (Class)nameContext.get(name);
601:                    //            Class newClass = _getClassForType(type, nameContext);
602:                    //            if (oldClass.equals(newClass)) {
603:                    //              // This is a redefinition of the same variable
604:                    //              // with the same type. Allow the user to do
605:                    //              // this so make a new SimpleAssignExpression
606:                    //              Identifier id = new Identifier(name);
607:                    //              LinkedList ids = new LinkedList();
608:                    //              ids.add(id);
609:                    //              QualifiedName qName = new QualifiedName(ids);
610:                    //              return new SimpleAssignExpression(qName, node.getInitializer());
611:                    //            }
612:                    //          }
613:                    //          throw e;
614:                    //        }
615:                    //      }
616:                    public Node visit(QualifiedName node) {
617:                        try {
618:                            return super .visit(node);
619:                        } catch (ExecutionError e) {
620:                            // This error is thrown only if this QualifiedName is not
621:                            // a local variable or a class
622:                            final List<IdentifierToken> ids = node
623:                                    .getIdentifiers();
624:                            final Iterator<IdentifierToken> iter = ids
625:                                    .iterator();
626:                            final StringBuilder fieldBuf = new StringBuilder(
627:                                    iter.next().image());
628:                            while (iter.hasNext()) {
629:                                IdentifierToken t = iter.next();
630:                                fieldBuf.append('$').append(t.image());
631:                            }
632:                            String field = fieldBuf.toString();
633:                            if (nameContext.isDefined("this")) {
634:                                // Check if it's a field or outer field if we're not in a
635:                                // static context.
636:                                ObjectFieldAccess ofa = _getObjectFieldAccessForField(
637:                                        field, nameContext);
638:                                if (ofa != null)
639:                                    return ofa;
640:                            } else {
641:                                // We're in a static context.
642:                                StaticFieldAccess sfa = _getStaticFieldAccessForField(
643:                                        field, nameContext);
644:                                if (sfa != null)
645:                                    return sfa;
646:                                else {
647:                                    // This is possibly a substring of our current context's class name.
648:                                    // (e.g. The user is trying to evaluate MonkeyOuter.someField and we
649:                                    // have to convert MonkeyOuter to MonkeyMostOuter$MonkeyOuter)
650:                                    // Try qualifying it.
651:                                    ReferenceType rt = _getReferenceTypeForField(
652:                                            field, nameContext);
653:                                    if (rt != null)
654:                                        return rt;
655:                                }
656:                            }
657:                            // Didn't find this field in any outer class. Throw original exception.
658:                            throw e;
659:                        }
660:                    }
661:
662:                    public Node visit(ObjectMethodCall node) {
663:                        MethodCall method = (MethodCall) super .visit(node);
664:                        // if (method != null) this object method call is either a method with no
665:                        // class before it or is a static method call
666:                        if (method != null) {
667:                            if (method instanceof  StaticMethodCall) {
668:                                return method;
669:                            }
670:                            // now we know that method is a FunctionCall
671:                            else if (nameContext.isDefined("this")) {
672:                                ObjectMethodCall omc = _getObjectMethodCallForFunction(
673:                                        method, nameContext);
674:                                if (omc != null) {
675:                                    return omc;
676:                                } else {
677:                                    return method;
678:                                }
679:                            }
680:                            // it's a FunctionCall from a static context
681:                            else {
682:                                StaticMethodCall smc = _getStaticMethodCallForFunction(
683:                                        method, nameContext);
684:                                if (smc != null) {
685:                                    return smc;
686:                                } else {
687:                                    return method;
688:                                }
689:                            }
690:                        } else {
691:                            return null;
692:                        }
693:                    }
694:                };
695:            }
696:
697:            /**
698:             * Factory method to make a new TypeChecker that treats "this" as a variable.
699:             * @param context the context
700:             * @return visitor the visitor
701:             */
702:            public AbstractTypeChecker makeTypeChecker(final Context context) {
703:                if (Float.valueOf(System
704:                        .getProperty("java.specification.version")) < 1.5) {
705:                    return new TypeChecker14(context) {
706:                        /**
707:                         * Visits a QualifiedName, returning our class if it is "this"
708:                         * @param node the node to visit
709:                         */
710:                        public Class<?> visit(QualifiedName node) {
711:                            String var = node.getRepresentation();
712:                            if ("this".equals(var)) {
713:                                //            String cName = _thisClassName.replace('$', '.');
714:                                //            if (!_thisPackageName.equals("")) {
715:                                //              cName = _thisPackageName + "." + cName;
716:                                //            }
717:                                //            Class c = context.lookupClass(cName);
718:                                Class<?> c = _loadClassForThis(context);
719:                                node.setProperty(NodeProperties.TYPE, c);
720:                                node.setProperty(NodeProperties.MODIFIER,
721:                                        context.getModifier(node));
722:                                return c;
723:                            } else
724:                                return super .visit(node);
725:                        }
726:
727:                    };
728:                } else {
729:                    return new TypeChecker15(context) {
730:                        /**
731:                         * Visits a QualifiedName, returning our class if it is "this"
732:                         * @param node the node to visit
733:                         */
734:                        public Class<?> visit(QualifiedName node) {
735:                            String var = node.getRepresentation();
736:                            if ("this".equals(var)) {
737:                                //            String cName = _thisClassName.replace('$', '.');
738:                                //            if (!_thisPackageName.equals("")) {
739:                                //              cName = _thisPackageName + "." + cName;
740:                                //            }
741:                                //            Class c = context.lookupClass(cName);
742:                                Class<?> c = _loadClassForThis(context);
743:                                node.setProperty(NodeProperties.TYPE, c);
744:                                node.setProperty(NodeProperties.MODIFIER,
745:                                        context.getModifier(node));
746:                                return c;
747:                            } else
748:                                return super.visit(node);
749:                        }
750:
751:                    };
752:                }
753:            }
754:
755:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.