EMMA Coverage Report (generated Thu Dec 06 15:52:10 GMT 2007)
[all classes][com.sun.tools.javac.code]

COVERAGE SUMMARY FOR SOURCE FILE [Scope.java]

nameclass, %method, %block, %line, %
Scope.java62%  (5/8)47%  (24/51)42%  (379/909)45%  (77.8/172)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Scope$10%   (0/1)0%   (0/2)0%   (0/11)0%   (0/2)
Scope$1 (Scope): void 0%   (0/1)0%   (0/6)0%   (0/1)
iterator (): Iterator 0%   (0/1)0%   (0/5)0%   (0/1)
     
class Scope$1$10%   (0/1)0%   (0/5)0%   (0/67)0%   (0/15)
Scope$1$1 (Scope$1): void 0%   (0/1)0%   (0/19)0%   (0/5)
hasNext (): boolean 0%   (0/1)0%   (0/7)0%   (0/1)
next (): Symbol 0%   (0/1)0%   (0/18)0%   (0/4)
remove (): void 0%   (0/1)0%   (0/4)0%   (0/1)
update (): void 0%   (0/1)0%   (0/19)0%   (0/4)
     
class Scope$DelegatedScope0%   (0/1)0%   (0/9)0%   (0/41)0%   (0/11)
<static initializer> 0%   (0/1)0%   (0/4)0%   (0/1)
Scope$DelegatedScope (Scope): void 0%   (0/1)0%   (0/10)0%   (0/3)
dup (): Scope 0%   (0/1)0%   (0/6)0%   (0/1)
dupUnshared (): Scope 0%   (0/1)0%   (0/6)0%   (0/1)
enter (Symbol): void 0%   (0/1)0%   (0/1)0%   (0/1)
enter (Symbol, Scope): void 0%   (0/1)0%   (0/1)0%   (0/1)
leave (): Scope 0%   (0/1)0%   (0/3)0%   (0/1)
lookup (Name): Scope$Entry 0%   (0/1)0%   (0/5)0%   (0/1)
remove (Symbol): void 0%   (0/1)0%   (0/5)0%   (0/1)
     
class Scope100% (1/1)74%  (14/19)41%  (254/615)46%  (49.9/109)
copy (Scope$Entry): void 0%   (0/1)0%   (0/28)0%   (0/6)
dble (): void 0%   (0/1)0%   (0/77)0%   (0/11)
getElements (): Iterable 0%   (0/1)0%   (0/5)0%   (0/1)
remove (Symbol): void 0%   (0/1)0%   (0/94)0%   (0/19)
toString (): String 0%   (0/1)0%   (0/52)0%   (0/9)
leave (): Scope 100% (1/1)32%  (26/81)37%  (4.4/12)
enter (Symbol): void 100% (1/1)50%  (7/14)74%  (2.2/3)
includes (Symbol): boolean 100% (1/1)52%  (11/21)60%  (3/5)
enterIfAbsent (Symbol): void 100% (1/1)53%  (19/36)70%  (3.5/5)
Scope (Scope, Symbol, Scope$Entry []): void 100% (1/1)80%  (32/40)96%  (10.6/11)
enter (Symbol, Scope, Scope): void 100% (1/1)84%  (36/43)89%  (6.2/7)
<static initializer> 100% (1/1)96%  (23/24)98%  (3/3)
Scope (Symbol): void 100% (1/1)100% (19/19)100% (3/3)
dup (): Scope 100% (1/1)100% (17/17)100% (3/3)
dup (Symbol): Scope 100% (1/1)100% (16/16)100% (3/3)
dupUnshared (): Scope 100% (1/1)100% (11/11)100% (1/1)
enter (Symbol, Scope): void 100% (1/1)100% (6/6)100% (2/2)
lookup (Name): Scope$Entry 100% (1/1)100% (23/23)100% (4/4)
makeEntry (Symbol, Scope$Entry, Scope$Entry, Scope, Scope): Scope$Entry 100% (1/1)100% (8/8)100% (1/1)
     
class Scope$ErrorScope100% (1/1)40%  (2/5)42%  (20/48)50%  (5/10)
Scope$ErrorScope (Scope, Symbol, Scope$Entry []): void 0%   (0/1)0%   (0/6)0%   (0/2)
dup (): Scope 0%   (0/1)0%   (0/9)0%   (0/1)
dupUnshared (): Scope 0%   (0/1)0%   (0/11)0%   (0/1)
lookup (Name): Scope$Entry 100% (1/1)89%  (16/18)75%  (3/4)
Scope$ErrorScope (Symbol): void 100% (1/1)100% (4/4)100% (2/2)
     
class Scope$Entry100% (1/1)60%  (3/5)73%  (33/45)78%  (9.4/12)
access$002 (Scope$Entry, Scope$Entry): Scope$Entry 0%   (0/1)0%   (0/5)0%   (0/1)
getOrigin (): Scope 0%   (0/1)0%   (0/3)0%   (0/1)
next (): Scope$Entry 100% (1/1)79%  (15/19)75%  (3/4)
Scope$Entry (Symbol, Scope$Entry, Scope$Entry, Scope): void 100% (1/1)100% (15/15)100% (6/6)
access$000 (Scope$Entry): Scope$Entry 100% (1/1)100% (3/3)100% (1/1)
     
class Scope$ImportScope$ImportEntry100% (1/1)67%  (2/3)74%  (29/39)82%  (6.6/8)
getOrigin (): Scope 0%   (0/1)0%   (0/3)0%   (0/1)
next (): Scope$Entry 100% (1/1)73%  (19/26)90%  (3.6/4)
Scope$ImportScope$ImportEntry (Symbol, Scope$Entry, Scope$Entry, Scope, Scope... 100% (1/1)100% (10/10)100% (3/3)
     
class Scope$ImportScope100% (1/1)100% (3/3)100% (43/43)100% (7/7)
Scope$ImportScope (Symbol): void 100% (1/1)100% (4/4)100% (2/2)
lookup (Name): Scope$Entry 100% (1/1)100% (30/30)100% (4/4)
makeEntry (Symbol, Scope$Entry, Scope$Entry, Scope, Scope): Scope$Entry 100% (1/1)100% (9/9)100% (1/1)

1/*
2 * Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25 
26package com.sun.tools.javac.code;
27 
28import com.sun.tools.javac.util.*;
29import java.util.Iterator;
30 
31/** A scope represents an area of visibility in a Java program. The
32 *  Scope class is a container for symbols which provides
33 *  efficient access to symbols given their names. Scopes are implemented
34 *  as hash tables. Scopes can be nested; the next field of a scope points
35 *  to its next outer scope. Nested scopes can share their hash tables.
36 *
37 *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
38 *  you write code that depends on this, you do so at your own risk.
39 *  This code and its internal interfaces are subject to change or
40 *  deletion without notice.</b>
41 */
42public class Scope {
43 
44    /** The number of scopes that share this scope's hash table.
45     */
46    private int shared;
47 
48    /** Next enclosing scope (with whom this scope may share a hashtable)
49     */
50    public Scope next;
51 
52    /** The scope's owner.
53     */
54    public Symbol owner;
55 
56    /** A hash table for the scope's entries.
57     */
58    public Entry[] table;
59 
60    /** Mask for hash codes, always equal to (table.length - 1).
61     */
62    int hashMask;
63 
64    /** A linear list that also contains all entries in
65     *  reverse order of appearance (i.e later entries are pushed on top).
66     */
67    public Entry elems;
68 
69    /** The number of elements in this scope.
70     */
71    public int nelems = 0;
72 
73    /** Every hash bucket is a list of Entry's which ends in sentinel.
74     */
75    private static final Entry sentinel = new Entry(null, null, null, null);
76 
77    /** The hash table's initial size.
78     */
79    private static final int INITIAL_SIZE = 0x10;
80 
81    /** A value for the empty scope.
82     */
83    public static final Scope emptyScope = new Scope(null, null, new Entry[]{});
84 
85    /** Construct a new scope, within scope next, with given owner, using
86     *  given table. The table's length must be an exponent of 2.
87     */
88    Scope(Scope next, Symbol owner, Entry[] table) {
89        this.next = next;
90        assert emptyScope == null || owner != null;
91        this.owner = owner;
92        this.table = table;
93        this.hashMask = table.length - 1;
94        this.elems = null;
95        this.nelems = 0;
96        this.shared = 0;
97    }
98 
99    /** Construct a new scope, within scope next, with given owner,
100     *  using a fresh table of length INITIAL_SIZE.
101     */
102    public Scope(Symbol owner) {
103        this(null, owner, new Entry[INITIAL_SIZE]);
104        for (int i = 0; i < INITIAL_SIZE; i++) table[i] = sentinel;
105    }
106 
107    /** Construct a fresh scope within this scope, with same owner,
108     *  which shares its table with the outer scope. Used in connection with
109     *  method leave if scope access is stack-like in order to avoid allocation
110     *  of fresh tables.
111     */
112    public Scope dup() {
113        Scope result = new Scope(this, this.owner, this.table);
114        shared++;
115        // System.out.println("====> duping scope " + this.hashCode() + " owned by " + this.owner + " to " + result.hashCode());
116        // new Error().printStackTrace(System.out);
117        return result;
118    }
119 
120    /** Construct a fresh scope within this scope, with new owner,
121     *  which shares its table with the outer scope. Used in connection with
122     *  method leave if scope access is stack-like in order to avoid allocation
123     *  of fresh tables.
124     */
125    public Scope dup(Symbol newOwner) {
126        Scope result = new Scope(this, newOwner, this.table);
127        shared++;
128        // System.out.println("====> duping scope " + this.hashCode() + " owned by " + newOwner + " to " + result.hashCode());
129        // new Error().printStackTrace(System.out);
130        return result;
131    }
132 
133    /** Construct a fresh scope within this scope, with same owner,
134     *  with a new hash table, whose contents initially are those of
135     *  the table of its outer scope.
136     */
137    public Scope dupUnshared() {
138        return new Scope(this, this.owner, this.table.clone());
139    }
140 
141    /** Remove all entries of this scope from its table, if shared
142     *  with next.
143     */
144    public Scope leave() {
145        assert shared == 0;
146        if (table != next.table) return next;
147        while (elems != null) {
148            int hash = elems.sym.name.index & hashMask;
149            Entry e = table[hash];
150            assert e == elems : elems.sym;
151            table[hash] = elems.shadowed;
152            elems = elems.sibling;
153        }
154        assert next.shared > 0;
155        next.shared--;
156        // System.out.println("====> leaving scope " + this.hashCode() + " owned by " + this.owner + " to " + next.hashCode());
157        // new Error().printStackTrace(System.out);
158        return next;
159    }
160 
161    /** Double size of hash table.
162     */
163    private void dble() {
164        assert shared == 0;
165        Entry[] oldtable = table;
166        Entry[] newtable = new Entry[oldtable.length * 2];
167        for (Scope s = this; s != null; s = s.next) {
168            if (s.table == oldtable) {
169                assert s == this || s.shared != 0;
170                s.table = newtable;
171                s.hashMask = newtable.length - 1;
172            }
173        }
174        for (int i = 0; i < newtable.length; i++) newtable[i] = sentinel;
175        for (int i = 0; i < oldtable.length; i++) copy(oldtable[i]);
176    }
177 
178    /** Copy the given entry and all entries shadowed by it to table
179     */
180    private void copy(Entry e) {
181        if (e.sym != null) {
182            copy(e.shadowed);
183            int hash = e.sym.name.index & hashMask;
184            e.shadowed = table[hash];
185            table[hash] = e;
186        }
187    }
188 
189    /** Enter symbol sym in this scope.
190     */
191    public void enter(Symbol sym) {
192        assert shared == 0;
193        enter(sym, this);
194    }
195 
196    public void enter(Symbol sym, Scope s) {
197        enter(sym, s, s);
198    }
199 
200    /**
201     * Enter symbol sym in this scope, but mark that it comes from
202     * given scope `s' accessed through `origin'.  The last two
203     * arguments are only used in import scopes.
204     */
205    public void enter(Symbol sym, Scope s, Scope origin) {
206        assert shared == 0;
207        // Temporarily disabled (bug 6460352):
208        // if (nelems * 3 >= hashMask * 2) dble();
209        int hash = sym.name.index & hashMask;
210        Entry e = makeEntry(sym, table[hash], elems, s, origin);
211        table[hash] = e;
212        elems = e;
213        nelems++;
214    }
215 
216    Entry makeEntry(Symbol sym, Entry shadowed, Entry sibling, Scope scope, Scope origin) {
217        return new Entry(sym, shadowed, sibling, scope);
218    }
219 
220    /** Remove symbol from this scope.  Used when an inner class
221     *  attribute tells us that the class isn't a package member.
222     */
223    public void remove(Symbol sym) {
224        assert shared == 0;
225        Entry e = lookup(sym.name);
226        while (e.scope == this && e.sym != sym) e = e.next();
227        if (e.scope == null) return;
228 
229        // remove e from table and shadowed list;
230        Entry te = table[sym.name.index & hashMask];
231        if (te == e)
232            table[sym.name.index & hashMask] = e.shadowed;
233        else while (true) {
234            if (te.shadowed == e) {
235                te.shadowed = e.shadowed;
236                break;
237            }
238            te = te.shadowed;
239        }
240 
241        // remove e from elems and sibling list
242        te = elems;
243        if (te == e)
244            elems = e.sibling;
245        else while (true) {
246            if (te.sibling == e) {
247                te.sibling = e.sibling;
248                break;
249            }
250            te = te.sibling;
251        }
252    }
253 
254    /** Enter symbol sym in this scope if not already there.
255     */
256    public void enterIfAbsent(Symbol sym) {
257        assert shared == 0;
258        Entry e = lookup(sym.name);
259        while (e.scope == this && e.sym.kind != sym.kind) e = e.next();
260        if (e.scope != this) enter(sym);
261    }
262 
263    /** Given a class, is there already a class with same fully
264     *  qualified name in this (import) scope?
265     */
266    public boolean includes(Symbol c) {
267        for (Scope.Entry e = lookup(c.name);
268             e.scope == this;
269             e = e.next()) {
270            if (e.sym == c) return true;
271        }
272        return false;
273    }
274 
275    /** Return the entry associated with given name, starting in
276     *  this scope and proceeding outwards. If no entry was found,
277     *  return the sentinel, which is characterized by having a null in
278     *  both its scope and sym fields, whereas both fields are non-null
279     *  for regular entries.
280     */
281    public Entry lookup(Name name) {
282        Entry e = table[name.index & hashMask];
283        while (e.scope != null && e.sym.name != name)
284            e = e.shadowed;
285        return e;
286    }
287 
288    public Iterable<Symbol> getElements() {
289        return new Iterable<Symbol>() {
290            public Iterator<Symbol> iterator() {
291                return new Iterator<Symbol>() {
292                    private Scope currScope = Scope.this;
293                    private Scope.Entry currEntry = elems;
294                    {
295                        update();
296                    }
297 
298                    public boolean hasNext() {
299                        return currEntry != null;
300                    }
301 
302                    public Symbol next() {
303                        Symbol sym = (currEntry == null ? null : currEntry.sym);
304                        currEntry = currEntry.sibling;
305                        update();
306                        return sym;
307                    }
308 
309                    public void remove() {
310                        throw new UnsupportedOperationException();
311                    }
312 
313                    private void update() {
314                        while (currEntry == null && currScope.next != null) {
315                            currScope = currScope.next;
316                            currEntry = currScope.elems;
317                        }
318                    }
319                };
320            }
321        };
322 
323    }
324 
325    public String toString() {
326        StringBuilder result = new StringBuilder();
327        result.append("Scope[");
328        for (Scope s = this; s != null ; s = s.next) {
329            if (s != this) result.append(" | ");
330            for (Entry e = s.elems; e != null; e = e.sibling) {
331                if (e != s.elems) result.append(", ");
332                result.append(e.sym);
333            }
334        }
335        result.append("]");
336        return result.toString();
337    }
338 
339    /** A class for scope entries.
340     */
341    public static class Entry {
342 
343        /** The referenced symbol.
344         *  sym == null   iff   this == sentinel
345         */
346        public Symbol sym;
347 
348        /** An entry with the same hash code, or sentinel.
349         */
350        private Entry shadowed;
351 
352        /** Next entry in same scope.
353         */
354        public Entry sibling;
355 
356        /** The entry's scope.
357         *  scope == null   iff   this == sentinel
358         *  for an entry in an import scope, this is the scope
359         *  where the entry came from (i.e. was imported from).
360         */
361        public Scope scope;
362 
363        public Entry(Symbol sym, Entry shadowed, Entry sibling, Scope scope) {
364            this.sym = sym;
365            this.shadowed = shadowed;
366            this.sibling = sibling;
367            this.scope = scope;
368        }
369 
370        /** Return next entry with the same name as this entry, proceeding
371         *  outwards if not found in this scope.
372         */
373        public Entry next() {
374            Entry e = shadowed;
375            while (e.scope != null && e.sym.name != sym.name)
376                e = e.shadowed;
377            return e;
378        }
379 
380        public Scope getOrigin() {
381            // The origin is only recorded for import scopes.  For all
382            // other scope entries, the "enclosing" type is available
383            // from other sources.  See Attr.visitSelect and
384            // Attr.visitIdent.  Rather than throwing an assertion
385            // error, we return scope which will be the same as origin
386            // in many cases.
387            return scope;
388        }
389    }
390 
391    public static class ImportScope extends Scope {
392 
393        public ImportScope(Symbol owner) {
394            super(owner);
395        }
396 
397        @Override
398        Entry makeEntry(Symbol sym, Entry shadowed, Entry sibling, Scope scope, Scope origin) {
399            return new ImportEntry(sym, shadowed, sibling, scope, origin);
400        }
401 
402        public Entry lookup(Name name) {
403            Entry e = table[name.index & hashMask];
404            while (e.scope != null &&
405                   (e.sym.name != name ||
406                    /* Since an inner class will show up in package and
407                     * import scopes until its inner class attribute has
408                     * been processed, we have to weed it out here.  This
409                     * is done by comparing the owners of the entry's
410                     * scope and symbol fields.  The scope field's owner
411                     * points to where the class originally was imported
412                     * from.  The symbol field's owner points to where the
413                     * class is situated now.  This can change when an
414                     * inner class is read (see ClassReader.enterClass).
415                     * By comparing the two fields we make sure that we do
416                     * not accidentally import an inner class that started
417                     * life as a flat class in a package. */
418                    e.sym.owner != e.scope.owner))
419                e = e.shadowed;
420            return e;
421        }
422 
423        static class ImportEntry extends Entry {
424            private Scope origin;
425 
426            ImportEntry(Symbol sym, Entry shadowed, Entry sibling, Scope scope, Scope origin) {
427                super(sym, shadowed, sibling, scope);
428                this.origin = origin;
429            }
430            public Entry next() {
431                Entry e = super.shadowed;
432                while (e.scope != null &&
433                       (e.sym.name != sym.name ||
434                        e.sym.owner != e.scope.owner)) // see lookup()
435                    e = e.shadowed;
436                return e;
437            }
438 
439            @Override
440            public Scope getOrigin() { return origin; }
441        }
442    }
443 
444    /** An empty scope, into which you can't place anything.  Used for
445     *  the scope for a variable initializer.
446     */
447    public static class DelegatedScope extends Scope {
448        Scope delegatee;
449        public static final Entry[] emptyTable = new Entry[0];
450 
451        public DelegatedScope(Scope outer) {
452            super(outer, outer.owner, emptyTable);
453            delegatee = outer;
454        }
455        public Scope dup() {
456            return new DelegatedScope(next);
457        }
458        public Scope dupUnshared() {
459            return new DelegatedScope(next);
460        }
461        public Scope leave() {
462            return next;
463        }
464        public void enter(Symbol sym) {
465            // only anonymous classes could be put here
466        }
467        public void enter(Symbol sym, Scope s) {
468            // only anonymous classes could be put here
469        }
470        public void remove(Symbol sym) {
471            throw new AssertionError(sym);
472        }
473        public Entry lookup(Name name) {
474            return delegatee.lookup(name);
475        }
476    }
477 
478    /** An error scope, for which the owner should be an error symbol. */
479    public static class ErrorScope extends Scope {
480        ErrorScope(Scope next, Symbol errSymbol, Entry[] table) {
481            super(next, /*owner=*/errSymbol, table);
482        }
483        public ErrorScope(Symbol errSymbol) {
484            super(errSymbol);
485        }
486        public Scope dup() {
487            return new ErrorScope(this, owner, table);
488        }
489        public Scope dupUnshared() {
490            return new ErrorScope(this, owner, table.clone());
491        }
492        public Entry lookup(Name name) {
493            Entry e = super.lookup(name);
494            if (e.scope == null)
495                return new Entry(owner, null, null, null);
496            else
497                return e;
498        }
499    }
500}

[all classes][com.sun.tools.javac.code]
EMMA 2.0.5312 (C) Vladimir Roubtsov