Как показать полную информацию об ошибках компиляции в Checker FrameWork с номерами строк и т. Д.
Я только начал использовать Checker Framework, и у меня возникла проблема, которая точно воспроизводится в одном из примеров проектов от авторов этого фреймворка. Этот проект доступен здесь: https://github.com/typetools/checker-framework/tree/master/docs/examples/GradleExamples
Когда я запускаю эту команду из корня:
>gradle compileJava
я получаю этот вывод компиляции:
public static /*@Nullable*/ Object nullable = null;
^
required: @Initialized @NonNull Object
list.add(null); // error on this line
^
required: @Initialized @NonNull String
2 errors
:compileJava FAILED
Как вы можете видеть, нет никакой информации о том, где происходят ошибки, такие как имя класса, номер строки в коде и т. Д. В их официальном руководстве я не нашел никакой информации о параметрах компилятора, которые могли бы соответствующим образом изменить формат вывода. Я хочу, чтобы сообщения об ошибках выглядели так:
~\GradleExample.java:33 error: ';' expected
ОБНОВИТЬ:
Я добиваюсь такого поведения на 3 машинах:
- ОС: Microsoft Windows 7 x64 Ultimate SP1 [версия 6.1.7601];
- Java: 1.8.0_73;
- Gradle: 2.14.
- ОС: Microsoft Windows 10 x64 Pro [версия 10.0.14393];
- Java: 1.8.0_121;
- Gradle: 3.4.1.
- ОС: Microsoft Windows 7 x64 Ultimate SP1 [версия 6.1.7601];
- Java: 1.8.0_121;
- Gradle: 3.4.1.
Отсутствие номеров строк и имен классов происходит только при работе с Gradle. Я также пытался запустить средство проверки с Maven и Javac из командной строки, и это работало отлично.
Чтобы настроить Checker Framework с Gradle, я следовал инструкциям из руководства. Есть 3 шага:
- Скачать фреймворк;
- Разархивируйте его, чтобы создать директорию checker-framework;
- Настройте Gradle для включения Checker Framework в путь к классам.
Как я понимаю, Gradle будет выполнять шаги 1 и 2 автоматически при предоставлении необходимых файлов Checker Framework посредством управления зависимостями. Тем не менее я попробовал оба варианта:
- управление зависимостями:
Я просто скачал пример проекта и выполнил "gradle compileJava" из корня проекта GradleJava7Example. - ручная запись путей в файле сборки Gradle:
allprojects {
tasks.withType(JavaCompile).all { JavaCompile compile ->
compile.options.compilerArgs = [
'-processor', 'org.checkerframework.checker.nullness.NullnessChecker',
'-processorpath', "C:\\checker-framework-2.1.10\\checker\\dist\\checker.jar",
"-Xbootclasspath/p:C:\\checker-framework-2.1.10\\checker\\dist\\jdk8.jar",
'-classpath', 'C:\\checker-framework-2.1.10\\checker\\dist\\checker.jar;C:\\checker-framework-2.1.10\\checker\\dist\\javac.jar'
]
}
}
1 ответ
Я нашел обходной путь. Я объясню это позже, но теперь, если у кого-то есть такая же проблема, добавьте эту строку в конфигурацию задач JavaCompile:
allprojects {
tasks.withType(JavaCompile).all { JavaCompile compile ->
System.setProperty("line.separator", "\n") // <<<<<< add this line
compile.options.compilerArgs = [
'-processor', 'org.checkerframework.checker.nullness.NullnessChecker',
'-processorpath', "${configurations.checkerFramework.asPath}",
"-Xbootclasspath/p:${configurations.checkerFrameworkAnnotatedJDK.asPath}"
]
}
}
Прежде всего, я должен сказать, что проблема не была в Checker Framework вообще. Мне удалось воспроизвести такое же поведение, как упомянуто в вопросе, без Checker Framework. Я создал небольшой пользовательский процессор аннотаций. Вот код:
@SupportedSourceVersion(value = SourceVersion.RELEASE_8)
@SupportedAnnotationTypes(value = {"*"})
public class MyProcessor extends AbstractProcessor{
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
String sepr = System.getProperty("line.separator");
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "[error code] " + sepr + " catched!!!");
return true;
}
}
Как видите, все, что он делает, это печатает сообщение сразу же после запуска. Обратите внимание, что я использовал разделитель строк, предоставленный java.lang.System
класс для разделения сообщения. Когда я зарегистрировал этот процессор и попытался запустить "gradle compileJava" из проекта gradle, он выдал следующий вывод:
:compileJava
catched!!!
1 error
:compileJava FAILED
Свойство "line.separator" для ОС Windows возвращает CR+LF: "\r\n". Я не знаю почему Messager.printMessage(Diagnostic.Kind kind, CharSequence msg)
имеет такое поведение, потому что, когда я печатаю System.err.print("[error code] " + sepr + " catched!!!")
вместо этого все работает нормально (обратите внимание также, что эта проблема возникает только тогда, когда я использую Gradle, если я запускаю javac вручную со всеми аргументами или использую Maven, все в порядке).
Я обнаружил, что если я заменил предоставленный системным разделителем простой символ "\n", то сообщения об ошибках компилятора будут отображаться правильно. Пока я выбираю это решение в качестве обходного пути.