From 93d7b296b63c06a889cc7e9fb5b0c383a5a13da7 Mon Sep 17 00:00:00 2001 From: Luolc Date: Fri, 7 Jul 2017 02:49:59 +0800 Subject: [PATCH] Issue #37: extract program --- .travis.yml | 13 ++ .../extract/ExtractInfoGeneratorTest.java | 81 +++++++++++++ .../checkstyle/regression/extract/Json.java | 114 ++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 src/main/resources/com/github/checkstyle/regression/extract/ExtractInfoGeneratorTest.java create mode 100644 src/main/resources/com/github/checkstyle/regression/extract/Json.java diff --git a/.travis.yml b/.travis.yml index dccbc7a..f950601 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,6 +46,19 @@ matrix: - DESC="findbugs and pmd" - CMD="mvn clean compile pmd:check findbugs:check" + # checkstyle injection compile no error (oraclejdk8) + - jdk: oraclejdk8 + env: + - DESC="checkstyle injection compile no error" + - CMD1="git clone https://github.com/checkstyle/checkstyle &&" + - CMD2="cp src/main/resources/com/github/checkstyle/regression/extract/ExtractInfoGeneratorTest.java " + - CMD3="checkstyle/src/test/java/com/puppycrawl/tools/checkstyle/ExtractInfoGeneratorTest.java &&" + - CMD4="cp src/main/resources/com/github/checkstyle/regression/extract/Json.java " + - CMD5="checkstyle/src/test/java/com/puppycrawl/tools/checkstyle/Json.java &&" + - CMD6="cd checkstyle &&" + - CMD7="mvn clean compile" + - CMD="$CMD1$CMD2$CMD3$CMD4$CMD5$CMD6$CMD7" + script: eval $CMD after_success: diff --git a/src/main/resources/com/github/checkstyle/regression/extract/ExtractInfoGeneratorTest.java b/src/main/resources/com/github/checkstyle/regression/extract/ExtractInfoGeneratorTest.java new file mode 100644 index 0000000..f3528c7 --- /dev/null +++ b/src/main/resources/com/github/checkstyle/regression/extract/ExtractInfoGeneratorTest.java @@ -0,0 +1,81 @@ +package com.puppycrawl.tools.checkstyle; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +import org.junit.Test; + +import com.puppycrawl.tools.checkstyle.api.RootModule; +import com.puppycrawl.tools.checkstyle.internal.CheckUtil; +import com.puppycrawl.tools.checkstyle.utils.ModuleReflectionUtils; + +/** + * This file would be injected into checkstyle project and invoked by maven command + * to generate the module extract info file. + * @author LuoLiangchen + */ +public class ExtractInfoGeneratorTest { + /** + * Generates the extract info file named as "checkstyle_modules.json". + * @throws IOException failure when generating the file + */ + @Test + public void generateExtractInfoFile() throws IOException { + final List> modules = new ArrayList<>(CheckUtil.getCheckstyleModules()); + modules.sort(Comparator.comparing(Class::getSimpleName)); + final Json.JsonArray moduleJsonArray = new Json.JsonArray(); + for (Class module : modules) { + moduleJsonArray.add(createJsonObjectFromModuleClass(module)); + } + String jsonString = moduleJsonArray.toString(); + final File output = new File("checkstyle_modules.json"); + Files.write(output.toPath(), jsonString.getBytes(Charset.forName("UTF-8")), + StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); + } + + /** + * Creates Json object for a module from the module class. + * @param clazz the given module class + * @return the Json object describing the extract info of the module + */ + private static Json.JsonObject createJsonObjectFromModuleClass(Class clazz) { + final Json.JsonObject object = new Json.JsonObject(); + + final String name = clazz.getSimpleName(); + final String parent; + if (ModuleReflectionUtils.isCheckstyleCheck(clazz)) { + parent = "TreeWalker"; + } + else if (RootModule.class.isAssignableFrom(clazz)) { + parent = ""; + } + else { + parent = "Checker"; + } + object.addProperty("name", name); + object.addProperty("packageName", clazz.getPackage().getName()); + object.addProperty("parent", parent); + + final Json.JsonArray interfaces = new Json.JsonArray(); + final Json.JsonArray hierarchies = new Json.JsonArray(); + Arrays.stream(clazz.getInterfaces()).forEach(cls -> interfaces.add(cls.getCanonicalName())); + Class superClass = clazz.getSuperclass(); + while (!Object.class.equals(superClass)) { + hierarchies.add(superClass.getCanonicalName()); + Arrays.stream(superClass.getInterfaces()) + .forEach(cls -> interfaces.add(cls.getCanonicalName())); + superClass = superClass.getSuperclass(); + } + object.add("interfaces", interfaces); + object.add("hierarchies", hierarchies); + + return object; + } +} diff --git a/src/main/resources/com/github/checkstyle/regression/extract/Json.java b/src/main/resources/com/github/checkstyle/regression/extract/Json.java new file mode 100644 index 0000000..cf271bb --- /dev/null +++ b/src/main/resources/com/github/checkstyle/regression/extract/Json.java @@ -0,0 +1,114 @@ +package com.puppycrawl.tools.checkstyle; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Our own Json processing classes. + * @author LuoLiangchen + */ +class Json { + /** + * Adds indent of the given text. + * @param text the text to add indent + * @return the result text with indent + */ + private static String addIndent(String text) { + return Arrays.stream(text.split("\n")) + .map(line -> " " + line) + .collect(Collectors.joining("\n")); + } + + /** + * Formats the Json object. + * @param object the object to format + * @return the format result + */ + private static String format(Object object) { + if (object instanceof String) { + return "\"" + object + "\""; + } else { + return object.toString(); + } + } + + /** Represents an object type in Json. */ + public static final class JsonObject { + /** Fields of this Json object. */ + private final List members = new LinkedList<>(); + + /** + * Adds a member. + * @param key the key of the field + * @param value the value of the field + */ + void addProperty(String key, Object value) { + add(key, value); + } + + /** + * Adds a member. + * @param key the key of the field + * @param value the value of the field + */ + void add(String key, Object value) { + members.add(new KeyValue(key, value)); + } + + @Override + public String toString() { + final String keyValueLines = members.stream() + .map(Object::toString) + .collect(Collectors.joining(",\n")); + return "{\n" + addIndent(keyValueLines) + "\n}"; + } + } + + /** Represents an array type in Json. */ + public static final class JsonArray { + /** Items of this Json array. */ + private final List members = new LinkedList<>(); + + /** + * Adds a member. + * @param object the member to add + */ + void add(Object object) { + members.add(object); + } + + @Override + public String toString() { + final String membersLines = members.stream() + .map(Json::format) + .collect(Collectors.joining(",\n")); + return "[\n" + addIndent(membersLines) + "\n]"; + } + } + + /** Represents a key-value pair in Json object. */ + private static final class KeyValue { + /** The key of the field. */ + private final String key; + + /** The value of the field. */ + private final Object value; + + /** + * Creates a new instance of KeyValue. + * @param key the key of the field + * @param value the value of the field + */ + KeyValue(String key, Object value) { + this.key = key; + this.value = value; + } + + @Override + public String toString() { + return "\"" + key + "\": " + format(value); + } + } +}