smaller methods

This commit is contained in:
Loredana Crusoveanu 2017-11-12 22:31:39 +02:00
parent b383d83bf4
commit 8e50444ba6
1 changed files with 56 additions and 57 deletions

View File

@ -26,10 +26,9 @@ public class SampleJavacPlugin implements Plugin {
public static final String NAME = "MyPlugin"; public static final String NAME = "MyPlugin";
private static Set<String> TARGET_TYPES = new HashSet<>(Arrays.asList( private static Set<String> TARGET_TYPES = new HashSet<>(Arrays.asList(
// Use only primitive types for simplicity // Use only primitive types for simplicity
byte.class.getName(), short.class.getName(), char.class.getName(), int.class.getName(), byte.class.getName(), short.class.getName(), char.class.getName(),
long.class.getName(), float.class.getName(), double.class.getName() int.class.getName(), long.class.getName(), float.class.getName(), double.class.getName()));
));
@Override @Override
public String getName() { public String getName() {
@ -49,34 +48,35 @@ public class SampleJavacPlugin implements Plugin {
if (e.getKind() != TaskEvent.Kind.PARSE) { if (e.getKind() != TaskEvent.Kind.PARSE) {
return; return;
} }
e.getCompilationUnit().accept(new TreeScanner<Void, Void>() { e.getCompilationUnit()
@Override .accept(new TreeScanner<Void, Void>() {
public Void visitMethod(MethodTree method, Void v) { @Override
List<VariableTree> parametersToInstrument = method.getParameters() public Void visitMethod(MethodTree method, Void v) {
.stream() List<VariableTree> parametersToInstrument = method.getParameters()
.filter(SampleJavacPlugin.this::shouldInstrument) .stream()
.collect(Collectors.toList()); .filter(SampleJavacPlugin.this::shouldInstrument)
if (!parametersToInstrument.isEmpty()) { .collect(Collectors.toList());
// There is a possible case that more than one argument is marked by @Positive, if (!parametersToInstrument.isEmpty()) {
// as the checks are added to the method's body beginning, we process parameters RTL // There is a possible case that more than one argument is marked by @Positive,
// to ensure correct order. // as the checks are added to the method's body beginning, we process parameters RTL
Collections.reverse(parametersToInstrument); // to ensure correct order.
parametersToInstrument.forEach(p -> addCheck(method, p, context)); Collections.reverse(parametersToInstrument);
parametersToInstrument.forEach(p -> addCheck(method, p, context));
}
// There is a possible case that there is a nested class declared in a method's body,
// hence, we want to proceed with method body AST as well.
return super.visitMethod(method, v);
} }
// There is a possible case that there is a nested class declared in a method's body, }, null);
// hence, we want to proceed with method body AST as well.
return super.visitMethod(method, v);
}
}, null);
} }
}); });
} }
private boolean shouldInstrument(VariableTree parameter) { private boolean shouldInstrument(VariableTree parameter) {
return TARGET_TYPES.contains(parameter.getType().toString()) return TARGET_TYPES.contains(parameter.getType().toString())
&& parameter.getModifiers().getAnnotations() && parameter.getModifiers().getAnnotations()
.stream() .stream()
.anyMatch(a -> Positive.class.getSimpleName().equals(a.getAnnotationType().toString())); .anyMatch(a -> Positive.class.getSimpleName().equals(a.getAnnotationType().toString()));
} }
private void addCheck(MethodTree method, VariableTree parameter, Context context) { private void addCheck(MethodTree method, VariableTree parameter, Context context) {
@ -88,37 +88,36 @@ public class SampleJavacPlugin implements Plugin {
private static JCTree.JCIf createCheck(VariableTree parameter, Context context) { private static JCTree.JCIf createCheck(VariableTree parameter, Context context) {
TreeMaker factory = TreeMaker.instance(context); TreeMaker factory = TreeMaker.instance(context);
Names symbolsTable = Names.instance(context); Names symbolsTable = Names.instance(context);
String parameterName = parameter.getName().toString();
String errorMessagePrefix = String.format("Argument '%s' of type %s is marked by @%s but got '", return factory.at(((JCTree) parameter).pos)
parameterName, parameter.getType(), Positive.class.getSimpleName()); .If(factory.Parens(createIfCondition(factory, symbolsTable, parameter)),
String errorMessageSuffix = "' for it"; createIfBlock(factory, symbolsTable, parameter),
Name parameterId = symbolsTable.fromString(parameterName); null);
return factory.at(((JCTree) parameter).pos).If(
factory.Parens(
factory.Binary(
JCTree.Tag.LE,
factory.Ident(parameterId),
factory.Literal(TypeTag.INT, 0))
),
factory.Block(0, com.sun.tools.javac.util.List.of(
factory.Throw(
factory.NewClass(
null,
nil(),
factory.Ident(
symbolsTable.fromString(IllegalArgumentException.class.getSimpleName())
),
com.sun.tools.javac.util.List.of(
factory.Binary(JCTree.Tag.PLUS,
factory.Binary(JCTree.Tag.PLUS,
factory.Literal(TypeTag.CLASS, errorMessagePrefix),
factory.Ident(parameterId)),
factory.Literal(TypeTag.CLASS, errorMessageSuffix))),
null
)
)
)),
null
);
} }
private static JCTree.JCBinary createIfCondition(TreeMaker factory, Names symbolsTable, VariableTree parameter) {
Name parameterId = symbolsTable.fromString(parameter.getName().toString());
return factory.Binary(JCTree.Tag.LE,
factory.Ident(parameterId),
factory.Literal(TypeTag.INT, 0));
}
private static JCTree.JCBlock createIfBlock(TreeMaker factory, Names symbolsTable, VariableTree parameter) {
String parameterName = parameter.getName().toString();
Name parameterId = symbolsTable.fromString(parameterName);
String errorMessagePrefix = String.format("Argument '%s' of type %s is marked by @%s but got '",
parameterName, parameter.getType(), Positive.class.getSimpleName());
String errorMessageSuffix = "' for it";
return factory.Block(0, com.sun.tools.javac.util.List.of(
factory.Throw(
factory.NewClass(null, nil(),
factory.Ident(symbolsTable.fromString(IllegalArgumentException.class.getSimpleName())),
com.sun.tools.javac.util.List.of(factory.Binary(JCTree.Tag.PLUS,
factory.Binary(JCTree.Tag.PLUS, factory.Literal(TypeTag.CLASS, errorMessagePrefix),
factory.Ident(parameterId)),
factory.Literal(TypeTag.CLASS, errorMessageSuffix))), null))));
}
} }