1 package annotator.find; 2 3 import java.util.List; 4 5 import type.DeclaredType; 6 7 /** 8 * An insertion for a method receiver. This supports inserting an 9 * annotation on an existing receiver and creating a new (annotated) 10 * receiver if none are present. 11 */ 12 public class ReceiverInsertion extends TypedInsertion { 13 /** 14 * If true a comma will be added at the end of the insertion (only if also 15 * inserting the receiver). 16 */ 17 private boolean addComma; 18 19 /** 20 * If true, {@code this} will be qualified with the name of the 21 * superclass. 22 */ 23 private boolean qualifyThis; 24 25 /** 26 * Construct a ReceiverInsertion. 27 * <p> 28 * If the receiver parameter already exists in the method declaration, then 29 * pass a DeclaredType thats name is the empty String. This will only insert 30 * an annotation on the existing receiver. 31 * <p> 32 * To insert the annotation and the receiver (for example, 33 * {@code @Anno Type this}) the name should be set to the type to insert. 34 * This can either be done before calling this constructor, or by modifying 35 * the return value of {@link #getType()}. 36 * <p> 37 * A comma will not be added to the end of the receiver. In the case that 38 * there is a parameter following the inserted receiver pass {@code true} to 39 * {@link #setAddComma(boolean)} to add a comma to the end of the receiver. 40 * 41 * @param type the type to use when inserting the receiver 42 * @param criteria where to insert the text 43 * @param innerTypeInsertions the inner types to go on this receiver 44 */ ReceiverInsertion(DeclaredType type, Criteria criteria, List<Insertion> innerTypeInsertions)45 public ReceiverInsertion(DeclaredType type, Criteria criteria, List<Insertion> innerTypeInsertions) { 46 super(type, criteria, innerTypeInsertions); 47 addComma = false; 48 qualifyThis = false; 49 } 50 51 /** 52 * If {@code true} a comma will be added at the end of the receiver. 53 * This will only happen if a receiver is inserted (see 54 * {@link #ReceiverInsertion(DeclaredType, Criteria, List)} for a description of 55 * when a receiver is inserted). This is useful if the method already has 56 * one or more parameters. 57 */ setAddComma(boolean addComma)58 public void setAddComma(boolean addComma) { 59 this.addComma = addComma; 60 } 61 62 /** 63 * If {@code true}, qualify {@code this} with the name of the superclass. 64 * This will only happen if a receiver is inserted (see 65 * {@link #ReceiverInsertion(DeclaredType, Criteria, List)} 66 * for a description of when a receiver is inserted). This is useful 67 * for inner class constructors. 68 */ setQualifyType(boolean qualifyThis)69 public void setQualifyType(boolean qualifyThis) { 70 this.qualifyThis = qualifyThis; 71 } 72 73 /** {@inheritDoc} */ 74 @Override getText(boolean comments, boolean abbreviate)75 protected String getText(boolean comments, boolean abbreviate) { 76 if (annotationsOnly) { 77 StringBuilder b = new StringBuilder(); 78 List<String> annotations = type.getAnnotations(); 79 if (annotations.isEmpty()) { return ""; } 80 for (String a : annotations) { 81 b.append(a); 82 b.append(' '); 83 } 84 return new AnnotationInsertion(b.toString(), getCriteria(), 85 getSeparateLine()).getText(comments, abbreviate); 86 } else { 87 DeclaredType baseType = getBaseType(); 88 boolean commentAnnotation = (comments && baseType.getName().isEmpty()); 89 String result = typeToString(type, commentAnnotation, abbreviate); 90 if (!baseType.getName().isEmpty()) { 91 result += " "; 92 if (qualifyThis) { 93 for (DeclaredType t = baseType; t != null; 94 t = t.getInnerType()) { 95 result += t.getName() + "."; 96 } 97 } 98 result += "this"; 99 if (addComma) { 100 result += ","; 101 } 102 if (comments) { 103 result = "/*>>> " + result + " */"; 104 } 105 } 106 return result; 107 } 108 } 109 110 /** {@inheritDoc} */ 111 @Override addLeadingSpace(boolean gotSeparateLine, int pos, char precedingChar)112 protected boolean addLeadingSpace(boolean gotSeparateLine, int pos, 113 char precedingChar) { 114 if (precedingChar == '.' && getBaseType().getName().isEmpty()) { 115 // If only the annotation is being inserted then don't insert a 116 // space if it's immediately after a '.' 117 return false; 118 } 119 return super.addLeadingSpace(gotSeparateLine, pos, precedingChar); 120 } 121 122 /** {@inheritDoc} */ 123 @Override addTrailingSpace(boolean gotSeparateLine)124 protected boolean addTrailingSpace(boolean gotSeparateLine) { 125 // If the type is not already in the source and the receiver is the only 126 // parameter, don't add a trailing space. 127 if (!getBaseType().getName().isEmpty() && !addComma) { 128 return false; 129 } 130 return super.addTrailingSpace(gotSeparateLine); 131 } 132 133 /** {@inheritDoc} */ 134 @Override getKind()135 public Kind getKind() { 136 return Kind.RECEIVER; 137 } 138 } 139