001package daikon.tools.runtimechecker; 002 003import daikon.tools.jtb.Ast; 004import jtb.syntaxtree.*; 005import org.checkerframework.checker.nullness.qual.NonNull; 006 007/** Represents a class created by the instrumenter to check invariants. */ 008public class CheckerClass { 009 010 String name; 011 StringBuilder code; 012 ClassOrInterfaceBody fclassbody; 013 014 public CheckerClass(ClassOrInterfaceBody clazz) { 015 this.fclassbody = clazz; 016 017 // The getClassName method may return some $'s and .'s. 018 // Since this is going to become a class name, remove them. 019 this.name = Ast.getClassName(clazz).replace("$", "_").replace(".", "_") + "_checks"; 020 021 // CompilationUnit: 022 // f0 -> [ PackageDeclaration() ] 023 // f1 -> ( ImportDeclaration() )* 024 // f2 -> ( TypeDeclaration() )* 025 // f3 -> ( <"\u001a"> )? 026 // f4 -> ( <STUFF_TO_IGNORE: ~[]> )? 027 // f5 -> <EOF> 028 // PackageDeclaration: 029 // f0 -> Modifiers() 030 // f1 -> "package" 031 // f2 -> Name() 032 // f3 -> ";" 033 // Get the package and imports from clazz. We'll include them. 034 @SuppressWarnings("nullness") // application invariant: every body is in a compilation unit 035 @NonNull CompilationUnit clazzCU = 036 (CompilationUnit) Ast.getParent(CompilationUnit.class, clazz); 037 NodeOptional no = clazzCU.f0; 038 String packageName; 039 if (no.present()) { 040 packageName = Ast.format(((PackageDeclaration) no.node).f2).trim(); 041 } else { 042 packageName = ""; 043 } 044 045 String imports = Ast.format(clazzCU.f1); 046 047 code = new StringBuilder(); 048 if (!packageName.equals("")) { 049 code.append("package " + packageName + ";"); 050 } 051 code.append(imports); 052 code.append(" public class " + name + "{ "); 053 } 054 055 // See getCompilationUnit(). 056 private boolean alreadyCalled = false; 057 058 /** Must be called only once, when you're done creating this checker. */ 059 public CompilationUnit getCompilationUnit() { 060 if (alreadyCalled) { 061 throw new Error("getCompilationUnit should only be called once."); 062 } 063 alreadyCalled = true; 064 code.append("}"); // we're done declaring the class. 065 return (CompilationUnit) Ast.create("CompilationUnit", code.toString()); 066 } 067 068 public String getCheckerClassName() { 069 return name; 070 } 071 072 public void addDeclaration(StringBuilder decl) { 073 code.append(decl); 074 } 075}