Checkstyle производит бессмысленные ошибки - как игнорировать / подавлять их [дублировать]

Что вы должны знать о this

this (иначе говоря, «контекст») - это специальное ключевое слово внутри каждой функции, и его значение зависит только от , как была вызвана функция, а не как / когда / где она была определена. Лексические области не затрагиваются, как и другие переменные. Вот несколько примеров:

function foo() {
    console.log(this);
}

// normal function call
foo(); // `this` will refer to `window`

// as object method
var obj = {bar: foo};
obj.bar(); // `this` will refer to `obj`

// as constructor function
new foo(); // `this` will refer to an object that inherits from `foo.prototype`

Чтобы узнать больше о this, просмотрите документацию MDN .


Как сделать обратитесь к правильному this

Не используйте this

Фактически вы не хотите иметь доступ к this в частности, но объект, на который он ссылается на . Вот почему простое решение - просто создать новую переменную, которая также относится к этому объекту. Переменная может иметь любое имя, но общие - self и that.

function MyConstructor(data, transport) {
    this.data = data;
    var self = this;
    transport.on('data', function() {
        alert(self.data);
    });
}

Поскольку self является нормальной переменной, она подчиняется лексическим правилам области и доступна внутри обратного вызова. Это также имеет то преимущество, что вы можете получить доступ к значению this самого обратного вызова.

Явно установить this обратного вызова - часть 1

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

Каждая функция имеет метод .bind [docs] , который возвращает новую функцию с this, привязанную к значению. Функция имеет то же поведение, что и тот, который вы назвали .bind, только то, что this было установлено вами. Независимо от того, как и когда эта функция вызывается, this всегда будет ссылаться на переданное значение.

function MyConstructor(data, transport) {
    this.data = data;
    var boundFunction = (function() { // parenthesis are not necessary
        alert(this.data);             // but might improve readability
    }).bind(this); // <- here we are calling `.bind()` 
    transport.on('data', boundFunction);
}

В этом случае мы привязываем обратный вызов this к значению MyConstructor 's this.

Примечание. При связывании контекста для jQuery вместо этого используйте jQuery.proxy [docs] . Причина этого заключается в том, что вам не нужно сохранять ссылку на функцию при отмене обратного вызова события. jQuery обрабатывает это внутренне.

ECMAScript 6: Используйте функции стрелок

В ECMAScript 6 представлены функции стрелок , которые можно рассматривать как лямбда-функции. У них нет собственной привязки this. Вместо этого this просматривается в области видимости как обычная переменная. Это означает, что вам не нужно называть .bind. Это не единственное особое поведение, которое у них есть. Дополнительную информацию см. В документации MDN.

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', () => alert(this.data));
}

Установите this обратного вызова - часть 2

Некоторые функции / методы, которые принимают обратные вызовы, также принимают значение, к которому должен обращаться обратный вызов this. Это в основном то же самое, что и привязывать его самостоятельно, но функция / метод делает это за вас. Array#map [docs] - такой метод. Его подпись такова:

array.map(callback[, thisArg])

Первый аргумент - это обратный вызов, а второй аргумент - значение this. Вот надуманный пример:

var arr = [1, 2, 3];
var obj = {multiplier: 42};

var new_arr = arr.map(function(v) {
    return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument

Примечание. Можно ли передать значение для this, как правило, упоминается в документации этой функции / метода. Например, метод $.ajax jQuery [docs] описывает параметр, называемый context:

Этот объект станет контекстом всех обратных вызовов, связанных с Ajax.


Общая проблема: использование объектных методов в качестве обработчиков обратных вызовов / событий

Еще одно распространенное проявление этой проблемы - когда объектный метод используется как обработчик обратного вызова / события , Функции являются первоклассными гражданами в JavaScript, а термин «метод» - просто разговорный термин для функции, которая является значением свойства объекта. Но эта функция не имеет конкретной ссылки на ее «содержащий» объект.

Рассмотрим следующий пример:

function Foo() {
    this.data = 42,
    document.body.onclick = this.method;
}

Foo.prototype.method = function() {
    console.log(this.data);
};

Функция this.method назначается как обработчик события click , но если щелкнуть document.body, зарегистрированное значение будет undefined, потому что внутри обработчика события this ссылается на document.body, а не на экземпляр Foo. Как уже упоминалось в начале, то, что относится к [49], зависит от того, как называется функция, а не от того, как она определена. Если код выглядит следующим образом, может быть более очевидно, что функция не имеет неявной ссылки на объект:

function method() {
    console.log(this.data);
}


function Foo() {
    this.data = 42,
    document.body.onclick = this.method;
}

Foo.prototype.method = method;

Решение такое же, как указано выше: если доступно, используйте .bind явно привязать this к определенному значению

document.body.onclick = this.method.bind(this);

или явно вызвать функцию как «метод» объекта, используя анонимную функцию в качестве обработчика обратного вызова / события и назначить object (this) к другой переменной:

var self = this;
document.body.onclick = function() {
    self.method();
};

или использовать функцию стрелки:

document.body.onclick = () => this.method();
143
задан yegor256 17 December 2015 в 13:54
поделиться

6 ответов

Проверьте использование supressionCommentFilter в http://checkstyle.sourceforge.net/config_filters.html#SuppressionCommentFilter . Вам нужно будет добавить модуль в свой checkstyle.xml

<module name="SuppressionCommentFilter"/>

и его можно настроить. Таким образом, вы можете добавлять комментарии к своему коду, чтобы отключить контрольный стиль (на разных уровнях), а затем снова включить его с помощью комментариев в вашем коде. Например,

//CHECKSTYLE:OFF
public void someMethod(String arg1, String arg2, String arg3, String arg4) {
//CHECKSTYLE:ON

Или еще лучше используйте эту более измененную версию:

<module name="SuppressionCommentFilter">
    <property name="offCommentFormat" value="CHECKSTYLE.OFF\: ([\w\|]+)"/>
    <property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)"/>
    <property name="checkFormat" value="$1"/>
</module>

, которая позволяет отключать специальные проверки для определенных строк кода:

//CHECKSTYLE.OFF: IllegalCatch - Much more readable than catching 7 exceptions
catch (Exception e)
//CHECKSTYLE.ON: IllegalCatch

* Примечание: вам также нужно будет добавить FileContentsHolder:

<module name="FileContentsHolder"/>

См. также

<module name="SuppressionFilter">
    <property name="file" value="docs/suppressions.xml"/>
</module>

в разделе SuppressionFilter на той же странице , который позволяет вам отключать отдельные проверки для сопоставленных шаблонов ресурсов.

Итак, если у вас есть в вашем checkstyle.xml:

<module name="ParameterNumber">
   <property name="id" value="maxParameterNumber"/>
   <property name="max" value="3"/>
   <property name="tokens" value="METHOD_DEF"/>
</module>

Вы можете отключить его при подавлении xml-файл с помощью:

<suppress id="maxParameterNumber" files="YourCode.java"/>

Другой способ, доступный в Checkstyle 5.7, заключается в подавлении нарушений с помощью аннотации @SuppressWarnings java. Для этого вам понадобится новые модули (SuppressWarningsFilter и SuppressWarningsHolder) в вашем файле конфигурации:

<module name="Checker">
   ...
   <module name="SuppressWarningsFilter" />
   <module name="TreeWalker">
       ...
       <module name="SuppressWarningsHolder" />
   </module>
</module> 

Затем в коде вы можете сделать следующее:

@SuppressWarnings("checkstyle:methodlength")
public void someLongMethod() throws Exception {

или для множественных подавлений:

@SuppressWarnings({"checkstyle:executablestatementcount", "checkstyle:methodlength"})
public void someLongMethod() throws Exception {

Примечание: префикс «checkstyle:» является необязательным (но рекомендуется). Согласно документам имя параметра должно быть во всех строчных строках, но практика показывает, что любой случай работает.

225
ответ дан tkruse 21 August 2018 в 11:43
поделиться
  • 1
    Не забудьте добавить FileContentsHolder в TreeWalter. См. stackoverflow.com/a/5764666/480483 – djjeck 17 January 2014 в 00:23
  • 2
    если вы используете //CHECKSTYLE.OFF: , а затем забудьте включить его снова, останется ли он оставаться только в файле, содержащем //CHECKSTYLE.OFF: или все последующие обработанные файлы? – Roland 30 September 2014 в 18:58
  • 3
    @Roland, он остается выключенным только на протяжении всего этого тестового класса. – Chris Knight 30 September 2014 в 23:12
  • 4
    «имя параметра должно быть в нижнем регистре». @SuppressWarnings("checkstyle:VariableDeclarationUsageDistance") работал так же хорошо, как и младший эквивалент. – Anders Rabo Thorbeck 5 December 2017 в 14:18
  • 5
    Поскольку checkstyle 8.1 , параметр SuppressionCommentFilter должен находиться под TreeWalker, а FileContentHolder больше не нужен (доступен). – avandeursen 7 April 2018 в 14:26

Если вы предпочитаете использовать аннотации для выборочного отключения правил, теперь это возможно, используя аннотацию @SuppressWarnings, начиная с Checkstyle 5.7 (и поддерживаемая плагином Checkstyle Maven 2.12 +).

Сначала, в checkstyle.xml добавьте модуль SuppressWarningsHolder в TreeWalker:

<module name="TreeWalker">
    <!-- Make the @SuppressWarnings annotations available to Checkstyle -->
    <module name="SuppressWarningsHolder" />
</module>

Затем включите SuppressWarningsFilter там (в качестве брата с TreeWalker):

<!-- Filter out Checkstyle warnings that have been suppressed with the @SuppressWarnings annotation -->
<module name="SuppressWarningsFilter" />

<module name="TreeWalker">
...

Теперь вы можете аннотировать, например метод, который вы хотите исключить из некоторого правила Checkstyle:

@SuppressWarnings("checkstyle:methodlength")
@Override
public boolean equals(Object obj) {
    // very long auto-generated equals() method
}

Префикс checkstyle: в аргументе @SuppressWarnings является необязательным, но мне нравится это как напоминание о том, откуда это предупреждение. Имя правила должно быть строчным.

Наконец, если вы используете Eclipse, он будет жаловаться на неизвестный ему аргумент:

Unsupported @SuppressWarnings ("checkstyle : methodlength ")

Вы можете отключить это предупреждение Eclipse в настройках, если хотите:

Preferences:
  Java
  --> Compiler
  --> Errors/Warnings
  --> Annotations
  --> Unhandled token in '@SuppressWarnings': set to 'Ignore'
50
ответ дан Clay 21 August 2018 в 11:43
поделиться
  • 1
    Я назначаю это как проверенный ответ, так как я думаю, что это решение, которое должно работать лучше всего в большинстве случаев. – avandeursen 7 April 2018 в 14:28

В каждом ответе, относящемся к SuppressWarningsFilter , отсутствует важная деталь. Вы можете использовать только строчный идентификатор, если он определен как таковой в вашем файле checkstyle-config.xml. Если нет, вы должны использовать оригинальное имя модуля.

Например, если в моем checkstyle-config.xml у меня есть:

<module name="NoWhitespaceBefore"/>

Я не могу использовать:

@SuppressWarnings({"nowhitespacebefore"})

Я должен, use:

@SuppressWarnings({"NoWhitespaceBefore"})

Для того, чтобы первый синтаксис работал, checkstyle-config.xml должен иметь:

<module name="NoWhitespaceBefore">
  <property name="id" value="nowhitespacebefore"/>
</module>

Это то, что сработало для меня, по крайней мере, в версия CheckStyle 6.17.

1
ответ дан Joao Baltazar 21 August 2018 в 11:43
поделиться

Что также хорошо работает, это SuppressWithNearbyCommentFilter , который использует отдельные комментарии для подавления событий аудита.

Например

// CHECKSTYLE IGNORE check FOR NEXT 1 LINES
public void onClick(View view) { ... }

Чтобы настроить фильтр так, что CHECKSTYLE IGNORE проверяет СЛЕДУЮЩИЙ var LINES избегает запуска любых проверок для данной проверки для текущей строки и следующих строк var (всего для var + 1 строки):

<module name="SuppressWithNearbyCommentFilter">
    <property name="commentFormat" value="CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINES"/>
    <property name="checkFormat" value="$1"/>
    <property name="influenceFormat" value="$2"/>
</module>

http : //checkstyle.sourceforge.net/config.html

30
ответ дан Ralph 21 August 2018 в 11:43
поделиться
  • 1
    Я бы изменил регулярное выражение на CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINES?, что сделает команду ignore более удобочитаемой. (Вы сможете использовать «CHECKSTYLE IGNORE check FOR NEXT 1 LINE» и «CHECKSTYLE IGNORE check FOR NEXT 3 LINES»). – Matt3o12 28 May 2014 в 18:10
  • 2
    @ matt3o12 CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINE также работает для меня (он соответствует как line, так и lines). – Slava Semushin 22 July 2015 в 08:10
<module name="Checker">
    <module name="SuppressionCommentFilter"/>
    <module name="TreeWalker">
        <module name="FileContentsHolder"/>
    </module>
</module>

Чтобы настроить фильтр для подавления событий аудита между комментарием, содержащим строку BEGIN GENERATED CODE, и комментарий, содержащий строку END GENERATED CODE:

<module name="SuppressionCommentFilter">
  <property name="offCommentFormat" value="BEGIN GENERATED CODE"/>
  <property name="onCommentFormat" value="END GENERATED CODE"/>
</module>

//BEGIN GENERATED CODE
@Override
public boolean equals(Object obj) { ... } // No violation events will be reported

@Override
public int hashCode() { ... } // No violation events will be reported
//END GENERATED CODE

Подробнее

1
ответ дан Roberto Pegoraro 21 August 2018 в 11:43
поделиться
  • 1
    это только опускает предупреждение, но проблемы все еще появляются в аудите ... – viruskimera 28 September 2017 в 16:49

У меня возникли трудности с ответами выше, возможно, потому что я установил предупреждения checkStyle как ошибки. Что делало SuppressionFilter: http://checkstyle.sourceforge.net/config_filters.html#SuppressionFilter

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

1
ответ дан Saltymule 21 August 2018 в 11:43
поделиться
  • 1
    Спасибо, это было единственное, что работало для меня тоже – jonathanrz 16 March 2017 в 01:34
Другие вопросы по тегам:

Похожие вопросы: