/**
* Copyright (C) 2006-2017 INRIA and contributors
* Spoon - http://spoon.gforge.inria.fr/
*
* This software is governed by the CeCILL-C License under French law and
* abiding by the rules of distribution of free software. You can use, modify
* and/or redistribute the software under the terms of the CeCILL-C license as
* circulated by CEA, CNRS and INRIA at http://www.cecill.info.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-C license and that you accept its terms.
*/
package spoon.support.visitor;
import spoon.reflect.declaration.CtAnnotationMethod;
import spoon.reflect.declaration.CtConstructor;
import spoon.reflect.declaration.CtExecutable;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtParameter;
import spoon.reflect.declaration.CtTypeParameter;
import spoon.reflect.reference.CtArrayTypeReference;
import spoon.reflect.reference.CtExecutableReference;
import spoon.reflect.reference.CtIntersectionTypeReference;
import spoon.reflect.reference.CtTypeParameterReference;
import spoon.reflect.reference.CtTypeReference;
import spoon.reflect.visitor.CtScanner;
/**
* Responsible for computing signatures for elements where a signature exists
* (CtType, CtMethod and CtPackage). Otherwise returns the empty string.
*
*/
public class SignaturePrinter extends CtScanner {
private final StringBuffer signature = new StringBuffer();
public String getSignature() {
return signature.toString();
}
@Override
public <T> void visitCtArrayTypeReference(CtArrayTypeReference<T> reference) {
scan(reference.getComponentType());
write("[]");
}
@Override
public <T> void visitCtExecutableReference(CtExecutableReference<T> reference) {
scan(reference.getDeclaringType());
write(CtExecutable.EXECUTABLE_SEPARATOR);
if (reference.isConstructor()) {
write(reference.getDeclaringType().getSimpleName());
} else {
write(reference.getSimpleName());
}
write("(");
if (reference.getParameters().size() > 0) {
for (CtTypeReference<?> param : reference.getParameters()) {
if (param != null && !"null".equals(param.getSimpleName())) {
scan(param);
} else {
write(CtExecutableReference.UNKNOWN_TYPE);
}
write(", ");
}
if (reference.getParameters().size() > 0) {
clearLast(); // ","
clearLast(); // space
}
}
write(")");
}
@Override
public <T> void visitCtTypeReference(CtTypeReference<T> reference) {
write(reference.getQualifiedName());
}
@Override
public void visitCtTypeParameterReference(CtTypeParameterReference ref) {
write(ref.getQualifiedName());
if (ref.getBoundingType() != null) {
if (ref.isUpper()) {
write(" extends ");
} else {
write(" super ");
}
scan(ref.getBoundingType());
}
}
@Override
public <T> void visitCtIntersectionTypeReference(CtIntersectionTypeReference<T> reference) {
for (CtTypeReference<?> bound : reference.getBounds()) {
scan(bound);
write(", ");
}
clearLast();
clearLast();
}
@Override
public <T> void visitCtConstructor(CtConstructor<T> c) {
if (c.getDeclaringType() != null) {
write(c.getDeclaringType().getQualifiedName());
}
write("(");
for (CtParameter<?> p : c.getParameters()) {
scan(p.getType());
write(",");
}
if (c.getParameters().size() > 0) {
clearLast();
}
write(")");
}
@Override
public <T> void visitCtAnnotationMethod(CtAnnotationMethod<T> annotationMethod) {
visitCtMethod(annotationMethod);
}
/**
* For methods, this implementation of signature contains the return type, which corresponds
* to what the Java compile and virtual machine call a "descriptor".
*
* See chapter "8.4.2 Method Signature" of the Java specification
*/
@Override
public <T> void visitCtMethod(CtMethod<T> m) {
if (!m.getFormalCtTypeParameters().isEmpty()) {
write("<");
for (CtTypeParameter typeParameter : m.getFormalCtTypeParameters()) {
scan(typeParameter.getReference());
write(",");
}
if (m.getFormalCtTypeParameters().size() > 0) {
clearLast();
}
write("> ");
}
// the return type is required, see example in SimilarSignatureMethodes in test code (name and arguments are identical)
if (m.getType() != null) {
write(m.getType().getQualifiedName());
}
write(" ");
write(m.getSimpleName());
write("(");
for (CtParameter<?> p : m.getParameters()) {
scan(p.getType());
write(",");
}
if (!m.getParameters().isEmpty()) {
clearLast();
}
write(")");
}
private SignaturePrinter clearLast() {
signature.deleteCharAt(signature.length() - 1);
return this;
}
protected SignaturePrinter write(String value) {
signature.append(value);
return this;
}
}