1 package annotator.find; 2 3 import java.util.List; 4 import java.util.regex.Matcher; 5 import java.util.regex.Pattern; 6 7 import type.DeclaredType; 8 import type.Type; 9 10 /** 11 * @author dbro 12 * 13 */ 14 public class NewInsertion extends TypedInsertion { 15 private final static Pattern qualifiers = Pattern.compile("(?:\\w++\\.)*+"); 16 17 /** 18 * If true, the type will be qualified with the name of the superclass. 19 */ 20 protected boolean qualifyType; 21 22 /** 23 * Construct a NewInsertion. 24 * <p> 25 * If "new" already exists in the initializer, then pass a 26 * {@link DeclaredType} thats name is the empty String. This will only 27 * insert an annotation on the existing type. 28 * <p> 29 * To insert the annotation along with "new" and the type (for example, 30 * {@code @Anno new Type[] \{...\}}), set the name to the type to insert. 31 * This can be done either before calling this constructor, or by modifying 32 * the return value of {@link #getType()}. 33 * 34 * @param type the type to use when inserting the receiver 35 * @param criteria where to insert the text 36 * @param innerTypeInsertions the inner types to go on this receiver 37 */ NewInsertion(Type type, Criteria criteria, List<Insertion> innerTypeInsertions)38 public NewInsertion(Type type, Criteria criteria, 39 List<Insertion> innerTypeInsertions) { 40 super(type, criteria, innerTypeInsertions); 41 annotationsOnly = false; 42 qualifyType = false; 43 } 44 45 /** {@inheritDoc} */ 46 @Override getText(boolean comments, boolean abbreviate)47 protected String getText(boolean comments, boolean abbreviate) { 48 if (annotationsOnly || type.getKind() != Type.Kind.ARRAY) { 49 StringBuilder b = new StringBuilder(); 50 List<String> annotations = type.getAnnotations(); 51 if (annotations.isEmpty()) { return ""; } 52 for (String a : annotations) { 53 b.append(' ').append(a); // initial space removed below 54 } 55 return new AnnotationInsertion(b.substring(1), getCriteria(), 56 getSeparateLine()).getText(comments, abbreviate); 57 } else { 58 DeclaredType baseType = getBaseType(); 59 boolean commentAnnotation = (comments && baseType.getName().isEmpty()); 60 String result = typeToString(type, commentAnnotation, abbreviate); 61 if (!baseType.getName().isEmpty()) { 62 // First, temporarily strip off any qualifiers. 63 Matcher matcher = qualifiers.matcher(result); 64 String prefix = ""; 65 if (matcher.find() && matcher.start() == 0) { 66 prefix = result.substring(0, matcher.end()); 67 result = result.substring(matcher.end()); 68 } 69 // If the variable name preceded the array brackets in the 70 // source, extract it from the result. 71 if (qualifyType) { 72 for (DeclaredType t = baseType; t != null; t = t.getInnerType()) { 73 result += t.getName() + "."; 74 } 75 } 76 // Finally, prepend extracted qualifiers. 77 result = prefix + result; 78 } 79 result = "new " + result; 80 if (comments) { 81 result = "/*>>> " + result + " */"; 82 } 83 return result; 84 } 85 } 86 87 /** 88 * If {@code true}, qualify {@code type} with the name of the superclass. 89 * This will only happen if a "new" is inserted. 90 */ setQualifyType(boolean qualifyType)91 public void setQualifyType(boolean qualifyType) { 92 this.qualifyType = qualifyType; 93 } 94 95 /** {@inheritDoc} */ 96 @Override addLeadingSpace(boolean gotSeparateLine, int pos, char precedingChar)97 protected boolean addLeadingSpace(boolean gotSeparateLine, int pos, 98 char precedingChar) { 99 if ((precedingChar == '.' || precedingChar == '(') 100 && getBaseType().getName().isEmpty()) { 101 // If only the annotation is being inserted then don't insert a 102 // space if it's immediately after a '.' or '(' 103 return false; 104 } 105 return super.addLeadingSpace(gotSeparateLine, pos, precedingChar); 106 } 107 108 /** {@inheritDoc} */ 109 @Override addTrailingSpace(boolean gotSeparateLine)110 protected boolean addTrailingSpace(boolean gotSeparateLine) { 111 return true; 112 } 113 114 /** {@inheritDoc} */ 115 @Override getKind()116 public Kind getKind() { 117 return Kind.NEW; 118 } 119 } 120