Когда Sonar TryStatementTree # resourceList возвращает дерево, которое не является VariableTree? - PullRequest
0 голосов
/ 09 апреля 2020

Я столкнулся с интерфейсом org.sonar.plugins.java.api.tree.TryStatementTree, когда просматривал код для плагина SonarQube. Одно из реализованных правил касается переменных, определенных в блоке try-with-resources.

Глядя на TryStatementTree#resourceList, я вижу, что он возвращает ListTree<Tree>. Это можно повторить несколькими способами. В одном случае плагин проверяет имя объявленной переменной. Когда это происходит, Tree приводится к VariableTree, потому что Tree является более универсальным c интерфейсом, который не обеспечивает доступ к именам переменных через IdentifierTree.

. Здесь приведение в коде, который я смотрю, класс, который расширяет BaseTreeVisitor и реализует JavaFileScanner.

@Override
public void visitTryStatement(TryStatementTree tree) {
  // ...
  tree.resourceList().stream()
     .filter(resource -> resource instanceof VariableTree) // Is it possible for this condition to evaluate to false? 
     .map(VariableTree.class::cast)
     .map(resource -> resource.simpleName().name())
     .forEach(SomeClass::handleThisCase);
  // ...
}

Глядя на Java Стандарт языка , я могу Я не думаю о ситуации, когда в операторе try вместо объявления ресурса будет что-то, что не является списком идентификаторов.

Я думал, что это связано с необходимостью представлять не представить определения ресурсов или что-то подобное, поэтому я бросил несколько примеров модульных тестов.

try { // No resource declaration here
  // ...
} catch (SomeException ex) {
  // ...
}

но в этом случае метод вообще не вызывается, который, я думаю, обрабатывается BaseTreeVisitor.

Я пытался найти примеры, которые бы сделать приведение невозможным, но все, что я придумал, либо не компилируется, либо никогда не следует этому пути выполнения.

Мне не хватает способа написать оператор try, который делает более обобщенным c Tree лучший выбор? Или этот выбор проистекает из того, как структурированы интерфейсы в библиотеке? Кажется, он не поддерживается ни одним из суперинтерфейсов (TryStatementTree -> StatementTree -> Tree). resourceList определяется самим TryStatementTree.

1 Ответ

0 голосов
/ 09 апреля 2020

Как ни странно, я наткнулся на ответ в документации SonarQube * через 1002 * минуты после публикации вопроса.

Оказывается, есть метод, который работает именно так, как я ожидал, TryStatementTree#resource , который был устарел и затем удален в пользу TryStatementTree#resourceList, что именно то, что использует мой код.

Устаревший метод org.sonar.plugins.java.api.tree.TryStatementTree.resources() удален в пользу org.sonar.plugins.java.api.tree.TryStatementTree.resourceList(), поскольку Java 9 позволяет другим деревьям, кроме VariableTree, размещаться в качестве ресурсов в операторах try-with-resources.

Вот пример:

SomeAutoCloseableClass myResource = obtainOneSomehow();
try (myResurce) { // No resource declaration here, just an identifier
  // ...
} catch (SomeException ex) {
  // ...
}

Мой проект скомпилирован с исходным уровнем совместимости Java 8, который должен быть исправлен, и в него должен быть добавлен новый пример модульного теста убедитесь, что новый возможный способ записи блока try-with-resources обработан.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...