Tue, 15 Feb 2011 11:49:46 +0000
7017664: Add listeners infrastracture to javac scopes
Summary: Add listeners to javac scopes, added CompoundScope and correct invalidation logic for ImplementationCache
Reviewed-by: jjg
1 /*
2 * Copyright (c) 2011, Oracle and/or its affiliates. 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
24 /*
25 * @test
26 * @bug 7017664
27 * @summary Basher for CompoundScopes
28 */
30 import java.util.Random;
31 import java.util.Map;
32 import java.util.HashMap;
33 import com.sun.tools.javac.util.*;
34 import com.sun.tools.javac.code.*;
35 import com.sun.tools.javac.code.Scope.*;
36 import com.sun.tools.javac.code.Symbol.*;
37 import com.sun.tools.javac.file.JavacFileManager;
39 public class CompoundScopeTest {
40 public static void main(String... args) throws Exception {
41 new CompoundScopeTest().run(args);
42 }
44 static final int MAX_SYMBOLS_COUNT = 20;
45 static final int PASSES = 10;
47 void run(String... args) throws Exception {
48 int count = PASSES;
50 for (int i = 0; i < args.length; i++) {
51 String arg = args[i];
52 if (arg.equals("-seed") && (i + 1 < args.length))
53 seed = Long.parseLong(args[++i]);
54 else if(arg.equals("-tests") && (i + 1 < args.length))
55 count = Integer.parseInt(args[++i]);
56 else
57 throw new Exception("unknown arg: " + arg);
58 }
60 rgen = new Random(seed);
62 for (int i = 0; i < count; i++) {
63 Test t = new Test();
64 t.run();
65 }
67 if (errors > 0)
68 throw new Exception(errors + " errors found");
69 }
71 /**
72 * Write a message to stderr.
73 */
74 void log(String msg) {
75 System.err.println(msg);
76 }
78 /**
79 * Write an error message to stderr.
80 */
81 void error(String msg) {
82 System.err.println("Error: " + msg);
83 errors++;
84 }
86 Random rgen;
87 long seed = 0;
89 int errors;
91 /** Class to encapsulate a test run. */
92 class Test {
94 List<Symbol> elems = List.nil();
95 Map<Name, List<Symbol>> shadowedMap = new HashMap<Name, List<Symbol>>();
97 /** Run the test. */
98 void run() throws Exception {
99 log ("starting test");
100 setup();
101 Scope[] scopes = { createScope(rgen.nextInt(MAX_SYMBOLS_COUNT)),
102 createScope(rgen.nextInt(MAX_SYMBOLS_COUNT)),
103 createScope(rgen.nextInt(MAX_SYMBOLS_COUNT)) };
104 boolean[][] scopeNesting = { {false, true, false, true},
105 {false, true, true, true},
106 {false, false, true, true} };
107 /**
108 * We want to generate (and check) the following compound scopes:
109 * C1 = C(S1, S2, S3)
110 * C2 = C((S1, S2), S3)
111 * C3 = C(S1, (S2, S3))
112 * C3 = C(C(S1, S2, S3))
113 */
114 for (int i = 0 ; i < 4 ; i ++) {
115 CompoundScope root = new CompoundScope(symtab.noSymbol);
116 CompoundScope sub = new CompoundScope(symtab.noSymbol);
117 boolean subAdded = false;
118 for (int sc = 0 ; sc < 3 ; sc ++) {
119 if (scopeNesting[sc][i]) {
120 sub.addSubScope(scopes[sc]);
121 if (!subAdded) {
122 root.addSubScope(sub);
123 subAdded = true;
124 }
125 } else {
126 root.addSubScope(scopes[sc]);
127 }
128 }
129 log("testing scope: " + root);
130 checkElems(root);
131 checkShadowed(root);
132 }
133 }
135 /**
136 * Create a scope containing a given number of synthetic symbols
137 */
138 Scope createScope(int nelems) {
139 Scope s = new Scope(symtab.noSymbol);
140 for (int i = 0 ; i < nelems ; i++) {
141 Symbol sym = new TypeSymbol(0, names.fromString("s" + i), null, null);
142 s.enter(sym);
143 elems = elems.prepend(sym);
144 List<Symbol> shadowed = shadowedMap.get(sym.name);
145 if (shadowed == null) {
146 shadowed = List.nil();
147 }
148 shadowedMap.put(sym.name, shadowed.prepend(sym));
149 }
150 return s;
151 }
153 /**
154 * Setup compiler context
155 */
156 void setup() {
157 log ("setup");
158 context = new Context();
159 JavacFileManager.preRegister(context); // required by ClassReader which is required by Symtab
160 names = Names.instance(context); // Name.Table impls tied to an instance of Names
161 symtab = Symtab.instance(context);
162 }
164 /**
165 * Check that CompoundScope.getElements() correctly visits all symbols
166 * in all subscopes (in the correct order)
167 */
168 void checkElems(CompoundScope cs) {
169 List<Symbol> allSymbols = elems;
170 int count = 0;
171 for (Symbol s : cs.getElements()) {
172 checkSameSymbols(s, allSymbols.head);
173 allSymbols = allSymbols.tail;
174 count++;
175 }
176 if (count != elems.size()) {
177 error("CompoundScope.getElements() did not returned enough symbols");
178 }
179 }
181 /**
182 * Check that CompoundScope.getElements() correctly visits all symbols
183 * with a given name in all subscopes (in the correct order)
184 */
185 void checkShadowed(CompoundScope cs) {
186 for (Map.Entry<Name, List<Symbol>> shadowedEntry : shadowedMap.entrySet()) {
187 int count = 0;
188 List<Symbol> shadowed = shadowedEntry.getValue();
189 Name name = shadowedEntry.getKey();
190 for (Symbol s : cs.getElementsByName(name)) {
191 checkSameSymbols(s, shadowed.head);
192 shadowed = shadowed.tail;
193 count++;
194 }
195 if (count != shadowedEntry.getValue().size()) {
196 error("CompoundScope.lookup() did not returned enough symbols for name " + name);
197 }
198 }
199 }
201 void checkSameSymbols(Symbol found, Symbol req) {
202 if (found != req) {
203 error("Symbol mismatch - found : " + found + ":" + found.hashCode() + "\n" +
204 " required : " + req + ":" + req.hashCode());
205 }
206 }
208 Context context;
209 Symtab symtab;
210 Names names;
211 }
212 }