views:

2415

answers:

7

When using the ObsoleteAtribute in .Net it gives you compiler warnings telling you that the object/method/property is obsolete and somthing else should be used. I'm currently working on a project that requires a lot of refactoring an ex-employees code. I want to write a custom attribute that I can use to mark methods or properties that will generate compiler warnings that give messages that I write. Something like this

[MyAttribute("This code sux and should be looked at")]
public sub DoEverything(){}

I want this to generate a compiler warning that says, "This code sux and should be looked at". I know how to create a custom attribute, the question is how do I cause it to generate compiler warnings in visual studio.

+8  A: 

In some compilers you can use #warning to issue a warning:

#warning "Do not use ABC, which is deprecated. Use XYZ instead."

In Microsoft compilers, you can typically use the message pragma:

#pragma message ( "text" )

You mentioned .Net, but didn't specify whether you were programming with C/C++ or C#. If you're programming in C#, than you should know that C# supports the #warning format.

Douglas Mayle
#warning or #pragma are pre-processor directives and thus will run regardless of the presence of any of micah's ex-colleagues' code, and it doesn't interact with the attribute at all. Pretty certain Obsolete is the only means of achieving this...
kronoz
+1  A: 

I don't think you can. As far as I know support for ObsoleteAttribute is essentially hardcoded into the C# compiler; you can't do anything similar directly.

What you might be able to do is use an MSBuild task (or a post-build event) that executes a custom tool against the just-compiled assembly. The custom tool would reflect over all types/methods in the assembly and consume your custom attribute, at which point it could print to System.Console's default or error TextWriters.

technophile
+20  A: 

Don't know if this will work but it's worth a try.

You can't extend Obsolete, because its final, but maybe you can create your own attribute, and mark that class as obsolete like this:

[Obsolete("Should be refactored")]
public class MustRefactor: System.Attribute{}

Then when you mark your methods with the "MustRefactor" attribute, the compile warnings might show.

I said "maybe" and "might" because I haven't tried this. Please tell me if it doesn't work so I'll remove the answer.

Regards!

UPDATE: Tested it. It generates a compile time warning, but the error message looks funny, you should see it for yourself and choose. This is very close to what you wanted to achieve.

UPDATE2: With this code It generates this warnings (not very nice, but I don't think there's something better).

Pablo Fernandez
Can you paste in what it generates? I'm curious.
Micah
+1 Very clever!
g .
+1 Very nice solution, not ideal but better than a direct Obsolete attribute.
Kyle Rozendo
Very clever! Diabolical, even.
Andrew Rollings
The compile warning is triggered even if the Property / Method is not called.
Rolf Kristensen
+2  A: 

Looking at the source for ObsoleteAttribute, it doesn't look like it's doing anything special to generate a compiler warning, so I would tend to go with @technophile and say that it is hard-coded into the compiler. Is there a reason you don't want to just use ObsoleteAttribute to generate your warning messages?

bdukes
No particular reason other than code isn't necessarily obsolete.
Micah
It's specified in the C# specification as being treated specially by the compiler, check out my answer :-). Micah - 'The attribute Obsolete is used to mark types and members of types that should no longer be used.' from the specification. Isn't that applicable?...
kronoz
+9  A: 

I don't believe it's possible. ObsoleteAttribute is treated specially by the compiler and is defined in the C# standard. Why on earth is ObsoleteAttribute not acceptable? It seems to me like this is precisely the situation it was designed for, and achieves precisely what you require!

Also note that Visual Studio picks up the warnings generated by ObsoleteAttribute on the fly too, which is very useful.

Don't mean to be unhelpful, just wondering why you're not keen on using it...

Unfortunately ObsoleteAttribute is sealed (probably partly due to the special treatment) hence you can't subclass your own attribute from it.

From the C# standard:-

The attribute Obsolete is used to mark types and members of types that should no longer be used.

If a program uses a type or member that is decorated with the Obsolete attribute, the compiler issues a warning or an error. Specifically, the compiler issues a warning if no error parameter is provided, or if the error parameter is provided and has the value false. The compiler issues an error if the error parameter is specified and has the value true.

Doesn't that sum up your needs?... you're not going to do better than that I don't think.

kronoz
I'm looking for the same thing. Obsolete 'works' but the code isn't really obsolete so much as incomplete due to refactoring.
g .
+1  A: 

We're currently in the middle of a lot of refactoring where we couldn't fix everything right away. We just use the #warning preproc command where we need to go back and look at code. It shows up in the compiler output. I don't think you can put it on a method, but you could put it just inside the method, and it's still easy to find.

public void DoEverything() {
   #warning "This code sucks"
}
Ted Elliott
A: 

In VS 2008 (+sp1) #warnings don't show properly in Error List after Clean Soultion & Rebuild Solution, no all of them. Some Warnings are showed in the Error List only after I open particular class file. So I was forced to use custom attribute:

[Obsolete("Mapping ToDo")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property)]
public class MappingToDo : System.Attribute
{
    public string Comment = "";

    public MappingToDo(string comment)
    {
        Comment = comment;
    }

    public MappingToDo()
    {}
}

So when I flag some code with it

[MappingToDo("Some comment")]
public class MembershipHour : Entity
{
    // .....
}

It produces warnings like this:

Namespace.MappingToDo is obsolete: 'Mapping ToDo'.

I can't change the text of the warning, 'Some comment' is not showed it Error List. But it will jump to proper place in file. So if you need to vary such warning messages, create various attributes.

Tomasz Modelski