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 /** Top-level Language Level Visitor that represents the Intermediate Language Level. Enforces constraints during the
049 * first walk of the AST (checking for langauge specific errors and building the symbol table).
050 * This class enforces things that are common to all contexts reachable at the Intermediate Language Level
051 * (i.e., inside class bodies, method bodies, interface bodies, etc), but also enforces specific top level
052 * constraints (i.e. you cannot have try catch statements at the top level, etc.)
053 */
054 public class IntermediateVisitor extends LanguageLevelVisitor {
055
056 /* Inheriting the following fields:
057 *
058 File _file;
059 String _package;
060 String _enclosingClassName;
061 LinkedList<String> _importedFiles;
062 LinkedList<String> _importedPackages;
063 HashMap<String, SymbolData> _generic types
064 *
065 */
066
067 /** This constructor is called when creating a new instance of IntermediateVisitor. The default value for className
068 * is the empty string. The default value of _genericTypes (a field of LanguageLevelVisitor) is an empty HashMap.
069 */
070 public IntermediateVisitor(File file,
071 String packageName,
072 String enclosingClassName,
073 LinkedList<String> importedFiles,
074 LinkedList<String> importedPackages,
075 HashSet<String> classesInThisFile,
076 Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>> continuations,
077 LinkedList<Command> fixUps) {
078 super(file, packageName, enclosingClassName, importedFiles, importedPackages, classesInThisFile, continuations, fixUps);
079 }
080
081 /** This constructor is called when testing. It initializes all of the static fields of LanguageLevelVisitor. */
082 public IntermediateVisitor(File file) {
083 this(file,
084 new LinkedList<Pair<String, JExpressionIF>>(),
085 new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(),
086 new LinkedList<Command>(),
087 new LinkedList<Pair<LanguageLevelVisitor, SourceFile>>());
088 }
089
090 /** This constructor is called from LanguageLevelVisitor and LanguageLevelConverter when they are instantiating a new
091 * IntermediateVisitor to visit a new file with. _package is set to "" by default. _enclosingClassName is set to null
092 * @param file The File corresponding to the source file we are visiting
093 * @param errors The list of errors that have been encountered so far.
094 * @param continuations The table of classes we have encountered but still need to resolve
095 * @param fixUps This list of symbolTable fixups to perform after visitation
096 * @param visitedFiles The list of files we have visited
097 */
098 public IntermediateVisitor(File file,
099 LinkedList<Pair<String, JExpressionIF>> errors,
100 Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>> continuations,
101 LinkedList<Command> fixUps,
102 LinkedList<Pair<LanguageLevelVisitor, SourceFile>> visitedFiles) {
103 this(file, new LinkedList<String>(), errors, continuations, fixUps, visitedFiles);
104 }
105
106 /** This constructor is called from LanguageLevelVisitor and LanguageLevelConverter when they are instantiating a new
107 * IntermediateVisitor to visit a new file with. _package is set to "" by default. _enclosingClassName is set to null
108 * @param file The File corresponding to the source file we are visiting
109 * @param importedPackages The list of strings describing the imported packages for this file
110 * @param errors The list of errors that have been encountered so far.
111 * @param continuations The table of classes we have encountered but still need to resolve
112 * @param fixUps This list of symbolTable fixups to perform after visitation
113 * @param visitedFiles The list of files we have visited
114 */
115 public IntermediateVisitor(File file,
116 LinkedList<String> importedPackages,
117 LinkedList<Pair<String, JExpressionIF>> errors,
118 Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>> continuations,
119 LinkedList<Command> fixUps,
120 LinkedList<Pair<LanguageLevelVisitor, SourceFile>> visitedFiles) {
121 super(file, "", null, new LinkedList<String>(), importedPackages, new HashSet<String>(), continuations, fixUps);
122 this.errors = errors;
123 this.visitedFiles= visitedFiles;
124 // _hierarchy = new Hashtable<String, TypeDefBase>(); //hierarchy;
125 }
126
127 /** Factory method inherited from LLV class. */
128 public LanguageLevelVisitor newClassBodyVisitor(SymbolData anonSD, String anonName) {
129 return new ClassBodyFullJavaVisitor(anonSD, anonName, _file, _package, _importedFiles, _importedPackages,
130 _classesInThisFile, continuations, fixUps);
131 }
132
133 /** Check to make sure the inner class def is well-formed, resolve it, and store the resulting symbol in the outer
134 * class's list of inner classes. This method is used in InterfaceBodyIntermediateVisitor but needs the correct
135 * Data so we pass it in. This method is tested in those files. We use the fully qualified name so that we
136 * don't accidentally conflict with another class in the symbol table.
137 * @param that AST Node for the inner class def
138 * @param enclosing Data that encloses this inner class; the inner class can be in a class or a method.
139 * @param relName The relative name of the inner class including no qualifiers
140 * @param name Fully qualified name of the inner class. For a local class, we construct the same name as the Java
141 * compiler, which inserts "$<seq#>" as the delimiter preceding the raw class name. For example, if class A
142 * has a method B with a local class C, then qualified name for this class is "A$1C", provided the class is the
143 * first local class (including anonymous classes) in the enclosing class.
144 */
145 // TODO: add a factory method for constructing the classbody visitor (so it is different for FullJava and Functional
146 // and hoist this code into LanguageLevelVisitor
147 protected void handleInnerClassDef(InnerClassDef that, Data enclosing, String relName, String name) {
148 // System.err.println("Processing InnerClassDef for " + name + " defined in " + enclosing.getName());
149
150 assert (enclosing instanceof SymbolData) || (enclosing instanceof MethodData);
151 forInnerClassDefDoFirst(that);
152 if (prune(that)) return;
153
154 that.getMav().visit(this);
155 that.getName().visit(this);
156
157 // TODO: type parameters are illegal in functional code. Fix this!!!
158 // for (int i = 0; i < that.getTypeParameters().length; i++) that.getTypeParameters()[i].visit(this);
159
160 that.getSuperclass().visit(this); // formerly commented out. Why?
161
162 for (int i = 0; i < that.getInterfaces().length; i++) that.getInterfaces()[i].visit(this);
163
164 SymbolData sd = defineInnerSymbolData(that, relName, name, enclosing);
165 if (sd != null) { // We have a SymbolData to work with, so visit the body and augment
166 that.getBody().visit(new ClassBodyIntermediateVisitor(sd,
167 sd.getName(),
168 _file,
169 _package,
170 _importedFiles,
171 _importedPackages,
172 _classesInThisFile,
173 continuations,
174 fixUps));
175
176 // The following methods are no-ops in FullJavaVisitor
177 createAccessors(sd, _file);
178 createToString(sd);
179 createHashCode(sd);
180 createEquals(sd);
181 }
182 // IMPORTANT: error message if sd is null?
183 // Inner classes are not entered in _classesInThisFile since they are parsed when their outer classes are parsed.
184
185 forInnerClassDefOnly(that);
186 }
187
188 /** Confirms that the inner interface is well-formed, resolves it, and stores it in the outer class's list of inner
189 * classes. This method is common to both ClassBodyIntermediateVisitor and InterfaceBodyIntermediateVisitor but
190 * needs the correct SymbolData so we pass it in. This method is tested in those files.
191 * @param that AST Node for the inner class def
192 * @param enclosing Data that encloses this inner class; the inner class can be in a class or a method.
193 * @param name Fully qualified name of the inner class. For a local class, we construct the same name as the Java
194 * compiler (??), which inserts "$<seq#>" as the delimiter preceding the raw class name. For example, if class A
195 * has a method B with a local class C, then qualified name for this class is "A$1C", provided the class is the
196 * first local class (including anonymous classes) in the enclosing class.
197 */
198 // TODO: add a factory method for constructing the classbody visitor (so it is different for FullJava and Functional
199 // and hoist this code into LanguageLevelVisitor
200 protected void handleInnerInterfaceDef(InnerInterfaceDef that, Data enclosing, String relName, String name) {
201 // System.err.println("Processing InnerInterfaceDef for " + name);
202 assert (enclosing instanceof SymbolData) || (enclosing instanceof MethodData);
203 forInnerInterfaceDefDoFirst(that);
204 if (prune(that)) return;
205
206 that.getMav().visit(this);
207 that.getName().visit(this);
208
209 // Type parameters are illegal in functional code. TODO: Fix this!!!!
210 // assert that.getTypeParameters().length == 0;
211
212 for (int i = 0; i < that.getInterfaces().length; i++) that.getInterfaces()[i].visit(this);
213
214 SymbolData sd = defineInnerSymbolData(that, relName, name, enclosing);
215 if (sd != null) {
216 that.getBody().visit(new InterfaceBodyIntermediateVisitor(sd,
217 _file,
218 _package,
219 _importedFiles,
220 _importedPackages,
221 _classesInThisFile,
222 continuations,
223 fixUps));
224 }
225
226 forInnerInterfaceDefOnly(that);
227 }
228
229 /** Only abstract, public, private, protected, static and final are allowed in language levels.*/
230 public Void forModifiersAndVisibilityDoFirst(ModifiersAndVisibility that) {
231 String[] modifiersAndVisibility = that.getModifiers();
232 StringBuffer sb = new StringBuffer();
233 String temp;
234 int count = 0;
235 for(int i = 0; i < modifiersAndVisibility.length; i++) {
236 temp = modifiersAndVisibility[i];
237 if (! temp.equals("final") && ! temp.equals("abstract") && ! temp.equals("public") && ! temp.equals("private") &&
238 ! temp.equals("protected") && ! temp.equals("static")) {
239 sb.append(" \"" + temp + "\"");
240 count++;
241 }
242 }
243 // check if any illegal keywords were found
244 temp = "The keyword";
245 if (sb.length() > 0) {
246 if (count > 1) temp = temp + "s";
247 _addAndIgnoreError(temp + sb.toString() + " cannot be used at the Intermediate level", that);
248 return null;
249 }
250 return super.forModifiersAndVisibilityDoFirst(that);
251 }
252
253 // /** Do not allow explicit Package Statements at the Intermediate Level. */
254 // public Void forPackageStatementDoFirst(PackageStatement that) {
255 //// _addError("Package statements cannot be used at the Intermediate level. " +
256 //// "All Intermediate level classes and interfaces are assumed to be in the default package", that);
257 // return null;
258 // }
259 //
260 /* The following two overrides appear unnecessary. */
261 // /** Allow inner classes at the Intermediate Level. Override any inherited code. */
262 // public Void forInnerClassDefDoFirst(InnerClassDef that) {
263 //// _addError("Inner classes cannot be used at the Intermediate level", that);
264 // return null;
265 // }
266 //
267 // /** Allow inner interfaces at the Intermediate Level. Override any inherited code. */
268 // public Void forInnerInterfaceDefDoFirst(InnerInterfaceDef that) {
269 //// _addError("Nested interfaces cannot be used at the Intermediate level", that);
270 // return null;
271 // }
272
273 // /**Do not allow static intiializers at the Intermediate Level.*/
274 // public Void forStaticInitializerDoFirst(StaticInitializer that) {
275 // _addError("Static initializers cannot be used at the Intermediate level", that);
276 // return null;
277 // }
278
279 // /**Do not allow labeled statements at the Intermediate Level.*/
280 // public Void forLabeledStatementDoFirst(LabeledStatement that) {
281 // _addError("Labeled statements cannot be used at the Intermediate level", that);
282 // return null;
283 // }
284
285 // /**Do not allow switch statements at the Intermediate Level.*/
286 // public Void forSwitchStatementDoFirst(SwitchStatement that) {
287 // _addError("Switch statements cannot be used at the Intermediate level", that);
288 // return null;
289 // }
290
291 // /**Do not allow while statements at the Intermediate Level.*/
292 // public Void forWhileStatementDoFirst(WhileStatement that) {
293 // _addError("While statements cannot be used at the Intermediate level", that);
294 // return null;
295 // }
296
297 // /**Do not allow do statements at the Intermediate Level.*/
298 // public Void forDoStatementDoFirst(DoStatement that) {
299 // _addError("Do statements cannot be used at the Intermediate level", that);
300 // return null;
301 // }
302
303 // /**Do not allow for statements at the Intermediate Level.*/
304 // public Void forForStatementDoFirst(ForStatement that) {
305 // _addError("For statements cannot be used at the Intermediate level", that);
306 // return null;
307 // }
308
309 // /**Do not allow break statements at the Intermediate Level.*/
310 // public Void forBreakStatementDoFirst(BreakStatement that) {
311 // _addError("Break statements cannot be used at the Intermediate level", that);
312 // return null;
313 // }
314
315 // /**Do not allow continue statements at the Intermediate Level.*/
316 // public Void forContinueStatementDoFirst(ContinueStatement that) {
317 // _addError("Continue statements cannot be used at the Intermediate level", that);
318 // return null;
319 // }
320
321 /**Do not allow synchronized statements at the Intermediate Level.*/
322 public Void forSynchronizedStatementDoFirst(SynchronizedStatement that) {
323 _addError("Synchronized statements cannot be used at the Intermediate level", that);
324 return null;
325 }
326
327 // /**Do not allow try-catch statements at the Intermediate Level.*/
328 // public Void forTryCatchStatementDoFirst(TryCatchStatement that) {
329 // _addAndIgnoreError("A try-catch statement cannot appear here", that);
330 // return null;
331 // }
332
333 // /**Make sure that the formal parameter is not final*/
334 // public Void forFormalParameterDoFirst(FormalParameter that) {
335 // if (that.isIsFinal()) {
336 // _addError("The keyword \"final\" cannot be used at the Intermediate level", that);
337 // return null;
338 // }
339 // else {
340 // return forJExpressionDoFirst(that);
341 // }
342 // }
343
344 /**Do not allow type parameters (generics) at the Intermediate level*/
345 public Void forTypeParameterDoFirst(TypeParameter that) {
346 _addError("Type Parameters cannot be used at the Intermediate level", that);
347 return null;
348 }
349
350 // /**Only allow the 4 basic primitives: int, double, boolean, and char*/
351 // public Void forPrimitiveTypeDoFirst(PrimitiveType that) {
352 // String name = that.getName();
353 // if (!(name.equals("int") || name.equals("double") || name.equals("boolean") || name.equals("char"))) {
354 // _addError("Only the primitive types \"int\", \"double\", \"boolean\", and \"char\" can be used " +
355 // "at the Intermediate level", that);
356 // return null;
357 // }
358 // else {
359 // return forTypeDoFirst(that);
360 // }
361 // }
362
363 // /**Do not allow arrays at the Intermediate Level*/
364 // public Void forArrayTypeDoFirst(ArrayType that) {
365 // _addError("Arrays cannot be used at the Intermediate level", that);
366 // return null;
367 // }
368
369 // /**Do not allow conditional expressions at the Intermediate Level*/
370 // public Void forConditionalExpressionDoFirst(ConditionalExpression that) {
371 // _addError("Conditional expressions cannot be used at the Intermediate level", that);
372 // return null;
373 // }
374
375 // /**Do not allow instanceof expressions at the Intermediate Level*/
376 // public Void forInstanceofExpressionDoFirst(InstanceofExpression that) {
377 // _addError("Instanceof expressions cannot be used at the Intermediate level", that);
378 // return null;
379 // }
380
381
382 /*Check to see if className is one of the classes declared in the current source file,
383 * by looking through classesInThisFile.*/
384 private boolean _isClassInCurrentFile(String className) {
385 Iterator<String> iter = _classesInThisFile.iterator();
386 while (iter.hasNext()) {
387 String s = iter.next();
388 if (s.equals(className) || s.endsWith('.' + className)) {
389 return true;
390 }
391 }
392 return false;
393 }
394
395 /** Use the doFirst method to make sure there aren't any errors with the declaration. Then, use defineSymbolData to
396 * create the appropriate SymbolData, and then visit the class body. Finally, autogenerate the toString, equals,
397 * hashCode, and accessor methods. The constructor will be autogenerated right before the TypeChecking pass starts.
398 * Once the class def has been handled, remove it from _classesInThisFile.
399 */
400 public Void forClassDef(ClassDef that) {
401 forClassDefDoFirst(that);
402 if (prune(that)) return null;
403
404 String className = getQualifiedClassName(that.getName().getText());
405 // System.err.println("Processing class " + className);
406
407 String superName = that.getSuperclass().getName();
408
409 SymbolData sd = defineSymbolData(that, className);
410
411 // Note: sd returns null only if there is an error such as redefining a class
412 // assert getQualifiedSymbolData(className, that.getSourceInfo()) != null;
413
414 that.getMav().visit(this);
415 that.getName().visit(this);
416 that.getSuperclass().visit(this);
417
418 if (sd != null) identifyInnerClasses(that);
419
420 // Type parameters are illegal in functional code.
421 // for (int i = 0; i < that.getTypeParameters().length; i++) that.getTypeParameters()[i].visit(this);
422
423 for (int i = 0; i < that.getInterfaces().length; i++) that.getInterfaces()[i].visit(this);
424
425 if (sd != null) {
426 // Perform special processing for classes extending TestCase
427 if (superName.equals("TestCase") || superName.equals("junit.framework.TestCase")) {
428 // Test cases are automatically public; isTestCase => sd != null
429 sd.addModifier("public");
430 // Check to see if we need to autognerate an import of TestCase class
431 if (! _importedPackages.contains("junit.framework") && ! _importedFiles.contains("junit.framework.TestCase")) {
432 sd.setHasAutoGeneratedJunitImport(true);
433 _importedFiles.addLast("junit.framework.TestCase");
434 createImportedSymbolContinuation("junit.framework.TestCase", that.getSourceInfo());
435 // System.err.println("*********** Imported symbol continuation created for junit.framework.TestCase");
436 }
437 assert getQualifiedSymbolData("junit.framework.TestCase", that.getSourceInfo()) != null;
438 }
439
440 that.getBody().visit(new ClassBodyIntermediateVisitor(sd, className, _file, _package, _importedFiles,
441 _importedPackages, _classesInThisFile, continuations,
442 fixUps));
443 createAccessors(sd, _file);
444 createToString(sd);
445 createHashCode(sd);
446 createEquals(sd);
447 }
448
449 forClassDefOnly(that);
450 _classesInThisFile.remove(className);
451 return null;
452 }
453
454 /** Use the doFirst method to make sure that there aren't any errors with the declaration. Define a SymbolData
455 * corresponding to this interface definition. Then visit the body to handle anything defined inside the interfac
456 * Once the interface has been resolved, remove it from _classesInThisFile.
457 */
458 public Void forInterfaceDef(InterfaceDef that) {
459 forInterfaceDefDoFirst(that);
460 if (prune(that)) return null;
461 String className = getQualifiedClassName(that.getName().getText());
462
463 // Type parameters are illegal in functional code. Fix this!!!
464 // assert that.getTypeParameters().length == 0;
465
466 for (int i = 0; i < that.getInterfaces().length; i++) that.getInterfaces()[i].visit(this);
467
468 SymbolData sd = defineSymbolData(that, className);
469 // Note: sd can only be null if an error occurs in defineSymbol
470
471 if (sd != null) {
472 sd.setInterface(true);
473 identifyInnerClasses(that); // inner interfaces??
474 that.getBody().visit(new InterfaceBodyIntermediateVisitor(sd, _file, _package, _importedFiles, _importedPackages,
475 _classesInThisFile, continuations, fixUps));
476 }
477
478 that.getMav().visit(this);
479 that.getName().visit(this);
480 forInterfaceDefOnly(that);
481 _classesInThisFile.remove(className);
482 return null;
483 }
484
485 /**Bitwise operators are not allowed at any language level...*/
486 public Void forShiftAssignmentExpressionDoFirst(ShiftAssignmentExpression that) {
487 _addAndIgnoreError("Shift assignment operators cannot be used at any language level", that);
488 return null;
489 }
490 public Void forBitwiseAssignmentExpressionDoFirst(BitwiseAssignmentExpression that) {
491 _addAndIgnoreError("Bitwise operators cannot be used at any language level", that);
492 return null;
493 }
494 public Void forBitwiseBinaryExpressionDoFirst(BitwiseBinaryExpression that) {
495 _addAndIgnoreError("Bitwise binary expressions cannot be used at any language level", that);
496 return null;
497 }
498 public Void forBitwiseOrExpressionDoFirst(BitwiseOrExpression that) {
499 // System.err.println("Visiting BitwiseOrExpression: " + that);
500 _addAndIgnoreError("Bitwise or expressions cannot be used in the functional language level." +
501 " Perhaps you meant to compare two values using regular or (||)", that);
502 return null;
503 }
504 public Void forBitwiseXorExpressionDoFirst(BitwiseXorExpression that) {
505 _addAndIgnoreError("Bitwise xor expressions cannot be used at any language level", that);
506 return null;
507 }
508 public Void forBitwiseAndExpressionDoFirst(BitwiseAndExpression that) {
509 _addAndIgnoreError("Bitwise and expressions cannot be used at any language level." +
510 " Perhaps you meant to compare two values using regular and (&&)", that);
511 return null;
512 }
513 public Void forBitwiseNotExpressionDoFirst(BitwiseNotExpression that) {
514 _addAndIgnoreError("Bitwise not expressions cannot be used at any language level." +
515 " Perhaps you meant to negate this value using regular not (!)", that);
516 return null;
517 }
518 public Void forShiftBinaryExpressionDoFirst(ShiftBinaryExpression that) {
519 _addAndIgnoreError("Bit shifting operators cannot be used at any language level", that);
520 return null;
521 }
522 public Void forBitwiseNotExpressionDoFirst(ShiftBinaryExpression that) {
523 _addAndIgnoreError("Bitwise operators cannot be used at any language level", that);
524 return null;
525 }
526
527 // /** Call the super method to convert these to a VariableData array, then make sure that
528 // * each VariableData is final, as required at the Intermediate level.
529 // * @param enclosingData The Data which contains the variables
530 // */
531 // protected VariableData[] _variableDeclaration2VariableData(VariableDeclaration vd, Data enclosingData) {
532 // VariableData[] vds = super._variableDeclaration2VariableData(vd, enclosingData);
533 // for (int i = 0; i < vds.length; i++) {
534 // if ((vds[i].hasModifier("static") && vds[i].getMav().getModifiers().length > 1) ||
535 // (! vds[i].hasModifier("static") && vds[i].getMav().getModifiers().length > 0)) {
536 // StringBuffer s = new StringBuffer("the keyword(s) ");
537 // String[] modifiers = vds[i].getMav().getModifiers();
538 // for (int j = 0; j<modifiers.length; j++) {
539 // if (! modifiers[j].equals("static")) {s.append("\"" + modifiers[j] + "\" ");}
540 // }
541 // _addAndIgnoreError("You cannot use " + s.toString() + "to declare a field at the Intermediate level. " +
542 // "Only the keyword 'static' is allowed", vd);
543 // }
544 // if (vds[i].hasModifier("static")) vds[i].addModifier("public");
545 // else vds[i].addModifier("private");
546 // vds[i].setFinal();
547 // }
548 // return vds;
549 // }
550
551 /** Pass this call directly onto the language level visitor. This is a hack to bypass the privateAndFinal setting
552 * when we are dealing with local variables.
553 */
554 protected VariableData[] llVariableDeclaration2VariableData(VariableDeclaration vd, Data enclosingData) {
555 return super._variableDeclaration2VariableData(vd, enclosingData);
556 }
557
558 // /** Do the work that is shared between SimpleAnonymousClassInstantiations and ComplexAnonymousClassInstantiations. Do
559 // * not generate automatic accessors for the anonymous class--this will be done in type checker pass.
560 // * @param that The AnonymousClassInstantiation being visited
561 // * @param enclosing The enclosing Data
562 // * @param superC The super class being instantiated--i.e. new A() { ...}, would have a super class of A.
563 // */
564 // public void anonymousClassInstantiationHelper(AnonymousClassInstantiation that, SymbolData enclosing,
565 // SymbolData superC) {
566 //
567 // that.getArguments().visit(this);
568 //
569 // // Generate the internal class name for this anonymous inner class
570 // String anonName = getQualifiedClassName(enclosing.getSymbolData().getName()) + "$" +
571 // enclosing.getSymbolData().preincrementAnonymousInnerClassNum();
572 //
573 // // Create the SymbolData that will correspond to this anonymous class
574 // SymbolData sd = new SymbolData(anonName);
575 // enclosing.addInnerClass(sd);
576 // sd.setOuterData(enclosing);
577 //
578 // if (superC != null && ! superC.isInterface()) {
579 // sd.setSuperClass(superC); // the super class is what was passed in
580 // }
581 // sd.setPackage(_package);
582 //
583 // createToString(sd);
584 // createHashCode(sd);
585 // createEquals(sd);
586 // //accessors will be filled in in typeChecker pass
587 //
588 // //visit the body to get it all nice and resolved. NOTE: what about the fact that all of the methods MUST BE PUBLIC
589 // that.getBody().visit(new ClassBodyIntermediateVisitor(sd, anonName, _file, _package, _importedFiles,
590 // _importedPackages, _classesInThisFile, continuations,
591 // fixUps));
592 // }
593
594 /** Look up the supertype of this class instantiation and add it to the symbol table. Visit the body of the class
595 * instantiation. The processing of this anonymous inner class (i.e. adding it to the enclosing SD's list of inner
596 * classes, creating a SymbolData for the anonyomous inner class, etc) will be handled in the TypeChecker pass.
597 * This is because no one will depend on that symbolData until we create it.
598 * @param that The SimpleAnonymousClassInstantiation being processed.
599 * @param enclosing The SymbolData of the enclosing class.
600 */
601 public void simpleAnonymousClassInstantiationHelper(SimpleAnonymousClassInstantiation that, SymbolData enclosing) {
602 forSimpleAnonymousClassInstantiationDoFirst(that);
603 if (prune(that)) return;
604
605 String superName = that.getType().getName();
606 anonymousClassInstantiationHelper(that, enclosing, superName);
607
608 forSimpleAnonymousClassInstantiationOnly(that);
609 }
610
611 /** Do not resolve the super class type of this instantiation, because it will have already been resolved (it is an
612 * inner class of the enclosing SD. When the enclosing SD was resolved, all of its inner classes
613 * should have also been resolved). Visit the body of the class instantiation.
614 * @param that The ComplexAnonymousClassInstantiation being processed.
615 * @param enclosing The SymbolData of the enclosing class.
616 */
617 public void complexAnonymousClassInstantiationHelper(ComplexAnonymousClassInstantiation that, SymbolData enclosing) {
618 forComplexAnonymousClassInstantiationDoFirst(that);
619 if (prune(that)) return;
620
621 //visit the enclosing
622 that.getEnclosing().visit(this);
623
624 String superName = that.getType().getName();
625 anonymousClassInstantiationHelper(that, enclosing, superName);
626
627 forComplexAnonymousClassInstantiationOnly(that);
628 }
629
630 /** Test the methods declared in the above class. */
631 public static class IntermediateVisitorTest extends TestCase {
632
633 private IntermediateVisitor _iv;
634
635 private SymbolData _sd1;
636 private SymbolData _sd2;
637 private SymbolData _sd3;
638 private SymbolData _sd4;
639 private SymbolData _sd5;
640 private SymbolData _sd6;
641 public static final ModifiersAndVisibility PUBLIC_MAV =
642 new ModifiersAndVisibility(SourceInfo.NONE, new String[] { "public" });
643 public static final ModifiersAndVisibility PROTECTED_MAV =
644 new ModifiersAndVisibility(SourceInfo.NONE, new String[] { "protected" });
645 public static final ModifiersAndVisibility PRIVATE_MAV =
646 new ModifiersAndVisibility(SourceInfo.NONE, new String[] { "private" });
647 public static final ModifiersAndVisibility PACKAGE_MAV = new ModifiersAndVisibility(SourceInfo.NONE, new String[0]);
648 public static final ModifiersAndVisibility ABSTRACT_MAV =
649 new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"abstract"});
650 public static final ModifiersAndVisibility PRIVATE_ABSTRACT_MAV =
651 new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"abstract", "private"}); // illegal
652 public static final ModifiersAndVisibility STATIC_MAV = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"static"});
653 public static final ModifiersAndVisibility FINAL_MAV = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"final"});
654
655 public IntermediateVisitorTest() { this(""); }
656 public IntermediateVisitorTest(String name) {
657 super(name);
658 // _file = File.createTempFile("DrJava-test", ".java");
659 // _iv = new ElementaryVisitor(new File(""), "", new LinkedList<String>(), new LinkedList<String>(),
660 // new LinkedList<String>());
661 }
662
663 public void setUp() {
664
665 errors = new LinkedList<Pair<String, JExpressionIF>>();
666 LanguageLevelConverter.symbolTable.clear();
667 LanguageLevelConverter._newSDs.clear();
668 LanguageLevelConverter.OPT = new Options(JavaVersion.JAVA_5, IterUtil.make(new File("lib/buildlib/junit.jar")));
669 visitedFiles = new LinkedList<Pair<LanguageLevelVisitor, SourceFile>>();
670 // _hierarchy = new Hashtable<String, TypeDefBase>();
671
672 _iv = new IntermediateVisitor(new File(""),
673 errors,
674 continuations,
675 new LinkedList<Command>(),
676 new LinkedList<Pair<LanguageLevelVisitor, SourceFile>>());
677 LanguageLevelConverter.OPT = new Options(JavaVersion.JAVA_5, IterUtil.make(new File("lib/buildlib/junit.jar")));
678 _iv._classesInThisFile = new HashSet<String>();
679 _iv.continuations = new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>();
680 // _iv._resetNonStaticFields();
681 _iv._importedPackages.addFirst("java.lang");
682 _errorAdded = false;
683 _sd1 = new SymbolData("i.like.monkey");
684 _sd2 = new SymbolData("i.like.giraffe");
685 _sd3 = new SymbolData("zebra");
686 _sd4 = new SymbolData("u.like.emu");
687 _sd5 = new SymbolData("");
688 _sd6 = new SymbolData("cebu");
689
690 _sd1.setIsContinuation(false);
691 _sd1.setInterface(false);
692 _sd1.setPackage("");
693 _sd1.setTypeParameters(new TypeParameter[0]);
694 _sd1.setInterfaces(new ArrayList<SymbolData>());
695
696 _iv._enclosingClassName = "i.like.monkey";
697 _iv.symbolTable.put("i.like.monkey", _sd1);
698 SymbolData objectSD = _iv.getQualifiedSymbolData("java.lang.Object", SourceInfo.NONE);
699 _sd1.setSuperClass(objectSD);
700 _errorAdded = false; // static field of this. TODO: fix this!
701 }
702
703 public void initTopLevel() {
704 _iv._enclosingClassName = null;
705 }
706
707 public void testForModifiersAndVisibilityDoFirst() {
708
709 // Check that the proper modifiers are allowed:
710 _iv.forModifiersAndVisibilityDoFirst(ABSTRACT_MAV);
711 _iv.forModifiersAndVisibilityDoFirst(PUBLIC_MAV);
712 _iv.forModifiersAndVisibilityDoFirst(PRIVATE_MAV);
713 _iv.forModifiersAndVisibilityDoFirst(PROTECTED_MAV);
714 _iv.forModifiersAndVisibilityDoFirst(STATIC_MAV);
715
716 ModifiersAndVisibility mavs = new ModifiersAndVisibility(SourceInfo.NONE,
717 new String[] {"private", "static"});
718 _iv.forModifiersAndVisibilityDoFirst(mavs);
719 assertEquals("there should still be 0 errors", 0, errors.size());
720
721 //check errors:
722
723 _iv.forModifiersAndVisibilityDoFirst(FINAL_MAV);
724 // assertEquals("there should now be 1 errors", 1, errors.size());
725 // assertEquals("The error message should be correct for private modifier:",
726 // "The keyword \"final\" cannot be used at the Intermediate level", errors.get(0).getFirst());
727
728 ModifiersAndVisibility mavs2 = new ModifiersAndVisibility(SourceInfo.NONE,
729 new String[] {"private", "final"});
730
731 _iv.forModifiersAndVisibilityDoFirst(mavs2);
732 assertEquals("There should still be 0 errors", 0, errors.size());
733
734 ModifiersAndVisibility mavs3 = new ModifiersAndVisibility(SourceInfo.NONE,
735 new String[] {"final", "native"});
736
737 _iv.forModifiersAndVisibilityDoFirst(mavs3);
738 assertEquals("There should now be 1 errors", 1, errors.size());
739 assertEquals("The error message should be correct for 1 bad modifier:",
740 "The keyword \"native\" cannot be used at the Intermediate level",
741 errors.get(0).getFirst());
742 }
743
744 public void testForClassDefDoFirst() {
745 //check an example that works
746 ClassDef cd0 = new ClassDef(SourceInfo.NONE, PUBLIC_MAV, new Word(SourceInfo.NONE, "Lisa"),
747 new TypeParameter[0],
748 new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]),
749 new ReferenceType[0],
750 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
751
752 _iv.forClassDefDoFirst(cd0);
753 assertEquals("should be no errors", 0, errors.size());
754
755 //check that an error is not thrown if a class doesn't explicitely extend another class
756 ClassDef cd1 = new ClassDef(SourceInfo.NONE, PUBLIC_MAV,
757 new Word(SourceInfo.NONE, "Test"), new TypeParameter[0], JExprParser.NO_TYPE,
758 new ReferenceType[0], new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
759
760 _iv.forClassDefDoFirst(cd1);
761 assertEquals("there should still be 0 errors", 0, errors.size());
762
763 //check that an error is not thrown if a class implements any interfaces.
764 ClassDef cd2 =
765 new ClassDef(SourceInfo.NONE, PUBLIC_MAV,
766 new Word(SourceInfo.NONE, "Test"),
767 new TypeParameter[0],
768 new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]),
769 new ReferenceType[] {new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0])},
770 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
771
772
773 _iv.forClassDefDoFirst(cd2);
774 assertEquals("there should still be 0 errors", 0, errors.size());
775 }
776
777 public void testForFormalParameterDoFirst() {
778 PrimitiveType pt = new PrimitiveType(SourceInfo.NONE, "int");
779 Word w = new Word(SourceInfo.NONE, "param");
780 UninitializedVariableDeclarator uvd = new UninitializedVariableDeclarator(SourceInfo.NONE, pt, w);
781
782 // check an example that works
783 FormalParameter fp = new FormalParameter(SourceInfo.NONE, uvd, false);
784 _iv.forFormalParameterDoFirst(fp);
785 assertEquals("should be no errors", 0, errors.size());
786
787 // check that an error is thrown if the FormalParameter is final
788 FormalParameter fp2 = new FormalParameter(SourceInfo.NONE, uvd, true);
789 _iv.forFormalParameterDoFirst(fp2);
790 assertEquals("should be no errors", 0, errors.size());
791 }
792
793 public void test_NotAllowed() {
794 SourceInfo noInfo = SourceInfo.NONE;
795 Word w = new Word(SourceInfo.NONE, "word");
796 TypeParameter[] tps = new TypeParameter[0];
797 ReferenceType[] rts = new ReferenceType[0];
798 BracedBody emptyBody = new BracedBody(SourceInfo.NONE, new BodyItemI[0]);
799 ClassOrInterfaceType superClass = new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]);
800 FormalParameter[] fps = new FormalParameter[0];
801 CompoundWord cw = new CompoundWord(noInfo, new Word[0]);
802 Statement stmt = new EmptyStatement(noInfo);
803 Expression e = new NullLiteral(noInfo);
804 Block b = new Block(noInfo, emptyBody);
805 // ClassModifier cm = ClassModifier.NONE;
806 TypeVariable tv = new TypeVariable(noInfo, "name");
807
808 InnerInterfaceDef ii = new InnerInterfaceDef(noInfo, PUBLIC_MAV, w, tps, rts, emptyBody);
809 InnerClassDef ic = new InnerClassDef(noInfo, PUBLIC_MAV, w, tps, superClass, rts, emptyBody);
810
811 StaticInitializer si = new StaticInitializer(noInfo, b);
812 LabeledStatement ls = new LabeledStatement(noInfo, new Word(noInfo, "label"), stmt);
813 SwitchStatement ss = new SwitchStatement(noInfo, e, new SwitchCase[0]);
814 WhileStatement ws = new WhileStatement(noInfo, e, stmt);
815 DoStatement ds = new DoStatement(noInfo, stmt, e);
816 ForStatement fs = new ForStatement(noInfo, new UnparenthesizedExpressionList(noInfo, new Expression[] {e}),
817 e, new UnparenthesizedExpressionList(noInfo, new Expression[] {e}),
818 stmt);
819 BreakStatement bs = new UnlabeledBreakStatement(noInfo);
820 ContinueStatement cs = new UnlabeledContinueStatement(noInfo);
821 SynchronizedStatement syncs = new SynchronizedStatement(noInfo, e, b);
822 TypeParameter tp = new TypeParameter(noInfo, tv, superClass);
823 ArrayInitializer ai = new ArrayInitializer(noInfo, new VariableInitializerI[0]);
824 ArrayType at = new ArrayType(noInfo, "myName", tv);
825 VoidReturn vr = new VoidReturn(noInfo, "string");
826 ConditionalExpression ce = new ConditionalExpression(noInfo, e, e, e);
827
828 BracedBody hasBitOperator =
829 new BracedBody(SourceInfo.NONE, new BodyItemI[] {
830 new ExpressionStatement(SourceInfo.NONE,
831 new BitwiseOrAssignmentExpression(SourceInfo.NONE,
832 new SimpleNameReference(SourceInfo.NONE,
833 new Word(SourceInfo.NONE,
834 "i")),
835 new IntegerLiteral(SourceInfo.NONE, 5)))});
836
837 TryCatchStatement tcs = new NormalTryCatchStatement(noInfo, b, new CatchBlock[0]);
838
839 si.visit(_iv);
840 assertEquals("After visiting static initializer, errors should still be 0", 0, errors.size());
841
842 ii.visit(_iv);
843 assertEquals("After visiting inner interface, errors should still be 0", 0, errors.size());
844
845 ic.visit(_iv);
846 assertEquals("After visiting inner class, errors should still be 0", 0, errors.size());
847
848 ls.visit(_iv);
849 assertEquals("After visiting labeled statment, errors should still be 0", 0, errors.size());
850
851 ss.visit(_iv);
852 assertEquals("After visiting switch statment, errors should still be 0", 0, errors.size());
853
854 ws.visit(_iv);
855 assertEquals("After visiting while statment, errors should still be 0", 0, errors.size());
856
857 ds.visit(_iv);
858 assertEquals("After visiting do statment, errors should still be 0", 0, errors.size());
859
860 fs.visit(_iv);
861 assertEquals("After visiting for statment, errors should still be 0", 0, errors.size());
862
863 bs.visit(_iv);
864 assertEquals("After visiting break statment, errors should still be 0", 0, errors.size());
865
866 cs.visit(_iv);
867 assertEquals("After visiting continue statment, errors should still be 0", 0, errors.size());
868
869 syncs.visit(_iv);
870 assertEquals("After visiting synchronized statment, errors should now be 1", 1, errors.size());
871 assertEquals("SynchronizedStatement is not allowed",
872 "Synchronized statements cannot be used at the Intermediate level",
873 errors.getLast().getFirst());
874
875 tp.visit(_iv);
876 assertEquals("After visiting type parameter, errors should now be 2", 2, errors.size());
877 assertEquals("TypeParameters are not allowed",
878 "Type Parameters cannot be used at the Intermediate level",
879 errors.getLast().getFirst());
880 }
881
882 public void testForPrimitiveTypeDoFirst() {
883
884 SourceInfo noInfo = SourceInfo.NONE;
885
886 //only primative types boolean, char, int, and double are allowed at Intermediate level.
887 PrimitiveType i = new PrimitiveType(noInfo, "int");
888 PrimitiveType c = new PrimitiveType(noInfo, "char");
889 PrimitiveType d = new PrimitiveType(noInfo, "double");
890 PrimitiveType b = new PrimitiveType(noInfo, "boolean");
891
892 i.visit(_iv);
893 assertEquals("After visiting int, errors should still be 0", 0, errors.size());
894
895 c.visit(_iv);
896 assertEquals("After visiting char, errors should still be 0", 0, errors.size());
897
898 d.visit(_iv);
899 assertEquals("After visiting double, errors should still be 0", 0, errors.size());
900
901 b.visit(_iv);
902 assertEquals("After visiting boolean, errors should still be 0", 0, errors.size());
903
904 // now the types that formerly threw errors:
905
906 PrimitiveType byt = new PrimitiveType(noInfo, "byte");
907 PrimitiveType s = new PrimitiveType(noInfo, "short");
908 PrimitiveType l = new PrimitiveType(noInfo, "long");
909 PrimitiveType f = new PrimitiveType(noInfo, "float");
910
911 byt.visit(_iv);
912 assertEquals("After visiting byte, errors should be 0", 0, errors.size());
913
914 s.visit(_iv);
915 assertEquals("After visiting short, errors should be 0", 0, errors.size());
916
917 l.visit(_iv);
918 assertEquals("After visiting long, errors should be 0", 0, errors.size());
919
920 f.visit(_iv);
921 assertEquals("After visiting float, errors should be 0", 0, errors.size());
922 }
923
924 public void test_isClassInCurrentFile() {
925 assertFalse("class not in file should return false", _iv._isClassInCurrentFile("NotInFile"));
926 _iv._classesInThisFile.add("package.MyClass");
927 assertTrue("full class name in file should return true", _iv._isClassInCurrentFile("package.MyClass"));
928 assertTrue("unqualified class name in file should return true", _iv._isClassInCurrentFile("MyClass"));
929
930 assertFalse("partial name in file, not same class, should return false", _iv._isClassInCurrentFile("Class"));
931
932 }
933
934 /** Tests createConstructor. Must ensure that no fixups remain pending before invoking this method. */
935 public void testCreateConstructor() {
936 SymbolData sd =
937 new SymbolData("ClassName", PUBLIC_MAV, new TypeParameter[0], null, new ArrayList<SymbolData>(), null);
938 VariableData v1 = new VariableData("i", PUBLIC_MAV, SymbolData.INT_TYPE, false, sd);
939 VariableData v2 = new VariableData("j", PUBLIC_MAV, SymbolData.CHAR_TYPE, false, sd);
940 sd.addVar(v1);
941 sd.addVar(v2);
942 sd.setSuperClass(_sd1);
943 sd.setIsContinuation(false);
944
945 // System.err.println("****** Creating constructor for " + _sd1);
946 _iv.createConstructor(_sd1); // Cannot create constructor for s1 without creating one for its superclass.
947
948 /* Construct expected MethodData */
949 // Copy vars without visibility
950 LinkedList<VariableData> params = new LinkedList<VariableData>();
951 for (VariableData vd: sd.getVars()) {
952 VariableData newParam = vd.copyWithoutVisibility();
953 newParam.setGenerated(true);
954 params.add(newParam);
955 };
956
957 MethodData md = new MethodData("ClassName",
958 PUBLIC_MAV,
959 new TypeParameter[0],
960 sd,
961 params.toArray(new VariableData[params.size()]),
962 new String[0],
963 sd,
964 null);
965 md.addVars(md.getParams());
966 md.setGenerated(true);
967
968 // System.err.println("****** Before creating Classname constructor, ClassName methods = " + sd.getMethods());
969 // System.err.println("****** Creating constructor for " + sd);
970 _iv.createConstructor(sd);
971 // System.err.println("****** After creating constructor, ClassName method = " + sd.getMethods());
972
973 MethodData conSD = sd.getMethods().getFirst();
974
975 // System.err.println("****** Generated MethodData: " + conSD.toBigString());
976 // System.err.println("****** Expectred MethodData: " + md.toBigString());
977 assertEquals("sd should have 1 method: its own constructor", md, conSD);
978
979 // // Since this is the only constructor in the SymbolData, all the fields should be assigned after visiting sd.
980 // v1 = new VariableData("i", PUBLIC_MAV, SymbolData.INT_TYPE, true, sd);
981 // v2 = new VariableData("j", PUBLIC_MAV, SymbolData.CHAR_TYPE, true, sd);
982
983 // We no longer do this in createConstructor
984 // assertTrue("v1 should be correct--set to true", sd.getVars().contains(v1));
985 // assertTrue("v2 should be correct--set to true", sd.getVars().contains(v2));
986
987 // Now test a subclass of sd:
988
989 SymbolData subSD =
990 new SymbolData("Subclass", PUBLIC_MAV, new TypeParameter[0], null, new ArrayList<SymbolData>(), null);
991 VariableData v3 = new VariableData("var", PUBLIC_MAV, SymbolData.DOUBLE_TYPE, false, subSD);
992 subSD.addVar(v3);
993
994 // // Revise params rather than recreating them, because they contain hidden fields like enclosingData that
995 // // must be right for equality testing to succeeed
996 // params.get(0).setName("super_i");
997 // params.get(1).setName("super_j");
998 // VariableData v3Param = v3.copyWithoutVisibility();
999 // v3Param.setGenerated(true);
1000 // params.add(v3Param);
1001
1002 subSD.setSuperClass(sd);
1003
1004 // Create copies of v1, v2. v3 with Package MAV
1005 VariableData v1Param = new VariableData("super_i", PACKAGE_MAV, SymbolData.INT_TYPE, true, subSD);
1006 VariableData v2Param = new VariableData("super_j", PACKAGE_MAV, SymbolData.CHAR_TYPE, true, subSD);
1007 VariableData v3Param = new VariableData("var", PACKAGE_MAV, SymbolData.DOUBLE_TYPE, true, subSD);
1008
1009 v1Param.setGenerated(true);
1010 v2Param.setGenerated(true);
1011 v3Param.setGenerated(true);
1012
1013 VariableData[] newParams = new VariableData[] { v1Param, v2Param, v3Param };
1014
1015 // VariableData[] newParams = params.toArray(new VariableData[params.size()]);
1016
1017 MethodData md2 =
1018 new MethodData("Subclass",
1019 PUBLIC_MAV,
1020 new TypeParameter[0],
1021 subSD,
1022 newParams,
1023 new String[0],
1024 subSD,
1025 null);
1026
1027 md2.addVars(md2.getParams());
1028 md2.setGenerated(true);
1029
1030 _iv.createConstructor(subSD);
1031
1032 conSD = subSD.getMethods().getFirst(); // Reusing conSD local variable
1033 // System.err.println("****** Expected params = " + Arrays.toString(md2.getParams()));
1034 // System.err.println("****** Results params = " + Arrays.toString(conSD.getParams()));
1035
1036 // System.err.println("****** Expected vars = " + md2.getVars());
1037 // System.err.println("****** Results vars = " + conSD.getVars());
1038
1039 // System.err.println("****** Constructor for Subclass is: " + conSD.toBigString());
1040 // System.err.println("****** Expected MethodData is: " + md2.toBigString());
1041
1042 assert md2.getName().equals(conSD.getName());
1043 assert md2.getMav().equals(conSD.getMav());
1044 assert arrayEquals(md2.getTypeParameters(), conSD.getTypeParameters());
1045 assert arrayEquals(md2.getThrown(), conSD.getThrown());
1046 assert md2.getEnclosingData().equals(conSD.getEnclosingData());
1047 LinkedList<VariableData> mVars = md2.getVars();
1048 LinkedList<VariableData> cVars = conSD.getVars();
1049 assert mVars.size() == cVars.size();
1050 for (int i = 0; i < mVars.size(); i++) {
1051 // System.err.println("****** EnclosingData of mVars " + i + " = " + mVars.get(i).getEnclosingData());
1052 // System.err.println("****** EnclosingData of cVars " + i + " = " + cVars.get(i).getEnclosingData());
1053 assertEquals("Var Test" + i, mVars.get(i), cVars.get(i));
1054 }
1055
1056 assert md2.getVars().equals(conSD.getVars());
1057 assert arrayEquals(md2.getParams(), conSD.getParams());
1058
1059 assertEquals("subSD should have 1 method: its own constructor.", md2, conSD);
1060 }
1061
1062 public void test_getFieldAccessorName() {
1063 // This may change in the future if we change getFieldAccessorName
1064 assertEquals("Should correctly convert from lower case to upper case", "name", _iv.getFieldAccessorName("name"));
1065 }
1066
1067 public void testCreateToString() {
1068 SymbolData sd =
1069 new SymbolData("ClassName", PUBLIC_MAV, new TypeParameter[0], null, new ArrayList<SymbolData>(), null);
1070
1071 MethodData md = new MethodData("toString",
1072 PUBLIC_MAV,
1073 new TypeParameter[0],
1074 _iv.getSymbolData("java.lang.String", SourceInfo.make("java.lang.String")),
1075 new VariableData[0],
1076 new String[0],
1077 sd,
1078 null); // no SourceInfo
1079
1080 _iv.createToString(sd);
1081 assertEquals("sd should have 1 method: toString", md, sd.getMethods().getFirst());
1082 }
1083
1084 public void testCreateHashCode() {
1085 SymbolData sd = new SymbolData("ClassName",
1086 PUBLIC_MAV,
1087 new TypeParameter[0],
1088 null,
1089 new ArrayList<SymbolData>(),
1090 null);
1091 MethodData md = new MethodData("hashCode",
1092 PUBLIC_MAV,
1093 new TypeParameter[0],
1094 SymbolData.INT_TYPE,
1095 new VariableData[0],
1096 new String[0],
1097 sd,
1098 null);
1099 _iv.createHashCode(sd);
1100 assertEquals("sd should have 1 method: hashCode()", md, sd.getMethods().getFirst());
1101 }
1102
1103 public void testCreateEquals() {
1104 SymbolData sd =
1105 new SymbolData("ClassName", PUBLIC_MAV, new TypeParameter[0], null, new ArrayList<SymbolData>(), null);
1106 VariableData[] vds =
1107 new VariableData[] { new VariableData(_iv.getSymbolData("java.lang.Object", SourceInfo.make("java.lang.Object"))) };
1108 MethodData md = new MethodData("equals",
1109 PUBLIC_MAV,
1110 new TypeParameter[0],
1111 SymbolData.BOOLEAN_TYPE,
1112 vds,
1113 new String[0],
1114 sd,
1115 null);
1116 _iv.createEquals(sd);
1117 md.getParams()[0].setEnclosingData(sd.getMethods().getFirst());
1118 assertEquals("sd should have 1 method: equals()", md, sd.getMethods().getFirst());
1119 }
1120
1121 public void testForClassDef() {
1122 //check an example that's not abstract
1123 initTopLevel();
1124 ClassDef cd0 =
1125 new ClassDef(SourceInfo.NONE, PACKAGE_MAV, new Word(SourceInfo.NONE, "Lisa"),
1126 new TypeParameter[0],
1127 new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]),
1128 new ReferenceType[0],
1129 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1130
1131 cd0.visit(_iv);
1132 assertEquals("There should be no errors", 0, errors.size());
1133 assertTrue("Should have resolved java.lang.Object",
1134 LanguageLevelConverter.symbolTable.containsKey("java.lang.Object"));
1135 assertFalse("Should not be a continuation",
1136 LanguageLevelConverter.symbolTable.get("java.lang.Object").isContinuation());
1137 SymbolData sd = LanguageLevelConverter.symbolTable.get("Lisa");
1138 assertTrue("Lisa should be in _newSDs", LanguageLevelConverter._newSDs.containsKey(sd));
1139 MethodData md2 =
1140 new MethodData("equals",
1141 PUBLIC_MAV,
1142 new TypeParameter[0],
1143 SymbolData.BOOLEAN_TYPE,
1144 new VariableData[] { new VariableData(_iv.getSymbolData("java.lang.Object",
1145 SourceInfo.make("java.lang.Object"))) },
1146 new String[0],
1147 sd,
1148 null);
1149
1150 md2.getParams()[0].setEnclosingData(sd.getMethods().getLast());
1151
1152 assertEquals("sd's last method should be equals()", md2, sd.getMethods().getLast());
1153 assertEquals("sd's package should be correct", "", sd.getPackage());
1154
1155 //check an example that's abstract
1156 _iv._package = "";
1157 ClassDef cd1 = new ClassDef(SourceInfo.NONE,
1158 ABSTRACT_MAV,
1159 new Word(SourceInfo.NONE, "Bart"),
1160 new TypeParameter[0],
1161 new ClassOrInterfaceType(SourceInfo.NONE, "System", new Type[0]),
1162 new ReferenceType[0],
1163 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1164 cd1.visit(_iv);
1165 assertEquals("There should be no errors", 0, errors.size());
1166 assertTrue("Should have resolved java.lang.System",
1167 LanguageLevelConverter.symbolTable.containsKey("java.lang.System"));
1168 assertFalse("Should not be a continuation",
1169 LanguageLevelConverter.symbolTable.get("java.lang.System").isContinuation());
1170 sd = LanguageLevelConverter.symbolTable.get("Bart");
1171
1172 assertEquals("There should be 3 methods", 3, sd.getMethods().size());
1173
1174
1175 //Check an example where the class extends TestCase, and has a test method that returns void.
1176 ConcreteMethodDef cmd = new ConcreteMethodDef(SourceInfo.NONE,
1177 PACKAGE_MAV,
1178 new TypeParameter[0],
1179 new VoidReturn(SourceInfo.NONE, "void"),
1180 new Word(SourceInfo.NONE, "testMethodName"),
1181 new FormalParameter[0],
1182 new ReferenceType[0],
1183 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1184
1185 ClassDef cd3 = new ClassDef(SourceInfo.NONE,
1186 ABSTRACT_MAV,
1187 new Word(SourceInfo.NONE, "TestSuper2"),
1188 new TypeParameter[0],
1189 new ClassOrInterfaceType(SourceInfo.NONE, "TestCase", new Type[0]),
1190 new ReferenceType[0],
1191 new BracedBody(SourceInfo.NONE, new BodyItemI[] { cmd }));
1192
1193 _iv._file=new File("TestSuper2.dj0");
1194 _iv._importedFiles.addLast("junit.framework.TestCase");
1195 LanguageLevelConverter.symbolTable.put("junit.framework.TestCase", new SymbolData("junit.framework.TestCase"));
1196 cd3.visit(_iv);
1197 assertEquals("There should still just be no errors", 0, errors.size());
1198 assertNotNull("Should have looked up TestSuper2", LanguageLevelConverter.symbolTable.get("TestSuper2"));
1199
1200 // Check a method with void return, but name not starting with test, but it's still okay.
1201 //This is now checked in the type checker!
1202 ConcreteMethodDef cmd2 = new ConcreteMethodDef(SourceInfo.NONE,
1203 PACKAGE_MAV,
1204 new TypeParameter[0],
1205 new VoidReturn(SourceInfo.NONE, "void"),
1206 new Word(SourceInfo.NONE, "uhOh"),
1207 new FormalParameter[0],
1208 new ReferenceType[0],
1209 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1210
1211 ClassDef cd4 = new ClassDef(SourceInfo.NONE,
1212 ABSTRACT_MAV,
1213 new Word(SourceInfo.NONE, "TestVoidNoTestMethod"),
1214 new TypeParameter[0],
1215 new ClassOrInterfaceType(SourceInfo.NONE, "junit.framework.TestCase", new Type[0]),
1216 new ReferenceType[0],
1217 new BracedBody(SourceInfo.NONE, new BodyItemI[] { cmd2 }));
1218
1219
1220
1221 _iv._file=new File("TestVoidNoTestMethod.dj0");
1222 cd4.visit(_iv);
1223
1224 assertEquals("There should still be 0 errors", 0, errors.size());
1225 _iv._importedFiles.remove("junit.framework.TestCase");
1226
1227 }
1228
1229 public void testForInterfaceDef() {
1230 initTopLevel();
1231 AbstractMethodDef amd = new AbstractMethodDef(SourceInfo.NONE,
1232 PUBLIC_MAV,
1233 new TypeParameter[0],
1234 new PrimitiveType(SourceInfo.NONE, "int"),
1235 new Word(SourceInfo.NONE, "myMethod"),
1236 new FormalParameter[0],
1237 new ReferenceType[0]);
1238 AbstractMethodDef amd2 = new AbstractMethodDef(SourceInfo.NONE,
1239 PUBLIC_MAV,
1240 new TypeParameter[0],
1241 new PrimitiveType(SourceInfo.NONE, "int"),
1242 new Word(SourceInfo.NONE, "myMethod"),
1243 new FormalParameter[0],
1244 new ReferenceType[0]);
1245 InterfaceDef id = new InterfaceDef(SourceInfo.NONE,
1246 PUBLIC_MAV,
1247 new Word(SourceInfo.NONE, "id"),
1248 new TypeParameter[0],
1249 new ReferenceType[0],
1250 new BracedBody(SourceInfo.NONE, new BodyItemI[] {amd}));
1251 InterfaceDef id2 =
1252 new InterfaceDef(SourceInfo.NONE,
1253 PUBLIC_MAV,
1254 new Word(SourceInfo.NONE, "id2"),
1255 new TypeParameter[0],
1256 new ReferenceType[] { new ClassOrInterfaceType(SourceInfo.NONE, "id", new Type[0]) },
1257 new BracedBody(SourceInfo.NONE, new BodyItemI[] { amd2 }));
1258 SymbolData sd = new SymbolData("id", PUBLIC_MAV, new TypeParameter[0], new ArrayList<SymbolData>(), null);
1259 sd.setIsContinuation(true);
1260 MethodData md =
1261 new MethodData("myMethod", PUBLIC_MAV, new TypeParameter[0], SymbolData.INT_TYPE, new VariableData[0],
1262 new String[0], sd, amd);
1263
1264 ArrayList<SymbolData> interfaces = new ArrayList<SymbolData>();
1265 interfaces.add(sd);
1266 SymbolData sd2 = new SymbolData("id2", PUBLIC_MAV, new TypeParameter[0], interfaces, null);
1267 sd2.setIsContinuation(true);
1268 MethodData md2 =
1269 new MethodData("myMethod", PUBLIC_MAV, new TypeParameter[0], SymbolData.INT_TYPE, new VariableData[0],
1270 new String[0], sd2, amd2);
1271 LanguageLevelConverter.symbolTable.put("id", sd);
1272 LanguageLevelConverter.symbolTable.put("id2", sd2);
1273
1274 id.visit(_iv);
1275 id2.visit(_iv);
1276
1277 assertEquals("Should be no errors", 0, errors.size());
1278 assertEquals("Should return the same symbol datas: id", sd, LanguageLevelConverter.symbolTable.get("id"));
1279 assertEquals("Should return the same symbol datas:id2 ", sd2, LanguageLevelConverter.symbolTable.get("id2"));
1280 }
1281
1282
1283
1284 public void testCreateMethodData() {
1285 // Test one that doesn't work.
1286 MethodDef mdef = new AbstractMethodDef(SourceInfo.NONE,
1287 PRIVATE_ABSTRACT_MAV,
1288 new TypeParameter[0],
1289 new PrimitiveType(SourceInfo.NONE, "int"),
1290 new Word(SourceInfo.NONE, "methodName"),
1291 new FormalParameter[0],
1292 new ReferenceType[0]);
1293
1294 MethodData mdata = new MethodData("methodName", PRIVATE_ABSTRACT_MAV, new TypeParameter[0], SymbolData.INT_TYPE,
1295 new VariableData[0],
1296 new String[0],
1297 _sd1,
1298 null);
1299 _iv._package = "i.like";
1300 _iv._enclosingClassName = "i.like.monkey";
1301 _iv.symbolTable.put("i.like.monkey", _sd1);
1302 // System.err.println("SymbolData for i.like.monkey = " + _iv.getQualifiedSymbolData("i.like.monkey", SourceInfo.NONE));
1303 assertEquals("Should return the correct MethodData", mdata, _iv.createMethodData(mdef, _sd1));
1304 assertEquals("There should be one errors.", 1, errors.size());
1305 // assertEquals("The error message should be correct.",
1306 // "The keyword \"final\" cannot be used at the Intermediate level",
1307 // errors.get(0).getFirst());
1308
1309 // Test one that does work.
1310 UninitializedVariableDeclarator uvd1 =
1311 new UninitializedVariableDeclarator(SourceInfo.NONE,
1312 new PrimitiveType(SourceInfo.NONE, "double"),
1313 new Word(SourceInfo.NONE, "field1"));
1314 UninitializedVariableDeclarator uvd2 =
1315 new UninitializedVariableDeclarator(SourceInfo.NONE,
1316 new PrimitiveType(SourceInfo.NONE, "int"),
1317 new Word(SourceInfo.NONE, "field1"));
1318 mdef =
1319 new AbstractMethodDef(SourceInfo.NONE,
1320 ABSTRACT_MAV,
1321 new TypeParameter[] { new TypeParameter(SourceInfo.NONE,
1322 new TypeVariable(SourceInfo.NONE, "T"),
1323 new TypeVariable(SourceInfo.NONE, "U"))},
1324 new VoidReturn(SourceInfo.NONE, "void"),
1325 new Word(SourceInfo.NONE, "methodName"),
1326 new FormalParameter[] {
1327 new FormalParameter(SourceInfo.NONE,
1328 uvd1,
1329 false
1330 ),
1331 new FormalParameter(SourceInfo.NONE,
1332 uvd2,
1333 false
1334 )},
1335 new ReferenceType[] { new TypeVariable(SourceInfo.NONE, "X") }
1336 );
1337 mdata =
1338 new MethodData("methodName",
1339 ABSTRACT_MAV,
1340 new TypeParameter[] { new TypeParameter(SourceInfo.NONE,
1341 new TypeVariable(SourceInfo.NONE, "T"),
1342 new TypeVariable(SourceInfo.NONE, "U"))},
1343 SymbolData.VOID_TYPE,
1344 new VariableData[] { new VariableData("field1", FINAL_MAV, SymbolData.DOUBLE_TYPE, true, _sd1),
1345 new VariableData("field1", FINAL_MAV, SymbolData.INT_TYPE, true, _sd1) },
1346 new String[] { "X" },
1347 _sd1,
1348 null);
1349
1350
1351 MethodData result = _iv.createMethodData(mdef, _sd1);
1352 /* Enclosing data for formal parameters is the enclosing class, not the enclosing method. */
1353 // mdata.getParams()[0].setEnclosingData(result);
1354 // mdata.getParams()[1].setEnclosingData(result);
1355
1356 // have to add the parameters to the vars manually
1357 mdata.addVars(new VariableData[] { new VariableData("field1", FINAL_MAV, SymbolData.DOUBLE_TYPE, true, _sd1) });
1358 // System.err.println("****** mdata = " + mdata);
1359 // System.err.println("****** result = " + result);
1360 assertEquals("Should return the correct MethodData", mdata, result);
1361 assertEquals("There should be 2 errors.", 2, errors.size());
1362 // This is now caught in the type checker.
1363 // assertEquals("The second error message should be correct.",
1364 // "The keyword \"void\" cannot be used at the Intermediate level",
1365 // errors.get(1).getFirst());
1366 assertEquals("The second error message should be correct.",
1367 "You cannot have two method parameters with the same name",
1368 errors.get(1).getFirst());
1369 }
1370
1371 public void testSimpleAnonymousClassInstantiationHelper() {
1372 SimpleAnonymousClassInstantiation basic =
1373 new SimpleAnonymousClassInstantiation(SourceInfo.NONE,
1374 new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]),
1375 new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]),
1376 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1377 _iv._package = "i.like";
1378 _iv._enclosingClassName = "i.like.monkey";
1379 _iv.symbolTable.put("i.like.monkey", _sd1);
1380 // System.err.println("SymbolData for i.like.monkey = " + _iv.getQualifiedSymbolData("i.like.monkey", SourceInfo.NONE));
1381 _iv.simpleAnonymousClassInstantiationHelper(basic, _sd1);
1382 assertEquals("There should be no errors", 0, errors.size());
1383 SymbolData obj = LanguageLevelConverter.symbolTable.get("java.lang.Object");
1384 assertNotNull("Object should be in the symbol table", obj);
1385 assertEquals("sd1 should have one inner class", 1, _sd1.getInnerClasses().size());
1386 SymbolData inner = _sd1.getInnerClasses().get(0);
1387 assertEquals("The inner class should have the proper name", "i.like.monkey$1", inner.getName());
1388 assertEquals("The inner class should have proper outer data", _sd1, inner.getOuterData());
1389 assertEquals("The inner class should have proper super class", obj, inner.getSuperClass());
1390 assertEquals("The inner class should have the right package", "i.like", inner.getPackage());
1391 assertEquals("The inner class should have 3 methods", 3, inner.getMethods().size());
1392 }
1393
1394 public void testComplexAnonymousClassInstantiationHelper() {
1395 SimpleNameReference snr =
1396 new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "java.lang.Object"));
1397 ComplexAnonymousClassInstantiation basic =
1398 new ComplexAnonymousClassInstantiation(SourceInfo.NONE,
1399 snr,
1400 new ClassOrInterfaceType(SourceInfo.NONE, "Inner", new Type[0]),
1401 new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]),
1402 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1403 _iv._package = "i.like";
1404 _iv._enclosingClassName = "i.like.monkey";
1405 _iv.complexAnonymousClassInstantiationHelper(basic, _sd1); // TODO: the wrong enclosing context?
1406 assertEquals("There should be no errors", 0, errors.size());
1407 SymbolData obj = LanguageLevelConverter.symbolTable.get("java.lang.Object");
1408 assertNotNull("Object should be in the symbol table", obj);
1409 SymbolData objInner = LanguageLevelConverter.symbolTable.get("java.lang.Object.Inner");
1410 assertEquals("sd1 should have one inner class", 1, _sd1.getInnerClasses().size());
1411 SymbolData inner = _sd1.getInnerClasses().get(0);
1412 assertEquals("The inner class should have the proper name", "i.like.monkey$1", inner.getName());
1413 assertEquals("The inner class should have proper outer data", _sd1, inner.getOuterData());
1414 assertEquals("The inner class should have null as its super class", null, inner.getSuperClass());
1415 assertEquals("The inner class should have the right package", "i.like", inner.getPackage());
1416 assertEquals("The inner class should have 3 methods", 3, inner.getMethods().size());
1417 }
1418
1419 public void testForVariableDeclaration() {
1420 // Confirm that if forVariableDeclaration is called with a AnonymousClassInstantiation, the symboldata is only
1421 // added once. This is to make sure an old bug stays fixed.
1422 SimpleAnonymousClassInstantiation basic =
1423 new SimpleAnonymousClassInstantiation(SourceInfo.NONE,
1424 new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]),
1425 new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]),
1426 new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1427
1428
1429
1430 VariableDeclarator[] d1 = {
1431 new InitializedVariableDeclarator(SourceInfo.NONE,
1432 new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]),
1433 new Word(SourceInfo.NONE, "b"), basic)};
1434
1435 VariableDeclaration vd1 = new VariableDeclaration(SourceInfo.NONE,PUBLIC_MAV, d1);
1436
1437 ClassBodyIntermediateVisitor cbiv =
1438 new ClassBodyIntermediateVisitor(_sd1,
1439 _sd1.getName(),
1440 _iv._file,
1441 _iv._package,
1442 _iv._importedFiles,
1443 _iv._importedPackages,
1444 _iv._classesInThisFile,
1445 _iv.continuations,
1446 _iv.fixUps);
1447
1448 vd1.visit(cbiv);
1449 assertEquals("Should be 1 inner class of _sd1", 1, _sd1.getInnerClasses().size());
1450 }
1451
1452 public void testForPackageStatementDoFirst() {
1453 PackageStatement ps = new PackageStatement(SourceInfo.NONE, new CompoundWord(SourceInfo.NONE, new Word[0]));
1454 ps.visit(_iv);
1455 assertEquals("Should be no errors", 0, errors.size());
1456 // assertEquals("Error message should be correct", "Package statements cannot be used at the Intermediate level."
1457 // + " All Intermediate level classes and interfaces are assumed to be in the default package",
1458 // errors.getLast().getFirst());
1459 }
1460 }
1461 }