001 /*BEGIN_COPYRIGHT_BLOCK
002 *
003 * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@rice.edu)
004 * All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or without
007 * modification, are permitted provided that the following conditions are met:
008 * * Redistributions of source code must retain the above copyright
009 * notice, this list of conditions and the following disclaimer.
010 * * Redistributions in binary form must reproduce the above copyright
011 * notice, this list of conditions and the following disclaimer in the
012 * documentation and/or other materials provided with the distribution.
013 * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014 * names of its contributors may be used to endorse or promote products
015 * derived from this software without specific prior written permission.
016 *
017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028 *
029 * This software is Open Source Initiative approved Open Source Software.
030 * Open Source Initative Approved is a trademark of the Open Source Initiative.
031 *
032 * This file is part of DrJava. Download the current version of this project
033 * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034 *
035 * END_COPYRIGHT_BLOCK*/
036
037 package edu.rice.cs.javalanglevels;
038
039 import edu.rice.cs.javalanglevels.tree.*;
040 import edu.rice.cs.javalanglevels.parser.*;
041 import java.util.*;
042 import java.io.*;
043 import edu.rice.cs.plt.reflect.JavaVersion;
044 import edu.rice.cs.plt.iter.*;
045
046 import junit.framework.TestCase;
047
048
049 /** Top-level Language Level Visitor that processes the Full Java Language Level. It constructs a symbol table from a
050 * Java source file if possible. It does not attempt to check for errors since Full Java files are compiled by javac.
051 */
052 public class FullJavaVisitor extends LanguageLevelVisitor {
053
054 /* Inheriting the following fields:
055 *
056 File _file;
057 String _package;
058 String _enclosingClassName;
059 LinkedList<String> _importedFiles;
060 LinkedList<String> _importedPackages;
061 HashMap<String, SymbolData> _generic types
062 *
063 */
064
065 /** Main constructor, which is called from sites where the genericTypes table is not empty. */
066 public FullJavaVisitor(File file,
067 String packageName,
068 String enclosingClassName,
069 LinkedList<String> importedFiles,
070 LinkedList<String> importedPackages,
071 HashSet<String> classesInThisFile,
072 Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>> continuations,
073 LinkedList<Command> fixUps,
074 HashMap<String, SymbolData> genericTypes) {
075 super(file, packageName, enclosingClassName, importedFiles, importedPackages, classesInThisFile, continuations,
076 fixUps, genericTypes);
077 }
078
079
080 /** This constructor is called from sites where no generic type variables are in scope. */
081 public FullJavaVisitor(File file,
082 String packageName,
083 String enclosingClassName,
084 LinkedList<String> importedFiles,
085 LinkedList<String> importedPackages,
086 HashSet<String> classesInThisFile,
087 Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>> continuations,
088 LinkedList<Command> fixUps) {
089 this(file, packageName, enclosingClassName, importedFiles, importedPackages, classesInThisFile, continuations,
090 fixUps, new HashMap<String, SymbolData>());
091 }
092
093 /** This constructor is called only in testing. It initializes all of the static fields of LanguageLevelVisitor. */
094 public FullJavaVisitor(File file) {
095 this(file,
096 new LinkedList<Pair<String, JExpressionIF>>(),
097 new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(),
098 new LinkedList<Command>(),
099 new LinkedList<Pair<LanguageLevelVisitor, SourceFile>>());
100 }
101
102 /** This constructor is called from LanguageLevelConverter when it is instantiating a new
103 * FullJavaVisitor to visit a new file. Package is set to "" by default. The generic
104 * types table (_genericTypes) is set to an emtpy HashMap by default.
105 * @param file The File corresponding to the source file we are visiting
106 * @param errors The list of errors that have been encountered so far.
107 * @param continuations The table of classes we have encountered but still need to resolve
108 * @param visitedFiles The list of files we have visited
109 */
110 public FullJavaVisitor(File file,
111 LinkedList<Pair<String, JExpressionIF>> errors,
112 Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>> continuations,
113 LinkedList<Command> fixUps,
114 LinkedList<Pair<LanguageLevelVisitor, SourceFile>> visitedFiles) {
115 this(file, new LinkedList<String>(), errors, continuations, fixUps, visitedFiles);
116 }
117
118 /** This constructor is called from LanguageLevelConverter when it is instantiating a new
119 * FullJavaVisitor to visit a new file. Package is set to "" by default.
120 * @param file The File corresponding to the source file we are visiting
121 * @param importedPackages The list of strings describing the imported packages for this file
122 * @param errors The list of errors that have been encountered so far.
123 * @param continuations The table of classes we have encountered but still need to resolve
124 * @param visitedFiles The list of files we have visited
125 */
126 public FullJavaVisitor(File file,
127 LinkedList<String> importedPackages,
128 LinkedList<Pair<String, JExpressionIF>> errors,
129 Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>> continuations,
130 LinkedList<Command> fixUps,
131 LinkedList<Pair<LanguageLevelVisitor, SourceFile>> visitedFiles) {
132 this(file, "", null, new LinkedList<String>(), importedPackages, new HashSet<String>(), continuations, fixUps);
133 this.errors = errors;
134 this.visitedFiles= visitedFiles; //new LinkedList<Pair<LanguageLevelVisitor, SourceFile>>();
135 // _hierarchy = new Hashtable<String, TypeDefBase>();//hierarchy;
136 }
137
138 /** At the FullJava Level, there is no code augmentation. If we are working with a class that has no constructor,
139 * we must record fact that has an implicit 0-ary default constructor.
140 * @param sd The SymbolData we are checking
141 */
142 public void createConstructor(SymbolData sd) {
143 SymbolData superSd = sd.getSuperClass();
144
145 //If sd is a continuation, there was an error somewhere else. just return.
146 if (sd.isContinuation()) return;
147
148 String name = getUnqualifiedClassName(sd.getName());
149
150 // if sd already has a constructor, just return.
151 boolean hasOtherConstructor = sd.hasMethod(name);
152 if (hasOtherConstructor) {
153 LanguageLevelConverter._newSDs.remove(sd); // this won't do anything if sd is not in _newSDs.
154 // System.err.println(sd + " removed from _newSDs. _newSDs = " + LanguageLevelConverter._newSDs);
155 return;
156 }
157
158 // otherwise, it doesn't have a constructor, so let's add it!
159 MethodData md = MethodData.make(name,
160 new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"}),
161 new TypeParameter[0],
162 sd,
163 new VariableData[0], // No Parameters
164 new String[0],
165 sd,
166 null);
167
168 addGeneratedMethod(sd, md);
169 LanguageLevelConverter._newSDs.remove(sd); // does nothing if sd is not in _newSDs.
170 }
171
172 /** Process the inner class def and then resolve it and store it in
173 * the outer class's list of inner classes. This method is common to both ClassBodyFullJavaVisitor
174 * and InterfaceBodyIntermediateVisitor but needs the correct Data so we pass it in. This method is tested
175 * in those files. We use the fully qualified name along with the $'s so we don't accidentally conflict with an
176 * actual class in the symbol table.
177 * @param that The AST Node for the inner class def
178 * @param data The Data that encloses this inner class. This is a Data because the inner class can be in a class
179 * or a method.
180 * @param relName The relative name of the inner class including no qualifiers
181 * @param name The qualified name of the inner class including the qualified name of the enclosing data followed by
182 * a $. For local classes, we append a number after the $ corresponding to the order that the local
183 * class appears in the enclosing class and then put the name of the class. For anonymous classes, we
184 * only put a number after the $. For example, if class A has a method B that has a local class C, then
185 * name should be "A$1C".
186 */
187 protected void handleInnerClassDef(InnerClassDef that, Data data, String relName, String name) {
188 // if (_file.getName().endsWith("MultipleNested.dj2"))
189 // System.err.println("********** Processing InnerClassDef for " + name + " defined in " + data.getName());
190
191 assert (data instanceof SymbolData) || (data instanceof MethodData);
192 // assert (data instanceof SymbolData) ? data.getName().equals(_enclosingClassName) : true;
193
194 forInnerClassDefDoFirst(that);
195 if (prune(that)) return;
196
197 that.getMav().visit(this);
198 that.getName().visit(this);
199
200 // Create a new generic types table for visiting this inner class.
201 @SuppressWarnings("unchecked")
202 HashMap<String, SymbolData> genericTypes = (HashMap<String, SymbolData>) _genericTypes.clone();
203 TypeParameter[] tps = that.getTypeParameters();
204 for (TypeParameter tp: tps) {
205 final String typeName = tp.getVariable().getName();
206 final String boundName = tp.getBound().getName();
207 SymbolData boundSD = _identifyType(boundName, that.getSourceInfo(), _enclosingClassName);
208 if (boundSD == null) { // create a dummy SymbolData
209 boundSD = symbolTable.get("java.lang.Object"); // TODO: could create a separate SymbolData.NOT_BOUND singleton class?
210 // System.err.println("Creating dummy SymbolData for bounding type " + typeName + " in inner class " + name);
211 }
212 genericTypes.put(typeName, boundSD);
213 }
214
215 /* The following two lines apparently do nothing. Note that they are NOT in the scope of the new generic types
216 * table. TODO: confirm that these two lines do nothing and eliminate them. */
217 that.getSuperclass().visit(this);
218 for (int i = 0; i < that.getInterfaces().length; i++) that.getInterfaces()[i].visit(this);
219
220 /* The following line is NOT in the scope of the new generic type table but should be. Since we are not
221 * performing generic type checking, we may get away with the error. TODO: refactor this code to
222 * create a new LLV for processing a generic class. */
223 SymbolData sd = defineInnerSymbolData(that, relName, name, data);
224 // The preceding only fails if there is an error in the program
225
226 if (sd != null) { // We have a symbol data to work with, so visit the body using the new generic types table
227 identifyInnerClasses(that);
228 ClassBodyFullJavaVisitor cbfjv =
229 new ClassBodyFullJavaVisitor(sd, _file, _package, _importedFiles, _importedPackages, _classesInThisFile,
230 continuations, fixUps, genericTypes);
231 that.getBody().visit(cbfjv);
232 }
233
234 // Inner classes are not put into _classesInThisFile since they are parsed whenever their outer classes are parsed.
235
236 forInnerClassDefOnly(that);
237 }
238
239 /** Process the inner interface, and resolve it and store it in the
240 * outer class's list of inner classes. This method is common to both ClassBodyIntermediateVisitor
241 * and InterfaceBodyIntermediateVisitor but needs the correct SymbolData so we pass it in. This method is tested
242 * in those files.
243 */
244 protected void handleInnerInterfaceDef(InnerInterfaceDef that, Data data, String relName, String name) {
245 // System.err.println("Processing InnerInterfaceDef for " + name);
246 assert (data instanceof SymbolData) || (data instanceof MethodData);
247
248 forInnerInterfaceDefDoFirst(that);
249 if (prune(that)) return;
250
251 that.getMav().visit(this);
252 that.getName().visit(this);
253
254 // Create a new generic types table for visiting this inner class.
255 // TODO: refactor this code to combine common code patterns in this method and forInnerClassDef
256 @SuppressWarnings("unchecked")
257 HashMap<String, SymbolData> genericTypes = (HashMap<String, SymbolData>) _genericTypes.clone();
258 TypeParameter[] tps = that.getTypeParameters();
259 for (TypeParameter tp: tps) {
260 final String typeName = tp.getVariable().getName();
261 final String boundName = tp.getBound().getName();
262 SymbolData boundSD = _identifyType(boundName, that.getSourceInfo(), _enclosingClassName);
263 if (boundSD == null) { // create a dummy SymbolData
264 boundSD = symbolTable.get("java.lang.Object"); // TODO: could create a separate SymbolData.NOT_BOUND singleton class?
265 // System.err.println("Creating dummy SymbolData for bounding type " + typeName + " in inner class " + name);
266 // TODO! !!!!! Create an appropriate fixUp mechanism
267 }
268 genericTypes.put(typeName, boundSD);
269 }
270
271 /* The following line apparently does nothing. Note that it is NOT in the scope of the new generic types
272 * table. TODO: confirm that this line does nothing and eliminate it. */
273 for (int i = 0; i < that.getInterfaces().length; i++) that.getInterfaces()[i].visit(this);
274
275 /* The following line is NOT in the scope of the new generic type table but should be. Since we are not
276 * performing generic type checking, we may get away with the error. TODO: refactor this code to
277 * create a new LLV for processing a generic class. */
278 SymbolData sd = defineInnerSymbolData(that, relName, name, data); // only returns null if error is encountered
279
280 if (sd != null) { // We have a symbol data to work with, so visit the body using the new generic types table
281 sd.setInterface(true);
282 identifyInnerClasses(that);
283 InterfaceBodyFullJavaVisitor ibfjv =
284 new InterfaceBodyFullJavaVisitor(sd, _file, _package, _importedFiles, _importedPackages, _classesInThisFile,
285 continuations, fixUps, genericTypes);
286 that.getBody().visit(ibfjv);
287 }
288
289 forInnerInterfaceDefOnly(that);
290 }
291
292 /** Process ModifiersAndVisibility. */
293 public Void forModifiersAndVisibilityDoFirst(ModifiersAndVisibility that) {
294 String[] modifiersAndVisibility = that.getModifiers();
295 StringBuffer sb = new StringBuffer();
296 String temp;
297 int count = 0;
298 for(int i = 0; i < modifiersAndVisibility.length; i++) {
299 temp = modifiersAndVisibility[i];
300 if (!(temp.equals("abstract") || temp.equals("public") || temp.equals("private") || temp.equals("protected") ||
301 temp.equals("static") || temp.equals("final"))) {
302 sb.append(" \"" + temp + "\"");
303 count++;
304 }
305 }
306 // Do NOT check for illegal keywords. We are only building a symbol table. The javac compiler checks for errors.
307 return super.forModifiersAndVisibilityDoFirst(that);
308 }
309
310 /** Process SwitchStatement. */
311 public Void forSwitchStatementDoFirst(SwitchStatement that) { return super.forSwitchStatementDoFirst(that); }
312
313 /* Ignore instance initializer. */
314 public Void forInstanceInitializerDoFirst(InstanceInitializer that) { return null; }
315
316 /* Ignore static initializer. */
317 public Void forStaticInitializerDoFirst(StaticInitializer that) { return null; }
318
319 /* Ignore labeled statement. */
320 public Void forLabeledStatementDoFirst(LabeledStatement that) { return null; }
321
322 /* Ignore LabeledBreakStatement. */
323 public Void forLabeledBreakStatementDoFirst(LabeledBreakStatement that) { return null; }
324
325 /* Ignore LabeledContinue Statement. */
326 public Void forLabeledContinueStatementDoFirst(LabeledContinueStatement that) { return null; }
327
328 /* Ignore SynchronizedStatement. */
329 public Void forSynchronizedStatementDoFirst(SynchronizedStatement that) { return null; }
330
331 /** Ignore TypeParameter. */
332 public Void forTypeParameterDoFirst(TypeParameter that) { return null; }
333
334 /** Ignore ConditionalExpression. */
335 public Void forConditionalExpressionDoFirst(ConditionalExpression that) { return null; }
336
337 /** Ignore instanceofExpression. */
338 public Void forInstanceofExpressionDoFirst(InstanceofExpression that) { return null; }
339
340 /** Process PrimitiveType. */
341 public Void forPrimitiveTypeDoFirst(PrimitiveType that) { return super.forPrimitiveTypeDoFirst(that); }
342
343 // /* Process TryCatchStatement. */
344 // public Void forTryCatchStatementDoFirst(TryCatchStatement that) {
345 // return super.forTryCatchStatementDoFirst(that);
346 // }
347
348 /** Check to see if the specified className is a class defined in the current file.
349 * If it is, it will be stored in _classesInThisFile.
350 */
351 private boolean _isClassInCurrentFile(String className) {
352 Iterator<String> iter = _classesInThisFile.iterator();
353 while (iter.hasNext()) {
354 String s = iter.next();
355 if (s.equals(className) || s.endsWith('.' + className)) return true;
356 }
357 return false;
358 }
359
360 /** This overriding is a hack. The parameters to a static method can be referenced within the method itself,
361 * even though they are not declared to be static fields. Making them static has no effect on any other processing.
362 */
363 protected String[] getFormalParameterMav(Data d) {
364 return (d.hasModifier("static")) ? new String[] {"static"} : new String[] { };
365 }
366
367 /** Use the doFirst method to make sure there aren't any errors with the declaration. Then, use defineSymbolData to
368 * create the appropriate symbol data, and then visit the class body.
369 * Once the ClassDef has been handled, remove the class from _classesInThisFile so we know it's been taken care of.
370 * @param that The ClassDef being handled.
371 * TODO: refactor with same method in IntermediateVisitor; almost identical.
372 */
373 public Void forClassDef(ClassDef that) {
374 forClassDefDoFirst(that);
375 if (prune(that)) return null;
376
377 that.getMav().visit(this);
378 that.getName().visit(this);
379
380 String className = getQualifiedClassName(that.getName().getText());
381
382 // Create a new generic types table for visiting this class.
383 // TODO: refactor this code to combine common code patterns in this method and forInnerClassDef
384 @SuppressWarnings("unchecked")
385 HashMap<String, SymbolData> genericTypes = (HashMap<String, SymbolData>) _genericTypes.clone();
386 TypeParameter[] tps = that.getTypeParameters();
387 for (TypeParameter tp: tps) {
388 final String typeName = tp.getVariable().getName();
389 final String boundName = tp.getBound().getName();
390 SymbolData boundSD = _identifyType(boundName, that.getSourceInfo(), _enclosingClassName);
391 if (boundSD == null) { // create a dummy SymbolData
392 boundSD = symbolTable.get("java.lang.Object"); // TODO: could create a separate SymbolData.NOT_BOUND singleton class?
393 // System.err.println("Creating dummy SymbolData for bounding type " + typeName + " in inner class " + name);
394 }
395 genericTypes.put(typeName, boundSD);
396 }
397
398 /* The following line is NOT in the scope of the new generic type table but should be. Since we are not
399 * performing generic type checking, we may get away with the error. TODO: refactor this code to
400 * create a new LLV for processing a generic class. */
401 SymbolData sd = defineSymbolData(that, className);
402
403 /* The following two lines apparently do nothing. They are in the wrong generic type scope. */
404 that.getSuperclass().visit(this);
405 for (int i = 0; i < that.getInterfaces().length; i++) that.getInterfaces()[i].visit(this);
406
407 if (sd != null) {
408 // System.err.println("********** Calling identifyInnerClasses for SymbolData " + sd.getName());
409 identifyInnerClasses(that);
410 ClassBodyFullJavaVisitor cbfjv =
411 new ClassBodyFullJavaVisitor(sd, _file, _package, _importedFiles, _importedPackages, _classesInThisFile,
412 continuations, fixUps, genericTypes);
413 that.getBody().visit(cbfjv);
414 }
415 forClassDefOnly(that);
416
417 return null;
418 }
419
420 /** This is a noop, because we do not do code augmentation at the Advanced Level. */
421 protected void createToString(SymbolData sd) { return; }
422
423 /** This is a noop, because we do not do code augmentation at the Advanced Level. */
424 protected void createHashCode(SymbolData sd) { return; }
425
426 /** This is a noop, because we do not do code augmentation at the Advanced Level. */
427 protected void createEquals(SymbolData sd) { return; }
428
429 /** Create a SymbolData corresponding to this interface and add it appropriately.
430 * Then visit the body to handle anything defined inside the interface.
431 * Once the interface has been resolved, remove it from _classesInThisFile.
432 * TODO: refactor with same method in IntermediateVisitor; they appear identical
433 */
434 public Void forInterfaceDef(InterfaceDef that) {
435 forInterfaceDefDoFirst(that);
436 if (prune(that)) return null;
437
438 String className = getQualifiedClassName(that.getName().getText());
439 // if (className.equals("listFW.IList")) System.err.println("Attempting to define symbol " + className);
440
441 SymbolData sd = defineSymbolData(that, className);
442 // TODO: should the preceding statement follow interface processing in 345
443
444 // Note: sd can only be null if an error occurs in defineSymbol
445 if (sd != null) sd.setInterface(true);
446
447 that.getMav().visit(this);
448 that.getName().visit(this);
449
450 // Create a new generic types table for visiting this interface.
451 // TODO: refactor this code to combine common code patterns in this method and forInnerClassDef
452 @SuppressWarnings("unchecked")
453 HashMap<String, SymbolData> genericTypes = (HashMap<String, SymbolData>) _genericTypes.clone();
454 TypeParameter[] tps = that.getTypeParameters();
455 for (TypeParameter tp: tps) {
456 final String typeName = tp.getVariable().getName();
457 final String boundName = tp.getBound().getName();
458 SymbolData boundSD = _identifyType(boundName, that.getSourceInfo(), _enclosingClassName);
459 if (boundSD == null) { // create a dummy SymbolData
460 boundSD = symbolTable.get("java.lang.Object"); // TODO: could create a separate SymbolData.NOT_BOUND singleton class?
461 // System.err.println("Creating dummy SymbolData for bounding type " + typeName + " in inner class " + name);
462 }
463 genericTypes.put(typeName, boundSD);
464 }
465
466 /* The following line apparently does nothing. Note that it is NOT in the scope of the new generic types
467 * table. TODO: confirm that this line does nothing and eliminate it. */
468 for (int i = 0; i < that.getInterfaces().length; i++) that.getInterfaces()[i].visit(this);
469
470 if (sd != null) {
471 sd.setInterface(true);
472 identifyInnerClasses(that);
473 InterfaceBodyFullJavaVisitor ibfjv =
474 new InterfaceBodyFullJavaVisitor(sd, _file, _package, _importedFiles, _importedPackages, _classesInThisFile,
475 continuations, fixUps, genericTypes);
476 that.getBody().visit(ibfjv);
477 }
478
479 forInterfaceDefOnly(that);
480 _classesInThisFile.remove(className);
481 return null;
482 }
483
484 /** Look up the super type of this class instantiation and add it to the symbol table. Visit the body of the class
485 * instantiation. All handling of this as an anonymous inner class (i.e. adding it to the enclosing SD's list of
486 * inner classes, creating a symbol data for the anonyomous inner class, etc) is handled in the TypeChecker pass.
487 * This is because no one will depend on that symbolData until we create it.
488 * @param that The SimpleAnonymousClassInstantiation being processed.
489 * @param enclosing The SymbolData of the enclosing class.
490 */
491 public void simpleAnonymousClassInstantiationHelper(SimpleAnonymousClassInstantiation that, SymbolData enclosing) {
492 /* Nested inner computation (e.g., new E().new W()) breaks conformity checking. So we suppress it. */
493 }
494
495 /** Do not resolve the super class type of this instantiation, because it will have already been resolved (it
496 * is an inner class of the enclosing of this instantiation. When the enclosing was resolved, all of its inner
497 * classes should have also been resolved).
498 * Visit the body of the class instantiation.
499 * @param that The ComplexAnonymousClassInstantiation being processed.
500 * @param enclosing The SymbolData of the enclosing class.
501 */
502 public void complexAnonymousClassInstantiationHelper(ComplexAnonymousClassInstantiation that, SymbolData enclosing) {
503 /* Nested inner computation (e.g., new E().new W()) breaks conformity checking. So we suppress it. */
504 }
505
506 /* Resolve the ArrayType by looking it up. */
507 public Void forArrayType(ArrayType that) {
508 forArrayTypeDoFirst(that);
509 if (prune(that)) return null;
510 // System.err.println("###### getSymbolData on " + that.getName() + " SHOULD BE ARRAY NAME");
511 getSymbolData(that.getName(), that.getSourceInfo());
512 return null;
513 }
514
515 /** Test the methods defined in the enclosing class. There is a test method corresponding to almost every method in
516 * the above class.
517 * TODO: WHICH IS WRONG! Many of the methods in FullJavaVisitor are invoked at the level of ClassBodyFullJavaVisitor
518 * and BodyBodyFullJavaVisitor. Moreover, they rely on overrides that are present only at that subclass level. Move
519 * the tests that relate to subclasses to the appropriate subclasses!
520 */
521 public static class FullJavaVisitorTest extends TestCase {
522
523 /*Some initial initializations:*/
524 private FullJavaVisitor _fv;
525
526 private SymbolData _sd1;
527 private SymbolData _sd2;
528 private SymbolData _sd3;
529 private SymbolData _sd4;
530 private SymbolData _sd5;
531 private SymbolData _sd6;
532 private SymbolData _objectSD;
533
534 private ModifiersAndVisibility _publicMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"});
535 private ModifiersAndVisibility _protectedMav =
536 new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"protected"});
537 private ModifiersAndVisibility _privateMav =
538 new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"private"});
539 private ModifiersAndVisibility _packageMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[0]);
540 private ModifiersAndVisibility _abstractMav =
541 new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"abstract"});
542 private ModifiersAndVisibility _staticMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"static"});
543 private ModifiersAndVisibility _finalMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"final"});
544 private ModifiersAndVisibility _volatileMav =
545 new ModifiersAndVisibility(SourceInfo.NONE, new String[]{"volatile"});
546
547 public FullJavaVisitorTest() { this(""); }
548 public FullJavaVisitorTest(String name) { super(name); }
549
550 public void setUp() {
551 errors = new LinkedList<Pair<String, JExpressionIF>>();
552 LanguageLevelConverter.symbolTable.clear();
553 LanguageLevelConverter._newSDs.clear();
554 LanguageLevelConverter.OPT = new Options(JavaVersion.JAVA_5, IterUtil.make(new File("lib/buildlib/junit.jar")));
555 visitedFiles = new LinkedList<Pair<LanguageLevelVisitor, edu.rice.cs.javalanglevels.tree.SourceFile>>();
556 // _hierarchy = new Hashtable<String, TypeDefBase>();
557 _fv = new FullJavaVisitor(new File(""),
558 errors,
559 continuations,
560 new LinkedList<Command>(),
561 new LinkedList<Pair<LanguageLevelVisitor, SourceFile>>());
562 _fv._classesInThisFile = new HashSet<String>();
563 _fv.continuations = new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>();
564 _fv._importedPackages.addFirst("java.lang");
565 _errorAdded = false;
566
567 _sd1 = new SymbolData("i.like.monkey");
568 _sd2 = new SymbolData("i.like.giraffe");
569 _sd3 = new SymbolData("zebra");
570 _sd4 = new SymbolData("u.like.emu");
571 _sd5 = new SymbolData("");
572 _sd6 = new SymbolData("cebu");
573
574 _sd1.setIsContinuation(false);
575 _sd1.setInterface(false);
576 _sd1.setPackage("i.like");
577 _sd1.setTypeParameters(new TypeParameter[0]);
578 _sd1.setInterfaces(new ArrayList<SymbolData>());
579
580 _objectSD = LanguageLevelConverter.symbolTable.get("java.lang.Object");
581 _sd1.setSuperClass(_objectSD);
582
583 _fv._enclosingClassName = "i.like.monkey";
584 _fv.symbolTable.put("i.like.monkey", _sd1);
585
586 _sd1.setSuperClass(_objectSD);
587 _errorAdded = false; // static field of this. TODO: fix this!
588 }
589
590 public void initTopLevel() {
591 _fv._enclosingClassName = null;
592 }
593
594 public void testForModifiersAndVisibilityDoFirst() {
595
596 //Check that the proper modifiers are allowed:
597 _fv.forModifiersAndVisibilityDoFirst(_abstractMav);
598 _fv.forModifiersAndVisibilityDoFirst(_publicMav);
599 _fv.forModifiersAndVisibilityDoFirst(_privateMav);
600 _fv.forModifiersAndVisibilityDoFirst(_protectedMav);
601 _fv.forModifiersAndVisibilityDoFirst(_staticMav);
602 _fv.forModifiersAndVisibilityDoFirst(_finalMav);
603
604 ModifiersAndVisibility mavs = new ModifiersAndVisibility(SourceInfo.NONE,
605 new String[] {"private", "static"});
606 _fv.forModifiersAndVisibilityDoFirst(mavs);
607 assertEquals("there should still be 0 errors", 0, errors.size());
608
609 //check errors:
610
611 _fv.forModifiersAndVisibilityDoFirst(_volatileMav);
612 assertEquals("there should now be no errors", 0, errors.size());
613 // assertEquals("The error message should be correct for private modifier:",
614 // "The keyword \"volatile\" cannot be used at the Advanced level",
615 // errors.get(0).getFirst());
616
617 ModifiersAndVisibility mavs2 = new ModifiersAndVisibility(SourceInfo.NONE,
618 new String[] {"final", "volatile"});
619
620 _fv.forModifiersAndVisibilityDoFirst(mavs2);
621 assertEquals("There should now be 1 error", 1, errors.size());
622 assertEquals("The error message should be correct for 1 bad, 1 good modifier:",
623 "Illegal combination of modifiers. Can't use final and volatile together.",
624 errors.get(0).getFirst());
625
626 ModifiersAndVisibility mavs3 = new ModifiersAndVisibility(SourceInfo.NONE,
627 new String[] {"synchronized", "native"});
628
629 _fv.forModifiersAndVisibilityDoFirst(mavs3);
630 assertEquals("There should now be 1 errors", 1, errors.size());
631 // assertEquals("The error message should be correct for 2 bad modifiers:",
632 // "The keywords \"synchronized\" \"native\" cannot be used at the Advanced level",
633 // errors.get(1).getFirst());
634 }
635
636 public void testForClassDefDoFirst() {
637 // System.err.println("*** Starting testForClassDefDoFirst");
638 // check an example that works
639 ClassDef cd0 = new ClassDef(SourceInfo.NONE, _publicMav,
640 new Word(SourceInfo.NONE, "Lisa"),
641 new TypeParameter[0],
642 new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]),
643 new ReferenceType[0],
644 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
645
646 _fv.forClassDefDoFirst(cd0);
647 assertEquals("should be no errors", 0, errors.size());
648
649 // check that an error is not thrown if a class doesn't explicitely extend another class
650 ClassDef cd1 = new ClassDef(SourceInfo.NONE, _publicMav,
651 new Word(SourceInfo.NONE, "Test"), new TypeParameter[0], JExprParser.NO_TYPE,
652 new ReferenceType[0], new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
653
654 _fv.forClassDefDoFirst(cd1);
655 assertEquals("there should still be 0 errors", 0, errors.size());
656
657 //check that an error is not thrown if a class implements any interfaces.
658 ReferenceType rt2 = new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]);
659 ClassDef cd2 = new ClassDef(SourceInfo.NONE, _publicMav,
660 new Word(SourceInfo.NONE, "Test"), new TypeParameter[0],
661 new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]),
662 new ReferenceType[] { rt2 },
663 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
664
665
666 _fv.forClassDefDoFirst(cd2);
667 assertEquals("there should still be 0 errors", 0, errors.size());
668 // System.err.println("Ending testForClassDefDoFirst");
669 }
670
671 public void testForFormalParameterDoFirst() {
672 PrimitiveType pt = new PrimitiveType(SourceInfo.NONE, "int");
673 Word w = new Word(SourceInfo.NONE, "param");
674 UninitializedVariableDeclarator uvd = new UninitializedVariableDeclarator(SourceInfo.NONE, pt, w);
675
676 // check an example that works
677 FormalParameter fp = new FormalParameter(SourceInfo.NONE, uvd, false);
678 _fv.forFormalParameterDoFirst(fp);
679 assertEquals("should be no errors", 0, errors.size());
680
681 // check that no errors are thrown if the FormalParameter is final
682 FormalParameter fp2 = new FormalParameter(SourceInfo.NONE, uvd, true);
683 _fv.forFormalParameterDoFirst(fp2);
684 assertEquals("should still be no errors", 0, errors.size());
685 }
686
687 public void test_NotAllowed() {
688 SourceInfo noInfo = SourceInfo.NONE;
689 Word w = new Word(SourceInfo.NONE, "word");
690 TypeParameter[] tps = new TypeParameter[0];
691 ReferenceType[] rts = new ReferenceType[0];
692 BracedBody emptyBody = new BracedBody(SourceInfo.NONE, new BodyItemI[0]);
693 UnbracedBody emptyUnbracedBody = new UnbracedBody(SourceInfo.NONE, new BodyItemI[0]);
694 ClassOrInterfaceType superClass = new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]);
695 FormalParameter[] fps = new FormalParameter[0];
696 CompoundWord cw = new CompoundWord(noInfo, new Word[0]);
697 Statement stmt = new EmptyStatement(noInfo);
698 Expression e = new EmptyExpression(noInfo);
699 Block b = new Block(noInfo, emptyBody);
700 // ClassModifier cm = ClassModifier.NONE;
701 TypeVariable tv = new TypeVariable(noInfo, "name");
702
703 InnerInterfaceDef ii = new InnerInterfaceDef(noInfo, _publicMav, w, tps, rts, emptyBody);
704 InnerClassDef ic = new InnerClassDef(noInfo, _publicMav, w, tps, superClass, rts, emptyBody);
705
706 StaticInitializer si = new StaticInitializer(noInfo, b);
707 LabeledStatement ls = new LabeledStatement(noInfo, new Word(noInfo, "label"), stmt);
708
709 LabeledBreakStatement bs = new LabeledBreakStatement(noInfo, new Word(noInfo, "myLabel"));
710 LabeledContinueStatement cs = new LabeledContinueStatement(noInfo, new Word(noInfo, "yourLabel"));
711 SimpleNameReference snr = new SimpleNameReference(noInfo, w);
712 SynchronizedStatement syncs = new SynchronizedStatement(noInfo, snr, b);
713 TypeParameter tp = new TypeParameter(noInfo, tv, superClass);
714 ConditionalExpression ce = new ConditionalExpression(noInfo, snr, snr, snr);
715
716 TryCatchStatement tcs = new NormalTryCatchStatement(noInfo, b, new CatchBlock[0]);
717 SwitchCase defaultSc = new DefaultCase(SourceInfo.NONE, emptyUnbracedBody);
718 SwitchStatement ssBadDefault =
719 new SwitchStatement(noInfo, new IntegerLiteral(SourceInfo.NONE, 5), new SwitchCase[]{defaultSc, defaultSc});
720
721 si.visit(_fv);
722 assertEquals("There should be 0 errors", 0, errors.size());
723
724 ls.visit(_fv);
725 assertEquals("There should be 0 errors", 0, errors.size());
726
727 bs.visit(_fv);
728 assertEquals("There should be 0 errors", 0, errors.size());
729
730 cs.visit(_fv);
731 assertEquals("There should be 0 errors", 0, errors.size());
732
733 syncs.visit(_fv);
734 assertEquals("There should be 0 errors", 0, errors.size());
735
736 tp.visit(_fv);
737 assertEquals("There should be 0 errors", 0, errors.size());
738
739 ce.visit(_fv);
740 assertEquals("There should be 0 errors", 0, errors.size());
741
742 tcs.visit(_fv);
743 assertEquals("There should be 0 errors", 0, errors.size());
744
745 ssBadDefault.visit(_fv);
746 assertEquals("There should be 0 errors", 0, errors.size());
747 }
748
749 public void testForPrimitiveTypeDoFirst() {
750
751 SourceInfo noInfo = SourceInfo.NONE;
752
753 //only primative types boolean, char, int, and double are allowed at Intermediate level.
754 PrimitiveType i = new PrimitiveType(noInfo, "int");
755 PrimitiveType c = new PrimitiveType(noInfo, "char");
756 PrimitiveType d = new PrimitiveType(noInfo, "double");
757 PrimitiveType b = new PrimitiveType(noInfo, "boolean");
758
759 i.visit(_fv);
760 assertEquals("After visiting int, errors should still be 0", 0, errors.size());
761
762 c.visit(_fv);
763 assertEquals("After visiting char, errors should still be 0", 0, errors.size());
764
765 d.visit(_fv);
766 assertEquals("After visiting double, errors should still be 0", 0, errors.size());
767
768 b.visit(_fv);
769 assertEquals("After visiting boolean, errors should still be 0", 0, errors.size());
770
771 // now the types that formerly threw errors:
772
773 PrimitiveType byt = new PrimitiveType(noInfo, "byte");
774 PrimitiveType s = new PrimitiveType(noInfo, "short");
775 PrimitiveType l = new PrimitiveType(noInfo, "long");
776 PrimitiveType f = new PrimitiveType(noInfo, "float");
777
778 byt.visit(_fv);
779 assertEquals("After visiting byte, errors should be 0", 0, errors.size());
780
781 s.visit(_fv);
782 assertEquals("After visiting short, errors should be 0", 0, errors.size());
783
784 l.visit(_fv);
785 assertEquals("After visiting long, errors should be 0", 0, errors.size());
786
787 f.visit(_fv);
788 assertEquals("After visiting float, errors should be 0", 0, errors.size());
789 }
790
791 public void testForArrayType() {
792 // System.err.println("**** Starting testForArrayType");
793 SymbolData sd = new SymbolData("Name");
794 sd.setIsContinuation(false);
795 sd.setInterface(false);
796 sd.setPackage("");
797 sd.setTypeParameters(new TypeParameter[0]);
798 sd.setInterfaces(new ArrayList<SymbolData>());
799 sd.setSuperClass(LanguageLevelConverter.symbolTable.get("java.lang.Object"));
800 LanguageLevelConverter.symbolTable.put("Name", sd);
801
802 ArrayInitializer ai = new ArrayInitializer(SourceInfo.NONE, new VariableInitializerI[0]);
803 TypeVariable tv = new TypeVariable(SourceInfo.NONE, "Name");
804 ArrayType at = new ArrayType(SourceInfo.NONE, "Name[]", tv);
805
806 at.visit(_fv);
807 assertEquals("There should be no errors", 0, errors.size());
808 SymbolData asd = LanguageLevelConverter.symbolTable.get("Name[]");
809 assertNotNull("asd should not be null", asd);
810 ArrayData ad = (ArrayData) asd;
811 assertEquals("ad should have an elt sd of name 'Name'", "Name", ad.getElementType().getName());
812
813 //Test a multi-dimensional array
814 tv = new TypeVariable(SourceInfo.NONE, "java.lang.Object");
815 at = new ArrayType(SourceInfo.NONE, "Object[]", tv);
816 ArrayType at2 = new ArrayType(SourceInfo.NONE, "Object[][]", at);
817
818 at2.visit(_fv);
819 assertEquals("There should be no errors", 0, errors.size());
820 assertNotNull("Object should be in the symbolTable", LanguageLevelConverter.symbolTable.get("java.lang.Object"));
821 assertNotNull("Object[] should be in the symbolTable",
822 LanguageLevelConverter.symbolTable.get("java.lang.Object[]"));
823 assertNotNull("Object[][] should be in the symbolTable",
824 LanguageLevelConverter.symbolTable.get("java.lang.Object[][]"));
825 }
826
827 // TODO: resurrect a test of this method
828 // public void testCreateConstructor() {
829 // SymbolData sd =
830 // new SymbolData("ClassName", _publicMav, new TypeParameter[0], null, new LinkedList<SymbolData>(), null);
831 // VariableData v1 = new VariableData("i", _publicMav, SymbolData.INT_TYPE, false, sd);
832 // VariableData v2 = new VariableData("j", _publicMav, SymbolData.CHAR_TYPE, false, sd);
833 // VariableData v3 = new VariableData("var", _publicMav, SymbolData.DOUBLE_TYPE, false, sd);
834 // sd.addVar(v1);
835 // sd.addVar(v2);
836 // sd.setSuperClass(_sd1);
837 //
838 // MethodData md = new MethodData("ClassName", _publicMav, new TypeParameter[0], sd,
839 // new VariableData[0],
840 // new String[0],
841 // sd,
842 // null);
843 // md.addVars(md.getParams());
844 // _fv.createConstructor(sd);
845 //
846 // assertEquals("sd should have 1 method: its own constructor", md, sd.getMethods().getFirst());
847 //
848 // // since this is the only constructor in the symbol data, all the fields should be assigned to have a value after
849 // // visiting sd.
850 // v1 = new VariableData("i", _publicMav, SymbolData.INT_TYPE, true, sd);
851 // v2 = new VariableData("j", _publicMav, SymbolData.CHAR_TYPE, true, sd);
852 //
853 //
854 // //now test a subclass of sd:
855 // SymbolData subSd =
856 // new SymbolData("Subclass",_publicMav, new TypeParameter[0], null, new ArrayList<SymbolData>(), null);
857 // subSd.addVar(v3);
858 // subSd.setSuperClass(sd);
859 //
860 //
861 // VariableData v1Param = new VariableData("super_i", _packageMav, SymbolData.INT_TYPE, true, null);
862 // VariableData v2Param = new VariableData("super_j", _packageMav, SymbolData.CHAR_TYPE, true, null);
863 // VariableData[] vars = {v1Param, v2Param, v3};
864 // MethodData md2 = new MethodData("Subclass", _publicMav, new TypeParameter[0], subSd,
865 // new VariableData[0], new String[0], subSd, null);
866 // md2.addVars(md2.getParams());
867 //
868 // _fv.createConstructor(subSd);
869 // v1Param.setEnclosingData(subSd.getMethods().getFirst());
870 // v2Param.setEnclosingData(subSd.getMethods().getFirst());
871 // assertEquals("subSd should have 1 method: its own constructor.", md2, subSd.getMethods().getFirst());
872 // }
873 //
874 // public void xtest_getFieldAccessorName() {
875 // // This may change in the future if we change getFieldAccessorName
876 // assertEquals("Should correctly convert from lower case to upper case", "name", _fv.getFieldAccessorName("name"));
877 // }
878
879 //ToString, HashCode, and Equals should be no-ops.
880 public void testCreateToString() {
881 SymbolData sd =
882 new SymbolData("ClassName", _publicMav, new TypeParameter[0], null, new ArrayList<SymbolData>(), null);
883 _fv.createToString(sd);
884 //should have been no-op
885 assertEquals("sd should have no methods", 0, sd.getMethods().size());
886 }
887
888 public void testCreateHashCode() {
889 SymbolData sd =
890 new SymbolData("ClassName", _publicMav, new TypeParameter[0], null, new ArrayList<SymbolData>(), null);
891 _fv.createHashCode(sd);
892 //should have been no-op
893 assertEquals("sd should have 0 methods", 0, sd.getMethods().size());
894 }
895
896 public void testCreateEquals() {
897 SymbolData sd =
898 new SymbolData("ClassName", _publicMav, new TypeParameter[0], null, new ArrayList<SymbolData>(), null);
899 _fv.createEquals(sd);
900 //should have been no-op
901 assertEquals("sd should have 0 methods", 0, sd.getMethods().size());
902 }
903
904 public void testForClassDef() {
905 // System.err.println("**** Starting testForClassDef");
906 //check an example that's not abstract
907
908 // Top-level init
909 initTopLevel();
910
911 ClassDef cd0 =
912 new ClassDef(SourceInfo.NONE, _packageMav,
913 new Word(SourceInfo.NONE, "Lisa"),
914 new TypeParameter[0],
915 new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]),
916 new ReferenceType[0],
917 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
918
919 cd0.visit(_fv);
920 assertEquals("There should be no errors", 0, errors.size());
921 assertTrue("Should have resolved java.lang.Object",
922 LanguageLevelConverter.symbolTable.containsKey("java.lang.Object"));
923 assertFalse("Should not be a continuation",
924 LanguageLevelConverter.symbolTable.get("java.lang.Object").isContinuation());
925 SymbolData sd = LanguageLevelConverter.symbolTable.get("Lisa");
926 assertTrue("Lisa should be in _newSDs", LanguageLevelConverter._newSDs.containsKey(sd));
927 assertEquals("sd should have no methods", 0, sd.getMethods().size());
928 assertEquals("sd's package should be correct", "", sd.getPackage());
929
930 // check an example that's abstract
931 assert _fv._package == "";
932 ClassDef cd1 =
933 new ClassDef(SourceInfo.NONE, _abstractMav, new Word(SourceInfo.NONE, "Bart"),
934 new TypeParameter[0],
935 new ClassOrInterfaceType(SourceInfo.NONE, "System", new Type[0]),
936 new ReferenceType[0],
937 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
938 cd1.visit(_fv);
939 assertEquals("There should be no errors", 0, errors.size());
940 assertTrue("Should have resolved java.lang.System",
941 LanguageLevelConverter.symbolTable.containsKey("java.lang.System"));
942 assertFalse("Should not be a continuation",
943 LanguageLevelConverter.symbolTable.get("java.lang.System").isContinuation());
944 sd = LanguageLevelConverter.symbolTable.get("Bart");
945
946 assertEquals("There should be 0 methods", 0, sd.getMethods().size()); //(no code augmentation is done)
947
948 //Check an example where the class extends TestCase, and has a test method that returns void.
949 ConcreteMethodDef cmd = new ConcreteMethodDef(SourceInfo.NONE,
950 _packageMav,
951 new TypeParameter[0],
952 new VoidReturn(SourceInfo.NONE, "void"),
953 new Word(SourceInfo.NONE, "testMethodName"),
954 new FormalParameter[0],
955 new ReferenceType[0],
956 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
957
958 ClassDef cd3 =
959 new ClassDef(SourceInfo.NONE,
960 _abstractMav,
961 new Word(SourceInfo.NONE, "TestSuper2"),
962 new TypeParameter[0], new ClassOrInterfaceType(SourceInfo.NONE, "TestCase", new Type[0]),
963 new ReferenceType[0],
964 new BracedBody(SourceInfo.NONE, new BodyItemI[] {cmd}));
965
966
967 _fv._file = new File("TestSuper2.dj2");
968 _fv._importedFiles.addLast("junit.framework.TestCase");
969 LanguageLevelConverter.symbolTable.put("junit.framework.TestCase", new SymbolData("junit.framework.TestCase"));
970 cd3.visit(_fv);
971 assertEquals("There should still just be no errors", 0, errors.size());
972 assertNotNull("Should have looked up TestSuper2",
973 LanguageLevelConverter.symbolTable.get("TestSuper2"));
974
975 //Check a method with void return, but name not starting with test, so it's not okay.
976 //This is now checked in the type checker!
977 ConcreteMethodDef cmd2 = new ConcreteMethodDef(SourceInfo.NONE,
978 _packageMav,
979 new TypeParameter[0],
980 new VoidReturn(SourceInfo.NONE, "void"),
981 new Word(SourceInfo.NONE, "uhOh"),
982 new FormalParameter[0],
983 new ReferenceType[0],
984 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
985
986 ClassDef cd4 =
987 new ClassDef(SourceInfo.NONE,
988 _abstractMav,
989 new Word(SourceInfo.NONE, "TestVoidNoTestMethod"),
990 new TypeParameter[0],
991 new ClassOrInterfaceType(SourceInfo.NONE,"junit.framework.TestCase", new Type[0]),
992 new ReferenceType[0],
993 new BracedBody(SourceInfo.NONE, new BodyItemI[] { cmd2 }));
994
995 _fv._file = new File("TestVoidNoTestMethod.dj2");
996 cd4.visit(_fv);
997
998 assertEquals("There should still be 0 errors", 0, errors.size());
999 _fv._importedFiles.remove("junit.framework.TestCase");
1000 // System.err.println("**** Ending testForClassDef");
1001 }
1002
1003 public void testForInterfaceDef() {
1004 AbstractMethodDef amd =
1005 new AbstractMethodDef(SourceInfo.NONE,
1006 _publicMav,
1007 new TypeParameter[0],
1008 new PrimitiveType(SourceInfo.NONE, "int"),
1009 new Word(SourceInfo.NONE, "myMethod"),
1010 new FormalParameter[0],
1011 new ReferenceType[0]);
1012 AbstractMethodDef amd2 =
1013 new AbstractMethodDef(SourceInfo.NONE,
1014 _publicMav,
1015 new TypeParameter[0],
1016 new PrimitiveType(SourceInfo.NONE, "int"),
1017 new Word(SourceInfo.NONE, "myMethod"),
1018 new FormalParameter[0],
1019 new ReferenceType[0]);
1020 InterfaceDef id =
1021 new InterfaceDef(SourceInfo.NONE,
1022 _publicMav,
1023 new Word(SourceInfo.NONE, "id"),
1024 new TypeParameter[0],
1025 new ReferenceType[0],
1026 new BracedBody(SourceInfo.NONE, new BodyItemI[] { amd }));
1027 InterfaceDef id2 =
1028 new InterfaceDef(SourceInfo.NONE,
1029 _publicMav,
1030 new Word(SourceInfo.NONE, "id2"),
1031 new TypeParameter[0],
1032 new ReferenceType[] { new ClassOrInterfaceType(SourceInfo.NONE, "id", new Type[0]) },
1033 new BracedBody(SourceInfo.NONE, new BodyItemI[] { amd2 }));
1034 SymbolData sd = new SymbolData("i.like.monkey.id", _publicMav, new TypeParameter[0], new ArrayList<SymbolData>(), null);
1035 sd.setIsContinuation(true);
1036 MethodData md =
1037 new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE, new VariableData[0],
1038 new String[0], sd, amd);
1039
1040 ArrayList<SymbolData> interfaces = new ArrayList<SymbolData>();
1041 interfaces.add(sd);
1042 SymbolData sd2 = new SymbolData("i.like.monkey.id2", _publicMav, new TypeParameter[0], interfaces, null);
1043 sd2.setIsContinuation(true);
1044 MethodData md2 =
1045 new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE, new VariableData[0],
1046 new String[0], sd2, amd2);
1047
1048 LanguageLevelConverter.symbolTable.put("i.like.monkey.id", sd);
1049 LanguageLevelConverter.symbolTable.put("i.like.monkey.id2", sd2);
1050
1051 id.visit(_fv);
1052 id2.visit(_fv);
1053 assertEquals("Should be no errors", 0, errors.size());
1054 assertEquals("Should return the same symbol datas: id", sd,
1055 LanguageLevelConverter.symbolTable.get("i.like.monkey.id"));
1056 assertEquals("Should return the same symbol datas:id2 ", sd2,
1057 LanguageLevelConverter.symbolTable.get("i.like.monkey.id2"));
1058 }
1059
1060 public void testHandleInnerClassDef() {
1061 // System.err.println("**** Starting testHandleInnerClassDef");
1062 // setUp has created a FullJavaVisitor which initializes the symbolTable
1063
1064 // LanguageLevelConverter.symbolTable.put("java.lang.Object", _objectSD);
1065 InnerClassDef cd1 =
1066 new InnerClassDef(SourceInfo.NONE,
1067 _packageMav,
1068 new Word(SourceInfo.NONE, "Bart"),
1069 new TypeParameter[0],
1070 new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]),
1071 new ReferenceType[0],
1072 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1073 InnerClassDef cd0 =
1074 new InnerClassDef(SourceInfo.NONE,
1075 _packageMav,
1076 new Word(SourceInfo.NONE, "Lisa"),
1077 new TypeParameter[0],
1078 new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]),
1079 new ReferenceType[0],
1080 new BracedBody(SourceInfo.NONE, new BodyItemI[] { cd1 }));
1081
1082 // SymbolData outerData = new SymbolData("i.eat.potato");
1083 // outerData.setIsContinuation(false);
1084 // outerData.setSuperClass(_objectSD);
1085
1086 // SymbolData sd0 =
1087 // new SymbolData(outerData.getName() + "$Lisa", _packageMav, new TypeParameter[0], _objectSD,
1088 // new ArrayList<SymbolData>(), null);
1089 // SymbolData sd1 =
1090 // new SymbolData(outerData.getName() + "$Lisa$Bart", _packageMav, new TypeParameter[0], _objectSD,
1091 // new ArrayList<SymbolData>(), null);
1092 //
1093 // outerData.addInnerClass(sd0);
1094 // sd0.setOuterData(outerData);
1095 //
1096 // sd0.addInnerClass(sd1);
1097 // sd1.setOuterData(sd0);
1098
1099 // sd0.setIsContinuation(true);
1100 // sd1.setIsContinuation(true);
1101
1102 // LanguageLevelConverter.symbolTable.put(outerData.getName() + "$Lisa", sd0);
1103
1104 _fv.handleInnerClassDef(cd0, _sd1, "Lisa", _sd1.getName() + ".Lisa");
1105
1106 SymbolData sd0 = _sd1.getInnerClassOrInterface("Lisa");
1107 assertEquals("There should be no errors", 0, errors.size());
1108 assertNotNull("Lisa is inner class of i.like.monkey", sd0);
1109 assertEquals("sd0 should have the correct outer data", _sd1, sd0.getOuterData());
1110 assertEquals("Lisa should have 0 methods", 0, sd0.getMethods().size());
1111 assertNotNull("symbolTable contains fully qualified name for Lisa",
1112 _fv.getQualifiedSymbolData("i.like.monkey.Lisa"));
1113
1114 SymbolData sd1 = sd0.getInnerClassOrInterface("Bart");
1115 assertEquals("There should be no errors", 0, errors.size());
1116 assertNotNull("Bart is inner class of Lisa", sd1);
1117 assertEquals("sd1 should have the correct outer data", sd0, sd1.getOuterData());
1118 assertEquals("Bart should have 0 methods", 0, sd1.getMethods().size());
1119 assertNotNull("symbolTable contains fully qualified name for Bart",
1120 _fv.getQualifiedSymbolData("i.like.monkey.Lisa.Bart"));
1121 // System.err.println("**** Ending testHandleInnerClassDef");
1122 }
1123
1124 public void xtestHandleInnerInterfaceDef() {
1125 InnerInterfaceDef cd1 =
1126 new InnerInterfaceDef(SourceInfo.NONE, _packageMav, new Word(SourceInfo.NONE, "Bart"),
1127 new TypeParameter[0], new ReferenceType[0],
1128 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1129
1130 InnerInterfaceDef cd0 =
1131 new InnerInterfaceDef(SourceInfo.NONE, _packageMav, new Word(SourceInfo.NONE, "Lisa"),
1132 new TypeParameter[0], new ReferenceType[0],
1133 new BracedBody(SourceInfo.NONE, new BodyItemI[] { cd1 }));
1134
1135 SymbolData outerData = new SymbolData("i.drink.vanilla.coke");
1136
1137
1138 SymbolData sd0 =
1139 new SymbolData(outerData.getName() + "$Lisa", _packageMav, new TypeParameter[0], new ArrayList<SymbolData>(),
1140 null);
1141 SymbolData sd1 =
1142 new SymbolData(outerData.getName() + "$Lisa$Bart", _packageMav, new TypeParameter[0],
1143 new ArrayList<SymbolData>(), null);
1144 sd0.addInnerInterface(sd1);
1145 sd0.setIsContinuation(true);
1146 sd1.setIsContinuation(true);
1147
1148 outerData.addInnerInterface(sd0);
1149 sd0.setOuterData(outerData);
1150
1151 sd0.addInnerInterface(sd1);
1152 sd1.setOuterData(sd0);
1153
1154 sd0.setIsContinuation(true);
1155 sd1.setIsContinuation(true);
1156
1157
1158 _fv.handleInnerInterfaceDef(cd0, outerData, "Lisa", outerData.getName() + "$Lisa");
1159
1160 SymbolData sd = outerData.getInnerClassOrInterface("Lisa");
1161
1162 assertEquals("There should be no errors", 0, errors.size());
1163 assertEquals("This symbolData should now have sd0 as an inner interface", sd0, sd);
1164 assertEquals("sd0 should have the correct outer data", outerData, sd0.getOuterData());
1165 assertEquals("sd1 should have the correct outer data", sd0, sd1.getOuterData());
1166 assertEquals("Sd should now have sd1 as an inner interface", sd1, sd.getInnerClassOrInterface("Bart"));
1167 assertTrue("Lisa should be an interface", sd0.isInterface());
1168 assertTrue("Bart should be an interface", sd1.isInterface());
1169 }
1170
1171
1172 public void testCreateMethodData() {
1173 // Test one that doesn't work at the old advanced level
1174 MethodDef mdef = new ConcreteMethodDef(SourceInfo.NONE,
1175 _volatileMav,
1176 new TypeParameter[0],
1177 new PrimitiveType(SourceInfo.NONE, "int"),
1178 new Word(SourceInfo.NONE, "methodName"),
1179 new FormalParameter[0],
1180 new ReferenceType[0],
1181 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1182
1183 MethodData mdata = new MethodData("methodName", _volatileMav, new TypeParameter[0], SymbolData.INT_TYPE,
1184 new VariableData[0],
1185 new String[0],
1186 _sd1,
1187 null);
1188 assertEquals("Should return the correct MethodData", mdata, _fv.createMethodData(mdef, _sd1));
1189 assertEquals("There should be no errors", 0, errors.size());
1190
1191 mdef = new ConcreteMethodDef(SourceInfo.NONE,
1192 _finalMav,
1193 new TypeParameter[0],
1194 new PrimitiveType(SourceInfo.NONE, "int"),
1195 new Word(SourceInfo.NONE, "methodName2"),
1196 new FormalParameter[0],
1197 new ReferenceType[0],
1198 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1199
1200 mdata = new MethodData("methodName2", _finalMav, new TypeParameter[0], SymbolData.INT_TYPE,
1201 new VariableData[0],
1202 new String[0],
1203 _sd1,
1204 null);
1205 assertEquals("Should return the correct MethodData", mdata, _fv.createMethodData(mdef, _sd1));
1206 assertEquals("There should still be no errors", 0, errors.size());
1207
1208
1209 // Test one that does work.
1210 FormalParameter fp1 =
1211 new FormalParameter(SourceInfo.NONE,
1212 new UninitializedVariableDeclarator(SourceInfo.NONE,
1213 new PrimitiveType(SourceInfo.NONE, "double"),
1214 new Word (SourceInfo.NONE, "field1")),
1215 false);
1216 FormalParameter fp2 =
1217 new FormalParameter(SourceInfo.NONE,
1218 new UninitializedVariableDeclarator(SourceInfo.NONE,
1219 new PrimitiveType(SourceInfo.NONE, "int"),
1220 new Word (SourceInfo.NONE, "field1")),
1221 false);
1222 mdef =
1223 new AbstractMethodDef(SourceInfo.NONE,
1224 _abstractMav,
1225 new TypeParameter[] { new TypeParameter(SourceInfo.NONE,
1226 new TypeVariable(SourceInfo.NONE, "T"),
1227 new TypeVariable(SourceInfo.NONE, "U"))},
1228 new VoidReturn(SourceInfo.NONE, "void"),
1229 new Word(SourceInfo.NONE, "methodName"),
1230 new FormalParameter[] {fp1, fp2},
1231 new ReferenceType[] { new TypeVariable(SourceInfo.NONE, "X") });
1232 VariableData[] vardatas =
1233 new VariableData[] { new VariableData("field1", _finalMav, SymbolData.DOUBLE_TYPE, true, null),
1234 new VariableData("field1", _finalMav, SymbolData.INT_TYPE, true, null) };
1235 mdata = new MethodData("methodName",
1236 _abstractMav,
1237 new TypeParameter[] { new TypeParameter(SourceInfo.NONE,
1238 new TypeVariable(SourceInfo.NONE, "T"),
1239 new TypeVariable(SourceInfo.NONE, "U"))},
1240 SymbolData.VOID_TYPE,
1241 vardatas,
1242 new String[] { "X" },
1243 _sd1,
1244 null);
1245
1246 mdata.getParams()[0].setEnclosingData(mdata);
1247 mdata.getParams()[1].setEnclosingData(mdata);
1248
1249 MethodData expectedMethod = _fv.createMethodData(mdef, _sd1);
1250
1251 // have to add the parameters to the vars manually
1252 mdata.getParams()[0].setEnclosingData(expectedMethod);
1253 mdata.getParams()[1].setEnclosingData(expectedMethod);
1254 VariableData[] vd = new VariableData[] {
1255 new VariableData("f,ield1", _finalMav, SymbolData.DOUBLE_TYPE, true, expectedMethod)
1256 };
1257 mdata.addVars(vd);
1258 // assertEquals("Should return the correct MethodData", mdata, expectedMethod);
1259 assertEquals("There should be 1 error", 1, errors.size());
1260 assertEquals("The first error message should be correct.",
1261 "You cannot have two method parameters with the same name", errors.get(0).getFirst());
1262 }
1263
1264 /* NOTE: This is test excluded because the tested method is now a no-op. */
1265 public void xtestSimpleAnonymousClassInstantiationHelper() {
1266 // System.err.println("**** Starting testSimpleAnonymousClassInstantiationHelper");
1267 SimpleAnonymousClassInstantiation basic =
1268 new SimpleAnonymousClassInstantiation(SourceInfo.NONE,
1269 new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]),
1270 new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]),
1271 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1272
1273
1274 _fv._package = "i.like";
1275 _fv.simpleAnonymousClassInstantiationHelper(basic, _sd1);
1276 assertEquals("There should be no errors", 0, errors.size());
1277 assertNotNull("Object should be in the symbol table", _objectSD);
1278 assertEquals("_sd1 should have one inner class", 1, _sd1.getInnerClasses().size());
1279 SymbolData inner = _sd1.getInnerClasses().get(0);
1280 assertEquals("The inner class should have the proper name", "i.like.monkey$1", inner.getName());
1281 assertEquals("The inner class should have proper outer data", _sd1, inner.getOuterData());
1282 assertEquals("The inner class should have proper super class", _objectSD, inner.getSuperClass());
1283 assertEquals("The inner class should have the right package", "i.like", inner.getPackage());
1284 assertEquals("The inner class should have 0 methods", 0, inner.getMethods().size());
1285
1286 // System.err.println("**** Ending testSimpleAnonymousClassInstantiationHelper");
1287 }
1288
1289 /* NOTE: This is test excluded because the tested method is now a no-op. */
1290 public void xtestComplexAnonymousClassInstantiationHelper() {
1291 ComplexAnonymousClassInstantiation basic =
1292 new ComplexAnonymousClassInstantiation(SourceInfo.NONE,
1293 new SimpleNameReference(SourceInfo.NONE,
1294 new Word(SourceInfo.NONE, "java.lang.Object")),
1295 new ClassOrInterfaceType(SourceInfo.NONE, "Inner", new Type[0]),
1296 new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]),
1297 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1298
1299 _fv._package = "i.like";
1300 _fv._enclosingClassName = "i.like.monkey";
1301 _fv.complexAnonymousClassInstantiationHelper(basic, _sd1); // TODO: the wrong enclosing context?
1302 assertEquals("There should be no errors", 0, errors.size());
1303 SymbolData obj = LanguageLevelConverter.symbolTable.get("java.lang.Object");
1304 assertNotNull("Object should be in the symbol table", obj);
1305 SymbolData objInner = LanguageLevelConverter.symbolTable.get("java.lang.Object.Inner");
1306 assertEquals("sd1 should have one inner class", 1, _sd1.getInnerClasses().size());
1307 SymbolData inner = _sd1.getInnerClasses().get(0);
1308 assertEquals("The inner class should have the proper name", "i.like.monkey$1", inner.getName());
1309 assertEquals("The inner class should have proper outer data", _sd1, inner.getOuterData());
1310 assertEquals("The inner class should have null as its super class", null, inner.getSuperClass());
1311 assertEquals("The inner class should have the right package", "i.like", inner.getPackage());
1312 assertEquals("The inner class should have 0 methods", 0, inner.getMethods().size());
1313 }
1314
1315 /* NOTE: the following test is excluded because the anonymous class helper functions are now no-ops. */
1316 public void xtestForVariableDeclaration() {
1317 // Make sure that if forVariableDeclaration is called with a AnonymousClassInstantiation, the symbolData is only
1318 // added once. This is to make sure an old bug stays fixed.
1319 SimpleAnonymousClassInstantiation basic =
1320 new SimpleAnonymousClassInstantiation(SourceInfo.NONE,
1321 new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]),
1322 new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]),
1323 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1324 VariableDeclarator[] d1 = {
1325 new InitializedVariableDeclarator(SourceInfo.NONE,
1326 new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]),
1327 new Word(SourceInfo.NONE, "b"), basic)
1328 };
1329 VariableDeclaration vd1 = new VariableDeclaration(SourceInfo.NONE,_publicMav, d1);
1330
1331 ClassBodyFullJavaVisitor cbav =
1332 new ClassBodyFullJavaVisitor(_sd1, _sd1.getName(), _fv._file, _fv._package, _fv._importedFiles, _fv._importedPackages,
1333 _fv._classesInThisFile, _fv.continuations, _fv.fixUps);
1334 vd1.visit(cbav);
1335 assertEquals("Should be 1 inner class of _sd1", 1, _sd1.getInnerClasses().size());
1336 // System.err.println("**** Completed testForVariableDeclaration");
1337 }
1338
1339 public void testDummy() { }
1340 }
1341 }