首页 > 其他分享 >创建Idea静态代码扫描工具

创建Idea静态代码扫描工具

时间:2024-07-26 13:51:50浏览次数:12  
标签:set return intellij 静态 扫描 Idea element com annotation

背景

近期公司框架升级,代码和配置的变动较大。为了保证升级的质量,开发了一个静态代码扫描工具,供所有开发者使用。此工具专注于检查异步方法中线程变量(例如myThreadlocal)的使用情况。

项目设置

版本

  • JDK 1.8
  • IntelliJ IDEA 2022
  • 基于 Gradle 构建插件

项目创建步骤

1. 新建项目

使用 IntelliJ IDEA 创建一个新的 Gradle 项目,并配置基本的项目结构。

2. 创建异步方法扫描类

新建一个 Java 类 AsyncInspection 来定义扫描逻辑。

package com.dxz.demo;

import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;

public class AsyncInspection extends AbstractBaseJavaLocalInspectionTool {

    private static final Logger LOG = Logger.getInstance(AsyncInspection.class);

    @Override
    @NotNull
    public String getShortName() {
        return "AsyncInspection";
    }

    @Override
    public String getGroupDisplayName() {
        return "WalletInspection";
    }

    @Override
    public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
        return new JavaElementVisitor() {
            @Override
            public void visitMethodCallExpression(PsiMethodCallExpression expression) {
                super.visitMethodCallExpression(expression);
                if (isAsyncMethodCall(expression)) {
                    LOG.info("AsyncInspection " + expression.getText());
                    checkTntCodeUsage(expression, holder);
                }
            }

            @Override
            public void visitAnnotation(PsiAnnotation annotation) {
                super.visitAnnotation(annotation);
                if (isAsyncAnnotation(annotation)) {
                    PsiElement parent = annotation.getParent().getParent();
                    if (parent instanceof PsiMethod) {
                        PsiMethod method = (PsiMethod) parent;
                        checkTntCodeUsage(method.getBody(), holder);
                    }
                }
            }
        };
    }

    private boolean isAsyncMethodCall(PsiMethodCallExpression expression) {
        String methodName = expression.getMethodExpression().getReferenceName();
        return "runAsync".equals(methodName) || "supplyAsync".equals(methodName);
    }

    private boolean isAsyncAnnotation(PsiAnnotation annotation) {
        String qualifiedName = annotation.getQualifiedName();
        return "org.springframework.scheduling.annotation.Async".equals(qualifiedName);
    }

    private void checkTntCodeUsage(PsiElement element, ProblemsHolder holder) {
        if (element != null && !containsTntCode(element)) {
            holder.registerProblem(element, "Possible missing myThreadlocal usage in async method.");
        }
    }

    private boolean containsTntCode(PsiElement element) {
        if (element instanceof PsiReferenceExpression) {
            String text = element.getText();
            if (text.contains("MyThreadlocal") || text.contains("myThreadlocal")) {
                return true;
            }
        }

        for (PsiElement child : element.getChildren()) {
            if (containsTntCode(child)) {
                return true;
            }
        }

        return false;
    }
}

 

3. 配置 Gradle 构建脚本

build.gradle 中添加以下内容:

plugins {
    id 'java'
    id 'org.jetbrains.intellij' version '1.8.0'
}

group = 'com.dxz'
version = '1.0.2.2021.3'

repositories {
    mavenCentral()
}

intellij {
    version.set('2021.3.3')
    type.set('IC')
    plugins.set(['com.intellij.java'])
}

dependencies {
    implementation 'org.jetbrains:annotations:21.0.1'
}

tasks.withType(JavaCompile) {
    sourceCompatibility = '11'
    targetCompatibility = '11'
}

patchPluginXml {
    sinceBuild.set('213')
    untilBuild.set('223.*')
}

signPlugin {
    certificateChain.set(System.getenv('CERTIFICATE_CHAIN'))
    privateKey.set(System.getenv('PRIVATE_KEY'))
    password.set(System.getenv('PRIVATE_KEY_PASSWORD'))
}

publishPlugin {
    token.set(System.getenv('PUBLISH_TOKEN'))
}

 

4. 配置 plugin.xml

创建 plugin.xml 文件以配置插件元数据:

<idea-plugin>
    <id>com.dxz.demo</id>
    <name>demo-inspection</name>
    <vendor email="[email protected]" url="https://www.yourcompany.com">duanxz</vendor>
    <description><![CDATA[
        我的第一个扫描工具,异步方法中的线程变量处理检测。
    ]]></description>
    <depends>com.intellij.modules.platform</depends>
    <extensions defaultExtensionNs="com.intellij">
        <localInspection language="JAVA"
                         shortName="AsyncInspection"
                         displayName="Absence of myThreadlocal Inspection"
                         groupDisplayName="Wallet Inspections"
                         implementationClass="com.dxz.AsyncInspection"/>
    </extensions>
</idea-plugin>

 

5. 打包构建

在 IntelliJ IDEA 中,使用 gradle buildPlugin 命令进行构建。成功后,在 build/distributions 目录下会生成相应的 zip 文件。

6. 插件安装与使用

在 IDEA 中安装生成的插件,然后从菜单栏选择 Code -> Inspect Code 运行静态代码扫描。

总结

通过这个静态扫描工具,可以有效地检查异步方法中的线程变量使用情况,确保代码质量,为框架升级提供保障。

标签:set,return,intellij,静态,扫描,Idea,element,com,annotation
From: https://www.cnblogs.com/duanxz/p/18325205

相关文章

  • 手写字稿扫描方法
    手写字稿扫描方法本教程由做字体网(www.zuoziti.com)友情提供!本教程是制作手写字体系列教程,建议从序言部分开始阅读学习!如需交流,请加QQ924268440本节视频教程写完的手写字稿是这样的前面我们设计好了手写模板,并选好了书写笔,剩下的就是工工整整地书写了,这个过程大约要......
  • Abaqus施加恒定载荷:选择静态分析步还是动态分析步?
    Abaqus施加恒定载荷用静态还是动态分析步?在探究这个问题前,我们先来搞清楚什么叫恒定载荷。在Abaqus中,恒定载荷是指在整个分析过程中保持不变的载荷。这意味着在应用恒定载荷时,加载大小和方向将保持不变,直到分析结束或者手动更改为其他载荷类型。恒定载荷通常用于模拟静态加载情......
  • 【nacos】记一次使用NacosExploitGUI扫描发现nacos安全漏洞
    一、场景   公司使用nacos作为配置和注册中心,使用的版本是1.4.0 二、下载NacosExploitGUIhttps://github.com/charonlight/NacosExploitGUI下载release中的压缩包  三、运行NacosExploitGUI1、运行$java-jarNacosExploitGUI_v4.0.jarError:JavaFXruntime......
  • java静态代码检测-checkstyle
    要想使用checkstyle,需要在代码仓库中做一些配置 1.在maven项目的pom.xml文件中,加入checkstyle的依赖包:UpgradingCheckstylereference:  https://maven.apache.org/plugins/maven-checkstyle-plugin/examples/upgrading-checkstyle.html<project>...<build>......
  • vite 静态离线无服务器部署 方案
    第一、第二种方案importpathfrom"path";import{defineConfig}from"vite";importvuefrom"@vitejs/plugin-vue";importvueJsxfrom"@vitejs/plugin-vue-jsx";import{viteSingleFile}from"vite-plugin-si......
  • 使用 IntelliJ IDEA 脚手架快速搭建 Spring Boot 项目
    使用IntelliJIDEA脚手架快速搭建SpringBoot项目大家好!今天我们来聊聊如何使用IntelliJIDEA脚手架快速搭建一个SpringBoot项目。SpringBoot是一个非常流行的Java框架,它简化了Spring应用的开发过程。而IntelliJIDEA则是一个功能强大的IDE,能够大大提高我们的......
  • IDEA社区版创建Web项目环境
    问题:IDEA社区版缺少Web项目的插件,可以借助maven创建一个web项目环境。基础环境:IDEA社区版2024.1.4maventomcat1.maven部署配置:不多说,抄作业2.tomcat部署配置:再抄3.IDEA社区版借助maven搭建Web开发环境:还抄主要的问题在于IDEA的版本不一致,在使用maven时,需要附加属性的......
  • C++中的四种类型转换(静态、动态、常量、重新解释。
    在C++中,类型转换是编程语言中的一个重要概念,它允许我们将一种数据类型的值转换为另一种数据类型。C++提供了四种主要的类型转换方式:静态类型转换(StaticCast)、动态类型转换(DynamicCast)、常量类型转换(ConstCast)和重新解释类型转换(ReinterpretCast)。每种转换都有其特定的用途......
  • 关于kali扫描不到靶机的解决方法
    关于kali扫描不到靶机的解决方法前情提要这里使用的都是VMware,因为Vulnhub的靶场都是适配于VirtualBox,因此在使用VMware开启Vulnhub的靶场的时候,靶机大概率会出现获取不到IP地址的情况,因此我们需要修改一些配置,来使得靶机可以获取IP地址。前提在开始之前我们首先要确保攻击......
  • IntelliJ IDEA使用技巧,粘贴内容
    这个技巧我最常用于网页制作举一个简单的例子,实现下面的网页这就是简单的一份html代码,首先我们生成5个li元素,接下来就是将文字粘贴到li元素,掌握下面这个技巧我们就不需要将光标一行一行移动再ctrl+v,直接鼠标一滑动ctrl+v即可<li></li><li></li><li></li><li></li><li></li......