package annotator.find;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import type.DeclaredType;
import type.Type;
/**
* @author dbro
*
*/
public class NewInsertion extends TypedInsertion {
private final static Pattern qualifiers = Pattern.compile("(?:\\w++\\.)*+");
/**
* If true, the type will be qualified with the name of the superclass.
*/
protected boolean qualifyType;
/**
* Construct a NewInsertion.
* <p>
* If "new" already exists in the initializer, then pass a
* {@link DeclaredType} thats name is the empty String. This will only
* insert an annotation on the existing type.
* <p>
* To insert the annotation along with "new" and the type (for example,
* {@code @Anno new Type[] \{...\}}), set the name to the type to insert.
* This can be done either before calling this constructor, or by modifying
* the return value of {@link #getType()}.
*
* @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 NewInsertion(Type type, Criteria criteria,
List<Insertion> innerTypeInsertions) {
super(type, criteria, innerTypeInsertions);
annotationsOnly = false;
qualifyType = false;
}
/** {@inheritDoc} */
@Override
protected String getText(boolean comments, boolean abbreviate) {
if (annotationsOnly || type.getKind() != Type.Kind.ARRAY) {
StringBuilder b = new StringBuilder();
List<String> annotations = type.getAnnotations();
if (annotations.isEmpty()) { return ""; }
for (String a : annotations) {
b.append(' ').append(a); // initial space removed below
}
return new AnnotationInsertion(b.substring(1), 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()) {
// First, temporarily strip off any qualifiers.
Matcher matcher = qualifiers.matcher(result);
String prefix = "";
if (matcher.find() && matcher.start() == 0) {
prefix = result.substring(0, matcher.end());
result = result.substring(matcher.end());
}
// If the variable name preceded the array brackets in the
// source, extract it from the result.
if (qualifyType) {
for (DeclaredType t = baseType; t != null; t = t.getInnerType()) {
result += t.getName() + ".";
}
}
// Finally, prepend extracted qualifiers.
result = prefix + result;
}
result = "new " + result;
if (comments) {
result = "/*>>> " + result + " */";
}
return result;
}
}
/**
* If {@code true}, qualify {@code type} with the name of the superclass.
* This will only happen if a "new" is inserted.
*/
public void setQualifyType(boolean qualifyType) {
this.qualifyType = qualifyType;
}
/** {@inheritDoc} */
@Override
protected boolean addLeadingSpace(boolean gotSeparateLine, int pos,
char precedingChar) {
if ((precedingChar == '.' || precedingChar == '(')
&& getBaseType().getName().isEmpty()) {
// If only the annotation is being inserted then don't insert a
// space if it's immediately after a '.' or '('
return false;
}
return super.addLeadingSpace(gotSeparateLine, pos, precedingChar);
}
/** {@inheritDoc} */
@Override
protected boolean addTrailingSpace(boolean gotSeparateLine) {
return true;
}
/** {@inheritDoc} */
@Override
public Kind getKind() {
return Kind.NEW;
}
}