aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/zwobble/couscous/transforms/SplitStaticsFromInterface.java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2016-08-29 17:13:03 +0100
committerMichael Williamson <mike@zwobble.org>2016-08-29 17:13:03 +0100
commita82ecb60d6ee7ee46e5800088f1769f86872077b (patch)
tree8b3c5442a1bd047606de63477839755e88dab2f5 /src/main/java/org/zwobble/couscous/transforms/SplitStaticsFromInterface.java
parent1babfdf8daa45ffef3d624db6c717f846d295440 (diff)
Initial support for static methods/fields on interfaces
Diffstat (limited to 'src/main/java/org/zwobble/couscous/transforms/SplitStaticsFromInterface.java')
-rw-r--r--src/main/java/org/zwobble/couscous/transforms/SplitStaticsFromInterface.java68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/main/java/org/zwobble/couscous/transforms/SplitStaticsFromInterface.java b/src/main/java/org/zwobble/couscous/transforms/SplitStaticsFromInterface.java
new file mode 100644
index 0000000..b2c88ea
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/transforms/SplitStaticsFromInterface.java
@@ -0,0 +1,68 @@
+package org.zwobble.couscous.transforms;
+
+import com.google.common.collect.Iterables;
+import org.zwobble.couscous.ast.*;
+import org.zwobble.couscous.ast.visitors.NodeTransformer;
+import org.zwobble.couscous.types.ScalarType;
+
+import java.util.*;
+
+import static org.zwobble.couscous.util.ExtraLists.eagerFilter;
+import static org.zwobble.couscous.util.ExtraLists.list;
+import static org.zwobble.couscous.util.ExtraSets.set;
+
+public class SplitStaticsFromInterface {
+ public static List<TypeNode> transform(List<TypeNode> typeNodes) {
+ List<TypeNode> result = new ArrayList<>();
+ Set<ScalarType> splitInterfaces = new HashSet<>();
+
+ for (TypeNode typeNode : typeNodes) {
+ if (isSplittable(typeNode)) {
+ splitInterfaces.add(typeNode.getName());
+ InterfaceNode interfaceNode = (InterfaceNode) typeNode;
+ result.add(ClassNode.declareClass(
+ staticTypeFor(interfaceNode.getName()),
+ list(),
+ set(),
+ interfaceNode.getFields(),
+ interfaceNode.getStaticConstructor(),
+ ConstructorNode.DEFAULT,
+ eagerFilter(interfaceNode.getMethods(), method -> method.isStatic())
+ ));
+ result.add(InterfaceNode.declareInterface(
+ interfaceNode.getName(),
+ interfaceNode.getTypeParameters(),
+ interfaceNode.getSuperTypes(),
+ list(),
+ list(),
+ eagerFilter(interfaceNode.getMethods(), method -> !method.isStatic())
+ ));
+ } else {
+ result.add(typeNode);
+ }
+ }
+
+ NodeTransformer transformer = NodeTransformer.builder()
+ .transformReceiver((Receiver receiver) -> {
+ if (receiver instanceof StaticReceiver && splitInterfaces.contains(((StaticReceiver) receiver).getType())) {
+ return StaticReceiver.staticReceiver(staticTypeFor(((StaticReceiver) receiver).getType()));
+ } else {
+ return receiver;
+ }
+ })
+ .build();
+ return NodeTransformer.apply(transformer, result);
+ }
+
+ private static ScalarType staticTypeFor(ScalarType name) {
+ return ScalarType.of(name.getQualifiedName() + "_static");
+ }
+
+ private static boolean isSplittable(TypeNode typeNode) {
+ if (!(typeNode instanceof InterfaceNode)) {
+ return false;
+ }
+ InterfaceNode interfaceNode = (InterfaceNode) typeNode;
+ return !interfaceNode.getFields().isEmpty() || Iterables.any(interfaceNode.getMethods(), MethodNode::isStatic);
+ }
+}