From 43495e5c51185a9c4c234b5a17a76095ea2dc419 Mon Sep 17 00:00:00 2001 From: tangcent Date: Wed, 21 Apr 2021 06:20:27 +0800 Subject: [PATCH] feat: forbidden http access to distrust hosts (#441) --- .../idea/config/CachedResourceResolver.kt | 19 +- .../idea/plugin/actions/ApiDashBoardAction.kt | 4 + .../plugin/actions/YapiDashBoardAction.kt | 3 + .../idea/plugin/actions/YapiExportAction.kt | 3 + .../plugin/api/DefaultMethodInferHelper.kt | 21 +- .../core/AbstractRequestClassExporter.kt | 28 +- .../generic/GenericMethodDocClassExporter.kt | 16 +- .../SimpleGenericMethodDocClassExporter.kt | 6 +- .../export/markdown/MarkdownApiExporter.kt | 8 +- .../api/export/markdown/MarkdownFormatter.kt | 12 +- .../export/postman/DefaultPostmanApiHelper.kt | 28 +- .../api/export/postman/PostmanApiExporter.kt | 8 +- .../api/export/postman/PostmanApiHelper.kt | 6 - .../export/postman/PostmanCachedApiHelper.kt | 26 +- .../api/export/postman/PostmanFormatter.kt | 12 +- .../plugin/api/export/suv/SuvApiExporter.kt | 38 +-- .../export/yapi/AbstractYapiApiExporter.kt | 21 +- .../api/export/yapi/AbstractYapiApiHelper.kt | 160 +---------- .../api/export/yapi/DefaultYapiApiHelper.kt | 27 +- .../export/yapi/DefaultYapiApiInputHelper.kt | 216 --------------- .../plugin/api/export/yapi/YapiApiExporter.kt | 11 +- .../plugin/api/export/yapi/YapiApiHelper.kt | 14 - .../api/export/yapi/YapiApiInputHelper.kt | 71 ----- .../api/export/yapi/YapiCachedApiHelper.kt | 2 +- .../plugin/api/export/yapi/YapiFormatter.kt | 16 +- .../yapi/YapiSpringRequestClassExporter.kt | 15 +- .../export/yapi/YapiTokenCheckerSupport.kt | 16 ++ .../plugin/config/RecommendConfigReader.kt | 38 +-- .../dialog/AbstractApiDashboardDialog.kt | 24 +- .../idea/plugin/dialog/ApiDashboardDialog.kt | 23 +- .../idea/plugin/dialog/EasyApiSettingGUI.form | 50 +++- .../idea/plugin/dialog/EasyApiSettingGUI.kt | 22 +- .../plugin/dialog/ScriptExecutorDialog.kt | 10 +- .../idea/plugin/dialog/YapiDashboardDialog.kt | 81 +++--- .../idea/plugin/rule/RuleToolUtils.kt | 5 +- .../idea/plugin/rule/StandardJdkRuleParser.kt | 4 +- .../idea/plugin/settings/SettingBinder.kt | 4 + .../idea/plugin/settings/Settings.kt | 28 +- .../idea/plugin/settings/group/JsonSetting.kt | 33 --- .../helper/BuiltInConfigSettingsHelper.kt | 16 ++ .../settings/helper/CommonSettingsHelper.kt | 82 ++++++ .../settings/helper/HttpSettingsHelper.kt | 117 ++++++++ .../helper/IntelligentSettingsHelper.kt | 49 ++++ .../settings/helper/MarkdownSettingsHelper.kt | 27 ++ .../settings/helper/PostmanSettingsHelper.kt | 55 ++++ .../helper/RecommendConfigSettingsHelper.kt} | 36 ++- .../settings/helper/SupportSettingsHelper.kt | 16 ++ .../settings/helper/YapiSettingsHelper.kt | 256 ++++++++++++++++++ .../itangcent/idea/plugin/utils/RegexUtils.kt | 1 + .../idea/swing/ActiveWindowProvider.kt | 11 + .../idea/swing/DefaultMessagesHelper.kt | 53 ++++ .../itangcent/idea/swing/MessagesHelper.kt | 21 ++ .../idea/swing/SimpleActiveWindowProvider.kt | 18 ++ .../idea/utils/ConfigurableLogger.kt | 63 +---- .../http/ConfigurableHttpClientProvider.kt | 94 +++++-- .../plugin/settings/group/JsonSettingTest.kt | 49 ---- .../helper/BuiltInConfigSettingsHelperTest.kt | 22 ++ .../helper/CommonSettingsHelperTest.kt | 45 +++ .../settings/helper/HttpSettingsHelperTest.kt | 95 +++++++ .../helper/IntelligentSettingsHelperTest.kt | 76 ++++++ .../helper/MarkdownSettingsHelperTest.kt | 43 +++ .../helper/PostmanSettingsHelperTest.kt | 71 +++++ .../helper/RecommendConfigLoaderTest.kt | 99 +++++++ .../RecommendConfigSettingsHelperTest.kt | 61 +++++ .../settings/helper/SettingsHelperTest.kt | 20 ++ .../helper/SupportSettingsHelperTest.kt | 23 ++ .../settings/helper/YapiSettingsHelperTest.kt | 193 +++++++++++++ .../idea/utils/ConfigurableLoggerTest.kt | 11 +- .../com/itangcent/mock/AdvancedContextTest.kt | 2 + .../com/itangcent/mock/EmptyMessagesHelper.kt | 15 + .../ConfigurableHttpClientProviderTest.kt | 14 + .../suv/http/HttpClientProviderTest.kt | 1 + ...nContextLightCodeInsightFixtureTestCase.kt | 3 + 73 files changed, 1975 insertions(+), 912 deletions(-) delete mode 100644 idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/DefaultYapiApiInputHelper.kt delete mode 100644 idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiApiInputHelper.kt create mode 100644 idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiTokenCheckerSupport.kt delete mode 100644 idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/group/JsonSetting.kt create mode 100644 idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/BuiltInConfigSettingsHelper.kt create mode 100644 idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/CommonSettingsHelper.kt create mode 100644 idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/HttpSettingsHelper.kt create mode 100644 idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/IntelligentSettingsHelper.kt create mode 100644 idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/MarkdownSettingsHelper.kt create mode 100644 idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/PostmanSettingsHelper.kt rename idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/{config/RecommendConfigLoader.kt => settings/helper/RecommendConfigSettingsHelper.kt} (80%) create mode 100644 idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/SupportSettingsHelper.kt create mode 100644 idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/YapiSettingsHelper.kt create mode 100644 idea-plugin/src/main/kotlin/com/itangcent/idea/swing/ActiveWindowProvider.kt create mode 100644 idea-plugin/src/main/kotlin/com/itangcent/idea/swing/DefaultMessagesHelper.kt create mode 100644 idea-plugin/src/main/kotlin/com/itangcent/idea/swing/MessagesHelper.kt create mode 100644 idea-plugin/src/main/kotlin/com/itangcent/idea/swing/SimpleActiveWindowProvider.kt delete mode 100644 idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/group/JsonSettingTest.kt create mode 100644 idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/BuiltInConfigSettingsHelperTest.kt create mode 100644 idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/CommonSettingsHelperTest.kt create mode 100644 idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/HttpSettingsHelperTest.kt create mode 100644 idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/IntelligentSettingsHelperTest.kt create mode 100644 idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/MarkdownSettingsHelperTest.kt create mode 100644 idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/PostmanSettingsHelperTest.kt create mode 100644 idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/RecommendConfigLoaderTest.kt create mode 100644 idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/RecommendConfigSettingsHelperTest.kt create mode 100644 idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/SettingsHelperTest.kt create mode 100644 idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/SupportSettingsHelperTest.kt create mode 100644 idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/YapiSettingsHelperTest.kt create mode 100644 idea-plugin/src/test/kotlin/com/itangcent/mock/EmptyMessagesHelper.kt diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/config/CachedResourceResolver.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/config/CachedResourceResolver.kt index 83a954a5f..74d748799 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/config/CachedResourceResolver.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/config/CachedResourceResolver.kt @@ -4,13 +4,14 @@ import com.google.inject.Inject import com.google.inject.Singleton import com.google.inject.name.Named import com.itangcent.common.utils.TimeSpanUtils -import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.helper.HttpSettingsHelper import com.itangcent.idea.sqlite.SqliteDataResourceHelper import com.itangcent.intellij.config.ConfigReader import com.itangcent.intellij.config.resource.DefaultResourceResolver import com.itangcent.intellij.config.resource.URLResource import com.itangcent.intellij.context.ActionContext import com.itangcent.intellij.file.LocalFileRepository +import com.itangcent.intellij.logger.Logger import java.io.ByteArrayInputStream import java.io.InputStream import java.net.URL @@ -30,6 +31,12 @@ open class CachedResourceResolver : DefaultResourceResolver() { @Inject private lateinit var configReader: ConfigReader + @Inject + private lateinit var httpSettingsHelper: HttpSettingsHelper + + @Inject + protected val logger: Logger? = null + private val beanDAO: SqliteDataResourceHelper.ExpiredBeanDAO by lazy { val context = ActionContext.getContext() val sqliteDataResourceHelper = context!!.instance(SqliteDataResourceHelper::class) @@ -49,6 +56,10 @@ open class CachedResourceResolver : DefaultResourceResolver() { var valueBytes = beanDAO.get(key) if (valueBytes == null) { LOG.debug("read:$url") + if (!httpSettingsHelper.checkTrustUrl(url.toString(), false)) { + logger?.warn("[access forbidden] read:$url") + return byteArrayOf() + } valueBytes = super.inputStream?.use { it.readBytes() } valueBytes?.let { beanDAO.set(key, it, System.currentTimeMillis() + @@ -72,9 +83,9 @@ open class CachedResourceResolver : DefaultResourceResolver() { get() = loadCache()?.let { String(it, Charsets.UTF_8) } override fun onConnection(connection: URLConnection) { - ActionContext.getContext()?.instance(SettingBinder::class) - ?.tryRead()?.httpTimeOut?.let { - connection.connectTimeout = it * 1000 + ActionContext.getContext()?.instance(HttpSettingsHelper::class) + ?.let { + connection.connectTimeout = it.httpTimeOut(TimeUnit.MILLISECONDS) } } } diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/actions/ApiDashBoardAction.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/actions/ApiDashBoardAction.kt index 595896493..f7e05f470 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/actions/ApiDashBoardAction.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/actions/ApiDashBoardAction.kt @@ -12,6 +12,8 @@ import com.itangcent.idea.plugin.api.export.postman.PostmanConfigReader import com.itangcent.idea.plugin.api.export.postman.PostmanRequestBuilderListener import com.itangcent.idea.plugin.api.export.spring.SpringRequestClassExporter import com.itangcent.idea.plugin.config.RecommendConfigReader +import com.itangcent.idea.swing.ActiveWindowProvider +import com.itangcent.idea.swing.SimpleActiveWindowProvider import com.itangcent.intellij.config.ConfigReader import com.itangcent.intellij.context.ActionContext import com.itangcent.intellij.extend.guice.singleton @@ -38,6 +40,8 @@ class ApiDashBoardAction : ApiExportAction("ApiDashBoard") { builder.bind(RequestBuilderListener::class) { it.with(ComponentRequestBuilderListener::class).singleton() } builder.bindInstance("AVAILABLE_REQUEST_BUILDER_LISTENER", arrayOf(DefaultRequestBuilderListener::class, PostmanRequestBuilderListener::class)) + + builder.bind(ActiveWindowProvider::class) { it.with(SimpleActiveWindowProvider::class) } } override fun actionPerformed(actionContext: ActionContext, project: Project?, anActionEvent: AnActionEvent) { diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/actions/YapiDashBoardAction.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/actions/YapiDashBoardAction.kt index b3565e817..524b63cc4 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/actions/YapiDashBoardAction.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/actions/YapiDashBoardAction.kt @@ -7,6 +7,8 @@ import com.itangcent.idea.plugin.api.export.core.* import com.itangcent.idea.plugin.api.export.generic.GenericMethodDocClassExporter import com.itangcent.idea.plugin.api.export.yapi.* import com.itangcent.idea.plugin.config.RecommendConfigReader +import com.itangcent.idea.swing.ActiveWindowProvider +import com.itangcent.idea.swing.SimpleActiveWindowProvider import com.itangcent.intellij.config.ConfigReader import com.itangcent.intellij.context.ActionContext import com.itangcent.intellij.extend.guice.singleton @@ -41,6 +43,7 @@ class YapiDashBoardAction : ApiExportAction("YapiDashBoard") { builder.bind(MethodDocBuilderListener::class) { it.with(ComponentMethodDocBuilderListener::class).singleton() } builder.bindInstance("AVAILABLE_METHOD_DOC_BUILDER_LISTENER", arrayOf(DefaultMethodDocBuilderListener::class, YapiMethodDocBuilderListener::class)) + builder.bind(ActiveWindowProvider::class) { it.with(SimpleActiveWindowProvider::class) } } override fun actionPerformed(actionContext: ActionContext, project: Project?, anActionEvent: AnActionEvent) { diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/actions/YapiExportAction.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/actions/YapiExportAction.kt index e364cef37..8d3b40d94 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/actions/YapiExportAction.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/actions/YapiExportAction.kt @@ -6,6 +6,7 @@ import com.itangcent.idea.plugin.api.export.core.* import com.itangcent.idea.plugin.api.export.generic.GenericMethodDocClassExporter import com.itangcent.idea.plugin.api.export.yapi.* import com.itangcent.idea.plugin.config.RecommendConfigReader +import com.itangcent.idea.plugin.settings.helper.YapiTokenChecker import com.itangcent.intellij.config.ConfigReader import com.itangcent.intellij.context.ActionContext import com.itangcent.intellij.extend.guice.singleton @@ -43,6 +44,8 @@ class YapiExportAction : ApiExportAction("Export Yapi") { builder.bindInstance("file.save.last.location.key", "com.itangcent.yapi.export.path") builder.bind(PsiClassHelper::class) { it.with(YapiPsiClassHelper::class).singleton() } + + builder.bind(YapiTokenChecker::class) { it.with(YapiTokenCheckerSupport::class).singleton() } } override fun actionPerformed(actionContext: ActionContext, project: Project?, anActionEvent: AnActionEvent) { diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/DefaultMethodInferHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/DefaultMethodInferHelper.kt index 623bc79ab..fbf329879 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/DefaultMethodInferHelper.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/DefaultMethodInferHelper.kt @@ -8,6 +8,7 @@ import com.itangcent.common.kit.KVUtils import com.itangcent.common.logger.traceError import com.itangcent.common.utils.* import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.helper.IntelligentSettingsHelper import com.itangcent.intellij.config.rule.RuleComputer import com.itangcent.intellij.context.ActionContext import com.itangcent.intellij.jvm.DuckTypeHelper @@ -21,10 +22,6 @@ import com.siyeh.ig.psiutils.ClassUtils import java.lang.reflect.Method import java.lang.reflect.Modifier import java.util.* -import kotlin.collections.ArrayList -import kotlin.collections.HashMap -import kotlin.collections.HashSet -import kotlin.collections.LinkedHashMap /** *1.Try infer the return type of method @@ -56,6 +53,9 @@ class DefaultMethodInferHelper : MethodInferHelper { @Inject protected val settingBinder: SettingBinder? = null + @Inject + protected lateinit var intelligentSettingsHelper: IntelligentSettingsHelper + private val staticMethodCache: HashMap?>, Any?> = HashMap() private val methodStack: Stack = Stack() @@ -64,17 +64,8 @@ class DefaultMethodInferHelper : MethodInferHelper { private var simpleJsonOption: Int = jsonOption and JsonOption.READ_GETTER.inv() - private var maxDeep: Int? = null - private var maxObjectDeep: Int = 4 - private fun inferMaxDeep(): Int { - if (this.maxDeep == null) { - this.maxDeep = settingBinder!!.read().inferMaxDeep - } - return maxDeep!! - } - private val emptyCallMethodCache: HashMap = HashMap() override fun inferReturn(psiMethod: PsiMethod, option: Int): Any? { @@ -95,7 +86,7 @@ class DefaultMethodInferHelper : MethodInferHelper { option: Int = DEFAULT_OPTION ): Any? { actionContext!!.checkStatus() - if (methodStack.size < inferMaxDeep()) { + if (methodStack.size < intelligentSettingsHelper.inferMaxDeep()) { try { var inferRet: Any? inferRet = callSimpleMethod(context, psiMethod, caller, args) @@ -564,7 +555,7 @@ class DefaultMethodInferHelper : MethodInferHelper { return when { !needCompute(obj) -> obj obj is Variable -> valueOf(obj.getValue()) - obj is Delay -> valueOf(obj.unwrapped { }) + obj is Delay -> valueOf(obj.unwrapped { }) obj is MutableMap<*, *> -> { val copy = KV.create() obj.entries.forEach { copy[valueOf(it.key)] = valueOf(it.value) } diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/core/AbstractRequestClassExporter.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/core/AbstractRequestClassExporter.kt index ee009af02..f96b65c18 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/core/AbstractRequestClassExporter.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/core/AbstractRequestClassExporter.kt @@ -17,8 +17,7 @@ import com.itangcent.idea.plugin.api.ClassApiExporterHelper import com.itangcent.idea.plugin.api.MethodInferHelper import com.itangcent.idea.plugin.api.export.MethodFilter import com.itangcent.idea.plugin.api.export.spring.SpringClassName -import com.itangcent.idea.plugin.settings.SettingBinder -import com.itangcent.idea.plugin.settings.group.JsonSetting +import com.itangcent.idea.plugin.settings.helper.IntelligentSettingsHelper import com.itangcent.idea.psi.PsiMethodResource import com.itangcent.intellij.config.rule.RuleComputer import com.itangcent.intellij.config.rule.computer @@ -71,10 +70,7 @@ abstract class AbstractRequestClassExporter : ClassExporter, Worker { protected lateinit var requestBuilderListener: RequestBuilderListener @Inject - protected val settingBinder: SettingBinder? = null - - @Inject - protected val jsonSetting: JsonSetting? = null + protected lateinit var intelligentSettingsHelper: IntelligentSettingsHelper @Inject protected val duckTypeHelper: DuckTypeHelper? = null @@ -519,7 +515,7 @@ abstract class AbstractRequestClassExporter : ClassExporter, Worker { ?: false, paramDesc ) } else if (typeObject != null && typeObject is Map<*, *>) { - if (request.hasBodyOrForm() && formExpanded() && typeObject.isComplex() + if (request.hasBodyOrForm() && this.intelligentSettingsHelper.formExpanded() && typeObject.isComplex() && requestBuilderListener.addHeaderIfMissed(parameterExportContext, request, "Content-Type", "multipart/form-data")) { typeObject.flatValid(object : FieldConsumer { @@ -601,7 +597,7 @@ abstract class AbstractRequestClassExporter : ClassExporter, Worker { ?: false, paramDesc ) } else if (typeObject != null && typeObject is Map<*, *>) { - if (formExpanded() && typeObject.isComplex() + if (this.intelligentSettingsHelper.formExpanded() && typeObject.isComplex() && requestBuilderListener.addHeaderIfMissed(parameterExportContext, request, "Content-Type", "multipart/form-data")) { typeObject.flatValid(object : FieldConsumer { @@ -673,15 +669,15 @@ abstract class AbstractRequestClassExporter : ClassExporter, Worker { return when { fromRule -> psiClassHelper!!.getTypeObject(duckType, method.psi(), - jsonSetting!!.jsonOptionForOutput(JsonOption.READ_COMMENT)) - needInfer() && (!duckTypeHelper!!.isQualified(duckType) || + this.intelligentSettingsHelper!!.jsonOptionForOutput(JsonOption.READ_COMMENT)) + this.intelligentSettingsHelper.inferEnable() && (!duckTypeHelper!!.isQualified(duckType) || jvmClassHelper!!.isInterface(duckType)) -> { logger!!.info("try infer return type of method[" + PsiClassUtils.fullNameOfMethod(method.psi()) + "]") methodReturnInferHelper!!.inferReturn(method.psi()) // actionContext!!.callWithTimeout(20000) { methodReturnInferHelper.inferReturn(method) } } else -> psiClassHelper!!.getTypeObject(duckType, method.psi(), - jsonSetting!!.jsonOptionForOutput(JsonOption.READ_COMMENT)) + this.intelligentSettingsHelper!!.jsonOptionForOutput(JsonOption.READ_COMMENT)) } } @@ -700,14 +696,6 @@ abstract class AbstractRequestClassExporter : ClassExporter, Worker { return obj } - private fun needInfer(): Boolean { - return settingBinder!!.read().inferEnable - } - - protected fun formExpanded(): Boolean { - return settingBinder!!.read().formExpanded - } - //region extent of ParameterExportContext fun ParameterExportContext.setName(name: String) { this.setExt("param_name", name) @@ -737,7 +725,7 @@ abstract class AbstractRequestClassExporter : ClassExporter, Worker { return this.cache("raw") { val paramType = this.parameter.getType() ?: return@cache null val typeObject = psiClassHelper!!.getTypeObject(paramType, parameter.psi(), - jsonSetting!!.jsonOptionForInput(JsonOption.READ_COMMENT)) + this@AbstractRequestClassExporter.intelligentSettingsHelper!!.jsonOptionForInput(JsonOption.READ_COMMENT)) this.setExt("raw", typeObject) return@cache typeObject } diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/generic/GenericMethodDocClassExporter.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/generic/GenericMethodDocClassExporter.kt index 20c1f1e43..db5096be9 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/generic/GenericMethodDocClassExporter.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/generic/GenericMethodDocClassExporter.kt @@ -17,8 +17,8 @@ import com.itangcent.idea.plugin.api.MethodInferHelper import com.itangcent.idea.plugin.api.export.MethodFilter import com.itangcent.idea.plugin.api.export.core.* import com.itangcent.idea.plugin.api.export.core.LinkResolver -import com.itangcent.idea.plugin.settings.SettingBinder -import com.itangcent.idea.plugin.settings.group.JsonSetting +import com.itangcent.idea.plugin.settings.helper.IntelligentSettingsHelper +import com.itangcent.idea.plugin.settings.helper.SupportSettingsHelper import com.itangcent.idea.psi.PsiMethodResource import com.itangcent.intellij.config.rule.RuleComputer import com.itangcent.intellij.config.rule.computer @@ -74,10 +74,10 @@ open class GenericMethodDocClassExporter : ClassExporter, Worker { protected lateinit var methodDocBuilderListener: MethodDocBuilderListener @Inject - protected val settingBinder: SettingBinder? = null + protected lateinit var supportSettingsHelper: SupportSettingsHelper @Inject - protected val jsonSetting: JsonSetting? = null + protected lateinit var intelligentSettingsHelper: IntelligentSettingsHelper @Inject protected val duckTypeHelper: DuckTypeHelper? = null @@ -329,7 +329,7 @@ open class GenericMethodDocClassExporter : ClassExporter, Worker { ) { val paramType = param.getType() ?: return val typeObject = psiClassHelper!!.getTypeObject(paramType, param.psi(), - jsonSetting!!.jsonOptionForInput(JsonOption.READ_COMMENT)) + intelligentSettingsHelper.jsonOptionForInput(JsonOption.READ_COMMENT)) methodDocBuilderListener.addParam(methodExportContext, methodDoc, param.name(), typeObject, paramDesc, ruleComputer!!.computer(ClassExportRuleKeys.PARAM_REQUIRED, param) == true) } @@ -347,7 +347,7 @@ open class GenericMethodDocClassExporter : ClassExporter, Worker { // actionContext!!.callWithTimeout(20000) { methodReturnInferHelper.inferReturn(method) } } else -> psiClassHelper!!.getTypeObject(duckType, methodExportContext.psi(), - jsonSetting!!.jsonOptionForOutput(JsonOption.READ_COMMENT)) + intelligentSettingsHelper.jsonOptionForOutput(JsonOption.READ_COMMENT)) } } @@ -356,10 +356,10 @@ open class GenericMethodDocClassExporter : ClassExporter, Worker { } private fun methodDocEnable(): Boolean { - return settingBinder!!.read().methodDocEnable + return supportSettingsHelper.methodDocEnable() } private fun needInfer(): Boolean { - return settingBinder!!.read().inferEnable + return intelligentSettingsHelper.inferEnable() } } \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/generic/SimpleGenericMethodDocClassExporter.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/generic/SimpleGenericMethodDocClassExporter.kt index 7f774b3ac..9f11aa26c 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/generic/SimpleGenericMethodDocClassExporter.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/generic/SimpleGenericMethodDocClassExporter.kt @@ -13,6 +13,7 @@ import com.itangcent.idea.plugin.WorkerStatus import com.itangcent.idea.plugin.api.export.MethodFilter import com.itangcent.idea.plugin.api.export.core.* import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.helper.SupportSettingsHelper import com.itangcent.idea.psi.PsiMethodResource import com.itangcent.intellij.config.rule.RuleComputer import com.itangcent.intellij.context.ActionContext @@ -28,6 +29,9 @@ open class SimpleGenericMethodDocClassExporter : ClassExporter, Worker { @Inject protected val jvmClassHelper: JvmClassHelper? = null + @Inject + protected lateinit var supportSettingsHelper: SupportSettingsHelper + override fun support(docType: KClass<*>): Boolean { return docType == MethodDoc::class && methodDocEnable() } @@ -170,6 +174,6 @@ open class SimpleGenericMethodDocClassExporter : ClassExporter, Worker { } private fun methodDocEnable(): Boolean { - return settingBinder!!.read().methodDocEnable + return supportSettingsHelper.methodDocEnable() } } \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/markdown/MarkdownApiExporter.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/markdown/MarkdownApiExporter.kt index 27bde31f9..55d17caa4 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/markdown/MarkdownApiExporter.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/markdown/MarkdownApiExporter.kt @@ -9,6 +9,7 @@ import com.itangcent.common.model.Doc import com.itangcent.idea.plugin.Worker import com.itangcent.idea.plugin.api.export.core.ClassExporter import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.helper.MarkdownSettingsHelper import com.itangcent.idea.utils.Charsets import com.itangcent.idea.utils.FileSaveHelper import com.itangcent.intellij.context.ActionContext @@ -37,7 +38,7 @@ class MarkdownApiExporter { private val markdownFormatter: MarkdownFormatter? = null @Inject - private val settingBinder: SettingBinder? = null + private lateinit var markdownSettingsHelper: MarkdownSettingsHelper fun export() { @@ -51,7 +52,7 @@ class MarkdownApiExporter { val project = actionContext.instance(Project::class) val yes = Messages.showYesNoDialog(project, "Export the api in directory [${ActionUtils.findCurrentPath(dir)}]?", - "Are you sure", + "Please Confirm", Messages.getQuestionIcon()) if (yes == Messages.YES) { callBack(true) @@ -83,8 +84,7 @@ class MarkdownApiExporter { docs.clear() actionContext!!.runAsync { try { - fileSaveHelper!!.saveOrCopy(apiInfo, Charsets.forName(settingBinder!!.read().outputCharset)?.charset() - ?: kotlin.text.Charsets.UTF_8, { + fileSaveHelper!!.saveOrCopy(apiInfo, markdownSettingsHelper.outputCharset(), { logger.info("Exported data are copied to clipboard,you can paste to a md file now") }, { logger.info("Apis save success: $it") diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/markdown/MarkdownFormatter.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/markdown/MarkdownFormatter.kt index 8a99c380d..969ff31c5 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/markdown/MarkdownFormatter.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/markdown/MarkdownFormatter.kt @@ -18,7 +18,7 @@ import com.itangcent.idea.plugin.api.export.core.Folder import com.itangcent.idea.plugin.api.export.core.FormatFolderHelper import com.itangcent.idea.plugin.api.export.postman.PostmanFormatter import com.itangcent.idea.plugin.settings.MarkdownFormatType -import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.helper.MarkdownSettingsHelper import com.itangcent.idea.psi.ResourceHelper import com.itangcent.idea.utils.ModuleHelper import com.itangcent.intellij.context.ActionContext @@ -39,7 +39,7 @@ class MarkdownFormatter { private val moduleHelper: ModuleHelper? = null @Inject - protected val settingBinder: SettingBinder? = null + protected lateinit var markdownSettingsHelper: MarkdownSettingsHelper @Inject protected val resourceHelper: ResourceHelper? = null @@ -250,7 +250,7 @@ class MarkdownFormatter { handle("\n**RequestBody**\n\n") objectFormatter.writeObject(request.body, request.bodyAttr ?: "") - if (settingBinder!!.read().outputDemo) { + if (markdownSettingsHelper.outputDemo()) { handle("\n**Request Demo:**\n\n") parseToJson(handle, request.body) } @@ -296,7 +296,7 @@ class MarkdownFormatter { } // handler json example - if (settingBinder!!.read().outputDemo) { + if (markdownSettingsHelper.outputDemo()) { handle("\n**Response Demo:**\n\n") parseToJson(handle, response.body) } @@ -361,8 +361,8 @@ class MarkdownFormatter { } private fun getObjectFormatter(handle: (String) -> Unit): ObjectFormatter { - val markdownFormatType = settingBinder!!.read().markdownFormatType - return if (markdownFormatType == MarkdownFormatType.ULTIMATE.name) { + val markdownFormatType = markdownSettingsHelper.markdownFormatType() + return if (markdownFormatType == MarkdownFormatType.ULTIMATE) { UltimateObjectFormatter(handle) } else { SimpleObjectFormatter(handle) diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/DefaultPostmanApiHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/DefaultPostmanApiHelper.kt index 99891ed30..be2cd3eb0 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/DefaultPostmanApiHelper.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/DefaultPostmanApiHelper.kt @@ -14,7 +14,7 @@ import com.itangcent.http.contentType import com.itangcent.idea.plugin.api.export.ReservedResponseHandle import com.itangcent.idea.plugin.api.export.core.StringResponseHandler import com.itangcent.idea.plugin.api.export.reserved -import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.helper.PostmanSettingsHelper import com.itangcent.intellij.extend.* import com.itangcent.intellij.extend.rx.Throttle import com.itangcent.intellij.extend.rx.ThrottleHelper @@ -42,7 +42,7 @@ import kotlin.streams.toList open class DefaultPostmanApiHelper : PostmanApiHelper { @Inject - private val settingBinder: SettingBinder? = null + private lateinit var postmanSettingsHelper: PostmanSettingsHelper @Inject private val logger: Logger? = null @@ -52,20 +52,6 @@ open class DefaultPostmanApiHelper : PostmanApiHelper { private val apiThrottle: Throttle = ThrottleHelper().build("postman_api") - override fun hasPrivateToken(): Boolean { - return getPrivateToken().notNullOrEmpty() - } - - override fun getPrivateToken(): String? { - return settingBinder!!.read().postmanToken?.trim() - } - - override fun setPrivateToken(postmanPrivateToken: String) { - val settings = settingBinder!!.read() - settings.postmanToken = postmanPrivateToken - settingBinder.save(settings) - } - protected open fun beforeRequest(request: HttpRequest) { apiThrottle.acquireGreedy(LIMIT_PERIOD_PRE_REQUEST) } @@ -123,7 +109,7 @@ open class DefaultPostmanApiHelper : PostmanApiHelper { val request = getHttpClient() .post(COLLECTION) .contentType(ContentType.APPLICATION_JSON) - .header("x-api-key", getPrivateToken()) + .header("x-api-key", postmanSettingsHelper.getPrivateToken()) .body(KV.by("collection", collection)) try { @@ -203,7 +189,7 @@ open class DefaultPostmanApiHelper : PostmanApiHelper { val request = getHttpClient().put("$COLLECTION/$collectionId") .contentType(ContentType.APPLICATION_JSON) - .header("x-api-key", getPrivateToken()) + .header("x-api-key", postmanSettingsHelper.getPrivateToken()) .body(KV.by("collection", apiInfo)) try { @@ -233,7 +219,7 @@ open class DefaultPostmanApiHelper : PostmanApiHelper { override fun getAllCollection(): ArrayList>? { val request = getHttpClient().get(COLLECTION) - .header("x-api-key", getPrivateToken()) + .header("x-api-key", postmanSettingsHelper.getPrivateToken()) try { beforeRequest(request) @@ -260,7 +246,7 @@ open class DefaultPostmanApiHelper : PostmanApiHelper { override fun getCollectionInfo(collectionId: String): HashMap? { val request = getHttpClient().get("$COLLECTION/$collectionId") - .header("x-api-key", getPrivateToken()) + .header("x-api-key", postmanSettingsHelper.getPrivateToken()) try { beforeRequest(request) val response = call(request) @@ -285,7 +271,7 @@ open class DefaultPostmanApiHelper : PostmanApiHelper { override fun deleteCollectionInfo(collectionId: String): HashMap? { val request = getHttpClient().delete("$COLLECTION/$collectionId") - .header("x-api-key", getPrivateToken()) + .header("x-api-key", postmanSettingsHelper.getPrivateToken()) try { beforeRequest(request) val result = call(request) diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/PostmanApiExporter.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/PostmanApiExporter.kt index 299c45977..35f33cfd2 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/PostmanApiExporter.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/PostmanApiExporter.kt @@ -13,6 +13,7 @@ import com.itangcent.common.utils.notNullOrEmpty import com.itangcent.idea.plugin.Worker import com.itangcent.idea.plugin.api.export.core.ClassExporter import com.itangcent.idea.plugin.api.export.core.requestOnly +import com.itangcent.idea.plugin.settings.helper.PostmanSettingsHelper import com.itangcent.idea.utils.FileSaveHelper import com.itangcent.intellij.context.ActionContext import com.itangcent.intellij.logger.Logger @@ -29,7 +30,10 @@ class PostmanApiExporter { private val logger: Logger? = null @Inject - private val postmanApiHelper: PostmanApiHelper? = null + private lateinit var postmanApiHelper: PostmanApiHelper + + @Inject + private lateinit var postmanSettingsHelper: PostmanSettingsHelper @Inject private val actionContext: ActionContext? = null @@ -84,7 +88,7 @@ class PostmanApiExporter { requests.clear() actionContext!!.runAsync { try { - if (postmanApiHelper!!.hasPrivateToken()) { + if (postmanSettingsHelper.hasPrivateToken()) { logger.info("PrivateToken of postman be found") val createdCollection = postmanApiHelper.createCollection(postman) diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/PostmanApiHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/PostmanApiHelper.kt index 411b40974..85d70c250 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/PostmanApiHelper.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/PostmanApiHelper.kt @@ -1,12 +1,6 @@ package com.itangcent.idea.plugin.api.export.postman interface PostmanApiHelper { - fun hasPrivateToken(): Boolean - - fun getPrivateToken(): String? - - fun setPrivateToken(postmanPrivateToken: String) - /** * @return collection id */ diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/PostmanCachedApiHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/PostmanCachedApiHelper.kt index 6ce121d08..1b9f953e7 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/PostmanCachedApiHelper.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/PostmanCachedApiHelper.kt @@ -3,6 +3,7 @@ package com.itangcent.idea.plugin.api.export.postman import com.google.inject.Inject import com.itangcent.common.utils.notNullOrEmpty import com.itangcent.idea.binder.DbBeanBinderFactory +import com.itangcent.idea.plugin.settings.helper.PostmanSettingsHelper import com.itangcent.intellij.file.LocalFileRepository import com.itangcent.intellij.logger.Logger import kotlin.streams.toList @@ -15,6 +16,9 @@ class PostmanCachedApiHelper : DefaultPostmanApiHelper() { @Inject private val localFileRepository: LocalFileRepository? = null + @Inject + private lateinit var postmanSettingsHelper: PostmanSettingsHelper + private var dbBeanBinderFactory: DbBeanBinderFactory? = null private fun getDbBeanBinderFactory(): DbBeanBinderFactory { @@ -36,7 +40,7 @@ class PostmanCachedApiHelper : DefaultPostmanApiHelper() { //region update collection of AllCollection----------------------------- val allCollectionBeanBinder = getDbBeanBinderFactory() - .getBeanBinder("${getPrivateToken()}_getAllCollection") + .getBeanBinder("${postmanSettingsHelper.getPrivateToken()}_getAllCollection") val cacheOfAllCollection = allCollectionBeanBinder.read() if (cacheOfAllCollection != NULL_COLLECTION_INFO_CACHE) { if (cacheOfAllCollection.allCollection == null) { @@ -52,7 +56,7 @@ class PostmanCachedApiHelper : DefaultPostmanApiHelper() { cacheOfCollection.collectionDetail = collection getDbBeanBinderFactory() - .getBeanBinder("${getPrivateToken()}_collection:$collectionId") + .getBeanBinder("${postmanSettingsHelper.getPrivateToken()}_collection:$collectionId") .save(cacheOfCollection) //endregion add cache of created collection-------------------------------- @@ -65,7 +69,7 @@ class PostmanCachedApiHelper : DefaultPostmanApiHelper() { if (super.updateCollection(collectionId, collectionInfo)) { //region try update collection of AllCollection----------------------------- val allCollectionBeanBinder = getDbBeanBinderFactory() - .getBeanBinder("${getPrivateToken()}_getAllCollection") + .getBeanBinder("${postmanSettingsHelper.getPrivateToken()}_getAllCollection") val cacheOfAllCollection = allCollectionBeanBinder.read() if (cacheOfAllCollection != NULL_COLLECTION_INFO_CACHE) { if (cacheOfAllCollection.allCollection != null) { @@ -83,7 +87,7 @@ class PostmanCachedApiHelper : DefaultPostmanApiHelper() { } //endregion try update collection of AllCollection----------------------------- - val collectionDetailBeanBinder = getDbBeanBinderFactory().getBeanBinder("${getPrivateToken()}_collection:$collectionId") + val collectionDetailBeanBinder = getDbBeanBinderFactory().getBeanBinder("${postmanSettingsHelper.getPrivateToken()}_collection:$collectionId") val cache = CollectionInfoCache() cache.collectionDetail = collectionInfo collectionDetailBeanBinder.save(cache) @@ -98,7 +102,7 @@ class PostmanCachedApiHelper : DefaultPostmanApiHelper() { //region update collection of AllCollection----------------------------- val allCollectionBeanBinder = getDbBeanBinderFactory() - .getBeanBinder("${getPrivateToken()}_getAllCollection") + .getBeanBinder("${postmanSettingsHelper.getPrivateToken()}_getAllCollection") val cacheOfAllCollection = allCollectionBeanBinder.read() if (cacheOfAllCollection != NULL_COLLECTION_INFO_CACHE) { if (cacheOfAllCollection.allCollection != null) { @@ -111,7 +115,7 @@ class PostmanCachedApiHelper : DefaultPostmanApiHelper() { } //endregion update collection of AllCollection----------------------------- - getDbBeanBinderFactory().deleteBinder("${getPrivateToken()}_collection:$collectionId") + getDbBeanBinderFactory().deleteBinder("${postmanSettingsHelper.getPrivateToken()}_collection:$collectionId") } return deleteCollectionInfo } @@ -127,7 +131,7 @@ class PostmanCachedApiHelper : DefaultPostmanApiHelper() { fun getAllCollection(useCache: Boolean): ArrayList>? { if (useCache) { val allCollectionBeanBinder = getDbBeanBinderFactory().getBeanBinder( - "${getPrivateToken()}_getAllCollection") + "${postmanSettingsHelper.getPrivateToken()}_getAllCollection") val cache = allCollectionBeanBinder.read() if (cache != NULL_COLLECTION_INFO_CACHE) { return cache.allCollection @@ -141,7 +145,7 @@ class PostmanCachedApiHelper : DefaultPostmanApiHelper() { val beanBinder = getDbBeanBinderFactory() - .getBeanBinder("${getPrivateToken()}_getAllCollection") + .getBeanBinder("${postmanSettingsHelper.getPrivateToken()}_getAllCollection") if (!useCache) { //try clean cache val oldCollectionCache = beanBinder.read() @@ -163,7 +167,7 @@ class PostmanCachedApiHelper : DefaultPostmanApiHelper() { .toList() deletedCollections.forEach { - getDbBeanBinderFactory().deleteBinder("${getPrivateToken()}_collection:$it") + getDbBeanBinderFactory().deleteBinder("${postmanSettingsHelper.getPrivateToken()}_collection:$it") } } } @@ -175,7 +179,7 @@ class PostmanCachedApiHelper : DefaultPostmanApiHelper() { fun getCollectionInfo(collectionId: String, useCache: Boolean = true): HashMap? { if (useCache) { - val collectionDetailBeanBinder = getDbBeanBinderFactory().getBeanBinder("${getPrivateToken()}_collection:$collectionId") + val collectionDetailBeanBinder = getDbBeanBinderFactory().getBeanBinder("${postmanSettingsHelper.getPrivateToken()}_collection:$collectionId") val cache = collectionDetailBeanBinder.read() if (cache != NULL_COLLECTION_INFO_CACHE) { return cache.collectionDetail @@ -186,7 +190,7 @@ class PostmanCachedApiHelper : DefaultPostmanApiHelper() { val cache = CollectionInfoCache() cache.collectionDetail = collectionDetail getDbBeanBinderFactory() - .getBeanBinder("${getPrivateToken()}_collection:$collectionId") + .getBeanBinder("${postmanSettingsHelper.getPrivateToken()}_collection:$collectionId") .save(cache) return collectionDetail } diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/PostmanFormatter.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/PostmanFormatter.kt index dba74a9a3..cf6bad054 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/PostmanFormatter.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/postman/PostmanFormatter.kt @@ -16,8 +16,7 @@ import com.itangcent.idea.plugin.json.Json5Formatter import com.itangcent.idea.plugin.json.JsonFormatter import com.itangcent.idea.plugin.json.SimpleJsonFormatter import com.itangcent.idea.plugin.rule.SuvRuleContext -import com.itangcent.idea.plugin.settings.PostmanJson5FormatType -import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.helper.PostmanSettingsHelper import com.itangcent.idea.psi.ResourceHelper import com.itangcent.idea.psi.resource import com.itangcent.idea.psi.resourceClass @@ -49,7 +48,7 @@ open class PostmanFormatter { private val ruleComputer: RuleComputer? = null @Inject - private val settingBinder: SettingBinder? = null + private lateinit var postmanSettingsHelper: PostmanSettingsHelper @Inject protected lateinit var systemProvider: SystemProvider @@ -437,7 +436,7 @@ open class PostmanFormatter { fun parseRequests(requests: MutableList): HashMap { val postmanCollection = doParseRequests(requests) - if (settingBinder!!.read().autoMergeScript) { + if (postmanSettingsHelper.autoMergeScript()) { autoMerge(postmanCollection) } return postmanCollection @@ -534,7 +533,7 @@ open class PostmanFormatter { } if (moduleFolderApiMap.size == 1) { - val wrapCollection = settingBinder!!.read().wrapCollection + val wrapCollection = postmanSettingsHelper.wrapCollection() //single module val folderApiMap = moduleFolderApiMap.values.first() @@ -611,8 +610,7 @@ open class PostmanFormatter { } private fun getBodyFormatter(type: Int): JsonFormatter { - val settings = settingBinder!!.read() - val useJson5 = PostmanJson5FormatType.valueOf(settings.postmanJson5FormatType).needUseJson5(type) + val useJson5 = postmanSettingsHelper.postmanJson5FormatType().needUseJson5(type) return if (useJson5) { actionContext!!.instance(Json5Formatter::class) } else { diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/suv/SuvApiExporter.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/suv/SuvApiExporter.kt index 2760a1ce4..5fb9e1671 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/suv/SuvApiExporter.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/suv/SuvApiExporter.kt @@ -32,8 +32,11 @@ import com.itangcent.idea.plugin.rule.SuvRuleParser import com.itangcent.idea.plugin.script.GroovyActionExtLoader import com.itangcent.idea.plugin.script.LoggerBuffer import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.helper.MarkdownSettingsHelper +import com.itangcent.idea.plugin.settings.helper.PostmanSettingsHelper +import com.itangcent.idea.plugin.settings.helper.YapiSettingsHelper +import com.itangcent.idea.plugin.settings.helper.YapiTokenChecker import com.itangcent.idea.psi.PsiResource -import com.itangcent.idea.utils.Charsets import com.itangcent.idea.utils.CustomizedPsiClassHelper import com.itangcent.idea.utils.FileSaveHelper import com.itangcent.idea.utils.RuleComputeListenerRegistry @@ -48,7 +51,6 @@ import com.itangcent.intellij.extend.guice.with import com.itangcent.intellij.file.DefaultLocalFileRepository import com.itangcent.intellij.file.LocalFileRepository import com.itangcent.intellij.jvm.PsiClassHelper -import com.itangcent.intellij.jvm.PsiResolver import com.itangcent.intellij.logger.Logger import com.itangcent.intellij.psi.SelectedHelper import com.itangcent.intellij.tip.TipsHelper @@ -178,9 +180,6 @@ class SuvApiExporter { @Inject protected val actionContext: ActionContext? = null - @Inject - private val psiResolver: PsiResolver? = null - private var suvApiExporter: SuvApiExporter? = null fun setSuvApiExporter(suvApiExporter: SuvApiExporter) { @@ -375,7 +374,10 @@ class SuvApiExporter { class PostmanApiExporterAdapter : ApiExporterAdapter() { @Inject - private val postmanApiHelper: PostmanApiHelper? = null + private lateinit var postmanApiHelper: PostmanApiHelper + + @Inject + private lateinit var postmanSettingsHelper: PostmanSettingsHelper @Inject private val fileSaveHelper: FileSaveHelper? = null @@ -418,7 +420,7 @@ class SuvApiExporter { try { val postman = postmanFormatter!!.parseRequests(docs.filterAs()) docs.clear() - if (postmanApiHelper!!.hasPrivateToken()) { + if (postmanSettingsHelper.hasPrivateToken()) { logger!!.info("PrivateToken of postman be found") val createdCollection = postmanApiHelper.createCollection(postman) @@ -459,13 +461,7 @@ class SuvApiExporter { class YapiApiExporterAdapter : ApiExporterAdapter() { @Inject - private val yapiApiHelper: YapiApiHelper? = null - - @Inject - protected val yapiApiInputHelper: YapiApiInputHelper? = null - - @Inject - private val project: Project? = null + protected val yapiSettingsHelper: YapiSettingsHelper? = null override fun actionName(): String { return "YapiExportAction" @@ -499,18 +495,13 @@ class SuvApiExporter { builder.bind(PsiClassHelper::class) { it.with(YapiPsiClassHelper::class).singleton() } + builder.bind(YapiTokenChecker::class) { it.with(YapiTokenCheckerSupport::class).singleton() } } override fun beforeExport(next: () -> Unit) { - val serverFound = yapiApiHelper!!.findServer().notNullOrBlank() + val serverFound = yapiSettingsHelper!!.getServer(false).notNullOrBlank() if (serverFound) { next() - } else { - yapiApiInputHelper!!.inputServer { - if (it.notNullOrBlank()) { - next() - } - } } } @@ -567,7 +558,7 @@ class SuvApiExporter { private val markdownFormatter: MarkdownFormatter? = null @Inject - private val settingBinder: SettingBinder? = null + private lateinit var markdownSettingsHelper: MarkdownSettingsHelper override fun actionName(): String { return "MarkdownExportAction" @@ -602,8 +593,7 @@ class SuvApiExporter { docs.clear() actionContext!!.runAsync { try { - fileSaveHelper!!.saveOrCopy(apiInfo, Charsets.forName(settingBinder!!.read().outputCharset)?.charset() - ?: kotlin.text.Charsets.UTF_8, { + fileSaveHelper!!.saveOrCopy(apiInfo, markdownSettingsHelper.outputCharset(), { logger!!.info("Exported data are copied to clipboard,you can paste to a md file now") }, { logger!!.info("Apis save success: $it") diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/AbstractYapiApiExporter.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/AbstractYapiApiExporter.kt index 38936a08b..d27fbc072 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/AbstractYapiApiExporter.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/AbstractYapiApiExporter.kt @@ -8,6 +8,7 @@ import com.itangcent.idea.plugin.api.export.core.ClassExporter import com.itangcent.idea.plugin.api.export.core.Folder import com.itangcent.idea.plugin.api.export.core.FormatFolderHelper import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.helper.YapiSettingsHelper import com.itangcent.idea.utils.ModuleHelper import com.itangcent.intellij.context.ActionContext import com.itangcent.intellij.logger.Logger @@ -22,7 +23,7 @@ open class AbstractYapiApiExporter { protected val yapiApiHelper: YapiApiHelper? = null @Inject - protected val yapiApiInputHelper: YapiApiInputHelper? = null + protected lateinit var yapiSettingsHelper: YapiSettingsHelper @Inject protected val actionContext: ActionContext? = null @@ -52,11 +53,7 @@ open class AbstractYapiApiExporter { * see https://hellosean1025.github.io/yapi/openapi.html */ protected open fun getTokenOfModule(module: String): String? { - val privateToken = yapiApiHelper!!.getPrivateToken(module) - if (privateToken.isNullOrBlank()) { - return yapiApiInputHelper!!.inputToken(module) - } - return privateToken + return yapiSettingsHelper.getPrivateToken(module, false) } protected open fun getCartForResource(resource: Any): CartInfo? { @@ -122,19 +119,9 @@ open class AbstractYapiApiExporter { apiInfos.forEach { apiInfo -> apiInfo["token"] = privateToken apiInfo["catid"] = cartId - apiInfo["switch_notice"] = switchNotice() + apiInfo["switch_notice"] = yapiSettingsHelper.switchNotice() ret = ret or yapiApiHelper!!.saveApiInfo(apiInfo) } return ret } - - - protected fun switchNotice(): Boolean { - return settingBinder!!.read().switchNotice - } - - companion object { - const val NULL_RESOURCE = "unknown" - } - } \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/AbstractYapiApiHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/AbstractYapiApiHelper.kt index ff0e8ae01..fc3b436cb 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/AbstractYapiApiHelper.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/AbstractYapiApiHelper.kt @@ -10,25 +10,23 @@ import com.itangcent.idea.plugin.api.export.ReservedResponseHandle import com.itangcent.idea.plugin.api.export.core.StringResponseHandler import com.itangcent.idea.plugin.api.export.reserved import com.itangcent.idea.plugin.rule.SuvRuleContext -import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.helper.YapiSettingsHelper import com.itangcent.intellij.config.ConfigReader import com.itangcent.intellij.config.rule.RuleComputer import com.itangcent.intellij.extend.sub import com.itangcent.intellij.logger.Logger import com.itangcent.suv.http.HttpClientProvider import org.apache.commons.lang3.StringUtils -import java.io.ByteArrayOutputStream import java.net.SocketException import java.net.SocketTimeoutException -import java.util.* import java.util.concurrent.locks.ReadWriteLock import java.util.concurrent.locks.ReentrantReadWriteLock -import kotlin.collections.HashMap import kotlin.concurrent.withLock abstract class AbstractYapiApiHelper : YapiApiHelper { + @Inject - private val settingBinder: SettingBinder? = null + protected lateinit var yapiSettingsHelper: YapiSettingsHelper @Inject protected lateinit var logger: Logger @@ -42,9 +40,6 @@ abstract class AbstractYapiApiHelper : YapiApiHelper { @Inject protected val httpClientProvide: HttpClientProvider? = null - @Volatile - var server: String? = null - @Volatile var init: Boolean = false @@ -54,30 +49,10 @@ abstract class AbstractYapiApiHelper : YapiApiHelper { protected var cacheLock: ReadWriteLock = ReentrantReadWriteLock() - open fun hasPrivateToken(module: String): Boolean { - return getPrivateToken(module) != null - } - - override fun findServer(): String? { - if (!server.isNullOrBlank()) return server - server = configReader!!.first("server")?.trim()?.removeSuffix("/") - if (!server.isNullOrBlank()) return server - server = settingBinder!!.read().yapiServer?.trim()?.removeSuffix("/") - return server - } - - override fun setYapiServer(yapiServer: String) { - val settings = settingBinder!!.read() - settings.yapiServer = yapiServer - settingBinder.save(settings) - Thread.sleep(200) - server = yapiServer.removeSuffix("/") - } - open fun getProjectWeb(module: String): String? { - val token = getPrivateToken(module) - val projectId = getProjectIdByToken(token!!) ?: return null - return "$server/project/$projectId/interface/api" + val token = yapiSettingsHelper.getPrivateToken(module, false) ?: return null + val projectId = getProjectIdByToken(token) ?: return null + return "${yapiSettingsHelper.getServer()}/project/$projectId/interface/api" } protected open fun findErrorMsg(res: String?): String? { @@ -95,7 +70,7 @@ abstract class AbstractYapiApiHelper : YapiApiHelper { } override fun getProjectIdByToken(token: String): String? { - if (loginMode()) { + if (yapiSettingsHelper.loginMode()) { return token } var projectId = cacheLock.readLock().withLock { projectIdCache[token] } @@ -127,10 +102,10 @@ abstract class AbstractYapiApiHelper : YapiApiHelper { } } - var url = "$server$GET_PROJECT_URL?token=$token" + var url = "${yapiSettingsHelper.getServer(false)}$GET_PROJECT_URL?token=$token" var rawProjectId = projectId - if (loginMode() && rawProjectId == null) { + if (yapiSettingsHelper.loginMode() && rawProjectId == null) { rawProjectId = getProjectIdByToken(token) } if (rawProjectId != null) { @@ -149,7 +124,9 @@ abstract class AbstractYapiApiHelper : YapiApiHelper { if (projectInfo.has("errcode")) { if (projectInfo.get("errcode").asInt == 40011) { logger.warn("project:$projectId may be deleted.") - cacheLock.writeLock().withLock { projectInfoCache[projectId] = NULL_PROJECT } + cacheLock.writeLock().withLock { + projectInfoCache[projectId] = NULL_PROJECT + } return null } } @@ -174,7 +151,7 @@ abstract class AbstractYapiApiHelper : YapiApiHelper { } } var rawUrl = url - if (loginMode()) { + if (yapiSettingsHelper.loginMode()) { //token is insignificant in loginMode if (rawUrl.contains("token=")) { rawUrl = TOKEN_REGEX.replace(url) { "" } @@ -213,117 +190,6 @@ abstract class AbstractYapiApiHelper : YapiApiHelper { return StringResponseHandler.DEFAULT_RESPONSE_HANDLER.reserved() } - /** - * Tokens in setting. - * Map> - * state: null->no_checked, true->valid, false->invalid - */ - private var tokenMap: HashMap>? = null - - override fun getPrivateToken(module: String): String? { - - cacheLock.readLock().withLock { - if (tokenMap != null) { - val token = tokenMap!![module] ?: return null - when (token.second) { - true -> { - return token.first - } - false -> { - return null - } - } - } - } - - cacheLock.writeLock().withLock { - if (tokenMap == null) { - initToken() - } - val token = tokenMap!![module] ?: return null - return if (getProjectInfo(token.first) == null) { - tokenMap!![module] = token.first to false - null - } else { - tokenMap!![module] = token.first to true - token.first - } - } - } - - private fun initToken() { - tokenMap = HashMap() - val settings = settingBinder!!.read() - if (settings.yapiTokens != null) { - val properties = Properties() - properties.load(settings.yapiTokens!!.byteInputStream()) - properties.forEach { t, u -> tokenMap!![t.toString()] = u.toString() to null } - } - } - - private fun updateTokens(handle: (Properties) -> Unit) { - - cacheLock.writeLock().withLock { - val settings = settingBinder!!.read() - val properties = Properties() - if (settings.yapiTokens != null) { - properties.load(settings.yapiTokens!!.byteInputStream()) - } - handle(properties) - - val byteOutputStream = ByteArrayOutputStream() - properties.store(byteOutputStream, "") - settings.yapiTokens = byteOutputStream.toString() - settingBinder.save(settings) - if (tokenMap == null) { - tokenMap = HashMap() - } else { - tokenMap!!.clear() - } - properties.forEach { t, u -> tokenMap!![t.toString()] = u.toString() to null } - } - } - - override fun setToken(module: String, token: String) { - updateTokens { properties -> - properties[module] = token - } - } - - override fun removeTokenByModule(module: String) { - updateTokens { properties -> - properties.remove(module) - } - } - - override fun removeToken(token: String) { - updateTokens { properties -> - val removedKeys = properties.entries - .filter { it.value == token } - .map { it.key } - .toList() - removedKeys.forEach { properties.remove(it) } - } - } - - override fun readTokens(): HashMap { - if (tokenMap == null) { - initToken() - } - return HashMap(tokenMap!!.mapValues { it.value.first }) - } - - fun rawToken(token: String): String { - if (loginMode()) { - return "" - } - return token - } - - protected fun loginMode(): Boolean { - return settingBinder!!.read().loginMode - } - companion object { const val GET_PROJECT_URL = "/api/project/get" val NULL_PROJECT: JsonElement = JsonNull.INSTANCE diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/DefaultYapiApiHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/DefaultYapiApiHelper.kt index 59313686d..e78827b1b 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/DefaultYapiApiHelper.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/DefaultYapiApiHelper.kt @@ -12,7 +12,6 @@ import com.itangcent.intellij.extend.sub import org.apache.commons.lang3.StringUtils import org.apache.commons.lang3.exception.ExceptionUtils import org.apache.http.entity.ContentType -import java.util.* import kotlin.collections.set import kotlin.concurrent.withLock @@ -23,26 +22,26 @@ open class DefaultYapiApiHelper : AbstractYapiApiHelper(), YapiApiHelper { private var cartIdCache: HashMap = HashMap() override fun findCartWeb(module: String, cartName: String): String? { - val token = getPrivateToken(module) + val token = yapiSettingsHelper.getPrivateToken(module) val projectId = getProjectIdByToken(token!!) ?: return null val catId = findCat(token, cartName) ?: return null return getCartWeb(projectId, catId) } override fun getCartWeb(projectId: String, catId: String): String? { - return "$server/project/$projectId/interface/api/cat_$catId" + return "${yapiSettingsHelper.getServer()}/project/$projectId/interface/api/cat_$catId" } override fun getApiWeb(module: String, cartName: String, apiName: String): String? { - val token = getPrivateToken(module) + val token = yapiSettingsHelper.getPrivateToken(module) val projectId = getProjectIdByToken(token!!) ?: return null val catId = findCat(token, cartName) ?: return null val apiId = findApi(token, catId, apiName) - return "$server/project/$projectId/interface/api/$apiId" + return "${yapiSettingsHelper.getServer()}/project/$projectId/interface/api/$apiId" } override fun findCat(token: String, name: String): String? { - val projectId: String? = getProjectIdByToken(token) ?: return null + val projectId: String = getProjectIdByToken(token) ?: return null val key = "$projectId$name" var cachedCartId = cacheLock.readLock().withLock { cartIdCache[key] } if (cachedCartId != null) return cachedCartId @@ -73,14 +72,14 @@ open class DefaultYapiApiHelper : AbstractYapiApiHelper(), YapiApiHelper { override fun saveApiInfo(apiInfo: HashMap): Boolean { - if (loginMode() && apiInfo.containsKey("token")) { + if (yapiSettingsHelper.loginMode() && apiInfo.containsKey("token")) { apiInfo["project_id"] = apiInfo["token"] apiInfo.remove("token") } try { val returnValue = httpClientProvide!!.getHttpClient() - .post(server + SAVE_API) + .post(yapiSettingsHelper.getServer(false) + SAVE_API) .contentType(ContentType.APPLICATION_JSON) .body(apiInfo) .call() @@ -106,13 +105,13 @@ open class DefaultYapiApiHelper : AbstractYapiApiHelper(), YapiApiHelper { override fun addCart(projectId: String, token: String, name: String, desc: String): Boolean { try { val returnValue = httpClientProvide!!.getHttpClient() - .post(server + ADD_CART) + .post(yapiSettingsHelper.getServer(false) + ADD_CART) .contentType(ContentType.APPLICATION_JSON) .body(KV.create() .set("desc", desc) .set("project_id", projectId) .set("name", name) - .set("token", rawToken(token))) + .set("token", yapiSettingsHelper.rawToken(token))) .call() .string() @@ -129,7 +128,7 @@ open class DefaultYapiApiHelper : AbstractYapiApiHelper(), YapiApiHelper { cacheLock.writeLock().withLock { cartIdCache["$projectId$name"] = addCartId } - logger.info("Add new cart:$server/project/$projectId/interface/api/cat_$addCartId") + logger.info("Add new cart:${yapiSettingsHelper.getServer()}/project/$projectId/interface/api/cat_$addCartId") } else { logger.info("Add cart failed,response is:$returnValue") } @@ -142,7 +141,7 @@ open class DefaultYapiApiHelper : AbstractYapiApiHelper(), YapiApiHelper { } override fun findApi(token: String, catId: String, apiName: String): String? { - val url = "$server$GET_CAT?token=$token&catid=$catId&limit=1000" + val url = "${yapiSettingsHelper.getServer()}$GET_CAT?token=$token&catid=$catId&limit=1000" return GsonUtils.parseToJsonTree(getByApi(url)) ?.sub("data") ?.sub("list") @@ -153,7 +152,7 @@ open class DefaultYapiApiHelper : AbstractYapiApiHelper(), YapiApiHelper { } override fun findApis(token: String, catId: String): ArrayList? { - val url = "$server$GET_CAT?token=$token&catid=$catId&limit=1000" + val url = "${yapiSettingsHelper.getServer()}$GET_CAT?token=$token&catid=$catId&limit=1000" return GsonUtils.parseToJsonTree(getByApi(url)) ?.sub("data") ?.sub("list") @@ -161,7 +160,7 @@ open class DefaultYapiApiHelper : AbstractYapiApiHelper(), YapiApiHelper { } override fun findCarts(project_id: String, token: String): ArrayList? { - val url = "$server$GET_CAT_MENU?project_id=$project_id&token=$token" + val url = "${yapiSettingsHelper.getServer()}$GET_CAT_MENU?project_id=$project_id&token=$token" return GsonUtils.parseToJsonTree(getByApi(url)) ?.sub("data") ?.asList() diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/DefaultYapiApiInputHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/DefaultYapiApiInputHelper.kt deleted file mode 100644 index 24ca81e0b..000000000 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/DefaultYapiApiInputHelper.kt +++ /dev/null @@ -1,216 +0,0 @@ -package com.itangcent.idea.plugin.api.export.yapi - -import com.google.inject.Inject -import com.google.inject.Singleton -import com.intellij.openapi.project.Project -import com.intellij.openapi.ui.Messages -import com.itangcent.idea.plugin.settings.SettingBinder -import com.itangcent.intellij.context.ActionContext -import com.itangcent.intellij.logger.Logger -import java.awt.Component - -@Singleton -class DefaultYapiApiInputHelper : YapiApiInputHelper { - - @Inject - private val settingBinder: SettingBinder? = null - - @Inject - protected val yapiApiHelper: YapiApiHelper? = null - - @Inject - protected val actionContext: ActionContext? = null - - @Inject - protected val project: Project? = null - - @Inject - protected val logger: Logger? = null - - override fun inputServer(): String? { - return actionContext!!.callInSwingUI { - val yapiServer = Messages.showInputDialog(project, "Input server of yapi", - "server of yapi", Messages.getInformationIcon()) - if (yapiServer.isNullOrBlank()) { - logger!!.info("No yapi server") - return@callInSwingUI null - } - - yapiApiHelper!!.setYapiServer(yapiServer) - return@callInSwingUI yapiServer - } - } - - override fun inputServer(parent: Component): String? { - return actionContext!!.callInSwingUI { - val yapiServer = Messages.showInputDialog(parent, "Input server of yapi", - "server of yapi", Messages.getInformationIcon()) - if (yapiServer.isNullOrBlank()) { - logger!!.info("No yapi server") - return@callInSwingUI null - } - - yapiApiHelper!!.setYapiServer(yapiServer) - return@callInSwingUI yapiServer - } - } - - override fun inputServer(next: (String?) -> Unit) { - actionContext!!.runAsync { - Thread.sleep(200) - actionContext.runInSwingUI { - val yapiServer = Messages.showInputDialog(project, "Input server of yapi", - "server of yapi", Messages.getInformationIcon()) - if (yapiServer.isNullOrBlank()) { - logger!!.info("No yapi server") - return@runInSwingUI - } - - yapiApiHelper!!.setYapiServer(yapiServer) - next(yapiServer) - } - } - - } - - override fun inputServer(parent: Component, next: (String?) -> Unit) { - actionContext!!.runAsync { - Thread.sleep(200) - actionContext.runInSwingUI { - val yapiServer = Messages.showInputDialog(parent, "Input server of yapi", - "server of yapi", Messages.getInformationIcon()) - if (yapiServer.isNullOrBlank()) { - logger!!.info("No yapi server") - return@runInSwingUI - } - yapiApiHelper!!.setYapiServer(yapiServer) - next(yapiServer) - } - } - - } - - override fun inputToken(): String? { - - if (loginMode()) { - val projectId = actionContext!!.callInSwingUI { - return@callInSwingUI Messages.showInputDialog(project, - "Input ProjectId", - "Yapi ProjectId", Messages.getInformationIcon()) - } - if (projectId.isNullOrBlank()) { - return null - } - return projectId - } - - val modulePrivateToken = actionContext!!.callInSwingUI { - return@callInSwingUI Messages.showInputDialog(project, "Input Private Token", - "Yapi Private Token", Messages.getInformationIcon()) - } - if (modulePrivateToken.isNullOrBlank()) { - return null - } - - return modulePrivateToken - } - - override fun inputToken(parent: Component): String? { - - if (loginMode()) { - val projectId = actionContext!!.callInSwingUI { - return@callInSwingUI Messages.showInputDialog(parent, - "Input ProjectId", - "Yapi ProjectId", Messages.getInformationIcon()) - } - if (projectId.isNullOrBlank()) { - return null - } - return projectId - } - - val modulePrivateToken = actionContext!!.callInSwingUI { - return@callInSwingUI Messages.showInputDialog(parent, "Input Private Token", - "Yapi Private Token", Messages.getInformationIcon()) - } - - if (modulePrivateToken.isNullOrBlank()) { - return null - } - return modulePrivateToken - } - - private var tryInputTokenOfModule: HashSet = HashSet() - - override fun inputToken(module: String): String? { - - //return null if user had cancel or ignore of input token of this module - if (!tryInputTokenOfModule.add(module)) { - return null - } - - tryInputTokenOfModule.add(module) - - if (loginMode()) { - val projectId = actionContext!!.callInSwingUI { - return@callInSwingUI Messages.showInputDialog(project, - "Input ProjectId Of Module:$module", - "Yapi ProjectId", Messages.getInformationIcon()) - } - if (projectId.isNullOrBlank()) { - return null - } - yapiApiHelper!!.setToken(module, projectId) - return projectId - } - - val modulePrivateToken = actionContext!!.callInSwingUI { - return@callInSwingUI Messages.showInputDialog(project, "Input Private Token Of Module:$module", - "Yapi Private Token", Messages.getInformationIcon()) - } - if (modulePrivateToken.isNullOrBlank()) { - return null - } - - yapiApiHelper!!.setToken(module, modulePrivateToken) - return modulePrivateToken - } - - override fun inputToken(parent: Component, module: String): String? { - - //return null if user had cancel or ignore of input token of this module - if (!tryInputTokenOfModule.add(module)) { - return null - } - - tryInputTokenOfModule.add(module) - - if (loginMode()) { - val projectId = actionContext!!.callInSwingUI { - return@callInSwingUI Messages.showInputDialog(parent, - "Input ProjectId Of Module:$module", - "Yapi ProjectId", Messages.getInformationIcon()) - } - if (projectId.isNullOrBlank()) { - return null - } - yapiApiHelper!!.setToken(module, projectId) - return projectId - } - - val modulePrivateToken = actionContext!!.callInSwingUI { - return@callInSwingUI Messages.showInputDialog(parent, "Input Private Token Of Module:$module", - "Yapi Private Token", Messages.getInformationIcon()) - } - - if (modulePrivateToken.isNullOrBlank()) { - return null - } - yapiApiHelper!!.setToken(module, modulePrivateToken) - return modulePrivateToken - } - - private fun loginMode(): Boolean { - return settingBinder!!.read().loginMode - } -} \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiApiExporter.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiApiExporter.kt index 67a4b5051..e4f3d073b 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiApiExporter.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiApiExporter.kt @@ -10,22 +10,15 @@ import com.itangcent.idea.plugin.api.export.core.Folder import com.itangcent.intellij.psi.SelectedHelper import com.itangcent.intellij.util.ActionUtils import com.itangcent.intellij.util.FileType -import java.util.* import kotlin.collections.set class YapiApiExporter : AbstractYapiApiExporter() { fun export() { - val serverFound = yapiApiHelper!!.findServer().notNullOrBlank() + val serverFound = yapiSettingsHelper.getServer(false).notNullOrBlank() if (serverFound) { doExport() - } else { - yapiApiInputHelper!!.inputServer { - if (it.notNullOrBlank()) { - doExport() - } - } } } @@ -40,7 +33,7 @@ class YapiApiExporter : AbstractYapiApiExporter() { val project = actionContext.instance(Project::class) val yes = Messages.showYesNoDialog(project, "Export the model in directory [${ActionUtils.findCurrentPath(dir)}]?", - "Are you sure", + "Please Confirm", Messages.getQuestionIcon()) if (yes == Messages.YES) { callBack(true) diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiApiHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiApiHelper.kt index d90639452..f2ee02b48 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiApiHelper.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiApiHelper.kt @@ -29,23 +29,9 @@ interface YapiApiHelper { fun findCarts(project_id: String, token: String): ArrayList? - fun findServer(): String? - - fun setYapiServer(yapiServer: String) - - fun setToken(module: String, token: String) - fun getProjectIdByToken(token: String): String? fun getProjectInfo(token: String, projectId: String?): JsonElement? fun getProjectInfo(token: String): JsonObject? - - fun readTokens(): HashMap - - fun removeToken(token: String) - - fun removeTokenByModule(module: String) - - fun getPrivateToken(module: String): String? } \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiApiInputHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiApiInputHelper.kt deleted file mode 100644 index 13f54cbf0..000000000 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiApiInputHelper.kt +++ /dev/null @@ -1,71 +0,0 @@ -package com.itangcent.idea.plugin.api.export.yapi - -import com.google.inject.ImplementedBy -import java.awt.Component - - -@ImplementedBy(DefaultYapiApiInputHelper::class) -interface YapiApiInputHelper { - - /** - * input yapi server url - * - * @return return the input yapi server or null - */ - fun inputServer(): String? - - /** - * input yapi server url - * - * @param parent the parent Component to show the input dialog - * - * @return return the input yapi server or null - */ - fun inputServer(parent: Component): String? - - /** - * input yapi server url - * - * @param next the next action which be called with the server url - */ - fun inputServer(next: (String?) -> Unit) - - /** - * input yapi server url - * - * @param parent the parent Component to show the input dialog - * @param next the next action which be called with the server url - */ - fun inputServer(parent: Component, next: (String?) -> Unit) - - /** - * input token of the special module - * - * @return return the input token or null - */ - fun inputToken(): String? - - /** - * input token of the special module - * - * @param parent the parent Component to show the input dialog - * @return return the input token or null - */ - fun inputToken(parent: Component): String? - - /** - * input token of the special module - * - * @return return the input token or null - */ - fun inputToken(module: String): String? - - /** - * input token of the special module - * - * @param parent the parent Component to show the input dialog - * @return return the input token or null - */ - fun inputToken(parent: Component, module: String): String? - -} \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiCachedApiHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiCachedApiHelper.kt index f71fb3100..9cd33d862 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiCachedApiHelper.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiCachedApiHelper.kt @@ -22,7 +22,7 @@ open class YapiCachedApiHelper : DefaultYapiApiHelper() { override fun getProjectIdByToken(token: String): String? { try { - val tokenBeanBinder = dbBeanBinderFactory.getBeanBinder("yapi:token-${loginMode().toInt()}:$token") + val tokenBeanBinder = dbBeanBinderFactory.getBeanBinder("yapi:token-${yapiSettingsHelper.loginMode().toInt()}:$token") val projectIdInCache = tokenBeanBinder.read() if (projectIdInCache.isNotBlank()) { return projectIdInCache diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiFormatter.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiFormatter.kt index f87d0363a..1cdcbd654 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiFormatter.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiFormatter.kt @@ -11,8 +11,7 @@ import com.itangcent.idea.plugin.api.export.core.ClassExportRuleKeys import com.itangcent.idea.plugin.api.export.core.ResolveMultiPath import com.itangcent.idea.plugin.json.Json5Formatter import com.itangcent.idea.plugin.render.MarkdownRender -import com.itangcent.idea.plugin.settings.SettingBinder -import com.itangcent.idea.plugin.settings.Settings +import com.itangcent.idea.plugin.settings.helper.YapiSettingsHelper import com.itangcent.idea.psi.resource import com.itangcent.idea.psi.resourceMethod import com.itangcent.idea.utils.SystemProvider @@ -53,9 +52,7 @@ open class YapiFormatter { protected lateinit var systemProvider: SystemProvider @Inject - protected lateinit var settingBinder: SettingBinder - - private val setting: Settings by lazy { settingBinder.read() } + protected lateinit var yapiSettingsHelper: YapiSettingsHelper fun doc2Item(doc: Doc): List> { if (doc is Request) { @@ -130,7 +127,7 @@ open class YapiFormatter { if (methodDoc.ret != null) { item["res_body_type"] = "json" - if (setting.yapiResBodyJson5) { + if (yapiSettingsHelper.yapiResBodyJson5()) { item["res_body_is_json_schema"] = false item["res_body"] = parseByJson5(methodDoc.ret, methodDoc.resourceMethod()?.let { @@ -144,7 +141,6 @@ open class YapiFormatter { } } else { item["res_body_type"] = "json" - item["res_body"] = "" } @@ -365,7 +361,7 @@ open class YapiFormatter { item["req_body_type"] = "json" item["req_body_form"] = EMPTY_ARR - if (setting.yapiResBodyJson5) { + if (yapiSettingsHelper.yapiReqBodyJson5()) { item["req_body_is_json_schema"] = false item["req_body_other"] = parseByJson5(request.body, request.bodyAttr) } else { @@ -378,7 +374,7 @@ open class YapiFormatter { val response = request.response!![0] item["res_body_type"] = "json" - if (setting.yapiResBodyJson5) { + if (yapiSettingsHelper.yapiResBodyJson5()) { item["res_body_is_json_schema"] = false item["res_body"] = parseByJson5(response.body, request.resourceMethod()?.let { findReturnOfMethod(it) @@ -813,7 +809,7 @@ open class YapiFormatter { ) return@safeComputeIfAbsent { - pattern.matcher(it).matches() + pattern.matcher(it ?: "").matches() } } diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiSpringRequestClassExporter.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiSpringRequestClassExporter.kt index c3a83f437..006c072d0 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiSpringRequestClassExporter.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiSpringRequestClassExporter.kt @@ -1,5 +1,7 @@ package com.itangcent.idea.plugin.api.export.yapi +import com.google.inject.Inject +import com.google.inject.Singleton import com.itangcent.common.constant.Attrs import com.itangcent.common.model.Header import com.itangcent.common.model.Param @@ -10,14 +12,19 @@ import com.itangcent.idea.plugin.api.export.core.MethodExportContext import com.itangcent.idea.plugin.api.export.core.addParam import com.itangcent.idea.plugin.api.export.core.addPathParam import com.itangcent.idea.plugin.api.export.spring.SpringRequestClassExporter +import com.itangcent.idea.plugin.settings.helper.YapiSettingsHelper import com.itangcent.utils.ExtensibleKit.fromJson /** * * 1.support enableUrlTemplating */ +@Singleton open class YapiSpringRequestClassExporter : SpringRequestClassExporter() { + @Inject + private lateinit var yapiSettingsHelper: YapiSettingsHelper + override fun resolveParamStr(methodExportContext: MethodExportContext, request: Request, params: String) { when { @@ -39,7 +46,7 @@ open class YapiSpringRequestClassExporter : SpringRequestClassExporter() { } !params.contains('=') -> { val param = request.querys?.find { it.name == params } - if (enableUrlTemplating()) { + if (yapiSettingsHelper.enableUrlTemplating()) { addParamToPath(request, params, "{$params}") requestBuilderListener.addPathParam(methodExportContext, request, params, "", param?.desc) @@ -61,7 +68,7 @@ open class YapiSpringRequestClassExporter : SpringRequestClassExporter() { val value = params.substringAfter("=").trim() val param = request.querys?.find { it.name == name } - if (enableUrlTemplating()) { + if (yapiSettingsHelper.enableUrlTemplating()) { addParamToPath(request, name, value) requestBuilderListener.addPathParam(methodExportContext, request, name, value, param?.desc) @@ -100,8 +107,4 @@ open class YapiSpringRequestClassExporter : SpringRequestClassExporter() { override fun parseHeaderFromJson(headerStr: String) = Header::class.fromJson(headerStr, Attrs.EXAMPLE_ATTR) override fun parseParamFromJson(paramStr: String) = Param::class.fromJson(paramStr, Attrs.EXAMPLE_ATTR) - - protected fun enableUrlTemplating(): Boolean { - return settingBinder!!.read().enableUrlTemplating - } } \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiTokenCheckerSupport.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiTokenCheckerSupport.kt new file mode 100644 index 000000000..7012e2932 --- /dev/null +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/api/export/yapi/YapiTokenCheckerSupport.kt @@ -0,0 +1,16 @@ +package com.itangcent.idea.plugin.api.export.yapi + +import com.google.inject.Inject +import com.google.inject.Singleton +import com.itangcent.idea.plugin.settings.helper.YapiTokenChecker + +@Singleton +class YapiTokenCheckerSupport : YapiTokenChecker { + + @Inject + private lateinit var yapiApiHelper: YapiApiHelper + + override fun checkToken(token: String): Boolean { + return yapiApiHelper.getProjectInfo(token) != null + } +} \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/config/RecommendConfigReader.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/config/RecommendConfigReader.kt index c4d05c126..c474fe4b1 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/config/RecommendConfigReader.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/config/RecommendConfigReader.kt @@ -4,7 +4,8 @@ import com.google.inject.Inject import com.google.inject.name.Named import com.itangcent.common.utils.invokeMethod import com.itangcent.common.utils.notNullOrBlank -import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.helper.BuiltInConfigSettingsHelper +import com.itangcent.idea.plugin.settings.helper.RecommendConfigSettingsHelper import com.itangcent.intellij.adaptor.ModuleAdaptor.file import com.itangcent.intellij.adaptor.ModuleAdaptor.filePath import com.itangcent.intellij.config.ConfigReader @@ -22,16 +23,19 @@ class RecommendConfigReader : ConfigReader, Initializable { @Inject @Named("delegate_config_reader") - val configReader: ConfigReader? = null + private val configReader: ConfigReader? = null @Inject(optional = true) - val settingBinder: SettingBinder? = null + private val builtInConfigSettingsHelper: BuiltInConfigSettingsHelper? = null + + @Inject(optional = true) + private val recommendConfigSettingsHelper: RecommendConfigSettingsHelper? = null @Inject - val contextSwitchListener: ContextSwitchListener? = null + private val contextSwitchListener: ContextSwitchListener? = null @Inject - val logger: Logger? = null + private val logger: Logger? = null @Inject private val devEnv: DevEnv? = null @@ -110,22 +114,18 @@ class RecommendConfigReader : ConfigReader, Initializable { } private fun tryLoadRecommend() { - if (settingBinder?.read()?.useRecommendConfig == true) { - if (settingBinder.read().recommendConfigs.isEmpty()) { - logger!!.info( - "Even useRecommendConfig was true, but no recommend config be selected!\n" + - "\n" + - "If you need to enable the built-in recommended configuration." + - "Go to [Preference -> Other Setting -> EasyApi -> Recommend]" - ) - return - } - + if (recommendConfigSettingsHelper?.useRecommendConfig() == true) { if (configReader is MutableConfigReader) { - val recommendConfig = RecommendConfigLoader.buildRecommendConfig(settingBinder.read().recommendConfigs) + val recommendConfig = recommendConfigSettingsHelper.loadRecommendConfig() if (recommendConfig.isEmpty()) { - logger!!.warn("No recommend config be selected!") + logger!!.info( + "Even useRecommendConfig was true, but no recommend config be selected!\n" + + "\n" + + "If you need to enable the built-in recommended configuration." + + "Go to [Preference -> Other Setting -> EasyApi -> Recommend]" + ) + return } @@ -141,7 +141,7 @@ class RecommendConfigReader : ConfigReader, Initializable { } private fun tryLoadBuiltIn() { - val builtInConfig = settingBinder?.read()?.builtInConfig + val builtInConfig = builtInConfigSettingsHelper?.builtInConfig() if (builtInConfig.notNullOrBlank()) { if (configReader is MutableConfigReader) { configReader.loadConfigInfoContent(builtInConfig!!) diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/AbstractApiDashboardDialog.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/AbstractApiDashboardDialog.kt index 007424e0c..3469aaaec 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/AbstractApiDashboardDialog.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/AbstractApiDashboardDialog.kt @@ -21,10 +21,7 @@ import com.itangcent.idea.psi.PsiResource import com.itangcent.idea.psi.ResourceHelper import com.itangcent.idea.psi.resourceClass import com.itangcent.idea.psi.resourceMethod -import com.itangcent.idea.swing.IconCustomized -import com.itangcent.idea.swing.SafeHashHelper -import com.itangcent.idea.swing.ToolTipAble -import com.itangcent.idea.swing.Tooltipable +import com.itangcent.idea.swing.* import com.itangcent.idea.utils.SwingUtils import com.itangcent.intellij.context.ActionContext import com.itangcent.intellij.extend.rx.AutoComputer @@ -59,7 +56,7 @@ abstract class AbstractApiDashboardDialog : JDialog() { protected val logger: Logger? = null @Inject - protected var actionContext: ActionContext? = null + protected lateinit var actionContext: ActionContext @Inject protected val classExporter: ClassExporter? = null @@ -77,11 +74,16 @@ abstract class AbstractApiDashboardDialog : JDialog() { @Inject var project: Project? = null + @Inject(optional = true) + private var activeWindowProvider: ActiveWindowProvider? = null + protected var apiLoadFuture: Future<*>? = null //region project module----------------------------------------------------- protected fun initProjectApiModule() { + (activeWindowProvider as? MutableActiveWindowProvider)?.setActiveWindow(this) + projectApiTree!!.model = null projectApiTree!!.dragEnabled = true @@ -100,8 +102,8 @@ abstract class AbstractApiDashboardDialog : JDialog() { } } - actionContext!!.runAsync { - actionContext!!.runInReadUI { + actionContext.runAsync { + actionContext.runInReadUI { val moduleManager = ModuleManager.getInstance(project!!) val treeNode = DefaultMutableTreeNode() @@ -115,10 +117,10 @@ abstract class AbstractApiDashboardDialog : JDialog() { moduleNodes.add(moduleProjectNode) } - actionContext!!.runInSwingUI { + actionContext.runInSwingUI { val rootTreeModel = DefaultTreeModel(treeNode, true) projectApiTree!!.model = rootTreeModel - apiLoadFuture = actionContext!!.runAsync { + apiLoadFuture = actionContext.runAsync { for (moduleNode in moduleNodes) { if (disposed) break loadApiInModule(moduleNode, rootTreeModel) @@ -169,7 +171,7 @@ abstract class AbstractApiDashboardDialog : JDialog() { } countLatch.down() val classNodeMap: ConcurrentHashMap = ConcurrentHashMap() - actionContext!!.runInReadUI { + actionContext.runInReadUI { try { if (disposed) { LOG.info("interrupt parsing api from ${contentRoot.path} because the action ApiDashBoard was disposed") @@ -230,7 +232,7 @@ abstract class AbstractApiDashboardDialog : JDialog() { } } } - actionContext!!.runAsync { + actionContext.runAsync { TimeUnit.MILLISECONDS.sleep(2000)//wait 2s countLatch.waitFor(60000)//60s if (anyFound) { diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/ApiDashboardDialog.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/ApiDashboardDialog.kt index 1270699af..eec203b67 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/ApiDashboardDialog.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/ApiDashboardDialog.kt @@ -8,10 +8,12 @@ import com.itangcent.common.model.Doc import com.itangcent.common.model.Request import com.itangcent.common.utils.DateUtils import com.itangcent.common.utils.mapNotNull +import com.itangcent.common.utils.notNullOrBlank import com.itangcent.idea.icons.EasyIcons import com.itangcent.idea.icons.iconOnly import com.itangcent.idea.plugin.api.export.postman.PostmanCachedApiHelper import com.itangcent.idea.plugin.api.export.postman.PostmanFormatter +import com.itangcent.idea.plugin.settings.helper.PostmanSettingsHelper import com.itangcent.idea.swing.EasyApiTreeCellRenderer import com.itangcent.idea.swing.IconCustomized import com.itangcent.idea.swing.ToolTipAble @@ -34,9 +36,6 @@ import javax.swing.tree.DefaultMutableTreeNode import javax.swing.tree.DefaultTreeModel import javax.swing.tree.TreeNode import javax.swing.tree.TreePath -import kotlin.collections.ArrayList -import kotlin.collections.HashMap -import kotlin.collections.LinkedHashMap class ApiDashboardDialog : AbstractApiDashboardDialog() { @@ -56,7 +55,10 @@ class ApiDashboardDialog : AbstractApiDashboardDialog() { var postmanPopMenu: JPopupMenu? = null @Inject - private val postmanCachedApiHelper: PostmanCachedApiHelper? = null + private lateinit var postmanCachedApiHelper: PostmanCachedApiHelper + + @Inject + private lateinit var postmanSettingsHelper: PostmanSettingsHelper @Inject private val postmanFormatter: PostmanFormatter? = null @@ -183,9 +185,8 @@ class ApiDashboardDialog : AbstractApiDashboardDialog() { autoComputer.bindEnable(this.postmanNewCollectionButton!!) .from(this::postmanAvailable) - if (!postmanCachedApiHelper!!.hasPrivateToken()) { + if (!postmanSettingsHelper.hasPrivateToken()) { autoComputer.value(this::postmanAvailable, false) - tryInputPostmanPrivateToken() } else { loadPostmanInfo(true) @@ -245,12 +246,8 @@ class ApiDashboardDialog : AbstractApiDashboardDialog() { private fun tryInputPostmanPrivateToken() { actionContext!!.runAsync { Thread.sleep(200) - actionContext!!.runInSwingUI { - val postmanPrivateToken = Messages.showInputDialog(this, "Input Postman Private Token", - "Postman Private Token", Messages.getInformationIcon()) - if (postmanPrivateToken.isNullOrBlank()) return@runInSwingUI - - postmanCachedApiHelper!!.setPrivateToken(postmanPrivateToken) + val postmanPrivateToken = postmanSettingsHelper.getPrivateToken(false) + if (postmanPrivateToken.notNullOrBlank()) { autoComputer.value(this::postmanAvailable, true) loadPostmanInfo(true) } @@ -259,7 +256,7 @@ class ApiDashboardDialog : AbstractApiDashboardDialog() { private fun loadPostmanInfo(useCache: Boolean) { - if (!postmanCachedApiHelper!!.hasPrivateToken()) { + if (!postmanSettingsHelper.hasPrivateToken()) { actionContext!!.runInSwingUI { Messages.showErrorDialog(this, "load postman info failed,no token be found", "Error") diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/EasyApiSettingGUI.form b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/EasyApiSettingGUI.form index d6dc9f2a1..65297cebb 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/EasyApiSettingGUI.form +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/EasyApiSettingGUI.form @@ -3,7 +3,7 @@ - + @@ -56,7 +56,7 @@ - + @@ -74,7 +74,7 @@ - + @@ -885,11 +885,11 @@ - + - + @@ -927,6 +927,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/EasyApiSettingGUI.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/EasyApiSettingGUI.kt index 187b422fa..34ae0eaf5 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/EasyApiSettingGUI.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/EasyApiSettingGUI.kt @@ -16,12 +16,12 @@ import com.intellij.ui.CheckBoxList import com.itangcent.common.utils.* import com.itangcent.idea.icons.EasyIcons import com.itangcent.idea.icons.iconOnly -import com.itangcent.idea.plugin.config.RecommendConfigLoader import com.itangcent.idea.plugin.settings.MarkdownFormatType import com.itangcent.idea.plugin.settings.PostmanJson5FormatType import com.itangcent.idea.plugin.settings.Settings +import com.itangcent.idea.plugin.settings.helper.CommonSettingsHelper +import com.itangcent.idea.plugin.settings.helper.RecommendConfigLoader import com.itangcent.idea.utils.Charsets -import com.itangcent.idea.utils.ConfigurableLogger import com.itangcent.idea.utils.SwingUtils import com.itangcent.intellij.extend.rx.AutoComputer import com.itangcent.intellij.extend.rx.ThrottleHelper @@ -117,6 +117,8 @@ class EasyApiSettingGUI { private var httpTimeOutTextField: JTextField? = null + private var trustHostsTextArea: JTextArea? = null + //endregion general----------------------------------------------------- //region recommend @@ -266,12 +268,12 @@ class EasyApiSettingGUI { } } - logLevelComboBox!!.model = DefaultComboBoxModel(ConfigurableLogger.CoarseLogLevel.editableValues()) + logLevelComboBox!!.model = DefaultComboBoxModel(CommonSettingsHelper.CoarseLogLevel.editableValues()) autoComputer.bind(this, "settings.logLevel") .with(this.logLevelComboBox!!) .filter { throttleHelper.acquire("settings.logLevel", 300) } - .eval { (it ?: ConfigurableLogger.CoarseLogLevel.LOW).getLevel() } + .eval { (it ?: CommonSettingsHelper.CoarseLogLevel.LOW).getLevel() } outputCharsetComboBox!!.model = DefaultComboBoxModel(Charsets.SUPPORTED_CHARSETS) @@ -302,6 +304,14 @@ class EasyApiSettingGUI { .with(builtInConfigTextArea!!) .eval { it.takeIf { it != DEFAULT_BUILT_IN_CONFIG } ?: "" } + autoComputer.bind>(this, "settings.trustHosts") + .with(trustHostsTextArea!!) + .eval { trustHosts -> trustHosts?.lines()?.toTypedArray() ?: emptyArray() } + + autoComputer.bind(trustHostsTextArea!!) + .with>(this, "settings.trustHosts") + .eval { trustHosts -> trustHosts.joinToString(separator = "\n") } + //endregion general----------------------------------------------------- refresh() @@ -309,7 +319,7 @@ class EasyApiSettingGUI { bindRecommendConfig() this.recommendConfigList!!.setCheckBoxListListener { index, value -> - val code = RecommendConfigLoader[index] ?: return@setCheckBoxListListener + val code = RecommendConfigLoader[index] val settings = this.settings!! if (value) { settings.recommendConfigs = RecommendConfigLoader.addSelectedConfig(settings.recommendConfigs, code) @@ -333,7 +343,7 @@ class EasyApiSettingGUI { autoComputer.value(this::settings, settings.copy()) - this.logLevelComboBox!!.selectedItem = ConfigurableLogger.CoarseLogLevel.toLevel(settings.logLevel) + this.logLevelComboBox!!.selectedItem = CommonSettingsHelper.CoarseLogLevel.toLevel(settings.logLevel) this.outputCharsetComboBox!!.selectedItem = Charsets.forName(settings.outputCharset) this.postmanJson5FormatTypeComboBox!!.selectedItem = settings.postmanJson5FormatType this.markdownFormatTypeComboBox!!.selectedItem = settings.markdownFormatType diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/ScriptExecutorDialog.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/ScriptExecutorDialog.kt index 56a2d3c8d..c1fc820c5 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/ScriptExecutorDialog.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/ScriptExecutorDialog.kt @@ -18,8 +18,7 @@ import com.itangcent.common.logger.traceError import com.itangcent.common.logger.traceWarn import com.itangcent.common.utils.notNullOrEmpty import com.itangcent.idea.plugin.rule.contextOf -import com.itangcent.idea.plugin.settings.SettingBinder -import com.itangcent.idea.utils.Charsets +import com.itangcent.idea.plugin.settings.helper.CommonSettingsHelper import com.itangcent.idea.utils.FileSaveHelper import com.itangcent.idea.utils.FileSelectHelper import com.itangcent.intellij.config.rule.RuleParser @@ -47,7 +46,6 @@ import javax.script.ScriptEngineManager import javax.swing.* import javax.swing.event.ListDataEvent import javax.swing.event.ListDataListener -import kotlin.collections.ArrayList class ScriptExecutorDialog : JDialog() { @@ -446,7 +444,7 @@ class ScriptExecutorDialog : JDialog() { this.scriptTypeComboBox!!.selectedItem = scriptType } } - val script = file.readText(kotlin.text.Charsets.UTF_8) + val script = file.readText(Charsets.UTF_8) actionContext!!.runInSwingUI { editor?.document?.setText(script) } @@ -455,8 +453,8 @@ class ScriptExecutorDialog : JDialog() { } private fun onSave() { - val charset = ActionContext.getContext()?.instance(SettingBinder::class)?.read() - ?.outputCharset?.let { Charsets.forName(it) }?.charset() ?: kotlin.text.Charsets.UTF_8 + val charset = ActionContext.getContext()?.instance(CommonSettingsHelper::class)?.outputCharset() + ?: Charsets.UTF_8 fileSaveHelper!!.saveBytes({ (scriptInfo?.script ?: "").toByteArray(charset) }, { diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/YapiDashboardDialog.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/YapiDashboardDialog.kt index 41bb1278d..84458e560 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/YapiDashboardDialog.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/dialog/YapiDashboardDialog.kt @@ -8,7 +8,7 @@ import com.itangcent.common.utils.notNullOrBlank import com.itangcent.idea.icons.EasyIcons import com.itangcent.idea.plugin.api.export.yapi.YapiApiDashBoardExporter import com.itangcent.idea.plugin.api.export.yapi.YapiApiHelper -import com.itangcent.idea.plugin.api.export.yapi.YapiApiInputHelper +import com.itangcent.idea.plugin.settings.helper.YapiSettingsHelper import com.itangcent.idea.swing.EasyApiTreeCellRenderer import com.itangcent.idea.swing.IconCustomized import com.itangcent.idea.swing.Tooltipable @@ -32,7 +32,6 @@ import javax.swing.* import javax.swing.tree.DefaultMutableTreeNode import javax.swing.tree.DefaultTreeModel import javax.swing.tree.TreePath -import kotlin.collections.ArrayList class YapiDashboardDialog : AbstractApiDashboardDialog() { @@ -53,13 +52,13 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { private var projectMode: ProjectMode = ProjectMode.Legible @Inject - private val yapiApiHelper: YapiApiHelper? = null + private lateinit var yapiApiHelper: YapiApiHelper @Inject - protected val yapiApiInputHelper: YapiApiInputHelper? = null + private val yapiApiDashBoardExporter: YapiApiDashBoardExporter? = null @Inject - private val yapiApiDashBoardExporter: YapiApiDashBoardExporter? = null + protected lateinit var yapiSettingsHelper: YapiSettingsHelper init { setContentPane(contentPane) @@ -159,7 +158,7 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { @PostConstruct fun postConstruct() { - actionContext!!.hold() + actionContext.hold() initProjectApiModule() @@ -183,16 +182,16 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { autoComputer.bindEnable(this.yapiNewProjectButton!!) .from(this::yapiAvailable) - if (yapiApiHelper!!.findServer().isNullOrEmpty()) { + if (yapiSettingsHelper.hasServer()) { + loadYapiInfo() + } else { autoComputer.value(this::yapiAvailable, false) - yapiApiInputHelper!!.inputServer { - if (it.notNullOrBlank()) { + actionContext.runAsync { + if (yapiSettingsHelper.getServer(false).notNullOrBlank()) { autoComputer.value(this::yapiAvailable, true) loadYapiInfo() } } - } else { - loadYapiInfo() } //drop drag from api to yapi @@ -248,28 +247,28 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { private fun loadYapiInfo() { - if (yapiApiHelper!!.findServer().isNullOrEmpty()) { - actionContext!!.runInSwingUI { + if (!yapiSettingsHelper.hasServer()) { + actionContext.runInSwingUI { Messages.showErrorDialog(this, "load yapi info failed,no server be found", "Error") } return } - actionContext!!.runInSwingUI { + actionContext.runInSwingUI { // yapiApiTree!!.dragEnabled = true val treeNode = DefaultMutableTreeNode() val rootTreeModel = DefaultTreeModel(treeNode, true) - actionContext!!.runAsync { + actionContext.runAsync { var projectNodes: ArrayList? = null try { - val yapiTokens = yapiApiHelper.readTokens() + val yapiTokens = yapiSettingsHelper.readTokens() if (yapiTokens.isNullOrEmpty()) { - actionContext!!.runInSwingUI { - Messages.showErrorDialog(actionContext!!.instance(Project::class), + actionContext.runInSwingUI { + Messages.showErrorDialog(actionContext.instance(Project::class), "No token be found", "Error") } return@runAsync @@ -303,10 +302,10 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { logger!!.error("error to load yapi info:" + ExceptionUtils.getStackTrace(e)) } - actionContext!!.runInSwingUI { + actionContext.runInSwingUI { yapiApiTree!!.model = rootTreeModel - yapiLoadFuture = actionContext!!.runAsync { + yapiLoadFuture = actionContext.runAsync { Thread.sleep(500) if (projectNodes != null) { for (projectNode in projectNodes) { @@ -328,14 +327,14 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { val projectId = yapiProjectNodeData.getProjectId() val yapiApiTreeModel = yapiApiTree!!.model as DefaultTreeModel if (projectId == null) { - actionContext!!.runInSwingUI { + actionContext.runInSwingUI { projectNode.removeFromParent() yapiApiTreeModel.reload(projectNode) } return } - actionContext!!.runAsync { + actionContext.runAsync { yapiProjectNodeData.status = NodeStatus.Loading try { val carts = yapiApiHelper!!.findCarts(projectId.toString(), yapiProjectNodeData.getProjectToken()!!) @@ -343,7 +342,7 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { yapiProjectNodeData.status = NodeStatus.Loaded return@runAsync } - actionContext!!.runInSwingUI { + actionContext.runInSwingUI { for (cart in carts) { val yapiCartNode = YapiCartNodeData(yapiProjectNodeData, cart as HashMap) @@ -360,13 +359,13 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { @Suppress("UNCHECKED_CAST") private fun loadYapiCart(parentNode: DefaultMutableTreeNode, yapiCartNodeData: YapiCartNodeData) { - actionContext!!.runInSwingUI { + actionContext.runInSwingUI { val parentNodeData = parentNode.userObject as YapiProjectNodeData val yapiCartNode = yapiCartNodeData.asTreeNode() parentNode.add(yapiCartNode) val cartInfo = yapiCartNodeData.info - val apis = yapiApiHelper!!.findApis(parentNodeData.getProjectToken()!!, + val apis = yapiApiHelper.findApis(parentNodeData.getProjectToken()!!, cartInfo["_id"].toString()) if (apis.isNullOrEmpty()) return@runInSwingUI for (api in apis) { @@ -379,7 +378,7 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { private fun loadYapiApi(parentNode: DefaultMutableTreeNode, item: HashMap) { if (item.isNullOrEmpty()) return - actionContext!!.runInSwingUI { + actionContext.runInSwingUI { val parentNodeData = parentNode.userObject as YapiCartNodeData val apiTreeNode = YapiApiNodeData(parentNodeData, item).asTreeNode() apiTreeNode.allowsChildren = false @@ -390,13 +389,13 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { @Suppress("UNCHECKED_CAST") private fun importNewYapiProject() { - val projectToken = yapiApiInputHelper!!.inputToken() + val projectToken = this.yapiSettingsHelper.inputNewToken() if (projectToken.isNullOrBlank()) return - actionContext!!.runAsync { + actionContext.runAsync { - val projectId = yapiApiHelper!!.getProjectIdByToken(projectToken) + val projectId = yapiApiHelper.getProjectIdByToken(projectToken) if (projectId.isNullOrEmpty()) { return@runAsync @@ -411,7 +410,7 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { return@runAsync } - actionContext!!.runInSwingUI { + actionContext.runInSwingUI { val yapiProjectName = projectInfo["name"].toString() val moduleName = Messages.showInputDialog(this, "Input Module Name Of Project", @@ -423,10 +422,10 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { @Suppress("LABEL_NAME_CLASH") if (moduleName.isNullOrBlank()) return@runInSwingUI - actionContext!!.runAsync { + actionContext.runAsync { - yapiApiHelper.setToken(moduleName, projectToken) - actionContext!!.runInSwingUI { + yapiSettingsHelper.setToken(moduleName, projectToken) + actionContext.runInSwingUI { val projectTreeNode = YapiProjectNodeData(projectToken, projectInfo).asTreeNode() var model = yapiApiTree!!.model if (model == null) { @@ -457,14 +456,14 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { if (lastSelectedPathComponent != null) { val yapiNodeData = lastSelectedPathComponent.userObject as YapiNodeData - actionContext!!.runInSwingUI { + actionContext.runInSwingUI { val cartName = Messages.showInputDialog(this, "Input Cart Name", "Cart Name", Messages.getInformationIcon()) if (cartName.isNullOrBlank()) return@runInSwingUI - yapiApiHelper!!.addCart(yapiNodeData.getProjectToken()!!, cartName, "") + yapiApiHelper.addCart(yapiNodeData.getProjectToken()!!, cartName, "") syncYapiNode(yapiNodeData.getRootNodeData()!!) } @@ -477,7 +476,7 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { if (lastSelectedPathComponent != null) { val yapiNodeData = lastSelectedPathComponent.userObject as YapiNodeData - yapiApiHelper!!.removeToken(yapiNodeData.getProjectToken()!!) + yapiSettingsHelper.removeToken(yapiNodeData.getProjectToken()!!) val treeModel = yapiApiTree!!.model as DefaultTreeModel (treeModel.root as DefaultMutableTreeNode) @@ -499,7 +498,7 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { } private fun syncYapiNode(yapiNodeData: YapiNodeData) { - actionContext!!.runInSwingUI { + actionContext.runInSwingUI { when (yapiNodeData) { is YapiApiNodeData -> { yapiNodeData.getParentNodeData()?.let { syncYapiNode(it) } @@ -702,7 +701,7 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { logger!!.info("export [$fromProjectData] to $targetNodeData") - actionContext!!.runAsync { + actionContext.runAsync { try { logger.info("parse api...") @@ -718,10 +717,10 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { Thread.sleep(200) syncYapiNode(targetNodeData) } else { - actionContext!!.runInSwingUI { + actionContext.runInSwingUI { val yesNoCancel = Messages.showYesNoCancelDialog(project!!, "Add as new cart?", "Export", "New", "Not", "Cancel", Messages.getInformationIcon()) - actionContext!!.runAsync { + actionContext.runAsync { when (yesNoCancel) { Messages.CANCEL -> return@runAsync Messages.OK -> { @@ -801,7 +800,7 @@ class YapiDashboardDialog : AbstractApiDashboardDialog() { logger!!.error("error to cancel yapi load:" + ExceptionUtils.getStackTrace(e)) } - actionContext!!.unHold() + actionContext.unHold() dispose() } diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/rule/RuleToolUtils.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/rule/RuleToolUtils.kt index 77db2134f..88955780f 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/rule/RuleToolUtils.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/rule/RuleToolUtils.kt @@ -15,8 +15,6 @@ import org.apache.commons.lang3.StringUtils import org.apache.commons.lang3.time.DateFormatUtils import java.util.* import java.util.regex.Pattern -import kotlin.collections.ArrayList -import kotlin.collections.HashSet import kotlin.reflect.* import kotlin.reflect.full.allSuperclasses import kotlin.reflect.full.findAnnotation @@ -1019,6 +1017,9 @@ class RuleToolUtils { } companion object { + + val INSTANCE = RuleToolUtils() + private val excludedMethods = Arrays.asList("hashCode", "toString", "equals", "getClass", "clone", "notify", "notifyAll", "wait", "finalize") private val TO_LINE_PATTERN = Pattern.compile("[A-Z]+") diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/rule/StandardJdkRuleParser.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/rule/StandardJdkRuleParser.kt index 9e1a4c756..3afd0cfa4 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/rule/StandardJdkRuleParser.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/rule/StandardJdkRuleParser.kt @@ -220,8 +220,8 @@ abstract class StandardJdkRuleParser : ScriptRuleParser() { init { val bindings: Bindings = SimpleBindings() - bindings["tool"] = RuleToolUtils() - bindings["regex"] = RegexUtils() + bindings["tool"] = RuleToolUtils.INSTANCE + bindings["regex"] = RegexUtils.INSTANCE toolBindings = bindings } } diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/SettingBinder.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/SettingBinder.kt index 96e574af4..9e6301e1e 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/SettingBinder.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/SettingBinder.kt @@ -6,6 +6,10 @@ import com.itangcent.intellij.file.CachedBeanBinder interface SettingBinder : BeanBinder { } +fun SettingBinder.update(updater: (Settings) -> Unit) { + this.read().also(updater).let { this.save(it) } +} + fun SettingBinder.lazy(): SettingBinder { return CachedSettingBinder(this) } diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/Settings.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/Settings.kt index 69371e454..d7ef5d6e4 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/Settings.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/Settings.kt @@ -1,17 +1,16 @@ package com.itangcent.idea.plugin.settings -import com.itangcent.idea.plugin.config.RecommendConfigLoader +import com.itangcent.idea.plugin.settings.helper.RecommendConfigLoader import com.itangcent.idea.utils.Charsets -import com.itangcent.idea.utils.ConfigurableLogger class Settings { - var pullNewestDataBefore: Boolean = false - var methodDocEnable: Boolean = false //postman + var pullNewestDataBefore: Boolean = false + var postmanToken: String? = null var wrapCollection: Boolean = false @@ -20,7 +19,7 @@ class Settings { var postmanJson5FormatType: String = PostmanJson5FormatType.EXAMPLE_ONLY.name - //intelligent + //region intelligent var formExpanded: Boolean = true @@ -32,6 +31,8 @@ class Settings { var inferMaxDeep: Int = DEFAULT_INFER_MAX_DEEP + //endregion + //yapi var yapiServer: String? = null @@ -48,15 +49,21 @@ class Settings { var yapiResBodyJson5: Boolean = false + //region http-------------------------- + //unit:s var httpTimeOut: Int = 5 + var trustHosts: Array = DEFAULT_TRUST_HOSTS + + //endregion + //enable to use recommend config var useRecommendConfig: Boolean = true var recommendConfigs: String = RecommendConfigLoader.defaultCodes() - var logLevel: Int = ConfigurableLogger.CoarseLogLevel.LOW.getLevel() + var logLevel: Int = 50 // markdown @@ -68,6 +75,7 @@ class Settings { var builtInConfig: String? = null + fun copy(): Settings { val newSetting = Settings() newSetting.postmanToken = this.postmanToken @@ -96,6 +104,7 @@ class Settings { newSetting.outputCharset = this.outputCharset newSetting.markdownFormatType = this.markdownFormatType newSetting.builtInConfig = this.builtInConfig + newSetting.trustHosts = this.trustHosts return newSetting } @@ -131,6 +140,7 @@ class Settings { if (outputCharset != other.outputCharset) return false if (markdownFormatType != other.markdownFormatType) return false if (builtInConfig != other.builtInConfig) return false + if (!trustHosts.contentEquals(other.trustHosts)) return false return true } @@ -162,11 +172,15 @@ class Settings { result = 31 * result + outputCharset.hashCode() result = 31 * result + markdownFormatType.hashCode() result = 31 * result + builtInConfig.hashCode() + result = 31 * result + trustHosts.hashCode() return result } - companion object { const val DEFAULT_INFER_MAX_DEEP = 4 + + val DEFAULT_TRUST_HOSTS: Array = + arrayOf("https://raw.githubusercontent.com/tangcent", + "https://api.getpostman.com") } } \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/group/JsonSetting.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/group/JsonSetting.kt deleted file mode 100644 index 5ddd1bb63..000000000 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/group/JsonSetting.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.itangcent.idea.plugin.settings.group - -import com.google.inject.Inject -import com.google.inject.Singleton -import com.itangcent.idea.plugin.settings.SettingBinder -import com.itangcent.intellij.psi.JsonOption - -@Singleton -class JsonSetting { - - @Inject - private val settingBinder: SettingBinder? = null - - fun defaultJsonOption(): Int { - return jsonOptionForInput(0) - } - - fun jsonOptionForInput(jsonOption: Int): Int { - return if (settingBinder!!.read().readSetter) { - jsonOption.or(JsonOption.READ_SETTER) - } else { - jsonOption - } - } - - fun jsonOptionForOutput(jsonOption: Int): Int { - return if (settingBinder!!.read().readGetter) { - jsonOption.or(JsonOption.READ_GETTER) - } else { - jsonOption - } - } -} \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/BuiltInConfigSettingsHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/BuiltInConfigSettingsHelper.kt new file mode 100644 index 000000000..185ca58dc --- /dev/null +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/BuiltInConfigSettingsHelper.kt @@ -0,0 +1,16 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.google.inject.Inject +import com.google.inject.Singleton +import com.itangcent.idea.plugin.settings.SettingBinder + +@Singleton +class BuiltInConfigSettingsHelper { + + @Inject + private lateinit var settingBinder: SettingBinder + + fun builtInConfig(): String? { + return settingBinder.read().builtInConfig + } +} \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/CommonSettingsHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/CommonSettingsHelper.kt new file mode 100644 index 000000000..b4867f0d1 --- /dev/null +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/CommonSettingsHelper.kt @@ -0,0 +1,82 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.google.inject.Inject +import com.google.inject.Singleton +import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.utils.Charsets +import com.itangcent.intellij.logger.Logger +import java.nio.charset.Charset + +@Singleton +class CommonSettingsHelper { + + @Inject + private lateinit var settingBinder: SettingBinder + + fun outputCharset(): Charset { + return Charsets.forName(settingBinder.read().outputCharset)?.charset() ?: kotlin.text.Charsets.UTF_8 + } + + fun logLevel(): Int { + return settingBinder.read().logLevel + } + + fun currentLogLevel(): Logger.Level { + val logLevel: Int = logLevel() + return logLevel.let { CoarseLogLevel.toLevel(it, CoarseLogLevel.LOW) } + } + + enum class CoarseLogLevel : Logger.Level { + EMPTY(1000) { + override fun getLevelStr(): String { + return "" + } + }, + LOW(50), + MEDIUM(250), + HIGH(450) + ; + + private val level: Int + + constructor(level: Int) { + this.level = level + } + + override fun getLevelStr(): String { + throw UnsupportedOperationException("CoarseLogLevel only be used as level") + } + + override fun getLevel(): Int { + return level + } + + override fun toString(): String { + return name + } + + companion object { + + fun toLevel(level: Int): Logger.Level { + return toLevel(level, LOW) + } + + fun toLevel(level: Int, defaultLevel: Logger.Level): Logger.Level { + return when (level) { + LOW.level -> LOW + MEDIUM.level -> MEDIUM + HIGH.level -> HIGH + else -> Logger.BasicLevel.toLevel(level, defaultLevel) + } + } + + fun editableValues(): Array { + return values().filter { it != EMPTY }.toTypedArray() + } + } + } +} + +fun CommonSettingsHelper?.currentLogLevel(): Logger.Level { + return this?.currentLogLevel() ?: CommonSettingsHelper.CoarseLogLevel.LOW +} diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/HttpSettingsHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/HttpSettingsHelper.kt new file mode 100644 index 000000000..2d597225b --- /dev/null +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/HttpSettingsHelper.kt @@ -0,0 +1,117 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.google.inject.Inject +import com.google.inject.Singleton +import com.intellij.openapi.ui.Messages +import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.update +import com.itangcent.idea.plugin.utils.RegexUtils +import com.itangcent.idea.swing.MessagesHelper +import java.net.URL +import java.util.concurrent.TimeUnit + +@Singleton +class HttpSettingsHelper { + + @Inject + private lateinit var settingBinder: SettingBinder + + @Inject + private lateinit var messagesHelper: MessagesHelper + + //region trustHosts---------------------------------------------------- + + fun checkTrustUrl(url: String, dumb: Boolean = true): Boolean { + val trustHosts = settingBinder.read().trustHosts + var ret: Boolean? = null + for (trustHost in trustHosts) { + if (trustHost.startsWith("!")) { + if (url.startsWith(trustHost.removePrefix("!"))) { + return false + } + } else if (url.startsWith(trustHost)) { + ret = true + } + } + if (ret == true) { + return true + } + return checkTrustHost(resolveHost(url), dumb) + } + + fun checkTrustHost(host: String, dumb: Boolean = true): Boolean { + val settings = settingBinder.read() + val trustHosts = settings.trustHosts + + //check forbidden first + if (trustHosts.contains("!$host")) { + return false + } + if (settings.yapiServer == host + || trustHosts.contains(host)) { + return true + } + if (!dumb) { + val trustRet = messagesHelper.showYesNoDialog("Do you trust [$host]?", + "Trust Host", Messages.getQuestionIcon()) + + return if (trustRet == Messages.YES) { + addTrustHost(host) + true + } else { + addTrustHost("!$host") + false + } + } + return false + } + + fun addTrustHost(host: String) { + settingBinder.update { settings -> + if (!settings.trustHosts.contains(host)) { + settings.trustHosts = settings.trustHosts + host + } + } + } + + fun resolveHost(url: String): String { + try { + val settings = settingBinder.read() + + //check if it belongs yapiServer + settings.yapiServer?.let { yapiServer -> + if (url.startsWith(yapiServer)) { + return yapiServer + } + } + + HOST_RESOLVERS.forEach { resolver -> + resolver(url)?.let { return it.removeSuffix("/") } + } + return URL(url).let { "${it.protocol}://${it.host}" }.removeSuffix("/") + } catch (e: Exception) { + return url + } + } + + //endregion trustHosts---------------------------------------------------- + + fun httpTimeOut(timeUnit: TimeUnit): Int { + //unit of httpTimeOut is second + if (timeUnit == TimeUnit.SECONDS) { + return settingBinder.read().httpTimeOut + } + return timeUnit.convert(settingBinder.read().httpTimeOut.toLong(), TimeUnit.SECONDS).toInt() + } + + companion object { + val HOST_RESOLVERS: Array<(String) -> String?> = arrayOf({ + if (it.startsWith("https://raw.githubusercontent.com")) { + val url = if (it.endsWith("/")) it else "$it/" + return@arrayOf RegexUtils.INSTANCE.extract("https://raw.githubusercontent.com/(.*?)/.*", + url, "https://raw.githubusercontent.com/$1") + } + return@arrayOf null + }) + } +} \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/IntelligentSettingsHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/IntelligentSettingsHelper.kt new file mode 100644 index 000000000..dc875da58 --- /dev/null +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/IntelligentSettingsHelper.kt @@ -0,0 +1,49 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.google.inject.Inject +import com.google.inject.Singleton +import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.intellij.psi.JsonOption + +@Singleton +class IntelligentSettingsHelper { + + @Inject + private lateinit var settingBinder: SettingBinder + + fun formExpanded(): Boolean { + return settingBinder.read().formExpanded + } + + fun readGetter(): Boolean { + return settingBinder.read().readGetter + } + + fun readSetter(): Boolean { + return settingBinder.read().readSetter + } + + fun inferEnable(): Boolean { + return settingBinder.read().inferEnable + } + + fun inferMaxDeep(): Int { + return settingBinder.read().inferMaxDeep + } + + fun jsonOptionForInput(jsonOption: Int): Int { + return if (readSetter()) { + jsonOption.or(JsonOption.READ_SETTER) + } else { + jsonOption + } + } + + fun jsonOptionForOutput(jsonOption: Int): Int { + return if (readGetter()) { + jsonOption.or(JsonOption.READ_GETTER) + } else { + jsonOption + } + } +} \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/MarkdownSettingsHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/MarkdownSettingsHelper.kt new file mode 100644 index 000000000..9ca73fae0 --- /dev/null +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/MarkdownSettingsHelper.kt @@ -0,0 +1,27 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.google.inject.Inject +import com.google.inject.Singleton +import com.itangcent.idea.plugin.settings.MarkdownFormatType +import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.utils.Charsets +import java.nio.charset.Charset + +@Singleton +class MarkdownSettingsHelper { + + @Inject + private lateinit var settingBinder: SettingBinder + + fun outputCharset(): Charset { + return Charsets.forName(settingBinder.read().outputCharset)?.charset() ?: kotlin.text.Charsets.UTF_8 + } + + fun outputDemo(): Boolean { + return settingBinder.read().outputDemo + } + + fun markdownFormatType(): MarkdownFormatType { + return MarkdownFormatType.valueOf(settingBinder.read().markdownFormatType) + } +} \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/PostmanSettingsHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/PostmanSettingsHelper.kt new file mode 100644 index 000000000..454c88c3f --- /dev/null +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/PostmanSettingsHelper.kt @@ -0,0 +1,55 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.google.inject.Inject +import com.google.inject.Singleton +import com.intellij.openapi.ui.Messages +import com.itangcent.common.utils.notNullOrEmpty +import com.itangcent.idea.plugin.settings.PostmanJson5FormatType +import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.update +import com.itangcent.idea.swing.MessagesHelper + +@Singleton +class PostmanSettingsHelper { + + @Inject + private lateinit var settingBinder: SettingBinder + + @Inject + private lateinit var messagesHelper: MessagesHelper + + //region privateToken---------------------------------------------------- + + fun hasPrivateToken(): Boolean { + return getPrivateToken().notNullOrEmpty() + } + + fun getPrivateToken(dumb: Boolean = true): String? { + settingBinder.read().postmanToken?.let { return it.trim() } + if (!dumb) { + val postmanPrivateToken = messagesHelper.showInputDialog( + "Input Postman Private Token", + "Postman Private Token", Messages.getInformationIcon()) + if (postmanPrivateToken.isNullOrBlank()) return null + settingBinder.update { + it.postmanToken = postmanPrivateToken + } + return postmanPrivateToken + } + return null + } + + //endregion privateToken---------------------------------------------------- + + fun wrapCollection(): Boolean { + return settingBinder.read().wrapCollection + } + + fun autoMergeScript(): Boolean { + return settingBinder.read().autoMergeScript + } + + fun postmanJson5FormatType(): PostmanJson5FormatType { + return PostmanJson5FormatType.valueOf(settingBinder.read().postmanJson5FormatType) + } +} \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/config/RecommendConfigLoader.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/RecommendConfigSettingsHelper.kt similarity index 80% rename from idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/config/RecommendConfigLoader.kt rename to idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/RecommendConfigSettingsHelper.kt index 6542fff29..960e402a9 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/config/RecommendConfigLoader.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/RecommendConfigSettingsHelper.kt @@ -1,19 +1,30 @@ -package com.itangcent.idea.plugin.config +package com.itangcent.idea.plugin.settings.helper import com.google.inject.Inject import com.google.inject.Singleton import com.itangcent.common.utils.appendln import com.itangcent.common.utils.mapToTypedArray -import com.itangcent.intellij.logger.Logger +import com.itangcent.idea.plugin.settings.SettingBinder import com.itangcent.utils.ResourceUtils import java.util.* - @Singleton -object RecommendConfigLoader { +class RecommendConfigSettingsHelper { @Inject - val logger: Logger? = null + private lateinit var settingBinder: SettingBinder + + fun useRecommendConfig(): Boolean { + return settingBinder.read().useRecommendConfig + } + + fun loadRecommendConfig(): String { + return RecommendConfigLoader.buildRecommendConfig(settingBinder.read().recommendConfigs) + } +} + +@Singleton +object RecommendConfigLoader { fun plaint(): String { return RECOMMEND_CONFIG_PLAINT @@ -101,11 +112,22 @@ object RecommendConfigLoader { RECOMMEND_CONFIGS = recommendConfigCodes.toTypedArray() } + /** + * Get the content of the specified code + * + * @param key the specified code + * @return the content of the specified code + */ operator fun get(key: String?): String? { - return RECOMMEND_CONFIGS.first { it.code == key }.content + return RECOMMEND_CONFIGS.firstOrNull { it.code == key }?.content } - operator fun get(index: Int): String? { + /** + * Returns the code at the specified index + * + * @return the code at the specified index + */ + operator fun get(index: Int): String { return RECOMMEND_CONFIGS[index].code } diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/SupportSettingsHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/SupportSettingsHelper.kt new file mode 100644 index 000000000..b6362478a --- /dev/null +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/SupportSettingsHelper.kt @@ -0,0 +1,16 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.google.inject.Inject +import com.google.inject.Singleton +import com.itangcent.idea.plugin.settings.SettingBinder + +@Singleton +class SupportSettingsHelper { + + @Inject + private lateinit var settingBinder: SettingBinder + + fun methodDocEnable(): Boolean { + return settingBinder.read().methodDocEnable + } +} \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/YapiSettingsHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/YapiSettingsHelper.kt new file mode 100644 index 000000000..47fcba7a4 --- /dev/null +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/settings/helper/YapiSettingsHelper.kt @@ -0,0 +1,256 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.google.inject.Inject +import com.google.inject.Singleton +import com.intellij.openapi.ui.Messages +import com.itangcent.common.utils.notNullOrBlank +import com.itangcent.common.utils.notNullOrEmpty +import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.update +import com.itangcent.idea.swing.MessagesHelper +import com.itangcent.intellij.config.ConfigReader +import com.itangcent.intellij.logger.Logger +import java.io.ByteArrayOutputStream +import java.util.* +import java.util.concurrent.locks.ReadWriteLock +import java.util.concurrent.locks.ReentrantReadWriteLock +import kotlin.concurrent.withLock + +@Singleton +class YapiSettingsHelper { + + @Inject + private lateinit var logger: Logger + + @Inject + private lateinit var settingBinder: SettingBinder + + @Inject + private val configReader: ConfigReader? = null + + @Inject(optional = true) + private val yapiTokenChecker: YapiTokenChecker? = null + + @Inject + private lateinit var messagesHelper: MessagesHelper + + @Volatile + private var server: String? = null + + protected var cacheLock: ReadWriteLock = ReentrantReadWriteLock() + + //region server---------------------------------------------------- + + fun hasServer(): Boolean { + return getServer().notNullOrEmpty() + } + + fun getServer(dumb: Boolean = true): String? { + if (server.notNullOrBlank()) return server + server = configReader!!.first("yapi.server")?.trim()?.removeSuffix("/") + if (server.notNullOrBlank()) return server + server = settingBinder.read().yapiServer?.trim()?.removeSuffix("/") + if (server.notNullOrBlank()) return server + if (!dumb) { + val yapiServer = + messagesHelper.showInputDialog("Input server of yapi", + "Server Of Yapi", Messages.getInformationIcon()) + ?.removeSuffix("/") + if (yapiServer.isNullOrBlank()) return null + server = yapiServer + settingBinder.update { + it.yapiServer = yapiServer + } + return yapiServer + } + return null + } + + //endregion server---------------------------------------------------- + + //region tokens---------------------------------------------- + + /** + * Tokens in setting. + * Map> + * state: null->unchecked,true->valid, false->invalid + */ + private var tokenMap: HashMap>? = null + + private var tryInputTokenOfModule: HashSet = HashSet() + + fun getPrivateToken(module: String, dumb: Boolean = true): String? { + cacheLock.readLock().withLock { + if (tokenMap != null) { + tokenMap!![module]?.checked()?.let { return it } + } + } + + cacheLock.writeLock().withLock { + if (tokenMap == null) { + initToken() + } + tokenMap!![module]?.checked()?.let { return it } + if (!dumb && tryInputTokenOfModule.add(module)) { + val modulePrivateToken = inputNewToken(module) + if (modulePrivateToken.notNullOrBlank() + && yapiTokenChecker?.checkToken(modulePrivateToken!!) != false) { + setToken(module, modulePrivateToken!!) + return modulePrivateToken + } + } + } + return null + } + + private fun inputNewToken(module: String): String? { + val inputTitle = if (loginMode()) "ProjectId" else "Private Token" + return messagesHelper.showInputDialog("Input $inputTitle Of Module:$module", + "Yapi $inputTitle", Messages.getInformationIcon()) + } + + fun inputNewToken(): String? { + val inputTitle = if (loginMode()) "ProjectId" else "Private Token" + return messagesHelper.showInputDialog("Input $inputTitle", + "Yapi $inputTitle", Messages.getInformationIcon()) + } + + private fun Pair.checked(): String? { + return when (this.second) { + null -> { + val status = yapiTokenChecker?.checkToken(this.first) ?: true + updateTokenStatus(this.first, status) + if (!status) { + logger.warn("token:${this.first} may be invalid.") + } + return if (status) this.first else null + } + true -> { + this.first + } + false -> { + null + } + } + } + + /** + * disable this token temporarily + */ + fun disableTemp(token: String) { + + cacheLock.writeLock().withLock { + if (tokenMap == null) { + initToken() + } + updateTokenStatus(token, false) + } + } + + private fun updateTokenStatus(token: String, status: Boolean) { + tokenMap!!.entries.forEach { + if (it.value.first == token) { + it.setValue(it.value.first to status) + } + } + } + + private fun initToken() { + tokenMap = HashMap() + val settings = settingBinder.read() + if (settings.yapiTokens != null) { + val properties = Properties() + properties.load(settings.yapiTokens!!.byteInputStream()) + properties.forEach { t, u -> tokenMap!![t.toString()] = u.toString() to null } + } + } + + private fun updateTokens(handle: (Properties) -> Unit) { + cacheLock.writeLock().withLock { + val settings = settingBinder.read() + val properties = Properties() + if (settings.yapiTokens != null) { + properties.load(settings.yapiTokens!!.byteInputStream()) + } + handle(properties) + + val byteOutputStream = ByteArrayOutputStream() + properties.store(byteOutputStream, "") + settings.yapiTokens = byteOutputStream.toString() + settingBinder.save(settings) + if (tokenMap == null) { + tokenMap = HashMap() + } else { + tokenMap!!.clear() + } + properties.forEach { t, u -> tokenMap!![t.toString()] = u.toString() to null } + } + } + + fun setToken(module: String, token: String) { + updateTokens { properties -> + properties[module] = token + } + tokenMap?.put(module,token to null) + } + + fun removeTokenByModule(module: String) { + updateTokens { properties -> + properties.remove(module) + } + tokenMap?.remove(module) + } + + fun removeToken(token: String) { + updateTokens { properties -> + val removedKeys = properties.entries + .filter { it.value == token } + .map { it.key } + .toList() + removedKeys.forEach { + properties.remove(it) + tokenMap?.remove(it) + } + } + } + + fun readTokens(): HashMap { + if (tokenMap == null) { + initToken() + } + return HashMap(tokenMap!!.mapValues { it.value.first }) + } + + fun rawToken(token: String): String { + if (loginMode()) { + return "" + } + return token + } + + //endregion tokens---------------------------------------------- + + fun enableUrlTemplating(): Boolean { + return settingBinder.read().enableUrlTemplating + } + + fun loginMode(): Boolean { + return settingBinder.read().loginMode + } + + fun switchNotice(): Boolean { + return settingBinder.read().switchNotice + } + + fun yapiReqBodyJson5(): Boolean { + return settingBinder.read().yapiReqBodyJson5 + } + + fun yapiResBodyJson5(): Boolean { + return settingBinder.read().yapiResBodyJson5 + } +} + +interface YapiTokenChecker { + fun checkToken(token: String): Boolean +} \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/utils/RegexUtils.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/utils/RegexUtils.kt index ca3a4b31a..0dba76e37 100755 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/utils/RegexUtils.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/plugin/utils/RegexUtils.kt @@ -301,6 +301,7 @@ class RegexUtils { val REGEX_KEYWORD = setOf('$', '(', ')', '*', '+', '.', '[', ']', '?', '\\', '^', '{', '}', '|') + val INSTANCE = RegexUtils() } private class RegexWithFlag(private val regex: String?, private val flag: Int) { diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/swing/ActiveWindowProvider.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/swing/ActiveWindowProvider.kt new file mode 100644 index 000000000..b6191ec5e --- /dev/null +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/swing/ActiveWindowProvider.kt @@ -0,0 +1,11 @@ +package com.itangcent.idea.swing + +import java.awt.Component + +interface ActiveWindowProvider { + fun activeWindow(): Component? +} + +interface MutableActiveWindowProvider : ActiveWindowProvider { + fun setActiveWindow(activeWindow: Component?) +} diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/swing/DefaultMessagesHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/swing/DefaultMessagesHelper.kt new file mode 100644 index 000000000..329abfc0d --- /dev/null +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/swing/DefaultMessagesHelper.kt @@ -0,0 +1,53 @@ +package com.itangcent.idea.swing + +import com.google.inject.Inject +import com.google.inject.Singleton +import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.Messages +import com.intellij.openapi.ui.Messages.YesNoResult +import com.itangcent.intellij.context.ActionContext +import org.jetbrains.annotations.Nls +import javax.swing.Icon + +@Singleton +class DefaultMessagesHelper : MessagesHelper { + + @Inject + private lateinit var project: Project + + @Inject + private lateinit var actionContext: ActionContext + + @Inject(optional = true) + private var activeWindowProvider: ActiveWindowProvider? = null + + /** + * @return [.YES] if user pressed "Yes" or [.NO] if user pressed "No" button. + */ + @YesNoResult + override fun showYesNoDialog(message: String?, @Nls(capitalization = Nls.Capitalization.Title) title: String, icon: Icon?): Int { + val activeWindow = activeWindowProvider?.activeWindow() + return actionContext.callInSwingUI { + if (activeWindow == null) { + Messages.showYesNoDialog(project, message, title, icon) + } else { + Messages.showYesNoDialog(activeWindow, message, title, icon) + } + }!! + } + + + /** + * @return trimmed input string or `null` if user cancelled dialog. + */ + override fun showInputDialog(message: String?, @Nls(capitalization = Nls.Capitalization.Title) title: String?, icon: Icon?): String? { + val activeWindow = activeWindowProvider?.activeWindow() + return actionContext.callInSwingUI { + if (activeWindow == null) { + Messages.showInputDialog(project, message, title, icon) + } else { + Messages.showInputDialog(activeWindow, message, title, icon) + } + } + } +} \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/swing/MessagesHelper.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/swing/MessagesHelper.kt new file mode 100644 index 000000000..c75a4b59a --- /dev/null +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/swing/MessagesHelper.kt @@ -0,0 +1,21 @@ +package com.itangcent.idea.swing + +import com.google.inject.ImplementedBy +import com.intellij.openapi.ui.Messages +import org.jetbrains.annotations.Nls +import javax.swing.Icon + +@ImplementedBy(DefaultMessagesHelper::class) +interface MessagesHelper { + + /** + * @return [.YES] if user pressed "Yes" or [.NO] if user pressed "No" button. + */ + @Messages.YesNoResult + fun showYesNoDialog(message: String?, @Nls(capitalization = Nls.Capitalization.Title) title: String, icon: Icon?): Int + + /** + * @return trimmed input string or `null` if user cancelled dialog. + */ + fun showInputDialog(message: String?, @Nls(capitalization = Nls.Capitalization.Title) title: String?, icon: Icon?): String? +} \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/swing/SimpleActiveWindowProvider.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/swing/SimpleActiveWindowProvider.kt new file mode 100644 index 000000000..ba3685267 --- /dev/null +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/swing/SimpleActiveWindowProvider.kt @@ -0,0 +1,18 @@ +package com.itangcent.idea.swing + +import com.google.inject.Singleton +import java.awt.Component + +@Singleton +class SimpleActiveWindowProvider : MutableActiveWindowProvider { + + private var activeWindow: Component? = null + + override fun setActiveWindow(activeWindow: Component?) { + this.activeWindow = activeWindow + } + + override fun activeWindow(): Component? { + return this.activeWindow + } +} \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/idea/utils/ConfigurableLogger.kt b/idea-plugin/src/main/kotlin/com/itangcent/idea/utils/ConfigurableLogger.kt index 94441da73..af5e779b0 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/idea/utils/ConfigurableLogger.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/idea/utils/ConfigurableLogger.kt @@ -5,7 +5,8 @@ import com.google.inject.name.Named import com.itangcent.annotation.script.ScriptIgnore import com.itangcent.annotation.script.ScriptTypeName import com.itangcent.annotation.script.ScriptUnIgnore -import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.helper.CommonSettingsHelper +import com.itangcent.idea.plugin.settings.helper.currentLogLevel import com.itangcent.intellij.extend.guice.PostConstruct import com.itangcent.intellij.logger.AbstractLogger import com.itangcent.intellij.logger.Logger @@ -20,25 +21,24 @@ class ConfigurableLogger : AbstractLogger() { private var delegateLogger: Logger? = null @Inject(optional = true) - private val settingBinder: SettingBinder? = null + private val commonSettingsHelper: CommonSettingsHelper? = null - private var currentLogLevel: Level? = null + private lateinit var currentLogLevel: Level @PostConstruct @ScriptIgnore fun init() { - val logLevel: Int? = settingBinder?.read()?.logLevel - currentLogLevel = logLevel?.let { CoarseLogLevel.toLevel(it, CoarseLogLevel.LOW) } ?: CoarseLogLevel.LOW + currentLogLevel = commonSettingsHelper.currentLogLevel() } @ScriptUnIgnore override fun log(msg: String) { - super.log(CoarseLogLevel.EMPTY, msg) + super.log(CommonSettingsHelper.CoarseLogLevel.EMPTY, msg) } @ScriptIgnore override fun currentLogLevel(): Level { - return currentLogLevel ?: CoarseLogLevel.LOW + return currentLogLevel } @ScriptIgnore @@ -52,53 +52,4 @@ class ConfigurableLogger : AbstractLogger() { throw IllegalArgumentException("ConfigurableLogger#processLog not be implemented") } - enum class CoarseLogLevel : Level { - EMPTY(1000) { - override fun getLevelStr(): String { - return "" - } - }, - LOW(50), - MEDIUM(250), - HIGH(450) - ; - - private val level: Int - - constructor(level: Int) { - this.level = level - } - - override fun getLevelStr(): String { - throw UnsupportedOperationException("CoarseLogLevel only be used as level") - } - - override fun getLevel(): Int { - return level - } - - override fun toString(): String { - return name - } - - companion object { - - fun toLevel(level: Int): Level { - return toLevel(level, LOW) - } - - fun toLevel(level: Int, defaultLevel: Level): Level { - return when (level) { - LOW.level -> LOW - MEDIUM.level -> MEDIUM - HIGH.level -> HIGH - else -> Logger.BasicLevel.toLevel(level, defaultLevel) - } - } - - fun editableValues(): Array { - return values().filter { it != EMPTY }.toTypedArray() - } - } - } } \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/com/itangcent/suv/http/ConfigurableHttpClientProvider.kt b/idea-plugin/src/main/kotlin/com/itangcent/suv/http/ConfigurableHttpClientProvider.kt index ac540a48a..c74eed854 100644 --- a/idea-plugin/src/main/kotlin/com/itangcent/suv/http/ConfigurableHttpClientProvider.kt +++ b/idea-plugin/src/main/kotlin/com/itangcent/suv/http/ConfigurableHttpClientProvider.kt @@ -7,20 +7,25 @@ import com.itangcent.annotation.script.ScriptTypeName import com.itangcent.http.* import com.itangcent.idea.plugin.api.export.core.ClassExportRuleKeys import com.itangcent.idea.plugin.rule.SuvRuleContext -import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.helper.HttpSettingsHelper import com.itangcent.intellij.config.ConfigReader import com.itangcent.intellij.config.rule.RuleComputer +import com.itangcent.intellij.logger.Logger import org.apache.http.client.config.CookieSpecs import org.apache.http.client.config.RequestConfig import org.apache.http.config.SocketConfig import org.apache.http.impl.client.HttpClients import org.apache.http.impl.conn.PoolingHttpClientConnectionManager +import java.io.ByteArrayInputStream +import java.io.InputStream +import java.nio.charset.Charset +import java.util.concurrent.TimeUnit @Singleton class ConfigurableHttpClientProvider : AbstractHttpClientProvider() { @Inject(optional = true) - protected val settingBinder: SettingBinder? = null + protected val httpSettingsHelper: HttpSettingsHelper? = null @Inject(optional = true) protected val configReader: ConfigReader? = null @@ -28,6 +33,9 @@ class ConfigurableHttpClientProvider : AbstractHttpClientProvider() { @Inject(optional = true) protected val ruleComputer: RuleComputer? = null + @Inject + protected val logger: Logger? = null + override fun buildHttpClient(): HttpClient { val httpClientBuilder = HttpClients.custom() @@ -39,33 +47,28 @@ class ConfigurableHttpClientProvider : AbstractHttpClientProvider() { it.defaultMaxPerRoute = 20 }) .setDefaultSocketConfig(SocketConfig.custom() - .setSoTimeout(config.timeOut.toMill()) + .setSoTimeout(config.timeOut) .build()) .setDefaultRequestConfig(RequestConfig.custom() - .setConnectTimeout(config.timeOut.toMill()) - .setConnectionRequestTimeout(config.timeOut.toMill()) - .setSocketTimeout(config.timeOut.toMill()) + .setConnectTimeout(config.timeOut) + .setConnectionRequestTimeout(config.timeOut) + .setSocketTimeout(config.timeOut) .setCookieSpec(CookieSpecs.STANDARD).build()) return HttpClientWrapper(ApacheHttpClient(httpClientBuilder.build())) } - private fun Int.toMill(): Int { - return this * 1000 - } - private fun readHttpConfig(): HttpConfig { val httpConfig = HttpConfig() - settingBinder?.read()?.let { setting -> - httpConfig.timeOut = setting.httpTimeOut + httpSettingsHelper?.let { + httpConfig.timeOut = it.httpTimeOut(TimeUnit.MILLISECONDS) } - if (configReader != null) { try { - configReader.first("http.timeOut")?.toInt() - ?.let { httpConfig.timeOut = it } + configReader.first("http.timeOut")?.toLong() + ?.let { httpConfig.timeOut = TimeUnit.SECONDS.toMillis(it).toInt() } } catch (e: NumberFormatException) { } } @@ -206,6 +209,12 @@ class ConfigurableHttpClientProvider : AbstractHttpClientProvider() { * @return the response to the request */ override fun call(): HttpResponse { + val url = url() ?: throw IllegalArgumentException("url not be set") + if (httpSettingsHelper != null + && !httpSettingsHelper.checkTrustUrl(url, false)) { + logger?.warn("[access forbidden] call:$url") + return EmptyHttpResponse(this) + } var i = 0 while (true) { val suvRuleContext = SuvRuleContext() @@ -223,6 +232,57 @@ class ConfigurableHttpClientProvider : AbstractHttpClientProvider() { } } + class EmptyHttpResponse(private val request: HttpRequest) : HttpResponse { + override fun code(): Int { + return 404 + } + + override fun headers(): List? { + return null + } + + override fun headers(headerName: String): Array? { + return null + } + + override fun string(): String? { + return null + } + + override fun string(charset: Charset): String? { + return null + } + + override fun stream(): InputStream { + return ByteArrayInputStream(byteArrayOf()) + } + + override fun contentType(): String? { + return null + } + + override fun bytes(): ByteArray? { + return null + } + + override fun containsHeader(headerName: String): Boolean? { + return false + } + + override fun firstHeader(headerName: String): String? { + return null + } + + override fun lastHeader(headerName: String): String? { + return null + } + + override fun request(): HttpRequest { + return this.request + } + + } + @ScriptTypeName("response") class DiscardAbleHttpResponse(httpResponse: HttpResponse) : HttpResponse by httpResponse { @@ -249,8 +309,6 @@ class ConfigurableHttpClientProvider : AbstractHttpClientProvider() { } companion object { - const val defaultHttpTimeOut: Int = 10 + val defaultHttpTimeOut: Int = TimeUnit.SECONDS.toMillis(10).toInt() } - - } \ No newline at end of file diff --git a/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/group/JsonSettingTest.kt b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/group/JsonSettingTest.kt deleted file mode 100644 index 0afa6c2c3..000000000 --- a/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/group/JsonSettingTest.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.itangcent.idea.plugin.settings.group - -import com.google.inject.Inject -import com.itangcent.idea.plugin.settings.SettingBinder -import com.itangcent.idea.plugin.settings.Settings -import com.itangcent.intellij.context.ActionContext -import com.itangcent.intellij.psi.JsonOption -import com.itangcent.mock.BaseContextTest -import com.itangcent.mock.SettingBinderAdaptor -import org.junit.jupiter.api.Test -import kotlin.test.assertEquals - -/** - * Test case of [JsonSetting] - */ -internal class JsonSettingTest : BaseContextTest() { - - private val settings = Settings() - - override fun bind(builder: ActionContext.ActionContextBuilder) { - super.bind(builder) - builder.bind(SettingBinder::class) { it.toInstance(SettingBinderAdaptor(settings)) } - } - - @Inject - private lateinit var jsonSetting: JsonSetting - - @Test - fun testDefaultJsonOption() { - assertEquals(0, jsonSetting.defaultJsonOption()) - } - - @Test - fun testJsonOptionForInput() { - settings.readSetter = false - assertEquals(JsonOption.NONE, jsonSetting.jsonOptionForInput(JsonOption.NONE)) - settings.readSetter = true - assertEquals(JsonOption.READ_SETTER, jsonSetting.jsonOptionForInput(JsonOption.NONE)) - } - - @Test - fun testJsonOptionForOutput() { - settings.readGetter = false - assertEquals(JsonOption.NONE, jsonSetting.jsonOptionForOutput(JsonOption.NONE)) - settings.readGetter = true - assertEquals(JsonOption.READ_GETTER, jsonSetting.jsonOptionForOutput(JsonOption.NONE)) - - } -} \ No newline at end of file diff --git a/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/BuiltInConfigSettingsHelperTest.kt b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/BuiltInConfigSettingsHelperTest.kt new file mode 100644 index 000000000..ccedefc41 --- /dev/null +++ b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/BuiltInConfigSettingsHelperTest.kt @@ -0,0 +1,22 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.google.inject.Inject +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +/** + * Test case of [BuiltInConfigSettingsHelper] + */ +internal class BuiltInConfigSettingsHelperTest : SettingsHelperTest() { + + @Inject + private lateinit var builtInConfigSettingsHelper: BuiltInConfigSettingsHelper + + @Test + fun testBuiltInConfig() { + settings.builtInConfig = "hello world" + assertEquals("hello world", builtInConfigSettingsHelper.builtInConfig()) + settings.builtInConfig = "test-demo" + assertEquals("test-demo", builtInConfigSettingsHelper.builtInConfig()) + } +} \ No newline at end of file diff --git a/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/CommonSettingsHelperTest.kt b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/CommonSettingsHelperTest.kt new file mode 100644 index 000000000..54b5c3be2 --- /dev/null +++ b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/CommonSettingsHelperTest.kt @@ -0,0 +1,45 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.google.inject.Inject +import com.itangcent.idea.utils.Charsets +import com.itangcent.intellij.logger.Logger +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +/** + * Test case of [CommonSettingsHelper] + */ +internal class CommonSettingsHelperTest : SettingsHelperTest() { + + @Inject + private lateinit var commonSettingsHelper: CommonSettingsHelper + + @Test + fun testOutputCharset() { + for (charset in Charsets.SUPPORTED_CHARSETS) { + settings.outputCharset = charset.displayName() + assertEquals(charset.charset(), commonSettingsHelper.outputCharset()) + } + } + + @Test + fun testLogLevel() { + for (level in Logger.BasicLevel.values()) { + settings.logLevel = level.getLevel() + assertEquals(level.getLevel(), commonSettingsHelper.logLevel()) + } + } + + @Test + fun testCurrentLogLevel() { + settings.logLevel = CommonSettingsHelper.CoarseLogLevel.LOW.getLevel() + assertEquals(CommonSettingsHelper.CoarseLogLevel.LOW, commonSettingsHelper.currentLogLevel()) + settings.logLevel = CommonSettingsHelper.CoarseLogLevel.HIGH.getLevel() + assertEquals(CommonSettingsHelper.CoarseLogLevel.HIGH, commonSettingsHelper.currentLogLevel()) + + for (level in Logger.BasicLevel.values()) { + settings.logLevel = level.getLevel() + assertEquals(level, commonSettingsHelper.currentLogLevel()) + } + } +} \ No newline at end of file diff --git a/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/HttpSettingsHelperTest.kt b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/HttpSettingsHelperTest.kt new file mode 100644 index 000000000..07ac864b0 --- /dev/null +++ b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/HttpSettingsHelperTest.kt @@ -0,0 +1,95 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.google.inject.Inject +import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.Settings +import com.itangcent.intellij.context.ActionContext +import com.itangcent.mock.AdvancedContextTest +import com.itangcent.mock.SettingBinderAdaptor +import org.junit.Assert.assertArrayEquals +import org.junit.jupiter.api.Test +import java.util.concurrent.TimeUnit +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +/** + * Test case of [HttpSettingsHelper] + */ +internal class HttpSettingsHelperTest : SettingsHelperTest() { + + @Inject + private lateinit var httpSettingsHelper: HttpSettingsHelper + + @Test + fun testCheckTrustUrl() { + settings.trustHosts = arrayOf( + "https://raw.githubusercontent.com", + "!https://raw.githubusercontent.com/itangcent", + "!http://192.168.1.1", + "!http://localhost", + "https://api.getpostman.com") + assertTrue(httpSettingsHelper.checkTrustUrl("https://raw.githubusercontent.com")) + assertTrue(httpSettingsHelper.checkTrustUrl("https://raw.githubusercontent.com/tangcent")) + assertTrue(httpSettingsHelper.checkTrustUrl("https://raw.githubusercontent.com/tangcent/easy-yapi/master/third/swagger.config")) + assertFalse(httpSettingsHelper.checkTrustUrl("https://raw.githubusercontent.com/itangcent")) + assertFalse(httpSettingsHelper.checkTrustUrl("https://raw.githubusercontent.com/itangcent/easy-yapi/master/third/swagger.config")) + assertFalse(httpSettingsHelper.checkTrustUrl("http://192.168.1.1")) + assertFalse(httpSettingsHelper.checkTrustUrl("http://192.168.1.1/index")) + assertFalse(httpSettingsHelper.checkTrustUrl("http://localhost")) + assertFalse(httpSettingsHelper.checkTrustUrl("http://localhost/a")) + assertTrue(httpSettingsHelper.checkTrustUrl("https://api.getpostman.com")) + assertTrue(httpSettingsHelper.checkTrustUrl("https://api.getpostman.com/collections")) + } + + @Test + fun testCheckTrustHost() { + settings.trustHosts = arrayOf( + "https://raw.githubusercontent.com", + "!https://raw.githubusercontent.com/itangcent", + "!http://192.168.1.1", + "!http://localhost", + "https://api.getpostman.com") + assertTrue(httpSettingsHelper.checkTrustHost("https://raw.githubusercontent.com")) + assertFalse(httpSettingsHelper.checkTrustHost("https://raw.githubusercontent.com/tangcent")) + assertFalse(httpSettingsHelper.checkTrustHost("https://raw.githubusercontent.com/itangcent")) + assertFalse(httpSettingsHelper.checkTrustHost("http://192.168.1.1")) + assertFalse(httpSettingsHelper.checkTrustHost("http://localhost")) + assertTrue(httpSettingsHelper.checkTrustHost("https://api.getpostman.com")) + } + + @Test + fun testAddTrustHost() { + settings.trustHosts = emptyArray() + httpSettingsHelper.addTrustHost("https://raw.githubusercontent.com") + assertArrayEquals(settings.trustHosts, arrayOf("https://raw.githubusercontent.com")) + httpSettingsHelper.addTrustHost("https://raw.githubusercontent.com") + assertArrayEquals(settings.trustHosts, arrayOf("https://raw.githubusercontent.com")) + httpSettingsHelper.addTrustHost("!https://127.0.0.1") + assertArrayEquals(settings.trustHosts, + arrayOf("https://raw.githubusercontent.com", "!https://127.0.0.1")) + } + + @Test + fun testResolveHost() { + assertEquals("https://raw.githubusercontent.com", + httpSettingsHelper.resolveHost("https://raw.githubusercontent.com")) + assertEquals("https://raw.githubusercontent.com/tangcent", + httpSettingsHelper.resolveHost("https://raw.githubusercontent.com/tangcent")) + assertEquals("https://raw.githubusercontent.com/tangcent", + httpSettingsHelper.resolveHost("https://raw.githubusercontent.com/tangcent/easy-yapi/master/third/swagger.config")) + assertEquals("https://api.getpostman.com", + httpSettingsHelper.resolveHost("https://api.getpostman.com/collections")) + assertEquals("http://127.0.0.1", + httpSettingsHelper.resolveHost("http://127.0.0.1/a/b/c")) + assertEquals("https://127.0.0.1", + httpSettingsHelper.resolveHost("https://127.0.0.1/a/b/c")) + } + + @Test + fun testHttpTimeOut() { + settings.httpTimeOut = 10 + assertEquals(10, httpSettingsHelper.httpTimeOut(TimeUnit.SECONDS)) + assertEquals(10000, httpSettingsHelper.httpTimeOut(TimeUnit.MILLISECONDS)) + } +} \ No newline at end of file diff --git a/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/IntelligentSettingsHelperTest.kt b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/IntelligentSettingsHelperTest.kt new file mode 100644 index 000000000..e06e84bed --- /dev/null +++ b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/IntelligentSettingsHelperTest.kt @@ -0,0 +1,76 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.google.inject.Inject +import com.itangcent.intellij.psi.JsonOption +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +/** + * Test case of [IntelligentSettingsHelper] + */ +internal class IntelligentSettingsHelperTest : SettingsHelperTest() { + + @Inject + private lateinit var intelligentSettingsHelper: IntelligentSettingsHelper + + @Test + fun testFormExpanded() { + settings.formExpanded = false + assertFalse(intelligentSettingsHelper.formExpanded()) + settings.formExpanded = true + assertTrue(intelligentSettingsHelper.formExpanded()) + } + + @Test + fun testReadGetter() { + settings.readGetter = false + assertFalse(intelligentSettingsHelper.readGetter()) + settings.readGetter = true + assertTrue(intelligentSettingsHelper.readGetter()) + } + + @Test + fun testReadSetter() { + settings.readSetter = false + assertFalse(intelligentSettingsHelper.readSetter()) + settings.readSetter = true + assertTrue(intelligentSettingsHelper.readSetter()) + } + + @Test + fun testInferEnable() { + settings.inferEnable = false + assertFalse(intelligentSettingsHelper.inferEnable()) + settings.inferEnable = true + assertTrue(intelligentSettingsHelper.inferEnable()) + } + + @Test + fun testInferMaxDeep() { + settings.inferMaxDeep = 1 + assertEquals(1, intelligentSettingsHelper.inferMaxDeep()) + settings.inferMaxDeep = 10 + assertEquals(10, intelligentSettingsHelper.inferMaxDeep()) + settings.inferMaxDeep = 100 + assertEquals(100, intelligentSettingsHelper.inferMaxDeep()) + } + + @Test + fun testJsonOptionForInput() { + settings.readSetter = false + assertEquals(JsonOption.NONE, intelligentSettingsHelper.jsonOptionForInput(JsonOption.NONE)) + settings.readSetter = true + assertEquals(JsonOption.READ_SETTER, intelligentSettingsHelper.jsonOptionForInput(JsonOption.NONE)) + } + + @Test + fun testJsonOptionForOutput() { + settings.readGetter = false + assertEquals(JsonOption.NONE, intelligentSettingsHelper.jsonOptionForOutput(JsonOption.NONE)) + settings.readGetter = true + assertEquals(JsonOption.READ_GETTER, intelligentSettingsHelper.jsonOptionForOutput(JsonOption.NONE)) + + } +} \ No newline at end of file diff --git a/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/MarkdownSettingsHelperTest.kt b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/MarkdownSettingsHelperTest.kt new file mode 100644 index 000000000..0b947a107 --- /dev/null +++ b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/MarkdownSettingsHelperTest.kt @@ -0,0 +1,43 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.google.inject.Inject +import com.itangcent.idea.plugin.settings.MarkdownFormatType +import com.itangcent.idea.utils.Charsets +import org.junit.jupiter.api.Test + +/** + * Test case of [MarkdownSettingsHelper] + */ +internal class MarkdownSettingsHelperTest : SettingsHelperTest() { + + @Inject + private lateinit var markdownSettingsHelper: MarkdownSettingsHelper + + @Test + fun testOutputCharset() { + for (charset in Charsets.SUPPORTED_CHARSETS) { + settings.outputCharset = charset.displayName() + kotlin.test.assertEquals(charset.charset(), markdownSettingsHelper.outputCharset()) + } + } + + @Test + fun testOutputDemo() { + settings.outputDemo = false + kotlin.test.assertFalse(markdownSettingsHelper.outputDemo()) + settings.outputDemo = true + kotlin.test.assertTrue(markdownSettingsHelper.outputDemo()) + } + + @Test + fun testMarkdownFormatType() { + settings.markdownFormatType = MarkdownFormatType.SIMPLE.name + kotlin.test.assertEquals(MarkdownFormatType.SIMPLE, + markdownSettingsHelper.markdownFormatType()) + + settings.markdownFormatType = MarkdownFormatType.ULTIMATE.name + kotlin.test.assertEquals(MarkdownFormatType.ULTIMATE, + markdownSettingsHelper.markdownFormatType()) + + } +} \ No newline at end of file diff --git a/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/PostmanSettingsHelperTest.kt b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/PostmanSettingsHelperTest.kt new file mode 100644 index 000000000..d62eaf2fb --- /dev/null +++ b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/PostmanSettingsHelperTest.kt @@ -0,0 +1,71 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.google.inject.Inject +import com.itangcent.idea.plugin.settings.PostmanJson5FormatType +import com.itangcent.idea.swing.MessagesHelper +import com.itangcent.intellij.context.ActionContext +import org.junit.jupiter.api.Test +import org.mockito.Mockito +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertNull +import kotlin.test.assertTrue + +/** + * Test case of [PostmanSettingsHelper] + */ +internal class PostmanSettingsHelperTest : SettingsHelperTest() { + + @Inject + private lateinit var postmanSettingsHelper: PostmanSettingsHelper + + override fun bind(builder: ActionContext.ActionContextBuilder) { + super.bind(builder) + + val messagesHelper = Mockito.mock(MessagesHelper::class.java) + Mockito.`when`(messagesHelper.showInputDialog(Mockito.anyString(), + Mockito.eq("Postman Private Token"), Mockito.any())) + .thenReturn("123") + builder.bindInstance(MessagesHelper::class, messagesHelper) + } + + @Test + fun testHasPrivateToken() { + assertFalse(postmanSettingsHelper.hasPrivateToken()) + settings.postmanToken = "123" + assertTrue(postmanSettingsHelper.hasPrivateToken()) + } + + @Test + fun testGetPrivateToken() { + assertNull(postmanSettingsHelper.getPrivateToken()) + assertNull(settings.postmanToken) + assertEquals("123", postmanSettingsHelper.getPrivateToken(false)) + assertEquals("123", settings.postmanToken) + assertEquals("123", postmanSettingsHelper.getPrivateToken()) + } + + @Test + fun testWrapCollection() { + settings.wrapCollection = false + assertFalse(postmanSettingsHelper.wrapCollection()) + settings.wrapCollection = true + assertTrue(postmanSettingsHelper.wrapCollection()) + } + + @Test + fun testAutoMergeScript() { + settings.autoMergeScript = false + assertFalse(postmanSettingsHelper.autoMergeScript()) + settings.autoMergeScript = true + assertTrue(postmanSettingsHelper.autoMergeScript()) + } + + @Test + fun testPostmanJson5FormatType() { + for (formatType in PostmanJson5FormatType.values()) { + settings.postmanJson5FormatType = formatType.name + assertEquals(formatType, postmanSettingsHelper.postmanJson5FormatType()) + } + } +} \ No newline at end of file diff --git a/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/RecommendConfigLoaderTest.kt b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/RecommendConfigLoaderTest.kt new file mode 100644 index 000000000..52dd2f8ce --- /dev/null +++ b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/RecommendConfigLoaderTest.kt @@ -0,0 +1,99 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.itangcent.mock.toUnixString +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +/** + * Test case of [RecommendConfigLoader] + */ +internal class RecommendConfigLoaderTest { + + @Test + fun testPlaint() { + assertTrue(RecommendConfigLoader.plaint().contains("module=#module")) + } + + @Test + fun testBuildRecommendConfig() { + assertEquals("#Get the module from the comment,group the apis\n" + + "module=#module\n" + + "#Ignore class/api\n" + + "ignore=#ignore\n" + + "#Support for Jackson annotations\n" + + "field.name=@com.fasterxml.jackson.annotation.JsonProperty#value\n" + + "field.ignore=@com.fasterxml.jackson.annotation.JsonIgnore#value\n" + + "#Support for Gson annotations\n" + + "field.name=@com.google.gson.annotations.SerializedName#value\n" + + "field.ignore=!@com.google.gson.annotations.Expose#serialize\n" + + "#ignore transient field\n" + + "field.ignore=groovy:it.hasModifier(\"transient\")\n" + + "#Support spring.validations\n" + + "field.required=@org.springframework.lang.NonNull\n" + + "param.ignore=groovy:it.type().isExtend(\"org.springframework.validation.BindingResult\")\n" + + "#Support spring file\n" + + "type.is_file=groovy:it.isExtend(\"org.springframework.web.multipart.MultipartFile\")\n" + + "#yapi tag for kotlin\n" + + "api.tag[@kotlin.Deprecated]=deprecated\n" + + "api.tag[groovy:it.containingClass().hasAnn(\"kotlin.Deprecated\")]=deprecated\n" + + "#yapi status\n" + + "api.status[#undone]=undone\n" + + "api.status[#todo]=undone\n" + + "#yapi mock\n" + + "field.mock=#mock\n" + + "#ignore serialVersionUID\n" + + "constant.field.ignore=groovy:it.name()==\"serialVersionUID\"\n" + + "#support the common ways to use enum\n" + + "enum.use.name=groovy:it.type().name()==\"java.lang.String\"\n" + + "enum.use.ordinal=groovy:it.type().name()==\"int\"\n" + + "enum.use.ordinal=groovy:it.type().name()==\"java.lang.Integer\"", + RecommendConfigLoader.buildRecommendConfig("-Jackson_JsonIgnoreProperties,-converts,-yapi_tag,-spring.ui,-import_spring_properties,-support_mock_for_general,-deprecated_java,-deprecated_kotlin,-spring_Entity,-spring_webflux,-javax.validation,-javax.validation(grouped),-support_mock_for_javax_validation").toUnixString()) + } + + @Test + fun testAddSelectedConfig() { + assertEquals("-deprecated_java,-yapi_tag,-javax.validation(grouped),-deprecated_kotlin,-spring_webflux,-spring.ui,-spring_Entity,-javax.validation,import_spring_properties,-Jackson_JsonIgnoreProperties,-converts,-support_mock_for_javax_validation,-support_mock_for_general", + RecommendConfigLoader.addSelectedConfig("-Jackson_JsonIgnoreProperties,-converts,-yapi_tag,-spring.ui,-import_spring_properties,-support_mock_for_general,-deprecated_java,-deprecated_kotlin,-spring_Entity,-spring_webflux,-javax.validation,-javax.validation(grouped),-support_mock_for_javax_validation,import_spring_properties", "import_spring_properties")) + assertEquals("-import_spring_properties,-deprecated_java,module,-yapi_tag,-javax.validation(grouped),-deprecated_kotlin,-spring_webflux,-spring.ui,-spring_Entity,-javax.validation,import_spring_properties,-Jackson_JsonIgnoreProperties,-converts,-support_mock_for_javax_validation,-support_mock_for_general", + RecommendConfigLoader.addSelectedConfig("-Jackson_JsonIgnoreProperties,-converts,-yapi_tag,-spring.ui,-import_spring_properties,-support_mock_for_general,-deprecated_java,-deprecated_kotlin,-spring_Entity,-spring_webflux,-javax.validation,-javax.validation(grouped),-support_mock_for_javax_validation,import_spring_properties", "module")) + assertEquals("-import_spring_properties,support_mock_for_javax_validation,-deprecated_java,-yapi_tag,-javax.validation(grouped),-deprecated_kotlin,-spring_webflux,-spring.ui,-spring_Entity,-javax.validation,import_spring_properties,-Jackson_JsonIgnoreProperties,-converts,-support_mock_for_general", RecommendConfigLoader.addSelectedConfig("-Jackson_JsonIgnoreProperties,-converts,-yapi_tag,-spring.ui,-import_spring_properties,-support_mock_for_general,-deprecated_java,-deprecated_kotlin,-spring_Entity,-spring_webflux,-javax.validation,-javax.validation(grouped),-support_mock_for_javax_validation,import_spring_properties", "support_mock_for_javax_validation")) + + } + + @Test + fun testRemoveSelectedConfig() { + assertEquals("-import_spring_properties,-deprecated_java,-yapi_tag,-javax.validation(grouped),-deprecated_kotlin,-spring_webflux,-spring.ui,-spring_Entity,-javax.validation,-Jackson_JsonIgnoreProperties,-converts,-support_mock_for_javax_validation,-support_mock_for_general", + RecommendConfigLoader.removeSelectedConfig("-Jackson_JsonIgnoreProperties,-converts,-yapi_tag,-spring.ui,-import_spring_properties,-support_mock_for_general,-deprecated_java,-deprecated_kotlin,-spring_Entity,-spring_webflux,-javax.validation,-javax.validation(grouped),-support_mock_for_javax_validation,import_spring_properties", "import_spring_properties")) + assertEquals("-import_spring_properties,-deprecated_java,-yapi_tag,-javax.validation(grouped),-deprecated_kotlin,-spring_webflux,-spring.ui,-spring_Entity,-javax.validation,import_spring_properties,-Jackson_JsonIgnoreProperties,-module,-converts,-support_mock_for_javax_validation,-support_mock_for_general", + RecommendConfigLoader.removeSelectedConfig("-Jackson_JsonIgnoreProperties,-converts,-yapi_tag,-spring.ui,-import_spring_properties,-support_mock_for_general,-deprecated_java,-deprecated_kotlin,-spring_Entity,-spring_webflux,-javax.validation,-javax.validation(grouped),-support_mock_for_javax_validation,import_spring_properties", "module")) + assertEquals("-import_spring_properties,-deprecated_java,-yapi_tag,-javax.validation(grouped),-deprecated_kotlin,-spring_webflux,-spring.ui,-spring_Entity,-javax.validation,import_spring_properties,-Jackson_JsonIgnoreProperties,-converts,-support_mock_for_javax_validation,-support_mock_for_general", RecommendConfigLoader.removeSelectedConfig("-Jackson_JsonIgnoreProperties,-converts,-yapi_tag,-spring.ui,-import_spring_properties,-support_mock_for_general,-deprecated_java,-deprecated_kotlin,-spring_Entity,-spring_webflux,-javax.validation,-javax.validation(grouped),-support_mock_for_javax_validation,import_spring_properties", "support_mock_for_javax_validation")) + + } + + @Test + fun testCodes() { + assertEquals("[module, ignore, deprecated_java, deprecated_kotlin, Jackson, Jackson_JsonIgnoreProperties, Gson, ignore_transient_field, converts, spring_Entity, spring_webflux, spring.validations, spring.ui, javax.validation, javax.validation(grouped), is_file, yapi_tag, yapi_tag_kotlin, yapi_status, yapi_mock, yapi_tag, import_spring_properties, resolve_spring_properties, ignore_serialVersionUID, support_mock_for_general, private_protected_field_only, support_mock_for_javax_validation, support_enum_common]", + RecommendConfigLoader.codes().contentToString()) + + } + + @Test + fun testSelectedCodes() { + assertEquals("[module, ignore, Jackson, Gson, ignore_transient_field, spring.validations, is_file, yapi_tag_kotlin, yapi_status, yapi_mock, import_spring_properties, ignore_serialVersionUID, support_enum_common]", + RecommendConfigLoader.selectedCodes("-Jackson_JsonIgnoreProperties,-converts,-yapi_tag,-spring.ui,-import_spring_properties,-support_mock_for_general,-deprecated_java,-deprecated_kotlin,-spring_Entity,-spring_webflux,-javax.validation,-javax.validation(grouped),-support_mock_for_javax_validation,import_spring_properties").contentToString()) + } + + @Test + fun testDefaultCodes() { + assertEquals("module,ignore,deprecated_java,deprecated_kotlin,Jackson,Gson,ignore_transient_field,converts,spring_Entity,spring.validations,spring.ui,javax.validation,is_file,yapi_tag,yapi_tag_kotlin,yapi_status,yapi_mock,yapi_tag,ignore_serialVersionUID,support_mock_for_general,support_mock_for_javax_validation,support_enum_common", + RecommendConfigLoader.defaultCodes()) + } + + @Test + fun testGet() { + assertEquals("#Get the module from the comment,group the apis\n" + + "module=#module", RecommendConfigLoader["module"]?.toUnixString()) + assertEquals("module", RecommendConfigLoader[0]) + } +} \ No newline at end of file diff --git a/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/RecommendConfigSettingsHelperTest.kt b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/RecommendConfigSettingsHelperTest.kt new file mode 100644 index 000000000..0b68b3da7 --- /dev/null +++ b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/RecommendConfigSettingsHelperTest.kt @@ -0,0 +1,61 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.google.inject.Inject +import com.itangcent.mock.toUnixString +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +/** + * Test case of [RecommendConfigSettingsHelper] + */ +internal class RecommendConfigSettingsHelperTest : SettingsHelperTest() { + + @Inject + private lateinit var recommendConfigSettingsHelper: RecommendConfigSettingsHelper + + @Test + fun testUseRecommendConfig() { + settings.useRecommendConfig = false + assertFalse(recommendConfigSettingsHelper.useRecommendConfig()) + settings.useRecommendConfig = true + assertTrue(recommendConfigSettingsHelper.useRecommendConfig()) + } + + @Test + fun testLoadRecommendConfig() { + settings.recommendConfigs = "-Jackson_JsonIgnoreProperties,-converts,-yapi_tag,-spring.ui,-import_spring_properties,-support_mock_for_general,-deprecated_java,-deprecated_kotlin,-spring_Entity,-spring_webflux,-javax.validation,-javax.validation(grouped),-support_mock_for_javax_validation" + assertEquals("#Get the module from the comment,group the apis\n" + + "module=#module\n" + + "#Ignore class/api\n" + + "ignore=#ignore\n" + + "#Support for Jackson annotations\n" + + "field.name=@com.fasterxml.jackson.annotation.JsonProperty#value\n" + + "field.ignore=@com.fasterxml.jackson.annotation.JsonIgnore#value\n" + + "#Support for Gson annotations\n" + + "field.name=@com.google.gson.annotations.SerializedName#value\n" + + "field.ignore=!@com.google.gson.annotations.Expose#serialize\n" + + "#ignore transient field\n" + + "field.ignore=groovy:it.hasModifier(\"transient\")\n" + + "#Support spring.validations\n" + + "field.required=@org.springframework.lang.NonNull\n" + + "param.ignore=groovy:it.type().isExtend(\"org.springframework.validation.BindingResult\")\n" + + "#Support spring file\n" + + "type.is_file=groovy:it.isExtend(\"org.springframework.web.multipart.MultipartFile\")\n" + + "#yapi tag for kotlin\n" + + "api.tag[@kotlin.Deprecated]=deprecated\n" + + "api.tag[groovy:it.containingClass().hasAnn(\"kotlin.Deprecated\")]=deprecated\n" + + "#yapi status\n" + + "api.status[#undone]=undone\n" + + "api.status[#todo]=undone\n" + + "#yapi mock\n" + + "field.mock=#mock\n" + + "#ignore serialVersionUID\n" + + "constant.field.ignore=groovy:it.name()==\"serialVersionUID\"\n" + + "#support the common ways to use enum\n" + + "enum.use.name=groovy:it.type().name()==\"java.lang.String\"\n" + + "enum.use.ordinal=groovy:it.type().name()==\"int\"\n" + + "enum.use.ordinal=groovy:it.type().name()==\"java.lang.Integer\"", recommendConfigSettingsHelper.loadRecommendConfig().toUnixString()) + } +} \ No newline at end of file diff --git a/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/SettingsHelperTest.kt b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/SettingsHelperTest.kt new file mode 100644 index 000000000..aaca71619 --- /dev/null +++ b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/SettingsHelperTest.kt @@ -0,0 +1,20 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.Settings +import com.itangcent.intellij.context.ActionContext +import com.itangcent.mock.AdvancedContextTest +import com.itangcent.mock.SettingBinderAdaptor + +/** + * Test case of [*SettingsHelper] + */ +abstract class SettingsHelperTest : AdvancedContextTest() { + + internal val settings = Settings() + + override fun bind(builder: ActionContext.ActionContextBuilder) { + super.bind(builder) + builder.bind(SettingBinder::class) { it.toInstance(SettingBinderAdaptor(settings)) } + } +} \ No newline at end of file diff --git a/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/SupportSettingsHelperTest.kt b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/SupportSettingsHelperTest.kt new file mode 100644 index 000000000..903ba0a33 --- /dev/null +++ b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/SupportSettingsHelperTest.kt @@ -0,0 +1,23 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.google.inject.Inject +import org.junit.jupiter.api.Test +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +/** + * Test case of [SupportSettingsHelper] + */ +internal class SupportSettingsHelperTest : SettingsHelperTest() { + + @Inject + private lateinit var supportSettingsHelper: SupportSettingsHelper + + @Test + fun testMethodDocEnable() { + settings.methodDocEnable = true + assertTrue(supportSettingsHelper.methodDocEnable()) + settings.methodDocEnable = false + assertFalse(supportSettingsHelper.methodDocEnable()) + } +} \ No newline at end of file diff --git a/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/YapiSettingsHelperTest.kt b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/YapiSettingsHelperTest.kt new file mode 100644 index 000000000..58730b1b8 --- /dev/null +++ b/idea-plugin/src/test/kotlin/com/itangcent/idea/plugin/settings/helper/YapiSettingsHelperTest.kt @@ -0,0 +1,193 @@ +package com.itangcent.idea.plugin.settings.helper + +import com.google.inject.Inject +import com.itangcent.common.kit.toJson +import com.itangcent.idea.swing.MessagesHelper +import com.itangcent.intellij.context.ActionContext +import org.junit.jupiter.api.Test +import org.mockito.Mockito +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertNull +import kotlin.test.assertTrue + +/** + * Test case of [YapiSettingsHelper] + */ +internal class YapiSettingsHelperTest : SettingsHelperTest() { + + @Inject + private lateinit var yapiSettingsHelper: YapiSettingsHelper + + override fun bind(builder: ActionContext.ActionContextBuilder) { + super.bind(builder) + + val messagesHelper = Mockito.mock(MessagesHelper::class.java) + Mockito.`when`(messagesHelper.showInputDialog(Mockito.anyString(), + Mockito.eq("Server Of Yapi"), Mockito.any())) + .thenReturn("http://127.0.0.1:3000") + Mockito.`when`(messagesHelper.showInputDialog(Mockito.anyString(), + Mockito.eq("Yapi ProjectId"), Mockito.any())) + .thenReturn("66") + Mockito.`when`(messagesHelper.showInputDialog(Mockito.anyString(), + Mockito.eq("Yapi Private Token"), Mockito.any())) + .thenReturn("123456789") + builder.bindInstance(MessagesHelper::class, messagesHelper) + } + + @Test + fun testHasServer() { + assertFalse(yapiSettingsHelper.hasServer()) + settings.yapiServer = "http://127.0.0.1:3000" + assertTrue(yapiSettingsHelper.hasServer()) + } + + @Test + fun testGetServer() { + assertNull(yapiSettingsHelper.getServer()) + assertNull(settings.postmanToken) + assertEquals("http://127.0.0.1:3000", yapiSettingsHelper.getServer(false)) + assertEquals("http://127.0.0.1:3000", settings.yapiServer) + assertEquals("http://127.0.0.1:3000", yapiSettingsHelper.getServer()) + } + + @Test + fun testGetPrivateToken() { + settings.loginMode = false + assertNull(yapiSettingsHelper.getPrivateToken("demo")) + assertEquals("123456789", yapiSettingsHelper.getPrivateToken("demo", false)) + assertEquals("123456789", yapiSettingsHelper.getPrivateToken("demo")) + + settings.loginMode = true + assertNull(yapiSettingsHelper.getPrivateToken("login-demo")) + assertEquals("66", yapiSettingsHelper.getPrivateToken("login-demo", false)) + assertEquals("66", yapiSettingsHelper.getPrivateToken("login-demo")) + } + + @Test + fun testInputNewToken() { + settings.loginMode = false + assertEquals("123456789", yapiSettingsHelper.inputNewToken()) + settings.loginMode = true + assertEquals("66", yapiSettingsHelper.inputNewToken()) + } + + @Test + fun testDisableTemp() { + settings.loginMode = false + assertNull(yapiSettingsHelper.getPrivateToken("demo")) + yapiSettingsHelper.setToken("demo", "123456789") + assertEquals("123456789", yapiSettingsHelper.getPrivateToken("demo")) + yapiSettingsHelper.disableTemp("123456789") + assertNull(yapiSettingsHelper.getPrivateToken("demo")) + } + + @Test + fun testSetToken() { + settings.loginMode = false + assertNull(yapiSettingsHelper.getPrivateToken("demo")) + yapiSettingsHelper.setToken("demo", "123456789") + assertEquals("123456789", yapiSettingsHelper.getPrivateToken("demo")) + + settings.loginMode = true + assertNull(yapiSettingsHelper.getPrivateToken("login-demo")) + yapiSettingsHelper.setToken("login-demo", "66") + assertEquals("66", yapiSettingsHelper.getPrivateToken("login-demo")) + } + + @Test + fun testRemoveTokenByModule() { + settings.loginMode = false + assertNull(yapiSettingsHelper.getPrivateToken("demo")) + yapiSettingsHelper.setToken("demo", "123456789") + assertEquals("123456789", yapiSettingsHelper.getPrivateToken("demo")) + yapiSettingsHelper.removeTokenByModule("demo") + assertNull(yapiSettingsHelper.getPrivateToken("demo")) + + settings.loginMode = true + assertNull(yapiSettingsHelper.getPrivateToken("login-demo")) + yapiSettingsHelper.setToken("login-demo", "66") + assertEquals("66", yapiSettingsHelper.getPrivateToken("login-demo")) + yapiSettingsHelper.removeTokenByModule("login-demo") + assertNull(yapiSettingsHelper.getPrivateToken("login-demo")) + } + + @Test + fun testRemoveToken() { + settings.loginMode = false + assertNull(yapiSettingsHelper.getPrivateToken("demo")) + yapiSettingsHelper.setToken("demo", "123456789") + yapiSettingsHelper.setToken("demo2", "123456789") + yapiSettingsHelper.setToken("demo3", "987654321") + assertEquals("123456789", yapiSettingsHelper.getPrivateToken("demo")) + assertEquals("123456789", yapiSettingsHelper.getPrivateToken("demo2")) + assertEquals("987654321", yapiSettingsHelper.getPrivateToken("demo3")) + yapiSettingsHelper.removeToken("123456789") + assertNull(yapiSettingsHelper.getPrivateToken("demo")) + assertNull(yapiSettingsHelper.getPrivateToken("demo2")) + assertEquals("987654321", yapiSettingsHelper.getPrivateToken("demo3")) + } + + @Test + fun testReadTokens() { + settings.loginMode = false + assertNull(yapiSettingsHelper.getPrivateToken("demo")) + yapiSettingsHelper.setToken("demo", "123456789") + yapiSettingsHelper.setToken("demo2", "123456789") + yapiSettingsHelper.setToken("demo3", "987654321") + assertEquals("123456789", yapiSettingsHelper.getPrivateToken("demo")) + assertEquals("123456789", yapiSettingsHelper.getPrivateToken("demo2")) + assertEquals("987654321", yapiSettingsHelper.getPrivateToken("demo3")) + assertEquals("{\"demo3\":\"987654321\",\"demo\":\"123456789\",\"demo2\":\"123456789\"}", yapiSettingsHelper.readTokens().toJson()) + + } + + @Test + fun testRawToken() { + settings.loginMode = false + assertEquals("123456789", yapiSettingsHelper.rawToken("123456789")) + + settings.loginMode = true + assertEquals("", yapiSettingsHelper.rawToken("66")) + } + + @Test + fun testEnableUrlTemplating() { + settings.enableUrlTemplating = false + assertFalse(yapiSettingsHelper.enableUrlTemplating()) + settings.enableUrlTemplating = true + assertTrue(yapiSettingsHelper.enableUrlTemplating()) + } + + @Test + fun testLoginMode() { + settings.loginMode = false + assertFalse(yapiSettingsHelper.loginMode()) + settings.loginMode = true + assertTrue(yapiSettingsHelper.loginMode()) + } + + @Test + fun testSwitchNotice() { + settings.switchNotice = false + assertFalse(yapiSettingsHelper.switchNotice()) + settings.switchNotice = true + assertTrue(yapiSettingsHelper.switchNotice()) + } + + @Test + fun testYapiReqBodyJson5() { + settings.yapiReqBodyJson5 = false + assertFalse(yapiSettingsHelper.yapiReqBodyJson5()) + settings.yapiReqBodyJson5 = true + assertTrue(yapiSettingsHelper.yapiReqBodyJson5()) + } + + @Test + fun testYapiResBodyJson5() { + settings.yapiResBodyJson5 = false + assertFalse(yapiSettingsHelper.yapiResBodyJson5()) + settings.yapiResBodyJson5 = true + assertTrue(yapiSettingsHelper.yapiResBodyJson5()) + } +} \ No newline at end of file diff --git a/idea-plugin/src/test/kotlin/com/itangcent/idea/utils/ConfigurableLoggerTest.kt b/idea-plugin/src/test/kotlin/com/itangcent/idea/utils/ConfigurableLoggerTest.kt index 4f6a1808f..eed628d0a 100644 --- a/idea-plugin/src/test/kotlin/com/itangcent/idea/utils/ConfigurableLoggerTest.kt +++ b/idea-plugin/src/test/kotlin/com/itangcent/idea/utils/ConfigurableLoggerTest.kt @@ -1,19 +1,24 @@ package com.itangcent.idea.utils -import com.itangcent.mock.BaseContextTest -import com.itangcent.mock.SettingBinderAdaptor import com.itangcent.common.utils.SystemUtils import com.itangcent.debug.LoggerCollector import com.itangcent.idea.plugin.settings.SettingBinder import com.itangcent.idea.plugin.settings.Settings +import com.itangcent.idea.plugin.settings.helper.CommonSettingsHelper import com.itangcent.intellij.context.ActionContext import com.itangcent.intellij.extend.guice.singleton import com.itangcent.intellij.extend.guice.with import com.itangcent.intellij.logger.Logger +import com.itangcent.mock.BaseContextTest +import com.itangcent.mock.SettingBinderAdaptor +import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.CsvSource import kotlin.test.assertEquals +/** + * Test case of [ConfigurableLogger] + */ internal class ConfigurableLoggerTest : BaseContextTest() { private val settings = Settings() @@ -32,7 +37,7 @@ internal class ConfigurableLoggerTest : BaseContextTest() { "MEDIUM,[INFO]\tinfo[WARN]\twarn[ERROR]\terrorlog", "HIGH,[ERROR]\terrorlog", ) - fun testLog(level: ConfigurableLogger.CoarseLogLevel, output: String) { + fun testLog(level: CommonSettingsHelper.CoarseLogLevel, output: String) { settings.logLevel = level.getLevel() (logger as ConfigurableLogger).init() logger.trace("trace") diff --git a/idea-plugin/src/test/kotlin/com/itangcent/mock/AdvancedContextTest.kt b/idea-plugin/src/test/kotlin/com/itangcent/mock/AdvancedContextTest.kt index 18014bd39..23a418c06 100644 --- a/idea-plugin/src/test/kotlin/com/itangcent/mock/AdvancedContextTest.kt +++ b/idea-plugin/src/test/kotlin/com/itangcent/mock/AdvancedContextTest.kt @@ -2,6 +2,7 @@ package com.itangcent.mock import com.itangcent.common.spi.Setup import com.itangcent.idea.plugin.rule.SuvRuleParser +import com.itangcent.idea.swing.MessagesHelper import com.itangcent.intellij.config.AbstractConfigReader import com.itangcent.intellij.config.ConfigReader import com.itangcent.intellij.config.rule.RuleParser @@ -51,6 +52,7 @@ abstract class AdvancedContextTest : BaseContextTest() { builder.bind(RuleParser::class) { it.with(SuvRuleParser::class).singleton() } builder.bind(PsiClassHelper::class) { it.with(DefaultPsiClassHelper::class).singleton() } + builder.bind(MessagesHelper::class) { it.with(EmptyMessagesHelper::class).singleton() } } private inner class TempFileRepository : AbstractLocalFileRepository() { diff --git a/idea-plugin/src/test/kotlin/com/itangcent/mock/EmptyMessagesHelper.kt b/idea-plugin/src/test/kotlin/com/itangcent/mock/EmptyMessagesHelper.kt new file mode 100644 index 000000000..82921f942 --- /dev/null +++ b/idea-plugin/src/test/kotlin/com/itangcent/mock/EmptyMessagesHelper.kt @@ -0,0 +1,15 @@ +package com.itangcent.mock + +import com.intellij.openapi.ui.Messages +import com.itangcent.idea.swing.MessagesHelper +import javax.swing.Icon + +class EmptyMessagesHelper : MessagesHelper { + override fun showYesNoDialog(message: String?, title: String, icon: Icon?): Int { + return Messages.YES + } + + override fun showInputDialog(message: String?, title: String?, icon: Icon?): String? { + return null + } +} \ No newline at end of file diff --git a/idea-plugin/src/test/kotlin/com/itangcent/suv/http/ConfigurableHttpClientProviderTest.kt b/idea-plugin/src/test/kotlin/com/itangcent/suv/http/ConfigurableHttpClientProviderTest.kt index da30a2819..2928b0abe 100644 --- a/idea-plugin/src/test/kotlin/com/itangcent/suv/http/ConfigurableHttpClientProviderTest.kt +++ b/idea-plugin/src/test/kotlin/com/itangcent/suv/http/ConfigurableHttpClientProviderTest.kt @@ -1,5 +1,10 @@ package com.itangcent.suv.http +import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.plugin.settings.Settings +import com.itangcent.intellij.context.ActionContext +import com.itangcent.mock.SettingBinderAdaptor + /** * Test case of [ConfigurableHttpClientProvider] */ @@ -7,6 +12,15 @@ internal class ConfigurableHttpClientProviderTest : HttpClientProviderTest() { override val httpClientProviderClass get() = ConfigurableHttpClientProvider::class + override fun bind(builder: ActionContext.ActionContextBuilder) { + super.bind(builder) + builder.bind(SettingBinder::class) { + it.toInstance(SettingBinderAdaptor(Settings().also { settings -> + settings.trustHosts = arrayOf("https://www.apache.org") + })) + } + } + override fun customConfig(): String { return "http.call.before=groovy:logger.info(\"call:\"+request.url())\nhttp.call.after=groovy:logger.info(\"response:\"+response.string())\nhttp.timeOut=3" } diff --git a/idea-plugin/src/test/kotlin/com/itangcent/suv/http/HttpClientProviderTest.kt b/idea-plugin/src/test/kotlin/com/itangcent/suv/http/HttpClientProviderTest.kt index f19df4666..48cec3ae4 100644 --- a/idea-plugin/src/test/kotlin/com/itangcent/suv/http/HttpClientProviderTest.kt +++ b/idea-plugin/src/test/kotlin/com/itangcent/suv/http/HttpClientProviderTest.kt @@ -21,6 +21,7 @@ internal abstract class HttpClientProviderTest : AdvancedContextTest() { override fun bind(builder: ActionContext.ActionContextBuilder) { super.bind(builder) builder.bind(HttpClientProvider::class) { it.with(httpClientProviderClass) } + } @Test diff --git a/idea-plugin/src/test/kotlin/com/itangcent/testFramework/PluginContextLightCodeInsightFixtureTestCase.kt b/idea-plugin/src/test/kotlin/com/itangcent/testFramework/PluginContextLightCodeInsightFixtureTestCase.kt index b60cfd7bc..ec735492a 100644 --- a/idea-plugin/src/test/kotlin/com/itangcent/testFramework/PluginContextLightCodeInsightFixtureTestCase.kt +++ b/idea-plugin/src/test/kotlin/com/itangcent/testFramework/PluginContextLightCodeInsightFixtureTestCase.kt @@ -2,12 +2,14 @@ package com.itangcent.testFramework import com.itangcent.idea.plugin.rule.SuvRuleParser import com.itangcent.idea.plugin.settings.SettingBinder +import com.itangcent.idea.swing.MessagesHelper import com.itangcent.idea.utils.ModuleHelper import com.itangcent.intellij.config.rule.RuleParser import com.itangcent.intellij.context.ActionContext import com.itangcent.intellij.extend.guice.singleton import com.itangcent.intellij.extend.guice.with import com.itangcent.mock.ConstantModuleHelper +import com.itangcent.mock.EmptyMessagesHelper import com.itangcent.mock.SettingBinderAdaptor import org.junit.jupiter.api.condition.DisabledOnJre @@ -20,5 +22,6 @@ abstract class PluginContextLightCodeInsightFixtureTestCase : ContextLightCodeIn builder.bind(RuleParser::class) { it.with(SuvRuleParser::class).singleton() } builder.bindInstance("plugin.name", "easy_api") builder.bind(ModuleHelper::class) { it.toInstance(ConstantModuleHelper.INSTANCE) } + builder.bind(MessagesHelper::class) { it.with(EmptyMessagesHelper::class).singleton() } } } \ No newline at end of file