diff options
| author | Michael Williamson <mike@zwobble.org> | 2016-08-29 17:13:03 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2016-08-29 17:13:03 +0100 |
| commit | a82ecb60d6ee7ee46e5800088f1769f86872077b (patch) | |
| tree | 8b3c5442a1bd047606de63477839755e88dab2f5 /src/main/java/org/zwobble/couscous/transforms/SplitStaticsFromInterface.java | |
| parent | 1babfdf8daa45ffef3d624db6c717f846d295440 (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.java | 68 |
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); + } +} |
