Comments 22
А как в байткоде представлены отложенные присвоения?
Будет ли анализатор рассматривать эту переменную, в качестве константы? А если без final?
final int a;
if (...) a = 5; else a = 6;
Будет ли анализатор рассматривать эту переменную, в качестве константы? А если без final?
Информация о том, что локальная переменная была объявлена как final в байткоде не сохранится. Эта информация сохраняется только для полей класса.
Присвоения будут выглядеть так же, как и любые другие присвоения локальной переменной:
Присвоения будут выглядеть так же, как и любые другие присвоения локальной переменной:
byte byte0;
if(args.length > 0)
//* 0 0:aload_0
//* 1 1:arraylength
//* 2 2:ifle 10
{
byte0 = 5;
// 3 5:iconst_5
// 4 6:istore_1
} else
//* 5 7:goto 13
{
byte0 = 6;
// 6 10:bipush 6
// 7 12:istore_1
}
Пока не будет. Со временем доберёмся. Наличие слова final ни на что не влияет.
На самом деле сейчас даже не будут анализироваться переменные, для которых переиспользован слот:
В байткоде a и b попадут в один слот, поэтому будет два присваивания. С этим тоже со временем разберёмся.
if(...) {
int a = ...
} else {
char b = ...
}
В байткоде a и b попадут в один слот, поэтому будет два присваивания. С этим тоже со временем разберёмся.
Ну вот, переделал всё: теперь по факту отслеживаются не переменные, а значения. Обрабатывается не только ваш случай и переиспользование слота, но и даже изменяемые переменные, если в процессе цепочки проверок гарантированно изменений не было. В том числе итерации цикла типа:
Причём проверки устойчивы к переброске значений из одной переменной в другую:
Оказалось, это проще, чем я думал.
public void testLoop() {
for(int i=0; i<10; i++) {
if(i < 10) { // бесполезно
System.out.println("i < 10");
}
}
}
Причём проверки устойчивы к переброске значений из одной переменной в другую:
public int testPassVariable(int a) {
if (a < 0) {
return a;
}
int b = a;
if (b >= 0) { // всегда истинно
return 1;
}
return 2; // мёртвый код
}
Оказалось, это проще, чем я думал.
Кстати, о finally-блоках:
Стажёры в Excelsior делали что-то подобное в далёком 2009-ом: http://www.excelsior.ru/internship/degreeworks#Toc_ExcDecomp
Было бы интересно добраться до текста это курсовой/дипломной работы.
Там же были перечислены и другие работы на смежные темы.
Стажёры в Excelsior делали что-то подобное в далёком 2009-ом: http://www.excelsior.ru/internship/degreeworks#Toc_ExcDecomp
Было бы интересно добраться до текста это курсовой/дипломной работы.
Там же были перечислены и другие работы на смежные темы.
Любопытно.
Судя по всему, вот она: http://www.system-informatics.ru/ru/article/43 (доступен полный текст)
Спасибо за сообщение об ошибке в IntelliJ IDEA,
SegmentArrayWithData#setElementAt мы поправили, на настоящий момент сделали исправление три раза :)
SegmentArrayWithData#setElementAt мы поправили, на настоящий момент сделали исправление три раза :)
:-) Так ваш собственный анализатор такое подсвечивает, я же правильно помню?
по умолчанию пока нет
Тогда гляньте ещё setSegmentData в том же классе, если не заметили.
И вот ещё что нашлось (возможно, у меня не последняя версия и строчки могли уехать):
com.intellij.execution.actions.ChooseRunConfigurationPopup.getSeparatorAbove(ItemWrapper value) (строка 669): index == 0 бессмысленно
com.intellij.ui.tabs.impl.DarculaEditorTabsPainter.paintSelectionAndBorder(...) (строка 127, 130): horizontalTabs? 2: 1 бессмысленно, так как выше if(!horizontalTabs)
com.intellij.ui.tabs.impl.DefaultEditorTabsPainter.paintSelectionAndBorder(...) (строка 158, 161): копипаста того же самого
com.jetbrains.python.codeInsight.editorActions.moveUpDown.PyStatementMover.moveOutsideFile (строка 126) lineNumber < 0? 0: бессмысленно.
Это всё, что создаёт мёртвый код. Ещё 8 сработок без мёртвого кода, там в основном перестраховочные условия.
Бонус из другого детектора, который я написал:
org.jetbrains.idea.svn.portable.JavaHLSvnStatusClient.doStatus(...) (строки 144, 147 в самом конце файла): обращение statusArr[0] вызовет гарантированное ArrayIndexOutOfBoundsException на рантайме: длина массива 0, а не 1.
Есть ещё пара адских штук, но я их приберегу для другой статьи :-)
И вот ещё что нашлось (возможно, у меня не последняя версия и строчки могли уехать):
com.intellij.execution.actions.ChooseRunConfigurationPopup.getSeparatorAbove(ItemWrapper value) (строка 669): index == 0 бессмысленно
com.intellij.ui.tabs.impl.DarculaEditorTabsPainter.paintSelectionAndBorder(...) (строка 127, 130): horizontalTabs? 2: 1 бессмысленно, так как выше if(!horizontalTabs)
com.intellij.ui.tabs.impl.DefaultEditorTabsPainter.paintSelectionAndBorder(...) (строка 158, 161): копипаста того же самого
com.jetbrains.python.codeInsight.editorActions.moveUpDown.PyStatementMover.moveOutsideFile (строка 126) lineNumber < 0? 0: бессмысленно.
Это всё, что создаёт мёртвый код. Ещё 8 сработок без мёртвого кода, там в основном перестраховочные условия.
Бонус из другого детектора, который я написал:
org.jetbrains.idea.svn.portable.JavaHLSvnStatusClient.doStatus(...) (строки 144, 147 в самом конце файла): обращение statusArr[0] вызовет гарантированное ArrayIndexOutOfBoundsException на рантайме: длина массива 0, а не 1.
Есть ещё пара адских штук, но я их приберегу для другой статьи :-)
Спасибо!
Будем ждать :)
Будем ждать :)
На булевских значениях наш анализатор сработал :)
Половина проблем уже зачинена (ещё раз благодарим:), а второй половине в транке уже нет, код поменялся
Продвинул детектор на изменяемые переменные. Ещё такое поймалось:
DTDModelLoader#processDTD:
Средний else никогда не выполнится. Возможно, перепутали || и &&, но надо разбираться.
DTDModelLoader#processDTD:
if (hasAttrFields || hasTextContents) {
...
} else if (hasTextContents) {
...
} else {
...
}
Средний else никогда не выполнится. Возможно, перепутали || и &&, но надо разбираться.
зачинили, спасибо
Прикрутил ещё несколько фишек, в частности, слежение за длиной массива. В IDEA в основном неаккуратности всякие поймались. Например, вот: EnterAction#update:
VirtualFile[] selection = view.getSelection();
if (selection.length > 0) {
if (selection.length == 1 && selection[0].isDirectory()) {
presentation.setVisible(true);
} else if (selection.length > 0) { // бессмысленно
...
} else { // мёртвый код
presentation.setVisible(false);
presentation.setEnabled(false);
}
} else {
presentation.setVisible(false);
presentation.setEnabled(false);
}
Понятно, что в данном случае проблем не вызывает, но раз уж вы всё чините, то и это исправьте :-)готово, спасибо большое
Обработку полей прикручиваю, с ней, конечно, сложнее всё и реже что-то удаётся поймать. Ну вот, например: ExtConfiguration#hashCode.
Вряд ли USE_INTERNAL_SSH_IMPLEMENTATION здесь будет истинно, выше был выход. Так что тут просто текущий hashCode умножается на 31.
result = 31 * result + (USE_INTERNAL_SSH_IMPLEMENTATION ? 1 : 0);
Вряд ли USE_INTERNAL_SSH_IMPLEMENTATION здесь будет истинно, выше был выход. Так что тут просто текущий hashCode умножается на 31.
Sign up to leave a comment.
Контроль диапазонов целых чисел в FindBugs