什么是静态分析?
静态分析是在不执行应用程序的情况下对源代码进行自动分析。
当分析是在程序执行过程中进行的,那么它就被称为动态分析。
静态分析通常用于检测。
- 安全漏洞。
- 性能问题。
- 不符合标准。
- 使用过时的编程结构。
静态分析工具是如何工作的?
所有静态分析工具共同的基本概念是搜索源代码,以确定具有某种警告或与之相关的信息的特定编码模式。
这可能是简单的 "JUnit 5测试类不需要是'公共'的"。或者是一些复杂的识别,如 "在SQL执行语句中使用了不可信任的字符串输入"。
静态分析工具在实现这一功能的方式上有所不同。
- 源代码解析技术来创建一个抽象语法树(AST)。
- 文本正则表达式匹配。
- 上述各项的组合。
正则表达式对文本的匹配非常灵活,很容易写出匹配规则,但往往会导致大量的误报,而且匹配规则对周围的代码环境一无所知。
AST匹配将源代码视为程序代码,而不仅仅是充满文本的文件,这允许更具体、更有背景的匹配,并可以减少针对代码报告的误报数量。
持续集成中的静态分析
静态分析通常是在持续集成(CI)过程中进行的,以生成一份合规性问题的报告,该报告可以被审查以获得代码库随时间变化的客观观点。
有些人通过配置静态分析工具,使其只测量代码的特定部分,并且只报告规则的子集,从而将静态分析作为其代码质量的客观测量。
客观性是由所使用的规则提供的,因为这些规则在评估代码时不会随时间而变化。显然,所使用的规则的组合及其配置是一个主观的决定,不同的团队在不同的时间选择使用不同的规则。
在CI中进行静态分析是有用的,但可能会延迟对程序员的反馈。程序员在编码时并没有收到反馈,他们是在以后通过静态分析工具运行代码时收到反馈。在CI中运行静态分析的另一个副作用是,结果更容易被忽略。
为了帮助团队更加关注静态分析的结果,通常可以在构建过程中配置一个阈值指标,如果超过该指标,例如触发了一些规则,则构建失败。
IDE中的静态分析
为了更快地收到反馈,有许多IDE插件可以在IDE中按需运行静态分析规则,或在代码变化时定期运行。
当程序员在写代码时,可以在IDE中看到违反规则的情况,为了使规则更难被忽视,通常可以将违反规则的情况配置为在编辑器中呈现下划线的代码。
我个人认为这是一种改进我的编码的有用方法,特别是当使用静态分析工具所涵盖的新库时。虽然它可能会有假阳性的 "噪音",或者你不感兴趣的规则。但这可以通过采取额外步骤配置静态分析工具以忽略某些规则来解决。
基于静态分析规则修复代码
在大多数静态分析工具中,规则的修复是留给程序员的,所以他们必须了解违反规则的原因以及如何修复它。
很少有静态分析工具还包括修复违规的能力,因为修复往往是根据团队和所使用的技术以及他们商定的编码风格来进行的。
默认规则
当静态分析工具带有默认的规则时,可能会对规则的质量产生错误的信心,很容易让人相信它们涵盖了程序员可能遇到的所有问题,以及规则应该适用的所有情况。有时,一个规则应该适用的情况可能很微妙,而且不容易被发现。
希望通过使用静态分析工具,并更详细地研究规则和违规行为,程序员将发展出在其特定领域背景下检测和避免问题的技能。
当领域需要上下文规则时,静态分析工具可能没有任何与你的领域或库相匹配的规则,此外,这些工具往往难以配置和扩展。
烦人的事
这些 "烦恼 "都不是不可克服的。
- 假阳性反应
- 缺乏修复
- 忽略规则的配置
- 添加特定环境的规则
但它们经常被用作借口,以避免首先使用静态分析工具,这是一个遗憾,因为使用静态分析可以非常有用,作为一种方法。
- 突出强调对初级开发人员的更好方法
- 对明显违反编码规定的行为获得快速反馈
- 确定程序员以前没有遇到过的晦涩难懂的问题
- 强化程序员采用了良好的编码方法(当没有报告违反情况时
基于IDE的静态分析工具
作为一个项目的个人贡献者,我喜欢使用在IDE中运行的静态分析工具,这样我就能快速收到对我的代码的反馈。
这补充了任何拉动请求的审查过程,以及一个项目可能有的CI整合。
我试图找出能给我带来优势的工具,并改善我的个人工作流程。
当工具在IDE中运行时,因为它们往往共享相同的基本GUI和配置方法,所以很容易将它们互换起来看待。
这些工具可能有重叠的功能或规则集,但为了获得最大的优势,我安装了多个工具来利用它们的优势。
我在编码时积极使用的静态分析IDE工具列举如下。
- 内置的IntelliJ检查 - 常见的编码模式
- SpotBugs - 常见错误
- SonarLint--常见的使用模式
- CheckStyle--常见的风格模式
- Sensei 来自Secure Code Warrior - 自定义规则创建
我使用它们是因为它们能很好地一起工作,相互增强和补充。
英特利杰检查
如果你使用IntelliJ,那么你已经在使用他们的检查。
这些是静态分析规则,在IDE中被标记出来。其中一些还有快速修复选项,可以重写代码以解决这个问题。
这些规则可配置为开启和关闭,并可选择用于在IDE中突出显示的错误级别。
有很多好的IntelliJ检查报告。我知道这一点,因为我在写这篇文章时阅读了它们。我把IntelliJ检查作为默认值,并没有对其进行配置,但为了从检查中获得充分的价值,你应该阅读它们,识别那些与你的编码风格相关的内容,并配置警告级别,以便你在代码中注意到它们。
IntelliJ检查的伟大之处在于,它们是随IDE免费提供的,它们有助于建立肌肉记忆。
- 在写代码时注意到源代码中的警告和错误
- 将鼠标悬停在被标记的代码上,了解违反规则的情况
- 使用alt+enter来应用问题的快速修复方法
斑点虫
SpotBugsIntelliJ插件使用静态分析来尝试并提醒你注意代码中的错误。
SpotBugs可以从IntelliJ首选项中配置来扫描你的代码,实际使用的规则可以在检测器标签中找到。
我倾向于在写完和审查完我的代码后使用SpotBugs,然后我会运行 "分析项目文件包括测试源"。
这确实有助于我识别错误、死代码和明显的优化。它还迫使我研究一些被标记的违规行为,以帮助我决定做什么。
SpotBugs将发现问题,但不提供任何试图解决问题的快速修复行动。
SpotBugs很容易配置,我发现它是一个有用的客观的第二意见,可以在我的IDE中咨询。
声波提示器(SonarLint)
SonarLint插件。
SonarLint可以从IntelliJ首选项中进行配置,以选择对代码进行验证的规则。
默认情况下,SonarLint是实时运行的,显示你正在编辑的当前代码的问题。
SonarLint不提供快速修复,但与违规报告相关的文件通常都很清楚,而且记录得很好。
我发现SonarLint在过去很有用,它能提醒我注意到较新版本的Java的新功能。
检查风格
CheckStyle插件提供了一个混合的格式化和代码质量规则。
CheckStyle插件与 "Sun Checks "和 "Google Checks "捆绑在一起。
这些的定义可以在网上很容易找到。
当一个项目花时间创建自己的规则集时,CheckStyle会增加最大的价值。然后,IDE插件可以被配置为使用该规则集,程序员可以在提交代码到CI之前进行扫描。
当违反CheckStyle的数量超过一个阈值时,CheckStyle通常被用作CI流程的构建失败插件。
Sensei
Sensei使用基于抽象语法树(AST)的静态分析来匹配代码和创建快速修复,这允许非常具体地识别有问题的代码。
AST允许与配方相关的QuickFixes理解周围的代码,例如,当在代码中添加一个新的类时,该类的任何导入将只被添加到源文件中一次,而不是为每个替换。
创建Sensei ,是为了方便建立自定义的匹配规则,这些规则在其他工具中可能不存在,或者难以配置。
所有的配置都可以在GUI中进行,而不是修改一个配置文件。当创建新的配方时,GUI可以很容易地看到配方所匹配的代码。当定义快速修复时,代码的前后状态可以立即被比较。这使得它更容易创建非常有背景的配方,即对团队或技术,甚至对个别程序员来说是独一无二的。
我将Sensei 与其他静态分析工具结合使用,例如,大多数静态分析工具会发现问题,但不会修复它们。Sensei 的一个常见用例是在Sensei 中复制其他工具的匹配搜索,并通过快速修复来扩展它。这样做的好处是,应用的自定义修复已经符合你项目的编码标准。
我经常发现自己创建的Sensei ,在IntelliJ Intensions集中已经存在,因为Intension报告与我创建的上下文不太匹配,或者因为IntelliJ提供的QuickFix与我想使用的代码模式不匹配。
我增强了现有的工具,而不是试图完全取代它们。
Sensei ,当你确定一个普通规则的上下文变体时,也是非常有用的,例如,如果你使用的是静态分析工具不支持的SQL库,但静态分析引擎中的普通SQL规则仍然适用,那么你可以使用Sensei ,创建这些规则的特定库变体。
Sensei 不像上面提到的静态分析工具那样开箱就有大量的通用配方,它的优势在于可以很容易地创建新的配方,完成快速修复的配置,以适应你的特定编码风格和使用情况。
注意:我们正在开发一个公共配方库,以涵盖一般的使用情况。 你可以在这里找到它.
摘要
我倾向于选择那些能一起工作的、可配置的、易于扩展的工具,以满足我的特定环境。多年来,我一直在IDE中使用静态分析工具来帮助我识别问题,并更多地了解我使用的编程语言和库。
我结合使用上述所有的工具。
- IntelliJ Intentions帮助标记出开箱即用的常见代码问题,通常有相关的快速修复方法。
- SpotBugs可以发现我可能错过的简单错误,并提醒我注意性能问题。
- SonarLint识别了我不知道的Java特性,并提示我用更多的方法来模拟我的代码。
- CheckStyle帮助我遵守约定的编码风格,在CI期间也会强制执行。
- Sensei 帮助我创建QuickFixes,以增强静态分析工具发现的常见情况,并创建在其他工具中难以配置的特定项目或技术配方。
---
使用 "Preferences \ Plugins"(Mac)或 "Settings \ Plugins"(Windows)从IntelliJ内部安装Sensei ,然后搜索 "sensei secure code "即可。
你可以在Secure Code Warrior GitHub账户中的 "sensei-blog-examples "项目中找到常见使用情况的示例代码和配方库。
https://github.com/securecodewarrior/sensei-blog-examples
了解更多关于Sensei