私はあなたがカスタム属性とroslynコード分析を使ってこれを行うことができると思います。私は解決策をスケッチしよう。これは少なくともリテラルで初期化する最初のケースを解決するはずです。あなたはここで行うことはあなたが最小値と最大値を格納している
[AttributeUsage(System.AttributeTargets.Struct)]
public class MinMaxSizeAttribute : Attribute
{
public int MinVal { get; set;}
public int MaxVal { get; set;}
public MinMaxSizeAttribute()
{
}
}
:
まず、コードが有効範囲を知ることができるように分析できるように、あなたの構造体に適用されるカスタム属性が必要になります属性。そうすれば、ソースコード分析の後半でこれを使うことができます。
は今のstruct宣言にこの属性を適用します。
[MinMaxSize(MinVal = 0, MaxVal = 100)]
public struct Foo
{
//members and implicit conversion operators go here
}
今のstruct Foo
の型情報は、値の範囲が含まれています。次に必要なことは、コードを分析するDiagnosticAnalyzer
です。
public class MyAnalyzer : DiagnosticAnalyzer
{
internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor("CS00042",
"Value not allowed here",
@"Type {0} does not allow Values in this range",
"type checker",
DiagnosticSeverity.Error,
isEnabledByDefault: true, description: "Value to big");
public MyAnalyzer()
{
}
#region implemented abstract members of DiagnosticAnalyzer
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzeSyntaxTree, SyntaxKind.SimpleAssignmentExpression);
}
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
#endregion
private static void AnalyzeSyntaxTree(SyntaxNodeAnalysisContext context)
{
}
}
これは、コード解析に参加するための骨なし骨格です。アナライザは、割り当てを分析するために登録します。
context.RegisterSyntaxNodeAction(AnalyzeSyntaxTree, SyntaxKind.SimpleAssignmentExpression);
変数宣言のためにあなたが別のSyntaxKind
のために登録することなく、簡単にするために、私はここで一つに固執する必要があります。
解析ロジックを見てましょう:
private static void AnalyzeSyntaxTree(SyntaxNodeAnalysisContext context)
{
if (context.Node.IsKind(SyntaxKind.SimpleAssignmentExpression))
{
var assign = (AssignmentExpressionSyntax)context.Node;
var leftType = context.SemanticModel.GetTypeInfo(assign.Left).GetType();
var attr = leftType.GetCustomAttributes(typeof(MinMaxSizeAttribute), false).OfType<MinMaxSizeAttribute>().FirstOrDefault();
if (attr != null && assign.Right.IsKind(SyntaxKind.NumericLiteralExpression))
{
var numLitteral = (LiteralExpressionSyntax)assign.Right;
var t = numLitteral.Token;
if (t.Value.GetType().Equals(typeof(int)))
{
var intVal = (int)t.Value;
if (intVal > attr.MaxVal || intVal < attr.MaxVal)
{
Diagnostic.Create(Rule, assign.GetLocation(), leftType.Name);
}
}
}
}
}
左側のタイプは、それに関連付けられているMinMaxSize
があり、その場合、右側ならば、それは確認した場合、チェックされているどのようなアナライザはありませんリテラルです。リテラルの場合は、整数値を取得しようとし、それをタイプに関連付けられたMinVal
とMaxVal
と比較します。値がその範囲を超えると、診断エラーが報告されます。
このコードはすべてテストされていないことに注意してください。それはコンパイルし、いくつかの基本的なテストに合格しました。しかし、それは可能な解決策を説明することを意味するだけです。詳細はRsolyn Docs
x
の値を取得するためにdataflow analyzesを適用する必要があるため、カバーする2番目のケースは複雑です。
できません。バイトは255の範囲の型です。コンパイル時にこれを制限したり、カスタム型を作成することはできません。 @ –
@M。kazemAkhgary Roslynを修正することで可能かもしれませんが、私はどれくらい難しくて妥当かは分かりません –
興味深い質問! Visual Studio 2013で、大きすぎるリテラル値を入力すると、Intellisenseが認識します。似たようなIntellisenseサポートを持つクラスを定義する方法があるのだろうか、それとも焼き付けられているのだろうか。 –