前言:經(jīng)常使用Objects.equals(a,b)方法的同學(xué) 應(yīng)該或多或少都會因?yàn)榇中亩鴤麇e參, 例如日常開發(fā)中 我們使用Objects.equals去比較 status(入?yún)?,statusEnum(枚舉), 很容易忘記statusEnum.getCode() 或 statusEnum.getVaule() ,再比如 我們比較一個訂單code時 orderCode(入?yún)?,orderDTO(其它業(yè)務(wù)對象) 很容易忘記orderDTO.getCode() 因?yàn)镺bjects.equals()兩個參數(shù)都是Object類型,idea默認(rèn)不會提示告警, 如果經(jīng)常使用該方法 你一定很清楚的明白我在說什么。
針對以上痛點(diǎn),博主編寫了一個idea插件: Equals Inspection , 插件代碼本身很簡單,極其輕量級。難得的是 在目前暫沒發(fā)現(xiàn)有人做了這件事時,而博主想到了可以通過IDE告警方式去解決問題,并且實(shí)際行動了。此外,知道該用什么API本身是件不容易的事,而閱讀代碼時,已經(jīng)處于一個上帝視角,則會顯得非常簡單。
下載一(推薦):
idea插件市場搜索: Equals Inspection
下載二:
github : https://github.com/qiuhuanhen/objects-equals-inspect/releases
安裝方式:1.idea內(nèi)插件下載會自動安裝 2. github下載直接將jar包拖進(jìn)idea,重啟idea
Q:為什么是IDE插件層面,而不是在java項(xiàng)目中重寫一個工具類 針對類型判斷呢?
A:
1.效率問題:java項(xiàng)目代碼判斷 說明要執(zhí)行到該方法時才能校驗(yàn),很多時候我們編寫完,在測試環(huán)節(jié)被提了bug,我們自己斷點(diǎn)執(zhí)行一遍,才能發(fā)現(xiàn)傳錯了參,插件層面在我們編寫時即可提醒,節(jié)省了大量時間.
2.設(shè)計問題: 很重要的一點(diǎn),java項(xiàng)目層面的提示,要怎么提示?throw new RuntimeExection? 顯然不太合理吧,例如在設(shè)計一些框架/通用代碼時,類型就是可以不一致 難道拋一個異常阻止程序運(yùn)行嗎?插件盡管會提示報錯,但它歸根結(jié)底都只是一個樣式,并不會阻止程序運(yùn)行。
使用前后效果對比:
使用前沒有告警
使用后示例:
vo.getStatus(Integer類型)與枚舉比較時,能直接提示我們類型不一致
(正確寫法是StatusEnum.AWAIT.getValue() 與枚舉類型的值進(jìn)行比較)
以下就以博主編寫的插件為例 ,寫一篇如何編寫idea插件的教程
注:本文由csdn博主 孟秋與你 編寫,如您在其它地方看到本文,很可能是被其它博主爬蟲/復(fù)制過來的,文章可能會持續(xù)更新,強(qiáng)烈建議您搜索:孟秋與你csdn 找到原文查看
第一步:創(chuàng)建插件項(xiàng)目
tips:
1.需要jdk11
2.以idea2021.1版本為例,不同idea版本可能有所差異
new project ->IntelliJ Platform Plugin-> Project SDK (需要jdk11)
第二步:修改plugin.xml文件內(nèi)容及創(chuàng)建java代碼
其中plugin.xml的description節(jié)點(diǎn),需要40個字符以上,否則插件上傳時會報錯。
編寫插件的核心難點(diǎn)在于,我們不知道idea的api是什么,什么情況用什么api。
以下是可以參考的幾點(diǎn):
- idea官方文檔 https://plugins.jetbrains.com/docs/intellij/welcome.html
- github idea 示例項(xiàng)目:https://github.com/JetBrains/intellij-sdk-code-samples
<idea-plugin>
<id>csdn-mengqiuyuni</id>
<name>Equals參數(shù)類型檢查</name>
<version>0.1.0</version>
<vendor email="1005738053@qq.com" url="https://blog.csdn.net/qq_36268103"> </vendor>
<description><![CDATA[
<li>check java.lang.Objects equals method params type ,if not match,idea will show the error line</li><br>
<li>could reduce Objects.equals(a,b) error params type by mistake</li><br>
<li>notice:this plugin can only inspect your code,it's just reminder java developers,but don't impact code execution,and never change or fix your code.</li>
]]></description>
<change-notes><![CDATA[
<li>github:qiuhuanhen,project name :objects-equals-inspect</li><br>
<li>beta version.csdn:孟秋與你</li><br>
<li>the first beta version,welcome,update date:2024.01.09</li>
]]>
</change-notes>
<vendor>qiuhuanhen</vendor>
<!-- please see https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html for description -->
<idea-version since-build="173.0"/>
<!-- please see https://plugins.jetbrains.com/docs/intellij/plugin-compatibility.html
on how to target different products -->
<depends>com.intellij.modules.platform</depends>
<depends>com.intellij.java</depends>
<depends>com.intellij.modules.java</depends>
<extensions defaultExtensionNs="com.intellij">
<localInspection
language="JAVA"
displayName="Title"
groupPath="Java"
groupBundle="messages.InspectionsBundle"
groupKey="group.names.probable.bugs"
enabledByDefault="true"
level="ERROR"
implementationClass="com.qiuhuanhen.ObjectsEqualsInspection"/><!--java類所在路徑-->
</extensions>
</idea-plugin>
package com.qiuhuanhen;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
/**
* @author qiuhuanhen
*/
public class ObjectsEqualsInspection extends LocalInspectionTool {
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
return new MyVisitor(holder);
}
private static class MyVisitor extends JavaElementVisitor {
private final ProblemsHolder holder;
public MyVisitor(ProblemsHolder holder) {
this.holder = holder;
}
@Override
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
String methodName = expression.getMethodExpression().getReferenceName();
if ("equals".equals(methodName)) {
PsiExpressionList argumentList = expression.getArgumentList();
PsiExpression[] expressions = argumentList.getExpressions();
if (expressions.length == 2) {
PsiType arg1Type = expressions[0].getType();
PsiType arg2Type = expressions[1].getType();
// 都為空 不做提示 注:即使idea會提示 type不為空 ,為防止插件報NPE 還是有大量的非空判斷
if (null == arg1Type && null == arg2Type) {
return;
}
// 其一為空 給出錯誤提示
if (null == arg1Type || null == arg2Type) {
holder.registerProblem(expression, "Objects.equals parameters are not of the same type.", ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
return;
}
// 這是忽視某些通用類,框架 用于比較反射class類型的情況
if (arg1Type.getCanonicalText().contains("Class") && arg2Type.getCanonicalText().contains("Class")) {
return;
}
if (isByte(arg1Type) && isByte(arg2Type)) {
return;
}
if (isShort(arg1Type) && isShort(arg2Type)) {
return;
}
if (isInt(arg1Type) && isInt(arg2Type)) {
return;
}
if (isLong(arg1Type) && isLong(arg2Type)) {
return;
}
if (isFloat(arg1Type) && isFloat(arg2Type)) {
return;
}
if (isDouble(arg1Type) && isDouble(arg2Type)) {
return;
}
if (isChar(arg1Type) && isChar(arg2Type)) {
return;
}
if (isBoolean(arg1Type) && isBoolean(arg2Type)) {
return;
}
if (!arg1Type.equals(arg2Type)) {
holder.registerProblem(expression, "Objects.equals parameters are not of the same type.", ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
}
}
}
}
private boolean isInt(PsiType type) {
PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(type);
if (PsiType.INT.equals(unboxedType)) {
// 是 int 類型
return true;
}
return PsiType.INT.equals(type) || "java.lang.Integer".equals(type.getCanonicalText());
}
private boolean isLong(PsiType type) {
PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(type);
if (PsiType.LONG.equals(unboxedType)) {
// 是 long 類型
return true;
}
return PsiType.LONG.equals(type) || "java.lang.Long".equals(type.getCanonicalText());
}
private boolean isDouble(PsiType type) {
PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(type);
if (PsiType.DOUBLE.equals(unboxedType)) {
return true;
}
return PsiType.DOUBLE.equals(type) || "java.lang.Double".equals(type.getCanonicalText());
}
private boolean isFloat(PsiType type) {
PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(type);
if (PsiType.FLOAT.equals(unboxedType)) {
return true;
}
return PsiType.FLOAT.equals(type) || "java.lang.Float".equals(type.getCanonicalText());
}
private boolean isBoolean(PsiType type) {
PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(type);
if (PsiType.BOOLEAN.equals(unboxedType)) {
return true;
}
return PsiType.BOOLEAN.equals(type) || "java.lang.Boolean".equals(type.getCanonicalText());
}
private boolean isByte(PsiType type) {
PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(type);
if (PsiType.BYTE.equals(unboxedType)) {
return true;
}
return PsiType.BYTE.equals(type) || "java.lang.Byte".equals(type.getCanonicalText());
}
private boolean isChar(PsiType type) {
PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(type);
if (PsiType.CHAR.equals(unboxedType)) {
return true;
}
return PsiType.CHAR.equals(type) || "java.lang.Char".equals(type.getCanonicalText());
}
private boolean isShort(PsiType type) {
PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(type);
if (PsiType.SHORT.equals(unboxedType)) {
return true;
}
return PsiType.SHORT.equals(type) || "java.lang.Short".equals(type.getCanonicalText());
}
}
}
第三步:打成jar包
沒有main方法則不用選擇main class
第四步:發(fā)布插件
發(fā)布插件沒有什么難點(diǎn),唯一值得注意的是description非常嚴(yán)格,必須要40個字符以上,且不能有非拉丁字符,博主在反復(fù)修改后發(fā)現(xiàn)不能有任何中文,最后把description里面的中文都改成了英文。
插件項(xiàng)目源碼地址:https://github.com/qiuhuanhen/objects-equals-inspect
打開項(xiàng)目方式:
在github下載博主的項(xiàng)目,idea打開后 默認(rèn)是常規(guī)項(xiàng)目,這時我們需要稍作處理
最后一步:文章來源:http://www.zghlxwxcb.cn/news/detail-798098.html
最后: 原創(chuàng)不易 ,歡迎各位在idea插件商店下載 Equals Inspection , 給github項(xiàng)目點(diǎn)上star 非常感謝各位文章來源地址http://www.zghlxwxcb.cn/news/detail-798098.html
到了這里,關(guān)于【idea】idea插件編寫教程,博主idea插件已上架idea插件市場 歡迎下載的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!