Clover coverage report - DynamicJava Test Coverage (dynamicjava-20130615-r5436)
Coverage timestamp: Sat Jun 15 2013 03:01:32 CDT
file stats: LOC: 409   Methods: 39
NCLOC: 300   Classes: 5
 
 Source file Conditionals Statements Methods TOTAL
ClassChecker.java 47.6% 62.1% 46.2% 57.4%
coverage coverage
 1    package edu.rice.cs.dynamicjava.interpreter;
 2   
 3    import java.util.Collections;
 4   
 5    import koala.dynamicjava.tree.*;
 6    import koala.dynamicjava.tree.tiger.*;
 7    import koala.dynamicjava.tree.visitor.*;
 8    import koala.dynamicjava.interpreter.error.ExecutionError;
 9    import edu.rice.cs.dynamicjava.Options;
 10    import edu.rice.cs.dynamicjava.symbol.*;
 11    import edu.rice.cs.dynamicjava.symbol.type.Type;
 12   
 13    import static koala.dynamicjava.interpreter.NodeProperties.*;
 14   
 15    import static edu.rice.cs.plt.debug.DebugUtil.debug;
 16   
 17    /**
 18    * Checks the members of a class declaration.
 19    * The following are set:<ul>
 20    * <li>ERASED_TYPE on all {@link MethodDeclaration}s</li>
 21    * </ul>
 22    */
 23    public class ClassChecker {
 24   
 25    private final DJClass _c;
 26    private final ClassLoader _loader;
 27    private final TypeContext _context;
 28    private final Options _opt;
 29   
 30  89 public ClassChecker(DJClass c, ClassLoader loader, TypeContext context, Options opt) {
 31  89 _c = c;
 32  89 _loader = loader;
 33  89 _context = context;
 34  89 _opt = opt;
 35    }
 36   
 37    /**
 38    * Initialize and check the structure of types in the signatures of the given class and any nested
 39    * classes. Requires the {@code DJ_CLASS} property to be set on all referenced classes; after this
 40    * step, the type hierarchy may safely be traversed. Types aren't guaranteed to be well-formed.
 41    */
 42  89 public void initializeClassSignatures(TypeDeclaration ast) {
 43  89 TypeContext sigContext = new ClassSignatureContext(_context, _c, _loader);
 44  89 TypeNameChecker sigChecker = new TypeNameChecker(sigContext, _opt);
 45  89 debug.logStart("Initializing type parameters", "class", ast.getName());
 46  89 try {
 47  89 Iterable<TypeParameter> tparams = ast.getTypeParams().unwrap(Collections.<TypeParameter>emptyList());
 48  89 sigChecker.checkStructureForTypeParameters(tparams);
 49    }
 50  89 finally { debug.logEnd(); }
 51  89 debug.logStart("Initializing supertypes", "class", ast.getName());
 52  89 try {
 53  89 if (ast instanceof ClassDeclaration) {
 54  89 sigChecker.checkStructure(((ClassDeclaration) ast).getSuperclass());
 55    }
 56  89 if (ast.getInterfaces() != null) {
 57  1 for (TypeName tn : ast.getInterfaces()) { sigChecker.checkStructure(tn); }
 58    }
 59    }
 60  89 finally { debug.logEnd(); }
 61  89 initializeNestedClassSignatures(ast.getMembers(), sigContext);
 62    }
 63   
 64    /**
 65    * Initialize and check the structure of types in the signatures of the given class and any nested
 66    * classes. Requires the {@code DJ_CLASS} property to be set on all referenced classes; after this
 67    * step, the type hierarchy may safely be traversed. Types aren't guaranteed to be well-formed.
 68    */
 69  0 public void initializeClassSignatures(AnonymousAllocation ast) {
 70  0 initializeNestedClassSignatures(ast.getMembers(), new ClassSignatureContext(_context, _c, _loader));
 71    }
 72   
 73    /**
 74    * Initialize and check the structure of types in the signatures of the given class and any nested
 75    * classes. Requires the {@code DJ_CLASS} property to be set on all referenced classes; after this
 76    * step, the type hierarchy may safely be traversed. Types aren't guaranteed to be well-formed.
 77    */
 78  0 public void initializeClassSignatures(AnonymousInnerAllocation ast) {
 79  0 initializeNestedClassSignatures(ast.getMembers(), new ClassSignatureContext(_context, _c, _loader));
 80    }
 81   
 82  89 private void initializeNestedClassSignatures(Iterable<? extends Node> members, TypeContext sigContext) {
 83  89 TypeContext bodyContext = new ClassContext(sigContext, _c);
 84  89 ExecutionError error = null;
 85  89 for (Node member : members) {
 86  250 try {
 87  250 if (member instanceof TypeDeclaration) {
 88  0 ClassChecker nestedChecker = new ClassChecker(getDJClass(member), _loader, bodyContext, _opt);
 89  0 nestedChecker.initializeClassSignatures((TypeDeclaration) member);
 90    }
 91    }
 92    catch (ExecutionError e) {
 93  0 if (error == null) { error = e; }
 94    }
 95    }
 96  0 if (error != null) { throw error; }
 97    }
 98   
 99    /**
 100    * Check the class's signature declarations. Verifies that the class's signature is well formed,
 101    * checks the types in field and method signatures, and recurs on nested classes.
 102    */
 103  89 public void checkSignatures(TypeDeclaration ast) {
 104  89 TypeContext sigContext = new ClassSignatureContext(_context, _c, _loader);
 105  89 TypeNameChecker sigChecker = new TypeNameChecker(sigContext, _opt);
 106  89 debug.logStart("Check type parameters");
 107  89 try {
 108  89 Iterable<TypeParameter> tparams = ast.getTypeParams().unwrap(Collections.<TypeParameter>emptyList());
 109  89 sigChecker.ensureWellFormedTypeParameters(tparams);
 110    }
 111  89 finally { debug.logEnd(); }
 112  89 debug.logStart("Check supertypes");
 113  89 try {
 114  89 if (ast instanceof ClassDeclaration) {
 115  89 sigChecker.ensureWellFormed(((ClassDeclaration) ast).getSuperclass());
 116    }
 117  89 if (ast.getInterfaces() != null) {
 118  1 for (TypeName tn : ast.getInterfaces()) { sigChecker.ensureWellFormed(tn); }
 119    }
 120    }
 121  89 finally { debug.logEnd(); }
 122   
 123  0 if (ast instanceof InterfaceDeclaration) { checkInterfaceMemberSignatures(ast.getMembers(), sigContext); }
 124  89 else { checkClassMemberSignatures(ast.getMembers(), sigContext); }
 125    }
 126   
 127    /**
 128    * Check the class's signature declarations. Verifies that the class's signature is well formed,
 129    * checks the types in field and method signatures, and recurs on nested classes.
 130    */
 131  0 public void checkSignatures(AnonymousAllocation ast) {
 132  0 checkClassMemberSignatures(ast.getMembers(), new ClassSignatureContext(_context, _c, _loader));
 133    }
 134   
 135    /**
 136    * Check the class's signature declarations. Verifies that the class's signature is well formed,
 137    * checks the types in field and method signatures, and recurs on nested classes.
 138    */
 139  0 public void checkSignatures(AnonymousInnerAllocation ast) {
 140  0 checkClassMemberSignatures(ast.getMembers(), new ClassSignatureContext(_context, _c, _loader));
 141    }
 142   
 143  178 private void visitMembers(Iterable<? extends Node> members, Visitor<?> v) {
 144  178 ExecutionError error = null;
 145  178 for (Node n : members) {
 146  500 debug.logStart();
 147  500 try { n.acceptVisitor(v); }
 148    catch (ExecutionError e) {
 149  0 if (error == null) { error = e; }
 150    }
 151  500 finally { debug.logEnd(); }
 152    }
 153  0 if (error != null) { throw error; }
 154    }
 155   
 156  89 private void checkClassMemberSignatures(Iterable<? extends Node> members, TypeContext sigContext) {
 157  89 TypeContext bodyContext = new ClassContext(sigContext, _c);
 158  89 visitMembers(members, new ClassMemberSignatureVisitor(bodyContext));
 159    }
 160   
 161  0 private void checkInterfaceMemberSignatures(Iterable<? extends Node> members, TypeContext sigContext) {
 162  0 TypeContext bodyContext = new ClassContext(sigContext, _c);
 163  0 visitMembers(members, new InterfaceMemberSignatureVisitor(bodyContext));
 164    }
 165   
 166    /**
 167    * Check the field initializers, method bodies, nested class bodies, etc., of a class or interface declaration.
 168    * Should be called <em>after</em> the signatures of all relevant classes and interfaces have been checked.
 169    */
 170  89 public void checkBodies(TypeDeclaration ast) {
 171  89 checkBodies(ast.getMembers());
 172    }
 173   
 174    /**
 175    * Check the field initializers, method bodies, nested class bodies, etc., of a class or interface declaration.
 176    * Should be called <em>after</em> the signatures of all relevant classes and interfaces have been checked.
 177    */
 178  0 public void checkBodies(AnonymousAllocation ast) {
 179  0 checkBodies(ast.getMembers());
 180    }
 181   
 182    /**
 183    * Check the field initializers, method bodies, nested class bodies, etc., of a class or interface declaration.
 184    * Should be called <em>after</em> the signatures of all relevant classes and interfaces have been checked.
 185    */
 186  0 public void checkBodies(AnonymousInnerAllocation ast) {
 187  0 checkBodies(ast.getMembers());
 188    }
 189   
 190  89 private void checkBodies(Iterable<? extends Node> members) {
 191  89 TypeContext sigContext = new ClassSignatureContext(_context, _c, _loader);
 192  89 TypeContext bodyContext = new ClassContext(sigContext, _c);
 193  89 visitMembers(members, new MemberBodyVisitor(bodyContext));
 194    }
 195   
 196    private abstract class MemberSignatureVisitor extends AbstractVisitor<Void> {
 197   
 198    protected final TypeContext _bodyContext;
 199   
 200  89 protected MemberSignatureVisitor(TypeContext bodyContext) { _bodyContext = bodyContext; }
 201   
 202  0 @Override public Void visit(ClassDeclaration node) {
 203  0 new ClassChecker(getDJClass(node), _loader, _bodyContext, _opt).checkSignatures(node);
 204  0 return null;
 205    }
 206   
 207  0 @Override public Void visit(InterfaceDeclaration node) {
 208  0 new ClassChecker(getDJClass(node), _loader, _bodyContext, _opt).checkSignatures(node);
 209  0 return null;
 210    }
 211   
 212  158 @Override public Void visit(MethodDeclaration node) {
 213  158 DJMethod m = getMethod(node);
 214   
 215  158 TypeContext sigContext = new FunctionSignatureContext(_bodyContext, m);
 216  158 TypeNameChecker sigChecker = new TypeNameChecker(sigContext, _opt);
 217   
 218  158 Iterable<TypeParameter> tparams = node.getTypeParams().unwrap(Collections.<TypeParameter>emptyList());
 219  158 sigChecker.checkTypeParameters(tparams);
 220   
 221  158 Type returnT = sigChecker.check(node.getReturnType());
 222  158 setErasedType(node, _opt.typeSystem().erasedClass(returnT));
 223   
 224  158 for (FormalParameter param : node.getParameters()) {
 225  167 Type t = sigChecker.check(param.getType());
 226  167 setVariable(param, new LocalVariable(param.getName(), t, param.getModifiers().isFinal()));
 227    }
 228   
 229  0 for (TypeName tn : node.getExceptions()) { sigChecker.check(tn); }
 230  158 return null;
 231    }
 232   
 233  23 @Override public Void visit(FieldDeclaration node) {
 234  23 new TypeNameChecker(_bodyContext, _opt).check(node.getType());
 235  23 return null;
 236    }
 237   
 238    @Override public abstract Void visit(ConstructorDeclaration node);
 239    @Override public abstract Void visit(ClassInitializer node);
 240    @Override public abstract Void visit(InstanceInitializer node);
 241    }
 242   
 243    private class ClassMemberSignatureVisitor extends MemberSignatureVisitor {
 244   
 245  89 public ClassMemberSignatureVisitor(TypeContext bodyContext) { super(bodyContext); }
 246   
 247  158 @Override public Void visit(MethodDeclaration node) {
 248  158 super.visit(node);
 249  158 ModifierSet mods = node.getModifiers();
 250  158 if (mods.isAbstract() && node.getBody() != null) {
 251  0 setErrorStrings(node, node.getName());
 252  0 throw new ExecutionError("abstract.method.body", node);
 253    }
 254  158 else if (!mods.isAbstract() && !mods.isNative() && node.getBody() == null) {
 255  0 setErrorStrings(node, node.getName());
 256  0 throw new ExecutionError("missing.method.body", node);
 257    }
 258  158 return null;
 259    }
 260   
 261  69 @Override public Void visit(ConstructorDeclaration node) {
 262  69 DJConstructor k = getConstructor(node);
 263  69 if (_c.isAnonymous() || !_c.declaredName().equals(node.getName())) {
 264  0 setErrorStrings(node, node.getName());
 265  0 throw new ExecutionError("constructor.name", node);
 266    }
 267   
 268  69 TypeContext sigContext = new FunctionSignatureContext(_bodyContext, k);
 269  69 TypeNameChecker sigChecker = new TypeNameChecker(sigContext, _opt);
 270   
 271  69 Iterable<TypeParameter> tparams = node.getTypeParams().unwrap(Collections.<TypeParameter>emptyList());
 272  69 sigChecker.checkTypeParameters(tparams);
 273   
 274  69 for (FormalParameter param : node.getParameters()) {
 275  69 Type t = sigChecker.check(param.getType());
 276  69 setVariable(param, new LocalVariable(param.getName(), t, param.getModifiers().isFinal()));
 277    }
 278   
 279  0 for (TypeName tn : node.getExceptions()) { sigChecker.check(tn); }
 280  69 return null;
 281    }
 282   
 283  0 @Override public Void visit(ClassInitializer node) {
 284  0 return null;
 285    }
 286   
 287  0 @Override public Void visit(InstanceInitializer node) {
 288  0 return null;
 289    }
 290   
 291    }
 292   
 293    private class InterfaceMemberSignatureVisitor extends MemberSignatureVisitor {
 294   
 295  0 public InterfaceMemberSignatureVisitor(TypeContext bodyContext) { super(bodyContext); }
 296   
 297  0 @Override public Void visit(MethodDeclaration node) {
 298  0 super.visit(node);
 299  0 if (node.getBody() != null) {
 300  0 setErrorStrings(node, node.getName());
 301  0 throw new ExecutionError("abstract.method.body", node);
 302    }
 303  0 return null;
 304    }
 305   
 306  0 @Override public Void visit(FieldDeclaration node) {
 307  0 super.visit(node);
 308  0 if (node.getInitializer() == null) {
 309  0 setErrorStrings(node, node.getName());
 310  0 throw new ExecutionError("uninitialized.variable", node);
 311    }
 312  0 return null;
 313    }
 314   
 315  0 @Override public Void visit(ConstructorDeclaration node) {
 316  0 throw new ExecutionError("interface.member", node);
 317    }
 318  0 @Override public Void visit(ClassInitializer node) {
 319  0 throw new ExecutionError("interface.member", node);
 320    }
 321  0 @Override public Void visit(InstanceInitializer node) {
 322  0 throw new ExecutionError("interface.member", node);
 323    }
 324   
 325    }
 326   
 327    private class MemberBodyVisitor extends AbstractVisitor<Void> {
 328   
 329    private final TypeContext _bodyContext;
 330   
 331  89 public MemberBodyVisitor(TypeContext bodyContext) { _bodyContext = bodyContext; }
 332   
 333  0 @Override public Void visit(ClassDeclaration node) {
 334  0 new ClassChecker(getDJClass(node), _loader, _bodyContext, _opt).checkBodies(node);
 335  0 return null;
 336    }
 337   
 338  0 @Override public Void visit(InterfaceDeclaration node) {
 339  0 new ClassChecker(getDJClass(node), _loader, _bodyContext, _opt).checkBodies(node);
 340  0 return null;
 341    }
 342   
 343  158 @Override public Void visit(MethodDeclaration node) {
 344  158 if (node.getBody() != null) {
 345  158 DJMethod m = getMethod(node);
 346  158 TypeContext sigContext = new FunctionSignatureContext(_bodyContext, m);
 347  158 TypeContext bodyContext = new FunctionContext(sigContext, m);
 348  158 node.getBody().acceptVisitor(new StatementChecker(bodyContext, _opt));
 349    }
 350  158 return null;
 351    }
 352   
 353  69 @Override public Void visit(ConstructorDeclaration node) {
 354  69 DJConstructor k = getConstructor(node);
 355  69 TypeContext sigContext = new FunctionSignatureContext(_bodyContext, k);
 356  69 TypeContext bodyContext = new FunctionContext(sigContext, k);
 357  69 ExpressionChecker callChecker = new ExpressionChecker(bodyContext, _opt);
 358  69 ConstructorCall call = node.getConstructorCall();
 359  69 ExecutionError error = null;
 360  69 if (call != null) {
 361  46 try { callChecker.checkConstructorCall(call); }
 362  0 catch (ExecutionError e) { error = e; }
 363    }
 364  69 try { new StatementChecker(bodyContext, _opt).checkList(node.getStatements()); }
 365    catch (ExecutionError e) {
 366  0 if (error != null) { error = e; }
 367    }
 368    // if the call is implicit, only check it if there are no errors (avoids redundant errors)
 369  69 if (call == null && error == null) {
 370  23 callChecker.checkConstructorCall(new ConstructorCall(null, null, true));
 371    }
 372  0 if (error != null) { throw error; }
 373  69 return null;
 374    }
 375   
 376  23 @Override public Void visit(FieldDeclaration node) {
 377  23 Expression init = node.getInitializer();
 378  23 if (init != null) {
 379  0 TypeContext c = new InitializerContext(_bodyContext, getField(node).isStatic(), _c);
 380  0 Type expectedT = getType(node.getType());
 381  0 Type initT = new ExpressionChecker(c, _opt).check(init, expectedT);
 382  0 TypeSystem ts = _opt.typeSystem();
 383  0 try {
 384  0 Expression newInit = ts.assign(expectedT, init);
 385  0 node.setInitializer(newInit);
 386    }
 387    catch (TypeSystem.UnsupportedConversionException e) {
 388  0 TypeSystem.TypePrinter printer = ts.typePrinter();
 389  0 setErrorStrings(node, printer.print(initT), printer.print(expectedT));
 390  0 throw new ExecutionError("assignment.types", node);
 391    }
 392    }
 393  23 return null;
 394    }
 395   
 396  0 @Override public Void visit(ClassInitializer node) {
 397  0 TypeContext c = new InitializerContext(_bodyContext, true, _c);
 398  0 node.getBlock().acceptVisitor(new StatementChecker(c, _opt));
 399  0 return null;
 400    }
 401   
 402  0 @Override public Void visit(InstanceInitializer node) {
 403  0 TypeContext c = new InitializerContext(_bodyContext, false, _c);
 404  0 node.getBlock().acceptVisitor(new StatementChecker(c, _opt));
 405  0 return null;
 406    }
 407    }
 408   
 409    }