test/tools/javac/types/TypeHarness.java

changeset 792
2199365892b1
child 821
c8d312dd17bc
equal deleted inserted replaced
791:dd9b5f767559 792:2199365892b1
1 /*
2 * Copyright (c) 2010, 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 */
23
24 import com.sun.tools.javac.code.BoundKind;
25 import com.sun.tools.javac.code.Flags;
26 import com.sun.tools.javac.util.Context;
27 import com.sun.tools.javac.code.Types;
28 import com.sun.tools.javac.code.Symtab;
29 import com.sun.tools.javac.code.Type;
30 import com.sun.tools.javac.code.Type.*;
31 import com.sun.tools.javac.code.Symbol.*;
32 import com.sun.tools.javac.util.List;
33 import com.sun.tools.javac.util.ListBuffer;
34 import com.sun.tools.javac.util.Name;
35 import com.sun.tools.javac.util.Names;
36 import com.sun.tools.javac.file.JavacFileManager;
37
38 /**
39 * Test harness whose goal is to simplify the task of writing type-system
40 * regression test. It provides functionalities to build custom types as well
41 * as to access the underlying javac's symbol table in order to retrieve
42 * predefined types. Among the features supported by the harness are: type
43 * substitution, type containment, subtyping, cast-conversion, assigment
44 * conversion.
45 *
46 * This class is meant to be a common super class for all concrete type test
47 * classes. A subclass can access the type-factory and the test methods so as
48 * to write compact tests. An example is reported below:
49 *
50 * <pre>
51 * Type X = fac.TypeVariable();
52 * Type Y = fac.TypeVariable();
53 * Type A_X_Y = fac.Class(0, X, Y);
54 * Type A_Obj_Obj = fac.Class(0,
55 * predef.objectType,
56 * predef.objectType);
57 * checkSameType(A_Obj_Obj, subst(A_X_Y,
58 * Mapping(X, predef.objectType),
59 * Mapping(Y, predef.objectType)));
60 * </pre>
61 *
62 * The above code is used to create two class types, namely {@code A<X,Y>} and
63 * {@code A<Object,Object>} where both {@code X} and {@code Y} are type-variables.
64 * The code then verifies that {@code [X:=Object,Y:=Object]A<X,Y> == A<Object,Object>}.
65 *
66 * @author mcimadamore
67 */
68 public class TypeHarness {
69
70 protected Types types;
71 protected Symtab predef;
72 protected Names names;
73 protected Factory fac;
74
75 protected TypeHarness() {
76 Context ctx = new Context();
77 JavacFileManager.preRegister(ctx);
78 types = Types.instance(ctx);
79 predef = Symtab.instance(ctx);
80 names = Names.instance(ctx);
81 fac = new Factory();
82 }
83
84 // <editor-fold defaultstate="collapsed" desc="type assertions">
85
86 /** assert that 's' is a subtype of 't' */
87 public void assertSubtype(Type s, Type t) {
88 assertSubtype(s, t, true);
89 }
90
91 /** assert that 's' is/is not a subtype of 't' */
92 public void assertSubtype(Type s, Type t, boolean expected) {
93 if (types.isSubtype(s, t) != expected) {
94 String msg = expected ?
95 " is not a subtype of " :
96 " is a subtype of ";
97 error(s + msg + t);
98 }
99 }
100
101 /** assert that 's' is the same type as 't' */
102 public void assertSameType(Type s, Type t) {
103 assertSameType(s, t, true);
104 }
105
106 /** assert that 's' is/is not the same type as 't' */
107 public void assertSameType(Type s, Type t, boolean expected) {
108 if (types.isSameType(s, t) != expected) {
109 String msg = expected ?
110 " is not the same type as " :
111 " is the same type as ";
112 error(s + msg + t);
113 }
114 }
115
116 /** assert that 's' is castable to 't' */
117 public void assertCastable(Type s, Type t) {
118 assertCastable(s, t, true);
119 }
120
121 /** assert that 's' is/is not castable to 't' */
122 public void assertCastable(Type s, Type t, boolean expected) {
123 if (types.isCastable(s, t) != expected) {
124 String msg = expected ?
125 " is not castable to " :
126 " is castable to ";
127 error(s + msg + t);
128 }
129 }
130
131 /** assert that 's' is convertible (method invocation conversion) to 't' */
132 public void assertConvertible(Type s, Type t) {
133 assertCastable(s, t, true);
134 }
135
136 /** assert that 's' is/is not convertible (method invocation conversion) to 't' */
137 public void assertConvertible(Type s, Type t, boolean expected) {
138 if (types.isConvertible(s, t) != expected) {
139 String msg = expected ?
140 " is not convertible to " :
141 " is convertible to ";
142 error(s + msg + t);
143 }
144 }
145
146 /** assert that 's' is assignable to 't' */
147 public void assertAssignable(Type s, Type t) {
148 assertCastable(s, t, true);
149 }
150
151 /** assert that 's' is/is not assignable to 't' */
152 public void assertAssignable(Type s, Type t, boolean expected) {
153 if (types.isAssignable(s, t) != expected) {
154 String msg = expected ?
155 " is not assignable to " :
156 " is assignable to ";
157 error(s + msg + t);
158 }
159 }
160 // </editor-fold>
161
162 private void error(String msg) {
163 throw new AssertionError("Unexpected result: " + msg);
164 }
165
166 // <editor-fold defaultstate="collapsed" desc="type functions">
167
168 /** compute the erasure of a type 't' */
169 public Type erasure(Type t) {
170 return types.erasure(t);
171 }
172
173 /** compute the capture of a type 't' */
174 public Type capture(Type t) {
175 return types.capture(t);
176 }
177
178 /** compute the boxed type associated with 't' */
179 public Type box(Type t) {
180 if (!t.isPrimitive()) {
181 throw new AssertionError("Cannot box non-primitive type: " + t);
182 }
183 return types.boxedClass(t).type;
184 }
185
186 /** compute the unboxed type associated with 't' */
187 public Type unbox(Type t) {
188 Type u = types.unboxedType(t);
189 if (t == null) {
190 throw new AssertionError("Cannot unbox reference type: " + t);
191 } else {
192 return u;
193 }
194 }
195
196 /** compute a type substitution on 't' given a list of type mappings */
197 public Type subst(Type t, Mapping... maps) {
198 ListBuffer<Type> from = ListBuffer.lb();
199 ListBuffer<Type> to = ListBuffer.lb();
200 for (Mapping tm : maps) {
201 from.append(tm.from);
202 to.append(tm.to);
203 }
204 return types.subst(t, from.toList(), to.toList());
205 }
206
207 /** create a fresh type mapping from a type to another */
208 public Mapping Mapping(Type from, Type to) {
209 return new Mapping(from, to);
210 }
211
212 public static class Mapping {
213 Type from;
214 Type to;
215 private Mapping(Type from, Type to) {
216 this.from = from;
217 this.to = to;
218 }
219 }
220 // </editor-fold>
221
222 // <editor-fold defaultstate="collapsed" desc="type factory">
223
224 /**
225 * This class is used to create Java types in a simple way. All main
226 * kinds of type are supported: primitive, reference, non-denotable. The
227 * factory also supports creation of constant types (used by the compiler
228 * to represent the type of a literal).
229 */
230 public class Factory {
231
232 private int synthNameCount = 0;
233
234 private Name syntheticName() {
235 return names.fromString("A$" + synthNameCount++);
236 }
237
238 public ClassType Class(long flags, Type... typeArgs) {
239 ClassSymbol csym = new ClassSymbol(flags, syntheticName(), predef.noSymbol);
240 csym.type = new ClassType(Type.noType, List.from(typeArgs), csym);
241 ((ClassType)csym.type).supertype_field = predef.objectType;
242 return (ClassType)csym.type;
243 }
244
245 public ClassType Class(Type... typeArgs) {
246 return Class(0, typeArgs);
247 }
248
249 public ClassType Interface(Type... typeArgs) {
250 return Class(Flags.INTERFACE, typeArgs);
251 }
252
253 public ClassType Interface(long flags, Type... typeArgs) {
254 return Class(Flags.INTERFACE | flags, typeArgs);
255 }
256
257 public Type Constant(byte b) {
258 return predef.byteType.constType(b);
259 }
260
261 public Type Constant(short s) {
262 return predef.shortType.constType(s);
263 }
264
265 public Type Constant(int i) {
266 return predef.intType.constType(i);
267 }
268
269 public Type Constant(long l) {
270 return predef.longType.constType(l);
271 }
272
273 public Type Constant(float f) {
274 return predef.floatType.constType(f);
275 }
276
277 public Type Constant(double d) {
278 return predef.doubleType.constType(d);
279 }
280
281 public Type Constant(char c) {
282 return predef.charType.constType(c + 0);
283 }
284
285 public ArrayType Array(Type elemType) {
286 return new ArrayType(elemType, predef.arrayClass);
287 }
288
289 public TypeVar TypeVariable() {
290 return TypeVariable(predef.objectType);
291 }
292
293 public TypeVar TypeVariable(Type bound) {
294 TypeSymbol tvsym = new TypeSymbol(0, syntheticName(), null, predef.noSymbol);
295 tvsym.type = new TypeVar(tvsym, bound, null);
296 return (TypeVar)tvsym.type;
297 }
298
299 public WildcardType Wildcard(BoundKind bk, Type bound) {
300 return new WildcardType(bound, bk, predef.boundClass);
301 }
302
303 public CapturedType CapturedVariable(Type upper, Type lower) {
304 return new CapturedType(syntheticName(), predef.noSymbol, upper, lower, null);
305 }
306
307 public ClassType Intersection(Type classBound, Type... intfBounds) {
308 ClassType ct = Class(Flags.COMPOUND);
309 ct.supertype_field = classBound;
310 ct.interfaces_field = List.from(intfBounds);
311 return ct;
312 }
313 }
314 // </editor-fold>
315 }

mercurial