Sonar(通常指SonarQube)是一款主流的静态代码分析工具,用于检测代码中的质量问题、安全漏洞、规范违背等问题。其核心目标是通过自动化分析提升代码质量,降低维护成本和潜在风险。
一、Sonar扫描代码的核心原理
Sonar的扫描过程本质是静态代码分析(无需运行代码即可检测问题),核心流程可分为以下几步:
1. 代码收集与预处理
- 扫描工具(如 sonar-scanner )从指定目录收集源代码文件(支持多语言,如Java、Python、JavaScript等)。
- 预处理:过滤无关文件(如编译产物、配置文件),识别代码的组织结构(如包、类、函数)。
2. 代码解析与抽象语法树(AST)生成
- 针对不同编程语言,Sonar使用对应的语言分析器(如Java的 sonar-java 插件、JavaScript的 sonar-javascript 插件)对代码进行语法解析。
- 将源代码转换为抽象语法树(AST):AST是代码的结构化表示,剥离了语法细节(如空格、注释),仅保留语法逻辑(如变量声明、条件判断、函数调用等)。
例如, if (a > b) { c = 1; } 的AST会清晰表示“条件判断节点”包含“比较表达式节点”和“赋值语句节点”。
3. 规则引擎与问题检测
- Sonar内置了大量规则(如“避免空指针异常”、“禁止硬编码密码”、“减少函数复杂度”等),这些规则被编码为可执行的检查逻辑。
- 规则引擎遍历AST,通过“模式匹配”或“逻辑判断”检测代码是否违反规则:
- 例如,“禁止未使用的变量”规则会遍历AST的变量声明节点,检查是否有引用该变量的节点
- “SQL注入风险”规则会检测字符串拼接SQL语句的模式(如 "SELECT * FROM users WHERE name = " + username )。
4. 结果聚合与报告生成
- 扫描完成后,工具将检测到的问题(按严重级别、类型分类)发送到SonarQube服务器。
- 服务器对结果进行聚合分析,生成可视化报告(如代码覆盖率、重复率、漏洞数量、技术债务等指标),并支持历史对比和趋势追踪。
二、如何制定/配置扫描代码的规则
Sonar的规则体系支持“内置规则复用”和“自定义规则开发”,具体可根据团队需求灵活配置:
1. 使用内置规则(基础配置)
SonarQube默认集成了数千条经过实践验证的规则(覆盖代码质量、安全、规范等维度),可直接通过界面配置启用/禁用或调整级别:
- 步骤1:登录SonarQube控制台,进入“Quality Profiles”(质量配置文件)。
- 步骤2:选择对应语言的配置文件(如“Sonar way”是默认配置),点击“Activate/Deactivate Rules”。
- 步骤3:根据需求筛选规则(按类型:Bug、Vulnerability(漏洞)、Code Smell;按严重级别:Blocker、Critical、Major等),勾选需要启用的规则。
- 步骤4:保存配置后,扫描时将自动应用该规则集。
Vulnerability是什么:漏洞,是安全层面的风险,及时功能正常的代码也可能存在漏洞,比如密码明文存储不影响功能,但存在严重安全风险
Code Smell 是什么:代码异味或代码坏味道,指代码中存在的表面性、结构性问题,本身不一定是语法错误或功能缺陷,但暗示了代码设计上或实现上可能存在更深层次的问题,可能影响代码的可读性、可维护性、扩展性、可测试性。总结就是代码的小瑕疵,初期不起眼,积累多了会让代码变得难以驾驭。
常见的Code smell类型:重复代码、过长函数、过大的类、未解释的数字、字符串、过渡注释、不一致的命名、过渡耦合、冗余代码等。
2. 自定义规则(进阶需求)
如果内置规则无法满足团队特定场景(如公司内部编码规范、业务相关的风险检查),可开发自定义规则:
- 核心思路:基于目标语言的AST,编写检测逻辑,打包为Sonar插件并部署到服务器。
- 开发步骤(以Java为例):
- 1)环境准备:使用Sonar提供的SDK(如 sonar-java-plugin 的API),基于Maven/Gradle创建项目。
- 2)编写规则逻辑:
- 定义规则元信息(名称、描述、严重级别、标签等)。
- 实现 IssuableSubscriptionVisitor 接口,通过重写 visitNode 方法遍历AST节点,编写检测逻辑(如检测特定函数调用、变量命名格式等)。
- public class ForbiddenMethodCheck extends IssuableSubscriptionVisitor {
- @Override
- public List<Tree.Kind> nodesToVisit() {
- // 关注方法调用节点
- return Collections.singletonList(Tree.Kind.METHOD_INVOCATION);
- }
-
- @Override
- public void visitNode(Tree tree) {
- MethodInvocationTree mit = (MethodInvocationTree) tree;
- // 检测是否调用了被禁止的方法(如Thread.sleep())
- if (mit.symbol().name().equals("sleep") &&
- mit.symbol().owner().name().equals("Thread")) {
- reportIssue(mit, "禁止使用Thread.sleep(),请使用定时任务框架");
- }
- }
- }
复制代码
- 3)打包与部署:
将规则代码打包为Jar插件,上传到SonarQube服务器的“Marketplace”或插件目录,重启服务器即可生效。
3. 规则管理的最佳实践
- 循序渐进:初期可基于内置规则集(如“Sonar way”),逐步添加自定义规则,避免因规则过多导致开发效率下降。
- 团队共识:规则需由开发、测试、安全团队共同评审,确保合理性(如某些“Code Smell”可能在特定场景下是合理的)。
- 定期迭代:根据项目反馈调整规则(如关闭误报率高的规则、新增高频问题的检测规则)。
- 结合场景:安全敏感项目(如支付系统)应重点启用安全类规则(如OWASP Top 10相关检测);长期维护的项目可加强代码可读性、复杂度相关规则。
通过以上方式,Sonar能够灵活适配不同团队的代码质量管理需求,从被动修复问题转变为主动预防问题。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |