├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.gradle.kts ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── lib ├── gene-plugin-2.0-SNAPSHOT.jar └── mybatis-generator-core-1.4.0.jar ├── qodana.yml ├── settings.gradle.kts └── src └── main ├── java └── com │ └── tianlei │ └── mybatis │ ├── action │ ├── MybatisGeneratorMainAction.java │ └── MybatisTypedHandler.java │ ├── alias │ ├── AliasClassReference.java │ ├── AliasDesc.java │ ├── AliasFacade.java │ ├── AliasResolver.java │ ├── AliasResolverFactory.java │ ├── AnnotationAliasResolver.java │ ├── BeanAliasResolver.java │ ├── ConfigPackageAliasResolver.java │ ├── InnerAliasResolver.java │ ├── PackageAliasResolver.java │ └── SingleAliasResolver.java │ ├── annotation │ └── Annotation.java │ ├── contributor │ ├── JavaMenthodCompletionContributor.java │ ├── SqlParamCompletionContributor.java │ └── TestParamContributor.java │ ├── definitionsearch │ └── MapperDefinitionSearch.java │ ├── dom │ ├── MapperBacktrackingUtils.java │ ├── converter │ │ ├── AliasConverter.java │ │ ├── ConverterAdaptor.java │ │ ├── DaoMethodConverter.java │ │ ├── IdBasedTagConverter.java │ │ ├── ParameterMapConverter.java │ │ ├── PropertyConverter.java │ │ ├── ResultMapConverter.java │ │ └── SqlConverter.java │ ├── description │ │ ├── ConfigurationDescription.java │ │ └── MapperDescription.java │ └── model │ │ ├── Arg.java │ │ ├── Association.java │ │ ├── Bean.java │ │ ├── BeanProperty.java │ │ ├── Beans.java │ │ ├── Bind.java │ │ ├── Cache.java │ │ ├── CacheRef.java │ │ ├── Case.java │ │ ├── Choose.java │ │ ├── Collection.java │ │ ├── Configuration.java │ │ ├── Constructor.java │ │ ├── Delete.java │ │ ├── Discriminator.java │ │ ├── Foreach.java │ │ ├── GroupFour.java │ │ ├── GroupOne.java │ │ ├── GroupThree.java │ │ ├── GroupTwo.java │ │ ├── Id.java │ │ ├── IdArg.java │ │ ├── IdDomElement.java │ │ ├── If.java │ │ ├── Include.java │ │ ├── Insert.java │ │ ├── Mapper.java │ │ ├── Otherwise.java │ │ ├── Package.java │ │ ├── Parameter.java │ │ ├── ParameterMap.java │ │ ├── Property.java │ │ ├── PropertyGroup.java │ │ ├── Result.java │ │ ├── ResultMap.java │ │ ├── ResultMapGroup.java │ │ ├── Select.java │ │ ├── SelectKey.java │ │ ├── Set.java │ │ ├── Sql.java │ │ ├── Trim.java │ │ ├── TypeAlias.java │ │ ├── TypeAliases.java │ │ ├── Update.java │ │ ├── When.java │ │ └── Where.java │ ├── generate │ ├── DeleteGenerator.java │ ├── GenerateModel.java │ ├── InsertGenerator.java │ ├── MybatisGenerator.java │ ├── SelectGenerator.java │ ├── StatementGenerator.java │ └── UpdateGenerator.java │ ├── inspection │ ├── GenericQuickFix.java │ ├── MapperInspection.java │ ├── MapperMethodInspection.java │ ├── MapperXmlInspection.java │ ├── ResultTypeQuickFix.java │ └── StatementNotExistsQuickFix.java │ ├── intention │ ├── GenerateMapperChooser.java │ ├── GenerateMapperIntention.java │ ├── GenerateParamAnnotationIntention.java │ ├── GenerateParamChooser.java │ ├── GenerateStatementChooser.java │ ├── GenerateStatementIntention.java │ ├── GenericIntention.java │ ├── IntentionChooser.java │ └── JavaFileIntentionChooser.java │ ├── locator │ ├── LocateStrategy.java │ ├── MapperLocator.java │ ├── MapperXmlPackageProvider.java │ ├── PackageLocateStrategy.java │ └── PackageProvider.java │ ├── model │ ├── Config.java │ ├── DbType.java │ ├── TableInfo.java │ └── User.java │ ├── provider │ ├── InjectionLineMarkerProvider.java │ ├── MapperLineMarkerProvider.java │ ├── SimpleLineMarkerProvider.java │ └── StatementLineMarkerProvider.java │ ├── refactoring │ └── MapperRefactoringProvider.java │ ├── reference │ ├── ContextPsiFieldReference.java │ ├── ContextReferenceSetResolver.java │ ├── PsiFieldReferenceSetResolver.java │ ├── ReferenceSetResolverFactory.java │ └── ResultPropertyReferenceSet.java │ ├── service │ ├── AnnotationService.java │ ├── EditorService.java │ ├── JavaService.java │ └── TableInfoService.java │ ├── setting │ ├── MybatisConfigurable.java │ ├── MybatisGeneratorConfigurable.java │ ├── MybatisSetting.java │ ├── MybatisSettingForm.form │ ├── MybatisSettingForm.java │ └── PersistentConfig.java │ ├── template │ └── MybatisFileTemplateDescriptorFactory.java │ ├── ui │ ├── ClickableListener.java │ ├── ExecutableListener.java │ ├── ListSelectionListener.java │ ├── MybatisGeneratorMainUI.java │ ├── MybatisGeneratorSettingUI.java │ └── UiComponentFacade.java │ └── util │ ├── ArrayUtils.java │ ├── CollectionUtils.java │ ├── DbToolsUtils.java │ ├── DomUtils.java │ ├── GeneratorCallback.java │ ├── Icons.java │ ├── JTextFieldHintListener.java │ ├── JavaUtils.java │ ├── MapperUtils.java │ ├── MybatisConstants.java │ └── StringUtils.java └── resources ├── META-INF ├── plugin.xml └── pluginIcon.svg ├── fileTemplates └── j2ee │ └── Mybatis Mapper.xml.ft ├── images ├── 7.png ├── 7d.png ├── injection.png ├── logo.png ├── mapper_method.png ├── s.png └── statement.png └── liveTemplates └── sql.xml /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Free MyBatis Tool Changelog 4 | 5 | ## [2.2.2] 6 | 7 | ### Fixed 8 | - Version compatibility fix 9 | 10 | ## [2.2.1] 11 | 12 | ### Fixed 13 | - Fix Generate Options Overwrite-Xml 14 | 15 | ## [2.2.0] 16 | 17 | ### Fixed 18 | - Fix Generate Options Comment(实体注释) 19 | - Fix Generate Options Repository-Annotation(Repository注解) 20 | 21 | ### Changed 22 | - Generate page layout optimization 23 | - Upgrade Gradle 8.2.1 24 | - Upgrade Java 17 25 | 26 | ## [2.1.3] 27 | 28 | ### Fixed 29 | - Upgrade Support to `2022.3` or higher 30 | 31 | ## [2.1.2] 32 | 33 | ### Fixed 34 | - Upgrade Support to `2022.2` 35 | 36 | ## [2.1.1] 37 | 38 | ### Fixed 39 | - Fix `java.lang.IllegalArgumentException: Argument for @NotNull parameter 'module' of ... must not be null` 40 | 41 | ## [2.1.0] 42 | 43 | ### Fixed 44 | - Upgrade Support to `2022.1` 45 | 46 | ## [2.0.4] 47 | 48 | ### Fixed 49 | - Fix the bug of jumping error when there is a **Dao/Xml** file with the same name. 50 | - Fix the bug that the **Xml** file is automatically generated when there is a **Dao** file with the same name. 51 | - Fix the `IncorrectOperationException` that was automatically generated when there was an **Xml** file with the same name 52 | 53 | ## [2.0.3] 54 | 55 | ### Fixed 56 | - Fix the problem of being overwritten by the first class when generating multiple tables. 57 | 58 | ## [2.0.2] 59 | 60 | ### Fixed 61 | - Fix `ClassCastException` Exception 62 | 63 | ## [2.0.1] 64 | 65 | ### Fixed 66 | - Fix `Page(分页)`,`Add-ForUpdate(select增加ForUpdate)` function 67 | 68 | ## [2.0.0] 69 | 70 | ### Changed 71 | - Upgrade Support to `2021.3.x` 72 | 73 | ### Fixed 74 | - Fix `LineMarkerInfo` Exception -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

6 | 7 |

8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |

18 | 19 | 20 | # Free MyBatis Tool 21 | 22 | ## [Plugin homepage](https://plugins.jetbrains.com/plugin/18617-free-mybatis-tool) 23 | 24 | 25 | **Free MyBatis Tool** is a plugin that enhances idea support for mybatis. 26 | 27 | #### Here is the main functions: 28 | * generate mapper xml files 29 | * navigate from the code to mapper and from the mapper back to code 30 | * auto code and error tips 31 | * support mybatis generator gui 32 | * generate swagger model annotation 33 | 34 | **Free MyBatis Tool** 是一款增强idea对mybatis支持的插件。 35 | #### 主要功能如下: 36 | * 生成mapper xml文件 37 | * 快速从代码跳转到mapper及从mapper返回代码 38 | * mybatis自动补全及语法错误提示 39 | * 集成mybatis generator gui界面 40 | * 根据数据库注解,生成swagger model注解 41 | 42 | ### Getting started 43 | * Open the **Dao** interface file and click the arrow on the left to jump to the **xml** file. 44 | * Open the **xml** interface file and click the arrow on the left to jump to the **Dao** file. 45 | * Open the **database** Tool on the left side of the idea, create a data source connection, right-click to select one or more tables, and select **Mybatis-Generator** to open the **Mybatis Generate Tool** panel for the Generate operation. 46 | 47 | ***Thanks for the contribution @wuzhizhan*** 48 | 49 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.changelog.markdownToHTML 2 | import org.jetbrains.changelog.Changelog 3 | 4 | fun properties(key: String) = providers.gradleProperty(key) 5 | fun environment(key: String) = providers.environmentVariable(key) 6 | 7 | plugins { 8 | id("java") // Java support 9 | alias(libs.plugins.kotlin) // Kotlin support 10 | alias(libs.plugins.gradleIntelliJPlugin) // Gradle IntelliJ Plugin 11 | alias(libs.plugins.changelog) // Gradle Changelog Plugin 12 | alias(libs.plugins.qodana) // Gradle Qodana Plugin 13 | alias(libs.plugins.kover) // Gradle Kover Plugin 14 | } 15 | 16 | group = properties("pluginGroup").get() 17 | version = properties("pluginVersion").get() 18 | 19 | // Configure project's dependencies 20 | repositories { 21 | mavenCentral() 22 | } 23 | 24 | // Dependencies are managed with Gradle version catalog - read more: https://docs.gradle.org/current/userguide/platforms.html#sub:version-catalog 25 | dependencies { 26 | implementation(fileTree(mapOf("dir" to "lib", "include" to listOf("*.jar")))) 27 | implementation("com.softwareloop:mybatis-generator-lombok-plugin:1.0") 28 | implementation("uk.com.robust-it:cloning:1.9.2") 29 | testImplementation("junit:junit:4.13.1") 30 | } 31 | 32 | // Set the JVM language level used to build the project. Use Java 11 for 2020.3+, and Java 17 for 2022.2+. 33 | kotlin { 34 | jvmToolchain(Integer.valueOf(properties("javaVersion").get())) 35 | } 36 | 37 | // Configure Gradle IntelliJ Plugin - read more: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html 38 | intellij { 39 | pluginName = properties("pluginName") 40 | version = properties("platformVersion") 41 | type = properties("platformType") 42 | 43 | // Plugin Dependencies. Uses `platformPlugins` property from the gradle.properties file. 44 | plugins = properties("platformPlugins").map { it.split(',').map(String::trim).filter(String::isNotEmpty) } 45 | } 46 | 47 | // Configure Gradle Changelog Plugin - read more: https://github.com/JetBrains/gradle-changelog-plugin 48 | changelog { 49 | groups.empty() 50 | repositoryUrl = properties("pluginRepositoryUrl") 51 | version = properties("pluginVersion") 52 | } 53 | 54 | // Configure Gradle Qodana Plugin - read more: https://github.com/JetBrains/gradle-qodana-plugin 55 | qodana { 56 | cachePath = provider { file(".qodana").canonicalPath } 57 | reportPath = provider { file("build/reports/inspections").canonicalPath } 58 | saveReport = true 59 | showReport = environment("QODANA_SHOW_REPORT").map { it.toBoolean() }.getOrElse(false) 60 | } 61 | 62 | // Configure Gradle Kover Plugin - read more: https://github.com/Kotlin/kotlinx-kover#configuration 63 | koverReport { 64 | defaults { 65 | xml { 66 | onCheck = true 67 | } 68 | } 69 | } 70 | 71 | tasks { 72 | wrapper { 73 | gradleVersion = properties("gradleVersion").get() 74 | } 75 | 76 | patchPluginXml { 77 | version = properties("pluginVersion") 78 | sinceBuild = properties("pluginSinceBuild") 79 | untilBuild = "" 80 | if (properties("pluginUntilBuild").get() != "*") { 81 | untilBuild = properties("pluginUntilBuild") 82 | } 83 | 84 | // Extract the section from README.md and provide for the plugin's manifest 85 | pluginDescription = providers.fileContents(layout.projectDirectory.file("README.md")).asText.map { 86 | val start = "" 87 | val end = "" 88 | 89 | with (it.lines()) { 90 | if (!containsAll(listOf(start, end))) { 91 | throw GradleException("Plugin description section not found in README.md:\n$start ... $end") 92 | } 93 | subList(indexOf(start) + 1, indexOf(end)).joinToString("\n").let(::markdownToHTML) 94 | } 95 | } 96 | 97 | val changelog = project.changelog // local variable for configuration cache compatibility 98 | // Get the latest available change notes from the changelog file 99 | changeNotes = properties("pluginVersion").map { pluginVersion -> 100 | with(changelog) { 101 | renderItem( 102 | (getOrNull(pluginVersion) ?: getUnreleased()) 103 | .withHeader(false) 104 | .withEmptySections(false), 105 | Changelog.OutputType.HTML, 106 | ) 107 | } 108 | } 109 | } 110 | 111 | // Configure UI tests plugin 112 | // Read more: https://github.com/JetBrains/intellij-ui-test-robot 113 | runIdeForUiTests { 114 | systemProperty("robot-server.port", "8082") 115 | systemProperty("ide.mac.message.dialogs.as.sheets", "false") 116 | systemProperty("jb.privacy.policy.text", "") 117 | systemProperty("jb.consents.confirmation.enabled", "false") 118 | } 119 | 120 | signPlugin { 121 | certificateChain = environment("CERTIFICATE_CHAIN") 122 | privateKey = environment("PRIVATE_KEY") 123 | password = environment("PRIVATE_KEY_PASSWORD") 124 | } 125 | 126 | publishPlugin { 127 | dependsOn("patchChangelog") 128 | token = environment("PUBLISH_TOKEN") 129 | // The pluginVersion is based on the SemVer (https://semver.org) and supports pre-release labels, like 2.1.7-alpha.3 130 | // Specify pre-release label to publish the plugin in a custom Release Channel automatically. Read more: 131 | // https://plugins.jetbrains.com/docs/intellij/deployment.html#specifying-a-release-channel 132 | channels = properties("pluginVersion").map { listOf(it.split('-').getOrElse(1) { "default" }.split('.').first()) } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # IntelliJ Platform Artifacts Repositories 2 | # -> https://plugins.jetbrains.com/docs/intellij/intellij-artifacts.html 3 | 4 | pluginGroup = com.mozt.plugins 5 | pluginName = Free MyBatis Tool 6 | pluginRepositoryUrl = https://github.com/moztl/Free-Mybatis-Tool 7 | # SemVer format -> https://semver.org 8 | pluginVersion = 2.2.2 9 | 10 | # See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html 11 | # for insight into build numbers and IntelliJ Platform versions. 12 | pluginSinceBuild = 222 13 | pluginUntilBuild = * 14 | 15 | # IntelliJ Platform Properties -> https://github.com/JetBrains/gradle-intellij-plugin#intellij-platform-properties 16 | platformType = IU 17 | platformVersion = 2023.3 18 | 19 | # Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html 20 | # Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22 21 | platformPlugins = Spring, DatabaseTools, java 22 | 23 | # Java language level used to compile sources and to generate the files for - Java 11 is required since 2020.3 24 | javaVersion = 17 25 | 26 | # Gradle Releases -> https://github.com/gradle/gradle/releases 27 | gradleVersion = 8.2.1 28 | 29 | # Opt-out flag for bundling Kotlin standard library. 30 | # See https://plugins.jetbrains.com/docs/intellij/kotlin.html#kotlin-standard-library for details. 31 | # suppress inspection "UnusedProperty" 32 | kotlin.stdlib.default.dependency = false 33 | 34 | # Enable Gradle Configuration Cache -> https://docs.gradle.org/current/userguide/configuration_cache.html 35 | org.gradle.configuration-cache = false 36 | 37 | # Enable Gradle Build Cache -> https://docs.gradle.org/current/userguide/build_cache.html 38 | org.gradle.caching = false 39 | 40 | # Enable Gradle Kotlin DSL Lazy Property Assignment -> https://docs.gradle.org/current/userguide/kotlin_dsl.html#kotdsl:assignment 41 | systemProp.org.gradle.unsafe.kotlin.assignment = true -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | # libraries 3 | annotations = "24.0.1" 4 | 5 | # plugins 6 | kotlin = "1.9.0" 7 | changelog = "2.1.2" 8 | gradleIntelliJPlugin = "1.15.0" 9 | qodana = "0.1.13" 10 | kover = "0.7.2" 11 | 12 | [libraries] 13 | annotations = { group = "org.jetbrains", name = "annotations", version.ref = "annotations" } 14 | 15 | [plugins] 16 | changelog = { id = "org.jetbrains.changelog", version.ref = "changelog" } 17 | gradleIntelliJPlugin = { id = "org.jetbrains.intellij", version.ref = "gradleIntelliJPlugin" } 18 | kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } 19 | kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" } 20 | qodana = { id = "org.jetbrains.qodana", version.ref = "qodana" } 21 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moztl/Free-Mybatis-Tool/7812f4c943e0af40b9d9ce8924dd93db631d4c4b/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /lib/gene-plugin-2.0-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moztl/Free-Mybatis-Tool/7812f4c943e0af40b9d9ce8924dd93db631d4c4b/lib/gene-plugin-2.0-SNAPSHOT.jar -------------------------------------------------------------------------------- /lib/mybatis-generator-core-1.4.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moztl/Free-Mybatis-Tool/7812f4c943e0af40b9d9ce8924dd93db631d4c4b/lib/mybatis-generator-core-1.4.0.jar -------------------------------------------------------------------------------- /qodana.yml: -------------------------------------------------------------------------------- 1 | # Qodana configuration: 2 | # https://www.jetbrains.com/help/qodana/qodana-yaml.html 3 | 4 | version: 1.0 5 | linter: jetbrains/qodana-jvm-community:latest 6 | projectJDK: 17 7 | profile: 8 | name: qodana.recommended 9 | exclude: 10 | - name: All 11 | paths: 12 | - .qodana 13 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "Free MyBatis Tool" 2 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/action/MybatisGeneratorMainAction.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.action; 2 | 3 | 4 | import com.intellij.database.psi.DbTable; 5 | import com.intellij.openapi.actionSystem.AnAction; 6 | import com.intellij.openapi.actionSystem.AnActionEvent; 7 | import com.intellij.openapi.actionSystem.LangDataKeys; 8 | import com.intellij.openapi.ui.Messages; 9 | import com.intellij.psi.PsiElement; 10 | import com.tianlei.mybatis.ui.MybatisGeneratorMainUI; 11 | 12 | public class MybatisGeneratorMainAction extends AnAction { 13 | 14 | 15 | /** 16 | * 点击后打开插件主页面 17 | */ 18 | @Override 19 | public void actionPerformed(AnActionEvent e) { 20 | PsiElement[] psiElements = e.getData(LangDataKeys.PSI_ELEMENT_ARRAY); 21 | if (psiElements == null || psiElements.length == 0) { 22 | Messages.showMessageDialog("Please select one or more tables", "Notice", Messages.getInformationIcon()); 23 | return; 24 | } 25 | for (PsiElement psiElement : psiElements) { 26 | if (!(psiElement instanceof DbTable)) { 27 | Messages.showMessageDialog("Please select one or more tables", "Notice", Messages.getInformationIcon()); 28 | return; 29 | } 30 | } 31 | new MybatisGeneratorMainUI(e); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/action/MybatisTypedHandler.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.action; 2 | 3 | import com.intellij.codeInsight.AutoPopupController; 4 | import com.intellij.codeInsight.editorActions.TypedHandlerDelegate; 5 | import com.intellij.lang.injection.InjectedLanguageManager; 6 | import com.intellij.openapi.editor.Editor; 7 | import com.intellij.openapi.project.Project; 8 | import com.intellij.psi.PsiFile; 9 | import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; 10 | import com.tianlei.mybatis.util.DomUtils; 11 | import org.jetbrains.annotations.NotNull; 12 | 13 | public class MybatisTypedHandler extends TypedHandlerDelegate { 14 | 15 | @Override 16 | public Result checkAutoPopup(char charTyped, final Project project, final Editor editor, PsiFile file) { 17 | if (charTyped == '.' && DomUtils.isMybatisFile(file)) { 18 | autoPopupParameter(project, editor); 19 | return Result.STOP; 20 | } 21 | return super.checkAutoPopup(charTyped, project, editor, file); 22 | } 23 | 24 | @Override 25 | public Result charTyped(char c, final Project project, @NotNull final Editor editor, @NotNull PsiFile file) { 26 | int index = editor.getCaretModel().getOffset() - 2; 27 | PsiFile topLevelFile = InjectedLanguageManager.getInstance(project).getTopLevelFile(file); 28 | boolean parameterCase = c == '{' && 29 | index >= 0 && 30 | editor.getDocument().getText().charAt(index) == '#' && 31 | DomUtils.isMybatisFile(topLevelFile); 32 | if (parameterCase) { 33 | autoPopupParameter(project, editor); 34 | return Result.STOP; 35 | } 36 | return super.charTyped(c, project, editor, file); 37 | } 38 | 39 | private static void autoPopupParameter(final Project project, final Editor editor) { 40 | AutoPopupController.getInstance(project).autoPopupMemberLookup(editor, psiFile -> true); 41 | } 42 | 43 | 44 | } -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/alias/AliasClassReference.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.alias; 2 | 3 | import com.google.common.base.Function; 4 | import com.google.common.collect.Collections2; 5 | import com.intellij.psi.PsiElement; 6 | import com.intellij.psi.PsiReferenceBase; 7 | import com.intellij.psi.xml.XmlAttributeValue; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | import java.util.Collection; 12 | 13 | public class AliasClassReference extends PsiReferenceBase { 14 | 15 | private Function function = new Function() { 16 | @Override 17 | public String apply(AliasDesc input) { 18 | return input.getAlias(); 19 | } 20 | }; 21 | 22 | public AliasClassReference(@NotNull XmlAttributeValue element) { 23 | super(element, true); 24 | } 25 | 26 | @Nullable 27 | @Override 28 | public PsiElement resolve() { 29 | XmlAttributeValue attributeValue = getElement(); 30 | return AliasFacade.getInstance(attributeValue.getProject()).findPsiClass(attributeValue, attributeValue.getValue()).orElse(null); 31 | } 32 | 33 | @NotNull 34 | @Override 35 | public Object[] getVariants() { 36 | AliasFacade aliasFacade = AliasFacade.getInstance(getElement().getProject()); 37 | Collection result = Collections2.transform(aliasFacade.getAliasDescs(getElement()), function); 38 | return result.toArray(new String[result.size()]); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/alias/AliasDesc.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.alias; 2 | 3 | import com.intellij.psi.PsiClass; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | public class AliasDesc { 7 | 8 | private PsiClass clazz; 9 | 10 | private String alias; 11 | 12 | public AliasDesc() { 13 | } 14 | 15 | public static AliasDesc create(@NotNull PsiClass psiClass, @NotNull String alias) { 16 | return new AliasDesc(psiClass, alias); 17 | } 18 | 19 | public AliasDesc(PsiClass clazz, String alias) { 20 | this.clazz = clazz; 21 | this.alias = alias; 22 | } 23 | 24 | public PsiClass getClazz() { 25 | return clazz; 26 | } 27 | 28 | public void setClazz(PsiClass clazz) { 29 | this.clazz = clazz; 30 | } 31 | 32 | public String getAlias() { 33 | return alias; 34 | } 35 | 36 | public void setAlias(String alias) { 37 | this.alias = alias; 38 | } 39 | 40 | @Override 41 | public boolean equals(Object o) { 42 | if (this == o) { 43 | return true; 44 | } 45 | if (o == null || getClass() != o.getClass()) { 46 | return false; 47 | } 48 | 49 | AliasDesc aliasDesc = (AliasDesc) o; 50 | 51 | if (alias != null ? !alias.equalsIgnoreCase(aliasDesc.alias) : aliasDesc.alias != null) { 52 | return false; 53 | } 54 | if (clazz != null ? !clazz.equals(aliasDesc.clazz) : aliasDesc.clazz != null) { 55 | return false; 56 | } 57 | 58 | return true; 59 | } 60 | 61 | @Override 62 | public int hashCode() { 63 | int result = clazz != null ? clazz.hashCode() : 0; 64 | result = 31 * result + (alias != null ? alias.hashCode() : 0); 65 | return result; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/alias/AliasFacade.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.alias; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.intellij.openapi.project.Project; 5 | import com.intellij.psi.JavaPsiFacade; 6 | import com.intellij.psi.PsiClass; 7 | import com.intellij.psi.PsiElement; 8 | import com.intellij.psi.search.GlobalSearchScope; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | import java.util.ArrayList; 13 | import java.util.Collection; 14 | import java.util.List; 15 | import java.util.Optional; 16 | 17 | public class AliasFacade { 18 | 19 | private Project project; 20 | 21 | private JavaPsiFacade javaPsiFacade; 22 | 23 | private List resolvers; 24 | 25 | public static final AliasFacade getInstance(@NotNull Project project) { 26 | return project.getService(AliasFacade.class); 27 | } 28 | 29 | public AliasFacade(Project project) { 30 | this.project = project; 31 | this.resolvers = Lists.newArrayList(); 32 | this.javaPsiFacade = JavaPsiFacade.getInstance(project); 33 | initResolvers(); 34 | } 35 | 36 | private void initResolvers() { 37 | try { 38 | Class.forName("com.intellij.spring.model.utils.SpringModelUtils"); 39 | this.registerResolver(AliasResolverFactory.createBeanResolver(project)); 40 | } catch (ClassNotFoundException e) { 41 | } 42 | this.registerResolver(AliasResolverFactory.createSingleAliasResolver(project)); 43 | this.registerResolver(AliasResolverFactory.createConfigPackageResolver(project)); 44 | this.registerResolver(AliasResolverFactory.createAnnotationResolver(project)); 45 | this.registerResolver(AliasResolverFactory.createInnerAliasResolver(project)); 46 | } 47 | 48 | @NotNull 49 | public Optional findPsiClass(@Nullable PsiElement element, @NotNull String shortName) { 50 | PsiClass clazz = javaPsiFacade.findClass(shortName, GlobalSearchScope.allScope(project)); 51 | if (null != clazz) { 52 | return Optional.of(clazz); 53 | } 54 | for (AliasResolver resolver : resolvers) { 55 | for (AliasDesc desc : resolver.getClassAliasDescriptions(element)) { 56 | if (shortName.equalsIgnoreCase(desc.getAlias())) { 57 | return Optional.of(desc.getClazz()); 58 | } 59 | } 60 | } 61 | return Optional.empty(); 62 | } 63 | 64 | @NotNull 65 | public Collection getAliasDescs(@Nullable PsiElement element) { 66 | ArrayList result = Lists.newArrayList(); 67 | for (AliasResolver resolver : resolvers) { 68 | result.addAll(resolver.getClassAliasDescriptions(element)); 69 | } 70 | return result; 71 | } 72 | 73 | public Optional findAliasDesc(@Nullable PsiClass clazz) { 74 | if (clazz == null) { 75 | return Optional.empty(); 76 | } 77 | for (AliasResolver resolver : resolvers) { 78 | for (AliasDesc desc : resolver.getClassAliasDescriptions(clazz)) { 79 | if (clazz.equals(desc.getClazz())) { 80 | return Optional.of(desc); 81 | } 82 | } 83 | } 84 | return Optional.empty(); 85 | } 86 | 87 | public void registerResolver(@NotNull AliasResolver resolver) { 88 | this.resolvers.add(resolver); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/alias/AliasResolver.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.alias; 2 | 3 | import com.intellij.openapi.project.Project; 4 | import com.intellij.psi.PsiClass; 5 | import com.intellij.psi.PsiElement; 6 | import com.tianlei.mybatis.util.JavaUtils; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.util.Optional; 11 | import java.util.Set; 12 | 13 | public abstract class AliasResolver { 14 | 15 | protected Project project; 16 | 17 | public AliasResolver(Project project) { 18 | this.project = project; 19 | } 20 | 21 | @NotNull 22 | protected Optional addAliasDesc(@NotNull Set descs, @Nullable PsiClass clazz, @Nullable String alias) { 23 | if (null == alias || !JavaUtils.isModelClazz(clazz)) { 24 | return Optional.empty(); 25 | } 26 | AliasDesc desc = new AliasDesc(); 27 | descs.add(desc); 28 | desc.setClazz(clazz); 29 | desc.setAlias(alias); 30 | return Optional.of(desc); 31 | } 32 | 33 | @NotNull 34 | public abstract Set getClassAliasDescriptions(@Nullable PsiElement element); 35 | 36 | public Project getProject() { 37 | return project; 38 | } 39 | 40 | public void setProject(Project project) { 41 | this.project = project; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/alias/AliasResolverFactory.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.alias; 2 | 3 | import com.intellij.openapi.project.Project; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | public class AliasResolverFactory { 7 | 8 | @NotNull 9 | public static AliasResolver createInnerAliasResolver(@NotNull Project project) { 10 | return new InnerAliasResolver(project); 11 | } 12 | 13 | @NotNull 14 | public static AliasResolver createAnnotationResolver(@NotNull Project project) { 15 | return new AnnotationAliasResolver(project); 16 | } 17 | 18 | @NotNull 19 | public static AliasResolver createBeanResolver(@NotNull Project project) { 20 | return new BeanAliasResolver(project); 21 | } 22 | 23 | @NotNull 24 | public static AliasResolver createConfigPackageResolver(@NotNull Project project) { 25 | return new ConfigPackageAliasResolver(project); 26 | } 27 | 28 | @NotNull 29 | public static AliasResolver createSingleAliasResolver(@NotNull Project project) { 30 | return new SingleAliasResolver(project); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/alias/AnnotationAliasResolver.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.alias; 2 | 3 | import com.google.common.base.Function; 4 | import com.google.common.collect.Collections2; 5 | import com.google.common.collect.Sets; 6 | import com.intellij.openapi.project.Project; 7 | import com.intellij.psi.PsiClass; 8 | import com.intellij.psi.PsiElement; 9 | import com.intellij.psi.search.GlobalSearchScope; 10 | import com.intellij.psi.search.searches.AnnotatedElementsSearch; 11 | import com.tianlei.mybatis.annotation.Annotation; 12 | import com.tianlei.mybatis.util.JavaUtils; 13 | import org.jetbrains.annotations.NotNull; 14 | import org.jetbrains.annotations.Nullable; 15 | 16 | import java.util.Collection; 17 | import java.util.Collections; 18 | import java.util.Optional; 19 | import java.util.Set; 20 | 21 | public class AnnotationAliasResolver extends AliasResolver { 22 | 23 | private static final Function FUN = (Function) psiClass -> { 24 | Optional txt = JavaUtils.getAnnotationValueText(psiClass, Annotation.ALIAS); 25 | if (!txt.isPresent()) return null; 26 | AliasDesc ad = new AliasDesc(); 27 | ad.setAlias(txt.get()); 28 | ad.setClazz(psiClass); 29 | return ad; 30 | }; 31 | 32 | public AnnotationAliasResolver(Project project) { 33 | super(project); 34 | } 35 | 36 | public static final AnnotationAliasResolver getInstance(@NotNull Project project) { 37 | return project.getService(AnnotationAliasResolver.class); 38 | } 39 | 40 | @NotNull 41 | @Override 42 | public Set getClassAliasDescriptions(@Nullable PsiElement element) { 43 | Optional clazz = Annotation.ALIAS.toPsiClass(project); 44 | if (clazz.isPresent()) { 45 | Collection res = AnnotatedElementsSearch.searchPsiClasses(clazz.get(), GlobalSearchScope.allScope(project)).findAll(); 46 | return Sets.newHashSet(Collections2.transform(res, FUN)); 47 | } 48 | return Collections.emptySet(); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/alias/BeanAliasResolver.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.alias; 2 | 3 | import com.google.common.collect.Sets; 4 | import com.intellij.openapi.module.Module; 5 | import com.intellij.openapi.module.ModuleManager; 6 | import com.intellij.openapi.project.Project; 7 | import com.intellij.psi.PsiClass; 8 | import com.intellij.psi.PsiElement; 9 | import com.intellij.spring.CommonSpringModel; 10 | import com.intellij.spring.SpringManager; 11 | import com.intellij.spring.model.SpringBeanPointer; 12 | import com.intellij.spring.model.utils.SpringPropertyUtils; 13 | import com.intellij.spring.model.xml.beans.SpringPropertyDefinition; 14 | import com.tianlei.mybatis.util.JavaUtils; 15 | import org.jetbrains.annotations.NotNull; 16 | import org.jetbrains.annotations.Nullable; 17 | 18 | import java.util.Collection; 19 | import java.util.Optional; 20 | import java.util.Set; 21 | 22 | public class BeanAliasResolver extends PackageAliasResolver { 23 | 24 | private static final String MAPPER_ALIAS_PACKAGE_CLASS = "org.mybatis.spring.SqlSessionFactoryBean"; 25 | private static final String MAPPER_ALIAS_PROPERTY = "typeAliasesPackage"; 26 | private ModuleManager moduleManager; 27 | private SpringManager springManager; 28 | 29 | public BeanAliasResolver(Project project) { 30 | super(project); 31 | this.moduleManager = ModuleManager.getInstance(project); 32 | this.springManager = SpringManager.getInstance(project); 33 | } 34 | 35 | @NotNull 36 | @Override 37 | public Collection getPackages(@Nullable PsiElement element) { 38 | Set res = Sets.newHashSet(); 39 | for (Module module : moduleManager.getModules()) { 40 | for (CommonSpringModel springModel : springManager.getCombinedModel(module).getRelatedModels()) { 41 | addPackages(res, springModel); 42 | } 43 | } 44 | return res; 45 | } 46 | 47 | private void addPackages(Set res, CommonSpringModel springModel) { 48 | Optional sqlSessionFactoryClazzOpt = JavaUtils.findClazz(project, MAPPER_ALIAS_PACKAGE_CLASS); 49 | if (sqlSessionFactoryClazzOpt.isPresent()) { 50 | Collection domBeans = springModel.getAllCommonBeans(); 51 | PsiClass sqlSessionFactoryClazz = (PsiClass) sqlSessionFactoryClazzOpt.get(); 52 | 53 | for (Object domBean : domBeans) { 54 | SpringBeanPointer pointer = (SpringBeanPointer) domBean; 55 | PsiClass beanClass = pointer.getBeanClass(); 56 | if (beanClass != null && beanClass.equals(sqlSessionFactoryClazz)) { 57 | SpringPropertyDefinition basePackages = SpringPropertyUtils.findPropertyByName(pointer.getSpringBean(), MAPPER_ALIAS_PROPERTY); 58 | if (basePackages != null) { 59 | final String value = basePackages.getValueElement().getStringValue(); 60 | if (value != null) { 61 | res.add(value); 62 | } 63 | } 64 | } 65 | } 66 | 67 | } 68 | 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/alias/ConfigPackageAliasResolver.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.alias; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.intellij.openapi.project.Project; 5 | import com.intellij.psi.PsiElement; 6 | import com.intellij.util.Processor; 7 | import com.tianlei.mybatis.dom.model.Package; 8 | import com.tianlei.mybatis.util.MapperUtils; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | import java.util.ArrayList; 13 | import java.util.Collection; 14 | 15 | public class ConfigPackageAliasResolver extends PackageAliasResolver { 16 | 17 | public ConfigPackageAliasResolver(Project project) { 18 | super(project); 19 | } 20 | 21 | @NotNull 22 | @Override 23 | public Collection getPackages(@Nullable PsiElement element) { 24 | final ArrayList result = Lists.newArrayList(); 25 | MapperUtils.processConfiguredPackage(project, new Processor() { 26 | @Override 27 | public boolean process(Package pkg) { 28 | result.add(pkg.getName().getStringValue()); 29 | return true; 30 | } 31 | }); 32 | return result; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/alias/InnerAliasResolver.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.alias; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import com.intellij.openapi.project.Project; 5 | import com.intellij.psi.PsiElement; 6 | import com.tianlei.mybatis.util.JavaUtils; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | import java.util.Set; 11 | 12 | public class InnerAliasResolver extends AliasResolver { 13 | 14 | private final Set innerAliasDescs = ImmutableSet.of( 15 | AliasDesc.create(JavaUtils.findClazz(project, "java.lang.String").get(), "string"), 16 | AliasDesc.create(JavaUtils.findClazz(project, "java.lang.Byte").get(), "byte"), 17 | AliasDesc.create(JavaUtils.findClazz(project, "java.lang.Long").get(), "long"), 18 | AliasDesc.create(JavaUtils.findClazz(project, "java.lang.Short").get(), "short"), 19 | AliasDesc.create(JavaUtils.findClazz(project, "java.lang.Integer").get(), "int"), 20 | AliasDesc.create(JavaUtils.findClazz(project, "java.lang.Integer").get(), "integer"), 21 | AliasDesc.create(JavaUtils.findClazz(project, "java.lang.Double").get(), "double"), 22 | AliasDesc.create(JavaUtils.findClazz(project, "java.lang.Float").get(), "float"), 23 | AliasDesc.create(JavaUtils.findClazz(project, "java.lang.Boolean").get(), "boolean"), 24 | AliasDesc.create(JavaUtils.findClazz(project, "java.util.Date").get(), "date"), 25 | AliasDesc.create(JavaUtils.findClazz(project, "java.math.BigDecimal").get(), "decimal"), 26 | AliasDesc.create(JavaUtils.findClazz(project, "java.lang.Object").get(), "object"), 27 | AliasDesc.create(JavaUtils.findClazz(project, "java.util.Map").get(), "map"), 28 | AliasDesc.create(JavaUtils.findClazz(project, "java.util.HashMap").get(), "hashmap"), 29 | AliasDesc.create(JavaUtils.findClazz(project, "java.util.List").get(), "list"), 30 | AliasDesc.create(JavaUtils.findClazz(project, "java.util.ArrayList").get(), "arraylist"), 31 | AliasDesc.create(JavaUtils.findClazz(project, "java.util.Collection").get(), "collection"), 32 | AliasDesc.create(JavaUtils.findClazz(project, "java.util.Iterator").get(), "iterator") 33 | ); 34 | 35 | public InnerAliasResolver(Project project) { 36 | super(project); 37 | } 38 | 39 | @NotNull 40 | @Override 41 | public Set getClassAliasDescriptions(@Nullable PsiElement element) { 42 | return innerAliasDescs; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/alias/PackageAliasResolver.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.alias; 2 | 3 | import com.google.common.collect.Sets; 4 | import com.intellij.openapi.project.Project; 5 | import com.intellij.psi.JavaPsiFacade; 6 | import com.intellij.psi.PsiClass; 7 | import com.intellij.psi.PsiElement; 8 | import com.intellij.psi.PsiPackage; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | import java.util.Collection; 13 | import java.util.Set; 14 | 15 | public abstract class PackageAliasResolver extends AliasResolver { 16 | 17 | private JavaPsiFacade javaPsiFacade; 18 | 19 | public PackageAliasResolver(Project project) { 20 | super(project); 21 | this.javaPsiFacade = JavaPsiFacade.getInstance(project); 22 | } 23 | 24 | @NotNull 25 | @Override 26 | public Set getClassAliasDescriptions(@Nullable PsiElement element) { 27 | Set result = Sets.newHashSet(); 28 | for (String pkgName : getPackages(element)) { 29 | if (null == pkgName) { 30 | continue; 31 | } 32 | PsiPackage pkg = javaPsiFacade.findPackage(pkgName); 33 | if (null != pkg) { 34 | addAliasDesc(result, pkg); 35 | for (PsiPackage tmp : pkg.getSubPackages()) { 36 | addAliasDesc(result, tmp); 37 | } 38 | } 39 | } 40 | return result; 41 | } 42 | 43 | private void addAliasDesc(Set result, PsiPackage pkg) { 44 | for (PsiClass clazz : pkg.getClasses()) { 45 | addAliasDesc(result, clazz, clazz.getName()); 46 | } 47 | } 48 | 49 | @NotNull 50 | public abstract Collection getPackages(@Nullable PsiElement element); 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/alias/SingleAliasResolver.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.alias; 2 | 3 | import com.google.common.collect.Sets; 4 | import com.intellij.openapi.project.Project; 5 | import com.intellij.psi.PsiElement; 6 | import com.intellij.util.Processor; 7 | import com.tianlei.mybatis.dom.model.TypeAlias; 8 | import com.tianlei.mybatis.util.MapperUtils; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | import java.util.Set; 13 | 14 | public class SingleAliasResolver extends AliasResolver { 15 | 16 | public SingleAliasResolver(Project project) { 17 | super(project); 18 | } 19 | 20 | @NotNull 21 | @Override 22 | public Set getClassAliasDescriptions(@Nullable PsiElement element) { 23 | final Set result = Sets.newHashSet(); 24 | MapperUtils.processConfiguredTypeAliases(project, new Processor() { 25 | @Override 26 | public boolean process(TypeAlias typeAlias) { 27 | addAliasDesc(result, typeAlias.getType().getValue(), typeAlias.getAlias().getStringValue()); 28 | return true; 29 | } 30 | }); 31 | return result; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/annotation/Annotation.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.annotation; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import com.google.common.collect.Iterables; 5 | import com.google.common.collect.Maps; 6 | import com.intellij.openapi.project.Project; 7 | import com.intellij.psi.JavaPsiFacade; 8 | import com.intellij.psi.PsiClass; 9 | import com.intellij.psi.search.GlobalSearchScope; 10 | import org.jetbrains.annotations.NotNull; 11 | 12 | import java.util.Map; 13 | import java.util.Optional; 14 | import java.util.Set; 15 | 16 | public class Annotation implements Cloneable { 17 | 18 | public static final Annotation PARAM = new Annotation("@Param", "org.apache.ibatis.annotations.Param"); 19 | 20 | public static final Annotation SELECT = new Annotation("@Select", "org.apache.ibatis.annotations.Select"); 21 | 22 | public static final Annotation UPDATE = new Annotation("@Update", "org.apache.ibatis.annotations.Update"); 23 | 24 | public static final Annotation INSERT = new Annotation("@Insert", "org.apache.ibatis.annotations.Insert"); 25 | 26 | public static final Annotation DELETE = new Annotation("@Delete", "org.apache.ibatis.annotations.Delete"); 27 | 28 | public static final Annotation ALIAS = new Annotation("@Alias", "org.apache.ibatis.type.Alias"); 29 | 30 | public static final Annotation AUTOWIRED = new Annotation("@Autowired", "org.springframework.beans.factory.annotation.Autowired"); 31 | 32 | public static final Annotation RESOURCE = new Annotation("@Resource", "javax.annotation.Resource"); 33 | 34 | public static final Set STATEMENT_SYMMETRIES = ImmutableSet.of(SELECT, UPDATE, INSERT, DELETE); 35 | 36 | private final String label; 37 | 38 | private final String qualifiedName; 39 | 40 | private Map attributePairs; 41 | 42 | public interface AnnotationValue { 43 | } 44 | 45 | public static class StringValue implements AnnotationValue { 46 | 47 | private String value; 48 | 49 | public StringValue(@NotNull String value) { 50 | this.value = value; 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return "\"" + value + "\""; 56 | } 57 | 58 | } 59 | 60 | public Annotation(@NotNull String label, @NotNull String qualifiedName) { 61 | this.label = label; 62 | this.qualifiedName = qualifiedName; 63 | attributePairs = Maps.newHashMap(); 64 | } 65 | 66 | private Annotation addAttribute(String key, AnnotationValue value) { 67 | this.attributePairs.put(key, value); 68 | return this; 69 | } 70 | 71 | public Annotation withAttribute(@NotNull String key, @NotNull AnnotationValue value) { 72 | Annotation copy = this.clone(); 73 | copy.attributePairs = Maps.newHashMap(this.attributePairs); 74 | return copy.addAttribute(key, value); 75 | } 76 | 77 | public Annotation withValue(@NotNull AnnotationValue value) { 78 | return withAttribute("value", value); 79 | } 80 | 81 | @Override 82 | public String toString() { 83 | StringBuilder builder = new StringBuilder(label); 84 | if (!Iterables.isEmpty(attributePairs.entrySet())) { 85 | builder.append(setupAttributeText()); 86 | } 87 | return builder.toString(); 88 | } 89 | 90 | private String setupAttributeText() { 91 | Optional singleValue = getSingleValue(); 92 | return singleValue.isPresent() ? singleValue.get() : getComplexValue(); 93 | } 94 | 95 | private String getComplexValue() { 96 | StringBuilder builder = new StringBuilder("("); 97 | for (String key : attributePairs.keySet()) { 98 | builder.append(key); 99 | builder.append(" = "); 100 | builder.append(attributePairs.get(key).toString()); 101 | builder.append(", "); 102 | } 103 | builder.deleteCharAt(builder.length() - 1); 104 | builder.deleteCharAt(builder.length() - 1); 105 | builder.append(")"); 106 | return builder.toString(); 107 | } 108 | 109 | @NotNull 110 | public Optional toPsiClass(@NotNull Project project) { 111 | return Optional.ofNullable(JavaPsiFacade.getInstance(project).findClass(getQualifiedName(), GlobalSearchScope.allScope(project))); 112 | } 113 | 114 | private Optional getSingleValue() { 115 | try { 116 | String value = Iterables.getOnlyElement(attributePairs.keySet()); 117 | StringBuilder builder = new StringBuilder("("); 118 | builder.append(attributePairs.get(value).toString()); 119 | builder.append(")"); 120 | return Optional.of(builder.toString()); 121 | } catch (Exception e) { 122 | return Optional.empty(); 123 | } 124 | } 125 | 126 | @NotNull 127 | public String getLabel() { 128 | return label; 129 | } 130 | 131 | @NotNull 132 | public String getQualifiedName() { 133 | return qualifiedName; 134 | } 135 | 136 | @Override 137 | protected Annotation clone() { 138 | try { 139 | return (Annotation) super.clone(); 140 | } catch (CloneNotSupportedException e) { 141 | throw new IllegalStateException(); 142 | } 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/contributor/JavaMenthodCompletionContributor.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.contributor; 2 | 3 | import com.intellij.codeInsight.completion.CompletionContributor; 4 | import com.intellij.codeInsight.completion.CompletionParameters; 5 | import com.intellij.codeInsight.completion.CompletionResultSet; 6 | import com.intellij.codeInsight.completion.CompletionType; 7 | 8 | public class JavaMenthodCompletionContributor extends CompletionContributor { 9 | @Override 10 | public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet result) { 11 | if (parameters.getCompletionType() != CompletionType.BASIC) { 12 | return; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/contributor/SqlParamCompletionContributor.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.contributor; 2 | 3 | import com.intellij.codeInsight.completion.CompletionContributor; 4 | import com.intellij.codeInsight.completion.CompletionParameters; 5 | import com.intellij.codeInsight.completion.CompletionResultSet; 6 | import com.intellij.codeInsight.completion.CompletionType; 7 | import com.intellij.injected.editor.DocumentWindow; 8 | import com.intellij.lang.injection.InjectedLanguageManager; 9 | import com.intellij.psi.PsiElement; 10 | import com.intellij.psi.PsiFile; 11 | import com.tianlei.mybatis.dom.model.IdDomElement; 12 | import com.tianlei.mybatis.util.DomUtils; 13 | import com.tianlei.mybatis.util.MapperUtils; 14 | 15 | import java.util.List; 16 | import java.util.Optional; 17 | 18 | public class SqlParamCompletionContributor extends CompletionContributor { 19 | 20 | @Override 21 | public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet result) { 22 | if (parameters.getCompletionType() != CompletionType.BASIC) { 23 | return; 24 | } 25 | 26 | PsiElement position = parameters.getPosition(); 27 | PsiFile topLevelFile = position.getContainingFile().getOriginalFile(); 28 | if (DomUtils.isMybatisFile(topLevelFile)) { 29 | if (shouldAddElement(position.getContainingFile(), parameters.getOffset())) { 30 | process(topLevelFile, result, position); 31 | } 32 | } 33 | } 34 | 35 | private void process(PsiFile xmlFile, CompletionResultSet result, PsiElement position) { 36 | PsiFile psiFile = position.getContainingFile(); 37 | InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(position.getProject()); 38 | List documentWindows = injectedLanguageManager.getCachedInjectedDocumentsInRange(psiFile, position.getTextRange()); 39 | DocumentWindow documentWindow = documentWindows.isEmpty() ? null : documentWindows.get(0); 40 | if (null != documentWindow) { 41 | int offset = documentWindow.injectedToHost(position.getTextOffset()); 42 | Optional idDomElement = MapperUtils.findParentIdDomElement(xmlFile.findElementAt(offset)); 43 | if (idDomElement.isPresent()) { 44 | TestParamContributor.addElementForPsiParameter(position.getProject(), result, idDomElement.get()); 45 | result.stopHere(); 46 | } 47 | } 48 | } 49 | 50 | private boolean shouldAddElement(PsiFile file, int offset) { 51 | String text = file.getText(); 52 | for (int i = offset - 1; i > 0; i--) { 53 | char c = text.charAt(i); 54 | if (c == '{' && text.charAt(i - 1) == '#') return true; 55 | } 56 | return false; 57 | } 58 | } -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/contributor/TestParamContributor.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.contributor; 2 | 3 | import com.intellij.codeInsight.completion.*; 4 | import com.intellij.codeInsight.lookup.LookupElement; 5 | import com.intellij.codeInsight.lookup.LookupElementBuilder; 6 | import com.intellij.openapi.project.Project; 7 | import com.intellij.patterns.XmlPatterns; 8 | import com.intellij.psi.PsiElement; 9 | import com.intellij.psi.PsiMethod; 10 | import com.intellij.psi.PsiParameter; 11 | import com.intellij.util.ProcessingContext; 12 | import com.tianlei.mybatis.dom.model.IdDomElement; 13 | import com.tianlei.mybatis.annotation.Annotation; 14 | import com.tianlei.mybatis.util.Icons; 15 | import com.tianlei.mybatis.util.JavaUtils; 16 | import com.tianlei.mybatis.util.MapperUtils; 17 | import com.tianlei.mybatis.util.MybatisConstants; 18 | import org.jetbrains.annotations.NotNull; 19 | import org.jetbrains.annotations.Nullable; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | 23 | import java.util.Optional; 24 | 25 | public class TestParamContributor extends CompletionContributor { 26 | private static final Logger logger = LoggerFactory.getLogger(TestParamContributor.class); 27 | 28 | public TestParamContributor() { 29 | extend(CompletionType.BASIC, 30 | XmlPatterns.psiElement() 31 | .inside(XmlPatterns.xmlAttributeValue() 32 | .inside(XmlPatterns.xmlAttribute().withName("test"))), 33 | new CompletionProvider() { 34 | @Override 35 | protected void addCompletions( 36 | @NotNull final CompletionParameters parameters, 37 | final ProcessingContext context, 38 | @NotNull final CompletionResultSet result) { 39 | final PsiElement position = parameters.getPosition(); 40 | addElementForPsiParameter( 41 | position.getProject(), 42 | result, 43 | MapperUtils.findParentIdDomElement(position).orElse(null)); 44 | } 45 | }); 46 | } 47 | 48 | static void addElementForPsiParameter( 49 | @NotNull final Project project, 50 | @NotNull final CompletionResultSet result, 51 | @Nullable final IdDomElement element) { 52 | if (element == null) { 53 | return; 54 | } 55 | 56 | final PsiMethod method = JavaUtils.findMethod(project, element).orElse(null); 57 | 58 | if (method == null) { 59 | logger.info("psiMethod null"); 60 | return; 61 | } 62 | 63 | final PsiParameter[] parameters = method.getParameterList().getParameters(); 64 | 65 | // For a single parameter MyBatis uses its name, while for a multitude they're 66 | // named as param1, param2, etc. I'll check if the @Param annotation [value] is present 67 | // and eventually I'll use its text. 68 | if (parameters.length == 1) { 69 | final PsiParameter parameter = parameters[0]; 70 | result.addElement(buildLookupElementWithIcon( 71 | parameter.getName(), 72 | parameter.getType().getPresentableText())); 73 | } else { 74 | for (int i = 0; i < parameters.length; i++) { 75 | final PsiParameter parameter = parameters[i]; 76 | final Optional value = JavaUtils.getAnnotationValueText(parameter, Annotation.PARAM); 77 | result.addElement(buildLookupElementWithIcon( 78 | value.isPresent() ? value.get() : "param" + (i + 1), 79 | parameter.getType().getPresentableText())); 80 | } 81 | } 82 | } 83 | 84 | private static LookupElement buildLookupElementWithIcon( 85 | final String parameterName, 86 | final String parameterType) { 87 | return PrioritizedLookupElement.withPriority( 88 | LookupElementBuilder.create(parameterName) 89 | .withTypeText(parameterType) 90 | .withIcon(Icons.PARAM_COMPLETION_ICON), 91 | MybatisConstants.PRIORITY); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/definitionsearch/MapperDefinitionSearch.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.definitionsearch; 2 | 3 | import com.intellij.openapi.application.QueryExecutorBase; 4 | import com.intellij.psi.PsiTypeParameterListOwner; 5 | import com.intellij.psi.search.searches.DefinitionsScopedSearch; 6 | import com.intellij.psi.xml.XmlElement; 7 | import com.intellij.util.Processor; 8 | import com.intellij.util.xml.DomElement; 9 | import com.tianlei.mybatis.service.JavaService; 10 | import org.jetbrains.annotations.NotNull; 11 | 12 | public class MapperDefinitionSearch extends QueryExecutorBase { 13 | 14 | public MapperDefinitionSearch() { 15 | super(true); 16 | } 17 | 18 | @Override 19 | public void processQuery(@NotNull DefinitionsScopedSearch.SearchParameters queryParameters, @NotNull Processor consumer) { 20 | if (!(queryParameters.getElement() instanceof PsiTypeParameterListOwner)) return; 21 | Processor processor = domElement -> consumer.process(domElement.getXmlElement()); 22 | JavaService.getInstance(queryParameters.getProject()).process(queryParameters.getElement(), processor); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/MapperBacktrackingUtils.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom; 2 | 3 | import com.intellij.psi.PsiClass; 4 | import com.intellij.psi.util.PsiTreeUtil; 5 | import com.intellij.psi.xml.XmlAttributeValue; 6 | import com.intellij.psi.xml.XmlElement; 7 | import com.intellij.psi.xml.XmlTag; 8 | import com.intellij.util.xml.DomElement; 9 | import com.intellij.util.xml.DomUtil; 10 | import com.tianlei.mybatis.dom.model.Association; 11 | import com.tianlei.mybatis.dom.model.Collection; 12 | import com.tianlei.mybatis.dom.model.ParameterMap; 13 | import com.tianlei.mybatis.dom.model.ResultMap; 14 | import org.jetbrains.annotations.NotNull; 15 | 16 | import java.util.Optional; 17 | 18 | public final class MapperBacktrackingUtils { 19 | 20 | private MapperBacktrackingUtils() { 21 | throw new UnsupportedOperationException(); 22 | } 23 | 24 | public static Optional getPropertyClazz(XmlAttributeValue attributeValue) { 25 | DomElement domElement = DomUtil.getDomElement(attributeValue); 26 | if (null == domElement) { 27 | return Optional.empty(); 28 | } 29 | 30 | Collection collection = DomUtil.getParentOfType(domElement, Collection.class, true); 31 | if (null != collection && !isWithinSameTag(collection, attributeValue)) { 32 | return Optional.ofNullable(collection.getOfType().getValue()); 33 | } 34 | 35 | Association association = DomUtil.getParentOfType(domElement, Association.class, true); 36 | if (null != association && !isWithinSameTag(association, attributeValue)) { 37 | return Optional.ofNullable(association.getJavaType().getValue()); 38 | } 39 | 40 | ParameterMap parameterMap = DomUtil.getParentOfType(domElement, ParameterMap.class, true); 41 | if (null != parameterMap && !isWithinSameTag(parameterMap, attributeValue)) { 42 | return Optional.ofNullable(parameterMap.getType().getValue()); 43 | } 44 | 45 | ResultMap resultMap = DomUtil.getParentOfType(domElement, ResultMap.class, true); 46 | if (null != resultMap && !isWithinSameTag(resultMap, attributeValue)) { 47 | return Optional.ofNullable(resultMap.getType().getValue()); 48 | } 49 | return Optional.empty(); 50 | } 51 | 52 | public static boolean isWithinSameTag(@NotNull DomElement domElement, @NotNull XmlElement xmlElement) { 53 | XmlTag xmlTag = PsiTreeUtil.getParentOfType(xmlElement, XmlTag.class); 54 | return null != xmlElement && domElement.getXmlTag().equals(xmlTag); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/converter/AliasConverter.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.converter; 2 | 3 | import com.intellij.openapi.util.text.StringUtil; 4 | import com.intellij.psi.PsiClass; 5 | import com.intellij.psi.PsiElement; 6 | import com.intellij.psi.PsiReference; 7 | import com.intellij.psi.search.GlobalSearchScope; 8 | import com.intellij.psi.xml.XmlAttributeValue; 9 | import com.intellij.util.xml.*; 10 | import com.tianlei.mybatis.alias.AliasClassReference; 11 | import com.tianlei.mybatis.alias.AliasFacade; 12 | import com.tianlei.mybatis.util.MybatisConstants; 13 | import org.jetbrains.annotations.NonNls; 14 | import org.jetbrains.annotations.NotNull; 15 | import org.jetbrains.annotations.Nullable; 16 | 17 | public class AliasConverter extends ConverterAdaptor implements CustomReferenceConverter { 18 | 19 | private PsiClassConverter delegate = new PsiClassConverter(); 20 | 21 | @Nullable 22 | @Override 23 | public PsiClass fromString(@Nullable @NonNls String s, ConvertContext context) { 24 | if (StringUtil.isEmptyOrSpaces(s)) return null; 25 | if (!s.contains(MybatisConstants.DOT_SEPARATOR)) { 26 | return AliasFacade.getInstance(context.getProject()).findPsiClass(context.getXmlElement(), s).orElse(null); 27 | } 28 | return DomJavaUtil.findClass(s.trim(), context.getFile(), context.getModule(), GlobalSearchScope.allScope(context.getProject())); 29 | } 30 | 31 | @Nullable 32 | @Override 33 | public String toString(@Nullable PsiClass psiClass, ConvertContext context) { 34 | return delegate.toString(psiClass, context); 35 | } 36 | 37 | @NotNull 38 | @Override 39 | public PsiReference[] createReferences(GenericDomValue value, PsiElement element, ConvertContext context) { 40 | if (((XmlAttributeValue) element).getValue().contains(MybatisConstants.DOT_SEPARATOR)) { 41 | return delegate.createReferences(value, element, context); 42 | } else { 43 | return new PsiReference[]{new AliasClassReference((XmlAttributeValue) element)}; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/converter/ConverterAdaptor.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.converter; 2 | 3 | import com.intellij.util.xml.ConvertContext; 4 | import com.intellij.util.xml.ResolvingConverter; 5 | import org.jetbrains.annotations.NonNls; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.util.Collection; 10 | import java.util.Collections; 11 | 12 | public abstract class ConverterAdaptor extends ResolvingConverter { 13 | 14 | @NotNull 15 | @Override 16 | public Collection getVariants(ConvertContext context) { 17 | return Collections.emptyList(); 18 | } 19 | 20 | @Nullable 21 | @Override 22 | public String toString(@Nullable T t, ConvertContext context) { 23 | return null; 24 | } 25 | 26 | @Nullable 27 | @Override 28 | public T fromString(@Nullable @NonNls String s, ConvertContext context) { 29 | return null; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/converter/DaoMethodConverter.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.converter; 2 | 3 | import com.intellij.psi.PsiMethod; 4 | import com.intellij.util.xml.ConvertContext; 5 | import com.tianlei.mybatis.dom.model.Mapper; 6 | import com.tianlei.mybatis.util.JavaUtils; 7 | import com.tianlei.mybatis.util.MapperUtils; 8 | import org.jetbrains.annotations.NonNls; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | public class DaoMethodConverter extends ConverterAdaptor { 12 | 13 | @Nullable 14 | @Override 15 | public PsiMethod fromString(@Nullable @NonNls String id, ConvertContext context) { 16 | Mapper mapper = MapperUtils.getMapper(context.getInvocationElement()); 17 | return JavaUtils.findMethod(context.getProject(), MapperUtils.getNamespace(mapper), id, null).orElse(null); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/converter/ParameterMapConverter.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.converter; 2 | 3 | import com.intellij.util.xml.ConvertContext; 4 | import com.tianlei.mybatis.dom.model.IdDomElement; 5 | import com.tianlei.mybatis.dom.model.Mapper; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.util.Collection; 10 | 11 | public class ParameterMapConverter extends IdBasedTagConverter { 12 | 13 | @NotNull 14 | @Override 15 | public Collection getComparisons(@Nullable Mapper mapper, 16 | ConvertContext context) { 17 | return mapper.getParameterMaps(); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/converter/PropertyConverter.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.converter; 2 | 3 | import com.intellij.psi.ElementManipulators; 4 | import com.intellij.psi.PsiElement; 5 | import com.intellij.psi.PsiReference; 6 | import com.intellij.psi.xml.XmlAttributeValue; 7 | import com.intellij.util.xml.*; 8 | import com.tianlei.mybatis.reference.ResultPropertyReferenceSet; 9 | import org.jetbrains.annotations.NonNls; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.jetbrains.annotations.Nullable; 12 | 13 | public class PropertyConverter extends ConverterAdaptor implements CustomReferenceConverter { 14 | 15 | @NotNull 16 | @Override 17 | public PsiReference[] createReferences(GenericDomValue value, PsiElement element, ConvertContext context) { 18 | final String s = value.getStringValue(); 19 | if (s == null) { 20 | return PsiReference.EMPTY_ARRAY; 21 | } 22 | return new ResultPropertyReferenceSet(s, element, ElementManipulators.getOffsetInElement(element)).getPsiReferences(); 23 | } 24 | 25 | @Nullable 26 | @Override 27 | public XmlAttributeValue fromString(@Nullable @NonNls String s, ConvertContext context) { 28 | DomElement ctxElement = context.getInvocationElement(); 29 | return ctxElement instanceof GenericAttributeValue ? ((GenericAttributeValue) ctxElement).getXmlAttributeValue() : null; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/converter/ResultMapConverter.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.converter; 2 | 3 | import com.google.common.base.Predicate; 4 | import com.google.common.collect.Collections2; 5 | import com.intellij.util.xml.ConvertContext; 6 | import com.intellij.util.xml.DomElement; 7 | import com.tianlei.mybatis.dom.model.IdDomElement; 8 | import com.tianlei.mybatis.dom.model.Mapper; 9 | import com.tianlei.mybatis.dom.model.ResultMap; 10 | import com.tianlei.mybatis.util.MapperUtils; 11 | import org.jetbrains.annotations.NotNull; 12 | import org.jetbrains.annotations.Nullable; 13 | 14 | import java.util.Collection; 15 | 16 | public class ResultMapConverter extends IdBasedTagConverter { 17 | 18 | @NotNull 19 | @Override 20 | public Collection getComparisons(@Nullable Mapper mapper, ConvertContext context) { 21 | DomElement invocationElement = context.getInvocationElement(); 22 | if (isContextElementOfResultMap(mapper, invocationElement)) { 23 | return doFilterResultMapItself(mapper, (ResultMap) invocationElement.getParent()); 24 | } else { 25 | return mapper.getResultMaps(); 26 | } 27 | } 28 | 29 | private boolean isContextElementOfResultMap(Mapper mapper, DomElement invocationElement) { 30 | return MapperUtils.isMapperWithSameNamespace(MapperUtils.getMapper(invocationElement), mapper) 31 | && invocationElement.getParent() instanceof ResultMap; 32 | } 33 | 34 | private Collection doFilterResultMapItself(Mapper mapper, final ResultMap resultMap) { 35 | return Collections2.filter(mapper.getResultMaps(), new Predicate() { 36 | @Override 37 | public boolean apply(ResultMap input) { 38 | return !MapperUtils.getId(input).equals(MapperUtils.getId(resultMap)); 39 | } 40 | }); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/converter/SqlConverter.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.converter; 2 | 3 | import com.intellij.util.xml.ConvertContext; 4 | import com.tianlei.mybatis.dom.model.IdDomElement; 5 | import com.tianlei.mybatis.dom.model.Mapper; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | import java.util.Collection; 10 | 11 | public class SqlConverter extends IdBasedTagConverter { 12 | 13 | @NotNull 14 | @Override 15 | public Collection getComparisons(@Nullable Mapper mapper, ConvertContext context) { 16 | return mapper.getSqls(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/description/ConfigurationDescription.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.description; 2 | 3 | import com.intellij.openapi.module.Module; 4 | import com.intellij.psi.xml.XmlFile; 5 | import com.intellij.util.xml.DomFileDescription; 6 | import com.tianlei.mybatis.dom.model.Configuration; 7 | import com.tianlei.mybatis.util.DomUtils; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | public class ConfigurationDescription extends DomFileDescription { 12 | 13 | public ConfigurationDescription() { 14 | super(Configuration.class, "configuration"); 15 | } 16 | 17 | @Override 18 | public boolean isMyFile(@NotNull XmlFile file, @Nullable Module module) { 19 | return DomUtils.isMybatisConfigurationFile(file); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/description/MapperDescription.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.description; 2 | 3 | import com.intellij.openapi.module.Module; 4 | import com.intellij.psi.xml.XmlFile; 5 | import com.intellij.util.xml.DomFileDescription; 6 | import com.intellij.util.xml.MergingFileDescription; 7 | import com.tianlei.mybatis.dom.model.Mapper; 8 | import com.tianlei.mybatis.util.DomUtils; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | public class MapperDescription extends DomFileDescription { 13 | 14 | public MapperDescription() { 15 | super(Mapper.class, "mapper"); 16 | } 17 | 18 | @Override 19 | public boolean isMyFile(@NotNull XmlFile file, @Nullable Module module) { 20 | return DomUtils.isMybatisFile(file); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Arg.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.util.xml.DomElement; 4 | 5 | public interface Arg extends DomElement { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Association.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.psi.PsiClass; 4 | import com.intellij.util.xml.Attribute; 5 | import com.intellij.util.xml.Convert; 6 | import com.intellij.util.xml.GenericAttributeValue; 7 | import com.tianlei.mybatis.dom.converter.AliasConverter; 8 | import org.jetbrains.annotations.NotNull; 9 | 10 | public interface Association extends GroupFour, ResultMapGroup, PropertyGroup { 11 | 12 | @NotNull 13 | @Attribute("javaType") 14 | @Convert(AliasConverter.class) 15 | GenericAttributeValue getJavaType(); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Bean.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.util.xml.DomElement; 4 | import com.intellij.util.xml.SubTagList; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | import java.util.List; 8 | 9 | public interface Bean extends DomElement { 10 | 11 | @NotNull 12 | @SubTagList("property") 13 | List getBeanProperties(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/BeanProperty.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.util.xml.Attribute; 4 | import com.intellij.util.xml.DomElement; 5 | import com.intellij.util.xml.GenericAttributeValue; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | public interface BeanProperty extends DomElement { 9 | 10 | @NotNull 11 | @Attribute("name") 12 | GenericAttributeValue getName(); 13 | 14 | @NotNull 15 | @Attribute("value") 16 | GenericAttributeValue getValue(); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Beans.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.util.xml.DomElement; 4 | import com.intellij.util.xml.SubTagList; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | import java.util.List; 8 | 9 | public interface Beans extends DomElement { 10 | 11 | @NotNull 12 | @SubTagList("bean") 13 | List getBeans(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Bind.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.util.xml.DomElement; 4 | 5 | public interface Bind extends DomElement { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Cache.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.util.xml.DomElement; 4 | import com.intellij.util.xml.SubTagList; 5 | 6 | import java.util.List; 7 | 8 | public interface Cache extends DomElement { 9 | 10 | @SubTagList("property") 11 | List getProperties(); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/CacheRef.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.util.xml.DomElement; 4 | 5 | public interface CacheRef extends DomElement { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Case.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | public interface Case extends GroupFour { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Choose.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.util.xml.DomElement; 4 | import com.intellij.util.xml.Required; 5 | import com.intellij.util.xml.SubTag; 6 | import com.intellij.util.xml.SubTagList; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | import java.util.List; 10 | 11 | public interface Choose extends DomElement { 12 | 13 | @NotNull 14 | @Required 15 | @SubTagList("when") 16 | List getWhens(); 17 | 18 | @SubTag("otherwise") 19 | Otherwise getOtherwise(); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Collection.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.psi.PsiClass; 4 | import com.intellij.util.xml.Attribute; 5 | import com.intellij.util.xml.Convert; 6 | import com.intellij.util.xml.GenericAttributeValue; 7 | import com.tianlei.mybatis.dom.converter.AliasConverter; 8 | import org.jetbrains.annotations.NotNull; 9 | 10 | public interface Collection extends GroupFour, ResultMapGroup, PropertyGroup { 11 | 12 | @NotNull 13 | @Attribute("ofType") 14 | @Convert(AliasConverter.class) 15 | GenericAttributeValue getOfType(); 16 | 17 | } -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Configuration.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.util.xml.DomElement; 4 | import com.intellij.util.xml.SubTagList; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | import java.util.List; 8 | 9 | public interface Configuration extends DomElement { 10 | 11 | @NotNull 12 | @SubTagList("typeAliases") 13 | List getTypeAliases(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Constructor.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.util.xml.DomElement; 4 | import com.intellij.util.xml.SubTagList; 5 | 6 | import java.util.List; 7 | 8 | public interface Constructor extends DomElement { 9 | 10 | @SubTagList("arg") 11 | List getArgs(); 12 | 13 | @SubTagList("idArg") 14 | List getIdArgs(); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Delete.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | public interface Delete extends GroupTwo { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Discriminator.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.util.xml.DomElement; 4 | import com.intellij.util.xml.Required; 5 | import com.intellij.util.xml.SubTagList; 6 | 7 | import java.util.List; 8 | 9 | public interface Discriminator extends DomElement { 10 | 11 | @Required 12 | @SubTagList("case") 13 | List getCases(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Foreach.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | public interface Foreach extends GroupOne { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/GroupFour.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.util.xml.DomElement; 4 | import com.intellij.util.xml.SubTag; 5 | import com.intellij.util.xml.SubTagList; 6 | 7 | import java.util.List; 8 | 9 | public interface GroupFour extends DomElement { 10 | 11 | @SubTag("constructor") 12 | Constructor getConstructor(); 13 | 14 | @SubTagList("id") 15 | List getIds(); 16 | 17 | @SubTagList("result") 18 | List getResults(); 19 | 20 | @SubTagList("association") 21 | List getAssociations(); 22 | 23 | @SubTagList("collection") 24 | List getCollections(); 25 | 26 | @SubTag("discriminator") 27 | Discriminator getDiscriminator(); 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/GroupOne.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.util.xml.DomElement; 4 | import com.intellij.util.xml.SubTagList; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | import java.util.List; 8 | 9 | public interface GroupOne extends DomElement { 10 | 11 | @NotNull 12 | @SubTagList("include") 13 | List getIncludes(); 14 | 15 | @NotNull 16 | @SubTagList("trim") 17 | List getTrims(); 18 | 19 | @NotNull 20 | @SubTagList("where") 21 | List getWheres(); 22 | 23 | @NotNull 24 | @SubTagList("set") 25 | List getSets(); 26 | 27 | @NotNull 28 | @SubTagList("foreach") 29 | List getForeachs(); 30 | 31 | @NotNull 32 | @SubTagList("choose") 33 | List getChooses(); 34 | 35 | @NotNull 36 | @SubTagList("if") 37 | List getIfs(); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/GroupThree.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.util.xml.SubTagList; 4 | 5 | import java.util.List; 6 | 7 | public interface GroupThree extends GroupTwo { 8 | 9 | @SubTagList("selectKey") 10 | List getSelectKey(); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/GroupTwo.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.psi.PsiClass; 4 | import com.intellij.psi.xml.XmlTag; 5 | import com.intellij.util.xml.Attribute; 6 | import com.intellij.util.xml.Convert; 7 | import com.intellij.util.xml.GenericAttributeValue; 8 | import com.intellij.util.xml.SubTagList; 9 | import com.tianlei.mybatis.dom.converter.AliasConverter; 10 | import com.tianlei.mybatis.dom.converter.DaoMethodConverter; 11 | import com.tianlei.mybatis.dom.converter.ParameterMapConverter; 12 | import org.jetbrains.annotations.NotNull; 13 | 14 | import java.util.List; 15 | 16 | public interface GroupTwo extends GroupOne, IdDomElement { 17 | 18 | @SubTagList("bind") 19 | List getBinds(); 20 | 21 | @NotNull 22 | @Attribute("parameterMap") 23 | @Convert(ParameterMapConverter.class) 24 | GenericAttributeValue getParameterMap(); 25 | 26 | @Attribute("id") 27 | @Convert(DaoMethodConverter.class) 28 | GenericAttributeValue getId(); 29 | 30 | @NotNull 31 | @Attribute("parameterType") 32 | @Convert(AliasConverter.class) 33 | GenericAttributeValue getParameterType(); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Id.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | public interface Id extends PropertyGroup { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/IdArg.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.util.xml.DomElement; 4 | 5 | public interface IdArg extends DomElement { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/IdDomElement.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.util.xml.*; 4 | 5 | public interface IdDomElement extends DomElement { 6 | 7 | @Required 8 | @NameValue 9 | @Attribute("id") 10 | GenericAttributeValue getId(); 11 | 12 | void setValue(String content); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/If.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | public interface If extends GroupOne { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Include.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.psi.xml.XmlTag; 4 | import com.intellij.util.xml.Attribute; 5 | import com.intellij.util.xml.Convert; 6 | import com.intellij.util.xml.DomElement; 7 | import com.intellij.util.xml.GenericAttributeValue; 8 | import com.tianlei.mybatis.dom.converter.SqlConverter; 9 | 10 | public interface Include extends DomElement { 11 | 12 | @Attribute("refid") 13 | @Convert(SqlConverter.class) 14 | GenericAttributeValue getRefId(); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Insert.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | 4 | public interface Insert extends GroupThree { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/tianlei/mybatis/dom/model/Mapper.java: -------------------------------------------------------------------------------- 1 | package com.tianlei.mybatis.dom.model; 2 | 3 | import com.intellij.util.xml.*; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.util.List; 7 | 8 | public interface Mapper extends DomElement { 9 | 10 | @NotNull 11 | @SubTagsList({"insert", "update", "delete", "select"}) 12 | List getDaoElements(); 13 | 14 | @Required 15 | @NameValue 16 | @NotNull 17 | @Attribute("namespace") 18 | GenericAttributeValue getNamespace(); 19 | 20 | @NotNull 21 | @SubTagList("resultMap") 22 | List getResultMaps(); 23 | 24 | @NotNull 25 | @SubTagList("parameterMap") 26 | List getParameterMaps(); 27 | 28 | @NotNull 29 | @SubTagList("sql") 30 | List getSqls(); 31 | 32 | @NotNull 33 | @SubTagList("insert") 34 | List getInserts(); 35 | 36 | @NotNull 37 | @SubTagList("update") 38 | List getUpdates(); 39 | 40 | @NotNull 41 | @SubTagList("delete") 42 | List getDeletes(); 43 | 44 | @NotNull 45 | @SubTagList("select") 46 | List