zoukankan      html  css  js  c++  java
  • 建立标准编码规则(二)-DiagnosticAnalyzer 增加诊断分析代码

    1.使用语法树

    当我们要编写一个规则,例如 检测正值表达式的时候,如何编写有效的规则呢

    Regex.Match("my text", @"pXXX");

    这里我们可以借助分析工具 Roslyn Syntax Visualizer,在 视图>其他窗口>Syntax Visualizer

    当我们在ConsoleApp项目中编写如下代码

    namespace ConsoleApp1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Regex.Match("my text", @"pXXX");
            } 
        }
    }

    发现 SyntaxTree (以下称语法树)自动定位到对应的语法中

    在语法树中

    1 蓝色表示语法节点

    2 绿色表示编译器读取源文件时所发现的语法令牌、各个词、数字和符号

    3 红色表示琐碎内容,代表不是令牌的其他内容:空格、注释等。

     2.编写实例

    新建RegexAnalyzerAnalyzer 类,继承DiagnosticAnalyzer,写法类似默认生成的 DiagnosticAnalyzer.cs

      public class RegexAnalyzerAnalyzer : DiagnosticAnalyzer
       {
            public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }
            public override void Initialize(AnalysisContext context)
            {
                context.RegisterSyntaxNodeAction(
                  AnalyzeNode, SyntaxKind.InvocationExpression);
            }
    }

    其中 AnalysisContext 如下:

    RegisterSyntaxNodeAction 在分析特定类型的语法节点时触发
    RegisterSymbolAction 在分析特定类型的符号时触发
    RegisterSyntaxTreeAction 在分析文件的整棵语法树时触发
    RegisterSemanticModelAction 在语义模型可用于整个文件时触发
    RegisterCodeBlockStartAction
    RegisterCodeBlockEndAction
    在分析方法主体或其他代码块之前/之后触发

    RegisterCompilationStartAction
    RegisterCompilationEndAction
    在分析整个项目之前/之后触发

    11

    具体判断代码

    /// <summary>
            /// 1 首先他是一个表达式节点
            /// 2 他是Match方法
            /// 3 他是ystem.Text.RegularExpressions.Regex.Match下的方法
            /// 4 他有两个参数
            /// 5 第二个参数有值
            /// 6 使用Match捕捉第二个参数的正值表达式异常
            /// </summary>
            /// <param name="context"></param>
            private void AnalyzeNode(SyntaxNodeAnalysisContext context)
            {
                var invocationExpr = (InvocationExpressionSyntax)context.Node;//InvocationExpressionSyntax 表达式特定节点
                var memberAccessExpr =
                  invocationExpr.Expression as MemberAccessExpressionSyntax;
                if (memberAccessExpr?.Name.ToString() != "Match") return;//如果不是Match 返回
                var memberSymbol = context.SemanticModel.
                  GetSymbolInfo(memberAccessExpr).Symbol as IMethodSymbol;//获取上下文memberAccessExpr的语义模型
                if (!memberSymbol?.ToString().StartsWith(
                  "System.Text.RegularExpressions.Regex.Match") ?? true) return;//如果memberAccessExpr不是System.Text.RegularExpressions.Regex.Match 返回
                var argumentList = invocationExpr.ArgumentList as ArgumentListSyntax;//获取节点参数 
                if ((argumentList?.Arguments.Count ?? 0) < 2) return;//参数小于2返回
                var regexLiteral =
                  argumentList.Arguments[1].Expression as LiteralExpressionSyntax;//获取第二个参数内容
                if (regexLiteral == null) return;//第二个参数是null的返回
                var regexOpt = context.SemanticModel.GetConstantValue(regexLiteral);//获取参数的常量字符串
                if (!regexOpt.HasValue) return;//空值返回
                var regex = regexOpt.Value as string;//获取字符串
                if (regex == null) return;
                try
                {
                    System.Text.RegularExpressions.Regex.Match("", regex);//使用System.Text.RegularExpressions.Regex.Match 如果异常抛出异常
                }
                catch (ArgumentException e)
                {
                    //ArgumentException异常 抛出定义的说明
                    var diagnostic =
                      Diagnostic.Create(Rule, regexLiteral.GetLocation(), e.Message);
                    context.ReportDiagnostic(diagnostic);
                }
            }

    参考:https://msdn.microsoft.com/zh-cn/library/dn879356

    禁止转载
  • 相关阅读:
    张量自动求导和计算图
    34 深入浅出 x86 中断机制(下)
    33 深入浅出 x86 中断机制(上)
    使用STM32 PWM控制LCD背光
    32 获取物理内存容量 下
    ucGUI内存管理相关
    STM32 SPI双机通信参考
    IAR_UCOSII_UCOSIII
    每日总结
    每日总结
  • 原文地址:https://www.cnblogs.com/fishpro/p/7874992.html
Copyright © 2011-2022 走看看