|
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 java.util.*; |
|
42 |
| import java.io.*; |
|
43 |
| |
|
44 |
| import junit.framework.TestCase; |
|
45 |
| |
|
46 |
| |
|
47 |
| public class ConstructorBodyTypeChecker extends BodyTypeChecker { |
|
48 |
| |
|
49 |
| |
|
50 |
| |
|
51 |
| |
|
52 |
| |
|
53 |
| |
|
54 |
| |
|
55 |
| |
|
56 |
| |
|
57 |
| |
|
58 |
29
| public ConstructorBodyTypeChecker(BodyData bodyData, File file, String packageName, LinkedList<String> importedFiles,
|
|
59 |
| LinkedList<String> importedPackages, LinkedList<VariableData> vars, |
|
60 |
| LinkedList<Pair<SymbolData, JExpression>> thrown) { |
|
61 |
29
| super(bodyData, file, packageName, importedFiles, importedPackages, vars, thrown);
|
|
62 |
| } |
|
63 |
| |
|
64 |
| |
|
65 |
| |
|
66 |
1
| protected BodyTypeChecker
|
|
67 |
| createANewInstanceOfMe(BodyData bodyData, File file, String pakage, LinkedList<String> importedFiles, |
|
68 |
| LinkedList<String> importedPackages, LinkedList<VariableData> vars, |
|
69 |
| LinkedList<Pair<SymbolData, JExpression>> thrown) { |
|
70 |
1
| return new ConstructorBodyTypeChecker(bodyData, file, pakage, importedFiles, importedPackages, vars, thrown);
|
|
71 |
| } |
|
72 |
| |
|
73 |
| |
|
74 |
| |
|
75 |
| |
|
76 |
| |
|
77 |
6
| public TypeData simpleThisConstructorInvocationAllowed(SimpleThisConstructorInvocation that) {
|
|
78 |
| |
|
79 |
| |
|
80 |
6
| String name = LanguageLevelVisitor.getUnqualifiedClassName(_data.getSymbolData().getName());
|
|
81 |
6
| InstanceData[] args = getArgTypesForInvocation(that.getArguments());
|
|
82 |
0
| if (args == null) {return null;}
|
|
83 |
6
| MethodData cd = _lookupMethod(name, _data.getSymbolData(), args, that,
|
|
84 |
| "No constructor found in class " + _data.getSymbolData().getName() + " with signature: ", |
|
85 |
| true, _data.getSymbolData()); |
|
86 |
| |
|
87 |
1
| if (cd==null) {return null;}
|
|
88 |
| |
|
89 |
| |
|
90 |
5
| LinkedList<VariableData> myFields = _data.getSymbolData().getVars();
|
|
91 |
5
| for (int i = 0; i<myFields.size(); i++) {
|
|
92 |
7
| if (myFields.get(i).hasModifier("final")) {
|
|
93 |
5
| _vars.get(_vars.indexOf(myFields.get(i))).gotValue();
|
|
94 |
5
| thingsThatHaveBeenAssigned.addLast(_vars.get(_vars.indexOf(myFields.get(i))));
|
|
95 |
| } |
|
96 |
| } |
|
97 |
| |
|
98 |
| |
|
99 |
5
| String[] thrown = cd.getThrown();
|
|
100 |
5
| for (int i = 0; i < thrown.length; i++) {
|
|
101 |
3
| _thrown.addLast(new Pair<SymbolData, JExpression>(getSymbolData(thrown[i], _getData(), that), that));
|
|
102 |
| } |
|
103 |
5
| return null;
|
|
104 |
| } |
|
105 |
| |
|
106 |
| |
|
107 |
1
| public TypeData complexThisConstructorInvocationNotAllowed(ComplexThisConstructorInvocation that) {
|
|
108 |
1
| _addError("Constructor Invocations of this form are never allowed. A constructor invocation can appear here, "
|
|
109 |
| + "but it must either be a super constructor invocation or have the form this(...)", that); |
|
110 |
1
| return null;
|
|
111 |
| } |
|
112 |
| |
|
113 |
| |
|
114 |
| |
|
115 |
| |
|
116 |
10
| public TypeData simpleSuperConstructorInvocationAllowed(SimpleSuperConstructorInvocation that) {
|
|
117 |
| |
|
118 |
10
| SymbolData superClass = _data.getSymbolData().getSuperClass();
|
|
119 |
| |
|
120 |
10
| if (superClass == null) {
|
|
121 |
1
| _addError("The class " + _data.getSymbolData().getName() + " does not have a super class", that);
|
|
122 |
1
| return null;
|
|
123 |
| } |
|
124 |
| |
|
125 |
| |
|
126 |
9
| if (superClass.getOuterData() != null && !(superClass.hasModifier("static"))) {
|
|
127 |
1
| _addError(superClass.getName() + " is a non-static inner class of " + superClass.getOuterData().getName() + ". Its constructor must be invoked from an instance of its outer class", that);
|
|
128 |
1
| return null;
|
|
129 |
| } |
|
130 |
| |
|
131 |
| |
|
132 |
| |
|
133 |
8
| String name = LanguageLevelVisitor.getUnqualifiedClassName(superClass.getName());
|
|
134 |
8
| InstanceData[] args = getArgTypesForInvocation(that.getArguments());
|
|
135 |
0
| if (args == null) return null;
|
|
136 |
8
| MethodData cd = _lookupMethod(name, superClass, args, that,
|
|
137 |
| "No constructor found in class " + superClass.getName() + " with signature: ", |
|
138 |
| true, superClass); |
|
139 |
| |
|
140 |
1
| if (cd == null) return null;
|
|
141 |
| |
|
142 |
| |
|
143 |
7
| String[] thrown = cd.getThrown();
|
|
144 |
7
| for (int i = 0; i < thrown.length; i++) {
|
|
145 |
3
| _thrown.addLast(new Pair<SymbolData, JExpression>(getSymbolData(thrown[i], _getData(), that), that));
|
|
146 |
| } |
|
147 |
7
| return null;
|
|
148 |
| } |
|
149 |
| |
|
150 |
| |
|
151 |
| |
|
152 |
| |
|
153 |
10
| public TypeData complexSuperConstructorInvocationAllowed(ComplexSuperConstructorInvocation that) {
|
|
154 |
| |
|
155 |
10
| ExpressionTypeChecker etc = new ExpressionTypeChecker(_data, _file, _package, _importedFiles, _importedPackages,
|
|
156 |
| _vars, _thrown); |
|
157 |
10
| TypeData enclosingResult = that.getEnclosing().visit(etc);
|
|
158 |
10
| thingsThatHaveBeenAssigned.addAll(etc.thingsThatHaveBeenAssigned);
|
|
159 |
| |
|
160 |
1
| if (! assertFound(enclosingResult, that)) return null;
|
|
161 |
9
| SymbolData superClass = _data.getSymbolData().getSuperClass();
|
|
162 |
| |
|
163 |
| |
|
164 |
9
| if (superClass == null) {
|
|
165 |
1
| _addError("A qualified super constructor invocation can only be used to invoke the constructor of your super "
|
|
166 |
| + "class from the context of its outer class. The class " + _data.getSymbolData().getName() + |
|
167 |
| " does not have a super class, so you cannot do this here", |
|
168 |
| that); |
|
169 |
1
| return null;
|
|
170 |
| } |
|
171 |
8
| else if (superClass.getOuterData() == null) {
|
|
172 |
1
| _addError("A qualified super constructor invocation can only be used to invoke the constructor of your super "
|
|
173 |
| + "class from the context of its outer class. The super class " + superClass.getName() |
|
174 |
| + " does not have an outer class, so you cannot do this here", |
|
175 |
| that); |
|
176 |
1
| return null;
|
|
177 |
| } |
|
178 |
7
| else if (enclosingResult == null) {
|
|
179 |
0
| _addError("A qualified super constructor invocation can only be used to invoke the constructor of your super "
|
|
180 |
| + "class from the context of its outer class.", |
|
181 |
| that); |
|
182 |
0
| return null;
|
|
183 |
| } |
|
184 |
7
| else if (superClass.getOuterData() != enclosingResult.getSymbolData()) {
|
|
185 |
1
| _addError("A qualified super constructor invocation can only be used to invoke the constructor of your super "
|
|
186 |
| + "class from the context of its outer class. The class or interface " |
|
187 |
| + enclosingResult.getSymbolData().getName() + " is not the outer class of the super class " |
|
188 |
| + superClass.getName(), |
|
189 |
| that); |
|
190 |
1
| return null;
|
|
191 |
| } |
|
192 |
6
| else if (!enclosingResult.isInstanceType()) {
|
|
193 |
1
| _addError("A qualified super constructor invocation can only be made from the context of an instance of the "
|
|
194 |
| + "outer class of the super class. You have specified a type name", |
|
195 |
| that); |
|
196 |
1
| return null;
|
|
197 |
| } |
|
198 |
5
| else if (superClass.hasModifier("static")) {
|
|
199 |
1
| _addError("A qualified super constructor invocation can only be used to invoke the constructor of a non-static "
|
|
200 |
| + "super class from the context of its outer class. The super class " + superClass.getName() |
|
201 |
| + " is a static inner class", |
|
202 |
| that); |
|
203 |
1
| return null;
|
|
204 |
| } |
|
205 |
4
| String name = LanguageLevelVisitor.getUnqualifiedClassName(superClass.getName());
|
|
206 |
4
| InstanceData[] args = getArgTypesForInvocation(that.getArguments());
|
|
207 |
0
| if (args == null) {return null;}
|
|
208 |
4
| MethodData cd = _lookupMethod(name, superClass, args, that,
|
|
209 |
| "No constructor found in class " + superClass.getName() + " with signature: ", |
|
210 |
| true, superClass); |
|
211 |
1
| if (cd == null) {return null;}
|
|
212 |
| |
|
213 |
3
| String[] thrown = cd.getThrown();
|
|
214 |
3
| for (int i = 0; i<thrown.length; i++) {
|
|
215 |
3
| _thrown.addLast(new Pair<SymbolData, JExpression>(getSymbolData(thrown[i], _getData(), that), that));
|
|
216 |
| } |
|
217 |
3
| return null;
|
|
218 |
| } |
|
219 |
| |
|
220 |
| |
|
221 |
| |
|
222 |
| |
|
223 |
| |
|
224 |
25
| private void implicitSuperConstructor(BracedBody that) {
|
|
225 |
| |
|
226 |
25
| SymbolData superClass = _data.getSymbolData().getSuperClass();
|
|
227 |
| |
|
228 |
25
| if (superClass == null) {
|
|
229 |
2
| return;
|
|
230 |
| } |
|
231 |
| |
|
232 |
| |
|
233 |
23
| if (superClass.getOuterData() != null && !(superClass.hasModifier("static"))) {
|
|
234 |
1
| _addError("There is an implicit call to the constructor of " + superClass.getName() + " here, but " +
|
|
235 |
| superClass.getName() + " is a non-static inner class of " + superClass.getOuterData().getName() + |
|
236 |
| ". Thus, you must explicitly invoke its constructor from an instance of its outer class", |
|
237 |
| that); |
|
238 |
1
| return;
|
|
239 |
| } |
|
240 |
| |
|
241 |
| |
|
242 |
| |
|
243 |
| |
|
244 |
22
| String name = LanguageLevelVisitor.getUnqualifiedClassName(superClass.getName());
|
|
245 |
| |
|
246 |
| |
|
247 |
| |
|
248 |
| |
|
249 |
| |
|
250 |
| |
|
251 |
22
| MethodData cd =
|
|
252 |
| _lookupMethod(name, |
|
253 |
| superClass, |
|
254 |
| new InstanceData[0], |
|
255 |
| that, |
|
256 |
| "You must invoke one of " + superClass.getName() + |
|
257 |
| "'s constructors here. You can either explicitly invoke one of its exisitng constructors or " |
|
258 |
| + "add a constructor with signature: ", |
|
259 |
| true, superClass); |
|
260 |
| |
|
261 |
4
| if (cd == null) return;
|
|
262 |
| |
|
263 |
| |
|
264 |
18
| String[] thrown = cd.getThrown();
|
|
265 |
18
| for (int i = 0; i<thrown.length; i++) {
|
|
266 |
3
| _thrown.addLast(new Pair<SymbolData, JExpression>(getSymbolData(thrown[i], _getData(), that), that));
|
|
267 |
| } |
|
268 |
18
| return;
|
|
269 |
| } |
|
270 |
| |
|
271 |
| |
|
272 |
| |
|
273 |
| |
|
274 |
| |
|
275 |
1
| public TypeData forVoidReturnStatementOnly(VoidReturnStatement that) {
|
|
276 |
| |
|
277 |
1
| return _bodyData.getSymbolData().getInstanceData();
|
|
278 |
| } |
|
279 |
| |
|
280 |
| |
|
281 |
1
| public TypeData forValueReturnStatementOnly(ValueReturnStatement that, TypeData valueRes) {
|
|
282 |
1
| _addError("You cannot return a value from a class's constructor", that);
|
|
283 |
1
| return _bodyData.getSymbolData().getInstanceData();
|
|
284 |
| } |
|
285 |
| |
|
286 |
| |
|
287 |
| |
|
288 |
| |
|
289 |
| |
|
290 |
| |
|
291 |
| |
|
292 |
29
| public TypeData forBracedBody(BracedBody that) {
|
|
293 |
| |
|
294 |
29
| int startIndex = 0;
|
|
295 |
29
| final TypeData[] items_result = makeArrayOfRetType(that.getStatements().length);
|
|
296 |
29
| if (items_result.length > 0) {
|
|
297 |
| |
|
298 |
22
| if (that.getStatements()[0] instanceof ExpressionStatement) {
|
|
299 |
20
| Expression firstExpression = ((ExpressionStatement) that.getStatements()[0]).getExpression();
|
|
300 |
20
| if (firstExpression instanceof SimpleThisConstructorInvocation) {
|
|
301 |
3
| items_result[0] = simpleThisConstructorInvocationAllowed((SimpleThisConstructorInvocation) firstExpression);
|
|
302 |
3
| startIndex ++;
|
|
303 |
| } |
|
304 |
| |
|
305 |
17
| else if (firstExpression instanceof ComplexThisConstructorInvocation) {
|
|
306 |
0
| items_result[0] = complexThisConstructorInvocationNotAllowed((ComplexThisConstructorInvocation) firstExpression);
|
|
307 |
0
| startIndex++;
|
|
308 |
| } |
|
309 |
17
| else if (firstExpression instanceof SimpleSuperConstructorInvocation) {
|
|
310 |
4
| items_result[0] = simpleSuperConstructorInvocationAllowed((SimpleSuperConstructorInvocation) firstExpression);
|
|
311 |
4
| startIndex++;
|
|
312 |
| } |
|
313 |
13
| else if (firstExpression instanceof ComplexSuperConstructorInvocation) {
|
|
314 |
2
| items_result[0] = complexSuperConstructorInvocationAllowed((ComplexSuperConstructorInvocation) firstExpression);
|
|
315 |
2
| startIndex++;
|
|
316 |
| } |
|
317 |
| } |
|
318 |
| } |
|
319 |
20
| if (startIndex == 0) implicitSuperConstructor(that);
|
|
320 |
| |
|
321 |
29
| int thrownSize = _thrown.size();
|
|
322 |
| |
|
323 |
29
| for (int j = 0; j < thrownSize; j++) {
|
|
324 |
9
| if (isUncaughtCheckedException(_thrown.get(j).getFirst(), that)) {
|
|
325 |
4
| handleUncheckedException(_thrown.get(j).getFirst(), _thrown.get(j).getSecond());
|
|
326 |
| } |
|
327 |
| } |
|
328 |
| |
|
329 |
| |
|
330 |
29
| for (int i = startIndex; i < that.getStatements().length; i++) {
|
|
331 |
18
| items_result[i] = that.getStatements()[i].visit(this);
|
|
332 |
| |
|
333 |
18
| for (int j = thrownSize; j < _thrown.size(); j++) {
|
|
334 |
0
| if (isUncaughtCheckedException(_thrown.get(j).getFirst(), that)) {
|
|
335 |
0
| handleUncheckedException(_thrown.get(j).getFirst(), _thrown.get(j).getSecond());
|
|
336 |
| } |
|
337 |
| } |
|
338 |
| } |
|
339 |
| |
|
340 |
29
| return forBracedBodyOnly(that, items_result);
|
|
341 |
| } |
|
342 |
| |
|
343 |
| |
|
344 |
| public static class ConstructorBodyTypeCheckerTest extends TestCase { |
|
345 |
| |
|
346 |
| private ConstructorBodyTypeChecker _cbtc; |
|
347 |
| |
|
348 |
| private MethodData _bd1; |
|
349 |
| |
|
350 |
| |
|
351 |
| private SymbolData _sd1; |
|
352 |
| private SymbolData _sd2; |
|
353 |
| private SymbolData _sd3; |
|
354 |
| private SymbolData _sd4; |
|
355 |
| private SymbolData _sd5; |
|
356 |
| private SymbolData _sd6; |
|
357 |
| private ModifiersAndVisibility _publicMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"}); |
|
358 |
| private ModifiersAndVisibility _protectedMav = |
|
359 |
| new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"protected"}); |
|
360 |
| private ModifiersAndVisibility _privateMav = |
|
361 |
| new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"private"}); |
|
362 |
| private ModifiersAndVisibility _packageMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[0]); |
|
363 |
| private ModifiersAndVisibility _abstractMav = |
|
364 |
| new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"abstract"}); |
|
365 |
| private ModifiersAndVisibility _finalMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"final"}); |
|
366 |
| |
|
367 |
0
| public ConstructorBodyTypeCheckerTest() { this(""); }
|
|
368 |
9
| public ConstructorBodyTypeCheckerTest(String name) { super(name); }
|
|
369 |
| |
|
370 |
9
| public void setUp() {
|
|
371 |
9
| _sd1 = new SymbolData("i.like.monkey");
|
|
372 |
9
| _sd2 = new SymbolData("i.like.giraffe");
|
|
373 |
9
| _sd3 = new SymbolData("zebra");
|
|
374 |
9
| _sd4 = new SymbolData("u.like.emu");
|
|
375 |
9
| _sd5 = new SymbolData("elephant");
|
|
376 |
9
| _sd6 = new SymbolData("cebu");
|
|
377 |
| |
|
378 |
9
| VariableData[] vds = new VariableData[] { new VariableData("i", _publicMav, SymbolData.INT_TYPE, true, null),
|
|
379 |
| new VariableData(SymbolData.BOOLEAN_TYPE) }; |
|
380 |
9
| _bd1 = new MethodData("monkey",
|
|
381 |
| _packageMav, |
|
382 |
| new TypeParameter[0], |
|
383 |
| _sd1, |
|
384 |
| vds, |
|
385 |
| new String[0], |
|
386 |
| _sd1, |
|
387 |
| null); |
|
388 |
| |
|
389 |
9
| _bd1.getParams()[0].setEnclosingData(_bd1);
|
|
390 |
9
| _bd1.getParams()[1].setEnclosingData(_bd1);
|
|
391 |
| |
|
392 |
9
| errors = new LinkedList<Pair<String, JExpressionIF>>();
|
|
393 |
9
| LanguageLevelConverter.symbolTable.clear();
|
|
394 |
9
| LanguageLevelConverter._newSDs.clear();
|
|
395 |
9
| _bd1.addEnclosingData(_sd1);
|
|
396 |
9
| _bd1.addVars(_bd1.getParams());
|
|
397 |
9
| _cbtc = new ConstructorBodyTypeChecker(_bd1,
|
|
398 |
| new File(""), |
|
399 |
| "", |
|
400 |
| new LinkedList<String>(), |
|
401 |
| new LinkedList<String>(), |
|
402 |
| new LinkedList<VariableData>(), |
|
403 |
| new LinkedList<Pair<SymbolData, JExpression>>()); |
|
404 |
9
| _cbtc._importedPackages.addFirst("java.lang");
|
|
405 |
| } |
|
406 |
| |
|
407 |
| |
|
408 |
1
| public void testForVoidReturnStatementOnly() {
|
|
409 |
1
| _cbtc._bodyData = _bd1;
|
|
410 |
| |
|
411 |
| |
|
412 |
1
| BracedBody bb1 = new BracedBody(SourceInfo.NONE,
|
|
413 |
| new BodyItemI[] { new VoidReturnStatement(SourceInfo.NONE)}); |
|
414 |
| |
|
415 |
1
| TypeData sd = bb1.visit(_cbtc);
|
|
416 |
| |
|
417 |
1
| assertEquals("There should be no errors.", 0, errors.size());
|
|
418 |
1
| assertEquals("Should return i.like.monkey type.", _sd1.getInstanceData(), sd);
|
|
419 |
| |
|
420 |
| } |
|
421 |
| |
|
422 |
1
| public void testforValueReturnStatementOnly() {
|
|
423 |
| |
|
424 |
1
| BodyItemI[] bis =
|
|
425 |
| new BodyItemI[] { new ValueReturnStatement(SourceInfo.NONE, |
|
426 |
| new BooleanLiteral(SourceInfo.NONE, true))}; |
|
427 |
1
| BracedBody bb1 = new BracedBody(SourceInfo.NONE, bis);
|
|
428 |
1
| TypeData sd = bb1.visit(_cbtc);
|
|
429 |
1
| assertEquals("There should be one error", 1, errors.size());
|
|
430 |
1
| assertEquals("Should return i.like.monkey type", _sd1.getInstanceData(), sd);
|
|
431 |
1
| assertEquals("Error message should be correct", "You cannot return a value from a class's constructor",
|
|
432 |
| errors.get(0).getFirst()); |
|
433 |
| |
|
434 |
| } |
|
435 |
| |
|
436 |
1
| public void testCreateANewInstanceOfMe() {
|
|
437 |
| |
|
438 |
1
| BodyTypeChecker btc =
|
|
439 |
| _cbtc.createANewInstanceOfMe(_cbtc._bodyData, _cbtc._file, _cbtc._package, _cbtc._importedFiles, |
|
440 |
| _cbtc._importedPackages, _cbtc._vars, _cbtc._thrown); |
|
441 |
1
| assertTrue("Should be an instance of ConstructorBodyTypeChecker", btc instanceof ConstructorBodyTypeChecker);
|
|
442 |
| } |
|
443 |
| |
|
444 |
1
| public void testForBracedBody() {
|
|
445 |
1
| LanguageLevelVisitor llv =
|
|
446 |
| new LanguageLevelVisitor(new File(""), |
|
447 |
| "", |
|
448 |
| null, |
|
449 |
| new LinkedList<String>(), |
|
450 |
| new LinkedList<String>(), |
|
451 |
| new HashSet<String>(), |
|
452 |
| new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(), |
|
453 |
| new LinkedList<Command>()); |
|
454 |
1
| llv.errors = new LinkedList<Pair<String, JExpressionIF>>();
|
|
455 |
1
| llv._errorAdded=false;
|
|
456 |
| |
|
457 |
1
| llv.continuations = new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>();
|
|
458 |
1
| llv.visitedFiles = new LinkedList<Pair<LanguageLevelVisitor, edu.rice.cs.javalanglevels.tree.SourceFile>>();
|
|
459 |
| |
|
460 |
1
| llv._classesInThisFile = new HashSet<String>();
|
|
461 |
| |
|
462 |
| |
|
463 |
1
| SymbolData throwable = llv.getSymbolData("java.lang.Exception", SourceInfo.NONE, true);
|
|
464 |
1
| SymbolData eb = llv.getSymbolData("java.util.prefs.BackingStoreException", SourceInfo.NONE, true);
|
|
465 |
1
| SymbolData re = llv.getSymbolData("java.lang.RuntimeException", SourceInfo.NONE, true);
|
|
466 |
| |
|
467 |
| |
|
468 |
1
| assert symbolTable.contains(eb);
|
|
469 |
1
| assert symbolTable.contains(re);
|
|
470 |
1
| assert symbolTable.containsKey("java.lang.Throwable");
|
|
471 |
1
| assert symbolTable.containsKey("java.lang.Exception");
|
|
472 |
| |
|
473 |
1
| _sd3.setIsContinuation(false);
|
|
474 |
1
| _sd3.setMav(_publicMav);
|
|
475 |
1
| _sd1.setSuperClass(_sd3);
|
|
476 |
| |
|
477 |
| |
|
478 |
1
| _cbtc._bodyData.getMethodData().setThrown(new String[0]);
|
|
479 |
1
| _sd3.setMav(_publicMav);
|
|
480 |
1
| _sd3.setIsContinuation(false);
|
|
481 |
1
| _cbtc.symbolTable.put(_sd3.getName(), _sd3);
|
|
482 |
1
| MethodData constructor = new MethodData("zebra",
|
|
483 |
| _publicMav, |
|
484 |
| new TypeParameter[0], |
|
485 |
| _sd3, |
|
486 |
| new VariableData[0], |
|
487 |
| new String[] {"java.util.prefs.BackingStoreException"}, |
|
488 |
| _sd3, |
|
489 |
| null); |
|
490 |
1
| _sd3.addMethod(constructor);
|
|
491 |
| |
|
492 |
1
| SimpleSuperConstructorInvocation ssci =
|
|
493 |
| new SimpleSuperConstructorInvocation(SourceInfo.NONE, |
|
494 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])); |
|
495 |
1
| BracedBody supConstr =
|
|
496 |
| new BracedBody(SourceInfo.NONE, new BodyItemI[]{new ExpressionStatement(SourceInfo.NONE, ssci)}); |
|
497 |
1
| _cbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
|
|
498 |
1
| supConstr.visit(_cbtc);
|
|
499 |
1
| assertEquals("There should be one error", 1, errors.size());
|
|
500 |
1
| assertEquals("The error message should be correct",
|
|
501 |
| "The constructor of this class's super class could throw the exception " + |
|
502 |
| "java.util.prefs.BackingStoreException, so the enclosing constructor needs to be declared to throw it", |
|
503 |
| errors.getLast().getFirst()); |
|
504 |
| |
|
505 |
| |
|
506 |
| |
|
507 |
1
| _cbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
|
|
508 |
1
| _cbtc._bodyData.getMethodData().setThrown(new String[] {"java.util.prefs.BackingStoreException"});
|
|
509 |
1
| supConstr.visit(_cbtc);
|
|
510 |
1
| assertEquals("There should still be one error", 1, errors.size());
|
|
511 |
| |
|
512 |
| |
|
513 |
1
| _cbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
|
|
514 |
1
| _cbtc._bodyData.getMethodData().setThrown(new String[0]);
|
|
515 |
1
| BracedBody emptyBody = new BracedBody(SourceInfo.NONE, new BodyItemI[0]);
|
|
516 |
1
| emptyBody.visit(_cbtc);
|
|
517 |
1
| assertEquals("There should be 2 errors", 2, errors.size());
|
|
518 |
1
| assertEquals("The error message should be correct", "There is an implicit call to the superclass's constructor here. That constructor could throw the exception java.util.prefs.BackingStoreException, so the enclosing constructor needs to be declared to throw it", errors.getLast().getFirst());
|
|
519 |
| |
|
520 |
| |
|
521 |
1
| _cbtc._bodyData.getMethodData().setThrown(new String[] {"java.util.prefs.BackingStoreException"});
|
|
522 |
1
| emptyBody.visit(_cbtc);
|
|
523 |
1
| assertEquals("There should still be two errors", 2, errors.size());
|
|
524 |
| |
|
525 |
| |
|
526 |
1
| _cbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
|
|
527 |
1
| BracedBody thisConstr = new BracedBody(SourceInfo.NONE, new BodyItemI[]{new ExpressionStatement(SourceInfo.NONE, new SimpleThisConstructorInvocation(SourceInfo.NONE, new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])))});
|
|
528 |
| |
|
529 |
1
| MethodData thisConstructor = new MethodData("cebu", _publicMav, new TypeParameter[0], _sd6, new VariableData[0], new String[] {"java.util.prefs.BackingStoreException"}, _sd6, null);
|
|
530 |
1
| MethodData thisConstructorNoThrown = new MethodData("cebu", _publicMav, new TypeParameter[0], _sd6, new VariableData[0], new String[0], _sd6, null);
|
|
531 |
1
| _sd6.addMethod(thisConstructor);
|
|
532 |
1
| BodyData oldData = _cbtc._bodyData;
|
|
533 |
1
| _cbtc._data = thisConstructorNoThrown;
|
|
534 |
1
| _cbtc._bodyData = thisConstructorNoThrown;
|
|
535 |
| |
|
536 |
1
| thisConstr.visit(_cbtc);
|
|
537 |
1
| assertEquals("There should be 3 errors", 3, errors.size());
|
|
538 |
1
| assertEquals("The error message should be correct", "This constructor could throw the exception java.util.prefs.BackingStoreException, so this enclosing constructor needs to be declared to throw it", errors.getLast().getFirst());
|
|
539 |
| |
|
540 |
| |
|
541 |
1
| _cbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
|
|
542 |
1
| _cbtc._bodyData.getMethodData().setThrown(new String[] {"java.util.prefs.BackingStoreException"});
|
|
543 |
1
| thisConstr.visit(_cbtc);
|
|
544 |
1
| assertEquals("There should still be 3 errors", 3, errors.size());
|
|
545 |
| |
|
546 |
| |
|
547 |
| |
|
548 |
1
| _cbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
|
|
549 |
| |
|
550 |
1
| _sd5.setIsContinuation(false);
|
|
551 |
1
| _sd5.addInnerClass(_sd3);
|
|
552 |
1
| _sd3.setOuterData(_sd5);
|
|
553 |
| |
|
554 |
1
| _sd5.setMav(_publicMav);
|
|
555 |
1
| _sd5.setIsContinuation(false);
|
|
556 |
1
| symbolTable.put("elephant", _sd5);
|
|
557 |
| |
|
558 |
1
| BracedBody complexSC = new BracedBody(SourceInfo.NONE, new BodyItemI[] {new ExpressionStatement(SourceInfo.NONE, new ComplexSuperConstructorInvocation(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "e")), new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])))});
|
|
559 |
1
| oldData.getMethodData().setThrown(new String[0]);
|
|
560 |
1
| _cbtc._vars.add(new VariableData("e", _publicMav, _sd5, true, _sd3));
|
|
561 |
1
| _cbtc._data = oldData;
|
|
562 |
1
| _cbtc._bodyData = oldData;
|
|
563 |
| |
|
564 |
1
| complexSC.visit(_cbtc);
|
|
565 |
1
| assertEquals("There should be 4 errors", 4, errors.size());
|
|
566 |
1
| assertEquals("Error message should be correct", "The constructor of this class's super class could throw the exception java.util.prefs.BackingStoreException, so the enclosing constructor needs to be declared to throw it", errors.getLast().getFirst());
|
|
567 |
| |
|
568 |
| |
|
569 |
1
| _cbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
|
|
570 |
| |
|
571 |
1
| _cbtc._bodyData.getMethodData().setThrown(new String[] {"java.util.prefs.BackingStoreException"});
|
|
572 |
1
| complexSC.visit(_cbtc);
|
|
573 |
1
| assertEquals("There should still be 4 errors", 4, errors.size());
|
|
574 |
| |
|
575 |
| } |
|
576 |
| |
|
577 |
1
| public void testSimpleThisConstructorInvocationAllowed() {
|
|
578 |
| |
|
579 |
1
| MethodData constructor =
|
|
580 |
| new MethodData("zebra", _publicMav, new TypeParameter[0], _sd3, |
|
581 |
| new VariableData[] {new VariableData(SymbolData.INT_TYPE)}, new String[0], _sd3, null); |
|
582 |
1
| _sd3.addMethod(constructor);
|
|
583 |
1
| _cbtc._bodyData = constructor;
|
|
584 |
1
| _cbtc._data = constructor;
|
|
585 |
| |
|
586 |
1
| VariableData vd1 = new VariableData("i", _finalMav, SymbolData.INT_TYPE, false, _sd3);
|
|
587 |
1
| VariableData vd2 = new VariableData("d", _finalMav, SymbolData.DOUBLE_TYPE, false, _sd3);
|
|
588 |
1
| VariableData vd3 = new VariableData("notFinal", _publicMav, SymbolData.BOOLEAN_TYPE, false, _sd3);
|
|
589 |
1
| _cbtc._vars.add(vd1);
|
|
590 |
1
| _cbtc._vars.add(vd2);
|
|
591 |
1
| _cbtc._vars.add(vd3);
|
|
592 |
1
| _sd3.addVar(vd1);
|
|
593 |
1
| _sd3.addVar(vd2);
|
|
594 |
1
| _sd3.addVar(vd3);
|
|
595 |
| |
|
596 |
1
| SimpleThisConstructorInvocation constr =
|
|
597 |
| new SimpleThisConstructorInvocation(SourceInfo.NONE, |
|
598 |
| new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[] { |
|
599 |
| new IntegerLiteral(SourceInfo.NONE, 5)})); |
|
600 |
1
| _cbtc.simpleThisConstructorInvocationAllowed(constr);
|
|
601 |
1
| assertEquals("Should be no errors", 0, errors.size());
|
|
602 |
1
| assertEquals("vd1 should have value", true, vd1.hasValue());
|
|
603 |
1
| assertEquals("vd2 should have value", true, vd2.hasValue());
|
|
604 |
1
| assertEquals("vd3 is not final, and thus should not have a value", false, vd3.hasValue());
|
|
605 |
1
| assertEquals("thrown should have 0 elements", 0, _cbtc._thrown.size());
|
|
606 |
| |
|
607 |
| |
|
608 |
1
| vd1.lostValue();
|
|
609 |
1
| vd2.lostValue();
|
|
610 |
| |
|
611 |
1
| SimpleThisConstructorInvocation constr2 = new SimpleThisConstructorInvocation(SourceInfo.NONE, new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]));
|
|
612 |
1
| _cbtc.simpleThisConstructorInvocationAllowed(constr2);
|
|
613 |
1
| assertEquals("Should be one error", 1, errors.size());
|
|
614 |
1
| assertEquals("Error message should be correct", "No constructor found in class zebra with signature: zebra().", errors.getLast().getFirst());
|
|
615 |
1
| assertFalse("vd1 should not have value", vd1.hasValue());
|
|
616 |
1
| assertFalse("vd2 should not have value", vd2.hasValue());
|
|
617 |
1
| assertFalse("vd3 should not have a value", vd3.hasValue());
|
|
618 |
1
| assertEquals("thrown should have 0 elements", 0, _cbtc._thrown.size());
|
|
619 |
| |
|
620 |
| |
|
621 |
| |
|
622 |
1
| constructor.setThrown(new String[] {"java.util.prefs.BackingStoreException"});
|
|
623 |
1
| _cbtc.simpleThisConstructorInvocationAllowed(constr);
|
|
624 |
1
| assertEquals("Should still be 1 error", 1, errors.size());
|
|
625 |
1
| assertTrue("vd1 should have a value", vd1.hasValue());
|
|
626 |
1
| assertTrue("vd2 should have a value", vd2.hasValue());
|
|
627 |
1
| assertFalse("vd3 is not final, and thus should not have a value", vd3.hasValue());
|
|
628 |
1
| assertEquals("thrown should have 1 element", 1, _cbtc._thrown.size());
|
|
629 |
| |
|
630 |
| } |
|
631 |
| |
|
632 |
| |
|
633 |
1
| public void testComplexThisConstructorInvocationNotAllowed() {
|
|
634 |
1
| ComplexThisConstructorInvocation constr = new ComplexThisConstructorInvocation(SourceInfo.NONE, new NullLiteral(SourceInfo.NONE), new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]));
|
|
635 |
1
| _cbtc.complexThisConstructorInvocationNotAllowed(constr);
|
|
636 |
1
| assertEquals("There should be 1 error", 1, errors.size());
|
|
637 |
1
| assertEquals("Error message should be correct", "Constructor Invocations of this form are never allowed. A constructor invocation can appear here, but it must either be a super constructor invocation or have the form this(...)", errors.getLast().getFirst());
|
|
638 |
| } |
|
639 |
| |
|
640 |
| |
|
641 |
1
| public void testSimpleSuperConstructorInvocationAllowed() {
|
|
642 |
| |
|
643 |
1
| SimpleSuperConstructorInvocation constr = new SimpleSuperConstructorInvocation(SourceInfo.NONE, new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[] {new IntegerLiteral(SourceInfo.NONE, 5)}));
|
|
644 |
1
| _cbtc.simpleSuperConstructorInvocationAllowed(constr);
|
|
645 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
646 |
1
| assertEquals("Error message should be correct", "The class i.like.monkey does not have a super class", errors.getLast().getFirst());
|
|
647 |
| |
|
648 |
| |
|
649 |
1
| _sd1.setSuperClass(_sd3);
|
|
650 |
1
| _cbtc.simpleSuperConstructorInvocationAllowed(constr);
|
|
651 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
652 |
1
| assertEquals("Error message should be correct", "No constructor found in class zebra with signature: zebra(int).", errors.getLast().getFirst());
|
|
653 |
| |
|
654 |
| |
|
655 |
1
| MethodData constructor = new MethodData("zebra", _publicMav, new TypeParameter[0], _sd3, new VariableData[] {new VariableData(SymbolData.INT_TYPE)}, new String[0], _sd3, null);
|
|
656 |
1
| _sd3.addMethod(constructor);
|
|
657 |
1
| _cbtc.simpleSuperConstructorInvocationAllowed(constr);
|
|
658 |
1
| assertEquals("Should still be 2 errors", 2, errors.size());
|
|
659 |
| |
|
660 |
| |
|
661 |
1
| constructor.setThrown(new String[] {"java.util.prefs.BackingStoreException"});
|
|
662 |
1
| _cbtc.simpleSuperConstructorInvocationAllowed(constr);
|
|
663 |
1
| assertEquals("Should still be 2 errors", 2, errors.size());
|
|
664 |
1
| assertEquals("thrown should have 1 element", 1, _cbtc._thrown.size());
|
|
665 |
| |
|
666 |
| |
|
667 |
1
| constructor.setThrown(new String[0]);
|
|
668 |
1
| _sd3.setOuterData(_sd5);
|
|
669 |
1
| _cbtc.simpleSuperConstructorInvocationAllowed(constr);
|
|
670 |
1
| assertEquals("Should be 3 errors", 3, errors.size());
|
|
671 |
1
| assertEquals("Error message should be correct", "zebra is a non-static inner class of elephant. Its constructor must be invoked from an instance of its outer class", errors.getLast().getFirst());
|
|
672 |
| |
|
673 |
| |
|
674 |
| |
|
675 |
1
| _sd3.addModifier("static");
|
|
676 |
1
| _cbtc.simpleSuperConstructorInvocationAllowed(constr);
|
|
677 |
1
| assertEquals("Should still be 3 errors", 3, errors.size());
|
|
678 |
| |
|
679 |
| } |
|
680 |
| |
|
681 |
1
| public void testComplexSuperConstructorInvocationAllowed() {
|
|
682 |
| |
|
683 |
| |
|
684 |
1
| ComplexSuperConstructorInvocation constr1 = new ComplexSuperConstructorInvocation(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "nonExistant")), new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]));
|
|
685 |
1
| _cbtc.complexSuperConstructorInvocationAllowed(constr1);
|
|
686 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
687 |
1
| assertEquals("Error message should be correct", "Could not resolve symbol nonExistant", errors.getLast().getFirst());
|
|
688 |
| |
|
689 |
| |
|
690 |
1
| ComplexSuperConstructorInvocation constr2 = new ComplexSuperConstructorInvocation(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "zebra")), new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]));
|
|
691 |
1
| symbolTable.put("zebra", _sd3);
|
|
692 |
1
| _sd3.setIsContinuation(false);
|
|
693 |
1
| _sd3.setMav(_publicMav);
|
|
694 |
1
| _cbtc.complexSuperConstructorInvocationAllowed(constr2);
|
|
695 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
696 |
1
| assertEquals("Error message should be correct", "A qualified super constructor invocation can only be used to invoke the constructor of your super class from the context of its outer class. The class i.like.monkey does not have a super class, so you cannot do this here", errors.getLast().getFirst());
|
|
697 |
| |
|
698 |
| |
|
699 |
1
| _sd1.setSuperClass(_sd5);
|
|
700 |
1
| _cbtc.complexSuperConstructorInvocationAllowed(constr2);
|
|
701 |
1
| assertEquals("Should be 3 errors", 3, errors.size());
|
|
702 |
1
| assertEquals("Error message should be correct", "A qualified super constructor invocation can only be used to invoke the constructor of your super class from the context of its outer class. The super class elephant does not have an outer class, so you cannot do this here", errors.getLast().getFirst());
|
|
703 |
| |
|
704 |
| |
|
705 |
1
| _sd5.setOuterData(_sd3);
|
|
706 |
1
| ComplexSuperConstructorInvocation constr3 = new ComplexSuperConstructorInvocation(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "u.like.emu")), new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]));
|
|
707 |
1
| symbolTable.put("u.like.emu", _sd4);
|
|
708 |
1
| _sd4.setPackage("u.like");
|
|
709 |
1
| _sd4.setIsContinuation(false);
|
|
710 |
1
| _sd4.setMav(_publicMav);
|
|
711 |
1
| _cbtc.complexSuperConstructorInvocationAllowed(constr3);
|
|
712 |
1
| assertEquals("Should be 4 errors", 4, errors.size());
|
|
713 |
1
| assertEquals("Error message should be correct", "A qualified super constructor invocation can only be used to invoke the constructor of your super class from the context of its outer class. The class or interface u.like.emu is not the outer class of the super class elephant", errors.getLast().getFirst());
|
|
714 |
| |
|
715 |
| |
|
716 |
1
| _cbtc.complexSuperConstructorInvocationAllowed(constr2);
|
|
717 |
1
| assertEquals("Should be 5 errors", 5, errors.size());
|
|
718 |
1
| assertEquals("Error message should be correct", "A qualified super constructor invocation can only be made from the context of an instance of the outer class of the super class. You have specified a type name", errors.getLast().getFirst());
|
|
719 |
| |
|
720 |
| |
|
721 |
1
| ComplexSuperConstructorInvocation constr4 = new ComplexSuperConstructorInvocation(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "var")), new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]));
|
|
722 |
1
| _cbtc._vars.add(new VariableData("var", _publicMav, _sd3, true, _sd1));
|
|
723 |
1
| _cbtc.complexSuperConstructorInvocationAllowed(constr4);
|
|
724 |
1
| assertEquals("Should be 6 errors", 6, errors.size());
|
|
725 |
1
| assertEquals("Error message should be correct", "No constructor found in class elephant with signature: elephant().", errors.getLast().getFirst());
|
|
726 |
| |
|
727 |
| |
|
728 |
1
| MethodData constructor = new MethodData("elephant", _publicMav, new TypeParameter[0], _sd5, new VariableData[0], new String[] {"java.util.prefs.BackingStoreException"}, _sd5, null);
|
|
729 |
1
| _sd5.addMethod(constructor);
|
|
730 |
1
| _cbtc.complexSuperConstructorInvocationAllowed(constr4);
|
|
731 |
1
| assertEquals("Should still be 6 errors", 6, errors.size());
|
|
732 |
1
| assertEquals("_thrown should now have 1 element", 1, _cbtc._thrown.size());
|
|
733 |
| |
|
734 |
| |
|
735 |
1
| _sd5.addModifier("static");
|
|
736 |
1
| _cbtc.complexSuperConstructorInvocationAllowed(constr4);
|
|
737 |
1
| assertEquals("Should be 7 errors", 7, errors.size());
|
|
738 |
1
| assertEquals("Error message should be correct", "A qualified super constructor invocation can only be used to invoke the constructor of a non-static super class from the context of its outer class. The super class elephant is a static inner class", errors.getLast().getFirst());
|
|
739 |
| } |
|
740 |
| |
|
741 |
| |
|
742 |
1
| public void testImplicitSuperConstructor() {
|
|
743 |
1
| BracedBody constr = new BracedBody(SourceInfo.NONE, new BodyItemI[0]);
|
|
744 |
| |
|
745 |
1
| _sd1.setSuperClass(_sd3);
|
|
746 |
1
| _cbtc.implicitSuperConstructor(constr);
|
|
747 |
1
| assertEquals("Should be 1 error", 1, errors.size());
|
|
748 |
1
| assertEquals("Error message should be correct", "You must invoke one of zebra's constructors here. You can either explicitly invoke one of its exisitng constructors or add a constructor with signature: zebra().",
|
|
749 |
| errors.getLast().getFirst()); |
|
750 |
| |
|
751 |
| |
|
752 |
1
| MethodData constructor = new MethodData("zebra", _publicMav, new TypeParameter[0], _sd3, new VariableData[0], new String[0], _sd3, null);
|
|
753 |
1
| _sd3.addMethod(constructor);
|
|
754 |
1
| _cbtc.implicitSuperConstructor(constr);
|
|
755 |
1
| assertEquals("Should still be 1 error", 1, errors.size());
|
|
756 |
| |
|
757 |
| |
|
758 |
1
| constructor.setThrown(new String[] {"java.util.prefs.BackingStoreException"});
|
|
759 |
1
| _cbtc.implicitSuperConstructor(constr);
|
|
760 |
1
| assertEquals("Should still be 1 error", 1, errors.size());
|
|
761 |
1
| assertEquals("thrown should have 1 element", 1, _cbtc._thrown.size());
|
|
762 |
| |
|
763 |
| |
|
764 |
1
| constructor.setThrown(new String[0]);
|
|
765 |
1
| _sd3.setOuterData(_sd5);
|
|
766 |
1
| _cbtc.implicitSuperConstructor(constr);
|
|
767 |
1
| assertEquals("Should be 2 errors", 2, errors.size());
|
|
768 |
1
| assertEquals("Error message should be correct", "There is an implicit call to the constructor of zebra here, but zebra is a non-static inner class of elephant. Thus, you must explicitly invoke its constructor from an instance of its outer class", errors.getLast().getFirst());
|
|
769 |
| |
|
770 |
| |
|
771 |
| |
|
772 |
1
| _sd3.addModifier("static");
|
|
773 |
1
| _cbtc.implicitSuperConstructor(constr);
|
|
774 |
1
| assertEquals("Should still be 2 errors", 2, errors.size());
|
|
775 |
| } |
|
776 |
| } |
|
777 |
| } |
|
778 |
| |
|
779 |
| |
|
780 |
| |
|
781 |
| |
|
782 |
| |