Типы предупреждений

Предупреждения, основанные на анализе абстрактного синтаксического дерева

BAD_COPY_PASTE

Описание ошибки

Код был скопирован и размножен, однако были внесены не все необходимые изменения.

Пример

В данном примере в скопированном фрагменте кода необходимо заменить sep на end

object sep = AttrCollectionPop(kwargs, "sep", " ");

if (sep != null && !(sep is string)) {
    throw PythonOps.TypeError(
        "sep must be None or str, not {0}",
        PythonTypeOps.GetName(sep));
}

object end = AttrCollectionPop(kwargs, "end", "\n");

if (sep != null && !(sep is string)) { // Should be end, not sep
    throw PythonOps.TypeError(
        "end must be None or str, not {0}",
        PythonTypeOps.GetName(end));
}

Обнаружено в IronPython

NO_BASE_CALL

Описание ошибки

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

Подкатегории

WRONG_COMPARISON

Oписание ошибки

После того, как значение было получено при помощи оператора as, с null вместо полученного сравнивается исходное значение.

Пример

var right = other as PredicateNullness;
if (other != null) // Should be "if (right != null)"
{
    if (this.value == right.value)
    {
        return this;
    }
}

Обнаружено в CodeContracts

VALUE_NULL_COMPARISON

Oписание ошибки

Выражение может принадлежать к value-типу, но сравнивается с null.

Пример

public static int GetHashCode<T>(T[] a)
{
    if (a == null)
        return 0;
    const int prime = 31;
    int hash = 17;
    foreach (var item in a)
    {
        // item is T, and T may be a value type
        hash = hash * 23 + (item == null ? 0 : item.GetHashCode());
    }
    return hash;
}

Обнаружено в Lucene.NET

CONDITIONAL_ASSIGN

Oписание ошибки

Внутри условия используется оператор присваивания (=). Это может быть опечаткой, поскольку оператор равенства (==) используется внутри условий значительно чаще. Такая диагностика наиболее актуальна в процессе написания кода для ускорения исправления опечаток.

INVARIANT_RESULT

Описание ошибки

Значение выражения не зависит от значений составляющих его частей или часть выражения может быть опущена без изменения результата.

Пример

В данном примере выражение foo[s+6]&0xff и аналогичные не имеют смысла, поскольку аргумент foo имеет тип byte[], а значение побайтового AND для любого значения a типа byte и 0xFF равно a.

internal override void write(byte[] foo, int s, int l) 
{
    .......
    int plen=(foo[s+6]&0xff)*256+(foo[s+7]&0xff);
    int dlen=(foo[s+8]&0xff)*256+(foo[s+9]&0xff);
    .......
}

Обнаружено в CSharpUtils.NET

EMPTY_CATCH

Описание ошибки

Блок catch пуст.

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

EMPTY_INTERFACE

Описание ошибки

Интерфейс не содержит ни одного члена. Пустые интерфейсы считаются антипаттерном.

FLOATING_POINT_EQUALITY

Подкатегории

Описание ошибки

Числа с плавающей точкой сравниваются на точное равенство.

В связи с ошибками округления, вызванными ограниченной точностью чисел с плавающей запятой, результаты операций с ними слегка неточны. Когда неточности невелики, это не является проблемой. Однако ожидания точного равенства при вычислении значений разными способами некорректно. Поэтому необходимо использовать другие способы, например, сравнение разности чисел с допустимой погрешностью.

Пример

public static Boolean operator ==(ComplexNumber c1, ComplexNumber c2)
{
    bool bEqual = false;
    if ((c1._realPart == c2._realPart) &&
            (c1._imaginaryPart == c2._imaginaryPart))
        bEqual = true;
    return bEqual;
}

Обнаружено в MathOS

HIDDEN_MEMBER

Описание ошибки

Имя локальной переменной или параметра метода “закрывает” другую переменную или поле класса с таким же именем.

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

Пример

public partial class AddAccountWizardForm : Form
{
    ...
    private Step m_CurrStep = Step.Screen1;
    ...
    private bool ValidateFields(Step m_CurrStep)
    {
        ...
    }
    ...
}

Обнаружено в MailSystem.NET

SIMILAR_BRANCHES

Подкатегории

Описание ошибки

В условном операторе исполняется одинаковый код при разных условиях (например, true- и false- ветви оператора if идентичны).

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

Пример

if (negx && negy) {
    return new BigInteger(-1, makeTwosComplement(zd));
} else if (negx || negy) {
    return new BigInteger(+1, zd);
} else {
    return new BigInteger(+1, zd);
}

Обнаружено в IronPython

IDENTICAL_METHOD_BODY

Описание ошибки

Несколько методов обладают одинаковой реализацией.

Пример

public static object GetCharArrayValue(_Array arr) {
    return arr.NativeType.GetValue(arr._memHolder, arr, 0, false);
}
public static object GetWCharArrayValue(_Array arr) {
    return arr.NativeType.GetValue(arr._memHolder, arr, 0, false);
}

Обнаружено в IronPython

INCOMPLETE_SWITCH

Описание ошибки

В switch рассмотрены не все возможные варианты значений аргумента.

Пример

public enum TraceEventKind {
    FrameEnter,
    FrameExit,
    ThreadExit,
    TracePoint,
    Exception,
    ExceptionUnwind
}
....
Debugging.TraceEventKind kind = ...
....
switch (kind) {
    case Debugging.TraceEventKind.FrameEnter: traceEvent = "call"; break;
    case Debugging.TraceEventKind.TracePoint: traceEvent = "line"; break;
    case Debugging.TraceEventKind.Exception:
        traceEvent = "exception";
        object pyException = PythonExceptions.ToPython((Exception)payload);
        object pyType = ((IPythonObject)pyException).PythonType;
        args = PythonTuple.MakeTuple(pyType, pyException, null);
        break;
    case Debugging.TraceEventKind.FrameExit:
        traceEvent = "return";
        args = payload;
        break;
}

Обнаружено в IronPython

INCORRECT_INIT

Описание ошибки

Статическое поле используется до инициализации.

Пример

public static readonly WeakReference WeakMissingConstant = new WeakReference(
    StrongMissingConstant);
private static readonly object StrongMissingConstant = new object();

Обнаружено в IronRuby

INCORRECT_REFEQUALS

Описание ошибки

Хотя бы один аргумент вызова ReferenceEquals не является ссылочным типом.

Пример

public struct Polynomial<Variable, Expression>
{
    ...
}
...
Polynomial<BoxedVariable<Variable>, BoxedExpression> pol;
...
Contract.Assume(!object.ReferenceEquals(pol, null));

Обнаружено в CodeContracts

INFINITE_LOOP

Подкатегории

Описание ошибки

Бесконечный цикл из-за ошибки при обновлении переменной цикла либо из-за обновления неправильной переменной.

Пример

Здесь требуется исправить i > stop на i < stop или i += step на i -= step

for (int i = start; i > stop; i += step) {
    pa._data.Append(_data.GetData(i));
}

Обнаружено в IronPython

Здесь требуется исправить i++ на j++

for (int j = 0; j < n; i++) {
    Cache.Integers[n - j - 1] = Reader.ReadInt32();
}

Обнаружено в OpenBVE

ITERATED_ONCE

Описание ошибки

Цикл содержит break или return без условий, и поэтому исполняется только один раз.

MATH_CONSTANTS

Описание ошибки

Вместо библиотечных констант используются явно заданные численные значения

Пример

В данном случае вместо 6.28318531 следовало использовать 2 * Math.PI

if (Math.Abs(InitialAngle - LastAngle) > 6.28318531) {
    ...
}

Обнаружено в OpenBVE

MISSING_THROW

Описание ошибки

Исключение создается, но оператор throw пропущен.

Пример

try
{
    mxRecords = GetMxRecords(domain);
}
catch
{
    new Exception("Can't connect to DNS server.");
}

Обнаружено в MailSystem.NET

MISSING_VOLATILE

Описание ошибки

Изменение значения поля, объявленного без оператора volatile, может произойти только в другом потоке. Условие может быть упрощено.

Пример

В данном примере цикл с условием globalState.DoneCount != globalState.Threads.Count имеет пустое тело, в связи с чем он может быть оптимизирован.

class DictThreadGlobalState {
    public int DoneCount;
    public List<Thread> Threads = new List<Thread>();
    ...
}
...
while (globalState.DoneCount != globalState.Threads.Count) {
    // wait for threads to get back to start point
}

Обнаружено в IronPython

CONFUSING_INDENTATION

Описание ошибки

Код отформатирован таким образом, что при чтении создается неправильное представление о его структуре.

Пример

В данном примере из-за неправильной индентации создается впечатление, что return true; происходит, только если вызов slot.TryGetValue(context, instance, this, out newValue) вернул true.

if (dt.TryLookupSlot(context, name, out slot)) {
    if (!hasValue || slot.IsSetDescriptor(context, this)) {
        if (slot.TryGetValue(context, instance, this, out newValue))
            value = newValue;
            return true;
    }
}

Обнаружено в IronPython

WRONG_LOCK.STATIC

Описание ошибки

При обращении к статическому полю используется lock на объект, не являющийся статическим.

Пример

public sealed class Profiler {
    private static int _Index;
    private readonly Dictionary<string, int> _counters;
    public int GetTickIndex(string name) {
        lock (_counters) {
            if (!_counters.TryGetValue(name, out index)) {
                index = _Index++;
                _counters.Add(name, index);
            }
            ...
        }
        ...
    }
    ...
}

Обнаружено в IronRuby

OBSOLETE_CRYPTO

Описание ошибки

Используются устаревшие криптографические алгоритмы.

OMITTED_RETURN_VALUE

Описание ошибки

Значение, возвращенное константным методом, проигнорировано.

Пример

try {
    ...
} catch (Exception e) {
    e.ToString();
    errors = true;
    throw;
}

Обнаружено в NAnt

NO_CAST.INTEGER_DIVISION

Описание ошибки

Непреднамеренная потеря арифметической точности из-за целочисленного деления.

Пример

decimal a, b, r;
int n = x.Count();
...
a = (1 / n) * sY - b * (1 / n) * sX;

Обнаружено в MathOS

NO_CAST.INTEGER_OVERFLOW

Описание ошибки

Целочисленное переполнение может произойти до расширения типа.

Пример

internal virtual long BaseRamBytesUsed()
{
    return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER +
           2 * RamUsageEstimator.NUM_BYTES_OBJECT_REF +
           2 * RamUsageEstimator.NUM_BYTES_INT +
           2 * RamUsageEstimator.NUM_BYTES_INT +
           RamUsageEstimator.NUM_BYTES_FLOAT +
           RamUsageEstimator.NUM_BYTES_LONG;
}

Обнаружено в Lucene.NET

REAL_INT_COMP

Описание ошибки

В сравнении смешаны целочисленные значения и значения с плавающей точкой.

RETURN_USING

Описание ошибки

Объект, реализующий интерфейс IDisposable, возвращается внутри блока using.

Пример

public static MemoryStream SerializeToStream(object o)
{
    using (var stream = new MemoryStream())
    {
        Formatter.Serialize(stream, o);
        return stream;
    }
}

Обнаружено в Lucene.NET

SAME_RETURN

Описание ошибки

Метод всегда возвращает одно и то же значение.

SELF_ASSIGN

Описание ошибки

Переменная присваивается сама себе.

WRONG_SEMICOLON

Описание ошибки

Точка с запятой стоит в неожиданном месте (например, после условия if до начала предполагаемого блока).

Пример

if (!BinaryUpdates.TryGetValue(update.Field, out fieldUpdates)) ;
{
    fieldUpdates = new HashMap<Term, BinaryDocValuesUpdate>();
    BinaryUpdates[update.Field] = fieldUpdates;
    BytesUsed.AddAndGet(BYTES_PER_BINARY_FIELD_ENTRY);
}

Обнаружено в Lucene.NET

STRING_CONCAT

Описание ошибки

Конкатенация строк внутри цикла неэффективна, следует использовать string.Join или StringBuilder.

var pluginStates = string.Format(
    "plugin states: ({0} in total)", this.otherStates.Length);
if (this.otherStates.Length > 0)
{
    foreach (var state in this.otherStates)
    {
        var str = state.ToString();
        pluginStates += Environment.NewLine + str;
    }
}

Обнаружено в CodeContracts

STRING_FORMAT

Описание ошибки

Ошибка форматирования строки.

Пример

В данном случае в форматной строке присутствуют индексы от 0 до 5, а аргументов 7.

public override string ToString()
{
    return String.Format(
        "Preconditions:\n{0}\nPostconditions:\n{1}\nObjectInvariants:\n{2}\n"
        "EntryAssumes:{3}\nCalleeAssumes:{4}MayReturnNull{5}",
      JoinWithDefaultIfNull("\n", this.PreConditions),
      JoinWithDefaultIfNull("\n", this.PostConditions),
      JoinWithDefaultIfNull("\n", this.ObjectInvariants),
      JoinWithDefaultIfNull("\n", this.NonNullFields),
      JoinWithDefaultIfNull("\n", this.EntryAssumes),
      JoinWithDefaultIfNull("\n", this.CalleeAssumes),
      this.MayReturnNull);
}

Обнаружено в CodeContracts

SUSPICIOUS_CAST

Описание ошибки

Приведение типов выглядит подозрительно.

WRONG_ARGUMENTS_ORDER

Описание ошибки

Аргументы метода переданы в неправильном порядке.

Пример

В данном примере перепутаны местами аргументы row и col.

public class RequestWindowChange : Request
{
    public void setSize(int row, int col, int wp, int hp)
    {
        ...
    }
}

public void setPtySize(int col, int row, int wp, int hp)
{
    try
    {
        RequestWindowChange request=new RequestWindowChange();
        request.setSize(col, row, wp, hp);
        request.request(session, this);
    }
    catch(Exception e)
    {
        throw new JSchException("ChannelShell.setPtySize: "+e.ToString());
    }
}

Обнаружено в CSharpUtils

THREAD_STATIC_FIELD

Подкатегории

Описание ошибки

Неправильно использован атрибут [ThreadStatic].

Пример

В данном примере инициализация произойдет только в первом потоке.

[Обнаружено в ThreadStatic]
public static List<object> _trace = new List<object>();

Обнаружено в IronRuby

В следующем примере атрибут применен не к статическому члену класса.

[Обнаружено в ThreadStatic]
private bool _traceListenerSuspended;

Обнаружено в IronRuby

VIRTUAL_CALL_IN_CONSTRUCTOR

Подкатегории

Описание ошибки

Виртуальный метод класса вызван внутри его конструктора. Это может привести к неконсистентному состоянию, поскольку виртуальный метод, переопределенный в классе-потомке, может использовать еще не проинициализирпованные данные потомка.

Пример.

В данном примере виртуальный метод Commit вызывается в конструкторе класса InvariantSubroutine.

public InvariantSubroutine(
    MethodCache<
        Local, Parameter, Type, Method, Field, Property,
        Event, Attribute, Assembly> methodCache,
    Subroutine inherited, Type associatedType)
    : base(methodCache)
{
    Contract.Requires(methodCache != null);
    this.AddSuccessor(this.Entry, "entry", this.Exit);
    this.AddBaseInvariant(this.Entry, this.Exit, inherited);
    this.Commit();
}

Обнаружено в CodeContracts

WRONG_COMPARETO

Описание ошибки

Метод CompareTo не соответствует сигнатуре ‘public int CompareTo(Object)’.

Предупреждения, основанные на анализе потока данных

UNUSED_VALUE

Описание ошибки

Переменной присвоено значение, не используемое в дальнейшем.

Пример

if (format <= Lucene3xSegmentInfoFormat.FORMAT_HAS_VECTORS)
{
    int hasVectors = input.ReadByte();
}

Обнаружено в Lucene.NET

UNREACHABLE_CODE

Описание ошибки

Код недостижим, потому что условия, при которых он должен быть исполнен, несовместны.

Пример

В данном примере равенство a1 == a2 приводит к выполнению первого условного оператора и выходу из функции. Код, начинающийся с a1 = a1.CloneExpanded();, недостижим.

public static Automaton Union(Automaton a1, Automaton a2)
{
    if ((a1.IsSingleton && a2.IsSingleton && a1.singleton.Equals(a2.singleton)) || a1 == a2)
    {
        return a1.CloneIfRequired();
    }
    if (a1 == a2)
    {
        a1 = a1.CloneExpanded();
        a2 = a2.CloneExpanded();
    }
    ...
}

Обнаружено в Lucene.NET

CONSTANT_RESULT

Описание ошибки

Результат выражения равен константе.

Пример

В данном примере значение newSize имеет тип int, а значит, не может превышать int.MaxValue

int newSize = Size + otherUpdates.Size;
if (newSize > int.MaxValue)
{
    throw new InvalidOperationException(
        "cannot support more than Integer.MAX_VALUE doc/value entries; size=" +
        Size + " other.size=" + otherUpdates.Size);
}

Обнаружено в Lucene.NET

Предупреждения, основанные на анализе с использованием символьного выполнения

NRE.DEREF_AFTER_NULL

Описание ошибки

Переменная была сравнена со значением null (что означает, что она может принимать это значение) и после использована без проверки.

Пример

В данном примере в случае, если expected == null && actual != null, будет выброшено исключение NullReferenceException

static void AreEqual<T>(T expected, T actual) {
    if (expected == null && actual == null) return;

    if (!expected.Equals(actual)) {
        Console.WriteLine("Expected: {0} Got: {1} from {2}",
            expected, actual, new StackTrace(true));
        throw new Exception();
    }
}

Обнаружено в IronPython

NRE

Описание ошибки

Использование переменной, которой присвоили значение null, и существуют пути исполнения программы, по которым это значение не было перезаписано.

Пример

В данном примере NullReferenceException будет выкинуто, если tree2 окажется равным null или не реализующим интерфейс IAssemblyReference.

IAssemblyReference ar = null;
try {
    var tree2 = transformer.Visit(compilationUnitDeclaration);
    ar = tree2 as IAssemblyReference;
} catch (ConverterException e) {
    exceptionMessage = e.Message;
}
if (exceptionMessage != null) {
    yield return Tuple.Create(
        exceptionMessage, compilationUnitDeclaration.GetFirstToken().Span);
    yield break;
}
var unit = ar;
this.host.RegisterUnit(unit.ResolvedUnit);

Обнаружено в CodeContracts

NRE.NULL_AFTER_DEREF

Описание ошибки

Проверка переменной на null произведена после ее использования.

Пример

В данном примере аргумент list проверяется на null позже, чем используется в (toIndex > list.Count).

public SubList(IList<T> list, int fromIndex, int toIndex)
{
    if (fromIndex < 0)
        throw new ArgumentOutOfRangeException("fromIndex");
    if (toIndex > list.Count)
        throw new ArgumentOutOfRangeException("toIndex");
    if (toIndex < fromIndex)
        throw new ArgumentOutOfRangeException("toIndex");
    if (list == null)
        throw new ArgumentNullException("list");
    this.list = list;
    this.fromIndex = fromIndex;
    this.toIndex = toIndex;
}

Обнаружено в Lucene.NET

DEADLOCK

Описание ошибки

Возможность взаимной блокировки.

Пример

В данном синтетическом примере функции Foo и Bar, вызванные одновременно в разных потоках, заблокируют одна другую.

void Foo() {
    lock(a)
        lock(b)
            Baz1();
}

void Bar() {
    lock(b)
        lock(a)
            Baz2();
}

CAST_AFTER_CHECK

Описание ошибки

Переменная была проверена на принадлежность типу (что означает, что она может ему не принадлежать) и после приведена к нему без проверки.

Пример

В примере вначале происходит проверка на то, что task.Result не принадлежит типу ResultResponse, после чего сразу происходит приведение к этому типу. В данном случае вместо оператора || использован оператор &&.

if (!(task.Result is ResultResponse) &&
    !(((ResultResponse)task.Result).Output is OutputRows))
{
    throw new DriverInternalError("Expected rows " + task.Result);
}

Обнаружено в C# Driver for Apache Cassandra

HANDLE_LEAK

Описание ошибки

У объекта, реализующего интерфейс IDisposable, не вызывается метод Dispose().

Пример

В данном примере ресурс bos не освобождается.

public static byte[] Compress(
    byte[] value, int offset, int length, int compressionLevel)
{
    var bos = new ByteArrayOutputStream(length);
    Deflater compressor = SharpZipLib.CreateDeflater();
    try
    {
        compressor.SetLevel(compressionLevel);
        compressor.SetInput(value, offset, length);
        compressor.Finish();
        var buf = new byte[1024];
        while (!compressor.IsFinished)
        {
            int count = compressor.Deflate(buf);
            bos.Write(buf, 0, count);
        }
    }
    finally
    {
    }
    return bos.ToArray();
}

Обнаружено в Lucene.NET

В следующем примере вызов метода WriteLine может выкинуть IOException, и если это произойдет, ресурс file не будет освобожден.

var file = new StreamWriter(Path.Combine(cwd, writeBatchFile + ".bat"));
file.WriteLine("\"{0}\" {1} %1 %2 %3 %4 %5", i.FileName, i.Arguments);
file.Close();

Обнаружено в CodeContracts

NO_LOCK.STAT

Подкатегории

Описание ошибки

К переменной, к которой в основном обращаются под lock-ом, произошло обращение вне lock-а.