diff --git a/builder/pom.xml b/builder/pom.xml index 1d0ffbf..73294ba 100644 --- a/builder/pom.xml +++ b/builder/pom.xml @@ -42,6 +42,8 @@ 2.3.5 1.0.0 4.3.0 + 7.8 + 1.24.0 @@ -92,6 +94,19 @@ ${map-builder.version} test + + + com.puppycrawl.tools + checkstyle + ${checkstyle.version} + compile + + + com.github.sevntu-checkstyle + sevntu-checks + ${sevntu.version} + + diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/BuilderConfiguration.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/BuilderConfiguration.java new file mode 100644 index 0000000..197c38c --- /dev/null +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/BuilderConfiguration.java @@ -0,0 +1,49 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2017 Paul Campbell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies + * or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package net.kemitix.checkstyle.ruleset.builder; + +import com.google.common.reflect.ClassPath; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.io.IOException; + +/** + * Configuration for Builder. + * + * @author Paul Campbell (pcampbell@kemitix.net). + */ +@Configuration +public class BuilderConfiguration { + + /** + * Create the ClassPath used to scan packages. + * + * @return the ClassPath + * + * @throws IOException if there is an error + */ + @Bean + public ClassPath classPath() throws IOException { + return ClassPath.from(getClass().getClassLoader()); + } +} diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleClassNotFoundException.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleClassNotFoundException.java new file mode 100644 index 0000000..ffa297c --- /dev/null +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleClassNotFoundException.java @@ -0,0 +1,39 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2017 Paul Campbell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies + * or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package net.kemitix.checkstyle.ruleset.builder; + +/** + * Raised when a Class to implement a Rule is not found. + * + * @author Paul Campbell (pcampbell@kemitix.net). + */ +public class CheckstyleClassNotFoundException extends RuntimeException { + + /** + * Constructor. + * + * @param name the name of the unimplemented rule + */ + public CheckstyleClassNotFoundException(final String name) { + super("No class found to implement " + name); + } +} diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleSourceLoadException.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleSourceLoadException.java new file mode 100644 index 0000000..ef9b959 --- /dev/null +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleSourceLoadException.java @@ -0,0 +1,42 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2017 Paul Campbell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies + * or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package net.kemitix.checkstyle.ruleset.builder; + +import java.io.IOException; + +/** + * Raised when there is an error scanning for check classes. + * + * @author Paul Campbell (pcampbell@kemitix.net). + */ +public class CheckstyleSourceLoadException extends RuntimeException { + + /** + * Constructor. + * + * @param basePackage the base package classes were being loaded from + * @param cause the cause + */ + public CheckstyleSourceLoadException(final String basePackage, final IOException cause) { + super("Error loading checkstyle rules from package: " + basePackage, cause); + } +} diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleWriter.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleWriter.java index 3e676e7..95a5a04 100644 --- a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleWriter.java +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleWriter.java @@ -55,6 +55,8 @@ class CheckstyleWriter implements CommandLineRunner { private final RulesProperties rulesProperties; + private final RuleClassLocator ruleClassLocator; + @Override public void run(final String... args) throws Exception { Stream.of(RuleLevel.values()) @@ -101,9 +103,9 @@ class CheckstyleWriter implements CommandLineRunner { private String formatRuleAsModule(final Rule rule) { if (rule.getProperties() .isEmpty()) { - return String.format("", rule.getName()); + return String.format("", ruleClassLocator.apply(rule)); } - return String.format("%n %s%n", rule.getName(), + return String.format("%n %s%n", ruleClassLocator.apply(rule), formatProperties(rule.getProperties()) ); } diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/DefaultPackageScanner.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/DefaultPackageScanner.java new file mode 100644 index 0000000..aea4769 --- /dev/null +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/DefaultPackageScanner.java @@ -0,0 +1,47 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2017 Paul Campbell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies + * or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package net.kemitix.checkstyle.ruleset.builder; + +import com.google.common.reflect.ClassPath; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.stream.Stream; + +/** + * Default implementation of {@link PackageScanner}. + * + * @author Paul Campbell (pcampbell@kemitix.net). + */ +@Service +@RequiredArgsConstructor +public class DefaultPackageScanner implements PackageScanner { + + private final ClassPath classPath; + + @Override + public final Stream apply(final RuleSource ruleSource) { + return classPath.getTopLevelClassesRecursive(ruleSource.getBasePackage()) + .stream() + .map(ClassPath.ClassInfo::getName); + } +} diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleClassLocator.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleClassLocator.java new file mode 100644 index 0000000..6a91c6b --- /dev/null +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleClassLocator.java @@ -0,0 +1,77 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2017 Paul Campbell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies + * or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package net.kemitix.checkstyle.ruleset.builder; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import java.util.AbstractMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Default implementation of {@link RuleClassLocator}. + * + * @author Paul Campbell (pcampbell@kemitix.net). + */ +@Service +@RequiredArgsConstructor +public class DefaultRuleClassLocator implements RuleClassLocator { + + private final PackageScanner packageScanner; + + private Map> checkClasses; + + /** + * Initialise class lists for {@link RuleSource}s. + */ + @PostConstruct + public final void init() { + checkClasses = Stream.of(RuleSource.values()) + .map(source -> new AbstractMap.SimpleEntry<>( + source, packageScanner.apply(source) + .collect(Collectors.toList()))) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + @Override + public final String apply(final Rule rule) { + return getCanonicalClassName(rule.getSource(), rule.getName()); + } + + private String getCanonicalClassName(final RuleSource source, final String name) { + return checkClasses.get(source) + .stream() + .sorted() + .filter(classname -> byRuleName(classname, name)) + .findFirst() + .orElseThrow(() -> new CheckstyleClassNotFoundException(name)); + } + + private boolean byRuleName(final String classname, final String name) { + final String classNameWithDelimiter = "." + name; + return classname.endsWith(classNameWithDelimiter) || classname.endsWith(classNameWithDelimiter + "Check"); + } +} diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/PackageScanner.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/PackageScanner.java new file mode 100644 index 0000000..7cc8c2b --- /dev/null +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/PackageScanner.java @@ -0,0 +1,34 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2017 Paul Campbell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies + * or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package net.kemitix.checkstyle.ruleset.builder; + +import java.util.function.Function; +import java.util.stream.Stream; + +/** + * Scans a package for all classes. + * + * @author Paul Campbell (pcampbell@kemitix.net). + */ +interface PackageScanner extends Function> { + +} diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/Rule.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/Rule.java index 6e6798e..33c5624 100644 --- a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/Rule.java +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/Rule.java @@ -40,6 +40,11 @@ public class Rule { private static final Locale LOCALE = Locale.ENGLISH; + /** + * Configuration properties. + */ + private final Map properties = new HashMap<>(); + /** * The name of the rule's Check class. */ @@ -80,11 +85,6 @@ public class Rule { */ private String reason; - /** - * Configuration properties. - */ - private final Map properties = new HashMap<>(); - /** * Compare two Rules lexicographically for sorting by rule name, ignoring case. * @@ -103,5 +103,4 @@ public class Rule { private String getLowerCaseRuleName() { return getName().toLowerCase(LOCALE); } - } diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/RuleClassLocator.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/RuleClassLocator.java new file mode 100644 index 0000000..14b7d50 --- /dev/null +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/RuleClassLocator.java @@ -0,0 +1,33 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2017 Paul Campbell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies + * or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package net.kemitix.checkstyle.ruleset.builder; + +import java.util.function.Function; + +/** + * Returns the canonical name of the class that implements a {@link Rule}. + * + * @author Paul Campbell (pcampbell@kemitix.net). + */ +interface RuleClassLocator extends Function { + +} diff --git a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/RuleSource.java b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/RuleSource.java index d675310..a74871e 100644 --- a/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/RuleSource.java +++ b/builder/src/main/java/net/kemitix/checkstyle/ruleset/builder/RuleSource.java @@ -21,6 +21,8 @@ package net.kemitix.checkstyle.ruleset.builder; +import lombok.Getter; + /** * The origin of the rule. * @@ -28,6 +30,19 @@ package net.kemitix.checkstyle.ruleset.builder; */ public enum RuleSource { - CHECKSTYLE, - SEVNTU, + CHECKSTYLE("com.puppycrawl.tools.checkstyle"), + SEVNTU("com.github.sevntu.checkstyle.checks"); + + @Getter + private final String basePackage; + + + /** + * Constructor. + * + * @param basePackage the base package that contains all checks from this source + */ + RuleSource(final String basePackage) { + this.basePackage = basePackage; + } } diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/BuilderConfigurationTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/BuilderConfigurationTest.java new file mode 100644 index 0000000..294cb87 --- /dev/null +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/BuilderConfigurationTest.java @@ -0,0 +1,24 @@ +package net.kemitix.checkstyle.ruleset.builder; + +import com.google.common.reflect.ClassPath; +import org.junit.Test; + +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link BuilderConfiguration}. + * + * @author Paul Campbell (pcampbell@kemitix.net) + */ +public class BuilderConfigurationTest { + + @Test + public void canGetClassPath() throws IOException { + //when + final ClassPath classPath = new BuilderConfiguration().classPath(); + //then + assertThat(classPath).isNotNull(); + } +} diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleClassNotFoundExceptionTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleClassNotFoundExceptionTest.java new file mode 100644 index 0000000..eadf0a5 --- /dev/null +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleClassNotFoundExceptionTest.java @@ -0,0 +1,24 @@ +package net.kemitix.checkstyle.ruleset.builder; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link CheckstyleClassNotFoundException}. + * + * @author Paul Campbell (pcampbell@kemitix.net). + */ +public class CheckstyleClassNotFoundExceptionTest { + + @Test + public void canRaiseException() { + //given + final String classname = "class name"; + //when + final CheckstyleClassNotFoundException exception = new CheckstyleClassNotFoundException(classname); + //then + assertThat(exception.getMessage()).startsWith("No class found to implement ") + .endsWith(classname); + } +} diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleSourceLoadExceptionTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleSourceLoadExceptionTest.java new file mode 100644 index 0000000..cb3d1b1 --- /dev/null +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleSourceLoadExceptionTest.java @@ -0,0 +1,28 @@ +package net.kemitix.checkstyle.ruleset.builder; + +import org.junit.Test; + +import java.io.IOException; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +/** + * Tests for {@link CheckstyleSourceLoadException}. + * + * @author Paul Campbell (pcampbell@kemitix.net). + */ +public class CheckstyleSourceLoadExceptionTest { + + @Test + public void canRaiseException() { + //given + final String basePackage = "base package"; + final IOException cause = new IOException(); + //when + final CheckstyleSourceLoadException exception = new CheckstyleSourceLoadException(basePackage, cause); + //then + assertThat(exception).hasCause(cause) + .hasMessageStartingWith("Error loading checkstyle rules from package: ") + .hasMessageEndingWith(basePackage); + } +} diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleWriterTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleWriterTest.java index f70cbaf..1ad7836 100644 --- a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleWriterTest.java +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/CheckstyleWriterTest.java @@ -5,7 +5,9 @@ import me.andrz.builder.map.MapBuilder; import org.assertj.core.api.ThrowableAssert; import org.junit.Before; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; +import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.IOException; @@ -17,10 +19,11 @@ import java.nio.file.StandardOpenOption; import java.util.AbstractMap; import java.util.List; import java.util.Map; -import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.any; /** * Tests for {@link CheckstyleWriter}. @@ -33,6 +36,12 @@ public class CheckstyleWriterTest { private static final String FILE_SEPARATOR = System.getProperty("file.separator"); + @org.junit.Rule + public ExpectedException exception = ExpectedException.none(); + + @org.junit.Rule + public TemporaryFolder folder = new TemporaryFolder(); + private CheckstyleWriter checkstyleWriter; private OutputProperties outputProperties; @@ -43,18 +52,20 @@ public class CheckstyleWriterTest { private String ruleName; + private String ruleClassname; + private Map outputFiles; private Path outputDirectory; - @org.junit.Rule - public TemporaryFolder folder = new TemporaryFolder(); + @Mock + private RuleClassLocator ruleClassLocator; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - ruleName = UUID.randomUUID() - .toString(); + ruleName = "RegexpOnFilename"; + ruleClassname = "com.puppycrawl.tools.checkstyle.checks.regexp.RegexpOnFilenameCheck"; outputProperties = new OutputProperties(); outputFiles = new MapBuilder().put(getOutputFile(RuleLevel.LAYOUT)) .put(getOutputFile(RuleLevel.NAMING)) @@ -73,7 +84,14 @@ public class CheckstyleWriterTest { checkstyleTemplate, TEMPLATE.getBytes(StandardCharsets.UTF_8), StandardOpenOption.TRUNCATE_EXISTING); templateProperties.setCheckstyleXml(checkstyleTemplate); rulesProperties = new RulesProperties(); - checkstyleWriter = new CheckstyleWriter(outputProperties, templateProperties, rulesProperties); + checkstyleWriter = + new CheckstyleWriter(outputProperties, templateProperties, rulesProperties, ruleClassLocator); + given(ruleClassLocator.apply(any())).willReturn(ruleClassname); + } + + private Map.Entry getOutputFile(final RuleLevel level) throws IOException { + final String xmlFile = String.format("checkstyle-%s.xml", level.toString()); + return new AbstractMap.SimpleImmutableEntry<>(level, xmlFile); } // write rule that matches current level @@ -87,7 +105,24 @@ public class CheckstyleWriterTest { checkstyleWriter.run(); //then val lines = loadOutputFile(RuleLevel.LAYOUT); - assertThat(lines).containsExactly("C:", String.format("TW:", ruleName)); + assertThat(lines).containsExactly("C:", String.format("TW:", ruleClassname)); + } + + private List loadOutputFile(final RuleLevel level) throws IOException { + val path = outputDirectory.resolve(outputFiles.get(level)); + assertThat(path).as("Output path exists") + .exists(); + return Files.readAllLines(path, StandardCharsets.UTF_8); + } + + private Rule enabledRule(final RuleLevel level, final RuleParent parent) { + val rule = new Rule(); + rule.setName(ruleName); + rule.setSource(RuleSource.CHECKSTYLE); + rule.setEnabled(true); + rule.setLevel(level); + rule.setParent(parent); + return rule; } // write rule that is below current level @@ -101,7 +136,7 @@ public class CheckstyleWriterTest { checkstyleWriter.run(); //then val lines = loadOutputFile(RuleLevel.NAMING); - assertThat(lines).containsExactly("C:", String.format("TW:", ruleName)); + assertThat(lines).containsExactly("C:", String.format("TW:", ruleClassname)); } // write rule with checker parent @@ -115,7 +150,7 @@ public class CheckstyleWriterTest { checkstyleWriter.run(); //then val lines = loadOutputFile(RuleLevel.LAYOUT); - assertThat(lines).containsExactly(String.format("C:", ruleName), "TW:"); + assertThat(lines).containsExactly(String.format("C:", ruleClassname), "TW:"); } // write rule with properties @@ -131,7 +166,7 @@ public class CheckstyleWriterTest { checkstyleWriter.run(); //then val lines = loadOutputFile(RuleLevel.LAYOUT); - assertThat(lines).containsExactly("C:", String.format("TW:", ruleName), + assertThat(lines).containsExactly("C:", String.format("TW:", ruleClassname), " ", "" ); } @@ -191,25 +226,4 @@ public class CheckstyleWriterTest { imaginary + FILE_SEPARATOR )); } - - private Map.Entry getOutputFile(final RuleLevel level) throws IOException { - final String xmlFile = String.format("checkstyle-%s.xml", level.toString()); - return new AbstractMap.SimpleImmutableEntry<>(level, xmlFile); - } - - private List loadOutputFile(final RuleLevel level) throws IOException { - val path = outputDirectory.resolve(outputFiles.get(level)); - assertThat(path).as("Output path exists") - .exists(); - return Files.readAllLines(path, StandardCharsets.UTF_8); - } - - private Rule enabledRule(final RuleLevel level, final RuleParent parent) { - val rule = new Rule(); - rule.setName(ruleName); - rule.setEnabled(true); - rule.setLevel(level); - rule.setParent(parent); - return rule; - } } diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/DefaultPackageScannerTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/DefaultPackageScannerTest.java new file mode 100644 index 0000000..e0540f2 --- /dev/null +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/DefaultPackageScannerTest.java @@ -0,0 +1,44 @@ +package net.kemitix.checkstyle.ruleset.builder; + +import com.google.common.reflect.ClassPath; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link DefaultPackageScanner}. + * + * @author Paul Campbell (pcampbell@kemitix.net) + */ +public class DefaultPackageScannerTest { + + private DefaultPackageScanner scanner; + + @Before + public void setUp() throws Exception { + final ClassPath classPath = ClassPath.from(getClass().getClassLoader()); + scanner = new DefaultPackageScanner(classPath); + } + + @Test + public void canScanCheckstylePackage() throws IOException { + //when + final Stream result = scanner.apply(RuleSource.CHECKSTYLE); + //then + assertThat(result).allMatch(cn -> cn.startsWith(RuleSource.CHECKSTYLE.getBasePackage())) + .contains("com.puppycrawl.tools.checkstyle.checks.sizes.FileLengthCheck"); + } + + @Test + public void canScanSevntuPackage() throws IOException { + //when + final Stream result = scanner.apply(RuleSource.SEVNTU); + //then + assertThat(result).allMatch(cn -> cn.startsWith(RuleSource.SEVNTU.getBasePackage())) + .contains("com.github.sevntu.checkstyle.checks.design.NestedSwitchCheck"); + } +} diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleClassLocatorTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleClassLocatorTest.java new file mode 100644 index 0000000..e8ea62a --- /dev/null +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/DefaultRuleClassLocatorTest.java @@ -0,0 +1,55 @@ +package net.kemitix.checkstyle.ruleset.builder; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.Collections; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +/** + * Tests for {@link DefaultRuleClassLocator}. + * + * @author Paul Campbell (pcampbell@kemitix.net) + */ +public class DefaultRuleClassLocatorTest { + + private DefaultRuleClassLocator subject; + + @Mock + private PackageScanner packageScanner; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + subject = new DefaultRuleClassLocator(packageScanner); + } + + @Test + public void canLookupRule() { + //given + final String rulename = "RegexpOnFilename"; + final String expected = "com.puppycrawl.tools.checkstyle.checks.regexp.RegexpOnFilenameCheck"; + final List checkstyleClasses = Collections.singletonList(expected); + final List sevntuClasses = Collections.emptyList(); + given(packageScanner.apply(RuleSource.CHECKSTYLE)).willReturn(checkstyleClasses.stream()); + given(packageScanner.apply(RuleSource.SEVNTU)).willReturn(sevntuClasses.stream()); + subject.init(); + final Rule rule = createCheckstyleRule(rulename); + //when + final String result = subject.apply(rule); + //then + assertThat(result).isEqualTo(expected); + } + + private Rule createCheckstyleRule(final String rulename) { + final Rule rule = new Rule(); + rule.setSource(RuleSource.CHECKSTYLE); + rule.setName(rulename); + return rule; + } +} diff --git a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleSourceTest.java b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleSourceTest.java index 3cf5562..47397a4 100644 --- a/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleSourceTest.java +++ b/builder/src/test/java/net/kemitix/checkstyle/ruleset/builder/RuleSourceTest.java @@ -30,4 +30,16 @@ public class RuleSourceTest { //then assertThat(values).containsExactlyElementsOf(expected); } + + @Test + public void basePackages() { + //given + final String puppycrawl = "puppycrawl"; + final String sevntu = "sevntu"; + //then + assertThat(RuleSource.CHECKSTYLE.getBasePackage()).contains(puppycrawl) + .doesNotContain(sevntu); + assertThat(RuleSource.SEVNTU.getBasePackage()).contains(sevntu) + .doesNotContain(puppycrawl); + } } diff --git a/plugin-sample/pom.xml b/plugin-sample/pom.xml index 8ae0218..2c7d70d 100644 --- a/plugin-sample/pom.xml +++ b/plugin-sample/pom.xml @@ -2,7 +2,9 @@ - + + 2-naming + 4.0.0 diff --git a/pom.xml b/pom.xml index f5c9d8f..5c317d7 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ 2.8.2 2.17 - 7.7 + 7.8 1.24.0 1.10.19 3.8.0 diff --git a/regressions/src/main/java/net/kemitix/checkstyle/regressions/ExplicitInitialization.java b/regressions/src/main/java/net/kemitix/checkstyle/regressions/ExplicitInitialization.java new file mode 100644 index 0000000..322b589 --- /dev/null +++ b/regressions/src/main/java/net/kemitix/checkstyle/regressions/ExplicitInitialization.java @@ -0,0 +1,60 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2017 Paul Campbell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies + * or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package net.kemitix.checkstyle.regressions; + +/** + * Regression demo for {@code ExplicitInitializationCheck}. + * + * @author Paul Campbell (pcampbell@kemitix.net). + */ +@SuppressWarnings("hideutilityclassconstructor") +class ExplicitInitialization { + + /** + * This will become valid in next release. + */ + @SuppressWarnings("explicitinitialization") + private boolean validBoolean = false; + + /** + * This will become valid in next release. + */ + @SuppressWarnings("explicitinitialization") + private int validInt = 0; + + private String validString = ""; + + private Object validObject = new Object(); + + @SuppressWarnings("explicitinitialization") + private Boolean invalidBoolean = null; + + @SuppressWarnings("explicitinitialization") + private Integer invalidInteger = null; + + @SuppressWarnings("explicitinitialization") + private String invalidString = null; + + @SuppressWarnings("explicitinitialization") + private Object invalidObject = null; + +} diff --git a/ruleset/src/main/resources/net/kemitix/checkstyle-1-layout.xml b/ruleset/src/main/resources/net/kemitix/checkstyle-1-layout.xml index c7c3f72..dcb2199 100644 --- a/ruleset/src/main/resources/net/kemitix/checkstyle-1-layout.xml +++ b/ruleset/src/main/resources/net/kemitix/checkstyle-1-layout.xml @@ -4,61 +4,61 @@ "http://www.puppycrawl.com/dtds/configuration_1_3.dtd"> - + - - + + - + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - + + + - - - - - - - + + + + + + + - - - - - - - - - + + + + + + + + + diff --git a/ruleset/src/main/resources/net/kemitix/checkstyle-2-naming.xml b/ruleset/src/main/resources/net/kemitix/checkstyle-2-naming.xml index 040fe94..a4a70a0 100644 --- a/ruleset/src/main/resources/net/kemitix/checkstyle-2-naming.xml +++ b/ruleset/src/main/resources/net/kemitix/checkstyle-2-naming.xml @@ -4,93 +4,93 @@ "http://www.puppycrawl.com/dtds/configuration_1_3.dtd"> - + - - + + - + - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/ruleset/src/main/resources/net/kemitix/checkstyle-3-javadoc.xml b/ruleset/src/main/resources/net/kemitix/checkstyle-3-javadoc.xml index 811e021..5536268 100644 --- a/ruleset/src/main/resources/net/kemitix/checkstyle-3-javadoc.xml +++ b/ruleset/src/main/resources/net/kemitix/checkstyle-3-javadoc.xml @@ -4,119 +4,119 @@ "http://www.puppycrawl.com/dtds/configuration_1_3.dtd"> - + - - + + - - + + - - - + + + - - - - - - + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - + + + - - + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - - - - - - - - + + + + + + + + + + + diff --git a/ruleset/src/main/resources/net/kemitix/checkstyle-4-tweaks.xml b/ruleset/src/main/resources/net/kemitix/checkstyle-4-tweaks.xml index 2e27c90..4a5e460 100644 --- a/ruleset/src/main/resources/net/kemitix/checkstyle-4-tweaks.xml +++ b/ruleset/src/main/resources/net/kemitix/checkstyle-4-tweaks.xml @@ -4,178 +4,178 @@ "http://www.puppycrawl.com/dtds/configuration_1_3.dtd"> - + - - + + - - + + - - - + + + - - - - - - + + + + + + - + - - - - - - - - - + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - + + - - - - + + + + - - + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ruleset/src/main/resources/net/kemitix/checkstyle-5-complexity.xml b/ruleset/src/main/resources/net/kemitix/checkstyle-5-complexity.xml index bc2b68b..7181911 100644 --- a/ruleset/src/main/resources/net/kemitix/checkstyle-5-complexity.xml +++ b/ruleset/src/main/resources/net/kemitix/checkstyle-5-complexity.xml @@ -4,231 +4,231 @@ "http://www.puppycrawl.com/dtds/configuration_1_3.dtd"> - + - - - + + + - - + + - - - + + + - - - - - - - + + + + + + + - + - - - - + + + + - + - - - - - - - - + + + + + + + + - - - - - + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - + + + - + - - + + - - - - - + + + + + - + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - - + + + + + - - + + - - - - - - - - + + + + + + + + - - + + - - - + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sample-parent/pom.xml b/sample-parent/pom.xml index ed2f245..f59ce12 100644 --- a/sample-parent/pom.xml +++ b/sample-parent/pom.xml @@ -14,7 +14,8 @@ Sample parent for modules that use kemitix-checkstyle-ruleset-maven-plugin - 2-naming + ${project.version} + 5-complexity UTF-8 UTF-8 @@ -50,9 +51,9 @@ net.kemitix kemitix-checkstyle-ruleset-maven-plugin - ${project.version} + ${kemitix-checkstyle-ruleset.version} - ${kemitix-checkstyle-ruleset-level} + ${kemitix-checkstyle-ruleset.level} diff --git a/travis-ci/travis-deploy.sh b/travis-ci/travis-deploy.sh index 240dd26..6ff7008 100755 --- a/travis-ci/travis-deploy.sh +++ b/travis-ci/travis-deploy.sh @@ -1,10 +1,18 @@ #!/usr/bin/env bash if [ "$TRAVIS_BRANCH" = 'master' ] && [ "$TRAVIS_PULL_REQUEST" == 'false' ]; then + echo "Preparing to deploy to nexus..." openssl aes-256-cbc -K $encrypted_efec3258f55d_key -iv $encrypted_efec3258f55d_iv \ -in travis-ci/codesigning.asc.enc -out travis-ci/codesigning.asc -d + echo "Signing key decrypted" gpg --batch --fast-import travis-ci/codesigning.asc + echo "Signing key imported" ./mvnw --projects plugin,ruleset --settings travis-ci/travis-settings.xml \ -Dskip-Tests=true -P release -B deploy + echo "Deploy complete" +else + echo "Not deploying" + echo " TRAVIS_BRANCH: $TRAVIS_BRANCH" + echo " TRAVIS_PULL_REQUEST: $TRAVIS_PULL_REQUEST" fi