Question

Lorsque vous utilisez ObsoleteAtribute dans .Net, vous recevez des avertissements pour le compilateur vous indiquant que l'objet / la méthode / la propriété est obsolète (e) et que tout le reste doit être utilisé. Je travaille actuellement sur un projet qui nécessite beaucoup de refactorisation d'un code d'ancien employé. Je veux écrire un attribut personnalisé que je peux utiliser pour marquer les méthodes ou les propriétés qui généreront des avertissements du compilateur qui donneront des messages que je rédigerai Quelque chose comme ça

[MyAttribute("This code sux and should be looked at")]
public void DoEverything()
{
}
<MyAttribute("This code sux and should be looked at")>
Public Sub DoEverything()
End Sub

Je souhaite que cela génère un avertissement du compilateur disant: "Ce code est sux et devrait être examiné". Je sais comment créer un attribut personnalisé, la question est de savoir comment lui faire générer les avertissements du compilateur dans Visual Studio.

Était-ce utile?

La solution

Mettre à jour

C’est désormais possible avec Roslyn (Visual Studio 2015). Vous pouvez créer un analyseur de code pour rechercher un attribut personnalisé

Je ne crois pas que ce soit possible. ObsoleteAttribute est traité spécialement par le compilateur et est défini dans la norme C #. Pourquoi diable est ObsoleteAttribute pas acceptable? Il me semble que c’est précisément la situation pour laquelle il a été conçu et vous permet de réaliser exactement ce dont vous avez besoin!

Notez également que Visual Studio collecte également les avertissements générés par ObsoleteAttribute à la volée, ce qui est très utile.

Ne voulez pas être inutile, demandez-vous simplement pourquoi vous n’êtes pas intéressé à l’utiliser ...

Malheureusement, ObsoleteAttribute est scellé (probablement en partie à cause du traitement spécial), vous ne pouvez donc pas en sous-classer votre propre attribut.

À partir de la norme C #: -

  

L'attribut Obsolète est utilisé pour marquer   types et membres de types qui devraient   ne plus être utilisé.

     

Si un programme utilise un type ou un membre   qui est décoré avec l'obsolète   attribut, le compilateur émet un   avertissement ou une erreur. Plus précisément, le   le compilateur émet un avertissement s'il n'y a pas d'erreur   paramètre est fourni, ou si l'erreur   paramètre est fourni et a la   valeur false. Le compilateur émet un   erreur si le paramètre d'erreur est   spécifié et a la valeur true.

Cela ne résume-t-il pas vos besoins? ... vous ne ferez pas mieux que ça, je ne pense pas.

Autres conseils

Je ne sais pas si cela fonctionnera, mais ça vaut le coup d'essayer.

Vous ne pouvez pas étendre Obsolete, car il est final, mais vous pouvez peut-être créer votre propre attribut et marquer cette classe comme obsolète comme ceci:

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

Ensuite, lorsque vous marquez vos méthodes avec l'option "MustRefactor" attribut, les avertissements de compilation peuvent apparaître.

J'ai dit "peut-être". et " pourrait " parce que je n'ai pas essayé cela. S'il vous plaît dites-moi si cela ne fonctionne pas alors je vais supprimer la réponse.

Cordialement!

UPDATE: Testé. Il génère un avertissement lors de la compilation, mais le message d'erreur a l'air drôle, vous devriez le voir vous-même et choisir. Ceci est très proche de ce que vous vouliez réaliser.

UPDATE2: Avec ce code , il génère cet avertissement (pas très gentil, mais je ne pense pas qu'il y ait quelque chose de mieux).

public class User
{
    private String userName;

    [TooManyArgs] // Will show warning: Try removing some arguments
    public User(String userName)
    {
        this.userName = userName;   
    }

    public String UserName
    {
        get { return userName; }
    }
    [MustRefactor] // will show warning: Refactor is needed Here
    public override string ToString()
    {
        return "User: " + userName;
    }
}
[Obsolete("Refactor is needed Here")]
public class MustRefactor : System.Attribute
{

}
[Obsolete("Try removing some arguments")]
public class TooManyArgs : System.Attribute
{

}

Dans certains compilateurs, vous pouvez utiliser #warning pour émettre un avertissement:

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

Dans les compilateurs Microsoft, vous pouvez généralement utiliser le pragma du message:

#pragma message ( "text" )

Vous avez mentionné .Net, sans préciser si vous programmez avec C / C ++ ou C #. Si vous programmez en C #, sachez que C # prend en charge le format #warning .

Nous sommes actuellement en plein travail de refactoring où nous ne pouvons pas tout réparer tout de suite. Nous utilisons simplement la commande #warning preproc où nous devons revenir en arrière et examiner le code. Cela apparaît dans la sortie du compilateur. Je ne pense pas que vous puissiez la mettre sur une méthode, mais vous pouvez la placer juste à l'intérieur de la méthode, et c'est toujours facile à trouver.

public void DoEverything() {
   #warning "This code sucks"
}

Dans VS 2008 (+ sp1), les avertissements ne s'affichent pas correctement dans la liste des erreurs après Clean Soultion & amp; Reconstruire la solution, pas tous. Certains avertissements n'apparaissent dans la liste des erreurs qu'après que j'ouvre un fichier de classe particulier. J'ai donc été obligé d'utiliser l'attribut personnalisé:

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

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

    public MappingToDo()
    {}
}

Donc, quand je marque du code avec ce code

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

Il produit des avertissements comme celui-ci:

  

Namespace.MappingToDo est obsolète:   "Mapping ToDo".

Je ne peux pas modifier le texte de l'avertissement. "Certains commentaires" ne s'affiche pas dans la liste des erreurs. Mais il va sauter à la bonne place dans le fichier. Par conséquent, si vous devez modifier ces messages d’avertissement, créez différents attributs.

Ce que vous essayez de faire est un mauvais usage des attributs. Utilisez plutôt la liste des tâches de Visual Studio. Vous pouvez entrer un commentaire dans votre code comme ceci:

//TODO:  This code sux and should be looked at
public class SuckyClass(){
  //TODO:  Do something really sucky here!
}

Ouvrez ensuite View / Task List dans le menu. La liste des tâches a deux catégories, les tâches utilisateur et les commentaires. Passez aux commentaires et vous verrez tous vos // Todo: là-bas. Double-cliquez sur un TODO pour accéder au commentaire de votre code.

Al

Je ne pense pas que vous puissiez. Autant que je sache, le support pour ObsoleteAttribute est essentiellement codé en dur dans le compilateur C #; vous ne pouvez rien faire de semblable directement.

Vous pouvez éventuellement utiliser une tâche MSBuild (ou un événement post-build) qui exécute un outil personnalisé par rapport à l’assembly qui vient d’être compilé. L’outil personnalisé reflèterait tous les types / méthodes de l’assemblage et utiliserait votre attribut personnalisé. À ce stade, il pourrait imprimer sur TextWriters, l’erreur ou le défaut de System.Console.

Consultation de la source pour ObsoleteAttribute 'on dirait qu'il fait quelque chose de spécial pour générer un avertissement pour le compilateur, donc j'aurais tendance à utiliser @ technophile et dites qu'il est codé en dur dans le compilateur. Existe-t-il une raison pour laquelle vous ne souhaitez pas simplement utiliser ObsoleteAttribute pour générer vos messages d’avertissement?

Plusieurs commentaires suggèrent d’insérer des avertissements ou un pragma. Obsolète fonctionne d'une manière très différente! En marquant obsolète une fonction d'une bibliothèque L, le message obsolète apparaît lorsqu'un programme appelle la fonction même si le programme appelant ne se trouve pas dans la bibliothèque L. Warning déclenche le message UNIQUEMENT lorsque L est compilé.

Voici l'implémentation de Roslyn, vous pouvez donc créer vos propres attributs qui donnent des avertissements ou des erreurs à la volée.

J'ai créé un attribut Type appelé IdeMessage qui sera l'attribut qui génère les avertissements:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class IDEMessageAttribute : Attribute
{
    public string Message;

    public IDEMessageAttribute(string message);
}

Pour ce faire, vous devez d'abord installer le SDK Roslyn et démarrer un nouveau projet VSIX avec analyseur. J'ai omis certains des éléments les moins pertinents tels que les messages, vous pouvez trouver un moyen de le faire. Vous faites cela dans votre analyseur

public override void Initialize(AnalysisContext context)
{
    context.RegisterSyntaxNodeAction(AnalyzerInvocation, SyntaxKind.InvocationExpression);
}

private static void AnalyzerInvocation(SyntaxNodeAnalysisContext context)
{
    var invocation = (InvocationExpressionSyntax)context.Node;

    var methodDeclaration = (context.SemanticModel.GetSymbolInfo(invocation, context.CancellationToken).Symbol as IMethodSymbol);

    //There are several reason why this may be null e.g invoking a delegate
    if (null == methodDeclaration)
    {
        return;
    }

    var methodAttributes = methodDeclaration.GetAttributes();
    var attributeData = methodAttributes.FirstOrDefault(attr => IsIDEMessageAttribute(context.SemanticModel, attr, typeof(IDEMessageAttribute)));
    if(null == attributeData)
    {
        return;
    }

    var message = GetMessage(attributeData); 
    var diagnostic = Diagnostic.Create(Rule, invocation.GetLocation(), methodDeclaration.Name, message);
    context.ReportDiagnostic(diagnostic);
}

static bool IsIDEMessageAttribute(SemanticModel semanticModel, AttributeData attribute, Type desiredAttributeType)
{
    var desiredTypeNamedSymbol = semanticModel.Compilation.GetTypeByMetadataName(desiredAttributeType.FullName);

    var result = attribute.AttributeClass.Equals(desiredTypeNamedSymbol);
    return result;
}

static string GetMessage(AttributeData attribute)
{
    if (attribute.ConstructorArguments.Length < 1)
    {
        return "This method is obsolete";
    }

    return (attribute.ConstructorArguments[0].Value as string);
}

Il n'y a pas CodeFixProvider pour cela, vous pouvez le supprimer de la solution.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top