自定义编译器警告自定义编译器警告(Custom Compiler Warnings)

2019-05-06 11:45发布

当在.NET中使用ObsoleteAtribute它为您提供了编译器的警告,告诉你有对象/方法/属性过时,其他的财产以后,应使用。 我目前工作的,需要大量的重构的前雇员代码的项目。 我想写我可以使用标记将会产生编译器警告,给我写邮件的方法或属性自定义属性。 像这样的事情

[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

我想这生成编译器警告说,“这个代码sux的,应被看作”。 我知道如何创建一个自定义属性,问题是我如何使它产生视觉工作室编译器警告。

Answer 1:

更新

这是现在可以与罗斯林(Visual Studio中2015年)。 你可以建立一个代码分析器来检查自定义属性


我不相信这是可能的。 ObsoleteAttribute是由编译器特殊处理和在C#标准被定义。 到底是什么原因ObsoleteAttribute不能接受? 在我看来,像这也正是它被设计的局面,并精确地达到您所需要的!

还要注意的是Visual Studio中拿起在飞行中通过ObsoleteAttribute产生的警告过,这是非常有用的。

不要吝啬是无益的,只是想知道为什么你不热衷于使用它...

不幸的是ObsoleteAttribute密封(可能部分是由于特殊处理),因此你不能从它继承自己的属性。

从C#标准: -

过时属性用于标记的类型和不应该再使用类型的成员。

如果程序使用装饰有过时的属性类型或成员,则编译器将发出警告或错误信息。 具体而言,编译器会发出警告,如果没有错误的参数设置,或者如果提供了错误的参数,其值为假。 编译器问题如果指定了错误的参数错误,值为true。

那岂不是总结您的需求?......你不会做的比我不觉得更好。



Answer 2:

不知道这是否会工作,但它是值得一试。

不能扩展过时,因为它的最后,但也许你可以创建自己的属性,并标记类为过时的是这样的:

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

然后,当你标记的“MustRefactor”属性的方法,编译警告可能会显示。

我说:“也许”和“可能”,是因为我没有尝试这样做。 请告诉我,如果它不工作,所以我就删除了答案。

问候!

UPDATE:测试它。 它会产生一个编译时警告,但错误信息看起来很滑稽,你应该看到它为自己和选择。 这是非常接近你想要达到的目标。

UPDATE2:有了这个代码,它会产生这样的警告 (不是很漂亮,但我不认为有更好的东西)。

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
{

}


Answer 3:

在一些编译器可以使用#warning后发出警告:

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

在微软的编译器,你可以用通常的消息编译:

#pragma message ( "text" )

你提到的.Net,但没有说明是否你用C / C ++或C#编程。 如果你在C#编程,比你应该知道, C#支持#warning后的格式 。



Answer 4:

目前,我们正处在一个大量的重构,我们不可能解决所有问题马上的中间。 我们只需要使用#warning后preproc命令,我们需要回去看看代码。 它显示了在编译器输出。 我不认为你可以把它放在一个方法,但你可以把它只是方法里面,它仍然很容易找到。

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


Answer 5:

2008年,VS(+ SP1)#warnings不正确的错误列表显示后清洁Soultion与重建解决方案,没有所有的人。 一些警告将显示在后,才打开特定的类文件中的错误列表。 所以,我被迫使用自定义属性:

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

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

    public MappingToDo()
    {}
}

所以,当我旗一些代码与它

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

它产生这样的警告:

Namespace.MappingToDo是过时:“映射待办事项”。

我不能改变的警语的文字,“有些评论”是不是表明,它错误列表。 但它会跳转到正确的位置在文件中。 所以,如果你需要改变这样的警告信息,创建各种属性。



Answer 6:

你所要做的是属性的误用。 相反,使用Visual Studio任务列表。 您可以输入您的代码中像这样的评论:

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

然后从菜单中打开查看/任务列表。 任务列表有两大类,用户的任务和评论。 切换到评论,你会看到所有//待做事项的:“在那儿。 在TODO双击就会跳转到代码中的注释。



Answer 7:

我不认为你可以。 据我知道ObsoleteAttribute支持基本上是硬编码到C#编译器; 你不能直接做类似的事情。

你也许能够做的是使用执行对刚刚编译的程序集的自定义工具的MSBuild任务(或生成后事件)。 自定义工具将反映在装配中的所有类型/方法和消耗你的自定义属性,此时它可以打印到System.Console的默认或错误TextWriters。



Answer 8:

纵观源ObsoleteAttribute ,它看起来并不像它做什么特别的生成编译器警告,所以我会倾向于去@ 让技术和说,这是硬编码到编译器。 你有什么不想只用一个理由ObsoleteAttribute产生的警告消息?



Answer 9:

有一些意见是建议插入警告或编译。 过时的作品在一个非常不同的方式! 标记库升过时的功能,当程序调用,即使调用者程序是不是在图书馆L.警告引发只有当L被编译消息的功能过时的消息引发。



Answer 10:

这里是罗斯林实施,这样你就可以创建自己的属性,让在飞行警告或错误。

我已经创建称为属性类型IdeMessage这将产生警告属性:

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

    public IDEMessageAttribute(string message);
}

为了做到这一点,你需要先安装罗斯林SDK并开始分析新的VSIX项目。 我省略一些不太相关的部分,如邮件,你可以找出如何做到这一点。 在你分析你这样做

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);
}

有没有CodeFixProvider为此,你可以从溶液中取出。



文章来源: Custom Compiler Warnings