網(wǎng)站開發(fā)使用的技術有哪些百度信息流推廣平臺
前言:經(jīng)常使用Objects.equals(a,b)方法的同學 應該或多或少都會因為粗心而傳錯參, 例如日常開發(fā)中 我們使用Objects.equals去比較 status(入?yún)?,statusEnum(枚舉), 很容易忘記statusEnum.getCode() 或 statusEnum.getVaule() ,再比如 我們比較一個訂單code時 orderCode(入?yún)?,orderDTO(其它業(yè)務對象) 很容易忘記orderDTO.getCode() 因為Objects.equals()兩個參數(shù)都是Object類型,idea默認不會提示告警, 如果經(jīng)常使用該方法 你一定很清楚的明白我在說什么。
針對以上痛點,博主編寫了一個idea插件: Equals Inspection , 插件代碼本身很簡單,極其輕量級。難得的是 在目前暫沒發(fā)現(xiàn)有人做了這件事時,而博主想到了可以通過IDE告警方式去解決問題,并且實際行動了。此外,知道該用什么API本身是件不容易的事,而閱讀代碼時,已經(jīng)處于一個上帝視角,則會顯得非常簡單。
Q:為什么是IDE插件層面,而不是在java項目中重寫一個工具類 針對類型判斷呢?
A:
1.效率問題:java項目代碼判斷 說明要執(zhí)行到該方法時才能校驗,很多時候我們編寫完,在測試環(huán)節(jié)被提了bug,我們自己斷點執(zhí)行一遍,才能發(fā)現(xiàn)傳錯了參,插件層面在我們編寫時即可提醒,節(jié)省了大量時間.
2.設計問題: 很重要的一點,java項目層面的提示,要怎么提示?throw new RuntimeExection? 顯然不太合理吧,例如在設計一些框架/通用代碼時,類型就是可以不一致 難道拋一個異常阻止程序運行嗎?插件盡管會提示報錯,但它歸根結底都只是一個樣式,并不會阻止程序運行。
使用前后效果對比:
使用前沒有告警
使用后示例:
vo.getStatus(Integer類型)與枚舉比較時,能直接提示我們類型不一致
(正確寫法是StatusEnum.AWAIT.getValue() 與枚舉類型的值進行比較)
以下就以博主編寫的插件為例 ,寫一篇如何編寫idea插件的教程
注:本文由csdn博主 孟秋與你 編寫,如您在其它地方看到本文,很可能是被其它博主爬蟲/復制過來的,文章可能會持續(xù)更新,強烈建議您搜索:孟秋與你csdn 找到原文查看
第一步:創(chuàng)建插件項目
tips:
1.需要jdk11
2.以idea2021.1版本為例,不同idea版本可能有所差異
new project ->IntelliJ Platform Plugin-> Project SDK (需要jdk11)
第二步:修改plugin.xml文件內容及創(chuàng)建java代碼
其中plugin.xml的description節(jié)點,需要40個字符以上,否則插件上傳時會報錯。
編寫插件的核心難點在于,我們不知道idea的api是什么,什么情況用什么api。
以下是可以參考的幾點:
- idea官方文檔 https://plugins.jetbrains.com/docs/intellij/welcome.html
- github idea 示例項目: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.htmlon 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"><localInspectionlanguage="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@Overridepublic 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;}@Overridepublic 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ā)布插件沒有什么難點,唯一值得注意的是description非常嚴格,必須要40個字符以上,且不能有非拉丁字符,博主在反復修改后發(fā)現(xiàn)不能有任何中文,最后把description里面的中文都改成了英文。
插件項目源碼地址:https://github.com/qiuhuanhen/objects-equals-inspect
下載一:( idea團隊給博主發(fā)了郵件 插件最開始的命名不規(guī)范 目前在重新審核 不知道后續(xù)結果 先在github下載吧)
idea插件商店搜索: Equals Inspection
下載二:github https://github.com/qiuhuanhen/objects-equals-inspect
releases區(qū)
安裝方式:1. 直接將jar包拖進idea,2.重啟idea
打開項目方式:
在github下載博主的項目,idea打開后 默認是常規(guī)項目,這時我們需要稍作處理
最后一步:
最后: 原創(chuàng)不易 ,歡迎各位在idea插件商店下載Equals Inspection , 給github項目點上star 非常感謝各位