[Property to Method] + System.Attribute
От: Пельмешко Россия blog
Дата: 21.06.09 19:34
Оценка:
В наличии свойство с атрибутами и атрибуты на ацессорах:
class A
{
    private int value;

    [DebuggerHidden]
    public int Value
    {
        [Pure]
        get { return this.value; }
        set { this.value = value; }
    }
}
Конвертим в методы:
class A
{
    private int value;

    public void SetValue([DebuggerHidden] int value) { this.value = value; }

    [DebuggerHidden]
    public int GetValue() { return this.value; }
}
Не понятно как как относится свойство к аргументу Set-метода и куда подевался [PureAttribute]...
Думаю при наличии атрибутов на самом свойстве, надо глянуть на AttributeUsage свойств и по возможности (то есть при наличии флага AttributeTargets.Method) применить их на получаемые после рефакторинга метод(ы).


Обратный рефакторинг тоже не очень корректен с атрибутами:
[Pure]
public int GetValue()
{
    return this.value;
}
Применяет атрибуты метода на свойство, а не на ацессор:
[Pure]
public int Value
{
    get { return this.value; }
}


Ещё заметил, что конвертирование в авто-свойство:
public int Value
{
    [Pure]
    get { return this.value; }
    [DebuggerHidden]
    get { this.value = value; }
}

Немного корёжит форматирование:
public int Value { [Pure]
get; [DebuggerHidden]
set; }


Это всё мелочи, но они иногда досаждают, когда атрибуты достаточно важны (как тот же [Pure] из контрактов).

ReSharper 4.5 Full Edition build 4.5.1231.7 on 2009-04-08T16:10:26

Re: [Property to Method] + System.Attribute
От: xvost Германия http://www.jetbrains.com/company/people/Pasynkov_Eugene.html
Дата: 21.06.09 20:12
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>Это всё мелочи, но они иногда досаждают, когда атрибуты достаточно важны (как тот же [Pure] из контрактов).


спасибо, бум лечить.....
А что это за Pure? Он же только в CLR4 появился...
С уважением, Евгений
JetBrains, Inc. "Develop with pleasure!"
Re[2]: [Property to Method] + System.Attribute
От: Пельмешко Россия blog
Дата: 21.06.09 20:40
Оценка:
Здравствуйте, xvost, Вы писали:
X>спасибо, бум лечить.....
X>А что это за Pure? Он же только в CLR4 появился...

Вам спасибо за экономию времени и сил!

PureAttribute из CodeContracts, их можно сейчас и без CLR4.0 использовать без особых проблем.

Кстати, а на каком основнии R# полагает "Possible 'System.NullReferenceException'" в данном случае:
int DoSmth(string text)
{
    Contract.Requires(text != null);

    return text.Length;
           ^^^^
}

Тут Contract.Requires() — всего лишь вызов статического метода, какая разница что туда передалось: true или false, разве это позволяет судить далее по коду о значении ссылки text? (на самом деле позволяет, но совершенно в иную сторону) В уйме мест теперь подчёркивание по этому поводу А на Debug.Assert() такой реакции нет, всё верно, хотя устроено внутри так же — просто вызов статического метода
Re[3]: [Property to Method] + System.Attribute
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 21.06.09 21:08
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>Тут Contract.Requires() — всего лишь вызов статического метода, какая разница что туда передалось: true или false, разве это позволяет судить далее по коду о значении ссылки text? (на самом деле позволяет, но совершенно в иную сторону) В уйме мест теперь подчёркивание по этому поводу А на Debug.Assert() такой реакции нет, всё верно, хотя устроено внутри так же — просто вызов статического метода


Ну так 4-тый решарпер ничего про CodeContracts не знает.
... << RSDN@Home 1.2.0 alpha 4 rev. 1227 on Windows Vista 6.1.7100.0>>
AVK Blog
Re[3]: [Property to Method] + System.Attribute
От: xvost Германия http://www.jetbrains.com/company/people/Pasynkov_Eugene.html
Дата: 21.06.09 21:53
Оценка:
Здравствуйте, Пельмешко, Вы писали:


П>Тут Contract.Requires() — всего лишь вызов статического метода, какая разница что туда передалось: true или false, разве это позволяет судить далее по коду о значении ссылки text? (на самом деле позволяет, но совершенно в иную сторону) В уйме мест теперь подчёркивание по этому поводу А на Debug.Assert() такой реакции нет, всё верно, хотя устроено внутри так же — просто вызов статического метода


РеШарпер ничего не знает что "Contract.Requires()" — это некоторый вариант ассерта. И, соответственно, видит что твою переменную сравнили с null — значит она может быть null
Следующую версию РеШарпера научим работать с код-контрактами...
С уважением, Евгений
JetBrains, Inc. "Develop with pleasure!"
Re[4]: [Property to Method] + System.Attribute
От: Пельмешко Россия blog
Дата: 22.06.09 09:32
Оценка: 12 (1) +1
Здравствуйте, AndrewVK, Вы писали:
AVK>Ну так 4-тый решарпер ничего про CodeContracts не знает.

Если вникнуть в мой пост, то меня интерисовало поведение именно "ничего не знающего" о контрактах решарпера.

Здравствуйте, xvost, Вы писали:
X>И, соответственно, видит что твою переменную сравнили с null — значит она может быть null
Спасибо, теперь понятно Интересная логика...

X>Следующую версию РеШарпера научим работать с код-контрактами...

Хорошо бы

Очень хочется много quick fix'ов на подобие:

if (value == null)
{
    throw new ArgumentNullException("value");
}

=> Convert to Contract.Requires:
Contract.Requires(value != null);

=> Convert to Contract.Requires<TException>:
Contract.Requires<ArgumentNullException>(value != null, "value");

=> Convert to Contract block:
if (value == null)
{
    throw new ArgumentNullException("value");
}

Contract.EndContractBlock();

И всякие мелочи типа исправления типов в Contract.Result<T> очень бы помогли:
int DoSmth()
{
    Contract.Ensures(Contract.Result<double>() > 0);
                                     ^^^^^^
    return 0;
}


Вообще проблем с решарпером нету никаких, можно спокойно и сейчас юзать, всё ок.
Re[4]: [Property to Method] + System.Attribute
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 22.06.09 11:22
Оценка:
Здравствуйте, xvost, Вы писали:

X>РеШарпер ничего не знает что "Contract.Requires()" — это некоторый вариант ассерта. И, соответственно, видит что твою переменную сравнили с null — значит она может быть null


Может быть имеет смысл добавить возможность пометки атрибутом собственных аналогичных методов?
... << RSDN@Home 1.2.0 alpha 4 rev. 1227 on Windows Vista 6.1.7100.0>>
AVK Blog
Re[5]: [Property to Method] + System.Attribute
От: xvost Германия http://www.jetbrains.com/company/people/Pasynkov_Eugene.html
Дата: 22.06.09 12:42
Оценка:
Здравствуйте, Пельмешко, Вы писали:

Спасибо. Очень ценно.
Если будут еще идеи таких преобразований — пиши, с удовольствием сделаем
С уважением, Евгений
JetBrains, Inc. "Develop with pleasure!"
Re[6]: [Property to Method] + System.Attribute
От: Пельмешко Россия blog
Дата: 22.06.09 15:03
Оценка: 75 (1)
Здравствуйте, xvost, Вы писали:

X>Здравствуйте, Пельмешко, Вы писали:


X>Спасибо. Очень ценно.

X>Если будут еще идеи таких преобразований — пиши, с удовольствием сделаем

Я с удовольствием, идей полно, и не только преобразований
Столкнулся со следующим:

На методы-инварианты (помечаются атрибутом System.Diagnostics.Contracts.ContractInvariantMethodAttribute) необходимо реагировать как на [UsedImplicitly], иначе выделяет как неиспользуемый:
[ContractInvariantMethod]
private void ObjectInvariant()
{
    Contract.Invariant(this.intField > 0);
}

Можно предусмотреть такие Bad Practices касаемо инвариантов:
1. В методе-инварианте нельзя вызывать метод-инвариант из базового класса.
2. Метод-инваринт должен быть всегда private в sealed-классах, в остальных случаях protected. (реврайтер/верификатор сейчас выдают ошибку только в случае использования private в non sealed, остальное побоку, хотя делать инвариант публичным или internal видимым — кощунство какое-то).
3. Можно приделать соглашение об именовании, цитирую мануал:

A common name used for the invariant method is "ObjectInvariant".



Ещё просто жизненно необходима генерация класса-контракта для интерфейсов и абстрактных классов.
Например? для того чтобы для такого интерфейса описать контракт:
interface ISomeInterface
{
    void SomeMethod(string x);
    int OtherMethod(DateTime d);

    int SomeProperty { get; set; }
}

Надо написать аж вот такую байду:
[ContractClass(typeof(ISomeInterfaceContract))]
interface ISomeInterface
{
    string SomeMethod(string x);
    int OtherMethod(DateTime d);

    int SomeProperty { get; set; }
}

[ContractClassFor(typeof(ISomeInterface))]
sealed class ISomeInterfaceContract : ISomeInterface
{
    string ISomeInterface.SomeMethod(string x)
    {
        return default(string);
    }

    int ISomeInterface.OtherMethod(DateTime d)
    {
        return default(int);
    }

    int ISomeInterface.SomeProperty
    {
        get
        {
            return default(int);
        }
        set
        {
        }
    }
}
И уже там излагать пред/пост-условия...

То есть: два атрибута + sealed class, explicitly-реализующий исходный интерфейс, в каждом из методов с возвращаемым значением заглушки в виде return default(T); (всё это согласно мануалу CodeContracts) Для абстрактных классов всё то же самое, только override и класс не sealed, а abstract.
Каждый раз набивать всё это, даже с помощью решарпера уж больно гемморно...

Сейчас R# ругается на именование такого класса (префикс I), что понятно...
Но думаю для контрактного класса стоит делать исключение

P.S. Синтаксис полный пердец, конечно...
Re[7]: [Property to Method] + System.Attribute
От: Пельмешко Россия blog
Дата: 22.06.09 15:57
Оценка:
До использования контрактов у меня код был покрыт обычными ассертами:
Debug.Assert(x > 0, "wtf?");

Совсем мелочь, но пока делал find & replace хотелось иметь quickfix "Convert to Contract.Assert":
Contract.Assert(x > 0, "wtf?");

А если ассерт в начале метода и завязан на параметрах, то это явно будущее предусловие, тогда было бы предпочтительнее предлагать "Convert to Contract.Requires":
Contract.Requires(x > 0, "wtf?");

Вообще контракты должны быть в методе строго в определённом порядке:

1. if-then-throw — обычные проверки могут распознаваться контрактами в целях совместимости.
2. Contract.Requires / Contract.Requires<TException>
3. Contract.Ensures
4. Contract.EnsuresOnThrow<TException>
5. Contract.EndContractBlock — необходимо отметить конец блока контрактов при наличии if-then-throw проверок, в остальных случаях считать за redundant.

Это надо бы как-нибудь учесть, а то просто верификатор (то есть уже после компиляции) бракует код, если последовательность не соблюдена...
Хотя бы при вставке новых контрактов учитывать порядок...

Для параметров методов можно сделать quickfix "Write precondition", аналогично для возвращаемых значений и out-параметров можно сделать "Write postcondition", вставляющие готовые snippets для нужного параметра / результата метода:
static string SomeMethod(string a, out int x)
{
    Contract.Requires(a ...);
    Contract.Ensures(Contract.Result<string>() ...);
    Contract.Ensures(Contract.ValueAtReturn(out x) ...);
    ...
}

Причём Contract.Result<T>() и Contract.ValueAtReturn(out T) нельзя использовать больше нигде, кроме как внутри вызова Ensures().

Есть ещё Contract.OldValue<T>(e), у которого очень много нюансов, описанных в мануале...
Re[8]: [Property to Method] + System.Attribute
От: xvost Германия http://www.jetbrains.com/company/people/Pasynkov_Eugene.html
Дата: 22.06.09 17:41
Оценка:
Здравствуйте, Пельмешко, Вы писали:

Огромное спасибо!
Все идеи занес в специальный список, буду изучать его, увязывать со всем остальным и т.д.
Спасибо!
С уважением, Евгений
JetBrains, Inc. "Develop with pleasure!"
Re[7]: [Property to Method] + System.Attribute
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 23.06.09 14:14
Оценка: 12 (1)
Здравствуйте, Пельмешко, Вы писали:

П>На методы-инварианты (помечаются атрибутом System.Diagnostics.Contracts.ContractInvariantMethodAttribute) необходимо реагировать как на [UsedImplicitly], иначе выделяет как неиспользуемый:


Нужно пометить в External Annotations атрибут System.Diagnostics.Contracts.ContractInvariantMethodAttribute атрибутом MeansImplicitUse.
... << RSDN@Home 1.2.0 alpha 4 rev. 1227 on Windows Vista 6.1.7100.0>>
AVK Blog
Re[8]: [Property to Method] + System.Attribute
От: Пельмешко Россия blog
Дата: 23.06.09 15:19
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Нужно пометить в External Annotations атрибут System.Diagnostics.Contracts.ContractInvariantMethodAttribute атрибутом MeansImplicitUse.


Списибо, то что доктор прописал!

Microsoft.Contracts.Attributes.xml
<assembly name="Microsoft.Contracts">
  <member name="T:System.Diagnostics.Contracts.ContractInvariantMethodAttribute">
    <attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor()"/>
  </member>
</assembly>

Обнаружил AssertionMethodAttribute, сейчас ещё и от 'Possible "System.NullReferenceException"' избавимся
Re[8]: [Property to Method] + System.Attribute
От: Пельмешко Россия blog
Дата: 23.06.09 15:54
Оценка:
Здравствуйте, AndrewVK, Вы писали:
AVK>Нужно пометить в External Annotations атрибут System.Diagnostics.Contracts.ContractInvariantMethodAttribute атрибутом MeansImplicitUse.

Спасибо огромное, избавился от надоедливого Possible NRE!!!

Если кому вдруг нужно, то готовые аннотации ко всем методам контрактов можно забрать отсюда, папку класть в \ReSharper\v4.5\Bin\ExternalAnnotations\
Re[9]: [Property to Method] + System.Attribute
От: Пельмешко Россия blog
Дата: 28.06.09 19:52
Оценка:
Здравствуйте, xvost, Вы писали:
X>Все идеи занес в специальный список, буду изучать его, увязывать со всем остальным и т.д.

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

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

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

Фактически всякие Contract.Result<>() являлись бы контекстными ключевыми словами (как сейчас from/select/let/group из Linq), если бы С# когда-нибудь будет поддерживать синтаксис контрактов:
int Foo(string s)
    requires s != null
    ensures result > 0
{
    ...
}

Но сейчас Contract.Result<T>() можно написать везде в методе и получить неопределённое поведение...
Re[10]: [Property to Method] + System.Attribute
От: xvost Германия http://www.jetbrains.com/company/people/Pasynkov_Eugene.html
Дата: 29.06.09 07:46
Оценка:
Здравствуйте, Пельмешко, Вы писали:

П>Поэтому было бы очень хорошо отлавливать некоторые глупости именно решарпером, это было бы большим подспорьем при покрытии кода контрактами.


Это в общем-то понятно. Только в real-time проверить мы сможем не очень многое... Ведь же задача проверки контрактов эквивалентна проблеме останова, которая, как известно, не решается в рамках машины Тьюринга Но простые кнтракты связаные с NRE проверять ес-но будем
С уважением, Евгений
JetBrains, Inc. "Develop with pleasure!"
Re[11]: [Property to Method] + System.Attribute
От: Пельмешко Россия blog
Дата: 29.06.09 13:45
Оценка:
Здравствуйте, xvost, Вы писали:

X>Здравствуйте, Пельмешко, Вы писали:


П>>Поэтому было бы очень хорошо отлавливать некоторые глупости именно решарпером, это было бы большим подспорьем при покрытии кода контрактами.


X>Это в общем-то понятно. Только в real-time проверить мы сможем не очень многое... Ведь же задача проверки контрактов эквивалентна проблеме останова, которая, как известно, не решается в рамках машины Тьюринга Но простые кнтракты связаные с NRE проверять ес-но будем


Не не не, я совершенно про другое — про контроль некорректного использования методов System.Diagnostics.Contracts, не в правильном порядке, не в своём контексте и т.п.
А сами контракты проверять решарпером я ни в коем случае не стал бы, зачем изобретать второй верификатор?
Нынешних средств со стороны R# достаточно для поверхностного анализа. Для верификации контрактов — cccheck.exe.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.