カスタムコンパイラの警告
-
03-07-2019 - |
質問
.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
これにより、「このコードはサックスであり、確認する必要があります」というコンパイラ警告が生成されます。カスタム属性を作成する方法は知っていますが、Visual Studioでコンパイラ警告を生成する方法を質問します。
解決
更新
これは、Roslyn(Visual Studio 2015)で可能になりました。 ビルド コードアナライザーでカスタム属性を確認
>それが可能だとは思わない。 ObsoleteAttributeはコンパイラによって特別に扱われ、C#標準で定義されています。 ObsoleteAttributeが受け入れられないのはなぜですか?これはまさにそれが設計された状況であり、あなたが必要とするものを正確に達成しているように思えます!
また、Visual StudioはObsoleteAttributeによって生成された警告をオンザフライでピックアップすることにも注意してください。これは非常に便利です。
役に立たないという意味ではなく、なぜそれを使用したくないのか疑問に思っているだけです...
残念ながら、ObsoleteAttributeは封印されているため(おそらく特別な処理が原因である可能性があります)、独自の属性をサブクラス化することはできません。
C#標準から:-
Obsolete属性はマークに使用されます 型と型のメンバー 使用されなくなりました。
プログラムが型またはメンバーを使用する場合 時代遅れで飾られている 属性、コンパイラは 警告またはエラー。具体的には、 エラーがない場合、コンパイラは警告を発行します パラメータが提供されるか、エラーの場合 パラメータが提供され、 値false。コンパイラは エラーパラメータが 指定され、値はtrueです。
それはあなたのニーズを要約していませんか?...あなたは私が思っていないよりもうまくやるつもりはありません。
他のヒント
これが機能するかどうかはわかりませんが、試してみる価値はあります。
Obsoleteは最終版であるため拡張できませんが、独自の属性を作成し、そのクラスを次のように陳腐化させることができます。
[Obsolete("Should be refactored")]
public class MustRefactor: System.Attribute{}
次に、「MustRefactor」でメソッドをマークすると、属性、コンパイル警告が表示される場合があります。
「たぶん」と言いました。および「might」」私はこれを試したことがないからです。機能しない場合は教えてください。回答を削除します。
よろしく!
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
{
}
一部のコンパイラでは、#warningを使用して警告を発行できます。
#warning "Do not use ABC, which is deprecated. Use XYZ instead."
Microsoftコンパイラでは、通常、メッセージプラグマを使用できます。
#pragma message ( "text" )
.Netについて言及しましたが、C / C ++またはC#のどちらでプログラミングしているかを指定しませんでした。 C#でプログラミングしている場合、 C# #warning形式をサポートしています。
現在、すべてをすぐに修正できなかった多くのリファクタリングの最中です。戻ってコードを確認する必要がある場合は、#warning preprocコマンドを使用します。コンパイラーの出力に表示されます。メソッドに配置できるとは思いませんが、メソッド内に配置することはできますが、それでも簡単に見つけることができます。
public void DoEverything() {
#warning "This code sucks"
}
VS 2008(+ sp1)では、クリーンソウルション&amp;の後、エラーリストに#warningsが正しく表示されません。ソリューションを再構築します。すべてではありません。 特定のクラスファイルを開いた後にのみ、エラーリストに警告が表示されます。 そのため、カスタム属性の使用を余儀なくされました:
[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は廃止されました: 「マッピングToDo」。
警告のテキストを変更できません。「コメント」にはエラーリストが表示されません。 ただし、ファイル内の適切な場所にジャンプします。 そのため、このような警告メッセージを変更する必要がある場合は、さまざまな属性を作成します。
やろうとしているのは、属性の誤用です。代わりに、Visual Studioタスクリストを使用します。次のようにコードにコメントを入力できます。
//TODO: This code sux and should be looked at
public class SuckyClass(){
//TODO: Do something really sucky here!
}
メニューから表示/タスクリストを開きます。タスクリストには、ユーザータスクとコメントの2つのカテゴリがあります。コメントに切り替えると、すべての// Todo:が表示されます。 TODOをダブルクリックすると、コード内のコメントにジャンプします。
Al
できるとは思わない。私の知る限り、ObsoleteAttributeのサポートは基本的にC#コンパイラにハードコードされています。同様のことを直接行うことはできません。
できることは、コンパイルしたばかりのアセンブリに対してカスタムツールを実行するMSBuildタスク(またはビルド後イベント)を使用することです。カスタムツールは、アセンブリ内のすべてのタイプ/メソッドを反映し、カスタム属性を消費します。この時点で、System.ConsoleのデフォルトまたはエラーTextWritersに出力できます。
ObsoleteAttribute のソースを見ると、コンパイラ警告を生成するために特別なことをしているようには見えないので、私は@ technophile そしてコンパイラにハードコードされていると言います。 ObsoleteAttribute 警告メッセージを生成するには?
警告またはプラグマの挿入を提案するコメントがいくつかあります。 廃止された機能は非常に異なる方法で動作します! ライブラリLの関数を廃止とマークすると、呼び出し元プログラムがライブラリLにない場合でも、プログラムが関数を呼び出すと廃止メッセージが発生します。警告は、Lのコンパイル時にのみメッセージを発生させます。
これはRoslyn実装です。そのため、警告やエラーをその場で生成する独自の属性を作成できます。
警告を生成する属性となる IdeMessage
という属性タイプを作成しました:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class IDEMessageAttribute : Attribute
{
public string Message;
public IDEMessageAttribute(string message);
}
これを行うには、最初にRoslyn 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はありません。ソリューションから削除できます。