|
1 |
| |
|
2 |
| |
|
3 |
| |
|
4 |
| |
|
5 |
| |
|
6 |
| |
|
7 |
| |
|
8 |
| |
|
9 |
| |
|
10 |
| |
|
11 |
| |
|
12 |
| |
|
13 |
| |
|
14 |
| |
|
15 |
| |
|
16 |
| |
|
17 |
| |
|
18 |
| |
|
19 |
| |
|
20 |
| |
|
21 |
| |
|
22 |
| |
|
23 |
| |
|
24 |
| |
|
25 |
| |
|
26 |
| |
|
27 |
| |
|
28 |
| |
|
29 |
| |
|
30 |
| |
|
31 |
| |
|
32 |
| |
|
33 |
| |
|
34 |
| |
|
35 |
| |
|
36 |
| |
|
37 |
| package edu.rice.cs.javalanglevels; |
|
38 |
| |
|
39 |
| import edu.rice.cs.javalanglevels.tree.*; |
|
40 |
| import edu.rice.cs.javalanglevels.parser.JExprParser; |
|
41 |
| import edu.rice.cs.javalanglevels.util.Utilities; |
|
42 |
| import java.util.*; |
|
43 |
| import java.io.File; |
|
44 |
| import edu.rice.cs.plt.reflect.JavaVersion; |
|
45 |
| import edu.rice.cs.plt.iter.*; |
|
46 |
| |
|
47 |
| import junit.framework.TestCase; |
|
48 |
| |
|
49 |
| |
|
50 |
| public class ExpressionTypeChecker extends SpecialTypeChecker { |
|
51 |
| |
|
52 |
| public static final JavaVersion JAVA_VERSION = LanguageLevelConverter.OPT.javaVersion(); |
|
53 |
| public static final NullLiteral NULL_LITERAL = new NullLiteral(SourceInfo.NONE); |
|
54 |
| |
|
55 |
| |
|
56 |
| |
|
57 |
| |
|
58 |
| |
|
59 |
| |
|
60 |
| |
|
61 |
| |
|
62 |
| |
|
63 |
| |
|
64 |
651
| public ExpressionTypeChecker(Data data, File file, String packageName, LinkedList<String> importedFiles,
|
|
65 |
| LinkedList<String> importedPackages, LinkedList<VariableData> vars, |
|
66 |
| LinkedList<Pair<SymbolData, JExpression>> thrown) { |
|
67 |
651
| super(data, file, packageName, importedFiles, importedPackages, vars, thrown);
|
|
68 |
0
| if (vars == null) throw new RuntimeException("vars == null in new ExpressionTypeChecker operation");
|
|
69 |
| } |
|
70 |
| |
|
71 |
| |
|
72 |
| |
|
73 |
| |
|
74 |
| |
|
75 |
| |
|
76 |
| |
|
77 |
59
| public TypeData forSimpleAssignmentExpression(SimpleAssignmentExpression that) {
|
|
78 |
59
| TypeData valueRes = that.getValue().visit(this);
|
|
79 |
59
| TypeData nameRes = that.getName().visit(new LValueTypeChecker(this));
|
|
80 |
59
| return forSimpleAssignmentExpressionOnly(that, nameRes, valueRes);
|
|
81 |
| } |
|
82 |
| |
|
83 |
| |
|
84 |
| |
|
85 |
| |
|
86 |
| |
|
87 |
| |
|
88 |
| |
|
89 |
67
| public TypeData forSimpleAssignmentExpressionOnly(SimpleAssignmentExpression that, TypeData nameRes,
|
|
90 |
| TypeData valueRes) { |
|
91 |
2
| if (nameRes == null || valueRes == null) {return null;}
|
|
92 |
| |
|
93 |
| |
|
94 |
65
| if (!assertFound(nameRes, that) || !assertFound(valueRes, that)) {
|
|
95 |
4
| return null;
|
|
96 |
| } |
|
97 |
| |
|
98 |
| |
|
99 |
61
| if (assertInstanceType(nameRes, "You cannot assign a value to the type " + nameRes.getName(), that) &&
|
|
100 |
| assertInstanceType(valueRes, "You cannot use the type name " + valueRes.getName() + |
|
101 |
| " on the right hand side of an assignment", that)) { |
|
102 |
| |
|
103 |
| |
|
104 |
57
| if (! valueRes.getSymbolData().isAssignableTo(nameRes.getSymbolData(), JAVA_VERSION)) {
|
|
105 |
1
| _addError("You cannot assign something of type " + valueRes.getName() + " to something of type " +
|
|
106 |
| nameRes.getName(), that); |
|
107 |
| } |
|
108 |
| } |
|
109 |
61
| return nameRes.getInstanceData();
|
|
110 |
| } |
|
111 |
| |
|
112 |
| |
|
113 |
| |
|
114 |
| |
|
115 |
| |
|
116 |
| |
|
117 |
12
| public TypeData forPlusAssignmentExpression(PlusAssignmentExpression that) {
|
|
118 |
12
| TypeData valueRes = that.getValue().visit(this);
|
|
119 |
12
| TypeData nameRes = that.getName().visit(new LValueWithValueTypeChecker(this));
|
|
120 |
| |
|
121 |
12
| return forPlusAssignmentExpressionOnly(that, nameRes, valueRes);
|
|
122 |
| } |
|
123 |
| |
|
124 |
| |
|
125 |
| |
|
126 |
| |
|
127 |
| |
|
128 |
| |
|
129 |
| |
|
130 |
| |
|
131 |
| |
|
132 |
24
| public TypeData forPlusAssignmentExpressionOnly(PlusAssignmentExpression that, TypeData nameRes,
|
|
133 |
| TypeData valueRes) { |
|
134 |
2
| if (nameRes == null || valueRes == null) {return null;}
|
|
135 |
| |
|
136 |
| |
|
137 |
22
| if (! assertFound(nameRes, that) || !assertFound(valueRes, that)) {
|
|
138 |
2
| return null;
|
|
139 |
| } |
|
140 |
| |
|
141 |
| |
|
142 |
20
| SymbolData string = getSymbolData("java.lang.String", that, false, false);
|
|
143 |
| |
|
144 |
20
| if (nameRes.getSymbolData().isAssignableTo(string, JAVA_VERSION)) {
|
|
145 |
| |
|
146 |
6
| assertInstanceType(nameRes, "The arguments to a Plus Assignment Operator (+=) must both be instances, " +
|
|
147 |
| "but you have specified a type name", that); |
|
148 |
6
| assertInstanceType(valueRes, "The arguments to a Plus Assignment Operator (+=) must both be instances, " +
|
|
149 |
| "but you have specified a type name", that); |
|
150 |
6
| return string.getInstanceData();
|
|
151 |
| } |
|
152 |
| |
|
153 |
| else { |
|
154 |
14
| if (!nameRes.getSymbolData().isNumberType(JAVA_VERSION) ||
|
|
155 |
| !valueRes.getSymbolData().isNumberType(JAVA_VERSION)) { |
|
156 |
3
| _addError("The arguments to the Plus Assignment Operator (+=) must either include an instance of a String " +
|
|
157 |
| "or both be numbers. You have specified arguments of type " + nameRes.getName() + " and " + |
|
158 |
| valueRes.getName(), that); |
|
159 |
3
| return string.getInstanceData();
|
|
160 |
| } |
|
161 |
| |
|
162 |
11
| else if (! valueRes.getSymbolData().isAssignableTo(nameRes.getSymbolData(),
|
|
163 |
| JAVA_VERSION)) { |
|
164 |
1
| _addError("You cannot increment something of type " + nameRes.getName() + " with something of type " +
|
|
165 |
| valueRes.getName(), that); |
|
166 |
| } |
|
167 |
| |
|
168 |
| else { |
|
169 |
10
| assertInstanceType(nameRes, "The arguments to the Plus Assignment Operator (+=) must both be instances, " +
|
|
170 |
| "but you have specified a type name", that); |
|
171 |
10
| assertInstanceType(valueRes, "The arguments to the Plus Assignment Operator (+=) must both be instances, " +
|
|
172 |
| "but you have specified a type name", that); |
|
173 |
| } |
|
174 |
| |
|
175 |
11
| return nameRes.getInstanceData();
|
|
176 |
| } |
|
177 |
| } |
|
178 |
| |
|
179 |
| |
|
180 |
| |
|
181 |
| |
|
182 |
| |
|
183 |
| |
|
184 |
| |
|
185 |
5
| public TypeData forNumericAssignmentExpression(NumericAssignmentExpression that) {
|
|
186 |
5
| TypeData valueRes = that.getValue().visit(this);
|
|
187 |
5
| TypeData nameRes = that.getName().visit(new LValueWithValueTypeChecker(this));
|
|
188 |
| |
|
189 |
5
| return forNumericAssignmentExpressionOnly(that, nameRes, valueRes);
|
|
190 |
| } |
|
191 |
| |
|
192 |
| |
|
193 |
3
| public TypeData forMinusAssignmentExpression(MinusAssignmentExpression that) {
|
|
194 |
3
| return forNumericAssignmentExpression(that);
|
|
195 |
| } |
|
196 |
| |
|
197 |
| |
|
198 |
0
| public TypeData forMultiplyAssignmentExpression(MultiplyAssignmentExpression that) {
|
|
199 |
0
| return forNumericAssignmentExpression(that);
|
|
200 |
| } |
|
201 |
| |
|
202 |
| |
|
203 |
0
| public TypeData forDivideAssignmentExpression(DivideAssignmentExpression that) {
|
|
204 |
0
| return forNumericAssignmentExpression(that);
|
|
205 |
| } |
|
206 |
| |
|
207 |
| |
|
208 |
2
| public TypeData forModAssignmentExpression(ModAssignmentExpression that) {
|
|
209 |
2
| return forNumericAssignmentExpression(that);
|
|
210 |
| } |
|
211 |
| |
|
212 |
| |
|
213 |
| |
|
214 |
| |
|
215 |
| |
|
216 |
| |
|
217 |
| |
|
218 |
| |
|
219 |
16
| public TypeData forNumericAssignmentExpressionOnly(NumericAssignmentExpression that, TypeData nameRes,
|
|
220 |
| TypeData valueRes) { |
|
221 |
2
| if (nameRes == null || valueRes == null) {return null;}
|
|
222 |
| |
|
223 |
| |
|
224 |
14
| if (!assertFound(nameRes, that) || !assertFound(valueRes, that)) {
|
|
225 |
2
| return null;
|
|
226 |
| } |
|
227 |
| |
|
228 |
| |
|
229 |
12
| if (assertInstanceType(nameRes, "You cannot use a numeric assignment (-=, %=, *=, /=) on the type " +
|
|
230 |
| nameRes.getName(), that) && |
|
231 |
| assertInstanceType(valueRes, "You cannot use the type name " + valueRes.getName() + |
|
232 |
| " on the left hand side of a numeric assignment (-=, %=, *=, /=)", that)) { |
|
233 |
| |
|
234 |
10
| boolean error = false;
|
|
235 |
| |
|
236 |
10
| if (!nameRes.getSymbolData().isNumberType(JAVA_VERSION)) {
|
|
237 |
1
| _addError("The left side of this expression is not a number. " +
|
|
238 |
| "Therefore, you cannot apply a numeric assignment (-=, %=, *=, /=) to it", that); |
|
239 |
1
| error=true;
|
|
240 |
| } |
|
241 |
10
| if (!valueRes.getSymbolData().isNumberType(JAVA_VERSION)) {
|
|
242 |
1
| _addError("The right side of this expression is not a number. " +
|
|
243 |
| "Therefore, you cannot apply a numeric assignment (-=, %=, *=, /=) to it", that); |
|
244 |
1
| error = true;
|
|
245 |
| } |
|
246 |
| |
|
247 |
| |
|
248 |
| |
|
249 |
10
| if (!error && !valueRes.getSymbolData().isAssignableTo(nameRes.getSymbolData(),
|
|
250 |
| JAVA_VERSION)) { |
|
251 |
1
| _addError("You cannot use a numeric assignment (-=, %=, *=, /=) on something of type " + nameRes.getName() +
|
|
252 |
| " with something of type " + valueRes.getName(), that); |
|
253 |
| } |
|
254 |
| } |
|
255 |
12
| return nameRes.getInstanceData();
|
|
256 |
| } |
|
257 |
| |
|
258 |
| |
|
259 |
1
| public TypeData forShiftAssignmentExpressionOnly(ShiftAssignmentExpression that, TypeData nameRes,
|
|
260 |
| TypeData valueRes) { |
|
261 |
1
| throw new RuntimeException ("Internal Program Error: Shift assignment operators are not supported. " +
|
|
262 |
| "This should have been caught before the TypeChecker. Please report this bug."); |
|
263 |
| } |
|
264 |
| |
|
265 |
| |
|
266 |
1
| public TypeData forBitwiseAssignmentExpressionOnly(BitwiseAssignmentExpression that, TypeData nameRes, TypeData valueRes) {
|
|
267 |
1
| throw new RuntimeException ("Internal Program Error: Bitwise assignment operators are not supported. " +
|
|
268 |
| "This should have been caught before the TypeChecker. Please report this bug."); |
|
269 |
| } |
|
270 |
| |
|
271 |
| |
|
272 |
| |
|
273 |
| |
|
274 |
| |
|
275 |
| |
|
276 |
| |
|
277 |
| |
|
278 |
5
| public TypeData forBooleanExpressionOnly(BooleanExpression that, TypeData left_result, TypeData right_result) {
|
|
279 |
0
| if (left_result == null || right_result == null) return null;
|
|
280 |
| |
|
281 |
| |
|
282 |
0
| if (! assertFound(left_result, that) || ! assertFound(right_result, that)) return null;
|
|
283 |
| |
|
284 |
5
| if (assertInstanceType(left_result, "The left side of this expression is a type, not an instance", that) &&
|
|
285 |
| !left_result.getSymbolData().isAssignableTo(SymbolData.BOOLEAN_TYPE, JAVA_VERSION)) { |
|
286 |
| |
|
287 |
1
| _addError("The left side of this expression is not a boolean value. " +
|
|
288 |
| "Therefore, you cannot apply a Boolean Operator (&&, ||) to it", that); |
|
289 |
| } |
|
290 |
| |
|
291 |
5
| if (assertInstanceType(right_result, "The right side of this expression is a type, not an instance", that) &&
|
|
292 |
| ! right_result.getSymbolData().isAssignableTo(SymbolData.BOOLEAN_TYPE, JAVA_VERSION)) { |
|
293 |
| |
|
294 |
1
| _addError("The right side of this expression is not a boolean value. " +
|
|
295 |
| "Therefore, you cannot apply a Boolean Operator (&&, ||) to it", that); |
|
296 |
| } |
|
297 |
| |
|
298 |
| |
|
299 |
5
| return SymbolData.BOOLEAN_TYPE.getInstanceData();
|
|
300 |
| } |
|
301 |
| |
|
302 |
| |
|
303 |
1
| public TypeData forBitwiseBinaryExpressionOnly(BitwiseBinaryExpression that, TypeData left_result,
|
|
304 |
| TypeData right_result) { |
|
305 |
1
| throw new RuntimeException ("Internal Program Error: Bitwise operators are not supported. " +
|
|
306 |
| "This should have been caught before the TypeChecker. Please report this bug."); |
|
307 |
| } |
|
308 |
| |
|
309 |
| |
|
310 |
| |
|
311 |
| |
|
312 |
| |
|
313 |
| |
|
314 |
| |
|
315 |
| |
|
316 |
| |
|
317 |
18
| public TypeData forEqualityExpressionOnly(EqualityExpression that, TypeData left_result, TypeData right_result) {
|
|
318 |
0
| if (left_result == null || right_result == null) return null;
|
|
319 |
| |
|
320 |
| |
|
321 |
0
| if (!assertFound(left_result, that) || !assertFound(right_result, that)) return null;
|
|
322 |
| |
|
323 |
| |
|
324 |
18
| SymbolData left = left_result.getSymbolData();
|
|
325 |
18
| SymbolData right = right_result.getSymbolData();
|
|
326 |
18
| if (left.isPrimitiveType() || right.isPrimitiveType()) {
|
|
327 |
15
| if (!((left.isNumberType(JAVA_VERSION) &&
|
|
328 |
| right.isNumberType(JAVA_VERSION)) || |
|
329 |
| (left.isAssignableTo(SymbolData.BOOLEAN_TYPE, JAVA_VERSION) |
|
330 |
| && right.isAssignableTo(SymbolData.BOOLEAN_TYPE, JAVA_VERSION)))) { |
|
331 |
3
| _addError("At least one of the arguments to this Equality Operator (==, !=) is primitive. Therefore, they " +
|
|
332 |
| "must either both be number types or both be boolean types. You have specified expressions with type " + |
|
333 |
| left_result.getName() + " and " + right_result.getName(), that); |
|
334 |
| } |
|
335 |
| } |
|
336 |
| |
|
337 |
| |
|
338 |
| |
|
339 |
18
| assertInstanceType(left_result, "The arguments to this Equality Operator(==, !=) must both be instances. " +
|
|
340 |
| "Instead, you have referenced a type name on the left side", that); |
|
341 |
18
| assertInstanceType(right_result, "The arguments to this Equality Operator(==, !=) must both be instances. " +
|
|
342 |
| "Instead, you have referenced a type name on the right side", that); |
|
343 |
| |
|
344 |
18
| return SymbolData.BOOLEAN_TYPE.getInstanceData();
|
|
345 |
| } |
|
346 |
| |
|
347 |
| |
|
348 |
| |
|
349 |
| |
|
350 |
| |
|
351 |
| |
|
352 |
| |
|
353 |
| |
|
354 |
| |
|
355 |
38
| public TypeData forComparisonExpressionOnly(ComparisonExpression that, TypeData left_result, TypeData right_result) {
|
|
356 |
0
| if (left_result == null || right_result == null) {return null;}
|
|
357 |
| |
|
358 |
| |
|
359 |
1
| if (!assertFound(left_result, that) || !assertFound(right_result, that)) return null;
|
|
360 |
| |
|
361 |
37
| if (!left_result.getSymbolData().isNumberType(JAVA_VERSION)) {
|
|
362 |
1
| _addError("The left side of this expression is not a number. Therefore, you cannot apply a Comparison Operator" +
|
|
363 |
| " (<, >; <=, >=) to it", that); |
|
364 |
| } |
|
365 |
| else { |
|
366 |
36
| assertInstanceType(left_result, "The left side of this expression is a type, not an instance", that);
|
|
367 |
| } |
|
368 |
| |
|
369 |
37
| if (!right_result.getSymbolData().isNumberType(JAVA_VERSION)) {
|
|
370 |
1
| _addError("The right side of this expression is not a number. Therefore, you cannot apply a Comparison Operator" +
|
|
371 |
| " (<, >; <=, >=) to it", that); |
|
372 |
| } |
|
373 |
| else { |
|
374 |
36
| assertInstanceType(right_result, "The right side of this expression is a type, not an instance", that);
|
|
375 |
| } |
|
376 |
| |
|
377 |
37
| return SymbolData.BOOLEAN_TYPE.getInstanceData();
|
|
378 |
| } |
|
379 |
| |
|
380 |
| |
|
381 |
| |
|
382 |
| |
|
383 |
1
| public TypeData forShiftBinaryExpressionOnly(ShiftBinaryExpression that, TypeData left_result, TypeData right_result) {
|
|
384 |
1
| throw new RuntimeException ("Internal Program Error: BinaryShifts are not supported. " +
|
|
385 |
| "This should have been caught before the TypeChecker. Please report this bug."); |
|
386 |
| } |
|
387 |
| |
|
388 |
| |
|
389 |
| |
|
390 |
| |
|
391 |
| |
|
392 |
| |
|
393 |
| |
|
394 |
| |
|
395 |
| |
|
396 |
| |
|
397 |
| |
|
398 |
44
| public TypeData forPlusExpressionOnly(PlusExpression that, TypeData left_result, TypeData right_result) {
|
|
399 |
0
| if (left_result == null || right_result == null) {return null;}
|
|
400 |
| |
|
401 |
| |
|
402 |
44
| if (!assertFound(left_result, that) || !assertFound(right_result, that)) {
|
|
403 |
0
| return null;
|
|
404 |
| } |
|
405 |
| |
|
406 |
44
| SymbolData string = getSymbolData("java.lang.String", that, false, false);
|
|
407 |
| |
|
408 |
44
| if (left_result.getSymbolData().isAssignableTo(string, JAVA_VERSION) ||
|
|
409 |
| right_result.getSymbolData().isAssignableTo(string, JAVA_VERSION)) { |
|
410 |
| |
|
411 |
14
| assertInstanceType(left_result, "The arguments to the Plus Operator (+) must both be instances, " +
|
|
412 |
| "but you have specified a type name", that); |
|
413 |
14
| assertInstanceType(right_result, "The arguments to the Plus Operator (+) must both be instances, " +
|
|
414 |
| "but you have specified a type name", that); |
|
415 |
14
| return string.getInstanceData();
|
|
416 |
| } |
|
417 |
| |
|
418 |
| else { |
|
419 |
30
| if (!left_result.getSymbolData().isNumberType(JAVA_VERSION) ||
|
|
420 |
| !right_result.getSymbolData().isNumberType(JAVA_VERSION)) { |
|
421 |
1
| _addError("The arguments to the Plus Operator (+) must either include an instance of a String or both be" +
|
|
422 |
| " numbers. You have specified arguments of type " + left_result.getName() + " and " + |
|
423 |
| right_result.getName(), that); |
|
424 |
1
| return string.getInstanceData();
|
|
425 |
| } |
|
426 |
| else { |
|
427 |
29
| assertInstanceType(left_result, "The arguments to the Plus Operator (+) must both be instances, but you have" +
|
|
428 |
| " specified a type name", that); |
|
429 |
29
| assertInstanceType(right_result, "The arguments to the Plus Operator (+) must both be instances, but you have" +
|
|
430 |
| " specified a type name", that); |
|
431 |
| } |
|
432 |
| |
|
433 |
29
| return _getLeastRestrictiveType(left_result.getSymbolData(), right_result.getSymbolData()).getInstanceData();
|
|
434 |
| |
|
435 |
| } |
|
436 |
| } |
|
437 |
| |
|
438 |
| |
|
439 |
| |
|
440 |
| |
|
441 |
| |
|
442 |
| |
|
443 |
| |
|
444 |
| |
|
445 |
| |
|
446 |
| |
|
447 |
10
| public TypeData forNumericBinaryExpressionOnly(NumericBinaryExpression that, TypeData left_result, TypeData right_result) {
|
|
448 |
0
| if (left_result == null || right_result == null) {return null;}
|
|
449 |
| |
|
450 |
| |
|
451 |
10
| if (!assertFound(left_result, that) || !assertFound(right_result, that)) {
|
|
452 |
0
| return null;
|
|
453 |
| } |
|
454 |
| |
|
455 |
10
| if (assertInstanceType(left_result, "The left side of this expression is a type, not an instance", that) &&
|
|
456 |
| !left_result.getSymbolData().isNumberType(JAVA_VERSION)) { |
|
457 |
| |
|
458 |
1
| _addError("The left side of this expression is not a number. Therefore, you cannot apply a Numeric Binary" +
|
|
459 |
| " Operator (*, /, -, %) to it", that); |
|
460 |
1
| return right_result.getInstanceData();
|
|
461 |
| } |
|
462 |
| |
|
463 |
9
| if (assertInstanceType(right_result, "The right side of this expression is a type, not an instance", that) &&
|
|
464 |
| !right_result.getSymbolData().isNumberType(JAVA_VERSION)) { |
|
465 |
| |
|
466 |
1
| _addError("The right side of this expression is not a number. Therefore, you cannot apply a Numeric Binary " +
|
|
467 |
| "Operator (*, /, -, %) to it", that); |
|
468 |
1
| return left_result.getInstanceData();
|
|
469 |
| } |
|
470 |
| |
|
471 |
| |
|
472 |
8
| return _getLeastRestrictiveType(left_result.getSymbolData(), right_result.getSymbolData()).getInstanceData();
|
|
473 |
| } |
|
474 |
| |
|
475 |
| |
|
476 |
| |
|
477 |
| |
|
478 |
1
| public TypeData forNoOpExpressionOnly(NoOpExpression that, TypeData left_result, TypeData right_result) {
|
|
479 |
1
| throw new RuntimeException("Internal Program Error: The student is missing an operator. " +
|
|
480 |
| "This should have been caught before the TypeChecker. Please report this bug."); |
|
481 |
| } |
|
482 |
| |
|
483 |
| |
|
484 |
| |
|
485 |
| |
|
486 |
| |
|
487 |
| |
|
488 |
14
| public TypeData forIncrementExpression(IncrementExpression that) {
|
|
489 |
14
| TypeData valueRes = that.getValue().visit(new LValueWithValueTypeChecker(this));
|
|
490 |
14
| return forIncrementExpressionOnly(that, valueRes);
|
|
491 |
| } |
|
492 |
| |
|
493 |
| |
|
494 |
| |
|
495 |
| |
|
496 |
| |
|
497 |
9
| public TypeData forPositivePrefixIncrementExpression(PositivePrefixIncrementExpression that) {
|
|
498 |
9
| return forIncrementExpression(that);
|
|
499 |
| } |
|
500 |
| |
|
501 |
0
| public TypeData forNegativePrefixIncrementExpression(NegativePrefixIncrementExpression that) {
|
|
502 |
0
| return forIncrementExpression(that);
|
|
503 |
| } |
|
504 |
| |
|
505 |
0
| public TypeData forPositivePostfixIncrementExpression(PositivePostfixIncrementExpression that) {
|
|
506 |
0
| return forIncrementExpression(that);
|
|
507 |
| } |
|
508 |
| |
|
509 |
5
| public TypeData forNegativePostfixIncrementExpression(NegativePostfixIncrementExpression that) {
|
|
510 |
5
| return forIncrementExpression(that);
|
|
511 |
| } |
|
512 |
| |
|
513 |
| |
|
514 |
| |
|
515 |
| |
|
516 |
| |
|
517 |
| |
|
518 |
| |
|
519 |
| |
|
520 |
19
| public TypeData forIncrementExpressionOnly(IncrementExpression that, TypeData valueRes) {
|
|
521 |
2
| if (valueRes == null) {return null;}
|
|
522 |
| |
|
523 |
| |
|
524 |
17
| if (!assertFound(valueRes, that)) {
|
|
525 |
1
| return null;
|
|
526 |
| } |
|
527 |
| |
|
528 |
16
| if (assertInstanceType(valueRes, "You cannot increment or decrement " + valueRes.getName() +
|
|
529 |
| ", because it is a class name not an instance", that)) { |
|
530 |
11
| if (!valueRes.getSymbolData().isNumberType(JAVA_VERSION)) {
|
|
531 |
2
| _addError("You cannot increment or decrement something that is not a number type." +
|
|
532 |
| " You have specified something of type " + valueRes.getName(), that); |
|
533 |
| } |
|
534 |
| } |
|
535 |
16
| return valueRes.getInstanceData();
|
|
536 |
| } |
|
537 |
| |
|
538 |
| |
|
539 |
| |
|
540 |
| |
|
541 |
| |
|
542 |
| |
|
543 |
| |
|
544 |
| |
|
545 |
11
| public TypeData forNumericUnaryExpressionOnly(NumericUnaryExpression that, TypeData valueRes) {
|
|
546 |
0
| if (valueRes==null) {return null;}
|
|
547 |
| |
|
548 |
| |
|
549 |
11
| if (!assertFound(valueRes, that)) {
|
|
550 |
0
| return null;
|
|
551 |
| } |
|
552 |
| |
|
553 |
11
| if (assertInstanceType(valueRes, "You cannot use a numeric unary operator (+, -) with " + valueRes.getName() +
|
|
554 |
| ", because it is a class name, not an instance", that) && |
|
555 |
| !valueRes.getSymbolData().isNumberType(JAVA_VERSION)) { |
|
556 |
| |
|
557 |
1
| _addError("You cannot apply this unary operator to something of type " + valueRes.getName() +
|
|
558 |
| ". You can only apply it to a numeric type such as double, int, or char", that); |
|
559 |
1
| return valueRes;
|
|
560 |
| } |
|
561 |
| |
|
562 |
| |
|
563 |
10
| return _getLeastRestrictiveType(valueRes.getSymbolData(), SymbolData.INT_TYPE).getInstanceData();
|
|
564 |
| } |
|
565 |
| |
|
566 |
| |
|
567 |
1
| public TypeData forBitwiseNotExpressionOnly(BitwiseNotExpression that, TypeData valueRes) {
|
|
568 |
1
| throw new RuntimeException("Internal Program Error: BitwiseNot is not supported. " +
|
|
569 |
| "It should have been caught before getting to the TypeChecker. Please report this bug."); |
|
570 |
| } |
|
571 |
| |
|
572 |
| |
|
573 |
| |
|
574 |
| |
|
575 |
| |
|
576 |
| |
|
577 |
| |
|
578 |
| |
|
579 |
| |
|
580 |
3
| public TypeData forNotExpressionOnly(NotExpression that, TypeData valueRes) {
|
|
581 |
0
| if (valueRes == null) {return null;}
|
|
582 |
| |
|
583 |
| |
|
584 |
3
| if (!assertFound(valueRes, that)) {
|
|
585 |
0
| return null;
|
|
586 |
| } |
|
587 |
| |
|
588 |
3
| if (assertInstanceType(valueRes,
|
|
589 |
| "You cannot use the not (!) operator with " + valueRes.getName() + |
|
590 |
| ", because it is a class name, not an instance", that) && |
|
591 |
| ! valueRes.getSymbolData().isAssignableTo(SymbolData.BOOLEAN_TYPE, |
|
592 |
| JAVA_VERSION)) { |
|
593 |
| |
|
594 |
1
| _addError("You cannot use the not (!) operator with something of type " + valueRes.getName() +
|
|
595 |
| ". Instead, it should be used with an expression of boolean type", that); |
|
596 |
| } |
|
597 |
| |
|
598 |
3
| return SymbolData.BOOLEAN_TYPE.getInstanceData();
|
|
599 |
| |
|
600 |
| } |
|
601 |
| |
|
602 |
| |
|
603 |
1
| public TypeData forConditionalExpressionOnly(ConditionalExpression that, TypeData condition_result,
|
|
604 |
| TypeData forTrue_result, TypeData forFalse_result) { |
|
605 |
1
| throw new RuntimeException ("Internal Program Error: Conditional expressions are not supported. " +
|
|
606 |
| "This should have been caught before the TypeChecker. Please report this bug."); |
|
607 |
| } |
|
608 |
| |
|
609 |
| |
|
610 |
| |
|
611 |
| |
|
612 |
| |
|
613 |
| |
|
614 |
| |
|
615 |
| |
|
616 |
| |
|
617 |
4
| public TypeData forInstanceofExpressionOnly(InstanceofExpression that, TypeData typeRes, TypeData valueRes) {
|
|
618 |
0
| if (typeRes == null) return null;
|
|
619 |
| |
|
620 |
| |
|
621 |
0
| if (! assertFound(valueRes, that) || ! assertFound(typeRes, that)) return null;
|
|
622 |
| |
|
623 |
4
| if (typeRes.isInstanceType()) {
|
|
624 |
0
| _addError("You are trying to test if an expression value belongs to an instance of a type, which is not allowed."
|
|
625 |
| + " Perhaps you meant to check membership in the type itself, " + typeRes.getName(), |
|
626 |
| that); |
|
627 |
| } |
|
628 |
| |
|
629 |
4
| else if (assertInstanceType(valueRes, "You are trying to test if " + valueRes.getName() +
|
|
630 |
| " belongs to type, but it is a class or interface type, not an instance", that) |
|
631 |
| && ! valueRes.getSymbolData().isCastableTo(typeRes.getSymbolData(), JAVA_VERSION)) { |
|
632 |
| |
|
633 |
1
| _addError("You cannot test whether an expression of type " + valueRes.getName() + " belongs to type "
|
|
634 |
| + typeRes.getName() + " because they are not related", |
|
635 |
| that); |
|
636 |
| } |
|
637 |
| |
|
638 |
4
| return SymbolData.BOOLEAN_TYPE.getInstanceData();
|
|
639 |
| } |
|
640 |
| |
|
641 |
| |
|
642 |
| |
|
643 |
| |
|
644 |
| |
|
645 |
| |
|
646 |
| |
|
647 |
| |
|
648 |
| |
|
649 |
10
| public TypeData forCastExpressionOnly(CastExpression that, TypeData typeRes, TypeData valueRes) {
|
|
650 |
0
| if (typeRes == null || valueRes == null) return null;
|
|
651 |
| |
|
652 |
| |
|
653 |
0
| if (! assertFound(valueRes, that) || ! assertFound(typeRes, that)) return null;
|
|
654 |
| |
|
655 |
10
| if (typeRes.isInstanceType()) {
|
|
656 |
0
| _addError("You are trying to cast to an instance of a type, which is not allowed. " +
|
|
657 |
| "Perhaps you meant to cast to the type itself, " + typeRes.getName(), that); |
|
658 |
| } |
|
659 |
| |
|
660 |
10
| else if (assertInstanceType(valueRes, "You are trying to cast " + valueRes.getName() +
|
|
661 |
| ", which is a class or interface type, not an instance", that) && |
|
662 |
| !valueRes.getSymbolData().isCastableTo(typeRes.getSymbolData(), |
|
663 |
| JAVA_VERSION)) { |
|
664 |
| |
|
665 |
1
| _addError("You cannot cast an expression of type " + valueRes.getName() + " to type " +
|
|
666 |
| typeRes.getName() + " because they are not related", that); |
|
667 |
| } |
|
668 |
| |
|
669 |
10
| return typeRes.getInstanceData();
|
|
670 |
| } |
|
671 |
| |
|
672 |
| |
|
673 |
| |
|
674 |
| |
|
675 |
| |
|
676 |
1
| public TypeData forEmptyExpressionOnly(EmptyExpression that) {
|
|
677 |
1
| throw new RuntimeException("Internal Program Error: EmptyExpression encountered. Student is missing something." +
|
|
678 |
| " Should have been caught before TypeChecker. Please report this bug."); |
|
679 |
| } |
|
680 |
| |
|
681 |
| |
|
682 |
| |
|
683 |
| |
|
684 |
93
| public InstanceData classInstantiationHelper(ClassInstantiation that, SymbolData classToInstantiate) {
|
|
685 |
1
| if (classToInstantiate == null) {return null;}
|
|
686 |
92
| Expression[] expr = that.getArguments().getExpressions();
|
|
687 |
92
| InstanceData[] args = new InstanceData[expr.length];
|
|
688 |
92
| for (int i = 0; i<expr.length; i++) {
|
|
689 |
59
| Expression e = expr[i];
|
|
690 |
59
| TypeData type = e.visit(this);
|
|
691 |
59
| if (type == null || !assertFound(type, expr[i]) ||
|
|
692 |
| ! assertInstanceType(type, "Cannot pass a class or interface name as a constructor argument", e)) { |
|
693 |
| |
|
694 |
1
| return classToInstantiate.getInstanceData();
|
|
695 |
| } |
|
696 |
58
| args[i] = type.getInstanceData();
|
|
697 |
| } |
|
698 |
| |
|
699 |
91
| MethodData md =
|
|
700 |
| _lookupMethod(LanguageLevelVisitor.getUnqualifiedClassName(that.getType().getName()), classToInstantiate, args, |
|
701 |
| that, "No constructor found in class " + Data.dollarSignsToDots(classToInstantiate.getName()) + |
|
702 |
| " with signature: ", true, _getData().getSymbolData()); |
|
703 |
| |
|
704 |
4
| if (md == null) {return classToInstantiate.getInstanceData();}
|
|
705 |
| |
|
706 |
| |
|
707 |
87
| String[] thrown = md.getThrown();
|
|
708 |
87
| for (int i = 0; i<thrown.length; i++) {
|
|
709 |
2
| _thrown.addLast(new Pair<SymbolData, JExpression>(getSymbolData(thrown[i], _getData(), that), that));
|
|
710 |
| } |
|
711 |
| |
|
712 |
87
| return classToInstantiate.getInstanceData();
|
|
713 |
| } |
|
714 |
| |
|
715 |
| |
|
716 |
| |
|
717 |
| |
|
718 |
| |
|
719 |
| |
|
720 |
| |
|
721 |
| |
|
722 |
| |
|
723 |
| |
|
724 |
| |
|
725 |
63
| public TypeData forSimpleNamedClassInstantiation(SimpleNamedClassInstantiation that) {
|
|
726 |
63
| SymbolData type = getSymbolData(that.getType().getName(), _getData(), that);
|
|
727 |
1
| if (type == null) {return null;}
|
|
728 |
| |
|
729 |
| |
|
730 |
62
| String name = that.getType().getName();
|
|
731 |
62
| int lastIndexOfDot = name.lastIndexOf('.');
|
|
732 |
62
| if (!type.hasModifier("static") && (type.getOuterData() != null) && lastIndexOfDot != -1) {
|
|
733 |
1
| String firstPart = name.substring(0, lastIndexOfDot);
|
|
734 |
1
| String secondPart = name.substring(lastIndexOfDot + 1, name.length());
|
|
735 |
1
| _addError(Data.dollarSignsToDots(type.getName()) + " is not a static inner class, and thus cannot be " +
|
|
736 |
| "instantiated from this context. Perhaps you meant to use an instantiation of the form new " + |
|
737 |
| firstPart + "().new " + secondPart + "()", that); |
|
738 |
| } |
|
739 |
62
| InstanceData result = classInstantiationHelper(that, type);
|
|
740 |
62
| if (result != null && result.getSymbolData().hasModifier("abstract")) {
|
|
741 |
1
| _addError(Data.dollarSignsToDots(type.getName()) + " is abstract and thus cannot be instantiated", that);
|
|
742 |
| } |
|
743 |
62
| return result;
|
|
744 |
| } |
|
745 |
| |
|
746 |
| |
|
747 |
| |
|
748 |
| |
|
749 |
| |
|
750 |
| |
|
751 |
| |
|
752 |
| |
|
753 |
| |
|
754 |
9
| public TypeData forComplexNamedClassInstantiation(ComplexNamedClassInstantiation that) {
|
|
755 |
9
| TypeData enclosingType = that.getEnclosing().visit(this);
|
|
756 |
1
| if ((enclosingType == null) || ! assertFound(enclosingType, that.getEnclosing())) { return null; }
|
|
757 |
| |
|
758 |
| else { |
|
759 |
| |
|
760 |
8
| checkAccess(that, enclosingType.getSymbolData().getMav(), enclosingType.getSymbolData().getName(),
|
|
761 |
| enclosingType.getSymbolData(), _data.getSymbolData(), "class or interface", true); |
|
762 |
| |
|
763 |
| |
|
764 |
| |
|
765 |
| |
|
766 |
8
| SymbolData innerClass = getSymbolData(that.getType().getName(), enclosingType.getSymbolData(), that.getType());
|
|
767 |
1
| if (innerClass == null) {return null;}
|
|
768 |
| |
|
769 |
| |
|
770 |
7
| checkAccess(that, innerClass.getMav(), innerClass.getName(), innerClass, _data.getSymbolData(),
|
|
771 |
| "class or interface", true); |
|
772 |
7
| InstanceData result = classInstantiationHelper(that, innerClass);
|
|
773 |
0
| if (result == null) {return null;}
|
|
774 |
7
| boolean resultIsStatic = result.getSymbolData().hasModifier("static");
|
|
775 |
| |
|
776 |
7
| if (!enclosingType.isInstanceType() && !resultIsStatic) {
|
|
777 |
1
| _addError ("The constructor of a non-static inner class can only be called on an instance of its" +
|
|
778 |
| " containing class (e.g. new " + Data.dollarSignsToDots(enclosingType.getName()) + "().new " + |
|
779 |
| that.getType().getName() + "())", that); |
|
780 |
| } |
|
781 |
6
| else if (resultIsStatic) {
|
|
782 |
1
| _addError("You cannot instantiate a static inner class or interface with this syntax. Instead, try new " +
|
|
783 |
| Data.dollarSignsToDots(result.getName()) + "()", that); |
|
784 |
| } |
|
785 |
| |
|
786 |
7
| if (result.getSymbolData().hasModifier("abstract")) {
|
|
787 |
1
| _addError(Data.dollarSignsToDots(result.getName()) + " is abstract and thus cannot be instantiated", that);
|
|
788 |
| } |
|
789 |
7
| return result;
|
|
790 |
| } |
|
791 |
| } |
|
792 |
| |
|
793 |
| |
|
794 |
| |
|
795 |
| |
|
796 |
| |
|
797 |
| |
|
798 |
| |
|
799 |
| |
|
800 |
19
| public SymbolData handleAnonymousClassInstantiation(AnonymousClassInstantiation that, SymbolData superC) {
|
|
801 |
| |
|
802 |
| |
|
803 |
| |
|
804 |
19
| SymbolData sd = superC.getNextAnonymousInnerClass();
|
|
805 |
| |
|
806 |
| |
|
807 |
19
| if (sd == null) {
|
|
808 |
0
| _addError("Nested anonymous classes are not supported at any language lavel", that);
|
|
809 |
0
| return sd;
|
|
810 |
| |
|
811 |
| |
|
812 |
| } |
|
813 |
19
| if (sd.getSuperClass() == null) {
|
|
814 |
2
| if (superC == null) {
|
|
815 |
0
| throw new RuntimeException("Internal Program Error: Superclass data for " + sd + " is null." +
|
|
816 |
| " Please report this bug."); |
|
817 |
| } |
|
818 |
2
| if (superC.isInterface()) {
|
|
819 |
0
| sd.setSuperClass(symbolTable.get("java.lang.Object"));
|
|
820 |
0
| sd.addInterface(superC);
|
|
821 |
| } |
|
822 |
2
| else { sd.setSuperClass(superC);}
|
|
823 |
| } |
|
824 |
19
| LanguageLevelVisitor.createAccessors(sd, _file);
|
|
825 |
| |
|
826 |
19
| return sd;
|
|
827 |
| } |
|
828 |
| |
|
829 |
| |
|
830 |
| |
|
831 |
| |
|
832 |
| |
|
833 |
| |
|
834 |
| |
|
835 |
9
| public TypeData forSimpleAnonymousClassInstantiation(SimpleAnonymousClassInstantiation that) {
|
|
836 |
| |
|
837 |
| |
|
838 |
| |
|
839 |
| |
|
840 |
| |
|
841 |
| |
|
842 |
| |
|
843 |
9
| SymbolData enclosing = _data.getSymbolData();
|
|
844 |
| |
|
845 |
9
| if (enclosing.isDoublyAnonymous()) {
|
|
846 |
0
| _addError(enclosing + "is a nested anonymous class, which is not supported at any language level", that);
|
|
847 |
0
| return null;
|
|
848 |
| } |
|
849 |
| |
|
850 |
9
| final SymbolData superClass = getSymbolData(that.getType().getName(), enclosing, that);
|
|
851 |
| |
|
852 |
| |
|
853 |
9
| SymbolData myData = handleAnonymousClassInstantiation(that, enclosing );
|
|
854 |
| |
|
855 |
0
| if (myData == null) return null;
|
|
856 |
| |
|
857 |
| |
|
858 |
| |
|
859 |
9
| String name = that.getType().getName();
|
|
860 |
9
| int lastIndexOfDot = name.lastIndexOf('.');
|
|
861 |
9
| if (!superClass.hasModifier("static") && !superClass.isInterface() &&
|
|
862 |
| (superClass.getOuterData() != null) && lastIndexOfDot != -1) { |
|
863 |
1
| String firstPart = name.substring(0, lastIndexOfDot);
|
|
864 |
1
| String secondPart = name.substring(lastIndexOfDot + 1, name.length());
|
|
865 |
1
| _addError(Data.dollarSignsToDots(superClass.getName()) +
|
|
866 |
| " is not a static inner class, and thus cannot be instantiated from this context." + |
|
867 |
| " Perhaps you meant to use an instantiation of the form new " + Data.dollarSignsToDots(firstPart) + |
|
868 |
| "().new " + Data.dollarSignsToDots(secondPart) + "()", that); |
|
869 |
| } |
|
870 |
| |
|
871 |
| |
|
872 |
| |
|
873 |
9
| if (superClass.isInterface()) {
|
|
874 |
0
| Expression[] expr = that.getArguments().getExpressions();
|
|
875 |
0
| if (expr.length > 0) {
|
|
876 |
0
| _addError("You are creating an anonymous inner class that directly implements an interface, thus you should" +
|
|
877 |
| " use the Object constructor which takes in no arguments. However, you have specified " + |
|
878 |
| expr.length + " arguments", that);} |
|
879 |
| } |
|
880 |
| |
|
881 |
9
| else classInstantiationHelper(that, superClass);
|
|
882 |
| |
|
883 |
| |
|
884 |
| |
|
885 |
9
| LinkedList<VariableData> vars = cloneVariableDataList(_vars);
|
|
886 |
9
| vars.addAll(myData.getVars());
|
|
887 |
9
| final TypeData bodyRes = that.getBody().visit(new ClassBodyTypeChecker(myData, _file, _package, _importedFiles,
|
|
888 |
| _importedPackages, vars, _thrown)); |
|
889 |
| |
|
890 |
| |
|
891 |
9
| _checkAbstractMethods(myData, that);
|
|
892 |
9
| return myData.getInstanceData();
|
|
893 |
| } |
|
894 |
| |
|
895 |
| |
|
896 |
| |
|
897 |
| |
|
898 |
| |
|
899 |
| |
|
900 |
| |
|
901 |
| |
|
902 |
10
| public TypeData forComplexAnonymousClassInstantiation(ComplexAnonymousClassInstantiation that) {
|
|
903 |
| |
|
904 |
| |
|
905 |
| |
|
906 |
| |
|
907 |
| |
|
908 |
| |
|
909 |
| |
|
910 |
| |
|
911 |
10
| if (_data.isDoublyAnonymous()) {
|
|
912 |
0
| _addError(_data + "is a nested anonymous class, which is not supported at any language level", that);
|
|
913 |
0
| return null;
|
|
914 |
| } |
|
915 |
| |
|
916 |
10
| SymbolData lexEnclosing = _data.getSymbolData();
|
|
917 |
| |
|
918 |
10
| Expression receiver = that.getEnclosing();
|
|
919 |
| |
|
920 |
| |
|
921 |
10
| TypeData enclosingType = receiver.visit(this);
|
|
922 |
| |
|
923 |
0
| if ((enclosingType == null) || ! assertFound(enclosingType, that.getEnclosing())) { return null; }
|
|
924 |
| |
|
925 |
10
| SymbolData enclosing = enclosingType.getSymbolData();
|
|
926 |
| |
|
927 |
| |
|
928 |
10
| checkAccess(that, enclosing.getMav(), enclosing.getName(), enclosing, lexEnclosing, "class or interface", true);
|
|
929 |
| |
|
930 |
10
| final SymbolData superClass = getSymbolData(that.getType().getName(), enclosing, that.getType());
|
|
931 |
| |
|
932 |
| |
|
933 |
| |
|
934 |
10
| SymbolData myData = handleAnonymousClassInstantiation(that, lexEnclosing);
|
|
935 |
0
| if (myData == null) return null;
|
|
936 |
| |
|
937 |
| |
|
938 |
| |
|
939 |
| |
|
940 |
10
| boolean resultIsStatic;
|
|
941 |
| |
|
942 |
10
| if (superClass.isInterface()) {
|
|
943 |
0
| Expression[] expr = that.getArguments().getExpressions();
|
|
944 |
0
| if (expr.length > 0) {
|
|
945 |
0
| _addError("You are creating an anonymous inner class that directly implements an interface, thus you should" +
|
|
946 |
| " use the Object constructor which takes in no arguments. However, you have specified " + |
|
947 |
| expr.length + " arguments", that); |
|
948 |
| } |
|
949 |
0
| resultIsStatic = true;
|
|
950 |
| } |
|
951 |
| |
|
952 |
| |
|
953 |
| else { |
|
954 |
10
| InstanceData result = classInstantiationHelper(that, superClass);
|
|
955 |
0
| if (result == null) return null;
|
|
956 |
| |
|
957 |
10
| resultIsStatic = result.getSymbolData().hasModifier("static");
|
|
958 |
| } |
|
959 |
| |
|
960 |
10
| if (!enclosingType.isInstanceType() && !resultIsStatic) {
|
|
961 |
1
| _addError ("The constructor of a non-static inner class can only be called on an instance of its containing" +
|
|
962 |
| " class (e.g. new " + Data.dollarSignsToDots(enclosingType.getName()) + "().new " + |
|
963 |
| that.getType().getName() + "())", that); |
|
964 |
| } |
|
965 |
| |
|
966 |
9
| else if (enclosingType.isInstanceType() && resultIsStatic) {
|
|
967 |
1
| _addError("You cannot instantiate a static inner class or interface with this syntax. Instead, try new " +
|
|
968 |
| Data.dollarSignsToDots(superClass.getName()) + "()", that); |
|
969 |
| } |
|
970 |
| |
|
971 |
| |
|
972 |
10
| LinkedList<VariableData> vars = cloneVariableDataList(_vars);
|
|
973 |
10
| vars.addAll(myData.getVars());
|
|
974 |
| |
|
975 |
10
| final TypeData bodyRes = that.getBody().visit(new ClassBodyTypeChecker(myData, _file, _package, _importedFiles,
|
|
976 |
| _importedPackages, vars, _thrown)); |
|
977 |
| |
|
978 |
| |
|
979 |
10
| _checkAbstractMethods(myData, that);
|
|
980 |
| |
|
981 |
10
| return myData.getInstanceData();
|
|
982 |
| } |
|
983 |
| |
|
984 |
| |
|
985 |
| |
|
986 |
1
| public TypeData forSimpleThisConstructorInvocation(SimpleThisConstructorInvocation that) {
|
|
987 |
1
| _addError("This constructor invocations are only allowed as the first statement of a constructor body", that);
|
|
988 |
1
| return null;
|
|
989 |
| } |
|
990 |
| |
|
991 |
| |
|
992 |
1
| public TypeData forComplexThisConstructorInvocation(ComplexThisConstructorInvocation that) {
|
|
993 |
1
| _addError("Constructor invocations of this form are never allowed", that);
|
|
994 |
1
| return null;
|
|
995 |
| } |
|
996 |
| |
|
997 |
| |
|
998 |
| |
|
999 |
| |
|
1000 |
| |
|
1001 |
| |
|
1002 |
| |
|
1003 |
292
| public TypeData forSimpleNameReference(SimpleNameReference that) {
|
|
1004 |
292
| Word myWord = that.getName();
|
|
1005 |
292
| myWord.visit(this);
|
|
1006 |
| |
|
1007 |
| |
|
1008 |
| |
|
1009 |
292
| VariableData reference = getFieldOrVariable(myWord.getText(), _data, _data.getSymbolData(), that, _vars, true, true);
|
|
1010 |
292
| if (reference != null) {
|
|
1011 |
232
| if (! reference.hasValue()) {
|
|
1012 |
4
| _addError("You cannot use " + reference.getName() + " because it may not have been given a value", that.getName());
|
|
1013 |
| } |
|
1014 |
| |
|
1015 |
| |
|
1016 |
232
| if (inStaticMethod() && ! reference.hasModifier("static") && ! reference.isLocalVariable()) {
|
|
1017 |
2
| _addError("Non-static variable or field " + reference.getName() + " cannot be referenced from a static context", that);
|
|
1018 |
| } |
|
1019 |
| |
|
1020 |
| |
|
1021 |
232
| return reference.getType().getInstanceData();
|
|
1022 |
| } |
|
1023 |
| |
|
1024 |
| |
|
1025 |
60
| SymbolData classR = findClassReference(null, myWord.getText(), that);
|
|
1026 |
60
| if (classR != null && classR != SymbolData.AMBIGUOUS_REFERENCE) {
|
|
1027 |
| |
|
1028 |
31
| if (checkAccess(that, classR.getMav(), classR.getName(), classR, _data.getSymbolData(),
|
|
1029 |
| "class or interface", false)) { |
|
1030 |
30
| return classR;
|
|
1031 |
| } |
|
1032 |
| } |
|
1033 |
1
| if (classR == SymbolData.AMBIGUOUS_REFERENCE) {return null;}
|
|
1034 |
| |
|
1035 |
29
| PackageData packageD = new PackageData(myWord.getText());
|
|
1036 |
29
| return packageD;
|
|
1037 |
| } |
|
1038 |
| |
|
1039 |
| |
|
1040 |
| |
|
1041 |
| |
|
1042 |
| |
|
1043 |
| |
|
1044 |
| |
|
1045 |
| |
|
1046 |
| |
|
1047 |
| |
|
1048 |
| |
|
1049 |
| |
|
1050 |
73
| public TypeData forComplexNameReference(ComplexNameReference that) {
|
|
1051 |
73
| TypeData lhs = that.getEnclosing().visit(this);
|
|
1052 |
0
| if (lhs == null) return null;
|
|
1053 |
| |
|
1054 |
73
| Word myWord = that.getName();
|
|
1055 |
| |
|
1056 |
| |
|
1057 |
73
| if (lhs instanceof PackageData) {
|
|
1058 |
37
| SymbolData classRef = findClassReference(lhs, myWord.getText(), that);
|
|
1059 |
17
| if (classRef != null) { return classRef; }
|
|
1060 |
20
| return new PackageData((PackageData) lhs, myWord.getText());
|
|
1061 |
| } |
|
1062 |
0
| if (_data == null) return null;
|
|
1063 |
36
| checkAccess(that, lhs.getSymbolData().getMav(), lhs.getSymbolData().getName(), lhs.getSymbolData(),
|
|
1064 |
| _data.getSymbolData(), "class or interface", true); |
|
1065 |
| |
|
1066 |
| |
|
1067 |
36
| VariableData reference = getFieldOrVariable(myWord.getText(), lhs.getSymbolData(), _data.getSymbolData(), that);
|
|
1068 |
36
| if (reference != null) {
|
|
1069 |
29
| if (lhs instanceof SymbolData) {
|
|
1070 |
| |
|
1071 |
13
| if (! reference.hasModifier("static")) {
|
|
1072 |
1
| _addError("Non-static variable " + reference.getName() + " cannot be accessed from the static context " +
|
|
1073 |
| Data.dollarSignsToDots(lhs.getName()) + ". Perhaps you meant to instantiate an instance of " + |
|
1074 |
| Data.dollarSignsToDots(lhs.getName()), that); |
|
1075 |
1
| return reference.getType().getInstanceData();
|
|
1076 |
| } |
|
1077 |
| } |
|
1078 |
| |
|
1079 |
| |
|
1080 |
28
| if (!reference.hasValue()) {
|
|
1081 |
4
| _addError("You cannot use " + reference.getName() + " here, because it may not have been given a value",
|
|
1082 |
| that.getName()); |
|
1083 |
| } |
|
1084 |
| |
|
1085 |
28
| return reference.getType().getInstanceData();
|
|
1086 |
| } |
|
1087 |
| |
|
1088 |
| |
|
1089 |
7
| SymbolData sd = getSymbolData(true, myWord.getText(), lhs.getSymbolData(), that, false);
|
|
1090 |
7
| if (sd != null && sd != SymbolData.AMBIGUOUS_REFERENCE) {
|
|
1091 |
5
| if (!checkAccess(that, sd.getMav(), sd.getName(), sd, _data.getSymbolData(), "class or interface")) {
|
|
1092 |
1
| return null;
|
|
1093 |
| } |
|
1094 |
4
| if (!sd.hasModifier("static")) {
|
|
1095 |
2
| _addError("Non-static inner class " + Data.dollarSignsToDots(sd.getName()) +
|
|
1096 |
| " cannot be accessed from this context. Perhaps you meant to instantiate it", that); |
|
1097 |
| } |
|
1098 |
| |
|
1099 |
| |
|
1100 |
2
| else if (lhs instanceof InstanceData) {
|
|
1101 |
1
| _addError("You cannot reference the static inner class " + Data.dollarSignsToDots(sd.getName()) +
|
|
1102 |
| " from an instance of " + Data.dollarSignsToDots(lhs.getName()) + ". Perhaps you meant to say " |
|
1103 |
| + Data.dollarSignsToDots(sd.getName()), that); |
|
1104 |
| } |
|
1105 |
4
| return sd;
|
|
1106 |
| } |
|
1107 |
| |
|
1108 |
2
| if (sd != SymbolData.AMBIGUOUS_REFERENCE) {
|
|
1109 |
1
| _addError("Could not resolve " + myWord.getText() + " from the context of " + Data.dollarSignsToDots(lhs.getName()),
|
|
1110 |
| that); |
|
1111 |
| } |
|
1112 |
2
| return null;
|
|
1113 |
| } |
|
1114 |
| |
|
1115 |
| |
|
1116 |
| |
|
1117 |
| |
|
1118 |
| |
|
1119 |
| |
|
1120 |
7
| public TypeData forSimpleThisReference(SimpleThisReference that) {
|
|
1121 |
7
| if (inStaticMethod()) {
|
|
1122 |
1
| _addError("'this' cannot be referenced from within a static method", that);
|
|
1123 |
| } |
|
1124 |
7
| return _getData().getSymbolData().getInstanceData();
|
|
1125 |
| } |
|
1126 |
| |
|
1127 |
| |
|
1128 |
| |
|
1129 |
| |
|
1130 |
| |
|
1131 |
| |
|
1132 |
| |
|
1133 |
| |
|
1134 |
| |
|
1135 |
7
| public TypeData forComplexThisReferenceOnly(ComplexThisReference that, TypeData enclosing_result) {
|
|
1136 |
| |
|
1137 |
2
| if ((enclosing_result == null) || ! assertFound(enclosing_result, that.getEnclosing())) { return null; }
|
|
1138 |
| |
|
1139 |
5
| if (inStaticMethod()) {
|
|
1140 |
1
| _addError("'this' cannot be referenced from within a static method", that);
|
|
1141 |
| } |
|
1142 |
| |
|
1143 |
5
| if (enclosing_result.isInstanceType()) {
|
|
1144 |
1
| _addError("'this' can only be referenced from a type name, but you have specified an instance of that type.", that);
|
|
1145 |
| } |
|
1146 |
| |
|
1147 |
5
| SymbolData myData = _getData().getSymbolData();
|
|
1148 |
5
| if (!myData.isInnerClassOf(enclosing_result.getSymbolData(), true)) {
|
|
1149 |
| |
|
1150 |
2
| if (myData.isInnerClassOf(enclosing_result.getSymbolData(), false)) {
|
|
1151 |
1
| _addError("You cannot reference " + enclosing_result.getName() + ".this from here, because " + myData.getName() +
|
|
1152 |
| " or one of its enclosing classes " + |
|
1153 |
| "is static. Thus, an enclosing instance of " + enclosing_result.getName() + " does not exist", that); |
|
1154 |
| } |
|
1155 |
| else { |
|
1156 |
1
| _addError("You cannot reference " + enclosing_result.getName() + ".this from here, because " + enclosing_result.getName() +
|
|
1157 |
| " is not an outer class of " + myData.getName(), that); |
|
1158 |
| } |
|
1159 |
| } |
|
1160 |
| |
|
1161 |
5
| return enclosing_result.getInstanceData();
|
|
1162 |
| } |
|
1163 |
| |
|
1164 |
| |
|
1165 |
| |
|
1166 |
| |
|
1167 |
| |
|
1168 |
| |
|
1169 |
| |
|
1170 |
3
| public TypeData forSimpleSuperReference(SimpleSuperReference that) {
|
|
1171 |
3
| if (inStaticMethod()) {
|
|
1172 |
1
| _addError("'super' cannot be referenced from within a static method", that);
|
|
1173 |
| } |
|
1174 |
3
| SymbolData superClass = _getData().getSymbolData().getSuperClass();
|
|
1175 |
3
| if (superClass == null) {
|
|
1176 |
0
| _addError("The class " + _getData().getSymbolData().getName() + " does not have a super class", that);
|
|
1177 |
0
| return null;
|
|
1178 |
| } |
|
1179 |
3
| return superClass.getInstanceData();
|
|
1180 |
| } |
|
1181 |
| |
|
1182 |
| |
|
1183 |
| |
|
1184 |
| |
|
1185 |
| |
|
1186 |
| |
|
1187 |
| |
|
1188 |
| |
|
1189 |
7
| public TypeData forComplexSuperReferenceOnly(ComplexSuperReference that, TypeData enclosing_result) {
|
|
1190 |
| |
|
1191 |
2
| if ((enclosing_result == null) || ! assertFound(enclosing_result, that.getEnclosing())) { return null; }
|
|
1192 |
| |
|
1193 |
5
| if (inStaticMethod()) {
|
|
1194 |
1
| _addError("'super' cannot be referenced from within a static method", that);
|
|
1195 |
| } |
|
1196 |
5
| if (enclosing_result.isInstanceType()) {
|
|
1197 |
1
| _addError("'super' can only be referenced from a type name, but you have specified an instance of that type.", that);
|
|
1198 |
| } |
|
1199 |
| |
|
1200 |
5
| SymbolData myData = _getData().getSymbolData();
|
|
1201 |
5
| if (!myData.isInnerClassOf(enclosing_result.getSymbolData(), true)) {
|
|
1202 |
| |
|
1203 |
2
| if (myData.isInnerClassOf(enclosing_result.getSymbolData(), false)) {
|
|
1204 |
1
| _addError("You cannot reference " + enclosing_result.getName() + ".super from here, because " + myData.getName() +
|
|
1205 |
| " or one of its enclosing classes " + |
|
1206 |
| "is static. Thus, an enclosing instance of " + enclosing_result.getName() + " does not exist", that); |
|
1207 |
| } |
|
1208 |
| else { |
|
1209 |
1
| _addError("You cannot reference " + enclosing_result.getName() + ".super from here, because " +
|
|
1210 |
| enclosing_result.getName() + " is not an outer class of " + myData.getName(), that); |
|
1211 |
| } |
|
1212 |
| } |
|
1213 |
| |
|
1214 |
5
| SymbolData superClass = enclosing_result.getSymbolData().getSuperClass();
|
|
1215 |
5
| if (superClass == null) {
|
|
1216 |
0
| _addError("The class " + enclosing_result.getName() + " does not have a super class", that);
|
|
1217 |
0
| return null;
|
|
1218 |
| } |
|
1219 |
| |
|
1220 |
5
| return superClass.getInstanceData();
|
|
1221 |
| } |
|
1222 |
| |
|
1223 |
| |
|
1224 |
| |
|
1225 |
| |
|
1226 |
| |
|
1227 |
17
| public TypeData forArrayAccessOnly(ArrayAccess that, TypeData lhs, TypeData index) {
|
|
1228 |
| |
|
1229 |
2
| if (lhs == null || index == null) {return null;}
|
|
1230 |
| |
|
1231 |
| |
|
1232 |
15
| if (!assertFound(lhs, that) || !assertFound(index, that)) {
|
|
1233 |
2
| return null;
|
|
1234 |
| } |
|
1235 |
| |
|
1236 |
13
| if (assertInstanceType(lhs, "You cannot access an array element of a type name", that) &&
|
|
1237 |
| ! (lhs.getSymbolData() instanceof ArrayData)) { |
|
1238 |
1
| _addError("The variable referred to by this array access is a " + lhs.getSymbolData().getName() + ", not an array",
|
|
1239 |
| that); |
|
1240 |
1
| return lhs.getInstanceData();
|
|
1241 |
| } |
|
1242 |
| |
|
1243 |
12
| if (assertInstanceType(index, "You have used a type name in place of an array index", that) &&
|
|
1244 |
| ! index.getSymbolData().isAssignableTo(SymbolData.INT_TYPE, JAVA_VERSION)) { |
|
1245 |
1
| _addError("You cannot reference an array element with an index of type " + index.getSymbolData().getName() +
|
|
1246 |
| ". Instead, you must use an int", that); |
|
1247 |
| } |
|
1248 |
| |
|
1249 |
12
| return ((ArrayData)lhs.getSymbolData()).getElementType().getInstanceData();
|
|
1250 |
| } |
|
1251 |
| |
|
1252 |
| |
|
1253 |
53
| public TypeData forStringLiteralOnly(StringLiteral that) {
|
|
1254 |
53
| assert symbolTable.get("java.lang.String") != null;
|
|
1255 |
53
| return symbolTable.get("java.lang.String").getInstanceData();
|
|
1256 |
| } |
|
1257 |
| |
|
1258 |
267
| public TypeData forIntegerLiteralOnly(IntegerLiteral that) {
|
|
1259 |
267
| return SymbolData.INT_TYPE.getInstanceData();
|
|
1260 |
| } |
|
1261 |
| |
|
1262 |
1
| public TypeData forLongLiteralOnly(LongLiteral that) {
|
|
1263 |
1
| return SymbolData.LONG_TYPE.getInstanceData();
|
|
1264 |
| } |
|
1265 |
| |
|
1266 |
1
| public TypeData forFloatLiteralOnly(FloatLiteral that) {
|
|
1267 |
1
| return SymbolData.FLOAT_TYPE.getInstanceData();
|
|
1268 |
| } |
|
1269 |
| |
|
1270 |
13
| public TypeData forDoubleLiteralOnly(DoubleLiteral that) {
|
|
1271 |
13
| return SymbolData.DOUBLE_TYPE.getInstanceData();
|
|
1272 |
| } |
|
1273 |
| |
|
1274 |
25
| public TypeData forCharLiteralOnly(CharLiteral that) {
|
|
1275 |
25
| return SymbolData.CHAR_TYPE.getInstanceData();
|
|
1276 |
| } |
|
1277 |
| |
|
1278 |
25
| public TypeData forBooleanLiteralOnly(BooleanLiteral that) {
|
|
1279 |
25
| return SymbolData.BOOLEAN_TYPE.getInstanceData();
|
|
1280 |
| } |
|
1281 |
| |
|
1282 |
9
| public TypeData forNullLiteralOnly(NullLiteral that) {
|
|
1283 |
9
| return SymbolData.NULL_TYPE.getInstanceData();
|
|
1284 |
| } |
|
1285 |
| |
|
1286 |
1
| public TypeData forClassLiteralOnly(ClassLiteral that) {
|
|
1287 |
1
| return symbolTable.get("java.lang.Class").getInstanceData();
|
|
1288 |
| } |
|
1289 |
| |
|
1290 |
| |
|
1291 |
| |
|
1292 |
| |
|
1293 |
| |
|
1294 |
11
| public TypeData forParenthesizedOnly(Parenthesized that, TypeData valueRes) {
|
|
1295 |
1
| if (valueRes == null) {return null;}
|
|
1296 |
| |
|
1297 |
10
| if (!assertFound(valueRes, that.getValue())) {
|
|
1298 |
1
| return null;
|
|
1299 |
| } |
|
1300 |
| |
|
1301 |
9
| assertInstanceType(valueRes, "This class or interface name cannot appear in parentheses", that);
|
|
1302 |
9
| return valueRes.getInstanceData();
|
|
1303 |
| } |
|
1304 |
| |
|
1305 |
| |
|
1306 |
| |
|
1307 |
| |
|
1308 |
| |
|
1309 |
| |
|
1310 |
| |
|
1311 |
| |
|
1312 |
| |
|
1313 |
67
| public TypeData methodInvocationHelper(MethodInvocation that, TypeData context) {
|
|
1314 |
67
| Expression[] exprs = that.getArguments().getExpressions();
|
|
1315 |
67
| TypeData[] args = new TypeData[exprs.length];
|
|
1316 |
67
| InstanceData[] newArgs = new InstanceData[exprs.length];
|
|
1317 |
67
| for (int i = 0; i < exprs.length; i++) {
|
|
1318 |
57
| args[i] = exprs[i].visit(this);
|
|
1319 |
57
| if (args[i] == null) {
|
|
1320 |
0
| return null;
|
|
1321 |
| } |
|
1322 |
| |
|
1323 |
0
| if (! assertFound(args[i], that)) return null;
|
|
1324 |
57
| if (! args[i].isInstanceType()) {
|
|
1325 |
1
| _addError("Cannot pass a class or interface name as an argument to a method." +
|
|
1326 |
| " Perhaps you meant to create an instance or use " + args[i].getName() + ".class", exprs[i]); |
|
1327 |
| } |
|
1328 |
57
| newArgs[i]=args[i].getInstanceData();
|
|
1329 |
| |
|
1330 |
| } |
|
1331 |
| |
|
1332 |
| |
|
1333 |
| |
|
1334 |
67
| MethodData md = _lookupMethod(that.getName().getText(), context.getSymbolData(), newArgs, that,
|
|
1335 |
| "No method found in class " + context.getName() + " with signature: ", |
|
1336 |
| false, _getData().getSymbolData()); |
|
1337 |
| |
|
1338 |
3
| if (md == null) return null;
|
|
1339 |
| |
|
1340 |
64
| if (! context.isInstanceType() && ! md.hasModifier("static")) {
|
|
1341 |
3
| _addError("Cannot access the non-static method " + md.getName() + " from a static context", that);
|
|
1342 |
| } |
|
1343 |
| |
|
1344 |
| |
|
1345 |
64
| String[] thrown = md.getThrown();
|
|
1346 |
64
| for (int i = 0; i < thrown.length; i++) {
|
|
1347 |
2
| _thrown.addLast(new Pair<SymbolData, JExpression>(getSymbolData(thrown[i], _getData(), that), that));
|
|
1348 |
| } |
|
1349 |
| |
|
1350 |
64
| SymbolData returnType = md.getReturnType();
|
|
1351 |
64
| if (returnType == null) {
|
|
1352 |
0
| _addError("Internal error: the returnType for " + md + " is null", that);
|
|
1353 |
| |
|
1354 |
| |
|
1355 |
| |
|
1356 |
0
| return null;
|
|
1357 |
| } |
|
1358 |
| |
|
1359 |
64
| return returnType.getInstanceData();
|
|
1360 |
| } |
|
1361 |
| |
|
1362 |
| |
|
1363 |
| |
|
1364 |
| |
|
1365 |
| |
|
1366 |
| |
|
1367 |
| |
|
1368 |
31
| public TypeData forSimpleMethodInvocation(SimpleMethodInvocation that) {
|
|
1369 |
31
| TypeData context = _getData().getSymbolData().getInstanceData();
|
|
1370 |
2
| if (inStaticMethod()) context = context.getSymbolData();
|
|
1371 |
31
| return methodInvocationHelper(that, context);
|
|
1372 |
| } |
|
1373 |
| |
|
1374 |
| |
|
1375 |
| |
|
1376 |
| |
|
1377 |
| |
|
1378 |
| |
|
1379 |
| |
|
1380 |
30
| public TypeData forComplexMethodInvocation(ComplexMethodInvocation that) {
|
|
1381 |
30
| TypeData context = that.getEnclosing().visit(this);
|
|
1382 |
0
| if (! assertFound(context, that.getEnclosing()) || context == null) return null;
|
|
1383 |
| |
|
1384 |
| |
|
1385 |
30
| checkAccess(that, context.getSymbolData().getMav(), context.getSymbolData().getName(),
|
|
1386 |
| context.getSymbolData(), _data.getSymbolData(), "class or interface", true); |
|
1387 |
| |
|
1388 |
| |
|
1389 |
| |
|
1390 |
| |
|
1391 |
30
| return methodInvocationHelper(that, context);
|
|
1392 |
| } |
|
1393 |
| |
|
1394 |
| |
|
1395 |
| |
|
1396 |
| |
|
1397 |
| |
|
1398 |
| |
|
1399 |
28
| protected boolean canBeAssigned(VariableData vd) { return ! vd.isFinal() || ! vd.hasValue(); }
|
|
1400 |
| |
|
1401 |
| |
|
1402 |
| |
|
1403 |
| |
|
1404 |
| |
|
1405 |
| |
|
1406 |
| |
|
1407 |
| |
|
1408 |
| |
|
1409 |
| |
|
1410 |
| |
|
1411 |
51
| protected SymbolData _getLeastRestrictiveType(SymbolData sd1, SymbolData sd2) {
|
|
1412 |
51
| if ((sd1.isDoubleType(JAVA_VERSION) &&
|
|
1413 |
| sd2.isNumberType(JAVA_VERSION)) || |
|
1414 |
| (sd2.isDoubleType(JAVA_VERSION) && |
|
1415 |
| sd1.isNumberType(JAVA_VERSION))) { |
|
1416 |
5
| return SymbolData.DOUBLE_TYPE;
|
|
1417 |
| } |
|
1418 |
46
| else if ((sd1.isFloatType(JAVA_VERSION) &&
|
|
1419 |
| sd2.isNumberType(JAVA_VERSION)) || |
|
1420 |
| (sd2.isFloatType(JAVA_VERSION) && |
|
1421 |
| sd1.isNumberType(JAVA_VERSION))) { |
|
1422 |
2
| return SymbolData.FLOAT_TYPE;
|
|
1423 |
| } |
|
1424 |
44
| else if ((sd1.isLongType(JAVA_VERSION) &&
|
|
1425 |
| sd2.isNumberType(JAVA_VERSION)) || |
|
1426 |
| (sd2.isLongType(JAVA_VERSION) && |
|
1427 |
| sd1.isNumberType(JAVA_VERSION))) { |
|
1428 |
0
| return SymbolData.LONG_TYPE;
|
|
1429 |
| } |
|
1430 |
44
| else if (sd1.isBooleanType(JAVA_VERSION) &&
|
|
1431 |
| sd2.isBooleanType(JAVA_VERSION)) { |
|
1432 |
0
| return SymbolData.BOOLEAN_TYPE;
|
|
1433 |
| } |
|
1434 |
44
| else return SymbolData.INT_TYPE;
|
|
1435 |
| } |
|
1436 |
| |
|
1437 |
| |
|
1438 |
| |
|
1439 |
| |
|
1440 |
| |
|
1441 |
| |
|
1442 |
| |
|
1443 |
| |
|
1444 |
0
| public TypeData forConditionalExpression(ConditionalExpression that) {
|
|
1445 |
0
| throw new RuntimeException("Internal Program Error: Conditional expressions are not supported. This should have been caught before the Type Checker. Please report this bug.");
|
|
1446 |
| } |
|
1447 |
| |
|
1448 |
| |
|
1449 |
| |
|
1450 |
| |
|
1451 |
| |
|
1452 |
| |
|
1453 |
| |
|
1454 |
| |
|
1455 |
0
| public TypeData forInstanceofExpression(InstanceofExpression that) {
|
|
1456 |
| |
|
1457 |
0
| final SymbolData typeRes = getSymbolData(that.getType().getName(), _data.getSymbolData(), that.getType(), false);
|
|
1458 |
0
| final TypeData valueRes = that.getValue().visit(this);
|
|
1459 |
| |
|
1460 |
0
| if (typeRes == null) {
|
|
1461 |
0
| _addError(that.getType().getName()
|
|
1462 |
| + " cannot appear as the type of a instanceof expression because it is not a valid type", |
|
1463 |
| that.getType()); |
|
1464 |
0
| return null;
|
|
1465 |
| } |
|
1466 |
| |
|
1467 |
0
| if (! assertFound(valueRes, that.getValue())) {
|
|
1468 |
| |
|
1469 |
| |
|
1470 |
0
| return SymbolData.BOOLEAN_TYPE.getInstanceData();
|
|
1471 |
| } |
|
1472 |
| |
|
1473 |
| |
|
1474 |
0
| return forInstanceofExpressionOnly(that, typeRes, valueRes);
|
|
1475 |
| } |
|
1476 |
| |
|
1477 |
| |
|
1478 |
| |
|
1479 |
| |
|
1480 |
| |
|
1481 |
| |
|
1482 |
| |
|
1483 |
| |
|
1484 |
| |
|
1485 |
| |
|
1486 |
8
| public TypeData forCastExpression(CastExpression that) {
|
|
1487 |
| |
|
1488 |
8
| final SymbolData typeRes = getSymbolData(that.getType().getName(), _data.getSymbolData(), that.getType(), false);
|
|
1489 |
8
| final TypeData valueRes = that.getValue().visit(this);
|
|
1490 |
| |
|
1491 |
8
| if (typeRes == null) {
|
|
1492 |
1
| _addError(that.getType().getName() + " cannot appear as the type of a cast expression because it is not a valid type", that.getType());
|
|
1493 |
1
| return null;
|
|
1494 |
| } |
|
1495 |
| |
|
1496 |
7
| if (valueRes == null || !assertFound(valueRes, that.getValue())) {
|
|
1497 |
| |
|
1498 |
| |
|
1499 |
1
| return typeRes.getInstanceData();
|
|
1500 |
| } |
|
1501 |
| |
|
1502 |
| |
|
1503 |
6
| return forCastExpressionOnly(that, typeRes, valueRes);
|
|
1504 |
| } |
|
1505 |
| |
|
1506 |
| |
|
1507 |
| |
|
1508 |
| |
|
1509 |
| |
|
1510 |
| |
|
1511 |
| |
|
1512 |
| |
|
1513 |
| |
|
1514 |
| |
|
1515 |
10
| public TypeData forUninitializedArrayInstantiationOnly(UninitializedArrayInstantiation that, TypeData typeRes,
|
|
1516 |
| TypeData[] dimensions_result) { |
|
1517 |
| |
|
1518 |
10
| Expression[] dims = that.getDimensionSizes().getExpressions();
|
|
1519 |
10
| for (int i = 0; i<dimensions_result.length; i++) {
|
|
1520 |
27
| if (dimensions_result[i] != null && assertFound(dimensions_result[i], dims[i])) {
|
|
1521 |
27
| if (!dimensions_result[i].getSymbolData().isAssignableTo(SymbolData.INT_TYPE,
|
|
1522 |
| JAVA_VERSION)) { |
|
1523 |
2
| _addError("The dimensions of an array instantiation must all be ints. You have specified something of type " +
|
|
1524 |
| dimensions_result[i].getName(), dims[i]); |
|
1525 |
| } |
|
1526 |
| else { |
|
1527 |
25
| assertInstanceType(dimensions_result[i], "All dimensions of an array instantiation must be instances." +
|
|
1528 |
| " You have specified the type " + dimensions_result[i].getName(), dims[i]); |
|
1529 |
| } |
|
1530 |
| } |
|
1531 |
| } |
|
1532 |
| |
|
1533 |
10
| if (typeRes instanceof ArrayData) {
|
|
1534 |
9
| int dim = ((ArrayData) typeRes).getDimensions();
|
|
1535 |
9
| if (dimensions_result.length > dim) {
|
|
1536 |
| |
|
1537 |
1
| _addError("You are trying to initialize an array of type " + typeRes.getName() + " which requires " + dim +
|
|
1538 |
| " dimensions, but you have specified " + dimensions_result.length + " dimensions--the wrong number", |
|
1539 |
| that); |
|
1540 |
| } |
|
1541 |
| } |
|
1542 |
| |
|
1543 |
| |
|
1544 |
1
| if (typeRes == null || !assertFound(typeRes, that)) {return null;}
|
|
1545 |
9
| return typeRes.getInstanceData();
|
|
1546 |
| } |
|
1547 |
| |
|
1548 |
| |
|
1549 |
| |
|
1550 |
| |
|
1551 |
| |
|
1552 |
| |
|
1553 |
6
| public TypeData forSimpleUninitializedArrayInstantiation(SimpleUninitializedArrayInstantiation that) {
|
|
1554 |
6
| final SymbolData typeRes = getSymbolData(that.getType().getName(), _data.getSymbolData(), that.getType());
|
|
1555 |
6
| final TypeData[] dimensions_result = makeArrayOfRetType(that.getDimensionSizes().getExpressions().length);
|
|
1556 |
| |
|
1557 |
6
| for (int i = 0; i<that.getDimensionSizes().getExpressions().length; i++) {
|
|
1558 |
15
| dimensions_result[i] = that.getDimensionSizes().getExpressions()[i].visit(this);
|
|
1559 |
| } |
|
1560 |
6
| return forUninitializedArrayInstantiationOnly(that, typeRes, dimensions_result);
|
|
1561 |
| } |
|
1562 |
| |
|
1563 |
| |
|
1564 |
| |
|
1565 |
| |
|
1566 |
| |
|
1567 |
1
| public TypeData forComplexUninitializedArrayInstantiation(ComplexUninitializedArrayInstantiation that) {
|
|
1568 |
1
| throw new RuntimeException("Internal Program Error: Complex Uninitialized Array Instantiations are not legal Java." +
|
|
1569 |
| " This should have been caught before the Type Checker. Please report this bug."); |
|
1570 |
| } |
|
1571 |
| |
|
1572 |
| |
|
1573 |
| |
|
1574 |
| |
|
1575 |
| |
|
1576 |
| |
|
1577 |
1
| public TypeData forArrayInitializer(ArrayInitializer that) {
|
|
1578 |
1
| throw new RuntimeException("Internal Program Error: forArrayInitializer should never be called, but it was." +
|
|
1579 |
| " Please report this bug."); |
|
1580 |
| } |
|
1581 |
| |
|
1582 |
| |
|
1583 |
| |
|
1584 |
| |
|
1585 |
| |
|
1586 |
| |
|
1587 |
| |
|
1588 |
7
| public TypeData forSimpleInitializedArrayInstantiation(SimpleInitializedArrayInstantiation that) {
|
|
1589 |
7
| SymbolData typeRes = getSymbolData(that.getType().getName(), _data, that.getType());
|
|
1590 |
7
| TypeData elementResult = forArrayInitializerHelper(that.getInitializer(), typeRes);
|
|
1591 |
1
| if (typeRes == null) {return null;}
|
|
1592 |
6
| return typeRes.getInstanceData();
|
|
1593 |
| } |
|
1594 |
| |
|
1595 |
| |
|
1596 |
| |
|
1597 |
| |
|
1598 |
0
| public TypeData forComplexInitializedArrayInstantiation(ComplexInitializedArrayInstantiation that) {
|
|
1599 |
0
| throw new RuntimeException("Internal Program Error: Complex Initialized Array Instantiations are not legal Java." +
|
|
1600 |
| " This should have been caught before the Type Checker. Please report this bug."); |
|
1601 |
| } |
|
1602 |
| |
|
1603 |
| |
|
1604 |
| |
|
1605 |
0
| public TypeData forInnerClassDef(InnerClassDef that) {
|
|
1606 |
0
| String className = that.getName().getText();
|
|
1607 |
0
| SymbolData sd = _data.getInnerClassOrInterface(className);
|
|
1608 |
| |
|
1609 |
0
| if (checkForCyclicInheritance(sd, new LinkedList<SymbolData>(), that)) {
|
|
1610 |
0
| return null;
|
|
1611 |
| } |
|
1612 |
0
| final TypeData mavRes = that.getMav().visit(this);
|
|
1613 |
0
| final TypeData nameRes = that.getName().visit(this);
|
|
1614 |
0
| final TypeData[] typeParamRes = makeArrayOfRetType(that.getTypeParameters().length);
|
|
1615 |
0
| for (int i = 0; i < that.getTypeParameters().length; i++) {
|
|
1616 |
0
| typeParamRes[i] = that.getTypeParameters()[i].visit(this);
|
|
1617 |
| } |
|
1618 |
0
| final TypeData superClass = that.getSuperclass().visit(this);
|
|
1619 |
0
| final TypeData[] interfacesRes = makeArrayOfRetType(that.getInterfaces().length);
|
|
1620 |
0
| for (int i = 0; i < that.getInterfaces().length; i++) {
|
|
1621 |
0
| interfacesRes[i] = that.getInterfaces()[i].visit(this);
|
|
1622 |
| } |
|
1623 |
0
| final TypeData bodyRes = that.getBody().visit(new ClassBodyTypeChecker(sd, _file, _package, _importedFiles,
|
|
1624 |
| _importedPackages, _vars, _thrown)); |
|
1625 |
| |
|
1626 |
| |
|
1627 |
0
| return null;
|
|
1628 |
| } |
|
1629 |
| |
|
1630 |
| |
|
1631 |
| |
|
1632 |
| |
|
1633 |
| |
|
1634 |
0
| void reassignVariableDatas(LinkedList<VariableData> l1, LinkedList<VariableData> l2) {
|
|
1635 |
0
| for (int i = 0; i<l1.size(); i++) {
|
|
1636 |
0
| if (l2.contains(l1.get(i))) l1.get(i).gotValue();
|
|
1637 |
| } |
|
1638 |
| } |
|
1639 |
| |
|
1640 |
| |
|
1641 |
| |
|
1642 |
| |
|
1643 |
| |
|
1644 |
| |
|
1645 |
0
| void reassignLotsaVariableDatas(LinkedList<VariableData> tryBlock, LinkedList<LinkedList<VariableData>> catchBlocks) {
|
|
1646 |
0
| for (int i = 0; i<tryBlock.size(); i++) {
|
|
1647 |
0
| boolean seenIt = true;
|
|
1648 |
0
| for (int j = 0; j<catchBlocks.size(); i++) {
|
|
1649 |
0
| if (! catchBlocks.get(j).contains(tryBlock.get(i))) {seenIt = false;}
|
|
1650 |
| } |
|
1651 |
| |
|
1652 |
0
| if (seenIt) {
|
|
1653 |
0
| tryBlock.get(i).gotValue();
|
|
1654 |
| } |
|
1655 |
| } |
|
1656 |
| } |
|
1657 |
| |
|
1658 |
| |
|
1659 |
| |
|
1660 |
| |
|
1661 |
| |
|
1662 |
| |
|
1663 |
0
| public void handleUncheckedException(SymbolData sd, JExpression j) {
|
|
1664 |
0
| if (j instanceof MethodInvocation) {
|
|
1665 |
0
| _addError("The method " + ((MethodInvocation)j).getName().getText() + " is declared to throw the exception " + sd.getName() + " which needs to be caught or declared to be thrown", j);
|
|
1666 |
| } |
|
1667 |
0
| else if (j instanceof ThrowStatement) {
|
|
1668 |
0
| _addError("This statement throws the exception " + sd.getName() + " which needs to be caught or declared to be thrown", j);
|
|
1669 |
| } |
|
1670 |
0
| else if (j instanceof ClassInstantiation) {
|
|
1671 |
0
| _addError("The constructor for the class " + ((ClassInstantiation)j).getType().getName() + " is declared to throw the exception " + sd.getName() + " which needs to be caught or declared to be thrown.", j);
|
|
1672 |
| } |
|
1673 |
| else { |
|
1674 |
0
| throw new RuntimeException("Internal Program Error: Something besides a method invocation or throw statement threw an exception. Please report this bug.");
|
|
1675 |
| } |
|
1676 |
| } |
|
1677 |
| |
|
1678 |
| |
|
1679 |
| |
|
1680 |
| |
|
1681 |
| |
|
1682 |
| |
|
1683 |
0
| public boolean isCheckedException(SymbolData sd, JExpression that) {
|
|
1684 |
0
| return sd.isSubClassOf(getSymbolData("java.lang.Throwable", _data, that, false)) &&
|
|
1685 |
| ! sd.isSubClassOf(getSymbolData("java.lang.RuntimeException", _data, that, false)) && |
|
1686 |
| ! sd.isSubClassOf(getSymbolData("java.lang.Error", _data, that, false)); |
|
1687 |
| } |
|
1688 |
| |
|
1689 |
| |
|
1690 |
| |
|
1691 |
| |
|
1692 |
| |
|
1693 |
| |
|
1694 |
| |
|
1695 |
| |
|
1696 |
0
| public boolean isUncaughtCheckedException(SymbolData sd, JExpression that) {
|
|
1697 |
0
| return isCheckedException(sd, that);
|
|
1698 |
| } |
|
1699 |
| |
|
1700 |
| |
|
1701 |
0
| public TypeData forBracedBody(BracedBody that) {
|
|
1702 |
0
| final TypeData[] items_result = makeArrayOfRetType(that.getStatements().length);
|
|
1703 |
0
| for (int i = 0; i < that.getStatements().length; i++) {
|
|
1704 |
0
| items_result[i] = that.getStatements()[i].visit(this);
|
|
1705 |
| |
|
1706 |
0
| for (int j = 0; j<this._thrown.size(); j++) {
|
|
1707 |
0
| if (isUncaughtCheckedException(this._thrown.get(j).getFirst(), that)) {
|
|
1708 |
0
| handleUncheckedException(this._thrown.get(j).getFirst(), this._thrown.get(j).getSecond());
|
|
1709 |
| } |
|
1710 |
| } |
|
1711 |
| } |
|
1712 |
| |
|
1713 |
0
| return forBracedBodyOnly(that, items_result);
|
|
1714 |
| } |
|
1715 |
| |
|
1716 |
| |
|
1717 |
2
| public TypeData forEmptyForCondition(EmptyForCondition that) {
|
|
1718 |
2
| return SymbolData.BOOLEAN_TYPE.getInstanceData();
|
|
1719 |
| } |
|
1720 |
| |
|
1721 |
| |
|
1722 |
| public static class ExpressionTypeCheckerTest extends TestCase { |
|
1723 |
| |
|
1724 |
| private ExpressionTypeChecker _etc; |
|
1725 |
| |
|
1726 |
| private SymbolData _sd1; |
|
1727 |
| private SymbolData _sd2; |
|
1728 |
| private SymbolData _sd3; |
|
1729 |
| private SymbolData _sd4; |
|
1730 |
| private SymbolData _sd5; |
|
1731 |
| private SymbolData _sd6; |
|
1732 |
| private ModifiersAndVisibility _publicMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"}); |
|
1733 |
| private ModifiersAndVisibility _protectedMav = |
|
1734 |
| new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"protected"}); |
|
1735 |
| private ModifiersAndVisibility _privateMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"private"}); |
|
1736 |
| private ModifiersAndVisibility _packageMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[0]); |
|
1737 |
| private ModifiersAndVisibility _abstractMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"abstract"}); |
|
1738 |
| private ModifiersAndVisibility _finalMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"final"}); |
|
1739 |
| private ModifiersAndVisibility _finalPublicMav = |
|
1740 |
| new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"final", "public"}); |
|
1741 |
| private ModifiersAndVisibility _publicAbstractMav = |
|
1742 |
| new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public", "abstract"}); |
|
1743 |
| private ModifiersAndVisibility _publicStaticMav = |
|
1744 |
| new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public", "static"}); |
|
1745 |
| |
|
1746 |
| |
|
1747 |
0
| public ExpressionTypeCheckerTest() { this(""); }
|
|
1748 |
54
| public ExpressionTypeCheckerTest(String name) { super(name); }
|
|
1749 |
| |
|
1750 |
54
| public void setUp() {
|
|
1751 |
54
| errors = new LinkedList<Pair<String, JExpressionIF>>();
|
|
1752 |
54
| LanguageLevelConverter.symbolTable.clear();
|
|
1753 |
54
| LanguageLevelConverter._newSDs.clear();
|
|
1754 |
54
| LanguageLevelConverter.loadSymbolTable();
|
|
1755 |
54
| _etc =
|
|
1756 |
| new ExpressionTypeChecker(null, new File(""), "", new LinkedList<String>(), new LinkedList<String>(), |
|
1757 |
| new LinkedList<VariableData>(), new LinkedList<Pair<SymbolData, JExpression>>()); |
|
1758 |
54
| LanguageLevelConverter.OPT = new Options(JavaVersion.JAVA_5, EmptyIterable.<File>make());
|
|
1759 |
54
| _etc._importedPackages.addFirst("java.lang");
|
|
1760 |
54
| _sd1 = new SymbolData("i.like.monkey");
|
|
1761 |
54
| _sd2 = new SymbolData("i.like.giraffe");
|
|
1762 |
54
| _sd3 = new SymbolData("zebra");
|
|
1763 |
54
| _sd4 = new SymbolData("u.like.emu");
|
|
1764 |
54
| _sd5 = new SymbolData("");
|
|
1765 |
54
| _sd6 = new SymbolData("cebu");
|
|
1766 |
54
| _etc._data = _sd1;
|
|
1767 |
| } |
|
1768 |
| |
|
1769 |
1
| public void testForCastExpression() {
|
|
1770 |
1
| CastExpression ce = new CastExpression(SourceInfo.NONE, new PrimitiveType(SourceInfo.NONE, "dan"), NULL_LITERAL);
|
|
1771 |
| |
|
1772 |
| |
|
1773 |
1
| assertEquals("Should return null", null, ce.visit(_etc));
|
|
1774 |
1
| assertEquals("There should be one error", 1, errors.size());
|
|
1775 |
1
| assertEquals("Error message should be correct",
|
|
1776 |
| "dan cannot appear as the type of a cast expression because it is not a valid type", |
|
1777 |
| errors.getLast().getFirst()); |
|
1778 |
| |
|
1779 |
| |
|
1780 |
1
| CastExpression ce2 =
|
|
1781 |
| new CastExpression(SourceInfo.NONE, |
|
1782 |
| new PrimitiveType(SourceInfo.NONE, "int"), |
|
1783 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "notReal"))); |
|
1784 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), ce2.visit(_etc));
|
|
1785 |
1
| assertEquals("There should be 2 errors", 2, errors.size());
|
|
1786 |
1
| assertEquals("Error message should be correct", "Could not resolve symbol notReal", errors.getLast().getFirst());
|
|
1787 |
| |
|
1788 |
| |
|
1789 |
1
| CastExpression ce3 = new CastExpression(SourceInfo.NONE,
|
|
1790 |
| new PrimitiveType(SourceInfo.NONE, "int"), |
|
1791 |
| new DoubleLiteral(SourceInfo.NONE, 5)); |
|
1792 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), ce3.visit(_etc));
|
|
1793 |
1
| assertEquals("There should still be 2 errors", 2, errors.size());
|
|
1794 |
| |
|
1795 |
| |
|
1796 |
| } |
|
1797 |
| |
|
1798 |
1
| public void testForCastExpressionOnly() {
|
|
1799 |
1
| SymbolData sd1 = SymbolData.DOUBLE_TYPE;
|
|
1800 |
1
| SymbolData sd2 = SymbolData.BOOLEAN_TYPE;
|
|
1801 |
1
| SymbolData sd3 = SymbolData.INT_TYPE;
|
|
1802 |
| |
|
1803 |
1
| CastExpression cd = new CastExpression(SourceInfo.NONE, JExprParser.NO_TYPE, NULL_LITERAL);
|
|
1804 |
1
| assertEquals("When valueRes is subtype of typeRes, return typeRes.", sd1.getInstanceData(),
|
|
1805 |
| _etc.forCastExpressionOnly(cd, sd1, sd3.getInstanceData())); |
|
1806 |
1
| assertEquals("Should not throw an error.", 0, errors.size());
|
|
1807 |
1
| assertEquals("When typeRes is subtype of valueRes, return typeRes.", sd3.getInstanceData(),
|
|
1808 |
| _etc.forCastExpressionOnly(cd, sd3, sd1.getInstanceData())); |
|
1809 |
1
| assertEquals("Should not throw an error.", 0, errors.size());
|
|
1810 |
1
| assertEquals("When typeRes and valueRes are not subtypes of each other, return typeRes",
|
|
1811 |
| sd2.getInstanceData(), _etc.forCastExpressionOnly(cd, sd2, sd1.getInstanceData())); |
|
1812 |
1
| assertEquals("Should now be one error.", 1, errors.size());
|
|
1813 |
1
| assertEquals("Error message should be correct.", "You cannot cast an expression of type " + sd1.getName()
|
|
1814 |
| + " to type " + sd2.getName() + " because they are not related", |
|
1815 |
| errors.getLast().getFirst()); |
|
1816 |
1
| SymbolData foo = new SymbolData("Foo");
|
|
1817 |
1
| SymbolData fooMama = new SymbolData("FooMama");
|
|
1818 |
1
| foo.setSuperClass(fooMama);
|
|
1819 |
1
| assertEquals("When valueRes is a SymbolData, return typeRes", fooMama.getInstanceData(),
|
|
1820 |
| _etc.forCastExpressionOnly(cd, fooMama, foo)); |
|
1821 |
1
| assertEquals("There should be 2 errors.", 2, errors.size());
|
|
1822 |
1
| assertEquals("Error message should be correct.",
|
|
1823 |
| "You are trying to cast Foo, which is a class or interface type, not an instance. " |
|
1824 |
| + "Perhaps you meant to create a new instance of Foo", |
|
1825 |
| errors.getLast().getFirst()); |
|
1826 |
| } |
|
1827 |
| |
|
1828 |
1
| public void testForEmptyExpressionOnly() {
|
|
1829 |
1
| EmptyExpression ee = new EmptyExpression(SourceInfo.NONE);
|
|
1830 |
1
| try {
|
|
1831 |
1
| _etc.forEmptyExpressionOnly(ee);
|
|
1832 |
0
| fail("Should have thrown exception");
|
|
1833 |
| } |
|
1834 |
| catch (RuntimeException e) { |
|
1835 |
1
| assertEquals("Error message should be correct",
|
|
1836 |
| "Internal Program Error: EmptyExpression encountered. Student is missing something. " |
|
1837 |
| + "Should have been caught before TypeChecker. Please report this bug.", |
|
1838 |
| e.getMessage()); |
|
1839 |
| } |
|
1840 |
| } |
|
1841 |
| |
|
1842 |
1
| public void test_getLeastRestrictiveType() {
|
|
1843 |
| |
|
1844 |
1
| assertEquals("Should return double.", SymbolData.FLOAT_TYPE,
|
|
1845 |
| _etc._getLeastRestrictiveType(SymbolData.INT_TYPE, SymbolData.FLOAT_TYPE)); |
|
1846 |
1
| assertEquals("Should return double.", SymbolData.FLOAT_TYPE,
|
|
1847 |
| _etc._getLeastRestrictiveType(SymbolData.FLOAT_TYPE, SymbolData.FLOAT_TYPE)); |
|
1848 |
1
| assertEquals("Should return int.", SymbolData.INT_TYPE,
|
|
1849 |
| _etc._getLeastRestrictiveType(SymbolData.INT_TYPE, SymbolData.CHAR_TYPE)); |
|
1850 |
1
| assertEquals("Should return char.", SymbolData.INT_TYPE,
|
|
1851 |
| _etc._getLeastRestrictiveType(SymbolData.CHAR_TYPE, SymbolData.CHAR_TYPE)); |
|
1852 |
| } |
|
1853 |
| |
|
1854 |
1
| public void test_isAssignableFrom() {
|
|
1855 |
1
| assertTrue("Should be assignable.", _etc._isAssignableFrom(SymbolData.DOUBLE_TYPE, SymbolData.DOUBLE_TYPE));
|
|
1856 |
1
| assertTrue("Should be assignable.", _etc._isAssignableFrom(SymbolData.DOUBLE_TYPE, SymbolData.INT_TYPE));
|
|
1857 |
1
| assertTrue("Should be assignable.", _etc._isAssignableFrom(SymbolData.DOUBLE_TYPE, SymbolData.CHAR_TYPE));
|
|
1858 |
1
| assertTrue("Should be assignable.", _etc._isAssignableFrom(SymbolData.INT_TYPE, SymbolData.INT_TYPE));
|
|
1859 |
1
| assertTrue("Should be assignable.", _etc._isAssignableFrom(SymbolData.INT_TYPE, SymbolData.CHAR_TYPE));
|
|
1860 |
1
| assertTrue("Should be assignable.", _etc._isAssignableFrom(SymbolData.CHAR_TYPE, SymbolData.CHAR_TYPE));
|
|
1861 |
| |
|
1862 |
1
| _sd2.setSuperClass(_sd1);
|
|
1863 |
1
| assertTrue("Should be assignable.", _etc._isAssignableFrom(_sd1, _sd1));
|
|
1864 |
1
| assertTrue("Should be assignable.", _etc._isAssignableFrom(_sd1, _sd2));
|
|
1865 |
| } |
|
1866 |
| |
|
1867 |
| |
|
1868 |
| |
|
1869 |
1
| public void testRandomExpressions() {
|
|
1870 |
| |
|
1871 |
1
| PositiveExpression pe = new PositiveExpression(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 5));
|
|
1872 |
1
| PositiveExpression pe2 = new PositiveExpression(SourceInfo.NONE, pe);
|
|
1873 |
1
| NegativeExpression pe3 = new NegativeExpression(SourceInfo.NONE, pe2);
|
|
1874 |
1
| PositiveExpression pe4 = new PositiveExpression(SourceInfo.NONE, pe3);
|
|
1875 |
1
| PositiveExpression pe5 = new PositiveExpression(SourceInfo.NONE, pe4);
|
|
1876 |
1
| NegativeExpression pe6 = new NegativeExpression(SourceInfo.NONE, pe5);
|
|
1877 |
| |
|
1878 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), pe6.visit(_etc));
|
|
1879 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
1880 |
| } |
|
1881 |
| |
|
1882 |
1
| public void testForSimpleUninitializedArrayInstantiation() {
|
|
1883 |
1
| LanguageLevelVisitor llv =
|
|
1884 |
| new LanguageLevelVisitor(_etc._file, |
|
1885 |
| _etc._package, |
|
1886 |
| null, |
|
1887 |
| _etc._importedFiles, |
|
1888 |
| _etc._importedPackages, |
|
1889 |
| new HashSet<String>(), |
|
1890 |
| new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(), |
|
1891 |
| new LinkedList<Command>()); |
|
1892 |
| |
|
1893 |
| |
|
1894 |
| |
|
1895 |
1
| SourceInfo si = SourceInfo.NONE;
|
|
1896 |
| |
|
1897 |
1
| ArrayData intArray = new ArrayData(SymbolData.INT_TYPE, llv, si);
|
|
1898 |
1
| intArray.setIsContinuation(false);
|
|
1899 |
1
| symbolTable.remove("int[]");
|
|
1900 |
1
| symbolTable.put("int[]", intArray);
|
|
1901 |
| |
|
1902 |
1
| ArrayData intArrayArray = new ArrayData(intArray, llv, si);
|
|
1903 |
1
| intArrayArray.setIsContinuation(false);
|
|
1904 |
1
| symbolTable.put("int[][]", intArrayArray);
|
|
1905 |
| |
|
1906 |
1
| ArrayData intArray3 = new ArrayData(intArrayArray, llv, si);
|
|
1907 |
1
| intArray3.setIsContinuation(false);
|
|
1908 |
1
| symbolTable.put("int[][][]", intArray3);
|
|
1909 |
| |
|
1910 |
1
| Expression i1 = new IntegerLiteral(si, 5);
|
|
1911 |
1
| Expression i2 = new PlusExpression(si, new IntegerLiteral(si, 5), new IntegerLiteral(si, 7));
|
|
1912 |
1
| Expression i3 = new CharLiteral(si, 'c');
|
|
1913 |
1
| Expression badIndexD = new DoubleLiteral(si, 4.2);
|
|
1914 |
1
| Expression badIndexL = new LongLiteral(si, 4l);
|
|
1915 |
| |
|
1916 |
| |
|
1917 |
1
| SimpleUninitializedArrayInstantiation sa1 =
|
|
1918 |
| new SimpleUninitializedArrayInstantiation(si, new ArrayType(si, "int[][][]", |
|
1919 |
| new ArrayType(si, "int[][]", |
|
1920 |
| new ArrayType(si, "int[]", new PrimitiveType(si, "int")))), |
|
1921 |
| new DimensionExpressionList(si, new Expression[] {i1, i2, i3})); |
|
1922 |
1
| assertEquals("Should return instance of int[][][]", intArray3.getInstanceData(), sa1.visit(_etc));
|
|
1923 |
1
| assertEquals("There should be no errors", 0, errors.size());
|
|
1924 |
| |
|
1925 |
| |
|
1926 |
1
| SimpleUninitializedArrayInstantiation sa2 =
|
|
1927 |
| new SimpleUninitializedArrayInstantiation(si, new ArrayType(si, "int[][][]", |
|
1928 |
| new ArrayType(si, "int[][]", new ArrayType(si, "int[]", new PrimitiveType(si, "int")))), |
|
1929 |
| new DimensionExpressionList(si, new Expression[] {i1, i2, badIndexD})); |
|
1930 |
1
| assertEquals("Should return instance of int[][][]", intArray3.getInstanceData(), sa2.visit(_etc));
|
|
1931 |
| |
|
1932 |
| |
|
1933 |
| |
|
1934 |
| |
|
1935 |
1
| assertEquals("There should be one error", 1, errors.size());
|
|
1936 |
1
| assertEquals("The error message should be correct",
|
|
1937 |
| "The dimensions of an array instantiation must all be ints. You have specified something of type double", |
|
1938 |
| errors.getLast().getFirst()); |
|
1939 |
| |
|
1940 |
| |
|
1941 |
1
| SimpleUninitializedArrayInstantiation sa3 =
|
|
1942 |
| new SimpleUninitializedArrayInstantiation(si, new ArrayType(si, "Jonathan[]", |
|
1943 |
| new ClassOrInterfaceType(si, "Jonathan", new Type[0])), |
|
1944 |
| new DimensionExpressionList(si, new Expression[]{i1})); |
|
1945 |
1
| assertEquals("Should return null", null, sa3.visit(_etc));
|
|
1946 |
1
| assertEquals("There should be 2 errors", 2, errors.size());
|
|
1947 |
1
| assertEquals("Error message should be correct",
|
|
1948 |
| "Class or variable Jonathan[] not found.", |
|
1949 |
| errors.getLast().getFirst()); |
|
1950 |
| |
|
1951 |
1
| SimpleUninitializedArrayInstantiation sa4 =
|
|
1952 |
| new SimpleUninitializedArrayInstantiation(si, new ArrayType(si, "int[][]", |
|
1953 |
| new ArrayType(si, "int[]", new PrimitiveType(si, "int"))), |
|
1954 |
| new DimensionExpressionList(si, new Expression[] {i1, i2, i3})); |
|
1955 |
1
| assertEquals("Should return instance of int[][]", intArrayArray.getInstanceData(), sa4.visit(_etc));
|
|
1956 |
1
| assertEquals("There should be 3 errors", 3, errors.size());
|
|
1957 |
1
| assertEquals("Error message should be correct",
|
|
1958 |
| "You are trying to initialize an array of type int[][] which requires 2 dimensions, but you have " |
|
1959 |
| + "specified 3 dimensions--the wrong number", |
|
1960 |
| errors.getLast().getFirst()); |
|
1961 |
| |
|
1962 |
1
| SimpleUninitializedArrayInstantiation sa5 =
|
|
1963 |
| new SimpleUninitializedArrayInstantiation(si, new ArrayType(si, "int[][][]", |
|
1964 |
| new ArrayType(si, "int[][]", new ArrayType(si, "int[]", |
|
1965 |
| new PrimitiveType(si, "int")))), |
|
1966 |
| new DimensionExpressionList(si, new Expression[] {i1, i2})); |
|
1967 |
1
| assertEquals("Should return instance of int[][][]", intArray3.getInstanceData(), sa5.visit(_etc));
|
|
1968 |
1
| assertEquals("There should still be 3 errors", 3, errors.size());
|
|
1969 |
| |
|
1970 |
| |
|
1971 |
1
| intArray3.setMav(_privateMav);
|
|
1972 |
1
| assertEquals("Should return instance of int[][][]", intArray3.getInstanceData(), sa1.visit(_etc));
|
|
1973 |
1
| assertEquals("There should be one new error", 4, errors.size());
|
|
1974 |
1
| assertEquals("Error message should be correct",
|
|
1975 |
| "The class or interface int[][][] in int[][][] is private and cannot be accessed from i.like.monkey", |
|
1976 |
| errors.getLast().getFirst()); |
|
1977 |
1
| intArray3.setMav(_publicMav);
|
|
1978 |
| } |
|
1979 |
| |
|
1980 |
1
| public void testForComplexUninitializedArrayInstantiation() {
|
|
1981 |
1
| ComplexUninitializedArrayInstantiation ca1 = new ComplexUninitializedArrayInstantiation(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "my")),
|
|
1982 |
| new ArrayType(SourceInfo.NONE, "type[][][]", new ArrayType(SourceInfo.NONE, "type[][]", new ArrayType(SourceInfo.NONE, "type[]", new ClassOrInterfaceType(SourceInfo.NONE, "type", new Type[0])))), |
|
1983 |
| new DimensionExpressionList(SourceInfo.NONE, new Expression[0])); |
|
1984 |
| |
|
1985 |
1
| try {
|
|
1986 |
1
| ca1.visit(_etc);
|
|
1987 |
0
| fail("Should have throw runtime exception");
|
|
1988 |
| } |
|
1989 |
| catch (RuntimeException e) { |
|
1990 |
1
| assertEquals("Correct exception should have been thrown","Internal Program Error: Complex Uninitialized Array Instantiations are not legal Java. This should have been caught before the Type Checker. Please report this bug." , e.getMessage());
|
|
1991 |
| } |
|
1992 |
| } |
|
1993 |
| |
|
1994 |
1
| public void testForUninitializedArrayInstantiationOnly() {
|
|
1995 |
1
| LanguageLevelVisitor llv =
|
|
1996 |
| new LanguageLevelVisitor(_etc._file, |
|
1997 |
| _etc._package, |
|
1998 |
| null, |
|
1999 |
| _etc._importedFiles, |
|
2000 |
| _etc._importedPackages, |
|
2001 |
| new HashSet<String>(), |
|
2002 |
| new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(), |
|
2003 |
| new LinkedList<Command>()); |
|
2004 |
| |
|
2005 |
| |
|
2006 |
| |
|
2007 |
| |
|
2008 |
1
| SourceInfo si = SourceInfo.NONE;
|
|
2009 |
| |
|
2010 |
1
| ArrayData intArray = new ArrayData(SymbolData.INT_TYPE, llv, si);
|
|
2011 |
1
| intArray.setIsContinuation(false);
|
|
2012 |
1
| symbolTable.remove("int[]");
|
|
2013 |
1
| symbolTable.put("int[]", intArray);
|
|
2014 |
| |
|
2015 |
1
| ArrayData intArrayArray = new ArrayData(intArray, llv, si);
|
|
2016 |
1
| intArrayArray.setIsContinuation(false);
|
|
2017 |
1
| symbolTable.put("int[][]", intArrayArray);
|
|
2018 |
| |
|
2019 |
1
| ArrayData intArray3 = new ArrayData(intArrayArray, llv, si);
|
|
2020 |
1
| intArray3.setIsContinuation(false);
|
|
2021 |
1
| symbolTable.put("int[][][]", intArray3);
|
|
2022 |
| |
|
2023 |
| |
|
2024 |
1
| SimpleUninitializedArrayInstantiation sa1 =
|
|
2025 |
| new SimpleUninitializedArrayInstantiation(si, new ArrayType(si, "int[][][]", |
|
2026 |
| new ArrayType(si, "int[][]", new ArrayType(si, "int[]", new PrimitiveType(si, "int")))), |
|
2027 |
| new DimensionExpressionList(si, new Expression[] {new NullLiteral(si), new NullLiteral(si), new NullLiteral(si)})); |
|
2028 |
| |
|
2029 |
1
| TypeData[] arrayInitTypes1 =
|
|
2030 |
| new TypeData[] { SymbolData.INT_TYPE.getInstanceData(), |
|
2031 |
| SymbolData.INT_TYPE.getInstanceData(), |
|
2032 |
| SymbolData.INT_TYPE.getInstanceData()}; |
|
2033 |
1
| assertEquals("Should return int[][][] instance", intArray3.getInstanceData(),
|
|
2034 |
| _etc.forUninitializedArrayInstantiationOnly(sa1, intArray3, arrayInitTypes1)); |
|
2035 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2036 |
| |
|
2037 |
| |
|
2038 |
1
| TypeData[] arrayInitTypes2 =
|
|
2039 |
| new TypeData[] { SymbolData.INT_TYPE.getInstanceData(), |
|
2040 |
| SymbolData.INT_TYPE.getInstanceData(), |
|
2041 |
| SymbolData.CHAR_TYPE.getInstanceData()}; |
|
2042 |
1
| assertEquals("Should return int[][][] instance", intArray3.getInstanceData(),
|
|
2043 |
| _etc.forUninitializedArrayInstantiationOnly(sa1, intArray3, arrayInitTypes2)); |
|
2044 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2045 |
| |
|
2046 |
| |
|
2047 |
1
| TypeData[] arrayInitTypes3 =
|
|
2048 |
| new TypeData[] { SymbolData.INT_TYPE.getInstanceData(), |
|
2049 |
| SymbolData.INT_TYPE, |
|
2050 |
| SymbolData.CHAR_TYPE.getInstanceData()}; |
|
2051 |
1
| assertEquals("Should return int[][][] instance", intArray3.getInstanceData(),
|
|
2052 |
| _etc.forUninitializedArrayInstantiationOnly(sa1, intArray3, arrayInitTypes3)); |
|
2053 |
1
| assertEquals("Should be one error", 1, errors.size());
|
|
2054 |
1
| assertEquals("Error message should be correct", "All dimensions of an array instantiation must be instances. You have specified the type int. Perhaps you meant to create a new instance of int", errors.getLast().getFirst());
|
|
2055 |
| |
|
2056 |
| |
|
2057 |
1
| assertEquals("Should return int[][][] instance", intArray3.getInstanceData(), _etc.forUninitializedArrayInstantiationOnly(sa1, intArray3, new TypeData[] {SymbolData.INT_TYPE.getInstanceData(), SymbolData.BOOLEAN_TYPE, SymbolData.CHAR_TYPE.getInstanceData()}));
|
|
2058 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
2059 |
1
| assertEquals("Error message should be correct", "The dimensions of an array instantiation must all be ints. You have specified something of type boolean" , errors.getLast().getFirst());
|
|
2060 |
| |
|
2061 |
| |
|
2062 |
| } |
|
2063 |
| |
|
2064 |
1
| public void testForArrayInitializer() {
|
|
2065 |
1
| ArrayInitializer ai = new ArrayInitializer(SourceInfo.NONE, new VariableInitializerI[] {new IntegerLiteral(SourceInfo.NONE, 2)});
|
|
2066 |
1
| try {
|
|
2067 |
1
| ai.visit(_etc);
|
|
2068 |
0
| fail("Should have throw runtime exception");
|
|
2069 |
| } |
|
2070 |
| catch(RuntimeException e) { |
|
2071 |
1
| assertEquals("Exception message should be correct", "Internal Program Error: forArrayInitializer should never be called, but it was. Please report this bug.", e.getMessage());
|
|
2072 |
| } |
|
2073 |
| |
|
2074 |
| } |
|
2075 |
| |
|
2076 |
1
| public void testForSimpleInitializedArrayInstantiation() {
|
|
2077 |
1
| IntegerLiteral e1 = new IntegerLiteral(SourceInfo.NONE, 5);
|
|
2078 |
1
| IntegerLiteral e2 = new IntegerLiteral(SourceInfo.NONE, 7);
|
|
2079 |
1
| SimpleNameReference e3 = new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "int"));
|
|
2080 |
1
| BooleanLiteral e4 = new BooleanLiteral(SourceInfo.NONE, true);
|
|
2081 |
1
| DoubleLiteral e5 = new DoubleLiteral(SourceInfo.NONE, 4.2);
|
|
2082 |
1
| CharLiteral e6 = new CharLiteral(SourceInfo.NONE, 'e');
|
|
2083 |
1
| SimpleNameReference e7 = new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "int"));
|
|
2084 |
| |
|
2085 |
1
| ArrayType intArrayType = new ArrayType(SourceInfo.NONE, "int[]", new PrimitiveType(SourceInfo.NONE, "int"));
|
|
2086 |
| |
|
2087 |
1
| LanguageLevelVisitor llv =
|
|
2088 |
| new LanguageLevelVisitor(_etc._file, |
|
2089 |
| _etc._package, |
|
2090 |
| null, |
|
2091 |
| _etc._importedFiles, |
|
2092 |
| _etc._importedPackages, |
|
2093 |
| new HashSet<String>(), |
|
2094 |
| new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(), |
|
2095 |
| new LinkedList<Command>()); |
|
2096 |
| |
|
2097 |
1
| ArrayData intArray = new ArrayData(SymbolData.INT_TYPE, llv, SourceInfo.NONE);
|
|
2098 |
1
| intArray.setIsContinuation(false);
|
|
2099 |
1
| symbolTable.remove("int[]");
|
|
2100 |
1
| symbolTable.put("int[]", intArray);
|
|
2101 |
| |
|
2102 |
| |
|
2103 |
1
| InitializedArrayInstantiation good = new SimpleInitializedArrayInstantiation(SourceInfo.NONE, intArrayType, new ArrayInitializer(SourceInfo.NONE, new VariableInitializerI[] {e1, e2}));
|
|
2104 |
1
| assertEquals("Should return int array instance", intArray.getInstanceData(), good.visit(_etc));
|
|
2105 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2106 |
| |
|
2107 |
| |
|
2108 |
1
| good = new SimpleInitializedArrayInstantiation(SourceInfo.NONE, intArrayType, new ArrayInitializer(SourceInfo.NONE, new VariableInitializerI[] {e1, e2, e6}));
|
|
2109 |
1
| assertEquals("Should return int array instance", intArray.getInstanceData(), good.visit(_etc));
|
|
2110 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2111 |
| |
|
2112 |
| |
|
2113 |
1
| InitializedArrayInstantiation bad = new SimpleInitializedArrayInstantiation(SourceInfo.NONE, new PrimitiveType(SourceInfo.NONE, "int"), new ArrayInitializer(SourceInfo.NONE, new VariableInitializerI[] {e1, e2}));
|
|
2114 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), bad.visit(_etc));
|
|
2115 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
2116 |
1
| assertEquals("Error message should be correct", "You cannot initialize the non-array type int with an array initializer", errors.getLast().getFirst());
|
|
2117 |
| |
|
2118 |
| |
|
2119 |
| |
|
2120 |
1
| bad = new SimpleInitializedArrayInstantiation(SourceInfo.NONE, intArrayType, new ArrayInitializer(SourceInfo.NONE, new VariableInitializerI[] {e1, e4, e2, e6}));
|
|
2121 |
1
| assertEquals("Should return int array instance", intArray.getInstanceData(), bad.visit(_etc));
|
|
2122 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
2123 |
1
| assertEquals("Error message should be correct", "The elements of this initializer should have type int but element 1 has type boolean", errors.getLast().getFirst());
|
|
2124 |
| |
|
2125 |
| |
|
2126 |
1
| bad = new SimpleInitializedArrayInstantiation(SourceInfo.NONE, intArrayType, new ArrayInitializer(SourceInfo.NONE, new VariableInitializerI[] {e1, e5, e2, e6}));
|
|
2127 |
1
| assertEquals("Should return int array instance", intArray.getInstanceData(), bad.visit(_etc));
|
|
2128 |
1
| assertEquals("Should be 3 errors", 3, errors.size());
|
|
2129 |
1
| assertEquals("Error message should be correct", "The elements of this initializer should have type int but element 1 has type double", errors.getLast().getFirst());
|
|
2130 |
| |
|
2131 |
| |
|
2132 |
1
| bad = new SimpleInitializedArrayInstantiation(SourceInfo.NONE, new PrimitiveType(SourceInfo.NONE, "ej"), new ArrayInitializer(SourceInfo.NONE, new VariableInitializerI[] {e1, e2}));
|
|
2133 |
1
| assertEquals("Should return null", null, bad.visit(_etc));
|
|
2134 |
1
| assertEquals("Should be 4 error", 4, errors.size());
|
|
2135 |
1
| assertEquals("Error message should be correct", "Class or variable ej not found.", errors.getLast().getFirst());
|
|
2136 |
| |
|
2137 |
| |
|
2138 |
1
| bad = new SimpleInitializedArrayInstantiation(SourceInfo.NONE, intArrayType, new ArrayInitializer(SourceInfo.NONE, new VariableInitializerI[] {e1, e7}));
|
|
2139 |
1
| assertEquals("Should return instance of int[]", intArray.getInstanceData(), bad.visit(_etc));
|
|
2140 |
1
| assertEquals("Should now be 5 error messages", 5, errors.size());
|
|
2141 |
1
| assertEquals("Error message should be correct", "The elements of this initializer should all be instances, but you have specified the type name int. Perhaps you meant to create a new instance of int", errors.getLast().getFirst());
|
|
2142 |
| |
|
2143 |
| |
|
2144 |
| } |
|
2145 |
| |
|
2146 |
| |
|
2147 |
| |
|
2148 |
| |
|
2149 |
1
| public void testForSimpleAssignmentExpressionOnly() {
|
|
2150 |
1
| SimpleAssignmentExpression sae = new SimpleAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")), new IntegerLiteral(SourceInfo.NONE, 5));
|
|
2151 |
| |
|
2152 |
| |
|
2153 |
1
| assertEquals("Should return double instance", SymbolData.DOUBLE_TYPE.getInstanceData(), _etc.forSimpleAssignmentExpressionOnly(sae, SymbolData.DOUBLE_TYPE.getInstanceData(), SymbolData.INT_TYPE.getInstanceData()));
|
|
2154 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2155 |
| |
|
2156 |
| |
|
2157 |
1
| assertEquals("Should return null", null, _etc.forSimpleAssignmentExpressionOnly(sae, null, SymbolData.INT_TYPE));
|
|
2158 |
1
| assertEquals("Should return null", null, _etc.forSimpleAssignmentExpressionOnly(sae, SymbolData.INT_TYPE, null));
|
|
2159 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2160 |
| |
|
2161 |
| |
|
2162 |
1
| PackageData pd = new PackageData("bad_reference");
|
|
2163 |
1
| assertEquals("Should return null", null, _etc.forSimpleAssignmentExpressionOnly(sae, pd, SymbolData.INT_TYPE));
|
|
2164 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
2165 |
1
| assertEquals("Error message should be correct", "Could not resolve symbol bad_reference", errors.get(0).getFirst());
|
|
2166 |
| |
|
2167 |
| |
|
2168 |
| |
|
2169 |
1
| assertEquals("Should return null", null, _etc.forSimpleAssignmentExpressionOnly(sae, SymbolData.INT_TYPE, pd));
|
|
2170 |
1
| assertEquals("Should only be 1 error", 1, errors.size());
|
|
2171 |
1
| assertEquals("Error message should be correct", "Could not resolve symbol bad_reference", errors.get(0).getFirst());
|
|
2172 |
| |
|
2173 |
| |
|
2174 |
1
| assertEquals("Should return double instance",
|
|
2175 |
| SymbolData.DOUBLE_TYPE.getInstanceData(), |
|
2176 |
| _etc.forSimpleAssignmentExpressionOnly(sae, |
|
2177 |
| SymbolData.DOUBLE_TYPE, |
|
2178 |
| SymbolData.INT_TYPE.getInstanceData())); |
|
2179 |
1
| assertEquals("Should now be 2 errors", 2, errors.size());
|
|
2180 |
1
| assertEquals("Error message should be correct",
|
|
2181 |
| "You cannot assign a value to the type double. Perhaps you meant to create a new instance of double", |
|
2182 |
| errors.get(1).getFirst()); |
|
2183 |
| |
|
2184 |
1
| assertEquals("Should return double instance",
|
|
2185 |
| SymbolData.DOUBLE_TYPE.getInstanceData(), |
|
2186 |
| _etc.forSimpleAssignmentExpressionOnly(sae, |
|
2187 |
| SymbolData.DOUBLE_TYPE.getInstanceData(), |
|
2188 |
| SymbolData.INT_TYPE)); |
|
2189 |
1
| assertEquals("Should now be 3 errors", 3, errors.size());
|
|
2190 |
1
| assertEquals("Error message should be correct",
|
|
2191 |
| "You cannot use the type name int on the right hand side of an assignment. " + |
|
2192 |
| "Perhaps you meant to create a new instance of int", |
|
2193 |
| errors.get(2).getFirst()); |
|
2194 |
| |
|
2195 |
| |
|
2196 |
1
| assertEquals("Should return int instance",
|
|
2197 |
| SymbolData.INT_TYPE.getInstanceData(), |
|
2198 |
| _etc.forSimpleAssignmentExpressionOnly(sae, |
|
2199 |
| SymbolData.INT_TYPE.getInstanceData(), |
|
2200 |
| SymbolData.DOUBLE_TYPE.getInstanceData())); |
|
2201 |
1
| assertEquals("Should now be 4 errors", 4, errors.size());
|
|
2202 |
1
| assertEquals("Error message should be correct",
|
|
2203 |
| "You cannot assign something of type double to something of type int", |
|
2204 |
| errors.get(3).getFirst()); |
|
2205 |
| |
|
2206 |
| } |
|
2207 |
| |
|
2208 |
| |
|
2209 |
1
| public void testForPlusAssignmentExpressionOnly() {
|
|
2210 |
1
| PlusAssignmentExpression pae =
|
|
2211 |
| new PlusAssignmentExpression(SourceInfo.NONE, |
|
2212 |
| new IntegerLiteral(SourceInfo.NONE, 5), new IntegerLiteral(SourceInfo.NONE, 6)); |
|
2213 |
| |
|
2214 |
| |
|
2215 |
1
| SymbolData string = new SymbolData("java.lang.String");
|
|
2216 |
1
| string.setIsContinuation(false);
|
|
2217 |
1
| string.setPackage("java.lang");
|
|
2218 |
1
| string.setMav(_publicMav);
|
|
2219 |
1
| symbolTable.put("java.lang.String", string);
|
|
2220 |
| |
|
2221 |
1
| assertEquals("Should return string instance",
|
|
2222 |
| string.getInstanceData(), |
|
2223 |
| _etc.forPlusAssignmentExpressionOnly(pae, string.getInstanceData(), |
|
2224 |
| SymbolData.INT_TYPE.getInstanceData())); |
|
2225 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2226 |
| |
|
2227 |
| |
|
2228 |
1
| assertEquals("Should return double instance",
|
|
2229 |
| SymbolData.DOUBLE_TYPE.getInstanceData(), |
|
2230 |
| _etc.forPlusAssignmentExpressionOnly(pae, |
|
2231 |
| SymbolData.DOUBLE_TYPE.getInstanceData(), |
|
2232 |
| SymbolData.INT_TYPE.getInstanceData())); |
|
2233 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2234 |
| |
|
2235 |
| |
|
2236 |
1
| assertEquals("Should return null", null, _etc.forPlusAssignmentExpressionOnly(pae, null, SymbolData.INT_TYPE));
|
|
2237 |
1
| assertEquals("Should return null", null, _etc.forPlusAssignmentExpressionOnly(pae, SymbolData.INT_TYPE, null));
|
|
2238 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2239 |
| |
|
2240 |
| |
|
2241 |
1
| PackageData pd = new PackageData("bad_reference");
|
|
2242 |
1
| assertEquals("Should return null", null, _etc.forPlusAssignmentExpressionOnly(pae, pd, SymbolData.INT_TYPE));
|
|
2243 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
2244 |
1
| assertEquals("Error message should be correct", "Could not resolve symbol bad_reference", errors.getLast().getFirst());
|
|
2245 |
| |
|
2246 |
| |
|
2247 |
| |
|
2248 |
1
| assertEquals("Should return null", null, _etc.forPlusAssignmentExpressionOnly(pae, SymbolData.INT_TYPE, pd));
|
|
2249 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
2250 |
1
| assertEquals("Error message should be correct", "Could not resolve symbol bad_reference", errors.get(0).getFirst());
|
|
2251 |
| |
|
2252 |
| |
|
2253 |
1
| assertEquals("Should return string instance",
|
|
2254 |
| string.getInstanceData(), |
|
2255 |
| _etc.forPlusAssignmentExpressionOnly(pae, string, |
|
2256 |
| SymbolData.INT_TYPE.getInstanceData())); |
|
2257 |
1
| assertEquals("Should now be 2 errors", 2, errors.size());
|
|
2258 |
1
| assertEquals("Error message should be correct",
|
|
2259 |
| "The arguments to a Plus Assignment Operator (+=) must both be instances, but you have specified " + |
|
2260 |
| "a type name. Perhaps you meant to create a new instance of java.lang.String", |
|
2261 |
| errors.get(1).getFirst()); |
|
2262 |
| |
|
2263 |
| |
|
2264 |
1
| assertEquals("Should return string instance", string.getInstanceData(),
|
|
2265 |
| _etc.forPlusAssignmentExpressionOnly(pae, string.getInstanceData(), |
|
2266 |
| SymbolData.INT_TYPE)); |
|
2267 |
1
| assertEquals("Should now be 3 errors", 3, errors.size());
|
|
2268 |
1
| assertEquals("Error message should be correct",
|
|
2269 |
| "The arguments to a Plus Assignment Operator (+=) must both be instances, " + |
|
2270 |
| "but you have specified a type name. Perhaps you meant to create a new instance of int" , |
|
2271 |
| errors.get(2).getFirst()); |
|
2272 |
| |
|
2273 |
| |
|
2274 |
1
| assertEquals("Should return string, by default", string.getInstanceData(),
|
|
2275 |
| _etc.forPlusAssignmentExpressionOnly(pae, _sd2.getInstanceData(), |
|
2276 |
| SymbolData.INT_TYPE.getInstanceData())); |
|
2277 |
1
| assertEquals("Should now be 4 errors", 4, errors.size());
|
|
2278 |
1
| assertEquals("Error message should be correct",
|
|
2279 |
| "The arguments to the Plus Assignment Operator (+=) must either include an instance of a String " + |
|
2280 |
| "or both be numbers. You have specified arguments of type " + _sd2.getName() + " and int", |
|
2281 |
| errors.get(3).getFirst()); |
|
2282 |
| |
|
2283 |
| |
|
2284 |
1
| assertEquals("should return string, by default", string.getInstanceData(),
|
|
2285 |
| _etc.forPlusAssignmentExpressionOnly(pae, SymbolData.INT_TYPE.getInstanceData(), |
|
2286 |
| _sd2.getInstanceData())); |
|
2287 |
1
| assertEquals("Should now be 5 errors", 5, errors.size());
|
|
2288 |
1
| assertEquals("Error message should be correct",
|
|
2289 |
| "The arguments to the Plus Assignment Operator (+=) must either include an instance of a String " + |
|
2290 |
| "or both be numbers. You have specified arguments of type int and " + _sd2.getName(), |
|
2291 |
| errors.get(4).getFirst()); |
|
2292 |
| |
|
2293 |
1
| assertEquals("Should return int instance",
|
|
2294 |
| SymbolData.INT_TYPE.getInstanceData(), |
|
2295 |
| _etc.forPlusAssignmentExpressionOnly(pae, SymbolData.INT_TYPE.getInstanceData(), |
|
2296 |
| SymbolData.DOUBLE_TYPE.getInstanceData())); |
|
2297 |
1
| assertEquals("Should now be 6 errors", 6, errors.size());
|
|
2298 |
1
| assertEquals("Error message should be correct",
|
|
2299 |
| "You cannot increment something of type int with something of type double", |
|
2300 |
| errors.get(5).getFirst()); |
|
2301 |
| |
|
2302 |
| |
|
2303 |
1
| assertEquals("Should return double instance",
|
|
2304 |
| SymbolData.DOUBLE_TYPE.getInstanceData(), |
|
2305 |
| _etc.forPlusAssignmentExpressionOnly(pae, SymbolData.DOUBLE_TYPE, SymbolData.INT_TYPE)); |
|
2306 |
1
| assertEquals("Should now be 8 errors", 8, errors.size());
|
|
2307 |
1
| assertEquals("Second error message should be new",
|
|
2308 |
| "The arguments to the Plus Assignment Operator (+=) must both be instances, but you have specified " + |
|
2309 |
| "a type name. Perhaps you meant to create a new instance of double", |
|
2310 |
| errors.get(6).getFirst()); |
|
2311 |
1
| assertEquals("First error message should be new",
|
|
2312 |
| "The arguments to the Plus Assignment Operator (+=) must both be instances, but you have specified " + |
|
2313 |
| "a type name. Perhaps you meant to create a new instance of int", |
|
2314 |
| errors.get(7).getFirst()); |
|
2315 |
| } |
|
2316 |
| |
|
2317 |
1
| public void testForNumericAssignmentExpressionOnly() {
|
|
2318 |
1
| NumericAssignmentExpression nae =
|
|
2319 |
| new MinusAssignmentExpression(SourceInfo.NONE, |
|
2320 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")), |
|
2321 |
| new IntegerLiteral(SourceInfo.NONE, 5)); |
|
2322 |
| |
|
2323 |
| |
|
2324 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), _etc.forNumericAssignmentExpressionOnly(nae, SymbolData.INT_TYPE.getInstanceData(), SymbolData.CHAR_TYPE.getInstanceData()));
|
|
2325 |
1
| assertEquals("Should return double instance", SymbolData.DOUBLE_TYPE.getInstanceData(), _etc.forNumericAssignmentExpressionOnly(nae, SymbolData.DOUBLE_TYPE.getInstanceData(), SymbolData.INT_TYPE.getInstanceData()));
|
|
2326 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2327 |
| |
|
2328 |
| |
|
2329 |
| |
|
2330 |
1
| assertEquals("Should return null", null, _etc.forNumericAssignmentExpressionOnly(nae, null, SymbolData.INT_TYPE));
|
|
2331 |
1
| assertEquals("Should return null", null, _etc.forNumericAssignmentExpressionOnly(nae, SymbolData.INT_TYPE, null));
|
|
2332 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2333 |
| |
|
2334 |
| |
|
2335 |
1
| PackageData pd = new PackageData("bad_reference");
|
|
2336 |
1
| assertEquals("Should return null", null, _etc.forNumericAssignmentExpressionOnly(nae, pd, SymbolData.INT_TYPE));
|
|
2337 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
2338 |
1
| assertEquals("Error message should be correct", "Could not resolve symbol bad_reference", errors.get(0).getFirst());
|
|
2339 |
| |
|
2340 |
| |
|
2341 |
1
| assertEquals("Should return null", null, _etc.forNumericAssignmentExpressionOnly(nae, SymbolData.INT_TYPE, pd));
|
|
2342 |
1
| assertEquals("Should still be 1 error", 1, errors.size());
|
|
2343 |
1
| assertEquals("Error message should be correct", "Could not resolve symbol bad_reference", errors.get(0).getFirst());
|
|
2344 |
| |
|
2345 |
| |
|
2346 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), _etc.forNumericAssignmentExpressionOnly(nae, SymbolData.INT_TYPE, SymbolData.CHAR_TYPE.getInstanceData()));
|
|
2347 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
2348 |
1
| assertEquals("Error message should be correct",
|
|
2349 |
| "You cannot use a numeric assignment (-=, %=, *=, /=) on the type int. Perhaps you meant to create " + |
|
2350 |
| "a new instance of int", |
|
2351 |
| errors.get(1).getFirst()); |
|
2352 |
| |
|
2353 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), _etc.forNumericAssignmentExpressionOnly(nae, SymbolData.INT_TYPE.getInstanceData(), SymbolData.CHAR_TYPE));
|
|
2354 |
1
| assertEquals("Should now be 3 errors", 3, errors.size());
|
|
2355 |
1
| assertEquals("Error message should be correct",
|
|
2356 |
| "You cannot use the type name char on the left hand side of a numeric assignment (-=, %=, *=, /=)." + |
|
2357 |
| " Perhaps you meant to create a new instance of char", |
|
2358 |
| errors.get(2).getFirst()); |
|
2359 |
| |
|
2360 |
| |
|
2361 |
1
| assertEquals("Should return sd2 instance", _sd2.getInstanceData(),
|
|
2362 |
| _etc.forNumericAssignmentExpressionOnly(nae, _sd2.getInstanceData(), |
|
2363 |
| SymbolData.CHAR_TYPE.getInstanceData())); |
|
2364 |
1
| assertEquals("Should now be 4 errors", 4, errors.size());
|
|
2365 |
1
| assertEquals("Error message should be correct",
|
|
2366 |
| "The left side of this expression is not a number. Therefore, you cannot apply " + |
|
2367 |
| "a numeric assignment (-=, %=, *=, /=) to it", |
|
2368 |
| errors.get(3).getFirst()); |
|
2369 |
| |
|
2370 |
| |
|
2371 |
1
| assertEquals("Should return int instance",
|
|
2372 |
| SymbolData.INT_TYPE.getInstanceData(), |
|
2373 |
| _etc.forNumericAssignmentExpressionOnly(nae, |
|
2374 |
| SymbolData.INT_TYPE.getInstanceData(), |
|
2375 |
| _sd2.getInstanceData())); |
|
2376 |
1
| assertEquals("Should still be 5 errors", 5, errors.size());
|
|
2377 |
1
| assertEquals("Error message should be correct",
|
|
2378 |
| "The right side of this expression is not a number. Therefore, you cannot apply " + |
|
2379 |
| "a numeric assignment (-=, %=, *=, /=) to it", |
|
2380 |
| errors.get(4).getFirst()); |
|
2381 |
| |
|
2382 |
| |
|
2383 |
1
| assertEquals("Should return int instance",
|
|
2384 |
| SymbolData.INT_TYPE.getInstanceData(), |
|
2385 |
| _etc.forNumericAssignmentExpressionOnly(nae, |
|
2386 |
| SymbolData.INT_TYPE.getInstanceData(), |
|
2387 |
| SymbolData.DOUBLE_TYPE.getInstanceData())); |
|
2388 |
1
| assertEquals("Should be 6 errors", 6, errors.size());
|
|
2389 |
1
| assertEquals("Error message should be correct",
|
|
2390 |
| "You cannot use a numeric assignment (-=, %=, *=, /=) on something of type int with something of " + |
|
2391 |
| "type double", |
|
2392 |
| errors.get(5).getFirst()); |
|
2393 |
| } |
|
2394 |
| |
|
2395 |
| |
|
2396 |
1
| public void testForShiftAssignmentExpressionOnly() {
|
|
2397 |
1
| ShiftAssignmentExpression sae = new LeftShiftAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")), new IntegerLiteral(SourceInfo.NONE, 2));
|
|
2398 |
1
| try {
|
|
2399 |
1
| _etc.forShiftAssignmentExpressionOnly(sae, _sd1, _sd2);
|
|
2400 |
0
| fail("forShiftAssignmentExpressionOnly should have thrown a runtime exception");
|
|
2401 |
| } |
|
2402 |
| catch (RuntimeException e) { |
|
2403 |
1
| assertEquals("Exception message should be correct", "Internal Program Error: Shift assignment operators are not supported. This should have been caught before the TypeChecker. Please report this bug.", e.getMessage());
|
|
2404 |
| } |
|
2405 |
| } |
|
2406 |
| |
|
2407 |
1
| public void testForBitwiseAssignmentExpressionOnly() {
|
|
2408 |
1
| BitwiseAssignmentExpression bae = new BitwiseXorAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")), new IntegerLiteral(SourceInfo.NONE, 2));
|
|
2409 |
1
| try {
|
|
2410 |
1
| _etc.forBitwiseAssignmentExpressionOnly(bae, _sd1, _sd2);
|
|
2411 |
0
| fail("forBitwiseAssignmentExpressionOnly should have thrown a runtime exception");
|
|
2412 |
| } |
|
2413 |
| catch (RuntimeException e) { |
|
2414 |
1
| assertEquals("Exception message should be correct", "Internal Program Error: Bitwise assignment operators are not supported. This should have been caught before the TypeChecker. Please report this bug.", e.getMessage());
|
|
2415 |
| } |
|
2416 |
| } |
|
2417 |
| |
|
2418 |
| |
|
2419 |
1
| public void testForBooleanExpressionOnly() {
|
|
2420 |
1
| BooleanExpression be = new OrExpression(SourceInfo.NONE, new BooleanLiteral(SourceInfo.NONE, true), new BooleanLiteral(SourceInfo.NONE, false));
|
|
2421 |
| |
|
2422 |
| |
|
2423 |
| |
|
2424 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(), _etc.forBooleanExpressionOnly(be, SymbolData.BOOLEAN_TYPE.getInstanceData(), SymbolData.BOOLEAN_TYPE.getInstanceData()));
|
|
2425 |
1
| assertEquals("There should be no errors", 0, errors.size());
|
|
2426 |
| |
|
2427 |
| |
|
2428 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(), _etc.forBooleanExpressionOnly(be, SymbolData.BOOLEAN_TYPE, SymbolData.BOOLEAN_TYPE.getInstanceData()));
|
|
2429 |
1
| assertEquals("There should now be 1 error", 1, errors.size());
|
|
2430 |
1
| assertEquals("The error message should be correct", "The left side of this expression is a type, not an instance. Perhaps you meant to create a new instance of boolean", errors.getLast().getFirst());
|
|
2431 |
| |
|
2432 |
| |
|
2433 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(), _etc.forBooleanExpressionOnly(be, SymbolData.INT_TYPE.getInstanceData(), SymbolData.BOOLEAN_TYPE.getInstanceData()));
|
|
2434 |
1
| assertEquals("There should now be 2 errors", 2, errors.size());
|
|
2435 |
1
| assertEquals("The error message should be correct", "The left side of this expression is not a boolean value. Therefore, you cannot apply a Boolean Operator (&&, ||) to it", errors.getLast().getFirst());
|
|
2436 |
| |
|
2437 |
| |
|
2438 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(), _etc.forBooleanExpressionOnly(be, SymbolData.BOOLEAN_TYPE.getInstanceData(), SymbolData.BOOLEAN_TYPE));
|
|
2439 |
1
| assertEquals("There should now be 3 errors", 3, errors.size());
|
|
2440 |
1
| assertEquals("The error message should be correct", "The right side of this expression is a type, not an instance. Perhaps you meant to create a new instance of boolean", errors.getLast().getFirst());
|
|
2441 |
| |
|
2442 |
| |
|
2443 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(), _etc.forBooleanExpressionOnly(be, SymbolData.BOOLEAN_TYPE.getInstanceData(), SymbolData.DOUBLE_TYPE.getInstanceData()));
|
|
2444 |
1
| assertEquals("There should now be 4 errors", 4, errors.size());
|
|
2445 |
1
| assertEquals("The error message should be correct",
|
|
2446 |
| "The right side of this expression is not a boolean value. Therefore, you cannot apply a Boolean Operator (&&, ||) to it", errors.getLast().getFirst()); |
|
2447 |
| |
|
2448 |
| } |
|
2449 |
| |
|
2450 |
1
| public void testForBitwiseBinaryExpressionOnly() {
|
|
2451 |
1
| BitwiseBinaryExpression bbe =
|
|
2452 |
| new BitwiseAndExpression(SourceInfo.NONE, |
|
2453 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")), |
|
2454 |
| new IntegerLiteral(SourceInfo.NONE, 2)); |
|
2455 |
1
| try {
|
|
2456 |
1
| _etc.forBitwiseBinaryExpressionOnly(bbe, _sd2, _sd3);
|
|
2457 |
0
| fail("forBitwiseBinaryExpressionOnly should have thrown a runtime exception");
|
|
2458 |
| } |
|
2459 |
| catch (RuntimeException e) { |
|
2460 |
1
| assertEquals("Exception message should be correct",
|
|
2461 |
| "Internal Program Error: Bitwise operators are not supported. This should have been caught " |
|
2462 |
| + "before the TypeChecker. Please report this bug.", e.getMessage()); |
|
2463 |
| } |
|
2464 |
| } |
|
2465 |
| |
|
2466 |
| |
|
2467 |
1
| public void testForEqualityExpressionOnly() {
|
|
2468 |
1
| EqualityExpression ee = new EqualsExpression(SourceInfo.NONE, NULL_LITERAL, NULL_LITERAL);
|
|
2469 |
| |
|
2470 |
| |
|
2471 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2472 |
| _etc.forEqualityExpressionOnly(ee, SymbolData.BOOLEAN_TYPE.getInstanceData(), |
|
2473 |
| SymbolData.BOOLEAN_TYPE.getInstanceData())); |
|
2474 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2475 |
| |
|
2476 |
| |
|
2477 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2478 |
| _etc.forEqualityExpressionOnly(ee, SymbolData.INT_TYPE.getInstanceData(), |
|
2479 |
| SymbolData.INT_TYPE.getInstanceData())); |
|
2480 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2481 |
| |
|
2482 |
| |
|
2483 |
| |
|
2484 |
1
| SymbolData integer = new SymbolData("java.lang.Integer");
|
|
2485 |
1
| integer.setIsContinuation(false);
|
|
2486 |
1
| symbolTable.put("java.lang.Integer", integer);
|
|
2487 |
| |
|
2488 |
1
| SymbolData bool = new SymbolData("java.lang.Boolean");
|
|
2489 |
1
| bool.setIsContinuation(false);
|
|
2490 |
1
| symbolTable.put("java.lang.Boolean", bool);
|
|
2491 |
| |
|
2492 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2493 |
| _etc.forEqualityExpressionOnly(ee, SymbolData.INT_TYPE.getInstanceData(), integer.getInstanceData())); |
|
2494 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2495 |
| |
|
2496 |
| |
|
2497 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2498 |
| _etc.forEqualityExpressionOnly(ee, integer.getInstanceData(), SymbolData.INT_TYPE.getInstanceData())); |
|
2499 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2500 |
| |
|
2501 |
| |
|
2502 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2503 |
| _etc.forEqualityExpressionOnly(ee, SymbolData.BOOLEAN_TYPE.getInstanceData(), bool.getInstanceData())); |
|
2504 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2505 |
| |
|
2506 |
| |
|
2507 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2508 |
| _etc.forEqualityExpressionOnly(ee, bool.getInstanceData(), SymbolData.BOOLEAN_TYPE.getInstanceData())); |
|
2509 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2510 |
| |
|
2511 |
| |
|
2512 |
| |
|
2513 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2514 |
| _etc.forEqualityExpressionOnly(ee, _sd1.getInstanceData(), _sd2.getInstanceData())); |
|
2515 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2516 |
| |
|
2517 |
| |
|
2518 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2519 |
| _etc.forEqualityExpressionOnly(ee, SymbolData.INT_TYPE.getInstanceData(), |
|
2520 |
| SymbolData.BOOLEAN_TYPE.getInstanceData())); |
|
2521 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
2522 |
1
| assertEquals("Error message should be correct",
|
|
2523 |
| "At least one of the arguments to this Equality Operator (==, !=) is primitive. Therefore, " |
|
2524 |
| + "they must either both be number types or both be boolean types. You have specified " |
|
2525 |
| + "expressions with type int and boolean", |
|
2526 |
| errors.getLast().getFirst()); |
|
2527 |
| |
|
2528 |
| |
|
2529 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(), _etc.forEqualityExpressionOnly(ee, SymbolData.INT_TYPE.getInstanceData(), _sd1.getInstanceData()));
|
|
2530 |
1
| assertEquals("There should now be 2 errors", 2, errors.size());
|
|
2531 |
1
| assertEquals("Error message should be correct",
|
|
2532 |
| "At least one of the arguments to this Equality Operator (==, !=) is primitive. Therefore, " |
|
2533 |
| + "they must either both be number types or both be boolean types. You have specified " |
|
2534 |
| + "expressions with type int and i.like.monkey", errors.getLast().getFirst()); |
|
2535 |
| |
|
2536 |
| |
|
2537 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2538 |
| _etc.forEqualityExpressionOnly(ee, _sd1.getInstanceData(), SymbolData.INT_TYPE.getInstanceData())); |
|
2539 |
1
| assertEquals("There should now be 3 errors", 3, errors.size());
|
|
2540 |
1
| assertEquals("Error message should be correct",
|
|
2541 |
| "At least one of the arguments to this Equality Operator (==, !=) is primitive. Therefore, they " |
|
2542 |
| + "must either both be number types or both be boolean types. You have specified expressions " |
|
2543 |
| + "with type i.like.monkey and int", |
|
2544 |
| errors.getLast().getFirst()); |
|
2545 |
| |
|
2546 |
| |
|
2547 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2548 |
| _etc.forEqualityExpressionOnly(ee, _sd1, _sd2.getInstanceData())); |
|
2549 |
1
| assertEquals("There should now be 4 errors", 4, errors.size());
|
|
2550 |
1
| assertEquals("Error message should be correct",
|
|
2551 |
| "The arguments to this Equality Operator(==, !=) must both be instances. Instead, you have " |
|
2552 |
| +"referenced a type name on the left side. Perhaps you meant to create a new instance of " + |
|
2553 |
| _sd1.getName(), |
|
2554 |
| errors.getLast().getFirst()); |
|
2555 |
| |
|
2556 |
| |
|
2557 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2558 |
| _etc.forEqualityExpressionOnly(ee, _sd1.getInstanceData(), _sd2)); |
|
2559 |
1
| assertEquals("There should now be 5 errors", 5, errors.size());
|
|
2560 |
1
| assertEquals("Error message should be correct", "The arguments to this Equality Operator(==, !=) must both "
|
|
2561 |
| + "be instances. Instead, you have referenced a type name on the right side. Perhaps you " |
|
2562 |
| + "meant to create a new instance of " + _sd2.getName(), |
|
2563 |
| errors.getLast().getFirst()); |
|
2564 |
| } |
|
2565 |
| |
|
2566 |
1
| public void testForComparisonExpressionOnly() {
|
|
2567 |
1
| ComparisonExpression ce = new LessThanExpression(SourceInfo.NONE, NULL_LITERAL, NULL_LITERAL);
|
|
2568 |
| |
|
2569 |
| |
|
2570 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2571 |
| _etc.forComparisonExpressionOnly(ce, SymbolData.DOUBLE_TYPE.getInstanceData(), |
|
2572 |
| SymbolData.INT_TYPE.getInstanceData())); |
|
2573 |
1
| assertEquals("There should be no errors", 0, errors.size());
|
|
2574 |
| |
|
2575 |
| |
|
2576 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2577 |
| _etc.forComparisonExpressionOnly(ce, SymbolData.BOOLEAN_TYPE.getInstanceData(), |
|
2578 |
| SymbolData.INT_TYPE.getInstanceData())); |
|
2579 |
1
| assertEquals("There should be one error", 1, errors.size());
|
|
2580 |
1
| assertEquals("Error message should be correct",
|
|
2581 |
| "The left side of this expression is not a number. Therefore, you cannot apply a Comparison " |
|
2582 |
| + "Operator (<, >; <=, >=) to it", |
|
2583 |
| errors.getLast().getFirst()); |
|
2584 |
| |
|
2585 |
| |
|
2586 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2587 |
| _etc.forComparisonExpressionOnly(ce, SymbolData.DOUBLE_TYPE, SymbolData.INT_TYPE.getInstanceData())); |
|
2588 |
1
| assertEquals("There should be two errors", 2, errors.size());
|
|
2589 |
1
| assertEquals("Error message should be correct",
|
|
2590 |
| "The left side of this expression is a type, not an instance. Perhaps you meant to create a " |
|
2591 |
| + "new instance of double", |
|
2592 |
| errors.getLast().getFirst()); |
|
2593 |
| |
|
2594 |
| |
|
2595 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2596 |
| _etc.forComparisonExpressionOnly(ce, SymbolData.DOUBLE_TYPE.getInstanceData(), |
|
2597 |
| _sd1.getInstanceData())); |
|
2598 |
1
| assertEquals("There should be three errors", 3, errors.size());
|
|
2599 |
1
| assertEquals("Error message should be correct",
|
|
2600 |
| "The right side of this expression is not a number. Therefore, you cannot apply a Comparison " |
|
2601 |
| + "Operator (<, >; <=, >=) to it", |
|
2602 |
| errors.getLast().getFirst()); |
|
2603 |
| |
|
2604 |
| |
|
2605 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2606 |
| _etc.forComparisonExpressionOnly(ce, SymbolData.DOUBLE_TYPE.getInstanceData(), SymbolData.INT_TYPE)); |
|
2607 |
1
| assertEquals("There should be four errors", 4, errors.size());
|
|
2608 |
1
| assertEquals("Error message should be correct", "The right side of this expression is a type, not an instance. "
|
|
2609 |
| + "Perhaps you meant to create a new instance of int", |
|
2610 |
| errors.getLast().getFirst()); |
|
2611 |
| } |
|
2612 |
| |
|
2613 |
| |
|
2614 |
1
| public void testForShiftBinaryExpressionOnly() {
|
|
2615 |
1
| ShiftBinaryExpression sbe =
|
|
2616 |
| new LeftShiftExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")), |
|
2617 |
| new IntegerLiteral(SourceInfo.NONE, 42)); |
|
2618 |
1
| try {
|
|
2619 |
1
| _etc.forShiftBinaryExpressionOnly(sbe, _sd2, _sd3);
|
|
2620 |
0
| fail("forShiftBinaryExpressionOnly should have thrown a runtime exception");
|
|
2621 |
| } |
|
2622 |
| catch (RuntimeException e) { |
|
2623 |
1
| assertEquals("Exception message should be correct",
|
|
2624 |
| "Internal Program Error: BinaryShifts are not supported. This should have been caught before " |
|
2625 |
| + "the TypeChecker. Please report this bug.", e.getMessage()); |
|
2626 |
| } |
|
2627 |
| } |
|
2628 |
| |
|
2629 |
| |
|
2630 |
1
| public void testForPlusExpressionOnly() {
|
|
2631 |
1
| PlusExpression pe = new PlusExpression(SourceInfo.NONE, NULL_LITERAL, NULL_LITERAL);
|
|
2632 |
1
| SymbolData string = new SymbolData("java.lang.String");
|
|
2633 |
1
| string.setPackage("java.lang");
|
|
2634 |
1
| string.setIsContinuation(false);
|
|
2635 |
1
| symbolTable.put("java.lang.String", string);
|
|
2636 |
| |
|
2637 |
| |
|
2638 |
1
| assertEquals("Should return String instance", string.getInstanceData(),
|
|
2639 |
| _etc.forPlusExpressionOnly(pe, string.getInstanceData(), _sd1.getInstanceData())); |
|
2640 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2641 |
| |
|
2642 |
| |
|
2643 |
1
| assertEquals("Should return String instance", string.getInstanceData(),
|
|
2644 |
| _etc.forPlusExpressionOnly(pe, _sd1.getInstanceData(), string.getInstanceData())); |
|
2645 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2646 |
| |
|
2647 |
| |
|
2648 |
1
| assertEquals("Should return String instance", string.getInstanceData(),
|
|
2649 |
| _etc.forPlusExpressionOnly(pe, string.getInstanceData(), string.getInstanceData())); |
|
2650 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2651 |
| |
|
2652 |
| |
|
2653 |
1
| assertEquals("Should return Double instance", SymbolData.DOUBLE_TYPE.getInstanceData(),
|
|
2654 |
| _etc.forPlusExpressionOnly(pe, SymbolData.DOUBLE_TYPE.getInstanceData(), |
|
2655 |
| SymbolData.INT_TYPE.getInstanceData())); |
|
2656 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2657 |
| |
|
2658 |
| |
|
2659 |
1
| assertEquals("Should return String instance", string.getInstanceData(),
|
|
2660 |
| _etc.forPlusExpressionOnly(pe, string.getInstanceData(), _sd1)); |
|
2661 |
1
| assertEquals("Should be one error", 1, errors.size());
|
|
2662 |
1
| assertEquals("Error message should be correct",
|
|
2663 |
| "The arguments to the Plus Operator (+) must both be instances, but you have specified a type " |
|
2664 |
| + "name. Perhaps you meant to create a new instance of " + _sd1.getName(), |
|
2665 |
| errors.getLast().getFirst()); |
|
2666 |
| |
|
2667 |
| |
|
2668 |
1
| assertEquals("Should return String instance", string.getInstanceData(),
|
|
2669 |
| _etc.forPlusExpressionOnly(pe, string, string.getInstanceData())); |
|
2670 |
1
| assertEquals("Should be two errors", 2, errors.size());
|
|
2671 |
1
| assertEquals("Error message should be correct",
|
|
2672 |
| "The arguments to the Plus Operator (+) must both be instances, but you have specified a type " |
|
2673 |
| + "name. Perhaps you meant to create a new instance of java.lang.String", |
|
2674 |
| errors.getLast().getFirst()); |
|
2675 |
| |
|
2676 |
| |
|
2677 |
1
| assertEquals("Should return String instance", string.getInstanceData(),
|
|
2678 |
| _etc.forPlusExpressionOnly(pe, SymbolData.INT_TYPE.getInstanceData(), |
|
2679 |
| SymbolData.BOOLEAN_TYPE.getInstanceData())); |
|
2680 |
1
| assertEquals("Should be three errors", 3, errors.size());
|
|
2681 |
1
| assertEquals("Error message should be correct",
|
|
2682 |
| "The arguments to the Plus Operator (+) must either include an instance of a String or both " |
|
2683 |
| + "be numbers. You have specified arguments of type int and boolean", |
|
2684 |
| errors.getLast().getFirst()); |
|
2685 |
| |
|
2686 |
| |
|
2687 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(),
|
|
2688 |
| _etc.forPlusExpressionOnly(pe, SymbolData.INT_TYPE, SymbolData.CHAR_TYPE.getInstanceData())); |
|
2689 |
1
| assertEquals("Should be 4 errors", 4, errors.size());
|
|
2690 |
1
| assertEquals("Error message should be correct",
|
|
2691 |
| "The arguments to the Plus Operator (+) must both be instances, but you have specified a type " |
|
2692 |
| + "name. Perhaps you meant to create a new instance of int", |
|
2693 |
| errors.getLast().getFirst()); |
|
2694 |
| |
|
2695 |
| |
|
2696 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(),
|
|
2697 |
| _etc.forPlusExpressionOnly(pe, SymbolData.INT_TYPE.getInstanceData(), SymbolData.CHAR_TYPE)); |
|
2698 |
1
| assertEquals("Should be 5 errors", 5, errors.size());
|
|
2699 |
1
| assertEquals("Error message should be correct",
|
|
2700 |
| "The arguments to the Plus Operator (+) must both be instances, but you have specified a type " |
|
2701 |
| + "name. Perhaps you meant to create a new instance of char", |
|
2702 |
| errors.getLast().getFirst()); |
|
2703 |
| |
|
2704 |
| |
|
2705 |
| } |
|
2706 |
| |
|
2707 |
| |
|
2708 |
1
| public void testForNumericBinaryExpressionOnly() {
|
|
2709 |
1
| NumericBinaryExpression nbe = new ModExpression(SourceInfo.NONE, NULL_LITERAL, NULL_LITERAL);
|
|
2710 |
| |
|
2711 |
| |
|
2712 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(),
|
|
2713 |
| _etc.forNumericBinaryExpressionOnly(nbe, SymbolData.INT_TYPE.getInstanceData(), |
|
2714 |
| SymbolData.INT_TYPE.getInstanceData())); |
|
2715 |
1
| assertEquals("There should be no errors", 0, errors.size());
|
|
2716 |
| |
|
2717 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(),
|
|
2718 |
| _etc.forNumericBinaryExpressionOnly(nbe, SymbolData.INT_TYPE.getInstanceData(), |
|
2719 |
| SymbolData.CHAR_TYPE.getInstanceData())); |
|
2720 |
1
| assertEquals("There should be no errors", 0, errors.size());
|
|
2721 |
| |
|
2722 |
1
| assertEquals("Should return double instance", SymbolData.DOUBLE_TYPE.getInstanceData(),
|
|
2723 |
| _etc.forNumericBinaryExpressionOnly(nbe, SymbolData.INT_TYPE.getInstanceData(), |
|
2724 |
| SymbolData.DOUBLE_TYPE.getInstanceData())); |
|
2725 |
1
| assertEquals("There should be no errors", 0, errors.size());
|
|
2726 |
| |
|
2727 |
| |
|
2728 |
1
| assertEquals("Should return double instance", SymbolData.DOUBLE_TYPE.getInstanceData(),
|
|
2729 |
| _etc.forNumericBinaryExpressionOnly(nbe, SymbolData.INT_TYPE, |
|
2730 |
| SymbolData.DOUBLE_TYPE.getInstanceData())); |
|
2731 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
2732 |
1
| assertEquals("Error message should be correct", "The left side of this expression is a type, not an instance. "
|
|
2733 |
| + "Perhaps you meant to create a new instance of int", errors.getLast().getFirst()); |
|
2734 |
| |
|
2735 |
| |
|
2736 |
1
| assertEquals("Should return double instance", SymbolData.DOUBLE_TYPE.getInstanceData(),
|
|
2737 |
| _etc.forNumericBinaryExpressionOnly(nbe, SymbolData.BOOLEAN_TYPE.getInstanceData(), |
|
2738 |
| SymbolData.DOUBLE_TYPE.getInstanceData())); |
|
2739 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
2740 |
1
| assertEquals("Error message should be correct", "The left side of this expression is not a number. "
|
|
2741 |
| + "Therefore, you cannot apply a Numeric Binary Operator (*, /, -, %) to it", |
|
2742 |
| errors.getLast().getFirst()); |
|
2743 |
| |
|
2744 |
| |
|
2745 |
1
| assertEquals("Should return double instance", SymbolData.DOUBLE_TYPE.getInstanceData(),
|
|
2746 |
| _etc.forNumericBinaryExpressionOnly(nbe, SymbolData.INT_TYPE.getInstanceData(), |
|
2747 |
| SymbolData.DOUBLE_TYPE)); |
|
2748 |
1
| assertEquals("Should be 3 errors", 3, errors.size());
|
|
2749 |
1
| assertEquals("Error message should be correct", "The right side of this expression is a type, not an instance. "
|
|
2750 |
| + "Perhaps you meant to create a new instance of double", errors.getLast().getFirst()); |
|
2751 |
| |
|
2752 |
| |
|
2753 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(),
|
|
2754 |
| _etc.forNumericBinaryExpressionOnly(nbe, SymbolData.INT_TYPE.getInstanceData(), |
|
2755 |
| SymbolData.BOOLEAN_TYPE.getInstanceData())); |
|
2756 |
1
| assertEquals("Should be 4 errors", 4, errors.size());
|
|
2757 |
1
| assertEquals("Error message should be correct",
|
|
2758 |
| "The right side of this expression is not a number. Therefore, you cannot apply a " |
|
2759 |
| + "Numeric Binary Operator (*, /, -, %) to it", errors.getLast().getFirst()); |
|
2760 |
| } |
|
2761 |
| |
|
2762 |
1
| public void testForNoOpExpressionOnly() {
|
|
2763 |
1
| NoOpExpression noe = new NoOpExpression(SourceInfo.NONE, NULL_LITERAL, NULL_LITERAL);
|
|
2764 |
1
| try {
|
|
2765 |
1
| _etc.forNoOpExpressionOnly(noe, null, null);
|
|
2766 |
0
| fail("Should have thrown runtime exception");
|
|
2767 |
| } |
|
2768 |
| catch (RuntimeException e) { |
|
2769 |
1
| assertEquals("Error message should be correct", "Internal Program Error: The student is missing an operator. This should have been caught before the TypeChecker. Please report this bug.", e.getMessage());
|
|
2770 |
| } |
|
2771 |
| } |
|
2772 |
| |
|
2773 |
1
| public void testForIncrementExpressionOnly() {
|
|
2774 |
1
| IncrementExpression ie =
|
|
2775 |
| new PositivePrefixIncrementExpression(SourceInfo.NONE, |
|
2776 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i"))); |
|
2777 |
| |
|
2778 |
| |
|
2779 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(),
|
|
2780 |
| _etc.forIncrementExpressionOnly(ie, SymbolData.INT_TYPE.getInstanceData())); |
|
2781 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2782 |
| |
|
2783 |
| |
|
2784 |
| |
|
2785 |
1
| assertEquals("Should return null", null, _etc.forIncrementExpressionOnly(ie, null));
|
|
2786 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2787 |
| |
|
2788 |
| |
|
2789 |
1
| PackageData pd = new PackageData("bad_reference");
|
|
2790 |
1
| assertEquals("Should return null", null, _etc.forIncrementExpressionOnly(ie, pd));
|
|
2791 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
2792 |
1
| assertEquals("Error message should be correct", "Could not resolve symbol bad_reference", errors.getLast().getFirst());
|
|
2793 |
| |
|
2794 |
| |
|
2795 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(),
|
|
2796 |
| _etc.forIncrementExpressionOnly(ie, SymbolData.INT_TYPE)); |
|
2797 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
2798 |
1
| assertEquals("Error message should be correct",
|
|
2799 |
| "You cannot increment or decrement int, because it is a class name not an instance. " |
|
2800 |
| + "Perhaps you meant to create a new instance of int", errors.getLast().getFirst()); |
|
2801 |
| |
|
2802 |
| |
|
2803 |
1
| assertEquals("Should return sd2 instance", _sd2.getInstanceData(),
|
|
2804 |
| _etc.forIncrementExpressionOnly(ie, _sd2.getInstanceData())); |
|
2805 |
1
| assertEquals("Should be 3 errors", 3, errors.size());
|
|
2806 |
1
| assertEquals("Error message should be correct",
|
|
2807 |
| "You cannot increment or decrement something that is not a number type. You have specified " |
|
2808 |
| + "something of type " + _sd2.getName(), |
|
2809 |
| errors.getLast().getFirst()); |
|
2810 |
| } |
|
2811 |
| |
|
2812 |
| |
|
2813 |
| |
|
2814 |
1
| public void testForNumericUnaryExpressionOnly() {
|
|
2815 |
1
| NumericUnaryExpression nue = new PositiveExpression(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 5));
|
|
2816 |
| |
|
2817 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(),
|
|
2818 |
| _etc.forNumericUnaryExpressionOnly(nue, SymbolData.CHAR_TYPE.getInstanceData())); |
|
2819 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(),
|
|
2820 |
| _etc.forNumericUnaryExpressionOnly(nue, SymbolData.BYTE_TYPE.getInstanceData())); |
|
2821 |
1
| assertEquals("There should be no errors", 0, errors.size());
|
|
2822 |
| |
|
2823 |
| |
|
2824 |
1
| assertEquals("Should return double instance", SymbolData.DOUBLE_TYPE.getInstanceData(),
|
|
2825 |
| _etc.forNumericUnaryExpressionOnly(nue, SymbolData.DOUBLE_TYPE.getInstanceData())); |
|
2826 |
1
| assertEquals("There should be no errors", 0, errors.size());
|
|
2827 |
| |
|
2828 |
| |
|
2829 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(),
|
|
2830 |
| _etc.forNumericUnaryExpressionOnly(nue, SymbolData.INT_TYPE)); |
|
2831 |
1
| assertEquals("Should be one error", 1, errors.size());
|
|
2832 |
1
| assertEquals("Error message should be correct",
|
|
2833 |
| "You cannot use a numeric unary operator (+, -) with int, because it is a class name, " |
|
2834 |
| + "not an instance. Perhaps you meant to create a new instance of int", |
|
2835 |
| errors.getLast().getFirst()); |
|
2836 |
| |
|
2837 |
| |
|
2838 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2839 |
| _etc.forNumericUnaryExpressionOnly(nue, SymbolData.BOOLEAN_TYPE.getInstanceData())); |
|
2840 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
2841 |
1
| assertEquals("Error message should be correct",
|
|
2842 |
| "You cannot apply this unary operator to something of type boolean. You can only apply it " |
|
2843 |
| + "to a numeric type such as double, int, or char", errors.getLast().getFirst()); |
|
2844 |
| } |
|
2845 |
| |
|
2846 |
1
| public void testForBitwiseNotExpressionOnly() {
|
|
2847 |
1
| BitwiseNotExpression bne =
|
|
2848 |
| new BitwiseNotExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "t"))); |
|
2849 |
1
| try {
|
|
2850 |
1
| _etc.forBitwiseNotExpressionOnly(bne, _sd3);
|
|
2851 |
0
| fail("forBitwiseNotExpressionOnly should have thrown a runtime exception");
|
|
2852 |
| } |
|
2853 |
| catch (RuntimeException e) { |
|
2854 |
1
| assertEquals("Exception message should be correct", "Internal Program Error: BitwiseNot is not supported. It should have been caught before getting to the TypeChecker. Please report this bug.", e.getMessage());
|
|
2855 |
| } |
|
2856 |
| } |
|
2857 |
| |
|
2858 |
| |
|
2859 |
1
| public void testForNotExpressionOnly() {
|
|
2860 |
1
| NotExpression ne = new NotExpression(SourceInfo.NONE, NULL_LITERAL);
|
|
2861 |
| |
|
2862 |
| |
|
2863 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2864 |
| _etc.forNotExpressionOnly(ne, SymbolData.BOOLEAN_TYPE.getInstanceData())); |
|
2865 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2866 |
| |
|
2867 |
| |
|
2868 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2869 |
| _etc.forNotExpressionOnly(ne, SymbolData.BOOLEAN_TYPE)); |
|
2870 |
1
| assertEquals("Should be one error", 1, errors.size());
|
|
2871 |
1
| assertEquals("Error message should be correct",
|
|
2872 |
| "You cannot use the not (!) operator with boolean, because it is a class name, not an instance. " |
|
2873 |
| + "Perhaps you meant to create a new instance of boolean", errors.getLast().getFirst()); |
|
2874 |
| |
|
2875 |
| |
|
2876 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
2877 |
| _etc.forNotExpressionOnly(ne, SymbolData.INT_TYPE.getInstanceData())); |
|
2878 |
1
| assertEquals("Should be two errors", 2, errors.size());
|
|
2879 |
1
| assertEquals("Error message should be correct",
|
|
2880 |
| "You cannot use the not (!) operator with something of type int. Instead, it should be used " |
|
2881 |
| + "with an expression of boolean type", errors.getLast().getFirst()); |
|
2882 |
| } |
|
2883 |
| |
|
2884 |
| |
|
2885 |
1
| public void testForConditionalExpressionOnly() {
|
|
2886 |
1
| SymbolData sd1 = SymbolData.DOUBLE_TYPE;
|
|
2887 |
1
| SymbolData sd2 = SymbolData.BOOLEAN_TYPE;
|
|
2888 |
1
| SymbolData sd3 = SymbolData.INT_TYPE;
|
|
2889 |
1
| ConditionalExpression cd = new ConditionalExpression(SourceInfo.NONE,
|
|
2890 |
| new BooleanLiteral(SourceInfo.NONE, true), |
|
2891 |
| new IntegerLiteral(SourceInfo.NONE, 5), |
|
2892 |
| new IntegerLiteral(SourceInfo.NONE, 79)); |
|
2893 |
| |
|
2894 |
1
| try {
|
|
2895 |
1
| _etc.forConditionalExpressionOnly(cd, _sd3, _sd2, _sd1);
|
|
2896 |
0
| fail("Should have thrown an exception.");
|
|
2897 |
| } |
|
2898 |
| catch (Exception e) { |
|
2899 |
1
| assertEquals("Exception message should be correct",
|
|
2900 |
| "Internal Program Error: Conditional expressions are not supported. This should have been " |
|
2901 |
| + "caught before the TypeChecker. Please report this bug.", e.getMessage()); |
|
2902 |
| |
|
2903 |
| } |
|
2904 |
| } |
|
2905 |
| |
|
2906 |
1
| public void testForInstanceOfExpressionOnly() {
|
|
2907 |
1
| SymbolData sd1 = SymbolData.DOUBLE_TYPE;
|
|
2908 |
1
| SymbolData sd2 = SymbolData.BOOLEAN_TYPE;
|
|
2909 |
1
| SymbolData sd3 = SymbolData.INT_TYPE;
|
|
2910 |
1
| InstanceofExpression ioe = new InstanceofExpression(SourceInfo.NONE, NULL_LITERAL, JExprParser.NO_TYPE);
|
|
2911 |
1
| assertEquals("When valueRes is subtype of typeRes, return BOOLEAN typeRes.", sd2.getInstanceData(),
|
|
2912 |
| _etc.forInstanceofExpressionOnly(ioe, sd1, sd3.getInstanceData())); |
|
2913 |
1
| assertEquals("Should not throw an error.", 0, errors.size());
|
|
2914 |
1
| assertEquals("When typeRes is subtype of valueRes, return BOOLEAN typeRes.", sd2.getInstanceData(),
|
|
2915 |
| _etc.forInstanceofExpressionOnly(ioe, sd3, sd1.getInstanceData())); |
|
2916 |
1
| assertEquals("Should not throw an error.", 0, errors.size());
|
|
2917 |
1
| assertEquals("When typeRes and valueRes are not subtypes of each other, return BOOLEAN typeRes",
|
|
2918 |
| sd2.getInstanceData(), |
|
2919 |
| _etc.forInstanceofExpressionOnly(ioe, sd2, sd1.getInstanceData())); |
|
2920 |
1
| assertEquals("Should now be one error.", 1, errors.size());
|
|
2921 |
1
| assertEquals("Error message should be correct.", "You cannot test whether an expression of type " + sd1.getName()
|
|
2922 |
| + " belongs to type " + sd2.getName() + " because they are not related", |
|
2923 |
| errors.getLast().getFirst()); |
|
2924 |
1
| SymbolData foo = new SymbolData("Foo");
|
|
2925 |
1
| SymbolData fooMama = new SymbolData("FooMama");
|
|
2926 |
1
| foo.setSuperClass(fooMama);
|
|
2927 |
1
| assertEquals("When valueRes is a SymbolData, return BOOLEAN typeRes", sd2.getInstanceData(),
|
|
2928 |
| _etc.forInstanceofExpressionOnly(ioe, foo, fooMama)); |
|
2929 |
1
| assertEquals("There should be 2 errors.", 2, errors.size());
|
|
2930 |
1
| assertEquals("Error message should be correct.",
|
|
2931 |
| "You are trying to test if FooMama belongs to type, but it is a class or interface type, " |
|
2932 |
| + "not an instance. Perhaps you meant to create a new instance of FooMama", |
|
2933 |
| errors.getLast().getFirst()); |
|
2934 |
| } |
|
2935 |
| |
|
2936 |
1
| public void testClassInstantiationHelper() {
|
|
2937 |
1
| ClassInstantiation simpleCI =
|
|
2938 |
| new SimpleNamedClassInstantiation(SourceInfo.NONE, |
|
2939 |
| new ClassOrInterfaceType(SourceInfo.NONE, "testClass", new Type[0]), |
|
2940 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])); |
|
2941 |
1
| ClassInstantiation complexCI =
|
|
2942 |
| new ComplexNamedClassInstantiation(SourceInfo.NONE, |
|
2943 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "Outer")), |
|
2944 |
| new ClassOrInterfaceType(SourceInfo.NONE, "Inner", new Type[0]), |
|
2945 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])); |
|
2946 |
| |
|
2947 |
1
| ParenthesizedExpressionList pel =
|
|
2948 |
| new ParenthesizedExpressionList(SourceInfo.NONE, |
|
2949 |
| new Expression[] {new SimpleNameReference(SourceInfo.NONE, |
|
2950 |
| new Word(SourceInfo.NONE, "int"))}); |
|
2951 |
1
| ClassInstantiation badArgs =
|
|
2952 |
| new SimpleNamedClassInstantiation(SourceInfo.NONE, |
|
2953 |
| new ClassOrInterfaceType(SourceInfo.NONE, "anotherClass", new Type[0]), |
|
2954 |
| pel); |
|
2955 |
| |
|
2956 |
1
| SymbolData testClass = new SymbolData("testClass");
|
|
2957 |
1
| SymbolData outer = new SymbolData("Outer");
|
|
2958 |
1
| SymbolData outerInner = new SymbolData("Outer.Inner");
|
|
2959 |
1
| outer.addInnerClass(outerInner);
|
|
2960 |
1
| outerInner.setOuterData(outer);
|
|
2961 |
| |
|
2962 |
| |
|
2963 |
1
| assertEquals("Should return null", null, _etc.classInstantiationHelper(simpleCI, null));
|
|
2964 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
2965 |
| |
|
2966 |
| |
|
2967 |
| |
|
2968 |
1
| assertEquals("Should return double instance", SymbolData.DOUBLE_TYPE.getInstanceData(),
|
|
2969 |
| _etc.classInstantiationHelper(badArgs, SymbolData.DOUBLE_TYPE)); |
|
2970 |
1
| assertEquals("Should be one error", 1, errors.size());
|
|
2971 |
1
| assertEquals("Error message should be correct",
|
|
2972 |
| "Cannot pass a class or interface name as a constructor argument. Perhaps you meant to create a " |
|
2973 |
| + "new instance of int", errors.getLast().getFirst()); |
|
2974 |
| |
|
2975 |
| |
|
2976 |
1
| assertEquals("Should return instance of testClass", testClass.getInstanceData(),
|
|
2977 |
| _etc.classInstantiationHelper(simpleCI, testClass)); |
|
2978 |
1
| assertEquals("Should be two errors", 2, errors.size());
|
|
2979 |
1
| assertEquals("Error message should be correct",
|
|
2980 |
| "No constructor found in class testClass with signature: testClass().", errors.getLast().getFirst()); |
|
2981 |
| |
|
2982 |
1
| assertEquals("Should return instance of Outer.Inner", outerInner.getInstanceData(),
|
|
2983 |
| _etc.classInstantiationHelper(complexCI, outerInner)); |
|
2984 |
1
| assertEquals("Should be three errors", 3, errors.size());
|
|
2985 |
1
| assertEquals("Error message should be correct",
|
|
2986 |
| "No constructor found in class Outer.Inner with signature: Inner().", errors.getLast().getFirst()); |
|
2987 |
| |
|
2988 |
| |
|
2989 |
| |
|
2990 |
1
| MethodData md = new MethodData("testClass", _publicMav, new TypeParameter[0], testClass,
|
|
2991 |
| new VariableData[0], |
|
2992 |
| new String[0], |
|
2993 |
| testClass, |
|
2994 |
| null); |
|
2995 |
1
| testClass.addMethod(md);
|
|
2996 |
1
| assertEquals("Should return instance of testClass", testClass.getInstanceData(),
|
|
2997 |
| _etc.classInstantiationHelper(simpleCI, testClass)); |
|
2998 |
1
| assertEquals("Should still be just three errors", 3, errors.size());
|
|
2999 |
| } |
|
3000 |
| |
|
3001 |
| |
|
3002 |
1
| public void testForSimpleNamedClassInstantiation() {
|
|
3003 |
1
| ParenthesizedExpressionList pel1 =
|
|
3004 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[] {new IntegerLiteral(SourceInfo.NONE, 5)}); |
|
3005 |
1
| SimpleNamedClassInstantiation ci1 =
|
|
3006 |
| new SimpleNamedClassInstantiation(SourceInfo.NONE, |
|
3007 |
| new ClassOrInterfaceType(SourceInfo.NONE, "simpleClass", new Type[0]), |
|
3008 |
| pel1); |
|
3009 |
1
| SimpleNamedClassInstantiation ci3 =
|
|
3010 |
| new SimpleNamedClassInstantiation(SourceInfo.NONE, |
|
3011 |
| new ClassOrInterfaceType(SourceInfo.NONE, "simpleClass", new Type[0]), |
|
3012 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])); |
|
3013 |
| |
|
3014 |
| |
|
3015 |
1
| assertEquals("Should return null, since simpleClass is not in symbol table", null, ci1.visit(_etc));
|
|
3016 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
3017 |
1
| assertEquals("Error message should be correct", "Class or variable simpleClass not found.", errors.getLast().getFirst());
|
|
3018 |
| |
|
3019 |
| |
|
3020 |
1
| SymbolData simpleClass = new SymbolData("simpleClass");
|
|
3021 |
1
| simpleClass.setIsContinuation(false);
|
|
3022 |
1
| MethodData cons1 = new MethodData("simpleClass", _publicMav, new TypeParameter[0], simpleClass,
|
|
3023 |
| new VariableData[0], |
|
3024 |
| new String[0], |
|
3025 |
| simpleClass, |
|
3026 |
| null); |
|
3027 |
1
| simpleClass.addMethod(cons1);
|
|
3028 |
1
| symbolTable.put("simpleClass", simpleClass);
|
|
3029 |
| |
|
3030 |
1
| assertEquals("Should return simpleClass even though it could not really access it",
|
|
3031 |
| simpleClass.getInstanceData(), ci3.visit(_etc)); |
|
3032 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
3033 |
1
| assertEquals("Error message should be correct",
|
|
3034 |
| "The class or interface simpleClass is package protected because there is no access specifier and " |
|
3035 |
| + "cannot be accessed from i.like.monkey", |
|
3036 |
| errors.getLast().getFirst()); |
|
3037 |
| |
|
3038 |
| |
|
3039 |
| |
|
3040 |
1
| simpleClass.setMav(new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"}));
|
|
3041 |
| |
|
3042 |
1
| assertEquals("Should return simpleClass even though it could not find constructor", simpleClass.getInstanceData(),
|
|
3043 |
| ci1.visit(_etc)); |
|
3044 |
1
| assertEquals("Should be 3 errors", 3, errors.size());
|
|
3045 |
1
| assertEquals("Error message should be correct",
|
|
3046 |
| "No constructor found in class simpleClass with signature: simpleClass(int).", |
|
3047 |
| errors.getLast().getFirst()); |
|
3048 |
| |
|
3049 |
| |
|
3050 |
1
| MethodData cons2 = new MethodData("simpleClass", _publicMav, new TypeParameter[0], simpleClass,
|
|
3051 |
| new VariableData[] {new VariableData(SymbolData.INT_TYPE)}, |
|
3052 |
| new String[0], |
|
3053 |
| simpleClass, |
|
3054 |
| null); |
|
3055 |
1
| simpleClass.addMethod(cons2);
|
|
3056 |
1
| assertEquals("Should return simpleClass", simpleClass.getInstanceData(), ci1.visit(_etc));
|
|
3057 |
1
| assertEquals("Should still be 3 errors", 3, errors.size());
|
|
3058 |
| |
|
3059 |
| |
|
3060 |
| |
|
3061 |
1
| simpleClass.addModifier("abstract");
|
|
3062 |
1
| assertEquals("Should return simpleClass even though it cannot really be instantiated",
|
|
3063 |
| simpleClass.getInstanceData(), ci1.visit(_etc)); |
|
3064 |
1
| assertEquals("Should be 4 errors", 4, errors.size());
|
|
3065 |
1
| assertEquals("Error message should be correct", "simpleClass is abstract and thus cannot be instantiated",
|
|
3066 |
| errors.getLast().getFirst()); |
|
3067 |
| |
|
3068 |
| |
|
3069 |
| |
|
3070 |
1
| SimpleNamedClassInstantiation ci2 =
|
|
3071 |
| new SimpleNamedClassInstantiation(SourceInfo.NONE, |
|
3072 |
| new ClassOrInterfaceType(SourceInfo.NONE, "A.B", new Type[0]), |
|
3073 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])); |
|
3074 |
| |
|
3075 |
| |
|
3076 |
1
| SymbolData a = new SymbolData("A");
|
|
3077 |
1
| a.setIsContinuation(false);
|
|
3078 |
1
| SymbolData b = new SymbolData("A$B");
|
|
3079 |
1
| b.setIsContinuation(false);
|
|
3080 |
1
| b.setOuterData(a);
|
|
3081 |
1
| a.addInnerClass(b);
|
|
3082 |
1
| MethodData consb = new MethodData("B", _publicMav, new TypeParameter[0], b,
|
|
3083 |
| new VariableData[0], |
|
3084 |
| new String[0], |
|
3085 |
| b, |
|
3086 |
| null); |
|
3087 |
1
| b.addMethod(consb);
|
|
3088 |
1
| symbolTable.put("A", a);
|
|
3089 |
1
| a.setMav(new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"}));
|
|
3090 |
1
| b.setMav(new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"}));
|
|
3091 |
| |
|
3092 |
| |
|
3093 |
1
| assertEquals("Should return A.B", b.getInstanceData(), ci2.visit(_etc));
|
|
3094 |
1
| assertEquals("Should be 5 errors", 5, errors.size());
|
|
3095 |
1
| assertEquals("Error message should be correct",
|
|
3096 |
| "A.B is not a static inner class, and thus cannot be instantiated from this context. Perhaps " |
|
3097 |
| +"you meant to use an instantiation of the form new A().new B()", |
|
3098 |
| errors.getLast().getFirst()); |
|
3099 |
| |
|
3100 |
1
| b.addModifier("static");
|
|
3101 |
1
| assertEquals("Should return A.B", b.getInstanceData(), ci2.visit(_etc));
|
|
3102 |
1
| assertEquals("Should still be just 5 errors", 5, errors.size());
|
|
3103 |
| } |
|
3104 |
| |
|
3105 |
1
| public void testForComplexNamedClassInstantiation() {
|
|
3106 |
1
| ParenthesizedExpressionList pel1 =
|
|
3107 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[] { new IntegerLiteral(SourceInfo.NONE, 5)}); |
|
3108 |
1
| ComplexNamedClassInstantiation ci1 =
|
|
3109 |
| new ComplexNamedClassInstantiation(SourceInfo.NONE, |
|
3110 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "o")), |
|
3111 |
| new ClassOrInterfaceType(SourceInfo.NONE, "innerClass", new Type[0]), |
|
3112 |
| pel1); |
|
3113 |
| |
|
3114 |
1
| ComplexNamedClassInstantiation ci2 =
|
|
3115 |
| new ComplexNamedClassInstantiation(SourceInfo.NONE, |
|
3116 |
| new SimpleNameReference(SourceInfo.NONE, |
|
3117 |
| new Word(SourceInfo.NONE, "o")), |
|
3118 |
| new ClassOrInterfaceType(SourceInfo.NONE, "innerClass", new Type[0]), |
|
3119 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])); |
|
3120 |
| |
|
3121 |
| |
|
3122 |
1
| assertEquals("Should return null", null, ci1.visit(_etc));
|
|
3123 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
3124 |
1
| assertEquals("Error message should be correct", "Could not resolve symbol o", errors.getLast().getFirst());
|
|
3125 |
| |
|
3126 |
| |
|
3127 |
| |
|
3128 |
1
| SymbolData outerClass = new SymbolData("outer");
|
|
3129 |
1
| outerClass.setIsContinuation(false);
|
|
3130 |
1
| SymbolData innerClass = new SymbolData("outer$innerClass");
|
|
3131 |
1
| innerClass.setIsContinuation(false);
|
|
3132 |
1
| outerClass.addInnerClass(innerClass);
|
|
3133 |
1
| innerClass.setOuterData(outerClass);
|
|
3134 |
1
| MethodData cons1 = new MethodData("innerClass", _publicMav, new TypeParameter[0], innerClass,
|
|
3135 |
| new VariableData[0], |
|
3136 |
| new String[0], |
|
3137 |
| innerClass, |
|
3138 |
| null); |
|
3139 |
1
| innerClass.addMethod(cons1);
|
|
3140 |
1
| symbolTable.put("outer", outerClass);
|
|
3141 |
1
| _etc._vars.addLast(new VariableData("o", _publicMav, outerClass, true, _etc._data));
|
|
3142 |
1
| outerClass.setMav(new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"}));
|
|
3143 |
1
| innerClass.setMav(new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"}));
|
|
3144 |
| |
|
3145 |
1
| assertEquals("Should return innerClass even though it could not find constructor", innerClass.getInstanceData(),
|
|
3146 |
| ci1.visit(_etc)); |
|
3147 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
3148 |
1
| assertEquals("Error message should be correct",
|
|
3149 |
| "No constructor found in class outer.innerClass with signature: innerClass(int).", |
|
3150 |
| errors.getLast().getFirst()); |
|
3151 |
| |
|
3152 |
| |
|
3153 |
1
| MethodData cons2 = new MethodData("innerClass", _publicMav, new TypeParameter[0], innerClass,
|
|
3154 |
| new VariableData[] {new VariableData(SymbolData.INT_TYPE)}, |
|
3155 |
| new String[0], |
|
3156 |
| innerClass, |
|
3157 |
| null); |
|
3158 |
1
| innerClass.addMethod(cons2);
|
|
3159 |
1
| assertEquals("Should return innerClass", innerClass.getInstanceData(), ci1.visit(_etc));
|
|
3160 |
1
| assertEquals("Should still be 2 errors", 2, errors.size());
|
|
3161 |
| |
|
3162 |
| |
|
3163 |
1
| innerClass.addModifier("abstract");
|
|
3164 |
1
| assertEquals("Should return innerClass even though it cannot really be instantiated", innerClass.getInstanceData(),
|
|
3165 |
| ci1.visit(_etc)); |
|
3166 |
1
| assertEquals("Should be 3 errors", 3, errors.size());
|
|
3167 |
1
| assertEquals("Error message should be correct", "outer.innerClass is abstract and thus cannot be instantiated",
|
|
3168 |
| errors.getLast().getFirst()); |
|
3169 |
| |
|
3170 |
| |
|
3171 |
1
| ComplexNamedClassInstantiation ci3 =
|
|
3172 |
| new ComplexNamedClassInstantiation(SourceInfo.NONE, |
|
3173 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "outer")), |
|
3174 |
| new ClassOrInterfaceType(SourceInfo.NONE, "innerClass", new Type[0]), |
|
3175 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])); |
|
3176 |
1
| outerClass.setMav(new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"}));
|
|
3177 |
1
| innerClass.setMav(new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"}));
|
|
3178 |
1
| assertEquals("Should return innerClass even though the syntax was wrong", innerClass.getInstanceData(),
|
|
3179 |
| ci3.visit(_etc)); |
|
3180 |
1
| assertEquals("Should be 4 errors", 4, errors.size());
|
|
3181 |
1
| assertEquals("Error message should be correct",
|
|
3182 |
| "The constructor of a non-static inner class can only be called on an instance of its containing " |
|
3183 |
| + "class (e.g. new outer().new innerClass())", |
|
3184 |
| errors.getLast().getFirst()); |
|
3185 |
| |
|
3186 |
| |
|
3187 |
1
| innerClass.addModifier("static");
|
|
3188 |
1
| assertEquals("Should return innerClass even though the syntax was wrong",
|
|
3189 |
| innerClass.getInstanceData(), ci1.visit(_etc)); |
|
3190 |
1
| assertEquals("Should be 5 errors", 5, errors.size());
|
|
3191 |
| |
|
3192 |
1
| assertEquals("Error message should be correct",
|
|
3193 |
| "You cannot instantiate a static inner class or interface with this syntax. Instead, " |
|
3194 |
| + "try new outer.innerClass()", |
|
3195 |
| errors.getLast().getFirst()); |
|
3196 |
| |
|
3197 |
| |
|
3198 |
| |
|
3199 |
1
| innerClass.setMav(_publicMav);
|
|
3200 |
1
| ParenthesizedExpressionList pel2 =
|
|
3201 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[] {new IntegerLiteral(SourceInfo.NONE, 5)}); |
|
3202 |
1
| ComplexNamedClassInstantiation ci4 =
|
|
3203 |
| new ComplexNamedClassInstantiation(SourceInfo.NONE, |
|
3204 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "o")), |
|
3205 |
| new ClassOrInterfaceType(SourceInfo.NONE, "notInnerClass", new Type[0]), |
|
3206 |
| pel2); |
|
3207 |
1
| assertEquals("Should return null", null, ci4.visit(_etc));
|
|
3208 |
1
| assertEquals("Should be 6 errors", 6, errors.size());
|
|
3209 |
1
| assertEquals("Error message should be correct", "Class or variable notInnerClass not found.",
|
|
3210 |
| errors.getLast().getFirst()); |
|
3211 |
| |
|
3212 |
| |
|
3213 |
| |
|
3214 |
1
| innerClass.setMav(_privateMav);
|
|
3215 |
1
| assertEquals("Should return inner class", innerClass.getInstanceData(), ci1.visit(_etc));
|
|
3216 |
1
| assertEquals("Should be 7 errors", 7, errors.size());
|
|
3217 |
1
| assertEquals("Error message should be correct",
|
|
3218 |
| "The class or interface outer.innerClass in outer.innerClass is private and cannot be accessed from i.like.monkey", |
|
3219 |
| errors.getLast().getFirst()); |
|
3220 |
| |
|
3221 |
| |
|
3222 |
1
| outerClass.setMav(_privateMav);
|
|
3223 |
1
| innerClass.setMav(_publicMav);
|
|
3224 |
1
| assertEquals("Should return inner class", innerClass.getInstanceData(), ci1.visit(_etc));
|
|
3225 |
1
| assertEquals("Should be 8 errors", 8, errors.size());
|
|
3226 |
1
| assertEquals("Error message should be correct",
|
|
3227 |
| "The class or interface outer in outer is private and cannot be accessed from i.like.monkey", |
|
3228 |
| errors.getLast().getFirst()); |
|
3229 |
| } |
|
3230 |
| |
|
3231 |
1
| public void testForSimpleThisConstructorInvocation() {
|
|
3232 |
| |
|
3233 |
1
| SimpleThisConstructorInvocation stci =
|
|
3234 |
| new SimpleThisConstructorInvocation(SourceInfo.NONE, |
|
3235 |
| new ParenthesizedExpressionList(SourceInfo.NONE, |
|
3236 |
| new Expression[0])); |
|
3237 |
1
| assertEquals("Should return null", null, stci.visit(_etc));
|
|
3238 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
3239 |
1
| assertEquals("Error message should be correct",
|
|
3240 |
| "This constructor invocations are only allowed as the first statement of a constructor body", |
|
3241 |
| errors.getLast().getFirst()); |
|
3242 |
| } |
|
3243 |
| |
|
3244 |
1
| public void testForComplexThisConstructorInvocation() {
|
|
3245 |
| |
|
3246 |
1
| ComplexThisConstructorInvocation ctci =
|
|
3247 |
| new ComplexThisConstructorInvocation(SourceInfo.NONE, |
|
3248 |
| new SimpleNameReference(SourceInfo.NONE, |
|
3249 |
| new Word(SourceInfo.NONE, "something")), |
|
3250 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])); |
|
3251 |
1
| assertEquals("Should return null", null, ctci.visit(_etc));
|
|
3252 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
3253 |
1
| assertEquals("Error message should be correct",
|
|
3254 |
| "Constructor invocations of this form are never allowed", |
|
3255 |
| errors.getLast().getFirst()); |
|
3256 |
| } |
|
3257 |
| |
|
3258 |
1
| public void testForSimpleNameReference() {
|
|
3259 |
| |
|
3260 |
1
| SimpleNameReference var = new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "variable1"));
|
|
3261 |
1
| VariableData varData = new VariableData("variable1", _publicMav, SymbolData.INT_TYPE, false, _etc._data);
|
|
3262 |
1
| _etc._vars.add(varData);
|
|
3263 |
| |
|
3264 |
| |
|
3265 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), var.visit(_etc));
|
|
3266 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
3267 |
1
| assertEquals("Error message should be correct",
|
|
3268 |
| "You cannot use variable1 because it may not have been given a value", |
|
3269 |
| errors.getLast().getFirst()); |
|
3270 |
| |
|
3271 |
| |
|
3272 |
1
| varData.gotValue();
|
|
3273 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), var.visit(_etc));
|
|
3274 |
1
| assertEquals("Should still be 1 error", 1, errors.size());
|
|
3275 |
| |
|
3276 |
| |
|
3277 |
1
| MethodData newContext =
|
|
3278 |
| new MethodData("method", _publicStaticMav, new TypeParameter[0], SymbolData.INT_TYPE, new VariableData[0], |
|
3279 |
| new String[0], _sd1, NULL_LITERAL); |
|
3280 |
1
| _etc._data = newContext;
|
|
3281 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), var.visit(_etc));
|
|
3282 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
3283 |
1
| assertEquals("Error message should be correct",
|
|
3284 |
| "Non-static variable or field variable1 cannot be referenced from a static context", |
|
3285 |
| errors.getLast().getFirst()); |
|
3286 |
| |
|
3287 |
| |
|
3288 |
1
| SimpleNameReference var2 = new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "variable1"));
|
|
3289 |
1
| MethodData newContext2 =
|
|
3290 |
| new MethodData("method2", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE, new VariableData[0], |
|
3291 |
| new String[0], _sd1, NULL_LITERAL); |
|
3292 |
1
| VariableData varData2 = new VariableData("variable2", _privateMav, SymbolData.INT_TYPE, false, newContext2);
|
|
3293 |
1
| newContext2.addVar(varData2);
|
|
3294 |
| |
|
3295 |
1
| varData2.gotValue();
|
|
3296 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), var2.visit(_etc));
|
|
3297 |
1
| assertEquals("Should be still be 2 errors", 2, errors.size());
|
|
3298 |
| |
|
3299 |
1
| _etc._data = _sd1;
|
|
3300 |
| |
|
3301 |
| |
|
3302 |
1
| _etc._vars = new LinkedList<VariableData>();
|
|
3303 |
1
| _sd1.setSuperClass(_sd2);
|
|
3304 |
1
| _sd2.addVar(varData);
|
|
3305 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), var.visit(_etc));
|
|
3306 |
1
| assertEquals("Should still be 2 errors", 2, errors.size());
|
|
3307 |
| |
|
3308 |
| |
|
3309 |
1
| SimpleNameReference className = new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "Frog"));
|
|
3310 |
1
| SymbolData frog = new SymbolData("Frog");
|
|
3311 |
1
| frog.setIsContinuation(false);
|
|
3312 |
1
| symbolTable.put("Frog", frog);
|
|
3313 |
| |
|
3314 |
| |
|
3315 |
1
| TypeData result = className.visit(_etc);
|
|
3316 |
1
| assertTrue("Result should be a PackageData since Frog is not accessible", result instanceof PackageData);
|
|
3317 |
1
| assertEquals("Should have correct name", "Frog", result.getName());
|
|
3318 |
1
| assertEquals("Should still be 2 errors", 2, errors.size());
|
|
3319 |
| |
|
3320 |
| |
|
3321 |
1
| frog.setMav(_publicMav);
|
|
3322 |
1
| assertEquals("Should return Frog", frog, className.visit(_etc));
|
|
3323 |
1
| assertEquals("Should still be 2 errors", 2, errors.size());
|
|
3324 |
| |
|
3325 |
| |
|
3326 |
1
| SimpleNameReference fake = new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "notRealReference"));
|
|
3327 |
1
| assertEquals("Should return package data", "notRealReference", (fake.visit(_etc)).getName());
|
|
3328 |
1
| assertEquals("Should still be just 2 errors", 2, errors.size());
|
|
3329 |
| |
|
3330 |
| |
|
3331 |
1
| SimpleNameReference ambigRef = new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "ambigThing"));
|
|
3332 |
| |
|
3333 |
1
| SymbolData interfaceD = new SymbolData("interface");
|
|
3334 |
1
| interfaceD.setIsContinuation(false);
|
|
3335 |
1
| interfaceD.setInterface(true);
|
|
3336 |
1
| interfaceD.setMav(_publicMav);
|
|
3337 |
| |
|
3338 |
1
| SymbolData classD = new SymbolData("superClass");
|
|
3339 |
1
| classD.setIsContinuation(false);
|
|
3340 |
1
| classD.setMav(_publicMav);
|
|
3341 |
| |
|
3342 |
1
| SymbolData ambigThingI = new SymbolData("ambigThing");
|
|
3343 |
1
| ambigThingI.setIsContinuation(false);
|
|
3344 |
1
| ambigThingI.setInterface(true);
|
|
3345 |
1
| interfaceD.addInnerInterface(ambigThingI);
|
|
3346 |
1
| ambigThingI.setOuterData(interfaceD);
|
|
3347 |
1
| ambigThingI.setMav(_publicStaticMav);
|
|
3348 |
| |
|
3349 |
1
| SymbolData ambigThingC = new SymbolData("ambigThing");
|
|
3350 |
1
| ambigThingC.setIsContinuation(false);
|
|
3351 |
1
| classD.addInnerClass(ambigThingC);
|
|
3352 |
1
| ambigThingC.setOuterData(classD);
|
|
3353 |
1
| ambigThingC.setMav(_publicStaticMav);
|
|
3354 |
| |
|
3355 |
1
| _sd6.addInterface(interfaceD);
|
|
3356 |
1
| _sd6.setSuperClass(classD);
|
|
3357 |
| |
|
3358 |
1
| _sd6.setMav(_publicMav);
|
|
3359 |
1
| _sd6.setIsContinuation(false);
|
|
3360 |
| |
|
3361 |
1
| _etc._data = _sd6;
|
|
3362 |
| |
|
3363 |
1
| assertEquals("Should return null", null, ambigRef.visit(_etc));
|
|
3364 |
1
| assertEquals("Should be 3 errors", 3, errors.size());
|
|
3365 |
1
| assertEquals("Error message should be correct",
|
|
3366 |
| "Ambiguous reference to class or interface ambigThing", |
|
3367 |
| errors.getLast().getFirst()); |
|
3368 |
| } |
|
3369 |
| |
|
3370 |
| |
|
3371 |
1
| public void testForComplexNameReference() {
|
|
3372 |
| |
|
3373 |
| |
|
3374 |
| |
|
3375 |
1
| ComplexNameReference ref1 =
|
|
3376 |
| new ComplexNameReference(SourceInfo.NONE, |
|
3377 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "java")), |
|
3378 |
| new Word(SourceInfo.NONE, "lang")); |
|
3379 |
1
| assertEquals("Should return correct package data", "java.lang", ref1.visit(_etc).getName());
|
|
3380 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
3381 |
| |
|
3382 |
| |
|
3383 |
1
| ComplexNameReference ref2 =
|
|
3384 |
| new ComplexNameReference(SourceInfo.NONE, ref1, new Word(SourceInfo.NONE, "String")); |
|
3385 |
1
| assertTrue("symbol table already contains String", symbolTable.containsKey("java.lang.String"));
|
|
3386 |
1
| SymbolData string = symbolTable.get("java.lang.String");
|
|
3387 |
| |
|
3388 |
| |
|
3389 |
| |
|
3390 |
| |
|
3391 |
| |
|
3392 |
| |
|
3393 |
1
| assertEquals("Should return string", string, ref2.visit(_etc));
|
|
3394 |
| |
|
3395 |
1
| assertEquals("Should still be no errors", 0, errors.size());
|
|
3396 |
| |
|
3397 |
| |
|
3398 |
| |
|
3399 |
| |
|
3400 |
| |
|
3401 |
1
| VariableData myVar = new VariableData("myVar", _publicStaticMav, SymbolData.DOUBLE_TYPE, true, string);
|
|
3402 |
1
| string.addVar(myVar);
|
|
3403 |
1
| ComplexNameReference varRef1 = new ComplexNameReference(SourceInfo.NONE, ref2, new Word(SourceInfo.NONE, "myVar"));
|
|
3404 |
| |
|
3405 |
| |
|
3406 |
1
| assertEquals("Should return Double_Type instance", SymbolData.DOUBLE_TYPE.getInstanceData(), varRef1.visit(_etc));
|
|
3407 |
1
| assertEquals("There should still be no errors", 0, errors.size());
|
|
3408 |
| |
|
3409 |
| |
|
3410 |
1
| myVar.lostValue();
|
|
3411 |
1
| assertEquals("Should return Double_Type instance", SymbolData.DOUBLE_TYPE.getInstanceData(), varRef1.visit(_etc));
|
|
3412 |
1
| assertEquals("There should still be one error", 1, errors.size());
|
|
3413 |
1
| assertEquals("Error message should be correct",
|
|
3414 |
| "You cannot use myVar here, because it may not have been given a value", |
|
3415 |
| errors.getLast().getFirst()); |
|
3416 |
| |
|
3417 |
| |
|
3418 |
1
| myVar.gotValue();
|
|
3419 |
1
| myVar.setMav(_publicMav);
|
|
3420 |
1
| assertEquals("Should return double instance", SymbolData.DOUBLE_TYPE.getInstanceData(), varRef1.visit(_etc));
|
|
3421 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
3422 |
1
| assertEquals("Error message should be correct",
|
|
3423 |
| "Non-static variable myVar cannot be accessed from the static context java.lang.String. " |
|
3424 |
| + "Perhaps you meant to instantiate an instance of java.lang.String", |
|
3425 |
| errors.getLast().getFirst()); |
|
3426 |
| |
|
3427 |
| |
|
3428 |
1
| VariableData stringVar = new VariableData("s", _publicMav, string, true, _etc._data);
|
|
3429 |
1
| _etc._vars.add(stringVar);
|
|
3430 |
1
| ComplexNameReference varRef2 =
|
|
3431 |
| new ComplexNameReference(SourceInfo.NONE, |
|
3432 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "s")), |
|
3433 |
| new Word(SourceInfo.NONE, "myVar")); |
|
3434 |
1
| assertEquals("Should return double instance", SymbolData.DOUBLE_TYPE.getInstanceData(), varRef2.visit(_etc));
|
|
3435 |
1
| assertEquals("Should still just be 2 errors", 2, errors.size());
|
|
3436 |
| |
|
3437 |
| |
|
3438 |
1
| VariableData privateStringVar = new VariableData("ps", _privateMav, string, true, _etc._data);
|
|
3439 |
1
| _etc._vars.add(privateStringVar);
|
|
3440 |
1
| ComplexNameReference varRef25 =
|
|
3441 |
| new ComplexNameReference(SourceInfo.NONE, |
|
3442 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "ps")), |
|
3443 |
| new Word(SourceInfo.NONE, "myVar")); |
|
3444 |
1
| assertEquals("Should return double instance", SymbolData.DOUBLE_TYPE.getInstanceData(), varRef25.visit(_etc));
|
|
3445 |
1
| assertEquals("Should still just be 2 errors", 2, errors.size());
|
|
3446 |
| |
|
3447 |
| |
|
3448 |
1
| string.setVars(new LinkedList<VariableData>());
|
|
3449 |
1
| string.setSuperClass(_sd2);
|
|
3450 |
1
| _sd2.addVar(myVar);
|
|
3451 |
1
| assertEquals("Should return double instance", SymbolData.DOUBLE_TYPE.getInstanceData(), varRef2.visit(_etc));
|
|
3452 |
1
| assertEquals("Should still be 2 errors", 2, errors.size());
|
|
3453 |
| |
|
3454 |
| |
|
3455 |
1
| VariableData vd1 = new VariableData("Mojo", _publicMav, SymbolData.INT_TYPE, true, _sd1);
|
|
3456 |
1
| VariableData vd2 = new VariableData("Santa's Little Helper", _publicMav, _sd1, true, _sd2);
|
|
3457 |
1
| VariableData vd3 = new VariableData("Snowball1", _publicMav, _sd2, true, _sd3);
|
|
3458 |
1
| _sd3.addVar(vd3);
|
|
3459 |
1
| _sd2.addVar(vd2);
|
|
3460 |
1
| _sd1.addVar(vd1);
|
|
3461 |
| |
|
3462 |
1
| ComplexNameReference varRef3 =
|
|
3463 |
| new ComplexNameReference(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, |
|
3464 |
| "Snowball1")), |
|
3465 |
| new Word(SourceInfo.NONE, "Santa's Little Helper")); |
|
3466 |
1
| ComplexNameReference varRef4 =
|
|
3467 |
| new ComplexNameReference(SourceInfo.NONE, varRef3, new Word(SourceInfo.NONE, "Mojo")); |
|
3468 |
| |
|
3469 |
1
| Data oldData = _etc._data;
|
|
3470 |
1
| _etc._data = _sd3;
|
|
3471 |
1
| _etc._vars.add(vd3);
|
|
3472 |
1
| _sd3.setMav(_publicMav);
|
|
3473 |
1
| _sd1.setMav(_publicMav);
|
|
3474 |
1
| _sd2.setMav(_publicMav);
|
|
3475 |
| |
|
3476 |
1
| TypeData result = varRef4.visit(_etc);
|
|
3477 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), result);
|
|
3478 |
1
| assertEquals("Should still be 2 errors", 2, errors.size());
|
|
3479 |
| |
|
3480 |
1
| _etc._data = oldData;
|
|
3481 |
| |
|
3482 |
| |
|
3483 |
1
| SymbolData inner = new SymbolData("java.lang.String$Inner");
|
|
3484 |
1
| inner.setPackage("java.lang");
|
|
3485 |
1
| inner.setIsContinuation(false);
|
|
3486 |
1
| inner.setOuterData(string);
|
|
3487 |
1
| string.addInnerClass(inner);
|
|
3488 |
| |
|
3489 |
| |
|
3490 |
1
| ComplexNameReference innerRef0 =
|
|
3491 |
| new ComplexNameReference(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, |
|
3492 |
| new Word(SourceInfo.NONE, "s")), |
|
3493 |
| new Word(SourceInfo.NONE, "Inner")); |
|
3494 |
1
| assertEquals("Should return null", null, innerRef0.visit(_etc));
|
|
3495 |
1
| assertEquals("Should be 3 errors", 3, errors.size());
|
|
3496 |
1
| assertEquals("Error message should be correct",
|
|
3497 |
| "The class or interface java.lang.String.Inner is package protected because there is no access " |
|
3498 |
| + "specifier and cannot be accessed from i.like.monkey", |
|
3499 |
| errors.getLast().getFirst()); |
|
3500 |
| |
|
3501 |
1
| inner.setMav(_publicMav);
|
|
3502 |
| |
|
3503 |
| |
|
3504 |
| |
|
3505 |
1
| ComplexNameReference innerRef1 =
|
|
3506 |
| new ComplexNameReference(SourceInfo.NONE, ref2, new Word(SourceInfo.NONE, "Inner")); |
|
3507 |
1
| assertEquals("Should return inner", inner, innerRef1.visit(_etc));
|
|
3508 |
1
| assertEquals("Should be 4 errors", 4, errors.size());
|
|
3509 |
1
| assertEquals("Error message should be correct",
|
|
3510 |
| "Non-static inner class java.lang.String.Inner cannot be accessed from this context. " |
|
3511 |
| + "Perhaps you meant to instantiate it", errors.getLast().getFirst()); |
|
3512 |
| |
|
3513 |
| |
|
3514 |
1
| ComplexNameReference innerRef2 =
|
|
3515 |
| new ComplexNameReference(SourceInfo.NONE, |
|
3516 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "s")), |
|
3517 |
| new Word(SourceInfo.NONE, "Inner")); |
|
3518 |
1
| assertEquals("Should return inner", inner, innerRef2.visit(_etc));
|
|
3519 |
1
| assertEquals("Should still be 5 errors", 5, errors.size());
|
|
3520 |
1
| assertEquals("Error message should be correct",
|
|
3521 |
| "Non-static inner class java.lang.String.Inner cannot be accessed from this context. " |
|
3522 |
| + "Perhaps you meant to instantiate it", |
|
3523 |
| errors.getLast().getFirst()); |
|
3524 |
| |
|
3525 |
| |
|
3526 |
1
| inner.setMav(_publicStaticMav);
|
|
3527 |
1
| assertEquals("Should return inner", inner, innerRef2.visit(_etc));
|
|
3528 |
1
| assertEquals("Should be 6 errors", 6, errors.size());
|
|
3529 |
1
| assertEquals("Error message should be correct",
|
|
3530 |
| "You cannot reference the static inner class java.lang.String.Inner from an instance of " |
|
3531 |
| + "java.lang.String. Perhaps you meant to say java.lang.String.Inner", |
|
3532 |
| errors.getLast().getFirst()); |
|
3533 |
| |
|
3534 |
| |
|
3535 |
| |
|
3536 |
1
| ComplexNameReference noSense =
|
|
3537 |
| new ComplexNameReference(SourceInfo.NONE, ref2, new Word(SourceInfo.NONE, "nonsense")); |
|
3538 |
1
| assertEquals("Should return null", null, noSense.visit(_etc));
|
|
3539 |
1
| assertEquals("Should be 7 errors", 7, errors.size());
|
|
3540 |
1
| assertEquals("Error message should be correct", "Could not resolve nonsense from the context of java.lang.String",
|
|
3541 |
| errors.getLast().getFirst()); |
|
3542 |
| |
|
3543 |
| |
|
3544 |
1
| ComplexNameReference ambigRef =
|
|
3545 |
| new ComplexNameReference(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, |
|
3546 |
| new Word(SourceInfo.NONE, "cebu")), |
|
3547 |
| new Word(SourceInfo.NONE, "ambigThing")); |
|
3548 |
| |
|
3549 |
1
| SymbolData interfaceD = new SymbolData("interface");
|
|
3550 |
1
| interfaceD.setIsContinuation(false);
|
|
3551 |
1
| interfaceD.setInterface(true);
|
|
3552 |
1
| interfaceD.setMav(_publicMav);
|
|
3553 |
| |
|
3554 |
1
| SymbolData classD = new SymbolData("superClass");
|
|
3555 |
1
| classD.setIsContinuation(false);
|
|
3556 |
1
| classD.setMav(_publicMav);
|
|
3557 |
| |
|
3558 |
1
| SymbolData ambigThingI = new SymbolData("ambigThing");
|
|
3559 |
1
| ambigThingI.setIsContinuation(false);
|
|
3560 |
1
| ambigThingI.setInterface(true);
|
|
3561 |
1
| interfaceD.addInnerInterface(ambigThingI);
|
|
3562 |
1
| ambigThingI.setOuterData(interfaceD);
|
|
3563 |
1
| ambigThingI.setMav(_publicStaticMav);
|
|
3564 |
| |
|
3565 |
1
| SymbolData ambigThingC = new SymbolData("ambigThing");
|
|
3566 |
1
| ambigThingC.setIsContinuation(false);
|
|
3567 |
1
| classD.addInnerClass(ambigThingC);
|
|
3568 |
1
| ambigThingC.setOuterData(classD);
|
|
3569 |
1
| ambigThingC.setMav(_publicStaticMav);
|
|
3570 |
| |
|
3571 |
1
| _sd6.addInterface(interfaceD);
|
|
3572 |
1
| _sd6.setSuperClass(classD);
|
|
3573 |
| |
|
3574 |
1
| symbolTable.put("cebu", _sd6);
|
|
3575 |
1
| _sd6.setMav(_publicMav);
|
|
3576 |
1
| _sd6.setIsContinuation(false);
|
|
3577 |
| |
|
3578 |
1
| assertEquals("Should return null", null, ambigRef.visit(_etc));
|
|
3579 |
1
| assertEquals("Should be 8 errors", 8, errors.size());
|
|
3580 |
1
| assertEquals("Error message should be correct",
|
|
3581 |
| "Ambiguous reference to class or interface ambigThing", |
|
3582 |
| errors.getLast().getFirst()); |
|
3583 |
| |
|
3584 |
| |
|
3585 |
1
| inner.setMav(_publicStaticMav);
|
|
3586 |
1
| string.setMav(_privateMav);
|
|
3587 |
| |
|
3588 |
1
| assertEquals("Should return inner", inner, innerRef1.visit(_etc));
|
|
3589 |
1
| assertEquals("Should be 9 errors", 9, errors.size());
|
|
3590 |
1
| assertEquals("Error message should be correct",
|
|
3591 |
| "The class or interface java.lang.String in java.lang.String is private and cannot be accessed from i.like.monkey", |
|
3592 |
| errors.getLast().getFirst()); |
|
3593 |
| } |
|
3594 |
| |
|
3595 |
| |
|
3596 |
1
| public void testForSimpleThisReference() {
|
|
3597 |
1
| SimpleThisReference str = new SimpleThisReference(SourceInfo.NONE);
|
|
3598 |
| |
|
3599 |
| |
|
3600 |
1
| assertEquals("Should return i.like.monkey instance", _etc._data.getSymbolData().getInstanceData(), str.visit(_etc));
|
|
3601 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
3602 |
| |
|
3603 |
| |
|
3604 |
1
| MethodData sm = new MethodData("staticMethod", new VariableData[0]);
|
|
3605 |
1
| sm.setMav(_publicStaticMav);
|
|
3606 |
1
| sm.setOuterData(_etc._data);
|
|
3607 |
1
| _etc._data = sm;
|
|
3608 |
| |
|
3609 |
1
| assertEquals("Should return i.like.monkey instance", _etc._data.getSymbolData().getInstanceData(),
|
|
3610 |
| str.visit(_etc)); |
|
3611 |
1
| assertEquals("Should be one errors", 1, errors.size());
|
|
3612 |
1
| assertEquals("Error message should be correct", "'this' cannot be referenced from within a static method",
|
|
3613 |
| errors.getLast().getFirst()); |
|
3614 |
| } |
|
3615 |
| |
|
3616 |
| |
|
3617 |
1
| public void testForComplexThisReferenceOnly() {
|
|
3618 |
1
| ComplexThisReference ctr =
|
|
3619 |
| new ComplexThisReference(SourceInfo.NONE, |
|
3620 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "context"))); |
|
3621 |
| |
|
3622 |
| |
|
3623 |
1
| assertEquals("Should return null", null, _etc.forComplexThisReferenceOnly(ctr, null));
|
|
3624 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
3625 |
| |
|
3626 |
| |
|
3627 |
1
| assertEquals("Should return null", null, _etc.forComplexThisReferenceOnly(ctr, new PackageData("context")));
|
|
3628 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
3629 |
1
| assertEquals("Error message should be correct","Could not resolve symbol context" , errors.getLast().getFirst());
|
|
3630 |
| |
|
3631 |
| |
|
3632 |
1
| SymbolData contextClass = new SymbolData("context");
|
|
3633 |
1
| contextClass.setIsContinuation(false);
|
|
3634 |
1
| contextClass.setMav(_publicMav);
|
|
3635 |
1
| assertEquals("Should return instance of this", contextClass.getInstanceData(),
|
|
3636 |
| _etc.forComplexThisReferenceOnly(ctr, contextClass)); |
|
3637 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
3638 |
1
| assertEquals("The error message should be correct", "You cannot reference context.this from here, "
|
|
3639 |
| + "because context is not an outer class of i.like.monkey", |
|
3640 |
| errors.getLast().getFirst()); |
|
3641 |
| |
|
3642 |
| |
|
3643 |
1
| _etc._data.setOuterData(contextClass);
|
|
3644 |
1
| contextClass.addInnerClass(_etc._data.getSymbolData());
|
|
3645 |
1
| assertEquals("Should return instance of this", contextClass.getInstanceData(),
|
|
3646 |
| _etc.forComplexThisReferenceOnly(ctr, contextClass)); |
|
3647 |
1
| assertEquals("Should still be 2 errors", 2, errors.size());
|
|
3648 |
| |
|
3649 |
| |
|
3650 |
1
| MethodData sm = new MethodData("staticMethod", new VariableData[0]);
|
|
3651 |
1
| sm.setMav(_publicStaticMav);
|
|
3652 |
1
| sm.setOuterData(_etc._data);
|
|
3653 |
1
| _etc._data = sm;
|
|
3654 |
1
| assertEquals("Should return instance of this", contextClass.getInstanceData(),
|
|
3655 |
| _etc.forComplexThisReferenceOnly(ctr, contextClass)); |
|
3656 |
1
| assertEquals("Should be 3 errors", 3, errors.size());
|
|
3657 |
1
| assertEquals("The error message should be correct", "'this' cannot be referenced from within a static method",
|
|
3658 |
| errors.getLast().getFirst()); |
|
3659 |
| |
|
3660 |
| |
|
3661 |
1
| _etc._data = sm.getOuterData();
|
|
3662 |
1
| assertEquals("Should return instance of this", contextClass.getInstanceData(),
|
|
3663 |
| _etc.forComplexThisReferenceOnly(ctr, contextClass.getInstanceData())); |
|
3664 |
1
| assertEquals("Should be 4 errors", 4, errors.size());
|
|
3665 |
1
| assertEquals("The error message should be correct",
|
|
3666 |
| "'this' can only be referenced from a type name, but you have specified an instance of that type.", |
|
3667 |
| errors.getLast().getFirst()); |
|
3668 |
| |
|
3669 |
| |
|
3670 |
1
| _etc._data.getSymbolData().addModifier("static");
|
|
3671 |
1
| assertEquals("Should return instance of this", contextClass.getInstanceData(),
|
|
3672 |
| _etc.forComplexThisReferenceOnly(ctr, contextClass)); |
|
3673 |
1
| assertEquals("Should be 5 errors", 5, errors.size());
|
|
3674 |
1
| assertEquals("Error message should be correct",
|
|
3675 |
| "You cannot reference context.this from here, because i.like.monkey or one of its enclosing " |
|
3676 |
| + "classes is static. Thus, an enclosing instance of context does not exist", |
|
3677 |
| errors.getLast().getFirst()); |
|
3678 |
| } |
|
3679 |
| |
|
3680 |
1
| public void testForSimpleSuperReference() {
|
|
3681 |
1
| SimpleSuperReference ssr = new SimpleSuperReference(SourceInfo.NONE);
|
|
3682 |
1
| _sd1.setSuperClass(_sd2);
|
|
3683 |
| |
|
3684 |
| |
|
3685 |
1
| assertEquals("Should return _sd2", _sd2.getInstanceData(), ssr.visit(_etc));
|
|
3686 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
3687 |
| |
|
3688 |
| |
|
3689 |
1
| MethodData sm = new MethodData("staticMethod", new VariableData[0]);
|
|
3690 |
1
| sm.setMav(_publicStaticMav);
|
|
3691 |
1
| sm.setOuterData(_etc._data);
|
|
3692 |
1
| _etc._data = sm;
|
|
3693 |
| |
|
3694 |
1
| assertEquals("Should return _sd2", _sd2.getInstanceData(), ssr.visit(_etc));
|
|
3695 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
3696 |
1
| assertEquals("Error message should be correct", "'super' cannot be referenced from within a static method",
|
|
3697 |
| errors.getLast().getFirst()); |
|
3698 |
| } |
|
3699 |
| |
|
3700 |
| |
|
3701 |
1
| public void testForComplexSuperReference() {
|
|
3702 |
1
| ComplexSuperReference csr =
|
|
3703 |
| new ComplexSuperReference(SourceInfo.NONE, |
|
3704 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "context"))); |
|
3705 |
| |
|
3706 |
| |
|
3707 |
1
| assertEquals("Should return null", null, _etc.forComplexSuperReferenceOnly(csr, null));
|
|
3708 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
3709 |
| |
|
3710 |
| |
|
3711 |
1
| assertEquals("Should return null", null, _etc.forComplexSuperReferenceOnly(csr, new PackageData("context")));
|
|
3712 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
3713 |
1
| assertEquals("Error message should be correct","Could not resolve symbol context" , errors.getLast().getFirst());
|
|
3714 |
| |
|
3715 |
| |
|
3716 |
1
| SymbolData contextClass = new SymbolData("context");
|
|
3717 |
1
| contextClass.setIsContinuation(false);
|
|
3718 |
1
| contextClass.setMav(_publicMav);
|
|
3719 |
1
| contextClass.setSuperClass(_sd2);
|
|
3720 |
1
| assertEquals("Should return instance of super", _sd2.getInstanceData(),
|
|
3721 |
| _etc.forComplexSuperReferenceOnly(csr, contextClass)); |
|
3722 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
3723 |
1
| assertEquals("The error message should be correct",
|
|
3724 |
| "You cannot reference context.super from here, because context is not an outer class of i.like.monkey", |
|
3725 |
| errors.getLast().getFirst()); |
|
3726 |
| |
|
3727 |
| |
|
3728 |
| |
|
3729 |
1
| _etc._data.setOuterData(contextClass);
|
|
3730 |
1
| contextClass.addInnerClass(_etc._data.getSymbolData());
|
|
3731 |
1
| assertEquals("Should return instance of super", _sd2.getInstanceData(),
|
|
3732 |
| _etc.forComplexSuperReferenceOnly(csr, contextClass)); |
|
3733 |
1
| assertEquals("Should still be 2 errors", 2, errors.size());
|
|
3734 |
| |
|
3735 |
| |
|
3736 |
1
| MethodData sm = new MethodData("staticMethod", new VariableData[0]);
|
|
3737 |
1
| sm.setMav(_publicStaticMav);
|
|
3738 |
1
| sm.setOuterData(_etc._data);
|
|
3739 |
1
| _etc._data = sm;
|
|
3740 |
1
| assertEquals("Should return instance of super", _sd2.getInstanceData(),
|
|
3741 |
| _etc.forComplexSuperReferenceOnly(csr, contextClass)); |
|
3742 |
1
| assertEquals("Should be 3 errors", 3, errors.size());
|
|
3743 |
1
| assertEquals("The error message should be correct", "'super' cannot be referenced from within a static method",
|
|
3744 |
| errors.getLast().getFirst()); |
|
3745 |
| |
|
3746 |
| |
|
3747 |
1
| _etc._data = sm.getOuterData();
|
|
3748 |
1
| assertEquals("Should return instance of super", _sd2.getInstanceData(),
|
|
3749 |
| _etc.forComplexSuperReferenceOnly(csr, contextClass.getInstanceData())); |
|
3750 |
1
| assertEquals("Should be 4 errors", 4, errors.size());
|
|
3751 |
1
| assertEquals("The error message should be correct", "'super' can only be referenced from a type name, "
|
|
3752 |
| + "but you have specified an instance of that type.", |
|
3753 |
| errors.getLast().getFirst()); |
|
3754 |
| |
|
3755 |
| |
|
3756 |
1
| _etc._data.getSymbolData().addModifier("static");
|
|
3757 |
1
| assertEquals("Should return instance of super", _sd2.getInstanceData(),
|
|
3758 |
| _etc.forComplexSuperReferenceOnly(csr, contextClass)); |
|
3759 |
1
| assertEquals("Should be 5 errors", 5, errors.size());
|
|
3760 |
1
| assertEquals("Error message should be correct",
|
|
3761 |
| "You cannot reference context.super from here, because i.like.monkey or one of its enclosing " |
|
3762 |
| + "classes is static. Thus, an enclosing instance of context does not exist", |
|
3763 |
| errors.getLast().getFirst()); |
|
3764 |
| } |
|
3765 |
| |
|
3766 |
1
| public void testForArrayAccessOnly() {
|
|
3767 |
1
| ArrayAccess aa =
|
|
3768 |
| new ArrayAccess(SourceInfo.NONE, NULL_LITERAL, NULL_LITERAL); |
|
3769 |
| |
|
3770 |
1
| Hashtable<SymbolData, LanguageLevelVisitor> testNewSDs = LanguageLevelConverter._newSDs;
|
|
3771 |
1
| LanguageLevelVisitor testLLVisitor =
|
|
3772 |
| new LanguageLevelVisitor(_etc._file, |
|
3773 |
| _etc._package, |
|
3774 |
| null, |
|
3775 |
| _etc._importedFiles, |
|
3776 |
| _etc._importedPackages, |
|
3777 |
| new HashSet<String>(), |
|
3778 |
| new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(), |
|
3779 |
| new LinkedList<Command>()); |
|
3780 |
| |
|
3781 |
| |
|
3782 |
1
| ArrayData ad = new ArrayData(SymbolData.INT_TYPE, testLLVisitor, SourceInfo.NONE);
|
|
3783 |
| |
|
3784 |
1
| assertEquals("should return int", SymbolData.INT_TYPE.getInstanceData(),
|
|
3785 |
| _etc.forArrayAccessOnly(aa, ad.getInstanceData(), SymbolData.INT_TYPE.getInstanceData())); |
|
3786 |
1
| assertEquals("should return int", SymbolData.INT_TYPE.getInstanceData(),
|
|
3787 |
| _etc.forArrayAccessOnly(aa, ad.getInstanceData(), SymbolData.CHAR_TYPE.getInstanceData())); |
|
3788 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
3789 |
| |
|
3790 |
| |
|
3791 |
1
| assertEquals("Should return null", null, _etc.forArrayAccessOnly(aa, null, SymbolData.INT_TYPE));
|
|
3792 |
1
| assertEquals("Should return null", null, _etc.forArrayAccessOnly(aa, SymbolData.INT_TYPE, null));
|
|
3793 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
3794 |
| |
|
3795 |
| |
|
3796 |
1
| PackageData pd = new PackageData("bad_reference");
|
|
3797 |
1
| assertEquals("Should return null", null, _etc.forArrayAccessOnly(aa, pd, SymbolData.INT_TYPE));
|
|
3798 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
3799 |
1
| assertEquals("Error message should be correct",
|
|
3800 |
| "Could not resolve symbol bad_reference", |
|
3801 |
| errors.getLast().getFirst()); |
|
3802 |
| |
|
3803 |
| |
|
3804 |
| |
|
3805 |
1
| assertEquals("Should return null", null, _etc.forArrayAccessOnly(aa, SymbolData.INT_TYPE, pd));
|
|
3806 |
1
| assertEquals("Should still be 1 error", 1, errors.size());
|
|
3807 |
1
| assertEquals("Error message should be correct",
|
|
3808 |
| "Could not resolve symbol bad_reference", |
|
3809 |
| errors.getLast().getFirst()); |
|
3810 |
| |
|
3811 |
| |
|
3812 |
1
| assertEquals("Should return int",
|
|
3813 |
| SymbolData.INT_TYPE.getInstanceData(), |
|
3814 |
| _etc.forArrayAccessOnly(aa, ad, SymbolData.INT_TYPE.getInstanceData())); |
|
3815 |
1
| assertEquals("Should now be 2 errors", 2, errors.size());
|
|
3816 |
1
| assertEquals("Error message should be correct",
|
|
3817 |
| "You cannot access an array element of a type name. Perhaps you meant to create " + |
|
3818 |
| "a new instance of int[]", |
|
3819 |
| errors.get(1).getFirst()); |
|
3820 |
| |
|
3821 |
| |
|
3822 |
1
| assertEquals("Should return char", SymbolData.CHAR_TYPE.getInstanceData(),
|
|
3823 |
| _etc.forArrayAccessOnly(aa, SymbolData.CHAR_TYPE.getInstanceData(), |
|
3824 |
| SymbolData.INT_TYPE.getInstanceData())); |
|
3825 |
1
| assertEquals("Should now be 3 errors", 3, errors.size());
|
|
3826 |
1
| assertEquals("Error message should be correct",
|
|
3827 |
| "The variable referred to by this array access is a char, not an array", |
|
3828 |
| errors.get(2).getFirst()); |
|
3829 |
| |
|
3830 |
| |
|
3831 |
1
| assertEquals("should return int", SymbolData.INT_TYPE.getInstanceData(),
|
|
3832 |
| _etc.forArrayAccessOnly(aa, ad.getInstanceData(), SymbolData.INT_TYPE)); |
|
3833 |
1
| assertEquals("Should now be 4 errors", 4, errors.size());
|
|
3834 |
1
| assertEquals("Error message should be correct",
|
|
3835 |
| "You have used a type name in place of an array index. Perhaps you meant to create " + |
|
3836 |
| "a new instance of int", |
|
3837 |
| errors.get(3).getFirst()); |
|
3838 |
| |
|
3839 |
| |
|
3840 |
1
| assertEquals("should return int", SymbolData.INT_TYPE.getInstanceData(),
|
|
3841 |
| _etc.forArrayAccessOnly(aa, ad.getInstanceData(), SymbolData.DOUBLE_TYPE.getInstanceData())); |
|
3842 |
1
| assertEquals("Should now be 5 errors", 5, errors.size());
|
|
3843 |
1
| assertEquals("Error message should be correct",
|
|
3844 |
| "You cannot reference an array element with an index of type double. Instead, you must use an int", |
|
3845 |
| errors.get(4).getFirst()); |
|
3846 |
| } |
|
3847 |
| |
|
3848 |
| |
|
3849 |
1
| public void testLiterals() {
|
|
3850 |
1
| StringLiteral sl = new StringLiteral(SourceInfo.NONE, "string literal!");
|
|
3851 |
1
| IntegerLiteral il = new IntegerLiteral(SourceInfo.NONE, 4);
|
|
3852 |
1
| LongLiteral ll = new LongLiteral(SourceInfo.NONE, 5);
|
|
3853 |
1
| FloatLiteral fl = new FloatLiteral(SourceInfo.NONE, 1.2f);
|
|
3854 |
1
| DoubleLiteral dl = new DoubleLiteral(SourceInfo.NONE, 4.2);
|
|
3855 |
1
| CharLiteral cl = new CharLiteral(SourceInfo.NONE, 'c');
|
|
3856 |
1
| BooleanLiteral bl = new BooleanLiteral(SourceInfo.NONE, true);
|
|
3857 |
1
| ClassLiteral csl =
|
|
3858 |
| new ClassLiteral(SourceInfo.NONE, new ClassOrInterfaceType(SourceInfo.NONE, "monkey", new Type[0])); |
|
3859 |
| |
|
3860 |
1
| SymbolData string = new SymbolData("java.lang.String");
|
|
3861 |
1
| string.setIsContinuation(false);
|
|
3862 |
1
| string.setPackage("java.lang");
|
|
3863 |
1
| string.setMav(_publicMav);
|
|
3864 |
1
| SymbolData classD = new SymbolData("java.lang.Class");
|
|
3865 |
1
| classD.setIsContinuation(false);
|
|
3866 |
1
| classD.setPackage("java.lang");
|
|
3867 |
1
| classD.setMav(_publicMav);
|
|
3868 |
| |
|
3869 |
1
| symbolTable.put("java.lang.String", string);
|
|
3870 |
1
| symbolTable.put("java.lang.Class", classD);
|
|
3871 |
| |
|
3872 |
1
| assertEquals("Should return string", string.getInstanceData(), sl.visit(_etc));
|
|
3873 |
1
| assertEquals("Should return int", SymbolData.INT_TYPE.getInstanceData(), il.visit(_etc));
|
|
3874 |
1
| assertEquals("Should return long", SymbolData.LONG_TYPE.getInstanceData(), ll.visit(_etc));
|
|
3875 |
1
| assertEquals("Should return float", SymbolData.FLOAT_TYPE.getInstanceData(), fl.visit(_etc));
|
|
3876 |
1
| assertEquals("Should return double", SymbolData.DOUBLE_TYPE.getInstanceData(), dl.visit(_etc));
|
|
3877 |
1
| assertEquals("Should return char", SymbolData.CHAR_TYPE.getInstanceData(), cl.visit(_etc));
|
|
3878 |
1
| assertEquals("Should return boolean", SymbolData.BOOLEAN_TYPE.getInstanceData(), bl.visit(_etc));
|
|
3879 |
1
| assertEquals("Should return null type", SymbolData.NULL_TYPE.getInstanceData(), NULL_LITERAL.visit(_etc));
|
|
3880 |
1
| assertEquals("Should return class", classD.getInstanceData(), _etc.forClassLiteralOnly(csl));
|
|
3881 |
| } |
|
3882 |
| |
|
3883 |
| |
|
3884 |
1
| public void testForParenthesizedOnly() {
|
|
3885 |
1
| Parenthesized p = new Parenthesized(SourceInfo.NONE, NULL_LITERAL);
|
|
3886 |
| |
|
3887 |
| |
|
3888 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
3889 |
| _etc.forParenthesizedOnly(p, SymbolData.BOOLEAN_TYPE.getInstanceData())); |
|
3890 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
3891 |
| |
|
3892 |
| |
|
3893 |
1
| assertEquals("Should return null", null, _etc.forParenthesizedOnly(p, null));
|
|
3894 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
3895 |
| |
|
3896 |
| |
|
3897 |
1
| assertEquals("Should return null", null, _etc.forParenthesizedOnly(p, new PackageData("bob")));
|
|
3898 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
3899 |
1
| assertEquals("Error message should be correct","Could not resolve symbol bob" , errors.getLast().getFirst());
|
|
3900 |
| |
|
3901 |
| |
|
3902 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(),
|
|
3903 |
| _etc.forParenthesizedOnly(p, SymbolData.INT_TYPE)); |
|
3904 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
3905 |
1
| assertEquals("Error message should be correct",
|
|
3906 |
| "This class or interface name cannot appear in parentheses. Perhaps you meant to create a new " |
|
3907 |
| + "instance of int" , |
|
3908 |
| errors.getLast().getFirst()); |
|
3909 |
| |
|
3910 |
| |
|
3911 |
| } |
|
3912 |
| |
|
3913 |
1
| public void testMethodInvocationHelper() {
|
|
3914 |
1
| ParenthesizedExpressionList exp1 = new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]);
|
|
3915 |
1
| MethodInvocation noArgs = new SimpleMethodInvocation(SourceInfo.NONE, new Word(SourceInfo.NONE, "myName"), exp1);
|
|
3916 |
1
| ParenthesizedExpressionList exp2 =
|
|
3917 |
| new ParenthesizedExpressionList(SourceInfo.NONE, |
|
3918 |
| new Expression[]{new SimpleNameReference(SourceInfo.NONE, |
|
3919 |
| new Word(SourceInfo.NONE, "int"))}); |
|
3920 |
1
| MethodInvocation typeArg = new SimpleMethodInvocation(SourceInfo.NONE, new Word(SourceInfo.NONE, "myName"), exp2);
|
|
3921 |
1
| ParenthesizedExpressionList exp3 =
|
|
3922 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[]{new IntegerLiteral(SourceInfo.NONE, 5)}); |
|
3923 |
1
| MethodInvocation oneIntArg =
|
|
3924 |
| new SimpleMethodInvocation(SourceInfo.NONE, new Word(SourceInfo.NONE, "myName"), exp3); |
|
3925 |
1
| ParenthesizedExpressionList exp4 =
|
|
3926 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[]{new DoubleLiteral(SourceInfo.NONE, 4.2)}); |
|
3927 |
1
| MethodInvocation oneDoubleArg =
|
|
3928 |
| new SimpleMethodInvocation(SourceInfo.NONE, new Word(SourceInfo.NONE, "myName"), exp4); |
|
3929 |
| |
|
3930 |
| |
|
3931 |
1
| MethodData noArgsM =
|
|
3932 |
| new MethodData("myName", _publicMav, new TypeParameter[0], SymbolData.BOOLEAN_TYPE, new VariableData[0], |
|
3933 |
| new String[0], _sd2, NULL_LITERAL); |
|
3934 |
1
| _sd2.addMethod(noArgsM);
|
|
3935 |
1
| assertEquals("Should return boolean instance",
|
|
3936 |
| SymbolData.BOOLEAN_TYPE.getInstanceData(), |
|
3937 |
| _etc.methodInvocationHelper(noArgs, _sd2.getInstanceData())); |
|
3938 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
3939 |
| |
|
3940 |
| |
|
3941 |
1
| assertEquals("Should return null", null, _etc.methodInvocationHelper(oneIntArg, _sd2.getInstanceData()));
|
|
3942 |
1
| assertEquals("Should be one error", 1, errors.size());
|
|
3943 |
1
| assertEquals("Error message should be correct", "No method found in class " + _sd2.getName()
|
|
3944 |
| + " with signature: myName(int).", |
|
3945 |
| errors.getLast().getFirst()); |
|
3946 |
| |
|
3947 |
| |
|
3948 |
1
| MethodData intArg =
|
|
3949 |
| new MethodData("myName", _publicMav, new TypeParameter[0], SymbolData.LONG_TYPE, |
|
3950 |
| new VariableData[] {new VariableData(SymbolData.INT_TYPE)}, new String[0], _sd2, NULL_LITERAL); |
|
3951 |
1
| _sd2.addMethod(intArg);
|
|
3952 |
1
| assertEquals("Should return long instance", SymbolData.LONG_TYPE.getInstanceData(), _etc.methodInvocationHelper(typeArg, _sd2.getInstanceData()));
|
|
3953 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
3954 |
1
| assertEquals("Error message should be correct", "Cannot pass a class or interface name as an argument to a method. Perhaps you meant to create an instance or use int.class", errors.getLast().getFirst());
|
|
3955 |
| |
|
3956 |
| |
|
3957 |
1
| assertEquals("Should return long instance", SymbolData.LONG_TYPE.getInstanceData(),
|
|
3958 |
| _etc.methodInvocationHelper(oneIntArg, _sd2.getInstanceData())); |
|
3959 |
1
| assertEquals("Should still be 2 errors", 2, errors.size());
|
|
3960 |
| |
|
3961 |
| |
|
3962 |
1
| assertEquals("Should return long instance", SymbolData.LONG_TYPE.getInstanceData(),
|
|
3963 |
| _etc.methodInvocationHelper(oneIntArg, _sd2)); |
|
3964 |
1
| assertEquals("Should be 3 errors", 3, errors.size());
|
|
3965 |
1
| assertEquals("Error message should be correct",
|
|
3966 |
| "Cannot access the non-static method myName from a static context", |
|
3967 |
| errors.getLast().getFirst()); |
|
3968 |
| |
|
3969 |
| |
|
3970 |
| |
|
3971 |
1
| MethodData doubleArg =
|
|
3972 |
| new MethodData("myName", _publicStaticMav, new TypeParameter[0], SymbolData.CHAR_TYPE, |
|
3973 |
| new VariableData[] {new VariableData(SymbolData.DOUBLE_TYPE)}, new String[0], _sd2, NULL_LITERAL); |
|
3974 |
1
| _sd2.addMethod(doubleArg);
|
|
3975 |
1
| assertEquals("Should return char instance", SymbolData.CHAR_TYPE.getInstanceData(),
|
|
3976 |
| _etc.methodInvocationHelper(oneDoubleArg, _sd2)); |
|
3977 |
1
| assertEquals("Should still be 3 errors", 3, errors.size());
|
|
3978 |
| } |
|
3979 |
| |
|
3980 |
1
| public void testForSimpleMethodInvocation() {
|
|
3981 |
1
| ParenthesizedExpressionList pel1 = new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]);
|
|
3982 |
1
| MethodInvocation noArgs = new SimpleMethodInvocation(SourceInfo.NONE, new Word(SourceInfo.NONE, "myName"), pel1);
|
|
3983 |
1
| ParenthesizedExpressionList pel2 =
|
|
3984 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[]{new IntegerLiteral(SourceInfo.NONE, 5)}); |
|
3985 |
1
| MethodInvocation oneIntArg =
|
|
3986 |
| new SimpleMethodInvocation(SourceInfo.NONE, new Word(SourceInfo.NONE, "myName"), pel2); |
|
3987 |
1
| ParenthesizedExpressionList pel3 =
|
|
3988 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[]{new DoubleLiteral(SourceInfo.NONE, 4.2)}); |
|
3989 |
1
| MethodInvocation oneDoubleArg =
|
|
3990 |
| new SimpleMethodInvocation(SourceInfo.NONE, new Word(SourceInfo.NONE, "myName"), pel3); |
|
3991 |
| |
|
3992 |
| |
|
3993 |
1
| assertEquals("Should return null", null, noArgs.visit(_etc));
|
|
3994 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
3995 |
1
| assertEquals("Error message should be correct", "No method found in class i.like.monkey with signature: myName().",
|
|
3996 |
| errors.getLast().getFirst()); |
|
3997 |
| |
|
3998 |
| |
|
3999 |
1
| MethodData noArgsM =
|
|
4000 |
| new MethodData("myName", _publicMav, new TypeParameter[0], SymbolData.BOOLEAN_TYPE, |
|
4001 |
| new VariableData[0], new String[0], _sd1, NULL_LITERAL); |
|
4002 |
1
| _sd1.addMethod(noArgsM);
|
|
4003 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(), noArgs.visit(_etc));
|
|
4004 |
1
| assertEquals("Should still just be 1 error", 1, errors.size());
|
|
4005 |
| |
|
4006 |
| |
|
4007 |
1
| MethodData doubleArg =
|
|
4008 |
| new MethodData("myName", _publicStaticMav, new TypeParameter[0], SymbolData.CHAR_TYPE, |
|
4009 |
| new VariableData[] {new VariableData(SymbolData.DOUBLE_TYPE)}, new String[0], _sd1, NULL_LITERAL); |
|
4010 |
1
| _sd1.addMethod(doubleArg);
|
|
4011 |
| |
|
4012 |
1
| assertEquals("Should return char instance", SymbolData.CHAR_TYPE.getInstanceData(), oneDoubleArg.visit(_etc));
|
|
4013 |
1
| assertEquals("Should still be just 1 error", 1, errors.size());
|
|
4014 |
| |
|
4015 |
| |
|
4016 |
1
| _etc._data = doubleArg;
|
|
4017 |
1
| assertEquals("Should return char instance", SymbolData.CHAR_TYPE.getInstanceData(), oneDoubleArg.visit(_etc));
|
|
4018 |
1
| assertEquals("Should still be just 1 error", 1, errors.size());
|
|
4019 |
| |
|
4020 |
| |
|
4021 |
1
| MethodData intArg =
|
|
4022 |
| new MethodData("myName", _publicMav, new TypeParameter[0], SymbolData.LONG_TYPE, |
|
4023 |
| new VariableData[] {new VariableData(SymbolData.INT_TYPE)}, new String[0], _sd1, NULL_LITERAL); |
|
4024 |
1
| _sd1.addMethod(intArg);
|
|
4025 |
1
| assertEquals("Should return long instance", SymbolData.LONG_TYPE.getInstanceData().getName(),
|
|
4026 |
| oneIntArg.visit(_etc).getName()); |
|
4027 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
4028 |
1
| assertEquals("Error message should be correct", "Cannot access the non-static method myName from a static context",
|
|
4029 |
| errors.getLast().getFirst()); |
|
4030 |
| |
|
4031 |
| } |
|
4032 |
| |
|
4033 |
| |
|
4034 |
1
| public void testForComplexMethodInvocation() {
|
|
4035 |
1
| MethodInvocation staticNoArgs =
|
|
4036 |
| new ComplexMethodInvocation(SourceInfo.NONE, |
|
4037 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "giraffe")), |
|
4038 |
| new Word(SourceInfo.NONE, "myName"), |
|
4039 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])); |
|
4040 |
1
| MethodInvocation noArgs =
|
|
4041 |
| new ComplexMethodInvocation(SourceInfo.NONE, |
|
4042 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "g")), |
|
4043 |
| new Word(SourceInfo.NONE, "myName"), |
|
4044 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])); |
|
4045 |
1
| MethodInvocation oneIntArg =
|
|
4046 |
| new ComplexMethodInvocation(SourceInfo.NONE, |
|
4047 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "g")), |
|
4048 |
| new Word(SourceInfo.NONE, "myName"), |
|
4049 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[] { |
|
4050 |
| new IntegerLiteral(SourceInfo.NONE, 5)})); |
|
4051 |
1
| MethodInvocation staticOneDoubleArg =
|
|
4052 |
| new ComplexMethodInvocation(SourceInfo.NONE, |
|
4053 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "giraffe")), |
|
4054 |
| new Word(SourceInfo.NONE, "myName"), |
|
4055 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[] { |
|
4056 |
| new DoubleLiteral(SourceInfo.NONE, 4.2)})); |
|
4057 |
1
| MethodInvocation oneDoubleArg =
|
|
4058 |
| new ComplexMethodInvocation(SourceInfo.NONE, |
|
4059 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "g")), |
|
4060 |
| new Word(SourceInfo.NONE, "myName"), |
|
4061 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[] { |
|
4062 |
| new DoubleLiteral(SourceInfo.NONE, 4.2)})); |
|
4063 |
| |
|
4064 |
1
| SymbolData g = new SymbolData("giraffe");
|
|
4065 |
1
| g.setIsContinuation(false);
|
|
4066 |
1
| g.setMav(_publicMav);
|
|
4067 |
1
| symbolTable.put("giraffe", g);
|
|
4068 |
| |
|
4069 |
1
| VariableData var = new VariableData("g", _publicMav, g, true, _sd1);
|
|
4070 |
1
| _etc._vars.addLast(var);
|
|
4071 |
| |
|
4072 |
| |
|
4073 |
1
| assertEquals("Should return null", null, noArgs.visit(_etc));
|
|
4074 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
4075 |
1
| assertEquals("Error message should be correct", "No method found in class giraffe with signature: myName().",
|
|
4076 |
| errors.getLast().getFirst()); |
|
4077 |
| |
|
4078 |
| |
|
4079 |
1
| MethodData noArgsM = new MethodData("myName", _publicMav, new TypeParameter[0], SymbolData.BOOLEAN_TYPE,
|
|
4080 |
| new VariableData[0], new String[0], g, NULL_LITERAL); |
|
4081 |
1
| g.addMethod(noArgsM);
|
|
4082 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(), noArgs.visit(_etc));
|
|
4083 |
1
| assertEquals("Should still just be 1 error", 1, errors.size());
|
|
4084 |
| |
|
4085 |
| |
|
4086 |
1
| MethodData doubleArg =
|
|
4087 |
| new MethodData("myName", _publicStaticMav, new TypeParameter[0], SymbolData.CHAR_TYPE, |
|
4088 |
| new VariableData[] { new VariableData(SymbolData.DOUBLE_TYPE) }, |
|
4089 |
| new String[0], g, NULL_LITERAL); |
|
4090 |
1
| g.addMethod(doubleArg);
|
|
4091 |
| |
|
4092 |
1
| assertEquals("Should return char instance", SymbolData.CHAR_TYPE.getInstanceData(), oneDoubleArg.visit(_etc));
|
|
4093 |
1
| assertEquals("Should still be just 1 error", 1, errors.size());
|
|
4094 |
| |
|
4095 |
| |
|
4096 |
1
| staticOneDoubleArg.visit(_etc);
|
|
4097 |
1
| assertEquals("Should return char instance", SymbolData.CHAR_TYPE.getInstanceData(),
|
|
4098 |
| staticOneDoubleArg.visit(_etc)); |
|
4099 |
1
| assertEquals("Should still be just 1 error", 1, errors.size());
|
|
4100 |
| |
|
4101 |
| |
|
4102 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(),
|
|
4103 |
| staticNoArgs.visit(_etc)); |
|
4104 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
4105 |
1
| assertEquals("Error message should be correct",
|
|
4106 |
| "Cannot access the non-static method myName from a static context", |
|
4107 |
| errors.getLast().getFirst()); |
|
4108 |
| |
|
4109 |
| |
|
4110 |
1
| _etc._data = doubleArg;
|
|
4111 |
1
| var.setMav(_publicStaticMav);
|
|
4112 |
1
| assertEquals("Should return char instance", SymbolData.CHAR_TYPE.getInstanceData(), oneDoubleArg.visit(_etc));
|
|
4113 |
1
| assertEquals("Should still be just 2 errors", 2, errors.size());
|
|
4114 |
| |
|
4115 |
| |
|
4116 |
1
| MethodData intArg =
|
|
4117 |
| new MethodData("myName", _publicMav, new TypeParameter[0], SymbolData.LONG_TYPE, |
|
4118 |
| new VariableData[] { new VariableData(SymbolData.INT_TYPE)}, |
|
4119 |
| new String[0], g, NULL_LITERAL); |
|
4120 |
1
| g.addMethod(intArg);
|
|
4121 |
1
| assertEquals("Should return long instance", SymbolData.LONG_TYPE.getInstanceData().getName(),
|
|
4122 |
| oneIntArg.visit(_etc).getName()); |
|
4123 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
4124 |
| |
|
4125 |
| |
|
4126 |
| |
|
4127 |
| |
|
4128 |
1
| _etc._data = _sd1;
|
|
4129 |
1
| g.setMav(_privateMav);
|
|
4130 |
1
| noArgsM.setMav(_publicStaticMav);
|
|
4131 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(), noArgs.visit(_etc));
|
|
4132 |
1
| assertEquals("Should be 3 errors", 3, errors.size());
|
|
4133 |
1
| assertEquals("Error message should be correct",
|
|
4134 |
| "The class or interface giraffe in giraffe is private and cannot be accessed from i.like.monkey", |
|
4135 |
| errors.getLast().getFirst()); |
|
4136 |
| |
|
4137 |
| } |
|
4138 |
| |
|
4139 |
| |
|
4140 |
1
| public void testCanBeAssigned() {
|
|
4141 |
1
| VariableData finalWithValue = new VariableData("i", _finalMav, SymbolData.INT_TYPE, true, _sd1);
|
|
4142 |
1
| VariableData finalWithOutValue = new VariableData("i", _finalMav, SymbolData.INT_TYPE, false, _sd1);
|
|
4143 |
1
| VariableData notFinalWithValue = new VariableData("i", _publicMav, SymbolData.INT_TYPE, true, _sd1);
|
|
4144 |
1
| VariableData notFinalWithOutValue = new VariableData("i", _publicMav, SymbolData.INT_TYPE, false, _sd1);
|
|
4145 |
| |
|
4146 |
1
| assertFalse("Should not be assignable", _etc.canBeAssigned(finalWithValue));
|
|
4147 |
1
| assertTrue("Should be assignable", _etc.canBeAssigned(finalWithOutValue));
|
|
4148 |
1
| assertTrue("Should be assignable", _etc.canBeAssigned(notFinalWithValue));
|
|
4149 |
1
| assertTrue("Should be assignable", _etc.canBeAssigned(notFinalWithOutValue));
|
|
4150 |
| |
|
4151 |
| |
|
4152 |
| } |
|
4153 |
| |
|
4154 |
| |
|
4155 |
1
| public void testForSimpleAssignment() {
|
|
4156 |
1
| VariableData vd4 = new VariableData("Flanders", _publicMav, SymbolData.INT_TYPE, true, _sd4);
|
|
4157 |
1
| VariableData vd5 = new VariableData("Ned", _publicMav, _sd4, true, _sd5);
|
|
4158 |
1
| _sd5.addVar(vd5);
|
|
4159 |
1
| _sd4.addVar(vd4);
|
|
4160 |
1
| _etc._vars.add(vd5);
|
|
4161 |
1
| _etc._data = _sd5;
|
|
4162 |
| |
|
4163 |
1
| ComplexNameReference nf =
|
|
4164 |
| new ComplexNameReference(SourceInfo.NONE, |
|
4165 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "Ned")), |
|
4166 |
| new Word(SourceInfo.NONE, "Flanders")); |
|
4167 |
1
| SimpleAssignmentExpression sa =
|
|
4168 |
| new SimpleAssignmentExpression(SourceInfo.NONE, nf, new IntegerLiteral(SourceInfo.NONE, 5)); |
|
4169 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), sa.visit(_etc));
|
|
4170 |
1
| assertEquals("Should be 0 errors", 0, errors.size());
|
|
4171 |
| |
|
4172 |
| |
|
4173 |
1
| vd4.gotValue();
|
|
4174 |
1
| vd4.setMav(_finalPublicMav);
|
|
4175 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), sa.visit(_etc));
|
|
4176 |
1
| assertEquals("Should now be 1 error", 1, errors.size());
|
|
4177 |
1
| assertEquals("Error message should be correct",
|
|
4178 |
| "You cannot assign a value to Flanders because it is immutable and has already been given a value", |
|
4179 |
| errors.getLast().getFirst()); |
|
4180 |
| |
|
4181 |
| |
|
4182 |
1
| vd4.setMav(_publicMav);
|
|
4183 |
1
| SimpleAssignmentExpression sa2 = new SimpleAssignmentExpression(SourceInfo.NONE, nf, nf);
|
|
4184 |
1
| _sd4.setMav(_publicMav);
|
|
4185 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), sa2.visit(_etc));
|
|
4186 |
1
| assertEquals("There should be 1 error", 1, errors.size());
|
|
4187 |
| |
|
4188 |
| |
|
4189 |
1
| vd4.lostValue();
|
|
4190 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), sa2.visit(_etc));
|
|
4191 |
1
| assertEquals("There should be 2 errors", 2, errors.size());
|
|
4192 |
1
| assertEquals("The error message should be correct",
|
|
4193 |
| "You cannot use Flanders here, because it may not have been given a value", |
|
4194 |
| errors.getLast().getFirst()); |
|
4195 |
| |
|
4196 |
| |
|
4197 |
1
| SimpleAssignmentExpression sa3 =
|
|
4198 |
| new SimpleAssignmentExpression(SourceInfo.NONE, |
|
4199 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "int")), |
|
4200 |
| new IntegerLiteral(SourceInfo.NONE, 5)); |
|
4201 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), sa3.visit(_etc));
|
|
4202 |
1
| assertEquals("Should be 3 errors", 3, errors.size());
|
|
4203 |
1
| assertEquals("Error message should be correct",
|
|
4204 |
| "You cannot assign a value to the type int. Perhaps you meant to create a new instance of int", |
|
4205 |
| errors.getLast().getFirst()); |
|
4206 |
| |
|
4207 |
| |
|
4208 |
1
| SimpleAssignmentExpression sa4 =
|
|
4209 |
| new SimpleAssignmentExpression(SourceInfo.NONE, nf, |
|
4210 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "int"))); |
|
4211 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), sa4.visit(_etc));
|
|
4212 |
1
| assertEquals("Should be 4 errors", 4, errors.size());
|
|
4213 |
1
| assertEquals("Error message should be correct",
|
|
4214 |
| "You cannot use the type name int on the right hand side of an assignment. Perhaps you meant to " |
|
4215 |
| + "create a new instance of int", |
|
4216 |
| errors.getLast().getFirst()); |
|
4217 |
| |
|
4218 |
| |
|
4219 |
1
| LanguageLevelVisitor llv =
|
|
4220 |
| new LanguageLevelVisitor(_etc._file, |
|
4221 |
| _etc._package, |
|
4222 |
| null, |
|
4223 |
| _etc._importedFiles, |
|
4224 |
| _etc._importedPackages, |
|
4225 |
| new HashSet<String>(), |
|
4226 |
| new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(), |
|
4227 |
| new LinkedList<Command>()); |
|
4228 |
| |
|
4229 |
| |
|
4230 |
1
| ArrayData boolArray = new ArrayData(SymbolData.BOOLEAN_TYPE, llv, SourceInfo.NONE);
|
|
4231 |
1
| boolArray.setIsContinuation(false);
|
|
4232 |
1
| symbolTable.remove("boolean[]");
|
|
4233 |
1
| symbolTable.put("boolean[]", boolArray);
|
|
4234 |
1
| VariableData myArrayVD = new VariableData("myArray", _publicMav, boolArray, true, _etc._data);
|
|
4235 |
1
| _etc._vars.addLast(myArrayVD);
|
|
4236 |
| |
|
4237 |
1
| SimpleNameReference snr = new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "myArray"));
|
|
4238 |
1
| SimpleAssignmentExpression sa5 =
|
|
4239 |
| new SimpleAssignmentExpression(SourceInfo.NONE, |
|
4240 |
| new ArrayAccess(SourceInfo.NONE, snr, new IntegerLiteral(SourceInfo.NONE, 5)), |
|
4241 |
| new BooleanLiteral(SourceInfo.NONE, true)); |
|
4242 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(), sa5.visit(_etc));
|
|
4243 |
1
| assertEquals("Should still be 4 errors", 4, errors.size());
|
|
4244 |
| |
|
4245 |
| |
|
4246 |
| |
|
4247 |
| } |
|
4248 |
| |
|
4249 |
1
| public void testForPlusAssignmentExpression() {
|
|
4250 |
1
| VariableData vd4 = new VariableData("Flanders", _publicMav, SymbolData.INT_TYPE, true, _sd4);
|
|
4251 |
1
| VariableData vd5 = new VariableData("Ned", _publicMav, _sd4, true, _sd5);
|
|
4252 |
1
| _sd5.addVar(vd5);
|
|
4253 |
1
| _sd4.addVar(vd4);
|
|
4254 |
1
| _etc._vars.add(vd5);
|
|
4255 |
1
| _etc._data = _sd5;
|
|
4256 |
| |
|
4257 |
| |
|
4258 |
| |
|
4259 |
1
| ComplexNameReference nf =
|
|
4260 |
| new ComplexNameReference(SourceInfo.NONE, |
|
4261 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "Ned")), |
|
4262 |
| new Word(SourceInfo.NONE, "Flanders")); |
|
4263 |
1
| PlusAssignmentExpression pa =
|
|
4264 |
| new PlusAssignmentExpression(SourceInfo.NONE, nf, new IntegerLiteral(SourceInfo.NONE, 5)); |
|
4265 |
| |
|
4266 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), pa.visit(_etc));
|
|
4267 |
1
| assertEquals("Should be 0 errors", 0, errors.size());
|
|
4268 |
| |
|
4269 |
| |
|
4270 |
1
| vd4.lostValue();
|
|
4271 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), pa.visit(_etc));
|
|
4272 |
1
| assertEquals("Should now be 1 error", 1, errors.size());
|
|
4273 |
1
| assertEquals("Error message should be correct",
|
|
4274 |
| "You cannot use Flanders here, because it may not have been given a value", |
|
4275 |
| errors.get(0).getFirst()); |
|
4276 |
| |
|
4277 |
| |
|
4278 |
1
| vd4.gotValue();
|
|
4279 |
1
| vd4.setMav(_finalPublicMav);
|
|
4280 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), pa.visit(_etc));
|
|
4281 |
1
| assertEquals("Should now be 2 errors", 2, errors.size());
|
|
4282 |
1
| assertEquals("Error message should be correct",
|
|
4283 |
| "You cannot assign a new value to Flanders because it is immutable and has already been given a value", |
|
4284 |
| errors.get(1).getFirst()); |
|
4285 |
| |
|
4286 |
| |
|
4287 |
1
| vd4.setMav(_publicMav);
|
|
4288 |
1
| _sd4.setMav(_publicMav);
|
|
4289 |
1
| PlusAssignmentExpression pa2 = new PlusAssignmentExpression(SourceInfo.NONE, nf, nf);
|
|
4290 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), pa2.visit(_etc));
|
|
4291 |
1
| assertEquals("There should still be 2 errors", 2, errors.size());
|
|
4292 |
| |
|
4293 |
| |
|
4294 |
1
| vd4.lostValue();
|
|
4295 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), pa2.visit(_etc));
|
|
4296 |
1
| assertEquals("There should still be 2 errors", 2, errors.size());
|
|
4297 |
1
| assertEquals("The first error message should be correct",
|
|
4298 |
| "You cannot use Flanders here, because it may not have been given a value", |
|
4299 |
| errors.get(0).getFirst()); |
|
4300 |
| |
|
4301 |
| |
|
4302 |
1
| SymbolData stringSD = new SymbolData("java.lang.String");
|
|
4303 |
1
| stringSD.setIsContinuation(false);
|
|
4304 |
1
| stringSD.setPackage("java.lang");
|
|
4305 |
1
| symbolTable.remove("java.lang.String");
|
|
4306 |
1
| symbolTable.put("java.lang.String", stringSD);
|
|
4307 |
1
| VariableData s = new VariableData("s", _publicMav, stringSD, true, _etc._data);
|
|
4308 |
1
| _etc._vars.add(s);
|
|
4309 |
| |
|
4310 |
1
| SimpleNameReference sRef = new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "s"));
|
|
4311 |
| |
|
4312 |
1
| PlusAssignmentExpression pa3 =
|
|
4313 |
| new PlusAssignmentExpression(SourceInfo.NONE, sRef, new BooleanLiteral(SourceInfo.NONE, true)); |
|
4314 |
1
| TypeData result = pa3.visit(_etc);
|
|
4315 |
1
| assertEquals("string concatenation with string at the front. Should return String type",
|
|
4316 |
| stringSD.getInstanceData(), |
|
4317 |
| pa3.visit(_etc)); |
|
4318 |
1
| assertEquals("Should still be 2 errors", 2, errors.size());
|
|
4319 |
| |
|
4320 |
| |
|
4321 |
1
| PlusAssignmentExpression pa4 =
|
|
4322 |
| new PlusAssignmentExpression(SourceInfo.NONE, sRef, new StringLiteral(SourceInfo.NONE, "cat")); |
|
4323 |
1
| assertEquals("string concatenation with string on both sides. Should return String type",
|
|
4324 |
| stringSD.getInstanceData(), pa4.visit(_etc)); |
|
4325 |
1
| assertEquals("Should still be 2 errors", 2, errors.size());
|
|
4326 |
| |
|
4327 |
| |
|
4328 |
1
| vd4.gotValue();
|
|
4329 |
1
| PlusAssignmentExpression pa5 =
|
|
4330 |
| new PlusAssignmentExpression(SourceInfo.NONE, nf, new StringLiteral(SourceInfo.NONE, "house ")); |
|
4331 |
1
| assertEquals("string + concatenation with string at back. Should give error",
|
|
4332 |
| stringSD.getInstanceData(), |
|
4333 |
| pa5.visit(_etc)); |
|
4334 |
1
| assertEquals("Should now be 3 errors", 3, errors.size());
|
|
4335 |
1
| assertEquals("Error message should be correct",
|
|
4336 |
| "The arguments to the Plus Assignment Operator (+=) must either include an instance of a String " + |
|
4337 |
| "or both be numbers. You have specified arguments of type int and java.lang.String", |
|
4338 |
| errors.get(2).getFirst()); |
|
4339 |
| } |
|
4340 |
| |
|
4341 |
1
| public void testForNumericAssignmentExpression() {
|
|
4342 |
1
| VariableData vd4 = new VariableData("Flanders", _publicMav, SymbolData.INT_TYPE, true, _sd4);
|
|
4343 |
1
| VariableData vd5 = new VariableData("Ned", _publicMav, _sd4, true, _sd5);
|
|
4344 |
1
| _sd5.addVar(vd5);
|
|
4345 |
1
| _sd4.addVar(vd4);
|
|
4346 |
1
| _etc._vars.add(vd5);
|
|
4347 |
1
| _etc._data = _sd5;
|
|
4348 |
| |
|
4349 |
| |
|
4350 |
1
| ComplexNameReference nf =
|
|
4351 |
| new ComplexNameReference(SourceInfo.NONE, |
|
4352 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "Ned")), |
|
4353 |
| new Word(SourceInfo.NONE, "Flanders")); |
|
4354 |
1
| NumericAssignmentExpression na =
|
|
4355 |
| new MinusAssignmentExpression(SourceInfo.NONE, nf, new IntegerLiteral(SourceInfo.NONE, 5)); |
|
4356 |
| |
|
4357 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), na.visit(_etc));
|
|
4358 |
1
| assertEquals("Should be 0 errors", 0, errors.size());
|
|
4359 |
| |
|
4360 |
| |
|
4361 |
1
| vd4.lostValue();
|
|
4362 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), na.visit(_etc));
|
|
4363 |
1
| assertEquals("Should now be 1 error", 1, errors.size());
|
|
4364 |
1
| assertEquals("Error message should be correct",
|
|
4365 |
| "You cannot use Flanders here, because it may not have been given a value", |
|
4366 |
| errors.get(0).getFirst()); |
|
4367 |
| |
|
4368 |
| |
|
4369 |
1
| vd4.gotValue();
|
|
4370 |
1
| vd4.setMav(_finalPublicMav);
|
|
4371 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), na.visit(_etc));
|
|
4372 |
1
| assertEquals("Should now be 2 errors", 2, errors.size());
|
|
4373 |
1
| assertEquals("Error message should be correct",
|
|
4374 |
| "You cannot assign a new value to Flanders because it is immutable and has already been given a value", |
|
4375 |
| errors.get(1).getFirst()); |
|
4376 |
| |
|
4377 |
| |
|
4378 |
1
| vd4.setMav(_publicMav);
|
|
4379 |
1
| _sd4.setMav(_publicMav);
|
|
4380 |
1
| NumericAssignmentExpression na2 = new ModAssignmentExpression(SourceInfo.NONE, nf, nf);
|
|
4381 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), na2.visit(_etc));
|
|
4382 |
1
| assertEquals("There should be 2 errors", 2, errors.size());
|
|
4383 |
| |
|
4384 |
| |
|
4385 |
1
| vd4.lostValue();
|
|
4386 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), na2.visit(_etc));
|
|
4387 |
1
| assertEquals("There should still be 2 errors", 2, errors.size());
|
|
4388 |
1
| assertEquals("The new error message should be correct",
|
|
4389 |
| "You cannot use Flanders here, because it may not have been given a value", |
|
4390 |
| errors.get(0).getFirst()); |
|
4391 |
| } |
|
4392 |
| |
|
4393 |
1
| public void testForIncrementExpression() {
|
|
4394 |
1
| VariableData vd4 = new VariableData("Flanders", _publicMav, SymbolData.INT_TYPE, true, _sd4);
|
|
4395 |
1
| VariableData vd5 = new VariableData("Ned", _publicMav, _sd4, true, _sd5);
|
|
4396 |
1
| _sd5.addVar(vd5);
|
|
4397 |
1
| _sd4.addVar(vd4);
|
|
4398 |
1
| _etc._vars.add(vd5);
|
|
4399 |
1
| _etc._data = _sd5;
|
|
4400 |
| |
|
4401 |
| |
|
4402 |
1
| ComplexNameReference nf =
|
|
4403 |
| new ComplexNameReference(SourceInfo.NONE, |
|
4404 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "Ned")), |
|
4405 |
| new Word(SourceInfo.NONE, "Flanders")); |
|
4406 |
1
| PositivePrefixIncrementExpression ppi = new PositivePrefixIncrementExpression(SourceInfo.NONE, nf);
|
|
4407 |
| |
|
4408 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), ppi.visit(_etc));
|
|
4409 |
1
| assertEquals("Should still be 0 errors", 0, errors.size());
|
|
4410 |
| |
|
4411 |
| |
|
4412 |
1
| vd4.lostValue();
|
|
4413 |
1
| assertEquals("Should return int instance.", SymbolData.INT_TYPE.getInstanceData(), ppi.visit(_etc));
|
|
4414 |
1
| assertEquals("Should now be 1 errors", 1, errors.size());
|
|
4415 |
1
| assertEquals("Error message should be correct",
|
|
4416 |
| "You cannot use Flanders here, because it may not have been given a value", |
|
4417 |
| errors.get(0).getFirst()); |
|
4418 |
| |
|
4419 |
| |
|
4420 |
1
| vd4.gotValue();
|
|
4421 |
1
| vd4.setMav(_finalPublicMav);
|
|
4422 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), ppi.visit(_etc));
|
|
4423 |
1
| assertEquals("Should now be 2 errors", 2, errors.size());
|
|
4424 |
1
| assertEquals("Error message should be correct",
|
|
4425 |
| "You cannot assign a new value to Flanders because it is immutable and has already been given a value", |
|
4426 |
| errors.get(1).getFirst()); |
|
4427 |
| |
|
4428 |
| |
|
4429 |
1
| PositivePrefixIncrementExpression ppi2 =
|
|
4430 |
| new PositivePrefixIncrementExpression(SourceInfo.NONE, |
|
4431 |
| new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "int"))); |
|
4432 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), ppi2.visit(_etc));
|
|
4433 |
1
| assertEquals("There should now be 3 errors", 3, errors.size());
|
|
4434 |
1
| assertEquals("The error message should be correct",
|
|
4435 |
| "You cannot increment or decrement int, because it is a class name not an instance. " + |
|
4436 |
| "Perhaps you meant to create a new instance of int", |
|
4437 |
| errors.get(2).getFirst()); |
|
4438 |
| |
|
4439 |
| |
|
4440 |
| |
|
4441 |
1
| Parenthesized p1 =
|
|
4442 |
| new Parenthesized(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "int"))); |
|
4443 |
1
| PositivePrefixIncrementExpression ppi3 = new PositivePrefixIncrementExpression(SourceInfo.NONE, p1);
|
|
4444 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), ppi3.visit(_etc));
|
|
4445 |
1
| assertEquals("There should now be 4 errors", 4, errors.size());
|
|
4446 |
1
| assertEquals("The error message should be correct",
|
|
4447 |
| "You cannot increment or decrement int, because it is a class name not an instance. " + |
|
4448 |
| "Perhaps you meant to create a new instance of int", |
|
4449 |
| errors.get(3).getFirst()); |
|
4450 |
| |
|
4451 |
| |
|
4452 |
| |
|
4453 |
1
| vd4.setMav(_publicMav);
|
|
4454 |
1
| NegativePostfixIncrementExpression npi = new NegativePostfixIncrementExpression(SourceInfo.NONE, nf);
|
|
4455 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), npi.visit(_etc));
|
|
4456 |
1
| assertEquals("Should still be 4 errors", 4, errors.size());
|
|
4457 |
| |
|
4458 |
| |
|
4459 |
1
| vd4.lostValue();
|
|
4460 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), npi.visit(_etc));
|
|
4461 |
1
| assertEquals("Should still be 4 errors", 4, errors.size());
|
|
4462 |
1
| assertEquals("Error message should be correct",
|
|
4463 |
| "You cannot use Flanders here, because it may not have been given a value", |
|
4464 |
| errors.get(0).getFirst()); |
|
4465 |
| |
|
4466 |
| |
|
4467 |
1
| vd4.gotValue();
|
|
4468 |
1
| vd4.setMav(_finalPublicMav);
|
|
4469 |
1
| assertEquals("Should return int instance.", SymbolData.INT_TYPE.getInstanceData(), npi.visit(_etc));
|
|
4470 |
1
| assertEquals("Should still be 4 errors", 4, errors.size());
|
|
4471 |
1
| assertEquals("Error message should be correct",
|
|
4472 |
| "You cannot assign a new value to Flanders because it is immutable and has already been given a value", |
|
4473 |
| errors.get(1).getFirst()); |
|
4474 |
| |
|
4475 |
| |
|
4476 |
| |
|
4477 |
1
| NegativePostfixIncrementExpression npi2 =
|
|
4478 |
| new NegativePostfixIncrementExpression(SourceInfo.NONE, |
|
4479 |
| new SimpleNameReference(SourceInfo.NONE, |
|
4480 |
| new Word(SourceInfo.NONE, "int"))); |
|
4481 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), npi2.visit(_etc));
|
|
4482 |
1
| assertEquals("There should be 5 errors", 5, errors.size());
|
|
4483 |
1
| assertEquals("The error message should be correct",
|
|
4484 |
| "You cannot increment or decrement int, because it is a class name not an instance. Perhaps you " + |
|
4485 |
| "meant to create a new instance of int", |
|
4486 |
| errors.get(4).getFirst()); |
|
4487 |
| |
|
4488 |
| |
|
4489 |
1
| Parenthesized p2 =
|
|
4490 |
| new Parenthesized(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "int"))); |
|
4491 |
1
| NegativePostfixIncrementExpression npi3 = new NegativePostfixIncrementExpression(SourceInfo.NONE, p2);
|
|
4492 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), npi3.visit(_etc));
|
|
4493 |
1
| assertEquals("There should be 6 errors", 6, errors.size());
|
|
4494 |
1
| assertEquals("The error message should be correct",
|
|
4495 |
| "You cannot increment or decrement int, because it is a class name not an instance. " + |
|
4496 |
| "Perhaps you meant to create a new instance of int", |
|
4497 |
| errors.get(5).getFirst()); |
|
4498 |
| |
|
4499 |
| |
|
4500 |
| |
|
4501 |
1
| vd4.setMav(_publicMav);
|
|
4502 |
1
| Parenthesized p3 = new Parenthesized(SourceInfo.NONE, new NegativePrefixIncrementExpression(SourceInfo.NONE, nf));
|
|
4503 |
1
| PositivePrefixIncrementExpression ppi4 = new PositivePrefixIncrementExpression(SourceInfo.NONE, p3);
|
|
4504 |
1
| assertEquals("Should return null", null, ppi4.visit(_etc));
|
|
4505 |
1
| assertEquals("Should have added 1 error", 7, errors.size());
|
|
4506 |
1
| assertEquals("Should have correct error message",
|
|
4507 |
| "You cannot assign a value to an increment expression", |
|
4508 |
| errors.getLast().getFirst()); |
|
4509 |
| |
|
4510 |
| |
|
4511 |
1
| VariableData s = new VariableData("s", _publicMav, SymbolData.BOOLEAN_TYPE, true, _etc._data);
|
|
4512 |
1
| _etc._vars.addLast(s);
|
|
4513 |
1
| PositivePrefixIncrementExpression ppi5 =
|
|
4514 |
| new PositivePrefixIncrementExpression(SourceInfo.NONE, |
|
4515 |
| new SimpleNameReference(SourceInfo.NONE, |
|
4516 |
| new Word(SourceInfo.NONE, "s"))); |
|
4517 |
1
| assertEquals("Should return boolean instance", SymbolData.BOOLEAN_TYPE.getInstanceData(), ppi5.visit(_etc));
|
|
4518 |
1
| assertEquals("Should have added 1 error", 8, errors.size());
|
|
4519 |
1
| assertEquals("Should have correct error message",
|
|
4520 |
| "You cannot increment or decrement something that is not a number type. You have specified " + |
|
4521 |
| "something of type boolean", errors.get(7).getFirst()); |
|
4522 |
| |
|
4523 |
| |
|
4524 |
1
| PositivePrefixIncrementExpression ppi6 =
|
|
4525 |
| new PositivePrefixIncrementExpression(SourceInfo.NONE, new Parenthesized(SourceInfo.NONE, |
|
4526 |
| new Parenthesized(SourceInfo.NONE, nf))); |
|
4527 |
1
| assertEquals("Should return int instance", SymbolData.INT_TYPE.getInstanceData(), ppi6.visit(_etc));
|
|
4528 |
1
| assertEquals("Should still be 8 errors", 8, errors.size());
|
|
4529 |
| } |
|
4530 |
| |
|
4531 |
| |
|
4532 |
1
| public void testForSimpleAnonymousClassInstantiation() {
|
|
4533 |
1
| ClassOrInterfaceType objType = new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]);
|
|
4534 |
1
| AnonymousClassInstantiation basic =
|
|
4535 |
| new SimpleAnonymousClassInstantiation(SourceInfo.NONE, |
|
4536 |
| objType, |
|
4537 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]), |
|
4538 |
| new BracedBody(SourceInfo.NONE, new BodyItemI[0])); |
|
4539 |
| |
|
4540 |
1
| SymbolData object = LanguageLevelConverter.symbolTable.get("java.lang.Object");
|
|
4541 |
| |
|
4542 |
1
| _sd1.setAnonymousInnerClassNum(0);
|
|
4543 |
| |
|
4544 |
| |
|
4545 |
1
| SymbolData anon1 = new SymbolData("i.like.monkey$1");
|
|
4546 |
1
| anon1.setIsContinuation(false);
|
|
4547 |
1
| anon1.setPackage("i.like");
|
|
4548 |
1
| anon1.setMav(_publicMav);
|
|
4549 |
1
| anon1.setOuterData(_sd1);
|
|
4550 |
1
| assert object != null;
|
|
4551 |
1
| anon1.setSuperClass(object);
|
|
4552 |
1
| _sd1.addInnerClass(anon1);
|
|
4553 |
| |
|
4554 |
| |
|
4555 |
1
| assertEquals("Should return anon1 instance", anon1.getInstanceData(), basic.visit(_etc));
|
|
4556 |
| |
|
4557 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
4558 |
| |
|
4559 |
1
| VariableDeclaration vdecl = new VariableDeclaration(SourceInfo.NONE,
|
|
4560 |
| _packageMav, |
|
4561 |
| new VariableDeclarator[] { |
|
4562 |
| new UninitializedVariableDeclarator(SourceInfo.NONE, |
|
4563 |
| new PrimitiveType(SourceInfo.NONE, "double"), |
|
4564 |
| new Word (SourceInfo.NONE, "field1")), |
|
4565 |
| new UninitializedVariableDeclarator(SourceInfo.NONE, |
|
4566 |
| new PrimitiveType(SourceInfo.NONE, "boolean"), |
|
4567 |
| new Word (SourceInfo.NONE, "field2"))}); |
|
4568 |
| |
|
4569 |
1
| PrimitiveType intt = new PrimitiveType(SourceInfo.NONE, "int");
|
|
4570 |
1
| UninitializedVariableDeclarator uvd =
|
|
4571 |
| new UninitializedVariableDeclarator(SourceInfo.NONE, intt, new Word(SourceInfo.NONE, "i")); |
|
4572 |
1
| FormalParameter param =
|
|
4573 |
| new FormalParameter(SourceInfo.NONE, |
|
4574 |
| new UninitializedVariableDeclarator(SourceInfo.NONE, intt, |
|
4575 |
| new Word(SourceInfo.NONE, "j")), false); |
|
4576 |
1
| BracedBody bb =
|
|
4577 |
| new BracedBody(SourceInfo.NONE, |
|
4578 |
| new BodyItemI[] {new VariableDeclaration(SourceInfo.NONE, _packageMav, |
|
4579 |
| new UninitializedVariableDeclarator[]{uvd}), |
|
4580 |
| new ValueReturnStatement(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 5))}); |
|
4581 |
| |
|
4582 |
1
| ConcreteMethodDef cmd1 =
|
|
4583 |
| new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0], |
|
4584 |
| intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param}, |
|
4585 |
| new ReferenceType[0], bb); |
|
4586 |
1
| BracedBody classBb = new BracedBody(SourceInfo.NONE, new BodyItemI[] { vdecl, cmd1 });
|
|
4587 |
| |
|
4588 |
1
| SimpleAnonymousClassInstantiation complicated =
|
|
4589 |
| new SimpleAnonymousClassInstantiation(SourceInfo.NONE, |
|
4590 |
| new ClassOrInterfaceType(SourceInfo.NONE, "name", new Type[0]), |
|
4591 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]), |
|
4592 |
| classBb); |
|
4593 |
1
| SymbolData sd = new SymbolData("name");
|
|
4594 |
1
| sd.setIsContinuation(false);
|
|
4595 |
1
| sd.setMav(_publicMav);
|
|
4596 |
1
| symbolTable.put("name", sd);
|
|
4597 |
1
| SymbolData anon2 = new SymbolData("i.like.monkey$2");
|
|
4598 |
1
| anon2.setIsContinuation(false);
|
|
4599 |
1
| anon2.setPackage("i.like");
|
|
4600 |
1
| anon2.setSuperClass(sd);
|
|
4601 |
1
| anon2.setOuterData(_sd1);
|
|
4602 |
1
| _sd1.addInnerClass(anon2);
|
|
4603 |
| |
|
4604 |
1
| VariableData vd1 = new VariableData("field1", _publicMav, SymbolData.DOUBLE_TYPE, true, sd);
|
|
4605 |
1
| VariableData vd2 = new VariableData("field2", _publicMav, SymbolData.DOUBLE_TYPE, true, sd);
|
|
4606 |
1
| sd.addVar(vd1);
|
|
4607 |
1
| sd.addVar(vd2);
|
|
4608 |
| |
|
4609 |
1
| MethodData md =
|
|
4610 |
| new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE, new VariableData[] { |
|
4611 |
| new VariableData("j", _finalMav, SymbolData.INT_TYPE, true, null)}, new String[0], sd, cmd1); |
|
4612 |
1
| md.getParams()[0].setEnclosingData(md);
|
|
4613 |
1
| MethodData cd =
|
|
4614 |
| new MethodData("name", _publicMav, new TypeParameter[0], sd, new VariableData[0], new String[0], sd, cmd1); |
|
4615 |
1
| anon2.addMethod(md);
|
|
4616 |
1
| sd.addMethod(cd);
|
|
4617 |
| |
|
4618 |
1
| assertEquals("Should return anon2. ", anon2.getInstanceData(), complicated.visit(_etc));
|
|
4619 |
1
| assertEquals("There should be no errors", 0, errors.size());
|
|
4620 |
| |
|
4621 |
1
| _etc._data.addVar(new VariableData("myAnon", _publicMav, sd, false, _etc._data));
|
|
4622 |
| |
|
4623 |
| |
|
4624 |
| |
|
4625 |
1
| _sd1.setAnonymousInnerClassNum(1);
|
|
4626 |
1
| symbolTable.put("int", SymbolData.INT_TYPE);
|
|
4627 |
1
| VariableDeclaration vd =
|
|
4628 |
| new VariableDeclaration(SourceInfo.NONE, _publicMav, new VariableDeclarator[] { |
|
4629 |
| new InitializedVariableDeclarator(SourceInfo.NONE, |
|
4630 |
| new ClassOrInterfaceType(SourceInfo.NONE, "name", new Type[0]), |
|
4631 |
| new Word(SourceInfo.NONE, "myAnon"), complicated)}); |
|
4632 |
1
| vd.visit(_etc);
|
|
4633 |
1
| assertEquals("There should still be no errors", 0, errors.size());
|
|
4634 |
| |
|
4635 |
| |
|
4636 |
1
| _sd1.setAnonymousInnerClassNum(1);
|
|
4637 |
1
| MethodInvocation mie =
|
|
4638 |
| new ComplexMethodInvocation(SourceInfo.NONE, |
|
4639 |
| complicated, |
|
4640 |
| new Word(SourceInfo.NONE, "myMethod"), |
|
4641 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[] { |
|
4642 |
| new IntegerLiteral(SourceInfo.NONE, 5)})); |
|
4643 |
1
| assertEquals("Should return int", SymbolData.INT_TYPE.getInstanceData(), mie.visit(_etc));
|
|
4644 |
1
| assertEquals("There should still be no errors", 0, errors.size());
|
|
4645 |
| |
|
4646 |
| |
|
4647 |
1
| _sd1.setAnonymousInnerClassNum(1);
|
|
4648 |
| |
|
4649 |
1
| Expression nr = new ComplexNameReference(SourceInfo.NONE, complicated, new Word(SourceInfo.NONE, "field1"));
|
|
4650 |
1
| assertEquals("Should return double", SymbolData.DOUBLE_TYPE.getInstanceData(), nr.visit(_etc));
|
|
4651 |
1
| assertEquals("There should be no errors...still!", 0, errors.size());
|
|
4652 |
| |
|
4653 |
| |
|
4654 |
1
| _sd1.setAnonymousInnerClassNum(1);
|
|
4655 |
1
| sd.setMav(_publicAbstractMav);
|
|
4656 |
1
| sd.addMethod(new MethodData("yeah", _abstractMav, new TypeParameter[0], SymbolData.BOOLEAN_TYPE,
|
|
4657 |
| new VariableData[0], new String[0], sd, cmd1)); |
|
4658 |
| |
|
4659 |
1
| assertEquals("Should return anon2 instance", anon2.getInstanceData(), complicated.visit(_etc));
|
|
4660 |
1
| assertEquals("There should be one error", 1, errors.size());
|
|
4661 |
1
| assertEquals("The error message should be correct",
|
|
4662 |
| "This anonymous inner class must override the abstract method: yeah() in name", |
|
4663 |
| errors.get(0).getFirst()); |
|
4664 |
| |
|
4665 |
| |
|
4666 |
1
| SimpleAnonymousClassInstantiation nestedNonStatic =
|
|
4667 |
| new SimpleAnonymousClassInstantiation(SourceInfo.NONE, |
|
4668 |
| new ClassOrInterfaceType(SourceInfo.NONE, "A.B", new Type[0]), |
|
4669 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]), |
|
4670 |
| new BracedBody(SourceInfo.NONE, new BodyItemI[0])); |
|
4671 |
| |
|
4672 |
1
| SymbolData a = new SymbolData("A");
|
|
4673 |
1
| a.setIsContinuation(false);
|
|
4674 |
1
| SymbolData b = new SymbolData("A$B");
|
|
4675 |
1
| b.setIsContinuation(false);
|
|
4676 |
1
| b.setOuterData(a);
|
|
4677 |
1
| a.addInnerClass(b);
|
|
4678 |
1
| MethodData consb = new MethodData("B", _publicMav, new TypeParameter[0], b,
|
|
4679 |
| new VariableData[0], |
|
4680 |
| new String[0], |
|
4681 |
| b, |
|
4682 |
| null); |
|
4683 |
1
| b.addMethod(consb);
|
|
4684 |
1
| symbolTable.put("A", a);
|
|
4685 |
1
| a.setMav(new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"}));
|
|
4686 |
1
| b.setMav(new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"}));
|
|
4687 |
| |
|
4688 |
1
| SymbolData anon3 = new SymbolData("i.like.monkey$3");
|
|
4689 |
1
| anon3.setIsContinuation(false);
|
|
4690 |
1
| anon3.setMav(_publicMav);
|
|
4691 |
1
| _sd1.addInnerClass(anon3);
|
|
4692 |
1
| anon3.setOuterData(_sd1);
|
|
4693 |
| |
|
4694 |
| |
|
4695 |
1
| assertEquals("Should return anon3", anon3.getInstanceData(), nestedNonStatic.visit(_etc));
|
|
4696 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
4697 |
| |
|
4698 |
1
| assertEquals("Error message should be correct",
|
|
4699 |
| "A.B is not a static inner class, and thus cannot be instantiated from this context. " |
|
4700 |
| + "Perhaps you meant to use an instantiation of the form new A().new B()", |
|
4701 |
| errors.getLast().getFirst()); |
|
4702 |
| |
|
4703 |
1
| _sd1.setAnonymousInnerClassNum(2);
|
|
4704 |
| |
|
4705 |
1
| b.addModifier("static");
|
|
4706 |
1
| assertEquals("Should return anon3", anon3.getInstanceData(), nestedNonStatic.visit(_etc));
|
|
4707 |
1
| assertEquals("Should still be just 2 errors", 2, errors.size());
|
|
4708 |
| |
|
4709 |
| } |
|
4710 |
| |
|
4711 |
1
| public void testForComplexAnonymousClassInstantiation() {
|
|
4712 |
1
| ClassOrInterfaceType objType = new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]);
|
|
4713 |
| |
|
4714 |
1
| AnonymousClassInstantiation basic =
|
|
4715 |
| new ComplexAnonymousClassInstantiation(SourceInfo.NONE, |
|
4716 |
| new SimpleNameReference(SourceInfo.NONE, |
|
4717 |
| new Word(SourceInfo.NONE, "bob")), |
|
4718 |
| objType, |
|
4719 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]), |
|
4720 |
| new BracedBody(SourceInfo.NONE, new BodyItemI[0])); |
|
4721 |
| |
|
4722 |
| |
|
4723 |
1
| VariableData bob = new VariableData("bob", _publicMav, _sd2, true, _sd1);
|
|
4724 |
1
| _etc._vars.add(bob);
|
|
4725 |
| |
|
4726 |
1
| SymbolData object = LanguageLevelConverter.symbolTable.get("java.lang.Object");
|
|
4727 |
1
| _sd1.setAnonymousInnerClassNum(0);
|
|
4728 |
1
| SymbolData anon1 = new SymbolData("i.like.monkey$1");
|
|
4729 |
1
| anon1.setIsContinuation(false);
|
|
4730 |
1
| anon1.setPackage("i.like");
|
|
4731 |
1
| anon1.setMav(_publicMav);
|
|
4732 |
1
| anon1.setOuterData(_sd1);
|
|
4733 |
1
| assert object != null;
|
|
4734 |
1
| anon1.setSuperClass(object);
|
|
4735 |
1
| _sd1.addInnerClass(anon1);
|
|
4736 |
1
| assertEquals("Should return anon1 instance", anon1.getInstanceData(), basic.visit(_etc));
|
|
4737 |
| |
|
4738 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
4739 |
| |
|
4740 |
| |
|
4741 |
1
| VariableDeclaration vdecl = new VariableDeclaration(SourceInfo.NONE,
|
|
4742 |
| _packageMav, |
|
4743 |
| new VariableDeclarator[] { |
|
4744 |
| new UninitializedVariableDeclarator(SourceInfo.NONE, |
|
4745 |
| new PrimitiveType(SourceInfo.NONE, "double"), |
|
4746 |
| new Word (SourceInfo.NONE, "field1")), |
|
4747 |
| new UninitializedVariableDeclarator(SourceInfo.NONE, |
|
4748 |
| new PrimitiveType(SourceInfo.NONE, "boolean"), |
|
4749 |
| new Word (SourceInfo.NONE, "field2"))}); |
|
4750 |
| |
|
4751 |
1
| PrimitiveType intt = new PrimitiveType(SourceInfo.NONE, "int");
|
|
4752 |
1
| UninitializedVariableDeclarator uvd =
|
|
4753 |
| new UninitializedVariableDeclarator(SourceInfo.NONE, intt, new Word(SourceInfo.NONE, "i")); |
|
4754 |
1
| FormalParameter param =
|
|
4755 |
| new FormalParameter(SourceInfo.NONE, |
|
4756 |
| new UninitializedVariableDeclarator(SourceInfo.NONE, intt, |
|
4757 |
| new Word(SourceInfo.NONE, "j")), false); |
|
4758 |
1
| BracedBody bb =
|
|
4759 |
| new BracedBody(SourceInfo.NONE, new BodyItemI[] { |
|
4760 |
| new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd}), |
|
4761 |
| new ValueReturnStatement(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 5))}); |
|
4762 |
| |
|
4763 |
1
| ConcreteMethodDef cmd1 =
|
|
4764 |
| new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0], |
|
4765 |
| intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param}, |
|
4766 |
| new ReferenceType[0], bb); |
|
4767 |
1
| BracedBody classBb = new BracedBody(SourceInfo.NONE, new BodyItemI[] { vdecl, cmd1 });
|
|
4768 |
| |
|
4769 |
1
| ComplexAnonymousClassInstantiation complicated =
|
|
4770 |
| new ComplexAnonymousClassInstantiation(SourceInfo.NONE, |
|
4771 |
| new SimpleNameReference(SourceInfo.NONE, |
|
4772 |
| new Word(SourceInfo.NONE, "bob")), |
|
4773 |
| new ClassOrInterfaceType(SourceInfo.NONE, "name", new Type[0]), |
|
4774 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]), |
|
4775 |
| classBb); |
|
4776 |
| |
|
4777 |
| |
|
4778 |
1
| SymbolData sd = new SymbolData("name");
|
|
4779 |
1
| sd.setIsContinuation(false);
|
|
4780 |
1
| sd.setMav(_publicMav);
|
|
4781 |
1
| sd.setSuperClass(object);
|
|
4782 |
1
| symbolTable.put("name", sd);
|
|
4783 |
1
| SymbolData anon2 = new SymbolData("i.like.monkey$2");
|
|
4784 |
1
| anon2.setIsContinuation(false);
|
|
4785 |
1
| anon2.setPackage("i.like");
|
|
4786 |
1
| anon2.setSuperClass(sd);
|
|
4787 |
1
| anon2.setOuterData(_sd1);
|
|
4788 |
1
| _sd1.addInnerClass(anon2);
|
|
4789 |
| |
|
4790 |
1
| VariableData vd1 = new VariableData("field1", _publicMav, SymbolData.DOUBLE_TYPE, true, sd);
|
|
4791 |
1
| VariableData vd2 = new VariableData("field2", _publicMav, SymbolData.DOUBLE_TYPE, true, sd);
|
|
4792 |
1
| sd.addVar(vd1);
|
|
4793 |
1
| sd.addVar(vd2);
|
|
4794 |
| |
|
4795 |
1
| MethodData md =
|
|
4796 |
| new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE, new VariableData[] { |
|
4797 |
| new VariableData("j", _finalMav, SymbolData.INT_TYPE, true, null)}, new String[0], sd, cmd1); |
|
4798 |
1
| md.getParams()[0].setEnclosingData(md);
|
|
4799 |
1
| MethodData cd =
|
|
4800 |
| new MethodData("name", _publicMav, new TypeParameter[0], sd, new VariableData[0], new String[0], sd, cmd1); |
|
4801 |
1
| anon2.addMethod(md);
|
|
4802 |
1
| sd.addMethod(cd);
|
|
4803 |
| |
|
4804 |
| |
|
4805 |
1
| assertEquals("Should return anon2. ", anon2.getInstanceData(), complicated.visit(_etc));
|
|
4806 |
1
| assertEquals("There should be no errors", 0, errors.size());
|
|
4807 |
| |
|
4808 |
1
| _etc._data.addVar(new VariableData("myAnon", _publicMav, sd, false, _etc._data));
|
|
4809 |
| |
|
4810 |
| |
|
4811 |
| |
|
4812 |
1
| _sd1.setAnonymousInnerClassNum(1);
|
|
4813 |
1
| symbolTable.put("int", SymbolData.INT_TYPE);
|
|
4814 |
1
| VariableDeclaration vd =
|
|
4815 |
| new VariableDeclaration(SourceInfo.NONE, _publicMav, new VariableDeclarator[] { |
|
4816 |
| new InitializedVariableDeclarator(SourceInfo.NONE, |
|
4817 |
| new ClassOrInterfaceType(SourceInfo.NONE, "name", new Type[0]), |
|
4818 |
| new Word(SourceInfo.NONE, "myAnon"), |
|
4819 |
| complicated)}); |
|
4820 |
1
| vd.visit(_etc);
|
|
4821 |
1
| assertEquals("There should still be no errors", 0, errors.size());
|
|
4822 |
| |
|
4823 |
| |
|
4824 |
1
| _sd1.setAnonymousInnerClassNum(1);
|
|
4825 |
1
| MethodInvocation mie =
|
|
4826 |
| new ComplexMethodInvocation(SourceInfo.NONE, complicated, |
|
4827 |
| new Word(SourceInfo.NONE, "myMethod"), |
|
4828 |
| new ParenthesizedExpressionList(SourceInfo.NONE, |
|
4829 |
| new Expression[] { |
|
4830 |
| new IntegerLiteral(SourceInfo.NONE, 5)})); |
|
4831 |
1
| assertEquals("Should return int", SymbolData.INT_TYPE.getInstanceData(), mie.visit(_etc));
|
|
4832 |
1
| assertEquals("There should still be no errors", 0, errors.size());
|
|
4833 |
| |
|
4834 |
| |
|
4835 |
1
| _sd1.setAnonymousInnerClassNum(1);
|
|
4836 |
| |
|
4837 |
1
| Expression nr = new ComplexNameReference(SourceInfo.NONE, complicated, new Word(SourceInfo.NONE, "field1"));
|
|
4838 |
1
| assertEquals("Should return double", SymbolData.DOUBLE_TYPE.getInstanceData(), nr.visit(_etc));
|
|
4839 |
1
| assertEquals("There should be no errors...still!", 0, errors.size());
|
|
4840 |
| |
|
4841 |
| |
|
4842 |
1
| _sd1.setAnonymousInnerClassNum(1);
|
|
4843 |
1
| sd.setMav(_publicAbstractMav);
|
|
4844 |
1
| sd.addMethod(new MethodData("yeah", _abstractMav, new TypeParameter[0], SymbolData.BOOLEAN_TYPE,
|
|
4845 |
| new VariableData[0], new String[0], sd, cmd1)); |
|
4846 |
| |
|
4847 |
1
| assertEquals("Should return anon2 instance", anon2.getInstanceData(), complicated.visit(_etc));
|
|
4848 |
1
| assertEquals("There should be one error", 1, errors.size());
|
|
4849 |
1
| assertEquals("The error message should be correct",
|
|
4850 |
| "This anonymous inner class must override the abstract method: yeah() in name", |
|
4851 |
| errors.get(0).getFirst()); |
|
4852 |
| |
|
4853 |
| |
|
4854 |
1
| ComplexAnonymousClassInstantiation nestedNonStatic =
|
|
4855 |
| new ComplexAnonymousClassInstantiation(SourceInfo.NONE, |
|
4856 |
| new SimpleNameReference(SourceInfo.NONE, |
|
4857 |
| new Word(SourceInfo.NONE, "a")), |
|
4858 |
| new ClassOrInterfaceType(SourceInfo.NONE, "B", new Type[0]), |
|
4859 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]), |
|
4860 |
| new BracedBody(SourceInfo.NONE, new BodyItemI[0])); |
|
4861 |
| |
|
4862 |
1
| SymbolData a = new SymbolData("A");
|
|
4863 |
1
| a.setIsContinuation(false);
|
|
4864 |
1
| SymbolData b = new SymbolData("A$B");
|
|
4865 |
1
| b.setIsContinuation(false);
|
|
4866 |
1
| b.setOuterData(a);
|
|
4867 |
1
| a.addInnerClass(b);
|
|
4868 |
1
| MethodData consb =
|
|
4869 |
| new MethodData("B", _publicMav, new TypeParameter[0], b, new VariableData[0], new String[0], b, null); |
|
4870 |
1
| b.addMethod(consb);
|
|
4871 |
1
| symbolTable.put("A", a);
|
|
4872 |
1
| a.setMav(new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"}));
|
|
4873 |
1
| b.setMav(new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"}));
|
|
4874 |
| |
|
4875 |
1
| SymbolData anon3 = new SymbolData("i.like.monkey$3");
|
|
4876 |
1
| anon3.setIsContinuation(false);
|
|
4877 |
1
| anon3.setMav(_publicMav);
|
|
4878 |
1
| _sd1.addInnerClass(anon3);
|
|
4879 |
1
| anon3.setOuterData(_sd1);
|
|
4880 |
1
| VariableData aVar = new VariableData("a", _publicMav, a, true, _sd1);
|
|
4881 |
1
| _etc._vars.add(aVar);
|
|
4882 |
| |
|
4883 |
| |
|
4884 |
1
| assertEquals("Should return anon3", anon3.getInstanceData(), nestedNonStatic.visit(_etc));
|
|
4885 |
1
| assertEquals("Should still be just 1 error", 1, errors.size());
|
|
4886 |
| |
|
4887 |
| |
|
4888 |
1
| _sd1.setAnonymousInnerClassNum(2);
|
|
4889 |
1
| a.setMav(_privateMav);
|
|
4890 |
1
| assertEquals("Should return anon3", anon3.getInstanceData(), nestedNonStatic.visit(_etc));
|
|
4891 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
4892 |
1
| assertEquals("Error message should be correct",
|
|
4893 |
| "The class or interface A in A is private and cannot be accessed from i.like.monkey", |
|
4894 |
| errors.getLast().getFirst()); |
|
4895 |
1
| a.setMav(_publicMav);
|
|
4896 |
| |
|
4897 |
| |
|
4898 |
1
| _sd1.setAnonymousInnerClassNum(2);
|
|
4899 |
1
| b.setMav(_publicStaticMav);
|
|
4900 |
1
| assertEquals("Should return anon3", anon3.getInstanceData(), nestedNonStatic.visit(_etc));
|
|
4901 |
1
| assertEquals("Should be 3 errors", 3, errors.size());
|
|
4902 |
1
| assertEquals("Error message should be correct",
|
|
4903 |
| "You cannot instantiate a static inner class or interface with this syntax. Instead, try new A.B()", |
|
4904 |
| errors.getLast().getFirst()); |
|
4905 |
| |
|
4906 |
| |
|
4907 |
1
| ComplexAnonymousClassInstantiation nested =
|
|
4908 |
| new ComplexAnonymousClassInstantiation(SourceInfo.NONE, |
|
4909 |
| new SimpleNameReference(SourceInfo.NONE, |
|
4910 |
| new Word(SourceInfo.NONE, "A")), |
|
4911 |
| new ClassOrInterfaceType(SourceInfo.NONE, "B", new Type[0]), |
|
4912 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]), |
|
4913 |
| new BracedBody(SourceInfo.NONE, new BodyItemI[0])); |
|
4914 |
1
| _sd1.setAnonymousInnerClassNum(2);
|
|
4915 |
1
| b.setMav(_publicMav);
|
|
4916 |
1
| assertEquals("Should return anon3", anon3.getInstanceData(), nested.visit(_etc));
|
|
4917 |
1
| assertEquals("Should be 4 errors", 4, errors.size());
|
|
4918 |
1
| assertEquals("Error message should be correct",
|
|
4919 |
| "The constructor of a non-static inner class can only be called on an instance of its " |
|
4920 |
| + "containing class (e.g. new A().new B())", |
|
4921 |
| errors.getLast().getFirst()); |
|
4922 |
| |
|
4923 |
| } |
|
4924 |
| } |
|
4925 |
| } |