Skip to content

Commit

Permalink
Give generated code meaningful parameter names (#2970)
Browse files Browse the repository at this point in the history
* Give generated code meaningful parameter names

Signed-off-by: Alex Saveau <[email protected]>
  • Loading branch information
SUPERCILEX authored and sjudd committed Mar 30, 2018
1 parent 5212e95 commit 58bcf53
Show file tree
Hide file tree
Showing 40 changed files with 3,193 additions and 3,068 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.MethodSpec.Builder;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeSpec;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -16,7 +17,6 @@
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.Elements;

/**
Expand Down Expand Up @@ -138,7 +138,7 @@ public MethodSpec apply(ExecutableElement input) {
}

private MethodSpec overrideGlideStaticMethod(ExecutableElement methodToOverride) {
List<? extends VariableElement> parameters = methodToOverride.getParameters();
List<ParameterSpec> parameters = ProcessorUtil.getParameters(methodToOverride);

TypeElement element =
(TypeElement) processingEnv.getTypeUtils().asElement(methodToOverride.getReturnType());
Expand All @@ -147,7 +147,7 @@ private MethodSpec overrideGlideStaticMethod(ExecutableElement methodToOverride)
MethodSpec.methodBuilder(methodToOverride.getSimpleName().toString())
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.addJavadoc(processorUtil.generateSeeMethodJavadoc(methodToOverride))
.addParameters(ProcessorUtil.getParameters(methodToOverride));
.addParameters(parameters);

addReturnAnnotations(builder, methodToOverride);

Expand All @@ -162,9 +162,9 @@ private MethodSpec overrideGlideStaticMethod(ExecutableElement methodToOverride)
args.add(ClassName.get(glideType));
args.add(methodToOverride.getSimpleName());
if (!parameters.isEmpty()) {
for (VariableElement param : parameters) {
for (ParameterSpec param : parameters) {
code.append("$L, ");
args.add(param.getSimpleName());
args.add(param.name);
}
code = new StringBuilder(code.substring(0, code.length() - 2));
}
Expand Down Expand Up @@ -210,20 +210,20 @@ private MethodSpec overrideGlideWithMethod(
String packageName, TypeSpec generatedRequestManager, ExecutableElement methodToOverride) {
ClassName generatedRequestManagerClassName =
ClassName.get(packageName, generatedRequestManager.name);
List<? extends VariableElement> parameters = methodToOverride.getParameters();
List<ParameterSpec> parameters = ProcessorUtil.getParameters(methodToOverride);
Preconditions.checkArgument(
parameters.size() == 1, "Expected size of 1, but got %s", methodToOverride);
VariableElement parameter = parameters.iterator().next();
ParameterSpec parameter = parameters.iterator().next();

Builder builder = MethodSpec.methodBuilder(methodToOverride.getSimpleName().toString())
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.addJavadoc(processorUtil.generateSeeMethodJavadoc(methodToOverride))
.addParameters(ProcessorUtil.getParameters(methodToOverride))
.addParameters(parameters)
.returns(generatedRequestManagerClassName)
.addStatement("return ($T) $T.$N($L)",
generatedRequestManagerClassName, glideType,
methodToOverride.getSimpleName().toString(),
parameter.getSimpleName());
parameter.name);

return addReturnAnnotations(builder, methodToOverride).build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,15 +256,15 @@ void warnLog(String toLog) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, toLog);
}

static CodeBlock generateCastingSuperCall(TypeName toReturn, ExecutableElement method) {
static CodeBlock generateCastingSuperCall(TypeName toReturn, MethodSpec method) {
return CodeBlock.builder()
.add("return ($T) super.$N(", toReturn, method.getSimpleName())
.add("return ($T) super.$N(", toReturn, method.name)
.add(
FluentIterable.from(method.getParameters())
.transform(new Function<VariableElement, String>() {
FluentIterable.from(method.parameters)
.transform(new Function<ParameterSpec, String>() {
@Override
public String apply(VariableElement input) {
return input.getSimpleName().toString();
public String apply(ParameterSpec input) {
return input.name;
}
})
.join(Joiner.on(",")))
Expand Down Expand Up @@ -317,18 +317,119 @@ static List<ParameterSpec> getParameters(List<? extends VariableElement> paramet
for (VariableElement parameter : parameters) {
result.add(getParameter(parameter));
}
return result;
return dedupedParameters(result);
}

private static List<ParameterSpec> dedupedParameters(List<ParameterSpec> parameters) {
boolean hasDupes = false;
Set<String> names = new HashSet<>();
for (ParameterSpec parameter : parameters) {
String name = parameter.name;
if (names.contains(name)) {
hasDupes = true;
} else {
names.add(name);
}
}

if (hasDupes) {
List<ParameterSpec> copy = parameters;
parameters = new ArrayList<>();
for (int i = 0; i < copy.size(); i++) {
ParameterSpec parameter = copy.get(i);
parameters.add(ParameterSpec.builder(parameter.type, parameter.name + i)
.addModifiers(parameter.modifiers)
.addAnnotations(parameter.annotations)
.build());
}
}

return parameters;
}

private static ParameterSpec getParameter(VariableElement method) {
TypeName type = TypeName.get(method.asType());
String name = method.getSimpleName().toString();
return ParameterSpec.builder(type, name)
.addModifiers(method.getModifiers())
.addAnnotations(getAnnotations(method))
private static ParameterSpec getParameter(VariableElement parameter) {
TypeName type = TypeName.get(parameter.asType());
return ParameterSpec.builder(type, computeParameterName(parameter, type))
.addModifiers(parameter.getModifiers())
.addAnnotations(getAnnotations(parameter))
.build();
}

private static String computeParameterName(VariableElement parameter, TypeName type) {
String rawClassName = type.withoutAnnotations().toString();

String name;

if (type.isPrimitive() || type.isBoxedPrimitive()) {
name = getSmartPrimitiveParameterName(parameter);
} else {
if (rawClassName.contains("<") && rawClassName.contains(">")) {
String[] preGenericSplit = rawClassName.split("<");
String preGeneric = preGenericSplit[0];
String[] postGenericSplit = rawClassName.split(">");
String postGeneric = postGenericSplit[postGenericSplit.length - 1];
if (postGenericSplit.length > 1) {
rawClassName = preGeneric + postGeneric;
} else {
rawClassName = preGeneric;
}
}

String[] qualifiers = rawClassName.split("\\.");
rawClassName = qualifiers[qualifiers.length - 1];

rawClassName = applySmartParameterNameReplacements(rawClassName);

boolean allCaps = true;
for (char c : rawClassName.toCharArray()) {
if (Character.isLowerCase(c)) {
allCaps = false;
break;
}
}
if (allCaps) {
name = rawClassName.toLowerCase();
} else {
int indexOfLastWordStart = 0;
char[] chars = rawClassName.toCharArray();
for (int i = 0, charArrayLength = chars.length; i < charArrayLength; i++) {
char c = chars[i];
if (Character.isUpperCase(c)) {
indexOfLastWordStart = i;
}
}
rawClassName = rawClassName.substring(indexOfLastWordStart, rawClassName.length());

name = Character.toLowerCase(rawClassName.charAt(0))
+ rawClassName.substring(1, rawClassName.length());
}
}

return name;
}

private static String getSmartPrimitiveParameterName(VariableElement parameter) {
for (AnnotationMirror annotation : parameter.getAnnotationMirrors()) {
String annotationName = annotation.getAnnotationType().toString().toUpperCase();
if (annotationName.endsWith("RES")) {
// Catch annotations like StringRes
return "id";
} else if (annotationName.endsWith("RANGE")) {
// Catch annotations like IntRange
return "value";
}
}

return parameter.getSimpleName().toString();
}

private static String applySmartParameterNameReplacements(String name) {
name = name.replace("[]", "s");
name = name.replace(Class.class.getSimpleName(), "clazz");
name = name.replace(Object.class.getSimpleName(), "o");
return name;
}

private static List<AnnotationSpec> getAnnotations(VariableElement element) {
List<AnnotationSpec> result = new ArrayList<>();
for (AnnotationMirror mirror : element.getAnnotationMirrors()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;

Expand Down Expand Up @@ -214,20 +213,20 @@ private MethodSpec generateRequestBuilderOverride(ExecutableElement methodToOver
ParameterizedTypeName.get(generatedRequestBuilderClassName, ClassName.get(typeArgument));

MethodSpec.Builder builder = ProcessorUtil.overriding(methodToOverride)
.returns(generatedRequestBuilderOfType)
.addCode(CodeBlock.builder()
.add("return ($T) super.$N(",
generatedRequestBuilderOfType, methodToOverride.getSimpleName())
.add(FluentIterable.from(methodToOverride.getParameters())
.transform(new Function<VariableElement, String>() {
@Override
public String apply(VariableElement input) {
return input.getSimpleName().toString();
}
})
.join(Joiner.on(", ")))
.add(");\n")
.build());
.returns(generatedRequestBuilderOfType);
builder.addCode(CodeBlock.builder()
.add("return ($T) super.$N(",
generatedRequestBuilderOfType, methodToOverride.getSimpleName())
.add(FluentIterable.from(builder.build().parameters)
.transform(new Function<ParameterSpec, String>() {
@Override
public String apply(ParameterSpec input) {
return input.name;
}
})
.join(Joiner.on(", ")))
.add(");\n")
.build());

for (AnnotationMirror mirror : methodToOverride.getAnnotationMirrors()) {
builder = builder.addAnnotation(AnnotationSpec.get(mirror));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.MethodSpec.Builder;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeSpec;
Expand Down Expand Up @@ -192,10 +193,12 @@ private MethodSpec generateRequestManagerRequestManagerMethodOverride(
String generatedPackageName, ExecutableElement method) {
ClassName generatedRequestManagerName =
ClassName.get(generatedPackageName, GENERATED_REQUEST_MANAGER_SIMPLE_NAME);
return ProcessorUtil.overriding(method)
Builder returns = ProcessorUtil.overriding(method)
.addAnnotation(nonNull())
.returns(generatedRequestManagerName)
.addCode(ProcessorUtil.generateCastingSuperCall(generatedRequestManagerName, method))
.returns(generatedRequestManagerName);
return returns
.addCode(ProcessorUtil.generateCastingSuperCall(
generatedRequestManagerName, returns.build()))
.build();
}

Expand Down Expand Up @@ -240,10 +243,9 @@ private MethodSpec generateRequestManagerRequestBuilderMethodOverride(
ParameterizedTypeName.get(generatedRequestBuilderClassName, ClassName.get(typeArgument));

MethodSpec.Builder builder = ProcessorUtil.overriding(methodToOverride)
.returns(generatedRequestBuilderOfType)
.addCode(
ProcessorUtil.generateCastingSuperCall(
generatedRequestBuilderOfType, methodToOverride));
.returns(generatedRequestBuilderOfType);
builder.addCode(
ProcessorUtil.generateCastingSuperCall(generatedRequestBuilderOfType, builder.build()));

for (AnnotationMirror mirror : methodToOverride.getAnnotationMirrors()) {
builder.addAnnotation(AnnotationSpec.get(mirror));
Expand Down
Loading

0 comments on commit 58bcf53

Please sign in to comment.