美文网首页
OCLINT自定义规则-长函数限定LongMethodRule

OCLINT自定义规则-长函数限定LongMethodRule

作者: 熊猫人和熊猫君 | 来源:发表于2018-07-07 16:17 被阅读0次

    目的:

    总所周知,优雅的代码结构,可以使代码结构更清晰,维护更方便。但,不是团队的每一个成员都有如此编写习惯,在codereview的时候可能需要人为去审核提出建议。这样做人力成本大。而此脚本急速oclint自定义检查校验长函数的动态库脚本。

    思路剖析:

    1.寻找AST函数定义,分为VisitObjCMethodDecl与VisitFunctionDecl,其中VisitObjCMethodDecl为oc方法定义,VisitFunctionDecl为c函数定义。
    2.访问到函数定义后可根据Stmt和文件管理器SourceManager计算出该函数的带代码总个数

    
    class LongMethodRule : public AbstractASTVisitorRule<LongMethodRule>
    {
    private:
        void applyDecl(Decl *decl)
        {
            //hasBody函数有实现内容吗
            if (decl->hasBody() &&
                !isCppMethodDeclLocatedInCppRecordDecl(dyn_cast<CXXMethodDecl>(decl)))
            {
                //有实现
                Stmt *stmt = decl->getBody();
                //计算函数里面代码总长度,getLineCount为帮助函数,后面有其方法
                int length = getLineCount(stmt->getSourceRange(), _carrier->getSourceManager());
                //oclint自身配置的长度可以调整修改
                int threshold = RuleConfiguration::intForKey("LONG_METHOD", 50);
                if (length > threshold)
                {
                    //告警
                    string description = "Method with " +
                        toString<int>(length) + " lines exceeds limit of " + toString<int>(threshold);
                    addViolation(decl, this, description);
                }
            }
        }
    
    public:
        virtual const string name() const override
        {
            return "long method";
        }
    
        virtual int priority() const override
        {
            return 3;
        }
    
        virtual const string category() const override
        {
            return "size";
        }
    
    #ifdef DOCGEN
        virtual const std::string since() const override
        {
            return "0.4";
        }
    
        virtual const std::string description() const override
        {
            return "Long method generally indicates that this method tries to do many things. "
                "Each method should do one thing and that one thing well.";
        }
    
        virtual const std::string example() const override
        {
            return R"rst(
    .. code-block:: cpp
    
        void example()
        {
            cout << "hello world";
            cout << "hello world";
            // repeat 48 times
        }
            )rst";
        }
    
        virtual const std::map<std::string, std::string> thresholds() const override
        {
            std::map<std::string, std::string> thresholdMapping;
            thresholdMapping["LONG_METHOD"] =
                "The long method reporting threshold, default value is 50.";
            return thresholdMapping;
        }
    #endif
        //oc函数:如果ViewController里面的- (void)viewDidLoad
        bool VisitObjCMethodDecl(ObjCMethodDecl *decl)
        {
            applyDecl(decl);
            return true;
        }
        //c函数的函数定义,eg:void testMyFunction(){***}
        bool VisitFunctionDecl(FunctionDecl *decl)
        {
            applyDecl(decl);
            return true;
        }
    };
    
    static RuleSet rules(new LongMethodRule());
    

    帮助函数:总行数

    int getLineCount(clang::SourceRange sourceRange, const clang::SourceManager& sourceManager)
    {
        clang::SourceLocation startLocation = sourceRange.getBegin();
        clang::SourceLocation endLocation = sourceRange.getEnd();
        unsigned startLineNumber = sourceManager.getPresumedLineNumber(startLocation);
        unsigned endLineNumber = sourceManager.getPresumedLineNumber(endLocation);
        return endLineNumber - startLineNumber + 1;
    }
    

    相关文章

      网友评论

          本文标题:OCLINT自定义规则-长函数限定LongMethodRule

          本文链接:https://www.haomeiwen.com/subject/fevwuftx.html