From ff96df2dfdb6c1adfd5892d3d37cadfcc1f52088 Mon Sep 17 00:00:00 2001 From: kunicmarko20 Date: Mon, 21 Oct 2019 22:53:32 +0100 Subject: [PATCH] Enum generation closes #5 --- .../actions/generation/EnumAction.java | 23 +++++++++ .../generation/handlers/EnumHandler.java | 47 +++++++++++++++++ .../idea/helpable/service/CaseConverter.java | 21 ++++++++ .../service/ClassConstantsFinder.java | 29 +++++++++++ src/main/resources/META-INF/plugin.xml | 5 ++ src/main/resources/templates/enum.twig.html | 50 +++++++++++++++++++ 6 files changed, 175 insertions(+) create mode 100644 src/main/java/com/github/kunicmarko20/idea/helpable/actions/generation/EnumAction.java create mode 100644 src/main/java/com/github/kunicmarko20/idea/helpable/actions/generation/handlers/EnumHandler.java create mode 100644 src/main/java/com/github/kunicmarko20/idea/helpable/service/CaseConverter.java create mode 100644 src/main/java/com/github/kunicmarko20/idea/helpable/service/ClassConstantsFinder.java create mode 100644 src/main/resources/templates/enum.twig.html diff --git a/src/main/java/com/github/kunicmarko20/idea/helpable/actions/generation/EnumAction.java b/src/main/java/com/github/kunicmarko20/idea/helpable/actions/generation/EnumAction.java new file mode 100644 index 0000000..6e3e588 --- /dev/null +++ b/src/main/java/com/github/kunicmarko20/idea/helpable/actions/generation/EnumAction.java @@ -0,0 +1,23 @@ +package com.github.kunicmarko20.idea.helpable.actions.generation; + +import com.github.kunicmarko20.idea.helpable.actions.generation.handlers.EnumHandler; +import com.intellij.codeInsight.CodeInsightActionHandler; +import com.intellij.codeInsight.actions.CodeInsightAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; + +public class EnumAction extends CodeInsightAction { + private final EnumHandler handler = new EnumHandler(); + + protected boolean isValidForFile(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) { + return this.handler.isValidFor(editor, file); + } + + @NotNull + @Override + protected CodeInsightActionHandler getHandler() { + return this.handler; + } +} diff --git a/src/main/java/com/github/kunicmarko20/idea/helpable/actions/generation/handlers/EnumHandler.java b/src/main/java/com/github/kunicmarko20/idea/helpable/actions/generation/handlers/EnumHandler.java new file mode 100644 index 0000000..b7ea3b2 --- /dev/null +++ b/src/main/java/com/github/kunicmarko20/idea/helpable/actions/generation/handlers/EnumHandler.java @@ -0,0 +1,47 @@ +package com.github.kunicmarko20.idea.helpable.actions.generation.handlers; + +import com.github.kunicmarko20.idea.helpable.service.CaseConverter; +import com.github.kunicmarko20.idea.helpable.service.ClassConstantsFinder; +import com.intellij.codeInsight.hint.HintManager; +import com.jetbrains.php.lang.actions.PhpNamedElementNode; +import org.apache.commons.lang.WordUtils; +import org.jetbrains.annotations.NotNull; +import org.jtwig.JtwigModel; +import org.jtwig.JtwigTemplate; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class EnumHandler extends ActionHandler { + @Override + @NotNull + protected String body() { + JtwigTemplate template = JtwigTemplate.classpathTemplate("templates/enum.twig.html"); + + JtwigModel model = JtwigModel.newModel() + .with("type", this.phpClass.getName()) + .with("variants", this.camelCasedVariants(ClassConstantsFinder.find(this.phpClass))); + + return template.render(model); + } + + private HashMap camelCasedVariants(PhpNamedElementNode[] constants) { + HashMap camelCasedVariants = new HashMap<>(); + + for (PhpNamedElementNode constant : constants) { + camelCasedVariants.put( + CaseConverter.fromSnakeToCamelCase(constant.getText()), + constant.getText() + ); + } + + return camelCasedVariants; + } + + @Override + @NotNull + protected boolean isValid() { + return true; + } +} diff --git a/src/main/java/com/github/kunicmarko20/idea/helpable/service/CaseConverter.java b/src/main/java/com/github/kunicmarko20/idea/helpable/service/CaseConverter.java new file mode 100644 index 0000000..bb407b6 --- /dev/null +++ b/src/main/java/com/github/kunicmarko20/idea/helpable/service/CaseConverter.java @@ -0,0 +1,21 @@ +package com.github.kunicmarko20.idea.helpable.service; + +public class CaseConverter { + public static String fromSnakeToCamelCase(String phrase) { + StringBuilder camelCasedWords = new StringBuilder(); + + String[] words = phrase.split("_"); + + camelCasedWords.append(words[0].toLowerCase()); + + for (int i = 1; i < words.length; i++) { + camelCasedWords.append(Character.toUpperCase(words[i].charAt(0))); + + if (words[i].length() > 1) { + camelCasedWords.append(words[i].substring(1).toLowerCase()); + } + } + + return camelCasedWords.toString(); + } +} diff --git a/src/main/java/com/github/kunicmarko20/idea/helpable/service/ClassConstantsFinder.java b/src/main/java/com/github/kunicmarko20/idea/helpable/service/ClassConstantsFinder.java new file mode 100644 index 0000000..86be2a2 --- /dev/null +++ b/src/main/java/com/github/kunicmarko20/idea/helpable/service/ClassConstantsFinder.java @@ -0,0 +1,29 @@ +package com.github.kunicmarko20.idea.helpable.service; + +import com.jetbrains.php.lang.actions.PhpNamedElementNode; +import com.jetbrains.php.lang.psi.elements.Field; +import com.jetbrains.php.lang.psi.elements.PhpClass; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Iterator; +import java.util.TreeMap; + +public class ClassConstantsFinder { + @NotNull + public static PhpNamedElementNode[] find(@NotNull PhpClass phpClass) { + TreeMap nodes = new TreeMap<>(); + Collection fields = phpClass.getFields(); + Iterator fieldIterator = fields.iterator(); + + while (fieldIterator.hasNext()) { + Field field = (Field) fieldIterator.next(); + + if (field.isConstant()) { + nodes.put(field.getName(), new PhpNamedElementNode(field)); + } + } + + return nodes.values().toArray(new PhpNamedElementNode[0]); + } +} diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index c840805..18749d7 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -30,6 +30,11 @@ text="Factory Method"> + + + diff --git a/src/main/resources/templates/enum.twig.html b/src/main/resources/templates/enum.twig.html new file mode 100644 index 0000000..8618226 --- /dev/null +++ b/src/main/resources/templates/enum.twig.html @@ -0,0 +1,50 @@ +private const ALL_MAP = [{% for variant in variants %} + self::{{ variant }}, +{%- endfor %} +]; + +/** +* @var string +*/ +private $value; + +/** +* @var {{ type }}[] +*/ +private static $lazyLoad = []; + +private function __construct(string $value) +{ + \Assert\Assert::that($value)->inArray(self::ALL_MAP); + + $this->value = $value; +} + +public static function fromString(string $value): self +{ + return new self($value); +} +{% for camel_cased_variant, variant in variants %} + public static function {{ camel_cased_variant }}(): self + { + return self::lazyLoad((self::{{ variant }})); + } +{% endfor %} +private static function lazyLoad(string $value): self +{ + if (isset(self::$lazyLoad[$value])) { + return self::$lazyLoad[$value]; + } + + return self::$lazyLoad[$value] = new self($value); +} + +public function toString(): string +{ + return $this->value; +} + +public function equals({{ type }} $other): bool +{ + return $this->value === $other->value; +} \ No newline at end of file