Как стать автором
Обновить

Комментарии 22

А как в байткоде представлены отложенные присвоения?

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 ни на что не влияет.
На самом деле сейчас даже не будут анализироваться переменные, для которых переиспользован слот:

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
Было бы интересно добраться до текста это курсовой/дипломной работы.
Там же были перечислены и другие работы на смежные темы.
Любопытно.
Спасибо!
Спасибо за сообщение об ошибке в IntelliJ IDEA,
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.

Есть ещё пара адских штук, но я их приберегу для другой статьи :-)
Спасибо!
Будем ждать :)
На булевских значениях наш анализатор сработал :)
Половина проблем уже зачинена (ещё раз благодарим:), а второй половине в транке уже нет, код поменялся
Продвинул детектор на изменяемые переменные. Ещё такое поймалось:

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.
result = 31 * result + (USE_INTERNAL_SSH_IMPLEMENTATION ? 1 : 0);

Вряд ли USE_INTERNAL_SSH_IMPLEMENTATION здесь будет истинно, выше был выход. Так что тут просто текущий hashCode умножается на 31.
благодарим, зачинили
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации