package annotator.find; import java.util.List; import type.DeclaredType; /** * An insertion for a method receiver. This supports inserting an * annotation on an existing receiver and creating a new (annotated) * receiver if none are present. */ public class ReceiverInsertion extends TypedInsertion { /** * If true a comma will be added at the end of the insertion (only if also * inserting the receiver). */ private boolean addComma; /** * If true, {@code this} will be qualified with the name of the * superclass. */ private boolean qualifyThis; /** * Construct a ReceiverInsertion. * <p> * If the receiver parameter already exists in the method declaration, then * pass a DeclaredType thats name is the empty String. This will only insert * an annotation on the existing receiver. * <p> * To insert the annotation and the receiver (for example, * {@code @Anno Type this}) the name should be set to the type to insert. * This can either be done before calling this constructor, or by modifying * the return value of {@link #getType()}. * <p> * A comma will not be added to the end of the receiver. In the case that * there is a parameter following the inserted receiver pass {@code true} to * {@link #setAddComma(boolean)} to add a comma to the end of the receiver. * * @param type the type to use when inserting the receiver * @param criteria where to insert the text * @param innerTypeInsertions the inner types to go on this receiver */ public ReceiverInsertion(DeclaredType type, Criteria criteria, List<Insertion> innerTypeInsertions) { super(type, criteria, innerTypeInsertions); addComma = false; qualifyThis = false; } /** * If {@code true} a comma will be added at the end of the receiver. * This will only happen if a receiver is inserted (see * {@link #ReceiverInsertion(DeclaredType, Criteria, List)} for a description of * when a receiver is inserted). This is useful if the method already has * one or more parameters. */ public void setAddComma(boolean addComma) { this.addComma = addComma; } /** * If {@code true}, qualify {@code this} with the name of the superclass. * This will only happen if a receiver is inserted (see * {@link #ReceiverInsertion(DeclaredType, Criteria, List)} * for a description of when a receiver is inserted). This is useful * for inner class constructors. */ public void setQualifyType(boolean qualifyThis) { this.qualifyThis = qualifyThis; } /** {@inheritDoc} */ @Override protected String getText(boolean comments, boolean abbreviate) { if (annotationsOnly) { StringBuilder b = new StringBuilder(); List<String> annotations = type.getAnnotations(); if (annotations.isEmpty()) { return ""; } for (String a : annotations) { b.append(a); b.append(' '); } return new AnnotationInsertion(b.toString(), getCriteria(), getSeparateLine()).getText(comments, abbreviate); } else { DeclaredType baseType = getBaseType(); boolean commentAnnotation = (comments && baseType.getName().isEmpty()); String result = typeToString(type, commentAnnotation, abbreviate); if (!baseType.getName().isEmpty()) { result += " "; if (qualifyThis) { for (DeclaredType t = baseType; t != null; t = t.getInnerType()) { result += t.getName() + "."; } } result += "this"; if (addComma) { result += ","; } if (comments) { result = "/*>>> " + result + " */"; } } return result; } } /** {@inheritDoc} */ @Override protected boolean addLeadingSpace(boolean gotSeparateLine, int pos, char precedingChar) { if (precedingChar == '.' && getBaseType().getName().isEmpty()) { // If only the annotation is being inserted then don't insert a // space if it's immediately after a '.' return false; } return super.addLeadingSpace(gotSeparateLine, pos, precedingChar); } /** {@inheritDoc} */ @Override protected boolean addTrailingSpace(boolean gotSeparateLine) { // If the type is not already in the source and the receiver is the only // parameter, don't add a trailing space. if (!getBaseType().getName().isEmpty() && !addComma) { return false; } return super.addTrailingSpace(gotSeparateLine); } /** {@inheritDoc} */ @Override public Kind getKind() { return Kind.RECEIVER; } }