diff --git a/pom.xml b/pom.xml
index 763bd26..aff7011 100644
--- a/pom.xml
+++ b/pom.xml
@@ -286,9 +286,9 @@
0
- com.github.checkstyle.regression.data.ModuleInfo
- 0
- 0
+ com.github.checkstyle.regression.module.ModuleUtils
+ 33
+ 57
diff --git a/src/main/java/com/github/checkstyle/regression/module/ModuleCollector.java b/src/main/java/com/github/checkstyle/regression/module/ModuleCollector.java
new file mode 100644
index 0000000..f41949b
--- /dev/null
+++ b/src/main/java/com/github/checkstyle/regression/module/ModuleCollector.java
@@ -0,0 +1,62 @@
+////////////////////////////////////////////////////////////////////////////////
+// checkstyle: Checks Java source code for adherence to a set of rules.
+// Copyright (C) 2001-2017 the original author or authors.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+////////////////////////////////////////////////////////////////////////////////
+
+package com.github.checkstyle.regression.module;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import com.github.checkstyle.regression.data.GitChange;
+import com.github.checkstyle.regression.data.ModifiableModuleInfo;
+import com.github.checkstyle.regression.data.ModuleExtractInfo;
+import com.github.checkstyle.regression.data.ModuleInfo;
+
+/**
+ * Collects all the necessary information for the generation, in module level.
+ * @author LuoLiangchen
+ */
+public final class ModuleCollector {
+ /** Prevents instantiation. */
+ private ModuleCollector() {
+ }
+
+ /**
+ * Generates the module information from a list of changes.
+ * @param changes the changes source
+ * @return the module information generated from the given changes
+ */
+ public static List generate(List changes) {
+ final Map moduleInfos = new LinkedHashMap<>();
+ for (GitChange change : changes) {
+ if (ModuleUtils.isCheckstyleModule(change)) {
+ final ModuleExtractInfo extractInfo =
+ ModuleUtils.convertModuleChangeToExtractInfo(change);
+ final ModifiableModuleInfo moduleInfo = ModifiableModuleInfo.create()
+ .setModuleExtractInfo(extractInfo);
+ moduleInfos.put(extractInfo.fullName(), moduleInfo);
+ }
+ }
+
+ return moduleInfos.values().stream()
+ .map(ModifiableModuleInfo::toImmutable)
+ .collect(Collectors.toList());
+ }
+}
diff --git a/src/main/java/com/github/checkstyle/regression/module/ModuleUtils.java b/src/main/java/com/github/checkstyle/regression/module/ModuleUtils.java
new file mode 100644
index 0000000..d6a78a9
--- /dev/null
+++ b/src/main/java/com/github/checkstyle/regression/module/ModuleUtils.java
@@ -0,0 +1,172 @@
+////////////////////////////////////////////////////////////////////////////////
+// checkstyle: Checks Java source code for adherence to a set of rules.
+// Copyright (C) 2001-2017 the original author or authors.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+////////////////////////////////////////////////////////////////////////////////
+
+package com.github.checkstyle.regression.module;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import com.github.checkstyle.regression.data.GitChange;
+import com.github.checkstyle.regression.data.ModuleExtractInfo;
+
+/**
+ * Contains utility methods related to checkstyle module.
+ * @author LuoLiangchen
+ */
+public final class ModuleUtils {
+ /** The compiled regex pattern of the path of Java source files. */
+ private static final Pattern JAVA_SOURCE_PARTTEN =
+ Pattern.compile("src/(main|test)/java/(.+)\\.java");
+
+ /** The postfix of a test of a checkstyle module. */
+ private static final String TEST_POSTFIX = "Test";
+
+ /** The map of full qualified name to module extract info. */
+ private static final Map NAME_TO_MODULE_EXTRAT_INFO =
+ new HashMap<>();
+
+ /** Prevents instantiation. */
+ private ModuleUtils() {
+ }
+
+ /**
+ * Sets the map of full qualified name to module extract info with the given map.
+ * @param map the given map
+ */
+ public static void setNameToModuleExtratInfo(Map map) {
+ NAME_TO_MODULE_EXTRAT_INFO.clear();
+ NAME_TO_MODULE_EXTRAT_INFO.putAll(map);
+ }
+
+ /**
+ * Checks whether the corresponding file of a change may be considered as
+ * a checkstyle module.
+ * @param change change to check
+ * @return true if the corresponding file of a change may be considered as
+ * a checkstyle module
+ */
+ public static boolean isCheckstyleModule(GitChange change) {
+ final boolean returnValue;
+ if (isJavaMainSource(change)) {
+ final String fullName = convertJavaSourcePathToFullName(change.getPath());
+ returnValue = NAME_TO_MODULE_EXTRAT_INFO.containsKey(fullName);
+ }
+ else {
+ returnValue = false;
+ }
+ return returnValue;
+ }
+
+ /**
+ * Checks whether the corresponding file of a change may be considered as
+ * a checkstyle utility class.
+ * @param change change to check
+ * @return true if the corresponding file of a change may be considered as
+ * a checkstyle utility class.
+ */
+ public static boolean isCheckstyleUtility(GitChange change) {
+ final boolean returnValue;
+ if (isJavaMainSource(change)) {
+ final String fullName = convertJavaSourcePathToFullName(change.getPath());
+ returnValue = !NAME_TO_MODULE_EXTRAT_INFO.containsKey(fullName);
+ }
+ else {
+ returnValue = false;
+ }
+ return returnValue;
+ }
+
+ /**
+ * Checks whether the corresponding file of a change may be considered as
+ * a Java main source file.
+ * @param change change to check
+ * @return true if the corresponding file of a change may be considered as
+ * a Java main source file.
+ */
+ private static boolean isJavaMainSource(GitChange change) {
+ final boolean returnValue;
+ final Matcher matcher = JAVA_SOURCE_PARTTEN.matcher(change.getPath());
+ if (matcher.find()) {
+ returnValue = "main".equals(matcher.group(1));
+ }
+ else {
+ returnValue = false;
+ }
+ return returnValue;
+ }
+
+ /**
+ * Checks whether the corresponding file of a change may be considered as
+ * a test of checkstyle module.
+ * @param change change to check
+ * @return true if the corresponding file of a change may be considered as
+ * a test of checkstyle module
+ */
+ public static boolean isCheckstyleModuleTest(GitChange change) {
+ final boolean returnValue;
+ if (JAVA_SOURCE_PARTTEN.matcher(change.getPath()).find()) {
+ final String fullName = convertJavaSourcePathToFullName(change.getPath());
+ if (fullName.endsWith(TEST_POSTFIX)) {
+ returnValue = NAME_TO_MODULE_EXTRAT_INFO.containsKey(
+ fullName.substring(0, fullName.length() - TEST_POSTFIX.length()));
+ }
+ else {
+ returnValue = false;
+ }
+ }
+ else {
+ returnValue = false;
+ }
+ return returnValue;
+ }
+
+ /**
+ * Converts a {@link GitChange} of checkstyle module to a {@link ModuleExtractInfo}.
+ * @param change the change to convert
+ * @return the module info converted from the given change
+ */
+ public static ModuleExtractInfo convertModuleChangeToExtractInfo(GitChange change) {
+ final String fullName = convertJavaSourcePathToFullName(change.getPath());
+ return NAME_TO_MODULE_EXTRAT_INFO.get(fullName);
+ }
+
+ /**
+ * Converts a {@link GitChange} of test to the full name of corresponding checkstyle module.
+ * @param change the change to convert
+ * @return the full name of corresponding checkstyle module
+ */
+ public static String convertModuleTestChangeToModuleFullName(GitChange change) {
+ final String testName = convertJavaSourcePathToFullName(change.getPath());
+ return testName.substring(0, testName.length() - TEST_POSTFIX.length());
+ }
+
+ /**
+ * Converts a path of Java source file to its full qualified name.
+ * @param path the path of Java source file
+ * @return the corresponding full qualified name
+ */
+ private static String convertJavaSourcePathToFullName(String path) {
+ return Arrays.stream(JAVA_SOURCE_PARTTEN.matcher(path).replaceAll("$2").split("/"))
+ .collect(Collectors.joining("."));
+ }
+}
diff --git a/src/main/java/com/github/checkstyle/regression/module/package-info.java b/src/main/java/com/github/checkstyle/regression/module/package-info.java
new file mode 100644
index 0000000..cf35f8f
--- /dev/null
+++ b/src/main/java/com/github/checkstyle/regression/module/package-info.java
@@ -0,0 +1,23 @@
+////////////////////////////////////////////////////////////////////////////////
+// checkstyle: Checks Java source code for adherence to a set of rules.
+// Copyright (C) 2001-2017 the original author or authors.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Contains the module information generation and utility classes.
+ */
+package com.github.checkstyle.regression.module;
diff --git a/src/test/java/com/github/checkstyle/regression/module/ModuleInfoCollectorTest.java b/src/test/java/com/github/checkstyle/regression/module/ModuleInfoCollectorTest.java
new file mode 100644
index 0000000..9e117b2
--- /dev/null
+++ b/src/test/java/com/github/checkstyle/regression/module/ModuleInfoCollectorTest.java
@@ -0,0 +1,127 @@
+////////////////////////////////////////////////////////////////////////////////
+// checkstyle: Checks Java source code for adherence to a set of rules.
+// Copyright (C) 2001-2017 the original author or authors.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+////////////////////////////////////////////////////////////////////////////////
+
+package com.github.checkstyle.regression.module;
+
+import static com.github.checkstyle.regression.internal.TestUtils.assertUtilsClassHasPrivateConstructor;
+import static org.junit.Assert.assertEquals;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.github.checkstyle.regression.data.GitChange;
+import com.github.checkstyle.regression.data.ImmutableModuleExtractInfo;
+import com.github.checkstyle.regression.data.ImmutableModuleInfo;
+import com.github.checkstyle.regression.data.ModuleExtractInfo;
+import com.github.checkstyle.regression.data.ModuleInfo;
+import com.github.checkstyle.regression.extract.ExtractInfoProcessor;
+
+public class ModuleInfoCollectorTest {
+ private static final String BASE_PACKAGE =
+ "com.puppycrawl.tools.checkstyle";
+
+ private static final String JAVA_MAIN_SOURCE_PREFIX =
+ "src/main/java/com/puppycrawl/tools/checkstyle/";
+
+ private static final String JAVA_TEST_SOURCE_PREFIX =
+ "src/test/java/com/puppycrawl/tools/checkstyle/";
+
+ @Before
+ public void setUp() {
+ final InputStream is = ExtractInfoProcessor.class.getClassLoader()
+ .getResourceAsStream("checkstyle_modules.json");
+ final InputStreamReader reader = new InputStreamReader(is, Charset.forName("UTF-8"));
+ final Map map =
+ ExtractInfoProcessor.getModuleExtractInfosFromReader(reader);
+ ModuleUtils.setNameToModuleExtratInfo(map);
+ }
+
+ @Test
+ public void testIsProperUtilsClass() throws Exception {
+ assertUtilsClassHasPrivateConstructor(ModuleCollector.class);
+ }
+
+ @Test
+ public void testGenerateConfigNodesForValidChanges1() {
+ final GitChange moduleChange = new GitChange(
+ JAVA_MAIN_SOURCE_PREFIX + "checks/coding/EmptyStatementCheck.java");
+ final GitChange testChange = new GitChange(
+ JAVA_TEST_SOURCE_PREFIX + "checks/coding/EmptyStatementCheckTest.java");
+ final GitChange nonRelatedChange = new GitChange(
+ JAVA_TEST_SOURCE_PREFIX + "checks/NewlineAtEndOfFileCheckTest.java");
+ final List changes = Arrays.asList(moduleChange, testChange, nonRelatedChange);
+ final ModuleExtractInfo moduleExtractInfo = ImmutableModuleExtractInfo.builder()
+ .name("EmptyStatementCheck")
+ .packageName(BASE_PACKAGE + ".checks.coding")
+ .parent("TreeWalker")
+ .build();
+ final List moduleInfos =
+ ModuleCollector.generate(changes);
+ final ModuleInfo moduleInfo = ImmutableModuleInfo.builder()
+ .moduleExtractInfo(moduleExtractInfo)
+ .build();
+ assertEquals(1, moduleInfos.size());
+ assertEquals(moduleInfo, moduleInfos.get(0));
+ // just for codecov, no need to check this.
+ assertEquals("EmptyStatementCheck", moduleInfos.get(0).name());
+ }
+
+ @Test
+ public void testGenerateConfigNodesForValidChanges2() {
+ final GitChange moduleChange = new GitChange(
+ JAVA_MAIN_SOURCE_PREFIX + "checks/NewlineAtEndOfFileCheck.java");
+ final GitChange testChange = new GitChange(
+ JAVA_TEST_SOURCE_PREFIX + "checks/NewlineAtEndOfFileCheckTest.java");
+ final GitChange nonRelatedChange = new GitChange(
+ JAVA_TEST_SOURCE_PREFIX + "checks/coding/EmptyStatementCheckTest.java");
+ final List changes = Arrays.asList(moduleChange, testChange, nonRelatedChange);
+ final ModuleExtractInfo moduleExtractInfo = ImmutableModuleExtractInfo.builder()
+ .name("NewlineAtEndOfFileCheck")
+ .packageName(BASE_PACKAGE + ".checks")
+ .parent("Checker")
+ .build();
+ final List moduleInfos =
+ ModuleCollector.generate(changes);
+ final ModuleInfo moduleInfo = ImmutableModuleInfo.builder()
+ .moduleExtractInfo(moduleExtractInfo)
+ .build();
+ assertEquals(1, moduleInfos.size());
+ assertEquals(moduleInfo, moduleInfos.get(0));
+ }
+
+ @Test
+ public void testGenerateConfigNodesForInvalidChanges() {
+ final List changes = new LinkedList<>();
+ changes.add(new GitChange(
+ JAVA_MAIN_SOURCE_PREFIX + "PackageObjectFactory.java"));
+ changes.add(new GitChange("src/main/java/Bar.java"));
+ changes.add(new GitChange("foo/A.java"));
+ final List moduleInfos =
+ ModuleCollector.generate(changes);
+ assertEquals(0, moduleInfos.size());
+ }
+}
diff --git a/src/test/java/com/github/checkstyle/regression/module/ModuleUtilsTest.java b/src/test/java/com/github/checkstyle/regression/module/ModuleUtilsTest.java
new file mode 100644
index 0000000..90c3560
--- /dev/null
+++ b/src/test/java/com/github/checkstyle/regression/module/ModuleUtilsTest.java
@@ -0,0 +1,97 @@
+////////////////////////////////////////////////////////////////////////////////
+// checkstyle: Checks Java source code for adherence to a set of rules.
+// Copyright (C) 2001-2017 the original author or authors.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+////////////////////////////////////////////////////////////////////////////////
+
+package com.github.checkstyle.regression.module;
+
+import static com.github.checkstyle.regression.internal.TestUtils.assertUtilsClassHasPrivateConstructor;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.Charset;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.github.checkstyle.regression.data.GitChange;
+import com.github.checkstyle.regression.data.ImmutableModuleExtractInfo;
+import com.github.checkstyle.regression.data.ModuleExtractInfo;
+import com.github.checkstyle.regression.extract.ExtractInfoProcessor;
+
+public class ModuleUtilsTest {
+ private static final String BASE_PACKAGE = "com.puppycrawl.tools.checkstyle";
+
+ private static final String JAVA_MAIN_SOURCE_PREFIX =
+ "src/main/java/com/puppycrawl/tools/checkstyle/";
+
+ @Before
+ public void setUp() {
+ final InputStream is = ExtractInfoProcessor.class.getClassLoader()
+ .getResourceAsStream("checkstyle_modules.json");
+ final InputStreamReader reader = new InputStreamReader(is, Charset.forName("UTF-8"));
+ final Map map =
+ ExtractInfoProcessor.getModuleExtractInfosFromReader(reader);
+ ModuleUtils.setNameToModuleExtratInfo(map);
+ }
+
+ @Test
+ public void testIsProperUtilsClass() throws Exception {
+ assertUtilsClassHasPrivateConstructor(ModuleUtils.class);
+ }
+
+ @Test
+ public void testIsCheckstyleModule() {
+ final GitChange change = new GitChange(
+ JAVA_MAIN_SOURCE_PREFIX + "checks/coding/EmptyStatementCheck.java");
+ final boolean result = ModuleUtils.isCheckstyleModule(change);
+ assertTrue(result);
+ }
+
+ @Test
+ public void testIsCheckstyleModuleNonModule() {
+ final GitChange change = new GitChange(
+ JAVA_MAIN_SOURCE_PREFIX + "PackageObjectFactory.java");
+ final boolean result = ModuleUtils.isCheckstyleModule(change);
+ assertFalse(result);
+ }
+
+ @Test
+ public void testIsCheckstyleModuleNonMainFile() {
+ final boolean result =
+ ModuleUtils.isCheckstyleModule(new GitChange("src/test/java/foo/Foo.java"));
+ assertFalse(result);
+ }
+
+ @Test
+ public void testConvertModuleChangeToModuleInfo() {
+ final GitChange change = new GitChange(
+ JAVA_MAIN_SOURCE_PREFIX + "checks/coding/EmptyStatementCheck.java");
+ final ModuleExtractInfo moduleExtractInfo =
+ ModuleUtils.convertModuleChangeToExtractInfo(change);
+ final ModuleExtractInfo expected = ImmutableModuleExtractInfo.builder()
+ .name("EmptyStatementCheck")
+ .packageName(BASE_PACKAGE + ".checks.coding")
+ .parent("TreeWalker")
+ .build();
+ assertEquals(expected, moduleExtractInfo);
+ }
+}