Все для той же цели, для которой я рисерчил ответ на вопрос, как компилить код java в рантайме я рисерчу ответы и на этот вопрос: как мне этот код еще и провалидировать. Чем можно валидировать? PMD, CheckStyle, FindBug, и т.д. - их очень много. Решил я начать с CheckStyle.
Качаем CheckStyle - нам нужен jar файл. Как описано тут, чекать свой класс на наличие всяких глюков надо так (из папки с jar)
Подключим к своему Maven проекту CheckStyle
Качаем CheckStyle - нам нужен jar файл. Как описано тут, чекать свой класс на наличие всяких глюков надо так (из папки с jar)
java -cp checkstyle-5.6-all.jar com.puppycrawl.tools.checkstyle.Main -c sun_checks.xml JavaClass.javaВ результате я увижу такое.
Starting audit... D:\checkstyle-5.6-src\bin\JavaClass.java:0: Missing package-info.java file. D:\checkstyle-5.6-src\bin\JavaClass.java:7: First sentence should end with a period. D:\checkstyle-5.6-src\bin\JavaClass.java:13:5: Missing a Javadoc comment. D:\checkstyle-5.6-src\bin\JavaClass.java:15:5: Missing a Javadoc comment. D:\checkstyle-5.6-src\bin\JavaClass.java:15:22: Parameter clazz should be final. D:\checkstyle-5.6-src\bin\JavaClass.java:15:28: 'clazz' hides a field. D:\checkstyle-5.6-src\bin\JavaClass.java:19:5: Method 'newInstance' is not designed for extension - needs to be abstract, final or empty. D:\checkstyle-5.6-src\bin\JavaClass.java:19:5: Missing a Javadoc comment. D:\checkstyle-5.6-src\bin\JavaClass.java:19:31: Parameter constructorArgs should be final. D:\checkstyle-5.6-src\bin\JavaClass.java:21: Line is longer than 80 characters (found 96). D:\checkstyle-5.6-src\bin\JavaClass.java:30: Line is longer than 80 characters (found 109). ... Audit done.Супер! Это уже что-то. Я теперь хоть знаю, где находится точка входа. Класс com.puppycrawl.tools.checkstyle.Main. А потому я открою исходники и посмотрю что там...
Подключим к своему Maven проекту CheckStyle
<dependency>
<groupId>checkstyle</groupId>
<artifactId>checkstyle</artifactId>
<version>5.0</version>
</dependency>
После, по образу и подобию написанного в com.puppycrawl.tools.checkstyle.Main, напишем свой раннер
import com.puppycrawl.tools.checkstyle.ConfigurationLoader;
import com.puppycrawl.tools.checkstyle.DefaultLogger;
import com.puppycrawl.tools.checkstyle.PropertiesExpander;
import com.puppycrawl.tools.checkstyle.api.AuditListener;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.Configuration;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.*;
public class Checker {
public List<String> checkstyle(String configFile, String javaFile) throws CheckstyleException {
StringListOutputStream out = new StringListOutputStream();
AuditListener listener = new DefaultLogger(out, true);
Configuration config = ConfigurationLoader.loadConfiguration(getPath(configFile),
new PropertiesExpander(System.getProperties()));
com.puppycrawl.tools.checkstyle.Checker checker = createChecker(config, listener);
int numErrs = checker.process(Arrays.asList(new File(javaFile)));
checker.destroy();
return out.getResult();
}
private String getPath(String name) {
return getClass().getClassLoader().getResource(name).getPath();
}
private com.puppycrawl.tools.checkstyle.Checker createChecker(Configuration aConfig, AuditListener aNosy) {
com.puppycrawl.tools.checkstyle.Checker c = null;
try {
c = new com.puppycrawl.tools.checkstyle.Checker();
final ClassLoader moduleClassLoader = com.puppycrawl.tools.checkstyle.Checker.class.getClassLoader();
c.setModuleClassLoader(moduleClassLoader);
c.configure(aConfig);
c.addListener(aNosy);
} catch (final Exception e) {
System.out.println("Unable to create Checker: " + e.getMessage());
e.printStackTrace(System.out);
}
return c;
}
}
class StringListOutputStream extends ByteArrayOutputStream {
public List<String> getResult() {
return Arrays.asList(new String(toByteArray()).split("\\r\\n"));
}
}
И воспользуемся им.
@Test
public void test() throws CheckstyleException {
String configFile = "sun_checks.xml";
String javaFile = "src/main/java/apofig/checker/Checker.java";
List<String> result = new Checker().checkFile(configFile, javaFile);
assertEquals(19, result.size());
assertEquals("[Starting audit..., " +
"D:\\CodeChecker\\src\\main\\java\\apofig\\checker\\Checker.java:0: Missing package-info.java file., " +
"D:\\CodeChecker\\src\\main\\java\\apofig\\checker\\Checker.java:14: First sentence should end with a period., " +
"D:\\CodeChecker\\src\\main\\java\\apofig\\checker\\Checker.java:21: Line is longer than 80 characters., " +
"D:\\CodeChecker\\src\\main\\java\\apofig\\checker\\Checker.java:21:5: Method 'checkstyle' is not designed for extension - needs to be abstract, final or empty., " +
...
"Audit done.]\n", result.toString());
}
Дальше дело за настройкой конфига... Еще я сделал одну версию метода, который работает с классом но в строке. Дело в том, что checkstyle работает с файлами, а потому мне пришлось временно создать файл из строки и указать на него checkstyle.
@Test
public void testCheckstyleText() throws CheckstyleException {
String configFile = "sun_checks.xml";
String javaClass =
"package apofig.checker;\n" +
"\n" +
"import java.io.ByteArrayOutputStream;\n" +
"import java.util.Arrays;\n" +
"import java.util.List;\n" +
"\n" +
"/**\n" +
" * User: oleksandr.baglai\n" +
" * Date: 1/19/13\n" +
" * Time: 12:55 AM\n" +
" */\n" +
"public class StringListOutputStream extends ByteArrayOutputStream {\n" +
"\n" +
" public List<String> getResult() {\n" +
" return Arrays.asList(new String(toByteArray()).split(\"\\\\r\\\\n\"));\n" +
" }\n" +
"\n" +
"}";
List<String> result = new CheckstyleChecker().checkString(configFile, javaClass);
assertEquals(7, result.size());
assertEquals("[Starting audit..., " +
"class:0: File does not end with a newline., " +
"class:0: Missing package-info.java file., " +
"class:7: First sentence should end with a period., " +
"class:14:5: Method 'getResult' is not designed for extension - needs to be abstract, final or empty., " +
"class:14:5: Missing a Javadoc comment., " +
"Audit done.]", result.toString());
}
Вот исходники сырого проекта, если кому надо. Может пригодится...

Комментариев нет:
Отправить комментарий