Skip to content

Commit 39ab435

Browse files
author
Andriy Onyshchuk
committed
introduce adt methods
1 parent 7a91307 commit 39ab435

15 files changed

Lines changed: 647 additions & 110 deletions

File tree

dataenum-processor/src/main/java/com/spotify/dataenum/processor/DataEnumProcessor.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,24 @@
3333
import com.squareup.javapoet.ArrayTypeName;
3434
import com.squareup.javapoet.JavaFile;
3535
import com.squareup.javapoet.TypeSpec;
36+
import com.sun.source.util.Trees;
3637
import java.io.IOException;
3738
import java.util.Collections;
3839
import java.util.Set;
39-
import javax.annotation.processing.AbstractProcessor;
40-
import javax.annotation.processing.Filer;
41-
import javax.annotation.processing.Messager;
42-
import javax.annotation.processing.RoundEnvironment;
40+
import javax.annotation.processing.*;
4341
import javax.lang.model.SourceVersion;
4442
import javax.lang.model.element.Element;
4543
import javax.lang.model.element.TypeElement;
4644
import javax.tools.Diagnostic;
4745

4846
public class DataEnumProcessor extends AbstractProcessor {
47+
private Trees trees;
48+
49+
@Override
50+
public synchronized void init(ProcessingEnvironment processingEnv) {
51+
super.init(processingEnv);
52+
this.trees = Trees.instance(processingEnv);
53+
}
4954

5055
@Override
5156
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
@@ -58,7 +63,7 @@ public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnv
5863
for (Element element : roundEnvironment.getElementsAnnotatedWith(DataEnum.class)) {
5964
try {
6065

61-
Spec spec = SpecParser.parse(element, processingEnv);
66+
Spec spec = SpecParser.parse(element, new ProcessingContext(processingEnv));
6267
if (spec == null) {
6368
continue;
6469
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.spotify.dataenum.processor;
2+
3+
import com.spotify.dataenum.dataenum_case;
4+
import com.sun.source.util.Trees;
5+
import javax.annotation.processing.ProcessingEnvironment;
6+
import javax.lang.model.type.TypeMirror;
7+
import javax.lang.model.util.Elements;
8+
import javax.lang.model.util.Types;
9+
10+
public final class ProcessingContext {
11+
public final ProcessingEnvironment env;
12+
public final Trees trees;
13+
public final TypeMirror dataenum_class_element;
14+
15+
public ProcessingContext(ProcessingEnvironment env) {
16+
this.env = env;
17+
this.trees = Trees.instance(env);
18+
19+
Types types = env.getTypeUtils();
20+
Elements elements = env.getElementUtils();
21+
this.dataenum_class_element =
22+
elements.getTypeElement(dataenum_case.class.getCanonicalName()).asType();
23+
}
24+
}

dataenum-processor/src/main/java/com/spotify/dataenum/processor/data/OutputSpec.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public class OutputSpec extends Spec {
3131
private final Iterable<OutputValue> outputValues;
3232

3333
public OutputSpec(Spec input, ClassName outputClass, Iterable<OutputValue> outputValues) {
34-
super(input.specClass(), input.typeVariables(), input.values());
34+
super(input.specClass(), input.typeVariables(), input.values(), input.methods());
3535
this.outputClass = outputClass;
3636
this.outputValues = outputValues;
3737
}

dataenum-processor/src/main/java/com/spotify/dataenum/processor/data/Spec.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import com.spotify.dataenum.processor.util.Iterables;
2323
import com.squareup.javapoet.ClassName;
24+
import com.squareup.javapoet.MethodSpec;
2425
import com.squareup.javapoet.TypeVariableName;
2526

2627
/**
@@ -33,12 +34,17 @@ public class Spec {
3334
private final ClassName specClass;
3435
private final Iterable<TypeVariableName> typeVariables;
3536
private final Iterable<Value> values;
37+
private final Iterable<MethodSpec> methods;
3638

3739
public Spec(
38-
ClassName specClass, Iterable<TypeVariableName> typeVariables, Iterable<Value> values) {
40+
ClassName specClass,
41+
Iterable<TypeVariableName> typeVariables,
42+
Iterable<Value> values,
43+
Iterable<MethodSpec> methods) {
3944
this.specClass = specClass;
4045
this.typeVariables = typeVariables;
4146
this.values = values;
47+
this.methods = methods;
4248
}
4349

4450
public ClassName specClass() {
@@ -56,4 +62,8 @@ public boolean hasTypeVariables() {
5662
public Iterable<Value> values() {
5763
return values;
5864
}
65+
66+
public Iterable<MethodSpec> methods() {
67+
return methods;
68+
}
5969
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package com.spotify.dataenum.processor.generator.method;
2+
3+
import com.squareup.javapoet.*;
4+
import com.sun.source.tree.MethodTree;
5+
import com.sun.source.util.TreePathScanner;
6+
import com.sun.source.util.Trees;
7+
import java.util.concurrent.atomic.AtomicReference;
8+
import java.util.function.Consumer;
9+
import java.util.function.Function;
10+
import java.util.stream.Collectors;
11+
import java.util.stream.Stream;
12+
import javax.lang.model.element.AnnotationMirror;
13+
import javax.lang.model.element.ElementKind;
14+
import javax.lang.model.element.ExecutableElement;
15+
import javax.lang.model.element.Modifier;
16+
17+
public final class MethodMethods {
18+
private MethodMethods() {}
19+
20+
public static MethodSpec.Builder builderFrom(
21+
ExecutableElement el,
22+
Function<Stream<Modifier>, Stream<Modifier>> adjustModifiers,
23+
Function<Stream<? extends AnnotationMirror>, Stream<? extends AnnotationMirror>>
24+
adjustAnnotations) {
25+
return MethodSpec.methodBuilder(el.getSimpleName().toString())
26+
.addModifiers(adjustModifiers.apply(el.getModifiers().stream()).collect(Collectors.toSet()))
27+
.addAnnotations(
28+
adjustAnnotations
29+
.apply(el.getAnnotationMirrors().stream())
30+
.map(AnnotationSpec::get)
31+
.collect(Collectors.toList()))
32+
.addTypeVariables(
33+
el.getTypeParameters().stream().map(TypeVariableName::get).collect(Collectors.toList()))
34+
.returns(TypeName.get(el.getReturnType()))
35+
.addParameters(
36+
el.getParameters().stream().map(ParameterSpec::get).collect(Collectors.toList()))
37+
.varargs(el.isVarArgs())
38+
.addExceptions(
39+
el.getThrownTypes().stream().map(TypeName::get).collect(Collectors.toList()));
40+
}
41+
42+
public static CodeBlock codeBlockFrom(ExecutableElement el, Trees trees) {
43+
final MethodTree methodTree = MethodLookup.lookupTree(el, trees);
44+
return methodTree
45+
.getBody()
46+
.getStatements()
47+
.stream()
48+
.map(x -> CodeBlock.of(x.toString()))
49+
.reduce(CodeBlock.of(""), (a, b) -> a.toBuilder().add(b).build());
50+
}
51+
52+
private static class MethodLookup extends TreePathScanner<Void, Void> {
53+
54+
private final Consumer<MethodTree> onMethod;
55+
56+
private MethodLookup(Consumer<MethodTree> onMethod) {
57+
this.onMethod = onMethod;
58+
}
59+
60+
public static MethodTree lookupTree(ExecutableElement methodElement, Trees trees) {
61+
assert methodElement.getKind() == ElementKind.METHOD;
62+
63+
AtomicReference<MethodTree> methodRef = new AtomicReference<>();
64+
new MethodLookup(methodRef::set).scan(trees.getPath(methodElement), null);
65+
MethodTree method = methodRef.get();
66+
assert method != null;
67+
68+
return method;
69+
}
70+
71+
@Override
72+
public Void visitMethod(MethodTree methodTree, Void v) {
73+
this.onMethod.accept(methodTree);
74+
return super.visitMethod(methodTree, v);
75+
}
76+
}
77+
}

dataenum-processor/src/main/java/com/spotify/dataenum/processor/generator/spec/SpecTypeFactory.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ public static TypeSpec create(
9595
enumBuilder.addMethod(mapMethods.createAbstractFoldMethod());
9696
}
9797

98+
enumBuilder.addMethods(spec.methods());
99+
98100
return enumBuilder.build();
99101
}
100102
}

0 commit comments

Comments
 (0)