1 package annotator.find; 2 3 import plume.Pair; 4 5 /** 6 * Specifies an annotation to be inserted into a source file. 7 */ 8 public class AnnotationInsertion extends Insertion { 9 10 /** 11 * The annotation to insert. 12 */ 13 private final String annotation; 14 private String type; 15 private boolean generateBound; 16 private boolean generateExtends; 17 private boolean wasGenerateExtends; 18 19 /** 20 * Creates a new insertion. 21 * 22 * @param annotation the annotation to insert, which starts with "@" 23 * @param criteria where to insert the annotation 24 * @param separateLine whether to insert the annotation on its own 25 */ AnnotationInsertion(String annotation, Criteria criteria, boolean separateLine)26 public AnnotationInsertion(String annotation, Criteria criteria, boolean separateLine) { 27 super(criteria, separateLine); 28 this.annotation = annotation; 29 type = null; 30 generateBound = false; 31 generateExtends = false; 32 wasGenerateExtends = false; 33 } 34 35 /** 36 * Creates a new insertion with an empty criteria and the text inserted on 37 * the same line. 38 * 39 * @param annotation the text to insert 40 */ AnnotationInsertion(String annotation)41 public AnnotationInsertion(String annotation) { 42 this(annotation, new Criteria(), false); 43 } 44 isGenerateExtends()45 public boolean isGenerateExtends() { 46 return generateExtends; 47 } 48 isGenerateBound()49 public boolean isGenerateBound() { 50 return generateBound; 51 } 52 setGenerateExtends(boolean generateExtends)53 public void setGenerateExtends(boolean generateExtends) { 54 this.generateExtends = generateExtends; 55 this.wasGenerateExtends |= generateExtends; 56 } 57 setGenerateBound(boolean b)58 public void setGenerateBound(boolean b) { 59 generateBound = b; 60 } 61 62 /** 63 * Gets the insertion text. 64 * 65 * @param comments 66 * if true, the annotation will be surrounded by block comments 67 * @param abbreviate 68 * if true, the package name will be removed from the annotation. 69 * The package name can be retrieved again by calling the 70 * {@link #getPackageName()} method. 71 * @return the text to insert 72 */ getText(boolean comments, boolean abbreviate)73 protected String getText(boolean comments, boolean abbreviate) { 74 String result = annotation; 75 if (abbreviate) { 76 Pair<String, String> ps = removePackage(result); 77 String packageName = ps.a; 78 if (packageName != null) { 79 packageNames.add(packageName); 80 result = ps.b; 81 } 82 } 83 if (!result.startsWith("@")) { 84 throw new Error("Illegal insertion, must start with @: " + result); 85 } 86 87 // We insert a "new " when annotating a variable initializer that is a 88 // bare array expression (e.g., as in "int[] a = {0, 1};") Since the 89 // syntax doesn't permit adding the type annotation in front of the 90 // expression, we generate the explicit "new" 91 // (as in "int[] a = new int[] {0, 1}") to provide a legal insertion site. 92 93 if (type != null) { 94 result = "new " + result + " " + type; 95 } else if (generateBound) { 96 result += " Object &"; 97 } else if (generateExtends) { 98 result = " extends " + result + " Object"; 99 } 100 return comments ? "/*" + result + "*/" : result; 101 } 102 103 /** 104 * Gets the raw, unmodified annotation that was passed into the constructor. 105 * @return the annotation 106 */ getAnnotation()107 public String getAnnotation() { 108 return annotation; 109 } 110 111 /** {@inheritDoc} */ addLeadingSpace(boolean gotSeparateLine, int pos, char precedingChar)112 protected boolean addLeadingSpace(boolean gotSeparateLine, int pos, 113 char precedingChar) { 114 if (generateExtends || precedingChar == '.') { 115 return false; 116 } 117 return super.addLeadingSpace(gotSeparateLine, pos, precedingChar); 118 } 119 120 /** 121 * {@inheritDoc} 122 */ 123 @Override addTrailingSpace(boolean gotSeparateLine)124 protected boolean addTrailingSpace(boolean gotSeparateLine) { 125 // Never add a trailing space on a type parameter bound. 126 return !wasGenerateExtends && super.addTrailingSpace(gotSeparateLine); 127 } 128 129 /** {@inheritDoc} */ getKind()130 public Kind getKind() { 131 return Kind.ANNOTATION; 132 } 133 toString()134 public String toString() { 135 return annotation + " " + super.toString(); 136 } 137 setType(String s)138 public void setType(String s) { 139 this.type = s; 140 } 141 } 142