Source Code Cross Referenced for Context.java in  » 6.0-JDK-Modules-sun » tools » sun » tools » tree » 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 » 6.0 JDK Modules sun » tools » sun.tools.tree 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 1994-2003 Sun Microsystems, Inc.  All Rights Reserved.
003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004:         *
005:         * This code is free software; you can redistribute it and/or modify it
006:         * under the terms of the GNU General Public License version 2 only, as
007:         * published by the Free Software Foundation.  Sun designates this
008:         * particular file as subject to the "Classpath" exception as provided
009:         * by Sun in the LICENSE file that accompanied this code.
010:         *
011:         * This code is distributed in the hope that it will be useful, but WITHOUT
012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014:         * version 2 for more details (a copy is included in the LICENSE file that
015:         * accompanied this code).
016:         *
017:         * You should have received a copy of the GNU General Public License version
018:         * 2 along with this work; if not, write to the Free Software Foundation,
019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020:         *
021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022:         * CA 95054 USA or visit www.sun.com if you need additional information or
023:         * have any questions.
024:         */
025:
026:        package sun.tools.tree;
027:
028:        import sun.tools.java.*;
029:        import sun.tools.asm.Assembler;
030:
031:        /**
032:         * WARNING: The contents of this source file are not part of any
033:         * supported API.  Code that depends on them does so at its own risk:
034:         * they are subject to change or removal without notice.
035:         */
036:        public class Context implements  Constants {
037:            Context prev;
038:            Node node;
039:            int varNumber;
040:            LocalMember locals;
041:            LocalMember classes;
042:            MemberDefinition field;
043:            int scopeNumber;
044:            int frameNumber;
045:
046:            /**
047:             * Create the initial context for a method
048:             * The incoming context is inherited from 
049:             */
050:            public Context(Context ctx, MemberDefinition field) {
051:                this .field = field;
052:                if (ctx == null) {
053:                    this .frameNumber = 1;
054:                    this .scopeNumber = 2;
055:                    this .varNumber = 0;
056:                } else {
057:                    this .prev = ctx;
058:                    this .locals = ctx.locals;
059:                    this .classes = ctx.classes;
060:                    if (field != null
061:                            && (field.isVariable() || field.isInitializer())) {
062:                        // Variables and initializers are inlined into a constructor.
063:                        // Model this by inheriting the frame number of the parent,
064:                        // which will contain a "this" parameter.
065:                        this .frameNumber = ctx.frameNumber;
066:                        this .scopeNumber = ctx.scopeNumber + 1;
067:                    } else {
068:                        this .frameNumber = ctx.scopeNumber + 1;
069:                        this .scopeNumber = this .frameNumber + 1;
070:                    }
071:                    this .varNumber = ctx.varNumber;
072:                }
073:            }
074:
075:            /**
076:             * Create a new context, for initializing a class.
077:             */
078:            public Context(Context ctx, ClassDefinition c) {
079:                this (ctx, (MemberDefinition) null);
080:            }
081:
082:            /**
083:             * Create a new nested context, for a block statement
084:             */
085:            Context(Context ctx, Node node) {
086:                if (ctx == null) {
087:                    this .frameNumber = 1;
088:                    this .scopeNumber = 2;
089:                    this .varNumber = 0;
090:                } else {
091:                    this .prev = ctx;
092:                    this .locals = ctx.locals;
093:                    // Inherit local classes from surrounding block,
094:                    // just as for local variables.  Fixes 4074421.
095:                    this .classes = ctx.classes;
096:                    this .varNumber = ctx.varNumber;
097:                    this .field = ctx.field;
098:                    this .frameNumber = ctx.frameNumber;
099:                    this .scopeNumber = ctx.scopeNumber + 1;
100:                    this .node = node;
101:                }
102:            }
103:
104:            public Context(Context ctx) {
105:                this (ctx, (Node) null);
106:            }
107:
108:            /**
109:             * Declare local
110:             */
111:            public int declare(Environment env, LocalMember local) {
112:                //System.out.println(	"DECLARE= " + local.getName() + "=" + varNumber + ", read=" + local.readcount + ", write=" + local.writecount + ", hash=" + local.hashCode());
113:                local.scopeNumber = scopeNumber;
114:                if (this .field == null && idThis.equals(local.getName())) {
115:                    local.scopeNumber += 1; // Anticipate variable or initializer.
116:                }
117:                if (local.isInnerClass()) {
118:                    local.prev = classes;
119:                    classes = local;
120:                    return 0;
121:                }
122:
123:                // Originally the statement:
124:                //
125:                //     local.subModifiers(M_INLINEABLE);
126:                //
127:                // was here with the comment:
128:                //
129:                //     // prevent inlining across call sites
130:                //
131:                // This statement prevented constant local variables from
132:                // inlining. It didn't seem to do anything useful.
133:                //
134:                // The statement has been removed and an assertion has been
135:                // added which mandates that the only members which are marked
136:                // with M_INLINEABLE are the ones for which isConstant() is true.
137:                // (Fix for 4106244.)
138:                //
139:                // Addition to the above comment: they might also be
140:                // final variables initialized with 'this', 'super', or other
141:                // final identifiers.  See VarDeclarationStatement.inline().
142:                // So I've removed the assertion.  The original subModifiers
143:                // call appears to have been there to fix nested class translation
144:                // breakage, which has been fixed in VarDeclarationStatement
145:                // now instead.  (Fix for 4073244.)
146:
147:                local.prev = locals;
148:                locals = local;
149:                local.number = varNumber;
150:                varNumber += local.getType().stackSize();
151:                return local.number;
152:            }
153:
154:            /**
155:             * Get a local variable by name
156:             */
157:            public LocalMember getLocalField(Identifier name) {
158:                for (LocalMember f = locals; f != null; f = f.prev) {
159:                    if (name.equals(f.getName())) {
160:                        return f;
161:                    }
162:                }
163:                return null;
164:            }
165:
166:            /**
167:             * Get the scope number for a reference to a member of this class
168:             * (Larger scope numbers are more deeply nested.)
169:             * @see LocalMember#scopeNumber
170:             */
171:            public int getScopeNumber(ClassDefinition c) {
172:                for (Context ctx = this ; ctx != null; ctx = ctx.prev) {
173:                    if (ctx.field == null)
174:                        continue;
175:                    if (ctx.field.getClassDefinition() == c) {
176:                        return ctx.frameNumber;
177:                    }
178:                }
179:                return -1;
180:            }
181:
182:            private MemberDefinition getFieldCommon(Environment env,
183:                    Identifier name, boolean apparentOnly)
184:                    throws AmbiguousMember, ClassNotFound {
185:                // Note:  This is structured as a pair of parallel lookups.
186:                // If we were to redesign Context, we might prefer to walk
187:                // along a single chain of scopes.
188:
189:                LocalMember lf = getLocalField(name);
190:                int ls = (lf == null) ? -2 : lf.scopeNumber;
191:
192:                ClassDefinition this Class = field.getClassDefinition();
193:
194:                // Also look for a class member in a shallower scope.
195:                for (ClassDefinition c = this Class; c != null; c = c
196:                        .getOuterClass()) {
197:                    MemberDefinition f = c.getVariable(env, name, this Class);
198:                    if (f != null && getScopeNumber(c) > ls) {
199:                        if (apparentOnly && f.getClassDefinition() != c) {
200:                            continue;
201:                        }
202:                        return f;
203:                    }
204:                }
205:
206:                return lf;
207:            }
208:
209:            /**
210:             * Assign a number to a class field.
211:             * (This is used to track definite assignment of some blank finals.)
212:             */
213:            public int declareFieldNumber(MemberDefinition field) {
214:                return declare(null, new LocalMember(field));
215:            }
216:
217:            /**
218:             * Retrieve a number previously assigned by declareMember().
219:             * Return -1 if there was no such assignment in this context.
220:             */
221:            public int getFieldNumber(MemberDefinition field) {
222:                for (LocalMember f = locals; f != null; f = f.prev) {
223:                    if (f.getMember() == field) {
224:                        return f.number;
225:                    }
226:                }
227:                return -1;
228:            }
229:
230:            /**
231:             * Return the local field or member field corresponding to a number.
232:             * Return null if there is no such field.
233:             */
234:            public MemberDefinition getElement(int number) {
235:                for (LocalMember f = locals; f != null; f = f.prev) {
236:                    if (f.number == number) {
237:                        MemberDefinition field = f.getMember();
238:                        return (field != null) ? field : f;
239:                    }
240:                }
241:                return null;
242:            }
243:
244:            /**
245:             * Get a local class by name
246:             */
247:            public LocalMember getLocalClass(Identifier name) {
248:                for (LocalMember f = classes; f != null; f = f.prev) {
249:                    if (name.equals(f.getName())) {
250:                        return f;
251:                    }
252:                }
253:                return null;
254:            }
255:
256:            private MemberDefinition getClassCommon(Environment env,
257:                    Identifier name, boolean apparentOnly) throws ClassNotFound {
258:                LocalMember lf = getLocalClass(name);
259:                int ls = (lf == null) ? -2 : lf.scopeNumber;
260:
261:                // Also look for a class member in a shallower scope.
262:                for (ClassDefinition c = field.getClassDefinition(); c != null; c = c
263:                        .getOuterClass()) {
264:                    // QUERY: We may need to get the inner class from a
265:                    // superclass of 'c'.  This call is prepared to 
266:                    // resolve the superclass if necessary.  Can we arrange
267:                    // to assure that it is always previously resolved?
268:                    // This is one of a small number of problematic calls that
269:                    // requires 'getSuperClass' to resolve superclasses on demand.
270:                    // See 'ClassDefinition.getInnerClass(env, nm)'.
271:                    MemberDefinition f = c.getInnerClass(env, name);
272:                    if (f != null && getScopeNumber(c) > ls) {
273:                        if (apparentOnly && f.getClassDefinition() != c) {
274:                            continue;
275:                        }
276:                        return f;
277:                    }
278:                }
279:
280:                return lf;
281:            }
282:
283:            /**
284:             * Get either a local variable, or a field in a current class
285:             */
286:            public final MemberDefinition getField(Environment env,
287:                    Identifier name) throws AmbiguousMember, ClassNotFound {
288:                return getFieldCommon(env, name, false);
289:            }
290:
291:            /**
292:             * Like getField, except that it skips over inherited fields.
293:             * Used for error checking.
294:             */
295:            public final MemberDefinition getApparentField(Environment env,
296:                    Identifier name) throws AmbiguousMember, ClassNotFound {
297:                return getFieldCommon(env, name, true);
298:            }
299:
300:            /**
301:             * Check if the given field is active in this context.
302:             */
303:            public boolean isInScope(LocalMember field) {
304:                for (LocalMember f = locals; f != null; f = f.prev) {
305:                    if (field == f) {
306:                        return true;
307:                    }
308:                }
309:                return false;
310:            }
311:
312:            /**
313:             * Notice a reference (usually an uplevel one).
314:             * Update the references list of every enclosing class
315:             * which is enclosed by the scope of the target.
316:             * Update decisions about which uplevels to make into fields.
317:             * Return the uplevel reference descriptor, or null if it's local.
318:             * <p>
319:             * The target must be in scope in this context.
320:             * So, call this method only from the check phase.
321:             * (In other phases, the context may be less complete.)
322:             * <p>
323:             * This can and should be called both before and after classes are frozen.
324:             * It should be a no-op, and will raise a compiler error if not.
325:             */
326:            public UplevelReference noteReference(Environment env,
327:                    LocalMember target) {
328:                int targetScopeNumber = !isInScope(target) ? -1
329:                        : target.scopeNumber;
330:
331:                // Walk outward visiting each scope.
332:                // Note each distinct frame (i.e., enclosing method).
333:                // For each frame in which the variable is uplevel,
334:                // record the event in the references list of the enclosing class.
335:                UplevelReference res = null;
336:                int currentFrameNumber = -1;
337:                for (Context refctx = this ; refctx != null; refctx = refctx.prev) {
338:                    if (currentFrameNumber == refctx.frameNumber) {
339:                        continue; // we're processing frames, not contexts
340:                    }
341:                    currentFrameNumber = refctx.frameNumber;
342:                    if (targetScopeNumber >= currentFrameNumber) {
343:                        break; // the target is native to this frame
344:                    }
345:
346:                    // process a frame which is using this variable as an uplevel
347:                    ClassDefinition refc = refctx.field.getClassDefinition();
348:                    UplevelReference r = refc.getReference(target);
349:                    r.noteReference(env, refctx);
350:
351:                    // remember the reference pertaining to the innermost frame
352:                    if (res == null) {
353:                        res = r;
354:                    }
355:                }
356:                return res;
357:            }
358:
359:            /**
360:             * Implement a reference (usually an uplevel one).
361:             * Call noteReference() first, to make sure the reference
362:             * lists are up to date.
363:             * <p>
364:             * The resulting expression tree does not need checking;
365:             * it can be code-generated right away.
366:             * If the reference is not uplevel, the result is an IDENT or THIS.
367:             */
368:            public Expression makeReference(Environment env, LocalMember target) {
369:                UplevelReference r = noteReference(env, target);
370:
371:                // Now create a referencing expression.
372:                if (r != null) {
373:                    return r.makeLocalReference(env, this );
374:                } else if (idThis.equals(target.getName())) {
375:                    return new ThisExpression(0, target);
376:                } else {
377:                    return new IdentifierExpression(0, target);
378:                }
379:            }
380:
381:            /**
382:             * Return a local expression which can serve as the base reference
383:             * for the given field.  If the field is a constructor, return an
384:             * expression for the implicit enclosing instance argument.
385:             * <p>
386:             * Return null if there is no need for such an argument,
387:             * or if there was an error.
388:             */
389:            public Expression findOuterLink(Environment env, long where,
390:                    MemberDefinition f) {
391:                // reqc is the base pointer type required to use f
392:                ClassDefinition fc = f.getClassDefinition();
393:                ClassDefinition reqc = f.isStatic() ? null
394:                        : !f.isConstructor() ? fc : fc.isTopLevel() ? null : fc
395:                                .getOuterClass();
396:                if (reqc == null) {
397:                    return null;
398:                }
399:                return findOuterLink(env, where, reqc, f, false);
400:            }
401:
402:            private static boolean match(Environment env,
403:                    ClassDefinition this c, ClassDefinition reqc) {
404:                try {
405:                    return this c == reqc
406:                            || reqc.implementedBy(env, this c
407:                                    .getClassDeclaration());
408:                } catch (ClassNotFound ee) {
409:                    return false;
410:                }
411:            }
412:
413:            public Expression findOuterLink(Environment env, long where,
414:                    ClassDefinition reqc, MemberDefinition f,
415:                    boolean needExactMatch) {
416:                if (field.isStatic()) {
417:                    if (f == null) {
418:                        // say something like: undefined variable A.this
419:                        Identifier nm = reqc.getName().getFlatName().getName();
420:                        env.error(where, "undef.var", Identifier.lookup(nm,
421:                                idThis));
422:                    } else if (f.isConstructor()) {
423:                        env.error(where, "no.outer.arg", reqc, f
424:                                .getClassDeclaration());
425:                    } else if (f.isMethod()) {
426:                        env.error(where, "no.static.meth.access", f, f
427:                                .getClassDeclaration());
428:                    } else {
429:                        env.error(where, "no.static.field.access", f.getName(),
430:                                f.getClassDeclaration());
431:                    }
432:                    // This is an attempt at error recovery.
433:                    // Unfortunately, the constructor may throw
434:                    // a null pointer exception after failing to resolve
435:                    // 'idThis'.  Since an error message has already been
436:                    // issued previously, this exception is caught and
437:                    // silently ignored.  Ideally, we should avoid throwing
438:                    // the exception.
439:                    Expression e = new ThisExpression(where, this );
440:                    e.type = reqc.getType();
441:                    return e;
442:                }
443:
444:                // use lp to scan for current instances (locals named "this")
445:                LocalMember lp = locals;
446:
447:                // thise is a link expression being built up
448:                Expression this e = null;
449:
450:                // root is the local variable (idThis) at the far left of thise
451:                LocalMember root = null;
452:
453:                // thisc is the class of the link expression thise
454:                ClassDefinition this c = null;
455:
456:                // conCls is the class of the "this", in a constructor
457:                ClassDefinition conCls = null;
458:                if (field.isConstructor()) {
459:                    conCls = field.getClassDefinition();
460:                }
461:
462:                if (!field.isMethod()) {
463:                    this c = field.getClassDefinition();
464:                    this e = new ThisExpression(where, this );
465:                }
466:
467:                while (true) {
468:                    if (this e == null) {
469:                        // start fresh from lp
470:                        while (lp != null && !idThis.equals(lp.getName())) {
471:                            lp = lp.prev;
472:                        }
473:                        if (lp == null) {
474:                            break;
475:                        }
476:                        this e = new ThisExpression(where, lp);
477:                        this c = lp.getClassDefinition();
478:                        root = lp;
479:                        lp = lp.prev;
480:                    }
481:
482:                    // Require exact class identity when called with
483:                    // 'needExactMatch' true.  This is done when checking
484:                    // the '<class>.this' syntax.  Fixes 4102393 and 4133457.
485:                    if (this c == reqc
486:                            || (!needExactMatch && match(env, this c, reqc))) {
487:                        break;
488:                    }
489:
490:                    // move out one step, if the current instance has an outer link
491:
492:                    MemberDefinition outerMember = this c.findOuterMember();
493:                    if (outerMember == null) {
494:                        this e = null;
495:                        continue; // try to find more help in lp
496:                    }
497:                    ClassDefinition prevc = this c;
498:                    this c = prevc.getOuterClass();
499:
500:                    if (prevc == conCls) {
501:                        // Must pick up "this$C" from the constructor argument,
502:                        // not from "this.this$C", since the latter may not be
503:                        // initialized properly.  (This way is cheaper too.)
504:                        Identifier nm = outerMember.getName();
505:                        IdentifierExpression arg = new IdentifierExpression(
506:                                where, nm);
507:                        arg.bind(env, this );
508:                        this e = arg;
509:                    } else {
510:                        this e = new FieldExpression(where, this e, outerMember);
511:                    }
512:                }
513:                if (this e != null) {
514:                    // mark crossed scopes
515:                    // ?????
516:                    //ensureAvailable(root);
517:                    return this e;
518:                }
519:
520:                if (f == null) {
521:                    // say something like: undefined variable A.this
522:                    Identifier nm = reqc.getName().getFlatName().getName();
523:                    env
524:                            .error(where, "undef.var", Identifier.lookup(nm,
525:                                    idThis));
526:                } else if (f.isConstructor()) {
527:                    env.error(where, "no.outer.arg", reqc, f
528:                            .getClassDefinition());
529:                } else {
530:                    env.error(where, "no.static.field.access", f, field);
531:                }
532:
533:                // avoid floodgating:
534:                Expression e = new ThisExpression(where, this );
535:                e.type = reqc.getType();
536:                return e;
537:            }
538:
539:            /**
540:             * Is there a "this" of type reqc in scope?
541:             */
542:            public static boolean outerLinkExists(Environment env,
543:                    ClassDefinition reqc, ClassDefinition this c) {
544:                while (!match(env, this c, reqc)) {
545:                    if (this c.isTopLevel()) {
546:                        return false;
547:                    }
548:                    this c = this c.getOuterClass();
549:                }
550:                return true;
551:            }
552:
553:            /**
554:             * From which enclosing class do members of this type come?
555:             */
556:            public ClassDefinition findScope(Environment env,
557:                    ClassDefinition reqc) {
558:                ClassDefinition this c = field.getClassDefinition();
559:                while (this c != null && !match(env, this c, reqc)) {
560:                    this c = this c.getOuterClass();
561:                }
562:                return this c;
563:            }
564:
565:            /**
566:             * Resolve a type name from within a local scope.
567:             * @see Environment#resolveName
568:             */
569:            Identifier resolveName(Environment env, Identifier name) {
570:                // This logic is pretty much exactly parallel to that of
571:                // Environment.resolveName().
572:                if (name.isQualified()) {
573:                    // Try to resolve the first identifier component,
574:                    // because inner class names take precedence over
575:                    // package prefixes.  (Cf. Environment.resolveName.)
576:                    Identifier rhead = resolveName(env, name.getHead());
577:
578:                    if (rhead.hasAmbigPrefix()) {
579:                        // The first identifier component refers to an
580:                        // ambiguous class.  Limp on.  We throw away the
581:                        // rest of the classname as it is irrelevant.
582:                        // (part of solution for 4059855).
583:                        return rhead;
584:                    }
585:
586:                    if (!env.classExists(rhead)) {
587:                        return env.resolvePackageQualifiedName(name);
588:                    }
589:                    try {
590:                        return env.getClassDefinition(rhead).resolveInnerClass(
591:                                env, name.getTail());
592:                    } catch (ClassNotFound ee) {
593:                        // return partially-resolved name someone else can fail on
594:                        return Identifier.lookupInner(rhead, name.getTail());
595:                    }
596:                }
597:
598:                // Look for an unqualified name in enclosing scopes.
599:                try {
600:                    MemberDefinition f = getClassCommon(env, name, false);
601:                    if (f != null) {
602:                        return f.getInnerClass().getName();
603:                    }
604:                } catch (ClassNotFound ee) {
605:                    // a missing superclass, or something catastrophic
606:                }
607:
608:                // look in imports, etc.
609:                return env.resolveName(name);
610:            }
611:
612:            /**
613:             * Return the name of a lexically apparent type,
614:             * skipping inherited members, and ignoring
615:             * the current pacakge and imports.
616:             * This is used for error checking.
617:             */
618:            public Identifier getApparentClassName(Environment env,
619:                    Identifier name) {
620:                if (name.isQualified()) {
621:                    // Try to resolve the first identifier component,
622:                    // because inner class names take precedence over
623:                    // package prefixes.  (Cf. Environment.resolveName.)
624:                    Identifier rhead = getApparentClassName(env, name.getHead());
625:                    return (rhead == null) ? idNull : Identifier.lookup(rhead,
626:                            name.getTail());
627:                }
628:
629:                // Look for an unqualified name in enclosing scopes.
630:                try {
631:                    MemberDefinition f = getClassCommon(env, name, true);
632:                    if (f != null) {
633:                        return f.getInnerClass().getName();
634:                    }
635:                } catch (ClassNotFound ee) {
636:                    // a missing superclass, or something catastrophic
637:                }
638:
639:                // the enclosing class name is the only apparent package member:
640:                Identifier topnm = field.getClassDefinition().getTopClass()
641:                        .getName();
642:                if (topnm.getName().equals(name)) {
643:                    return topnm;
644:                }
645:                return idNull;
646:            }
647:
648:            /**
649:             * Raise an error if a blank final was definitely unassigned
650:             * on entry to a loop, but has possibly been assigned on the
651:             * back-branch.  If this is the case, the loop may be assigning
652:             * it multiple times.
653:             */
654:            public void checkBackBranch(Environment env, Statement loop,
655:                    Vset vsEntry, Vset vsBack) {
656:                for (LocalMember f = locals; f != null; f = f.prev) {
657:                    if (f.isBlankFinal() && vsEntry.testVarUnassigned(f.number)
658:                            && !vsBack.testVarUnassigned(f.number)) {
659:                        env.error(loop.where, "assign.to.blank.final.in.loop",
660:                                f.getName());
661:                    }
662:                }
663:            }
664:
665:            /**
666:             * Check if a field can reach another field (only considers
667:             * forward references, not the access modifiers).
668:             */
669:            public boolean canReach(Environment env, MemberDefinition f) {
670:                return field.canReach(env, f);
671:            }
672:
673:            /**
674:             * Get the context that corresponds to a label, return null if
675:             * not found.
676:             */
677:            public Context getLabelContext(Identifier lbl) {
678:                for (Context ctx = this ; ctx != null; ctx = ctx.prev) {
679:                    if ((ctx.node != null) && (ctx.node instanceof  Statement)) {
680:                        if (((Statement) (ctx.node)).hasLabel(lbl))
681:                            return ctx;
682:                    }
683:                }
684:                return null;
685:            }
686:
687:            /**
688:             * Get the destination context of a break
689:             */
690:            public Context getBreakContext(Identifier lbl) {
691:                if (lbl != null) {
692:                    return getLabelContext(lbl);
693:                }
694:                for (Context ctx = this ; ctx != null; ctx = ctx.prev) {
695:                    if (ctx.node != null) {
696:                        switch (ctx.node.op) {
697:                        case SWITCH:
698:                        case FOR:
699:                        case DO:
700:                        case WHILE:
701:                            return ctx;
702:                        }
703:                    }
704:                }
705:                return null;
706:            }
707:
708:            /**
709:             * Get the destination context of a continue
710:             */
711:            public Context getContinueContext(Identifier lbl) {
712:                if (lbl != null) {
713:                    return getLabelContext(lbl);
714:                }
715:                for (Context ctx = this ; ctx != null; ctx = ctx.prev) {
716:                    if (ctx.node != null) {
717:                        switch (ctx.node.op) {
718:                        case FOR:
719:                        case DO:
720:                        case WHILE:
721:                            return ctx;
722:                        }
723:                    }
724:                }
725:                return null;
726:            }
727:
728:            /**
729:             * Get the destination context of a return (the method body)
730:             */
731:            public CheckContext getReturnContext() {
732:                for (Context ctx = this ; ctx != null; ctx = ctx.prev) {
733:                    // The METHOD node is set up by Statement.checkMethod().
734:                    if (ctx.node != null && ctx.node.op == METHOD) {
735:                        return (CheckContext) ctx;
736:                    }
737:                }
738:                return null;
739:            }
740:
741:            /**
742:             * Get the context of the innermost surrounding try-block.
743:             * Consider only try-blocks contained within the same method.
744:             * (There could be others when searching from within a method
745:             * of a local class, but they are irrelevant to our purpose.)
746:             * This is used for recording DA/DU information preceding
747:             * all abnormal transfers of control: break, continue, return,
748:             * and throw.  
749:             */
750:            public CheckContext getTryExitContext() {
751:                for (Context ctx = this ; ctx != null && ctx.node != null
752:                        && ctx.node.op != METHOD; ctx = ctx.prev) {
753:                    if (ctx.node.op == TRY) {
754:                        return (CheckContext) ctx;
755:                    }
756:                }
757:                return null;
758:            }
759:
760:            /**
761:             * Get the nearest inlined context
762:             */
763:            Context getInlineContext() {
764:                for (Context ctx = this ; ctx != null; ctx = ctx.prev) {
765:                    if (ctx.node != null) {
766:                        switch (ctx.node.op) {
767:                        case INLINEMETHOD:
768:                        case INLINENEWINSTANCE:
769:                            return ctx;
770:                        }
771:                    }
772:                }
773:                return null;
774:            }
775:
776:            /**
777:             * Get the context of a field that is being inlined
778:             */
779:            Context getInlineMemberContext(MemberDefinition field) {
780:                for (Context ctx = this ; ctx != null; ctx = ctx.prev) {
781:                    if (ctx.node != null) {
782:                        switch (ctx.node.op) {
783:                        case INLINEMETHOD:
784:                            if (((InlineMethodExpression) ctx.node).field
785:                                    .equals(field)) {
786:                                return ctx;
787:                            }
788:                            break;
789:                        case INLINENEWINSTANCE:
790:                            if (((InlineNewInstanceExpression) ctx.node).field
791:                                    .equals(field)) {
792:                                return ctx;
793:                            }
794:                        }
795:                    }
796:                }
797:                return null;
798:            }
799:
800:            /**
801:             * Remove variables from the vset set  that are no longer part of 
802:             * this context.
803:             */
804:            public final Vset removeAdditionalVars(Vset vset) {
805:                return vset.removeAdditionalVars(varNumber);
806:            }
807:
808:            public final int getVarNumber() {
809:                return varNumber;
810:            }
811:
812:            /**
813:             * Return the number of the innermost current instance reference.
814:             */
815:            public int getThisNumber() {
816:                LocalMember this f = getLocalField(idThis);
817:                if (this f != null
818:                        && this f.getClassDefinition() == field
819:                                .getClassDefinition()) {
820:                    return this f.number;
821:                }
822:                // this is a variable; there is no "this" (should not happen)
823:                return varNumber;
824:            }
825:
826:            /**
827:             * Return the field containing the present context.
828:             */
829:            public final MemberDefinition getField() {
830:                return field;
831:            }
832:
833:            /**
834:             * Extend an environment with the given context.
835:             * The resulting environment behaves the same as
836:             * the given one, except that resolveName() takes
837:             * into account local class names in this context.
838:             */
839:            public static Environment newEnvironment(Environment env,
840:                    Context ctx) {
841:                return new ContextEnvironment(env, ctx);
842:            }
843:        }
844:
845:        final class ContextEnvironment extends Environment {
846:            Context ctx;
847:            Environment innerEnv;
848:
849:            ContextEnvironment(Environment env, Context ctx) {
850:                super (env, env.getSource());
851:                this .ctx = ctx;
852:                this .innerEnv = env;
853:            }
854:
855:            public Identifier resolveName(Identifier name) {
856:                return ctx.resolveName(innerEnv, name);
857:            }
858:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.