├── .gitignore ├── .idea ├── libraries │ ├── com_google_guava_guava_18_0.xml │ └── mybatis_generator_core_1_3_5.xml ├── mybatis-plugin.zip └── snapshot │ ├── DeepinScrot-2141.png │ ├── screenshot_16384.png │ ├── screenshot_16385.png │ ├── screenshot_16386.png │ ├── screenshot_16801.png │ └── screenshot_16802.png ├── README.md ├── lib ├── guava-18.0-sources.jar ├── guava-18.0.jar └── mybatis-generator-core-1.3.5.jar ├── resources ├── META-INF │ └── plugin.xml ├── icons │ └── mybatis │ │ ├── generate.png │ │ ├── generate@2x.png │ │ ├── generate@2x_dark.png │ │ ├── generate_dark.png │ │ ├── navigateDown.png │ │ ├── navigateDown@2x.png │ │ ├── navigateDown@2x_dark.png │ │ ├── navigateDown_dark.png │ │ ├── navigateUp.png │ │ ├── navigateUp@2x.png │ │ ├── navigateUp@2x_dark.png │ │ └── navigateUp_dark.png ├── inspectionDescriptions │ ├── Mappers.html │ ├── MybatisMapper.html │ └── TypeAliases.html ├── intentionDescriptions │ ├── DeleteGenerateIntention │ │ ├── after.generation.template │ │ ├── before.generation.template │ │ └── description.html │ ├── InsertGenerateIntention │ │ ├── after.generation.template │ │ ├── before.generation.template │ │ └── description.html │ ├── MapperGenerateIntention │ │ ├── after.generation.template │ │ ├── before.generation.template │ │ └── description.html │ ├── SelectGenerateIntention │ │ ├── after.generation.template │ │ ├── before.generation.template │ │ └── description.html │ └── UpdateGenerateIntention │ │ ├── after.generation.template │ │ ├── before.generation.template │ │ └── description.html └── velocity │ ├── template │ └── mapper.vm │ └── velocity.properties └── src └── org └── qunar └── plugin ├── action └── DebugAction.java ├── bean └── ModuleSetting.java ├── mybatis ├── action │ └── SqlGenerateAction.java ├── bean │ ├── Annotation.java │ ├── IdDomElement.java │ ├── IdRefMethodDomElement.java │ ├── IdRefStringDomElement.java │ ├── config │ │ ├── Configuration.java │ │ ├── Mapper.java │ │ ├── Mappers.java │ │ ├── Package.java │ │ ├── TypeAlias.java │ │ └── TypeAliases.java │ ├── mapper │ │ ├── Cache.java │ │ ├── CacheRef.java │ │ ├── Delete.java │ │ ├── Insert.java │ │ ├── Mapper.java │ │ ├── ParameterMap.java │ │ ├── ResultMap.java │ │ ├── Select.java │ │ ├── Sql.java │ │ ├── Statement.java │ │ └── Update.java │ └── model │ │ ├── CreateTableDdl.java │ │ ├── DbColumn.java │ │ ├── DbForeignKey.java │ │ ├── DbIndex.java │ │ └── DbKey.java ├── contributor │ ├── MapperInclude2SqlReferenceContributor.java │ ├── MapperResultMapAttrReferenceContributor.java │ ├── RelatedFilePathReferenceContributor.java │ ├── StatementParamsCompletionContributor.java │ └── StatementParamsReferenceContributor.java ├── converter │ ├── MapperMethodConverter.java │ ├── PathFileConverter.java │ └── TypeAliasConverter.java ├── description │ ├── ConfigurationDescription.java │ └── MapperDescription.java ├── generator │ ├── AbstractGenerator.java │ ├── JavaGenerator.java │ ├── XmlGenerator.java │ └── XmlVelocityGenerator.java ├── inspection │ ├── MybatisMapperInspection.java │ └── config │ │ ├── AbstractConfigInspection.java │ │ ├── MappersInspection.java │ │ └── TypeAliasesInspection.java ├── intention │ ├── MapperGenerateIntention.java │ └── statement │ │ ├── DeleteGenerateIntention.java │ │ ├── InsertGenerateIntention.java │ │ ├── SelectGenerateIntention.java │ │ ├── StatementGenerateIntention.java │ │ └── UpdateGenerateIntention.java ├── linemarker │ ├── AbstractMapperMakerProvider.java │ ├── Java2XmlLineMarkerProvider.java │ └── Xml2JavaLineMarkerProvider.java ├── query │ └── MapperXmlInheritorsSearch.java ├── reference │ ├── ClassPathRelatedFileReference.java │ ├── MapperAttr2ResultMapReference.java │ ├── MapperIdAttrRefXmlTagReference.java │ ├── MapperInclude2SqlReference.java │ ├── StatementParamsReference.java │ └── TypeAliasNameReference.java ├── typehandler │ └── MapperSqlParamTypedHandler.java ├── ui │ ├── CreateMapperXmlDialog.form │ └── CreateMapperXmlDialog.java └── util │ ├── ConfigConfHolder.java │ ├── DbDdlParser.java │ ├── DomElements.java │ ├── MapperConfHolder.java │ ├── ParamPropertyHelper.java │ ├── TypeAliasResolver.java │ └── domchecker │ ├── DeleteChecker.java │ ├── InsertChecker.java │ ├── MappersChecker.java │ ├── SelectChecker.java │ ├── StatementChecker.java │ ├── TypeAliasesChecker.java │ └── UpdateChecker.java ├── service ├── DomParseService.java ├── EditorService.java ├── JavaService.java └── TypeAliasService.java └── util ├── CodeFormatter.java ├── ConfHolder.java ├── DomChecker.java ├── Icons.java ├── Inspections.java ├── Javas.java ├── Modules.java ├── Springs.java ├── Strings.java └── XmlUtils.java /.gitignore: -------------------------------------------------------------------------------- 1 | # kdiff3 ignore 2 | *.orig 3 | 4 | # maven ignore 5 | target/ 6 | 7 | # eclipse ignore 8 | .settings/ 9 | .project 10 | .classpath 11 | 12 | # idea ignore 13 | .idea/copyright 14 | .idea/dictionaries 15 | .idea/inspectionProfiles 16 | .idea/*.xml 17 | *.ipr 18 | *.iml 19 | *.iws 20 | 21 | # temp ignore 22 | *.log 23 | *.cache 24 | *.diff 25 | *.patch 26 | *.tmp 27 | 28 | # system ignore 29 | .DS_Store 30 | Thumbs.db 31 | 32 | # package ignore (optional) 33 | # *.jar 34 | # *.war 35 | # *.zip 36 | # *.tar 37 | # *.tar.gz 38 | out/ 39 | 40 | -------------------------------------------------------------------------------- /.idea/libraries/com_google_guava_guava_18_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/libraries/mybatis_generator_core_1_3_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/mybatis-plugin.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/.idea/mybatis-plugin.zip -------------------------------------------------------------------------------- /.idea/snapshot/DeepinScrot-2141.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/.idea/snapshot/DeepinScrot-2141.png -------------------------------------------------------------------------------- /.idea/snapshot/screenshot_16384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/.idea/snapshot/screenshot_16384.png -------------------------------------------------------------------------------- /.idea/snapshot/screenshot_16385.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/.idea/snapshot/screenshot_16385.png -------------------------------------------------------------------------------- /.idea/snapshot/screenshot_16386.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/.idea/snapshot/screenshot_16386.png -------------------------------------------------------------------------------- /.idea/snapshot/screenshot_16801.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/.idea/snapshot/screenshot_16801.png -------------------------------------------------------------------------------- /.idea/snapshot/screenshot_16802.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/.idea/snapshot/screenshot_16802.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | {toc} 2 | 3 | # [提供打包插件jar](.idea/mybatis-plugin.jar) 4 | 5 | ## Mybatis Plugin For IDEA 6 | 7 | ### 提供的功能 8 | 1. mybatis接口和xml跳转、等内部节点的关联跳转 9 | 2. mybatis的configuration、mapper文件校验,解析typeAliases等 10 | 3. 解析spring mybatis集成配置 11 | 3. mybatis自动代码提示,如:id、resultMap、${}、#{}等 12 | 4. mapper方法xml跳转、#{}${}参数跳转 13 | 5. and more... 14 | 15 | ### 2016.12.05 v1.4.2更新 16 | 1. \#{} \${}参数跳转支持原始类型 17 | 2. 修复isMybatis方法可能死循环的问题 18 | 3. 解析module配置,获取resource路径(之前通过名称判断) 19 | 20 | ### 2016.12.03 v1.4.0更新 21 | 1. 增加interface创建xml文件intention, 及ui dialog 22 | 2. 增加interface方法创建xml statement intention 23 | 3. 增加xml文件中#{} ${}参数的关联跳转 24 | 4. 修复spring bean name重复问题 25 | 5. 修复mapper配置缓存没生效的问题 26 | 27 | ### 插件截图 28 | 29 | ![Alt text](.idea/snapshot/DeepinScrot-2141.png) 30 | 31 | ![Alt text](.idea/snapshot/screenshot_16384.png) 32 | 33 | ![Alt text](.idea/snapshot/screenshot_16385.png) 34 | 35 | ![Alt text](.idea/snapshot/screenshot_16386.png) 36 | 37 | ![Alt_text](.idea/snapshot/screenshot_16802.png) 38 | 39 | ![Alt_text](.idea/snapshot/screenshot_16801.png) 40 | 41 | -------------------------------------------------------------------------------- /lib/guava-18.0-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/lib/guava-18.0-sources.jar -------------------------------------------------------------------------------- /lib/guava-18.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/lib/guava-18.0.jar -------------------------------------------------------------------------------- /lib/mybatis-generator-core-1.3.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/lib/mybatis-generator-core-1.3.5.jar -------------------------------------------------------------------------------- /resources/META-INF/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | common.plugin.extension 4 | Mybatis Tools 5 | v1.4.7 6 | Qunar.com, 聪明你的旅行 7 | 8 | Add some framework support, such as mybatis etc.

10 |

11 | depend on intellij'spring plugin, not support 12 | intellij community、Android Studio version so far
13 |

14 | ]]>
15 | 16 | v1.4.7

18 | 19 |
  • rebuild and package
  • 20 | 21 |

    v1.4.6

    22 | 23 |
  • bug fix
  • 24 | 25 | ]]> 26 |
    27 | 28 | 29 | 30 | com.intellij.modules.lang 31 | 32 | com.intellij.spring 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 48 | 51 | 54 | 55 | 57 | 59 | 60 | 62 | 63 | 64 | 65 | 66 | 67 | 69 | 71 | 73 | 75 | 76 | 77 | org.qunar.plugin.mybatis.intention.statement.InsertGenerateIntention 78 | 79 | 80 | org.qunar.plugin.mybatis.intention.statement.SelectGenerateIntention 81 | 82 | 83 | org.qunar.plugin.mybatis.intention.statement.UpdateGenerateIntention 84 | 85 | 86 | org.qunar.plugin.mybatis.intention.statement.DeleteGenerateIntention 87 | 88 | 89 | org.qunar.plugin.mybatis.intention.MapperGenerateIntention 90 | 91 | 92 | 93 | 94 | 95 | 97 | 100 | 101 | 102 | 103 |
    -------------------------------------------------------------------------------- /resources/icons/mybatis/generate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/icons/mybatis/generate.png -------------------------------------------------------------------------------- /resources/icons/mybatis/generate@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/icons/mybatis/generate@2x.png -------------------------------------------------------------------------------- /resources/icons/mybatis/generate@2x_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/icons/mybatis/generate@2x_dark.png -------------------------------------------------------------------------------- /resources/icons/mybatis/generate_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/icons/mybatis/generate_dark.png -------------------------------------------------------------------------------- /resources/icons/mybatis/navigateDown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/icons/mybatis/navigateDown.png -------------------------------------------------------------------------------- /resources/icons/mybatis/navigateDown@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/icons/mybatis/navigateDown@2x.png -------------------------------------------------------------------------------- /resources/icons/mybatis/navigateDown@2x_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/icons/mybatis/navigateDown@2x_dark.png -------------------------------------------------------------------------------- /resources/icons/mybatis/navigateDown_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/icons/mybatis/navigateDown_dark.png -------------------------------------------------------------------------------- /resources/icons/mybatis/navigateUp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/icons/mybatis/navigateUp.png -------------------------------------------------------------------------------- /resources/icons/mybatis/navigateUp@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/icons/mybatis/navigateUp@2x.png -------------------------------------------------------------------------------- /resources/icons/mybatis/navigateUp@2x_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/icons/mybatis/navigateUp@2x_dark.png -------------------------------------------------------------------------------- /resources/icons/mybatis/navigateUp_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/icons/mybatis/navigateUp_dark.png -------------------------------------------------------------------------------- /resources/inspectionDescriptions/Mappers.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | validate mappers node of configuration xml 4 | 5 | -------------------------------------------------------------------------------- /resources/inspectionDescriptions/MybatisMapper.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | mybatis mapper xml helper 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /resources/inspectionDescriptions/TypeAliases.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | validate typeAliases node of configuration xml 4 | 5 | -------------------------------------------------------------------------------- /resources/intentionDescriptions/DeleteGenerateIntention/after.generation.template: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/intentionDescriptions/DeleteGenerateIntention/after.generation.template -------------------------------------------------------------------------------- /resources/intentionDescriptions/DeleteGenerateIntention/before.generation.template: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/intentionDescriptions/DeleteGenerateIntention/before.generation.template -------------------------------------------------------------------------------- /resources/intentionDescriptions/DeleteGenerateIntention/description.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Generate Delete Node In Mapper Xml 4 | 5 | -------------------------------------------------------------------------------- /resources/intentionDescriptions/InsertGenerateIntention/after.generation.template: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/intentionDescriptions/InsertGenerateIntention/after.generation.template -------------------------------------------------------------------------------- /resources/intentionDescriptions/InsertGenerateIntention/before.generation.template: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/intentionDescriptions/InsertGenerateIntention/before.generation.template -------------------------------------------------------------------------------- /resources/intentionDescriptions/InsertGenerateIntention/description.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Generate Insert Node In Mapper Xml 4 | 5 | -------------------------------------------------------------------------------- /resources/intentionDescriptions/MapperGenerateIntention/after.generation.template: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/intentionDescriptions/MapperGenerateIntention/after.generation.template -------------------------------------------------------------------------------- /resources/intentionDescriptions/MapperGenerateIntention/before.generation.template: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/intentionDescriptions/MapperGenerateIntention/before.generation.template -------------------------------------------------------------------------------- /resources/intentionDescriptions/MapperGenerateIntention/description.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Generate new Mapper Xml 4 | 5 | -------------------------------------------------------------------------------- /resources/intentionDescriptions/SelectGenerateIntention/after.generation.template: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/intentionDescriptions/SelectGenerateIntention/after.generation.template -------------------------------------------------------------------------------- /resources/intentionDescriptions/SelectGenerateIntention/before.generation.template: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/intentionDescriptions/SelectGenerateIntention/before.generation.template -------------------------------------------------------------------------------- /resources/intentionDescriptions/SelectGenerateIntention/description.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Generate Select Node In Mapper Xml 4 | 5 | -------------------------------------------------------------------------------- /resources/intentionDescriptions/UpdateGenerateIntention/after.generation.template: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/intentionDescriptions/UpdateGenerateIntention/after.generation.template -------------------------------------------------------------------------------- /resources/intentionDescriptions/UpdateGenerateIntention/before.generation.template: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easonlian/mybatis-plugin-for-IDEA/2b50b5fa0386918bf2daf853a820e4f8c44be197/resources/intentionDescriptions/UpdateGenerateIntention/before.generation.template -------------------------------------------------------------------------------- /resources/intentionDescriptions/UpdateGenerateIntention/description.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Generate Update Node In Mapper Xml 4 | 5 | -------------------------------------------------------------------------------- /resources/velocity/template/mapper.vm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #foreach($column in $columns) 7 | 8 | #end 9 | 10 | 11 | 12 | #foreach($column in $columns) 13 | $column.name as $column.propertyName #if($velocityCount != $columns.size()),#end $empty 14 | #end 15 | 16 | 17 | 18 | 19 | #foreach($column in $columns) 20 | 21 | AND $column.name = #{$column.name} 22 | 23 | #end 24 | 25 | 26 | 27 | 34 | 35 | 42 | 43 | 44 | INSERT INTO 45 | $dbName (#foreach($column in $columns)$column.name #if($velocityCount != $columns.size()),#end #end) 46 | VALUES (#foreach($column in $columns)#{$column.propertyName} #if($velocityCount != $columns.size()),#end #end) 47 | 48 | 49 | 50 | DELETE FROM $dbName 51 | 52 | 53 | -------------------------------------------------------------------------------- /resources/velocity/velocity.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | # ---------------------------------------------------------------------------- 19 | # T E M P L A T E E N C O D I N G 20 | # ---------------------------------------------------------------------------- 21 | 22 | input.encoding=UTF-8 23 | output.encoding=UTF-8 24 | 25 | # ---------------------------------------------------------------------------- 26 | # T E M P L A T E L O A D E R S 27 | # ---------------------------------------------------------------------------- 28 | # 29 | # 30 | # ---------------------------------------------------------------------------- 31 | 32 | resource.loader = file 33 | 34 | file.resource.loader.description = Velocity File Resource Loader 35 | file.resource.loader.class = org.apache.velocity.runtime.resource.loader.FileResourceLoader 36 | file.resource.loader.path = 37 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/action/DebugAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.action; 5 | 6 | import com.intellij.openapi.actionSystem.AnAction; 7 | import com.intellij.openapi.actionSystem.AnActionEvent; 8 | import com.intellij.openapi.project.Project; 9 | 10 | /** 11 | * 12 | * 13 | * Author: jianyu.lin 14 | * Date: 2016/11/21 Time: 上午11:35 15 | */ 16 | public class DebugAction extends AnAction { 17 | 18 | @Override 19 | public void actionPerformed(AnActionEvent e) { 20 | Project project = e.getProject(); 21 | if (project == null) { return; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/bean/ModuleSetting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.bean; 5 | 6 | import com.google.common.collect.Lists; 7 | import com.intellij.openapi.module.Module; 8 | import com.intellij.openapi.vfs.VirtualFile; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * resole part of module setting 15 | * 16 | * Author: jianyu.lin 17 | * Date: 2016/12/5 Time: 下午7:51 18 | */ 19 | @SuppressWarnings("UnusedReturnValue") 20 | public class ModuleSetting { 21 | 22 | private Module module; 23 | 24 | private final List javaSources = Lists.newArrayList(); 25 | private final List javaTestSources = Lists.newArrayList(); 26 | private final List resourceSources = Lists.newArrayList(); 27 | private final List resourceTestSources = Lists.newArrayList(); 28 | 29 | public ModuleSetting addJavaSources(VirtualFile javaSource) { 30 | if (javaSource != null) { 31 | javaSources.add(javaSource); 32 | } 33 | return this; 34 | } 35 | 36 | public ModuleSetting addJavaTestSources(VirtualFile javaTestSource) { 37 | if (javaTestSource != null) { 38 | javaTestSources.add(javaTestSource); 39 | } 40 | return this; 41 | } 42 | 43 | public ModuleSetting addResourceSources(VirtualFile resourceSource) { 44 | if (resourceSource != null) { 45 | resourceSources.add(resourceSource); 46 | } 47 | return this; 48 | } 49 | 50 | public ModuleSetting addResourceTestSources(VirtualFile resourceTestSource) { 51 | if (resourceTestSource != null) { 52 | resourceTestSources.add(resourceTestSource); 53 | } 54 | return this; 55 | } 56 | 57 | public List getJavaSources() { 58 | return javaSources; 59 | } 60 | 61 | public List getJavaTestSources() { 62 | return javaTestSources; 63 | } 64 | 65 | public List getResourceSources() { 66 | return resourceSources; 67 | } 68 | 69 | public List getResourceTestSources() { 70 | return resourceTestSources; 71 | } 72 | 73 | @Nullable 74 | public Module getModule() { 75 | return module; 76 | } 77 | 78 | public void setModule(Module module) { 79 | this.module = module; 80 | } 81 | 82 | public List getAllResourceSources() { 83 | List resources = Lists.newArrayList(); 84 | resources.addAll(resourceSources); 85 | resources.addAll(resourceTestSources); 86 | return resources; 87 | } 88 | 89 | @Override 90 | public String toString() { 91 | return "ModuleSetting{" + 92 | "javaSources=" + javaSources + 93 | ", javaTestSources=" + javaTestSources + 94 | ", resourceSources=" + resourceSources + 95 | ", resourceTestSources=" + resourceTestSources + 96 | '}'; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/action/SqlGenerateAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.action; 5 | 6 | import com.intellij.openapi.actionSystem.AnAction; 7 | import com.intellij.openapi.actionSystem.AnActionEvent; 8 | import com.intellij.openapi.actionSystem.CommonDataKeys; 9 | import com.intellij.openapi.editor.Editor; 10 | import com.intellij.openapi.editor.ex.EditorEx; 11 | import com.intellij.openapi.project.Project; 12 | import com.intellij.openapi.util.Pair; 13 | import com.intellij.openapi.vfs.VirtualFile; 14 | import com.intellij.psi.PsiClass; 15 | import com.intellij.psi.PsiFile; 16 | import com.intellij.psi.PsiManager; 17 | import com.intellij.psi.xml.XmlFile; 18 | import com.intellij.sql.psi.SqlCreateTableStatement; 19 | import com.intellij.sql.psi.SqlElement; 20 | import com.intellij.sql.psi.SqlFile; 21 | import org.jetbrains.annotations.NotNull; 22 | import org.jetbrains.annotations.Nullable; 23 | import org.qunar.plugin.mybatis.generator.JavaGenerator; 24 | import org.qunar.plugin.mybatis.generator.XmlVelocityGenerator; 25 | 26 | import java.util.List; 27 | 28 | /** 29 | * generator sql action 30 | * 31 | * Author: jianyu.lin 32 | * Date: 2016/12/22 Time: 上午11:22 33 | */ 34 | public class SqlGenerateAction extends AnAction { 35 | 36 | /** 37 | * click action of right click menu 38 | * @param e event 39 | */ 40 | @Override 41 | public void actionPerformed(AnActionEvent e) { 42 | //Get required data keys 43 | final Project project = e.getData(CommonDataKeys.PROJECT); 44 | final Editor editor = e.getData(CommonDataKeys.EDITOR); 45 | if (project == null || editor == null) { 46 | return; 47 | } 48 | 49 | SqlFile sqlFile = getCurrentEditFile(project, editor); 50 | if (sqlFile == null) return; 51 | SqlElement sqlElement = getFirstCreateTableStatement(sqlFile.getDdl()); 52 | if (sqlElement == null) return; 53 | 54 | System.out.println(sqlFile); 55 | 56 | String qualifiedName = "org.qunar.temp.dao.SupplierDao"; 57 | 58 | JavaGenerator javaGenerator = new JavaGenerator(project, sqlElement, qualifiedName); 59 | Pair classPair = javaGenerator.generate(); 60 | 61 | if (classPair == null) { 62 | return; 63 | } 64 | 65 | String relatedPath = "mybatis/mapper/temp/SupplierMapper"; 66 | XmlVelocityGenerator xmlGenerator = new XmlVelocityGenerator(project, 67 | classPair.getFirst(), classPair.getSecond(), sqlElement, relatedPath); 68 | XmlFile xmlFile = xmlGenerator.generate(); 69 | System.out.println(xmlFile); 70 | } 71 | 72 | /** 73 | * {@inheritDoc} 74 | * @param e event 75 | */ 76 | @Override 77 | public void update(AnActionEvent e) { 78 | final Project project = e.getData(CommonDataKeys.PROJECT); 79 | final Editor editor = e.getData(CommonDataKeys.EDITOR); 80 | SqlFile sqlFile = getCurrentEditFile(project, editor); 81 | if (sqlFile == null) { 82 | e.getPresentation().setVisible(false); 83 | } else { 84 | SqlElement sqlElement = getFirstCreateTableStatement(sqlFile.getDdl()); 85 | if (sqlElement == null) { 86 | e.getPresentation().setVisible(false); 87 | } 88 | } 89 | } 90 | 91 | /** 92 | * peek first create table sql 93 | * @param sqlElements ddl list 94 | * @return create table ddl 95 | */ 96 | @Nullable 97 | private SqlElement getFirstCreateTableStatement(@NotNull List sqlElements) { 98 | for (SqlElement sqlElement : sqlElements) { 99 | if (sqlElement instanceof SqlCreateTableStatement) { 100 | return sqlElement; 101 | } 102 | } 103 | return null; 104 | } 105 | 106 | /** 107 | * get current edit file 108 | * @param project current project 109 | * @param editor current editor 110 | * @return psi file 111 | */ 112 | @Nullable 113 | private SqlFile getCurrentEditFile(Project project, Editor editor) { 114 | if (project == null || editor == null) return null; 115 | VirtualFile virtualFile = ((EditorEx) editor).getVirtualFile(); 116 | PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile); 117 | if (!(psiFile instanceof SqlFile)) return null; 118 | return (SqlFile) psiFile; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/bean/Annotation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.bean; 5 | 6 | import com.google.common.collect.Sets; 7 | 8 | import java.util.Set; 9 | 10 | /** 11 | * represent mybatis annotation 12 | * 13 | * Author: jianyu.lin 14 | * Date: 2016/11/28 Time: 下午1:29 15 | */ 16 | public enum Annotation { 17 | 18 | Param("org.apache.ibatis.annotations.Param"), 19 | Insert("org.apache.ibatis.annotations.Insert"), 20 | Select("org.apache.ibatis.annotations.Select"), 21 | Delete("org.apache.ibatis.annotations.Delete"), 22 | Update("org.apache.ibatis.annotations.Update"), 23 | ; 24 | 25 | Annotation(String qualified) { 26 | this.qualified = qualified; 27 | } 28 | 29 | public final String qualified; 30 | 31 | public static Set getStatementNames() { 32 | return Sets.newHashSet( 33 | Insert.name().toLowerCase(), 34 | Select.name().toLowerCase(), 35 | Delete.name().toLowerCase(), 36 | Update.name().toLowerCase() 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/bean/IdDomElement.java: -------------------------------------------------------------------------------- 1 | package org.qunar.plugin.mybatis.bean; 2 | 3 | import com.intellij.util.xml.DomElement; 4 | import com.intellij.util.xml.GenericAttributeValue; 5 | 6 | /** 7 | * dom element has required id attribute 8 | * 9 | * Author: jianyu.lin 10 | * Date: 16-11-29 Time: 下午8:00 11 | */ 12 | public interface IdDomElement extends DomElement { 13 | 14 | @SuppressWarnings("EmptyMethod") 15 | GenericAttributeValue getId(); 16 | } 17 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/bean/IdRefMethodDomElement.java: -------------------------------------------------------------------------------- 1 | package org.qunar.plugin.mybatis.bean; 2 | 3 | import com.intellij.psi.PsiMethod; 4 | import com.intellij.util.xml.Convert; 5 | import com.intellij.util.xml.GenericAttributeValue; 6 | import org.qunar.plugin.mybatis.converter.MapperMethodConverter; 7 | 8 | /** 9 | * dom element has required id attribute 10 | * 11 | * Author: jianyu.lin 12 | * Date: 16-11-29 Time: 下午8:00 13 | */ 14 | public interface IdRefMethodDomElement extends IdDomElement { 15 | 16 | @Convert(MapperMethodConverter.class) 17 | GenericAttributeValue getId(); 18 | } 19 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/bean/IdRefStringDomElement.java: -------------------------------------------------------------------------------- 1 | package org.qunar.plugin.mybatis.bean; 2 | 3 | import com.intellij.util.xml.GenericAttributeValue; 4 | 5 | /** 6 | * dom element has required id attribute 7 | * 8 | * Author: jianyu.lin 9 | * Date: 16-11-29 Time: 下午8:00 10 | */ 11 | public interface IdRefStringDomElement extends IdDomElement { 12 | 13 | GenericAttributeValue getId(); 14 | } 15 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/bean/config/Configuration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.bean.config; 5 | 6 | import com.intellij.util.xml.DomElement; 7 | import com.intellij.util.xml.SubTag; 8 | 9 | /** 10 | * Configuration node 11 | * 12 | * Author: jianyu.lin 13 | * Date: 2016/11/21 Time: 下午10:17 14 | */ 15 | public interface Configuration extends DomElement { 16 | 17 | // 详见: http://mybatis.org/dtd/mybatis-3-config.dtd 18 | // org.apache.ibatis.builder.xml.XMLConfigBuilder 19 | 20 | @SubTag("typeAliases") 21 | TypeAliases getTypeAliases(); 22 | 23 | @SubTag("mappers") 24 | Mappers getMappers(); 25 | } 26 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/bean/config/Mapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.bean.config; 5 | 6 | import com.intellij.psi.PsiClass; 7 | import com.intellij.psi.PsiFile; 8 | import com.intellij.util.xml.Attribute; 9 | import com.intellij.util.xml.Convert; 10 | import com.intellij.util.xml.DomElement; 11 | import com.intellij.util.xml.GenericAttributeValue; 12 | import org.jetbrains.annotations.Nullable; 13 | import org.qunar.plugin.mybatis.converter.PathFileConverter; 14 | 15 | /** 16 | * Mapper node 17 | * 18 | * Author: jianyu.lin 19 | * Date: 2016/11/21 Time: 下午10:17 20 | */ 21 | public interface Mapper extends DomElement { 22 | 23 | @Nullable 24 | @Convert(value = PathFileConverter.class) 25 | GenericAttributeValue getResource(); 26 | 27 | @Nullable 28 | GenericAttributeValue getUrl(); 29 | 30 | @Nullable 31 | @Attribute("class") 32 | GenericAttributeValue getClazz(); 33 | } 34 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/bean/config/Mappers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.bean.config; 5 | 6 | import com.intellij.util.xml.DomElement; 7 | import com.intellij.util.xml.SubTagList; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Mappers node 13 | * 14 | * Author: jianyu.lin 15 | * Date: 2016/11/21 Time: 下午10:17 16 | */ 17 | public interface Mappers extends DomElement { 18 | 19 | @SubTagList("mapper") 20 | List getMappers(); 21 | } 22 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/bean/config/Package.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.bean.config; 5 | 6 | import com.intellij.psi.PsiPackage; 7 | import com.intellij.util.xml.Attribute; 8 | import com.intellij.util.xml.Convert; 9 | import com.intellij.util.xml.DomElement; 10 | import com.intellij.util.xml.GenericAttributeValue; 11 | import com.intellij.util.xml.PsiPackageConverter; 12 | import org.jetbrains.annotations.NotNull; 13 | 14 | /** 15 | * TypeAliases node 16 | * 17 | * Author: jianyu.lin 18 | * Date: 2016/11/21 Time: 下午10:17 19 | */ 20 | public interface Package extends DomElement { 21 | 22 | @NotNull 23 | @Attribute("name") 24 | @Convert(value = PsiPackageConverter.class) 25 | GenericAttributeValue getName(); 26 | } 27 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/bean/config/TypeAlias.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.bean.config; 5 | 6 | import com.intellij.psi.PsiClass; 7 | import com.intellij.util.xml.Attribute; 8 | import com.intellij.util.xml.DomElement; 9 | import com.intellij.util.xml.GenericAttributeValue; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.jetbrains.annotations.Nullable; 12 | 13 | /** 14 | * TypeAliases node 15 | * 16 | * Author: jianyu.lin 17 | * Date: 2016/11/21 Time: 下午10:17 18 | */ 19 | public interface TypeAlias extends DomElement { 20 | 21 | @NotNull 22 | @Attribute("type") 23 | GenericAttributeValue getType(); 24 | 25 | @Nullable 26 | @Attribute("alias") 27 | GenericAttributeValue getAlias(); 28 | } 29 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/bean/config/TypeAliases.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.bean.config; 5 | 6 | import com.intellij.util.xml.DomElement; 7 | import com.intellij.util.xml.SubTagList; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * TypeAliases node 13 | * 14 | * Author: jianyu.lin 15 | * Date: 2016/11/21 Time: 下午10:17 16 | */ 17 | public interface TypeAliases extends DomElement { 18 | 19 | @SubTagList("typeAlias") 20 | List getTypeAlias(); 21 | 22 | @SubTagList("package") 23 | List getPackages(); 24 | } 25 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/bean/mapper/Cache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.bean.mapper; 5 | 6 | import com.intellij.util.xml.DomElement; 7 | 8 | /** 9 | * cache xml tag 10 | * 11 | * Author: jianyu.lin 12 | * Date: 2016/11/21 Time: 下午4:15 13 | */ 14 | public interface Cache extends DomElement { 15 | 16 | } -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/bean/mapper/CacheRef.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.bean.mapper; 5 | 6 | import com.intellij.util.xml.DomElement; 7 | 8 | /** 9 | * cache-ref xml tag 10 | * 11 | * Author: jianyu.lin 12 | * Date: 2016/11/21 Time: 下午4:15 13 | */ 14 | public interface CacheRef extends DomElement { 15 | 16 | } -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/bean/mapper/Delete.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.bean.mapper; 5 | 6 | /** 7 | * delete xml tag 8 | * 9 | * Author: jianyu.lin 10 | * Date: 2016/11/21 Time: 下午4:15 11 | */ 12 | public interface Delete extends Statement { 13 | 14 | } -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/bean/mapper/Insert.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.bean.mapper; 5 | 6 | import com.intellij.util.xml.Attribute; 7 | import com.intellij.util.xml.Convert; 8 | import com.intellij.util.xml.GenericAttributeValue; 9 | import com.intellij.util.xml.converters.values.BooleanValueConverter; 10 | 11 | /** 12 | * insert xml tag 13 | * 14 | * Author: jianyu.lin 15 | * Date: 2016/11/21 Time: 下午4:15 16 | */ 17 | public interface Insert extends Statement { 18 | 19 | @Convert(BooleanValueConverter.class) 20 | @Attribute("getUseGeneratedKeys") 21 | GenericAttributeValue getUseGeneratedKeys(); 22 | } -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/bean/mapper/Mapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.bean.mapper; 5 | 6 | import com.intellij.psi.PsiClass; 7 | import com.intellij.util.xml.Attribute; 8 | import com.intellij.util.xml.DomElement; 9 | import com.intellij.util.xml.GenericAttributeValue; 10 | import com.intellij.util.xml.SubTag; 11 | import com.intellij.util.xml.SubTagList; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * mapper root tag 17 | * 18 | * Author: jianyu.lin 19 | * Date: 2016/11/21 Time: 下午3:47 20 | */ 21 | public interface Mapper extends DomElement { 22 | 23 | @Attribute("namespace") 24 | GenericAttributeValue getNamespace(); 25 | 26 | List getCaches(); 27 | 28 | List getCacheRefs(); 29 | 30 | @SubTagList("delete") 31 | List getDeletes(); 32 | 33 | @SubTagList("insert") 34 | List getInserts(); 35 | 36 | @SubTagList("select") 37 | List\n" + 92 | " SELECT * FROM %s\n" + 93 | " ", qualifiedBeanName, myCreateTableDdl.getName()); 94 | XmlTag selectListTag = XmlElementFactory.getInstance(project).createTagFromText(sql); 95 | rootTag.add(selectListTag); 96 | 97 | sql = String.format( 98 | "\n" + 99 | " DELETE FROM %s WHERE id = #{id}\n" + 100 | " ", qualifiedBeanName, myCreateTableDdl.getName()); 101 | XmlTag deleteTag = XmlElementFactory.getInstance(project).createTagFromText(sql); 102 | rootTag.add(deleteTag); 103 | 104 | sql = String.format( 105 | "\n" + 106 | " INSERT INTO %s(" + 107 | ")\n" + 108 | " ", qualifiedBeanName, myCreateTableDdl.getName()); 109 | XmlTag insertOne = XmlElementFactory.getInstance(project).createTagFromText(sql); 110 | rootTag.add(insertOne); 111 | 112 | CodeStyleManager.getInstance(project).reformat(xmlFile.getRootTag()); 113 | } 114 | }); 115 | } 116 | 117 | /** 118 | * create or find directory with given base dir 119 | * @param baseDir class path based dir 120 | * @return psi directory 121 | */ 122 | private PsiDirectory createOrFindDirectory(final PsiDirectory baseDir) { 123 | return ApplicationManager.getApplication().runWriteAction(new Computable() { 124 | @Override 125 | public PsiDirectory compute() { 126 | PsiDirectory directory = baseDir; 127 | for (String path : dirPath.split("/")) { 128 | PsiDirectory subDirectory = directory.findSubdirectory(path); 129 | if (subDirectory == null) { 130 | subDirectory = directory.createSubdirectory(path); 131 | } 132 | directory = subDirectory; 133 | } 134 | return directory; 135 | } 136 | }); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/inspection/MybatisMapperInspection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.inspection; 5 | 6 | import com.google.common.collect.Lists; 7 | import com.intellij.codeInspection.InspectionManager; 8 | import com.intellij.codeInspection.LocalInspectionTool; 9 | import com.intellij.codeInspection.ProblemDescriptor; 10 | import com.intellij.psi.PsiFile; 11 | import org.jetbrains.annotations.NotNull; 12 | import org.jetbrains.annotations.Nullable; 13 | import org.qunar.plugin.mybatis.bean.mapper.Mapper; 14 | import org.qunar.plugin.mybatis.util.DomElements; 15 | import org.qunar.plugin.mybatis.util.MapperConfHolder; 16 | import org.qunar.plugin.util.Inspections; 17 | 18 | import java.util.List; 19 | 20 | /** 21 | * mybatis mapper xml inspection 22 | *

    23 | * Author: jianyu.lin 24 | * Date: 2016/11/22 Time: 下午8:13 25 | */ 26 | public class MybatisMapperInspection extends LocalInspectionTool { 27 | 28 | /** 29 | * valid config file 30 | * @param file config file 31 | * @param manager inspection manager 32 | * @param isOnTheFly the error show at the end of line 33 | * @return potential problems 34 | */ 35 | @Nullable 36 | @Override 37 | public ProblemDescriptor[] checkFile(@NotNull PsiFile file, 38 | @NotNull InspectionManager manager, boolean isOnTheFly) { 39 | if (!(DomElements.isMapperXmlFile(file))) { 40 | return null; 41 | } 42 | Mapper mapper = MapperConfHolder.INSTANCE.getDomElement(file); 43 | if (mapper == null || mapper.getNamespace() == null) { 44 | return null; 45 | } 46 | 47 | List allProblems = Lists.newArrayList(); 48 | // validate namespace attribute 49 | allProblems.addAll(Inspections.buildPsiClassProblems(manager, mapper.getNamespace())); 50 | // validate mapper statement nodes 51 | allProblems.addAll(DomElements.checkMapperDomElement(manager, mapper)); 52 | return allProblems.toArray(new ProblemDescriptor[allProblems.size()]); 53 | } 54 | } 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/inspection/config/AbstractConfigInspection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.inspection.config; 5 | 6 | import com.intellij.codeInspection.InspectionManager; 7 | import com.intellij.codeInspection.LocalInspectionTool; 8 | import com.intellij.codeInspection.ProblemDescriptor; 9 | import com.intellij.psi.PsiFile; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.jetbrains.annotations.Nullable; 12 | import org.qunar.plugin.mybatis.bean.config.Configuration; 13 | import org.qunar.plugin.mybatis.util.ConfigConfHolder; 14 | import org.qunar.plugin.mybatis.util.DomElements; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | * super class of configuration node inspection 20 | * 21 | * Author: jianyu.lin 22 | * Date: 2016/12/19 Time: 下午6:52 23 | */ 24 | abstract class AbstractConfigInspection extends LocalInspectionTool { 25 | 26 | /** 27 | * valid config file 28 | * @param file config file 29 | * @param manager inspection manager 30 | * @param isOnTheFly the error show at the end of line 31 | * @return potential problems 32 | */ 33 | @Nullable 34 | @Override 35 | public ProblemDescriptor[] checkFile(@NotNull PsiFile file, 36 | @NotNull InspectionManager manager, boolean isOnTheFly) { 37 | if (!DomElements.isConfigurationXmlFile(file)) { 38 | return null; 39 | } 40 | Configuration configuration = ConfigConfHolder.INSTANCE.getDomElement(file); 41 | if (configuration == null) { 42 | return null; 43 | } 44 | List allProblems = buildProblems(manager, configuration); 45 | return allProblems.toArray(new ProblemDescriptor[allProblems.size()]); 46 | } 47 | 48 | /** 49 | * build problems 50 | * @param manager manager 51 | * @param configuration config dom 52 | * @return problems 53 | */ 54 | @NotNull 55 | protected abstract List buildProblems(@NotNull InspectionManager manager, 56 | @NotNull Configuration configuration); 57 | } 58 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/inspection/config/MappersInspection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.inspection.config; 5 | 6 | import com.google.common.collect.Lists; 7 | import com.intellij.codeInspection.InspectionManager; 8 | import com.intellij.codeInspection.ProblemDescriptor; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.qunar.plugin.mybatis.bean.config.Configuration; 11 | import org.qunar.plugin.mybatis.util.domchecker.MappersChecker; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * mybatis configuration xml inspection 17 | *

    18 | * Author: jianyu.lin 19 | * Date: 2016/11/22 Time: 下午8:13 20 | */ 21 | public class MappersInspection extends AbstractConfigInspection { 22 | 23 | /** 24 | * {@inheritDoc} 25 | * @param manager manager 26 | * @param configuration config dom 27 | * @return problems 28 | */ 29 | @NotNull 30 | @Override 31 | protected List buildProblems(@NotNull InspectionManager manager, 32 | @NotNull Configuration configuration) { 33 | return new MappersChecker().check(manager, Lists.newArrayList(configuration.getMappers())); 34 | } 35 | } 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/inspection/config/TypeAliasesInspection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.inspection.config; 5 | 6 | import com.google.common.collect.Lists; 7 | import com.intellij.codeInspection.InspectionManager; 8 | import com.intellij.codeInspection.ProblemDescriptor; 9 | import org.jetbrains.annotations.NotNull; 10 | import org.qunar.plugin.mybatis.bean.config.Configuration; 11 | import org.qunar.plugin.mybatis.util.domchecker.TypeAliasesChecker; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * mybatis configuration xml inspection 17 | *

    18 | * Author: jianyu.lin 19 | * Date: 2016/11/22 Time: 下午8:13 20 | */ 21 | public class TypeAliasesInspection extends AbstractConfigInspection { 22 | 23 | /** 24 | * {@inheritDoc} 25 | * @param manager manager 26 | * @param configuration config dom 27 | * @return problems 28 | */ 29 | @NotNull 30 | @Override 31 | protected List buildProblems(@NotNull InspectionManager manager, 32 | @NotNull Configuration configuration) { 33 | return new TypeAliasesChecker().check(manager, Lists.newArrayList(configuration.getTypeAliases())); 34 | } 35 | } 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/intention/MapperGenerateIntention.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.intention; 5 | 6 | import com.intellij.codeInsight.intention.IntentionAction; 7 | import com.intellij.openapi.application.ApplicationManager; 8 | import com.intellij.openapi.application.Result; 9 | import com.intellij.openapi.command.WriteCommandAction; 10 | import com.intellij.openapi.editor.Editor; 11 | import com.intellij.openapi.module.Module; 12 | import com.intellij.openapi.module.ModuleUtil; 13 | import com.intellij.openapi.project.Project; 14 | import com.intellij.psi.PsiClass; 15 | import com.intellij.psi.PsiElement; 16 | import com.intellij.psi.PsiFile; 17 | import com.intellij.psi.PsiIdentifier; 18 | import com.intellij.psi.PsiJavaFile; 19 | import com.intellij.util.IncorrectOperationException; 20 | import org.jetbrains.annotations.Nls; 21 | import org.jetbrains.annotations.NotNull; 22 | import org.jetbrains.annotations.Nullable; 23 | import org.qunar.plugin.mybatis.bean.mapper.Mapper; 24 | import org.qunar.plugin.mybatis.ui.CreateMapperXmlDialog; 25 | import org.qunar.plugin.mybatis.util.MapperConfHolder; 26 | import org.qunar.plugin.service.EditorService; 27 | 28 | /** 29 | * generate new mapper xml 30 | * 31 | * Author: jianyu.lin 32 | * Date: 2016/12/1 Time: 下午7:26 33 | */ 34 | public class MapperGenerateIntention implements IntentionAction { 35 | 36 | @Nls 37 | @NotNull 38 | @Override 39 | public String getText() { 40 | return getFamilyName(); 41 | } 42 | 43 | @Nls 44 | @NotNull 45 | @Override 46 | public String getFamilyName() { 47 | return "Generate Mybatis Mapper Xml"; 48 | } 49 | 50 | @Override 51 | public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { 52 | return getCurrentClass(editor, file) != null; 53 | } 54 | 55 | @Override 56 | public void invoke(@NotNull final Project project, Editor editor, final PsiFile file) throws IncorrectOperationException { 57 | final PsiClass psiClass = getCurrentClass(editor, file); 58 | if (psiClass == null) { 59 | return; 60 | } 61 | new WriteCommandAction(project) { 62 | @Override 63 | protected void run(@NotNull Result result) throws Throwable { 64 | Module module = ModuleUtil.findModuleForPsiElement(file); 65 | if (module == null) return; 66 | ApplicationManager.getApplication().runWriteAction(new Runnable() { 67 | @Override 68 | public void run() { 69 | CreateMapperXmlDialog dialog = new CreateMapperXmlDialog(project, psiClass); 70 | if (dialog.showAndGet()) { 71 | PsiFile mapperFile = dialog.getNewMapperFile(); 72 | if (mapperFile == null) return; 73 | Mapper mapperDom = MapperConfHolder.INSTANCE.getDomElement(mapperFile); 74 | if (mapperDom == null) return; 75 | EditorService.getInstance(project).scrollTo(mapperDom.getXmlTag()); 76 | } 77 | } 78 | }); 79 | } 80 | }.execute(); 81 | } 82 | 83 | @Override 84 | public boolean startInWriteAction() { 85 | return false; 86 | } 87 | 88 | /** 89 | * get the caret point method 90 | * @param editor current editor 91 | * @param file current file 92 | * @return psi method 93 | */ 94 | @Nullable 95 | private PsiClass getCurrentClass(@Nullable Editor editor, @Nullable PsiFile file) { 96 | if (editor == null || file == null 97 | || !(file instanceof PsiJavaFile)) { 98 | return null; 99 | } 100 | PsiJavaFile javaFile = (PsiJavaFile) file; 101 | int offset = editor.getCaretModel().getOffset(); 102 | PsiElement psiElement = javaFile.findElementAt(offset); 103 | if (!(psiElement instanceof PsiIdentifier) 104 | || !(psiElement.getParent() instanceof PsiClass)) { 105 | return null; 106 | } 107 | if (javaFile.getClasses().length == 0) { 108 | return null; 109 | } 110 | PsiClass psiClass = javaFile.getClasses()[0]; 111 | if (!psiClass.isInterface() 112 | && !MapperConfHolder.INSTANCE.getMapperDomElements(psiClass).isEmpty()) { 113 | return null; 114 | } 115 | return psiClass; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/intention/statement/DeleteGenerateIntention.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.intention.statement; 5 | 6 | import com.google.common.collect.Sets; 7 | import org.jetbrains.annotations.Nls; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.qunar.plugin.mybatis.bean.mapper.Mapper; 10 | import org.qunar.plugin.mybatis.bean.mapper.Statement; 11 | 12 | import java.util.Set; 13 | 14 | /** 15 | * generate insert node in xml 16 | * 17 | * Author: jianyu.lin 18 | * Date: 2016/12/1 Time: 下午8:14 19 | */ 20 | public class DeleteGenerateIntention extends StatementGenerateIntention { 21 | 22 | private static final Set KEYWORDS = Sets.newHashSet( 23 | "delete", "remove", "del" 24 | ); 25 | @NotNull 26 | @Override 27 | protected Statement generateStatement(@NotNull Mapper mapperDom) { 28 | return mapperDom.addDelete(mapperDom.getDeletes().size()); 29 | } 30 | 31 | @NotNull 32 | @Override 33 | protected Set getSubGeneratorKeywords() { 34 | return KEYWORDS; 35 | } 36 | 37 | @Nls 38 | @NotNull 39 | @Override 40 | public String getFamilyName() { 41 | return "Generate Mapper Delete Statement"; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/intention/statement/InsertGenerateIntention.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.intention.statement; 5 | 6 | import com.google.common.collect.Sets; 7 | import org.jetbrains.annotations.Nls; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.qunar.plugin.mybatis.bean.mapper.Mapper; 10 | import org.qunar.plugin.mybatis.bean.mapper.Statement; 11 | 12 | import java.util.Set; 13 | 14 | /** 15 | * generate insert node in xml 16 | * 17 | * Author: jianyu.lin 18 | * Date: 2016/12/1 Time: 下午8:14 19 | */ 20 | public class InsertGenerateIntention extends StatementGenerateIntention { 21 | 22 | private static final Set KEYWORDS = Sets.newHashSet( 23 | "insert", "add", "append", "addictive" 24 | ); 25 | 26 | @NotNull 27 | @Override 28 | protected Statement generateStatement(@NotNull Mapper mapperDom) { 29 | return mapperDom.addInsert(mapperDom.getInserts().size()); 30 | } 31 | 32 | @NotNull 33 | @Override 34 | protected Set getSubGeneratorKeywords() { 35 | return KEYWORDS; 36 | } 37 | 38 | @Nls 39 | @NotNull 40 | @Override 41 | public String getFamilyName() { 42 | return "Generate Mapper Insert Statement"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/intention/statement/SelectGenerateIntention.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.intention.statement; 5 | 6 | import com.google.common.collect.Sets; 7 | import org.jetbrains.annotations.Nls; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.qunar.plugin.mybatis.bean.mapper.Mapper; 10 | import org.qunar.plugin.mybatis.bean.mapper.Statement; 11 | 12 | import java.util.Set; 13 | 14 | /** 15 | * generate select node in xml 16 | * 17 | * Author: jianyu.lin 18 | * Date: 2016/12/1 Time: 下午8:14 19 | */ 20 | public class SelectGenerateIntention extends StatementGenerateIntention { 21 | 22 | private static final Set KEYWORDS = Sets.newHashSet( 23 | "select", "get", "find", "query", "count", "sort" 24 | ); 25 | 26 | @NotNull 27 | @Override 28 | protected Statement generateStatement(@NotNull Mapper mapperDom) { 29 | return mapperDom.addSelect(mapperDom.getSelects().size()); 30 | } 31 | 32 | @NotNull 33 | @Override 34 | protected Set getSubGeneratorKeywords() { 35 | return KEYWORDS; 36 | } 37 | 38 | @Nls 39 | @NotNull 40 | @Override 41 | public String getFamilyName() { 42 | return "Generate Mapper Select Statement"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/intention/statement/StatementGenerateIntention.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.intention.statement; 5 | 6 | import com.intellij.codeInsight.intention.IntentionAction; 7 | import com.intellij.openapi.application.ApplicationManager; 8 | import com.intellij.openapi.editor.Editor; 9 | import com.intellij.openapi.project.Project; 10 | import com.intellij.psi.PsiElement; 11 | import com.intellij.psi.PsiFile; 12 | import com.intellij.psi.PsiIdentifier; 13 | import com.intellij.psi.PsiJavaFile; 14 | import com.intellij.psi.PsiMethod; 15 | import com.intellij.psi.xml.XmlTag; 16 | import com.intellij.util.IncorrectOperationException; 17 | import org.jetbrains.annotations.Nls; 18 | import org.jetbrains.annotations.NotNull; 19 | import org.jetbrains.annotations.Nullable; 20 | import org.qunar.plugin.mybatis.bean.mapper.Mapper; 21 | import org.qunar.plugin.mybatis.bean.mapper.Statement; 22 | import org.qunar.plugin.mybatis.util.DomElements; 23 | import org.qunar.plugin.mybatis.util.MapperConfHolder; 24 | import org.qunar.plugin.service.EditorService; 25 | import org.qunar.plugin.util.CodeFormatter; 26 | 27 | import java.util.Collection; 28 | import java.util.Set; 29 | 30 | /** 31 | * generate statement int mapping mapper xml 32 | * 33 | * Author: jianyu.lin 34 | * Date: 2016/12/1 Time: 下午7:26 35 | */ 36 | abstract class StatementGenerateIntention implements IntentionAction { 37 | 38 | /** 39 | * return same as family name 40 | * @return family name 41 | */ 42 | @Nls 43 | @NotNull 44 | @Override 45 | public String getText() { 46 | return getFamilyName(); 47 | } 48 | 49 | /** 50 | * check method reference to mapper xml 51 | * @param project current project 52 | * @param editor current editor 53 | * @param file current file 54 | * @return boolean 55 | */ 56 | @Override 57 | public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { 58 | 59 | PsiMethod method = getCurrentMethod(editor, file); 60 | if (method == null || method.getContainingClass() == null) { 61 | return false; 62 | } 63 | @SuppressWarnings("ConstantConditions") 64 | Collection mapperDomList = MapperConfHolder.INSTANCE.getMapperDomElements(method.getContainingClass()); 65 | if (mapperDomList.size() != 1) { 66 | return false; 67 | } 68 | Mapper mapperDom = mapperDomList.iterator().next(); 69 | for (Statement statement : DomElements.collectStatements(mapperDom)) { 70 | if (statement.getId().getValue() == method) { 71 | return false; 72 | } 73 | } 74 | return checkKeywords(method.getName()); 75 | } 76 | 77 | /** 78 | * do generate action 79 | * @param project current project 80 | * @param editor current editor 81 | * @param file current file 82 | * @throws IncorrectOperationException any 83 | */ 84 | @Override 85 | public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { 86 | PsiMethod method = getCurrentMethod(editor, file); 87 | if (method == null || method.getContainingClass() == null) { 88 | return; 89 | } 90 | @SuppressWarnings("ConstantConditions") 91 | Collection mapperDomList = MapperConfHolder.INSTANCE.getMapperDomElements(method.getContainingClass()); 92 | if (mapperDomList.size() != 1) { 93 | return; 94 | } 95 | generateStatement(project, method, mapperDomList.iterator().next()); 96 | } 97 | 98 | @Override 99 | public boolean startInWriteAction() { 100 | return false; 101 | } 102 | 103 | /** 104 | * check intention key words 105 | * @param methodName current method name 106 | * @return boolean 107 | */ 108 | private boolean checkKeywords(String methodName) { 109 | Set keywords = getSubGeneratorKeywords(); 110 | for (String keyword : keywords) { 111 | if (methodName.toLowerCase().contains(keyword.toLowerCase())) { 112 | return true; 113 | } 114 | } 115 | return false; 116 | } 117 | 118 | /** 119 | * get the caret point method 120 | * @param editor current editor 121 | * @param file current file 122 | * @return psi method 123 | */ 124 | @Nullable 125 | private PsiMethod getCurrentMethod(@Nullable Editor editor, @Nullable PsiFile file) { 126 | if (editor == null || file == null 127 | || !(file instanceof PsiJavaFile)) { 128 | return null; 129 | } 130 | PsiJavaFile javaFile = (PsiJavaFile) file; 131 | int offset = editor.getCaretModel().getOffset(); 132 | PsiElement psiElement = javaFile.findElementAt(offset); 133 | if (!(psiElement instanceof PsiIdentifier) 134 | || !(psiElement.getParent() instanceof PsiMethod)) { 135 | return null; 136 | } 137 | return (PsiMethod) psiElement.getParent(); 138 | } 139 | 140 | /** 141 | * generate statement in mapper xml 142 | * @param project current project 143 | * @param mapperDom mapper dom 144 | */ 145 | private void generateStatement(@NotNull final Project project, 146 | @NotNull final PsiMethod method, @NotNull final Mapper mapperDom) { 147 | final XmlTag rootTag = mapperDom.getXmlTag(); 148 | if (rootTag == null || mapperDom.getNamespace().getValue() == null) { 149 | return; 150 | } 151 | ApplicationManager.getApplication().runWriteAction(new Runnable() { 152 | @Override 153 | public void run() { 154 | // generate new statement 155 | Statement statement = generateStatement(mapperDom); 156 | statement.getId().setStringValue(method.getName()); 157 | statement.setStringValue("\n"); 158 | CodeFormatter.format(statement.getXmlTag()); 159 | // navigate to new statement 160 | //noinspection ConstantConditions 161 | EditorService.getInstance(project).scrollTo(statement.getId().getXmlAttributeValue()); 162 | } 163 | }); 164 | } 165 | 166 | /** 167 | * generated dom element 168 | * @return new dom element 169 | */ 170 | @NotNull 171 | protected abstract Statement generateStatement(@NotNull Mapper mapperDom); 172 | 173 | /** 174 | * get sub generator 175 | * @return key words 176 | */ 177 | @NotNull 178 | protected abstract Set getSubGeneratorKeywords(); 179 | } 180 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/intention/statement/UpdateGenerateIntention.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.intention.statement; 5 | 6 | import com.google.common.collect.Sets; 7 | import org.jetbrains.annotations.Nls; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.qunar.plugin.mybatis.bean.mapper.Mapper; 10 | import org.qunar.plugin.mybatis.bean.mapper.Statement; 11 | 12 | import java.util.Set; 13 | 14 | /** 15 | * generate insert node in xml 16 | * 17 | * Author: jianyu.lin 18 | * Date: 2016/12/1 Time: 下午8:14 19 | */ 20 | public class UpdateGenerateIntention extends StatementGenerateIntention { 21 | 22 | private static final Set KEYWORDS = Sets.newHashSet( 23 | "update", "change" 24 | ); 25 | 26 | @NotNull 27 | @Override 28 | protected Statement generateStatement(@NotNull Mapper mapperDom) { 29 | return mapperDom.addUpdate(mapperDom.getUpdates().size()); 30 | } 31 | 32 | @NotNull 33 | @Override 34 | protected Set getSubGeneratorKeywords() { 35 | return KEYWORDS; 36 | } 37 | 38 | @Nls 39 | @NotNull 40 | @Override 41 | public String getFamilyName() { 42 | return "Generate Mapper Update Statement"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/linemarker/AbstractMapperMakerProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.linemarker; 5 | 6 | import com.google.common.collect.Lists; 7 | import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo; 8 | import com.intellij.codeInsight.daemon.RelatedItemLineMarkerProvider; 9 | import com.intellij.psi.PsiElement; 10 | import com.intellij.psi.PsiMethod; 11 | import org.jetbrains.annotations.NotNull; 12 | import org.jetbrains.annotations.Nullable; 13 | import org.qunar.plugin.mybatis.bean.mapper.Mapper; 14 | import org.qunar.plugin.mybatis.bean.mapper.Statement; 15 | import org.qunar.plugin.mybatis.util.DomElements; 16 | import org.qunar.plugin.util.XmlUtils; 17 | 18 | import java.util.Collection; 19 | import java.util.List; 20 | 21 | /** 22 | * mapper maker abstract super class 23 | * 24 | * Author: jianyu.lin 25 | * Date: 2016/11/25 Time: 下午10:19 26 | */ 27 | abstract class AbstractMapperMakerProvider extends RelatedItemLineMarkerProvider { 28 | 29 | /** 30 | * one mapper xml deal only once 31 | * @param elements changed elements 32 | * @param result marker result 33 | * @param forNavigation navigation 34 | */ 35 | @Override 36 | public void collectNavigationMarkers(@NotNull List elements, 37 | Collection result, boolean forNavigation) { 38 | List myElements = elements.size() > 0 ? chooseElement(elements) : Lists.newArrayList(); 39 | super.collectNavigationMarkers(myElements, result, forNavigation); 40 | } 41 | 42 | /** 43 | * filter duplicate elements request 44 | * @param elements changed elements 45 | * @return choose correct element to build markers 46 | */ 47 | @NotNull 48 | protected abstract List chooseElement(@NotNull List elements); 49 | 50 | /** 51 | * build mapping method marks 52 | * @param mapperDom mapper dom 53 | * @return mark info list 54 | */ 55 | List buildMethodLineMarkers(Mapper mapperDom) { 56 | List lineMarkerInfoList = Lists.newArrayList(); 57 | for (Statement statement : DomElements.collectStatements(mapperDom)) { 58 | PsiMethod method = XmlUtils.getAttrValue(statement.getId()); 59 | if (method == null || method.getNameIdentifier() == null) { 60 | continue; 61 | } 62 | RelatedItemLineMarkerInfo lineMarker = buildMethodLineMarker(statement, method); 63 | if (lineMarker != null) { 64 | lineMarkerInfoList.add(lineMarker); 65 | } 66 | } 67 | return lineMarkerInfoList; 68 | } 69 | 70 | /** 71 | * build single mapping method marks 72 | * @param statement sql statement 73 | * @return single line marker 74 | */ 75 | @Nullable 76 | protected abstract RelatedItemLineMarkerInfo buildMethodLineMarker(@NotNull Statement statement, 77 | @NotNull PsiMethod method); 78 | } 79 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/linemarker/Java2XmlLineMarkerProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.linemarker; 5 | 6 | import com.google.common.collect.Lists; 7 | import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo; 8 | import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder; 9 | import com.intellij.openapi.editor.markup.GutterIconRenderer; 10 | import com.intellij.psi.PsiClass; 11 | import com.intellij.psi.PsiDirectory; 12 | import com.intellij.psi.PsiElement; 13 | import com.intellij.psi.PsiFile; 14 | import com.intellij.psi.PsiJavaFile; 15 | import com.intellij.psi.PsiMethod; 16 | import com.intellij.psi.xml.XmlAttribute; 17 | import com.intellij.psi.xml.XmlAttributeValue; 18 | import org.jetbrains.annotations.NotNull; 19 | import org.jetbrains.annotations.Nullable; 20 | import org.qunar.plugin.mybatis.bean.mapper.Mapper; 21 | import org.qunar.plugin.mybatis.bean.mapper.Statement; 22 | import org.qunar.plugin.mybatis.util.MapperConfHolder; 23 | import org.qunar.plugin.util.Icons; 24 | 25 | import java.util.Collection; 26 | import java.util.List; 27 | 28 | /** 29 | * navigate from java interface 2 mapper xml 30 | * 31 | * Author: jianyu.lin 32 | * Date: 2016/11/25 Time: 下午7:08 33 | */ 34 | public class Java2XmlLineMarkerProvider extends AbstractMapperMakerProvider { 35 | 36 | /** 37 | * {@inheritDoc} 38 | * @param elements changed elements 39 | * @return psiClass 40 | */ 41 | @NotNull 42 | @Override 43 | protected List chooseElement(@NotNull List elements) { 44 | for (PsiElement element : elements) { 45 | if (element instanceof PsiClass) { 46 | return Lists.newArrayList(element); 47 | } 48 | } 49 | return Lists.newArrayList(); 50 | } 51 | 52 | @Override 53 | protected void collectNavigationMarkers(@NotNull PsiElement element, 54 | Collection result) { 55 | PsiClass mapperClass = getCurrentPsiClass(element); 56 | if (mapperClass == null) { 57 | return; 58 | } 59 | Collection mapperDomElements = MapperConfHolder.INSTANCE.getMapperDomElements(mapperClass); 60 | 61 | for (Mapper mapperDom : mapperDomElements) { 62 | // add interface 2 mapper 63 | if (mapperDom.getNamespace().getXmlAttribute() != null) { 64 | result.add(buildInterfaceLineMarker(mapperClass, mapperDom)); 65 | } 66 | // add method 2 statement 67 | result.addAll(buildMethodLineMarkers(mapperDom)); 68 | } 69 | } 70 | 71 | /** 72 | * get psi class by current element 73 | * @param element element 74 | * @return psi class 75 | */ 76 | @Nullable 77 | private PsiClass getCurrentPsiClass(PsiElement element) { 78 | PsiElement tempElement = element; 79 | while (tempElement != null && !(tempElement instanceof PsiDirectory)) { 80 | if (tempElement instanceof PsiClass) { 81 | return (PsiClass) tempElement; 82 | } 83 | if (tempElement instanceof PsiJavaFile) { 84 | PsiClass[] psiClasses = ((PsiJavaFile) tempElement).getClasses(); 85 | if (psiClasses.length > 0) { 86 | return psiClasses[0]; 87 | } 88 | } 89 | tempElement = tempElement.getParent(); 90 | } 91 | return null; 92 | } 93 | 94 | /** 95 | * build interface line marker 96 | * @param mapperClass mapper class 97 | * @param mapperDom mapper dom element 98 | * @return line marker 99 | */ 100 | @SuppressWarnings("ConstantConditions") 101 | private RelatedItemLineMarkerInfo buildInterfaceLineMarker(@NotNull PsiClass mapperClass, 102 | @NotNull Mapper mapperDom) { 103 | // marker element 104 | PsiElement markElement = mapperClass.getNameIdentifier() == null ? mapperClass : mapperClass.getNameIdentifier(); 105 | // target element 106 | XmlAttribute attribute = mapperDom.getNamespace().getXmlAttribute(); 107 | PsiElement targetElement = attribute.getValueElement() == null ? attribute : attribute.getValueElement(); 108 | // tooltip text 109 | PsiFile mapperFile = mapperDom.getXmlElement().getContainingFile(); 110 | String tooltipText = "Navigate to mapper xml" + (mapperFile == null ? "" : ": " + mapperFile.getName()); 111 | // build line marker 112 | return NavigationGutterIconBuilder.create(Icons.MYBATIS_2_XML_ICON) 113 | .setTarget(targetElement) 114 | .setTooltipText(tooltipText) 115 | .createLineMarkerInfo(markElement); 116 | } 117 | 118 | /** 119 | * {@inheritDoc} 120 | * @param statement sql statement 121 | * @return marker 122 | */ 123 | @Override 124 | @Nullable 125 | protected RelatedItemLineMarkerInfo buildMethodLineMarker(@NotNull Statement statement, 126 | @NotNull PsiMethod method) { 127 | @SuppressWarnings("ConstantConditions") 128 | XmlAttributeValue idAttrValue = statement.getXmlTag().getAttribute("id").getValueElement(); 129 | String statementDesc = String.format("<%s id="%s" .../>", statement.getXmlTag().getName(), method.getName()); 130 | NavigationGutterIconBuilder builder = 131 | NavigationGutterIconBuilder.create(Icons.MYBATIS_2_XML_ICON).setTarget(idAttrValue) 132 | .setAlignment(GutterIconRenderer.Alignment.CENTER) 133 | .setTooltipText("Navigate to mapper xml statement: " + statementDesc); 134 | PsiElement markElement = method.getNameIdentifier() == null ? method : method.getNameIdentifier(); 135 | return builder.createLineMarkerInfo(markElement); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/linemarker/Xml2JavaLineMarkerProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.linemarker; 5 | 6 | import com.google.common.collect.Lists; 7 | import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo; 8 | import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder; 9 | import com.intellij.psi.PsiClass; 10 | import com.intellij.psi.PsiElement; 11 | import com.intellij.psi.PsiMethod; 12 | import com.intellij.psi.xml.XmlTag; 13 | import org.jetbrains.annotations.NotNull; 14 | import org.jetbrains.annotations.Nullable; 15 | import org.qunar.plugin.mybatis.bean.mapper.Mapper; 16 | import org.qunar.plugin.mybatis.bean.mapper.Statement; 17 | import org.qunar.plugin.mybatis.util.DomElements; 18 | import org.qunar.plugin.mybatis.util.MapperConfHolder; 19 | import org.qunar.plugin.util.Icons; 20 | 21 | import java.util.Collection; 22 | import java.util.List; 23 | 24 | /** 25 | * navigate from mapper xml 2 java interface 26 | * 27 | * Author: jianyu.lin 28 | * Date: 2016/11/25 Time: 下午7:08 29 | */ 30 | public class Xml2JavaLineMarkerProvider extends AbstractMapperMakerProvider { 31 | 32 | /** 33 | * {@inheritDoc} 34 | * @param elements changed elements 35 | * @return root tag 36 | */ 37 | @NotNull 38 | @Override 39 | protected List chooseElement(@NotNull List elements) { 40 | for (PsiElement element : elements) { 41 | if (element instanceof XmlTag) { 42 | XmlTag xmlTag = (XmlTag) element; 43 | if (MapperConfHolder.INSTANCE.rootTagName.contains(xmlTag.getName())) { 44 | return Lists.newArrayList(element); 45 | } 46 | } 47 | } 48 | return Lists.newArrayList(); 49 | } 50 | 51 | @Override 52 | protected void collectNavigationMarkers(@NotNull PsiElement element, 53 | Collection result) { 54 | if (!DomElements.isMapperXmlFile(element.getContainingFile())) { 55 | return; 56 | } 57 | 58 | Mapper mapperDom = MapperConfHolder.INSTANCE.getDomElement(element.getContainingFile()); 59 | if (mapperDom == null || mapperDom.getNamespace() == null 60 | || mapperDom.getNamespace().getValue() == null) { 61 | return; 62 | } 63 | 64 | // mark mapping mapper tag 65 | PsiClass mapperClass = mapperDom.getNamespace().getValue(); 66 | NavigationGutterIconBuilder builder = 67 | NavigationGutterIconBuilder.create(Icons.MYBATIS_2_JAVA_ICON) 68 | .setTarget(mapperClass).setTooltipText("Navigate to mapper java interface: " + mapperClass.getName()); 69 | result.add(builder.createLineMarkerInfo(mapperDom.getXmlTag())); 70 | 71 | // mark mapping statement tag 72 | result.addAll(buildMethodLineMarkers(mapperDom)); 73 | } 74 | 75 | /** 76 | * {@inheritDoc} 77 | * @param statement sql statement 78 | * @return marker 79 | */ 80 | @Nullable 81 | @Override 82 | protected RelatedItemLineMarkerInfo buildMethodLineMarker(@NotNull Statement statement, 83 | @NotNull PsiMethod method) { 84 | NavigationGutterIconBuilder builder = 85 | NavigationGutterIconBuilder.create(Icons.MYBATIS_2_JAVA_ICON).setTarget(method.getNameIdentifier()) 86 | .setTooltipText("Navigate to mapper java method: " + method.getName()); 87 | return builder.createLineMarkerInfo(statement.getXmlTag()); 88 | } 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/query/MapperXmlInheritorsSearch.java: -------------------------------------------------------------------------------- 1 | package org.qunar.plugin.mybatis.query; 2 | 3 | import com.intellij.openapi.application.ApplicationManager; 4 | import com.intellij.openapi.util.Computable; 5 | import com.intellij.psi.PsiClass; 6 | import com.intellij.psi.PsiElement; 7 | import com.intellij.psi.PsiMethod; 8 | import com.intellij.psi.search.searches.DefinitionsScopedSearch; 9 | import com.intellij.psi.xml.XmlAttribute; 10 | import com.intellij.psi.xml.XmlElement; 11 | import com.intellij.util.Processor; 12 | import com.intellij.util.QueryExecutor; 13 | import org.jetbrains.annotations.NotNull; 14 | import org.qunar.plugin.mybatis.bean.mapper.Mapper; 15 | import org.qunar.plugin.mybatis.bean.mapper.Statement; 16 | import org.qunar.plugin.mybatis.util.DomElements; 17 | import org.qunar.plugin.mybatis.util.MapperConfHolder; 18 | import org.qunar.plugin.util.XmlUtils; 19 | 20 | import java.util.Collection; 21 | import java.util.List; 22 | 23 | /** 24 | * mark mapper xml to be the implementation of mapper class 25 | * can use 'implementation' key to navigate to xml 26 | *

    27 | * author: jianyu.lin Date: 16-11-26. 28 | */ 29 | public class MapperXmlInheritorsSearch implements QueryExecutor { 30 | 31 | /** 32 | * process inheritor between xml and interface 33 | * 34 | * @param queryParameters query parameters 35 | * @param consumer processor 36 | * @return result 37 | */ 38 | @Override 39 | public boolean execute(@NotNull DefinitionsScopedSearch.SearchParameters queryParameters, 40 | @NotNull Processor consumer) { 41 | PsiElement element = queryParameters.getElement(); 42 | //noinspection SimplifiableIfStatement 43 | if (!(element instanceof PsiClass) && !(element instanceof PsiMethod)) { 44 | return true; 45 | } 46 | return element instanceof PsiClass ? 47 | processClass((PsiClass) element, consumer) : 48 | processMethod((PsiMethod) element, consumer); 49 | } 50 | 51 | /** 52 | * process class inheritors 53 | * 54 | * @param mapperClass mapper class 55 | * @param consumer processor 56 | * @return result 57 | */ 58 | @SuppressWarnings("SameReturnValue") 59 | private boolean processClass(@NotNull PsiClass mapperClass, 60 | @NotNull final Processor consumer) { 61 | Collection mapperDomElements = MapperConfHolder.INSTANCE.getMapperDomElements(mapperClass); 62 | for (final Mapper mapperDom : mapperDomElements) { 63 | if (mapperDom.getXmlElement() != null) { 64 | consumer.process(mapperDom.getXmlElement()); 65 | } 66 | } 67 | return Boolean.TRUE; 68 | } 69 | 70 | /** 71 | * process method inheritors 72 | * 73 | * @param mapperMethod mapper method 74 | * @param consumer processor 75 | * @return result 76 | */ 77 | @SuppressWarnings("SameReturnValue") 78 | private boolean processMethod(@NotNull final PsiMethod mapperMethod, 79 | @NotNull final Processor consumer) { 80 | return ApplicationManager.getApplication().runReadAction(new Computable() { 81 | @Override 82 | public Boolean compute() { 83 | if (mapperMethod.getContainingClass() == null) { 84 | return Boolean.TRUE; 85 | } 86 | Collection mapperDomElements = MapperConfHolder.INSTANCE 87 | .getMapperDomElements(mapperMethod.getContainingClass()); 88 | for (final Mapper mapperDom : mapperDomElements) { 89 | if (mapperDom.getXmlElement() != null) { 90 | List statements = DomElements.collectStatements(mapperDom); 91 | for (final Statement statement : statements) { 92 | PsiMethod psiMethod = XmlUtils.getAttrValue(statement.getId()); 93 | final XmlAttribute idAttr = statement.getXmlTag().getAttribute("id"); 94 | if (psiMethod == mapperMethod && idAttr != null) { 95 | if (idAttr.getValueElement() != null) { 96 | consumer.process(idAttr.getValueElement()); 97 | } 98 | } 99 | } 100 | } 101 | } 102 | return Boolean.TRUE; 103 | } 104 | }); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/reference/ClassPathRelatedFileReference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.reference; 5 | 6 | import com.intellij.psi.PsiElement; 7 | import com.intellij.psi.PsiElementResolveResult; 8 | import com.intellij.psi.PsiFile; 9 | import com.intellij.psi.PsiPolyVariantReference; 10 | import com.intellij.psi.PsiReferenceBase; 11 | import com.intellij.psi.ResolveResult; 12 | import com.intellij.psi.xml.XmlAttributeValue; 13 | import org.jetbrains.annotations.NotNull; 14 | import org.jetbrains.annotations.Nullable; 15 | import org.qunar.plugin.mybatis.converter.PathFileConverter; 16 | 17 | /** 18 | * classPath related file reference 19 | * 20 | * Author: jianyu.lin 21 | * Date: 2016/11/23 Time: 下午2:19 22 | */ 23 | public class ClassPathRelatedFileReference extends PsiReferenceBase implements PsiPolyVariantReference { 24 | 25 | public ClassPathRelatedFileReference(@NotNull XmlAttributeValue element) { 26 | super(element); 27 | } 28 | 29 | @Nullable 30 | @Override 31 | public PsiElement resolve() { 32 | ResolveResult[] results = multiResolve(true); 33 | return results.length > 0 ? results[0].getElement() : null; 34 | } 35 | 36 | @NotNull 37 | @Override 38 | public Object[] getVariants() { 39 | return new Object[0]; 40 | } 41 | 42 | @NotNull 43 | @Override 44 | public ResolveResult[] multiResolve(boolean incompleteCode) { 45 | PsiFile relatedFile = PathFileConverter.parseClassPathRelatedFile(myElement.getProject(), myElement.getValue()); 46 | return relatedFile == null ? new ResolveResult[]{} : 47 | new ResolveResult[]{new PsiElementResolveResult(relatedFile.getOriginalElement())}; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/reference/MapperAttr2ResultMapReference.java: -------------------------------------------------------------------------------- 1 | package org.qunar.plugin.mybatis.reference; 2 | 3 | import com.intellij.psi.xml.XmlAttributeValue; 4 | import org.jetbrains.annotations.NotNull; 5 | import org.qunar.plugin.mybatis.bean.IdDomElement; 6 | import org.qunar.plugin.mybatis.bean.mapper.Mapper; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * mapper sql tag reference 12 | * 13 | * Author: jianyu.lin 14 | * Date: 16-11-27 Time: 下午1:57 15 | */ 16 | public class MapperAttr2ResultMapReference extends MapperIdAttrRefXmlTagReference { 17 | 18 | public MapperAttr2ResultMapReference(@NotNull XmlAttributeValue resultMapAttrValue) { 19 | super(resultMapAttrValue); 20 | } 21 | 22 | @Override 23 | protected List getIdDomElements(@NotNull Mapper mapperDom) { 24 | return mapperDom.getResultMaps(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/reference/MapperIdAttrRefXmlTagReference.java: -------------------------------------------------------------------------------- 1 | package org.qunar.plugin.mybatis.reference; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.intellij.codeInsight.lookup.LookupElement; 5 | import com.intellij.codeInsight.lookup.LookupElementBuilder; 6 | import com.intellij.psi.PsiElement; 7 | import com.intellij.psi.PsiReferenceBase; 8 | import com.intellij.psi.xml.XmlAttribute; 9 | import com.intellij.psi.xml.XmlAttributeValue; 10 | import org.apache.commons.lang.ObjectUtils; 11 | import org.apache.commons.lang.StringUtils; 12 | import org.jetbrains.annotations.NotNull; 13 | import org.jetbrains.annotations.Nullable; 14 | import org.qunar.plugin.mybatis.bean.IdDomElement; 15 | import org.qunar.plugin.mybatis.bean.mapper.Mapper; 16 | import org.qunar.plugin.service.DomParseService; 17 | import org.qunar.plugin.util.XmlUtils; 18 | 19 | import java.util.List; 20 | 21 | /** 22 | * mapper id attribute to id required tag reference 23 | * 24 | * Author: jianyu.lin 25 | * Date: 16-11-27 Time: 下午1:57 26 | */ 27 | abstract class MapperIdAttrRefXmlTagReference extends PsiReferenceBase { 28 | 29 | MapperIdAttrRefXmlTagReference(@NotNull XmlAttributeValue resultMapAttrValue) { 30 | super(resultMapAttrValue); 31 | } 32 | 33 | @Nullable 34 | @Override 35 | public PsiElement resolve() { 36 | for (IdDomElement result : getIdDomElements()) { 37 | XmlAttribute resultMapIdAttr = result.getXmlTag().getAttribute("id"); 38 | if (ObjectUtils.equals(XmlUtils.getAttrValue(result.getId()), myElement.getValue()) 39 | && resultMapIdAttr != null) { 40 | return resultMapIdAttr.getValueElement(); 41 | } 42 | } 43 | return null; 44 | } 45 | 46 | @NotNull 47 | @Override 48 | public Object[] getVariants() { 49 | List lookupElements = Lists.newArrayList(); 50 | for (IdDomElement idDomElement : getIdDomElements()) { 51 | if (XmlUtils.getAttrValue(idDomElement.getId()) != null) { 52 | //noinspection ConstantConditions 53 | lookupElements.add(LookupElementBuilder.create(XmlUtils.getAttrValue(idDomElement.getId()))); 54 | } 55 | } 56 | return lookupElements.toArray(); 57 | } 58 | 59 | @NotNull 60 | private List getIdDomElements() { 61 | if (myElement == null || StringUtils.isBlank(myElement.getValue())) { 62 | return Lists.newArrayList(); 63 | } 64 | Mapper mapperDom = DomParseService.INSTANCE(myElement.getProject()) 65 | .parseDomElementsByFile(myElement.getContainingFile(), Mapper.class); 66 | if (mapperDom == null) { 67 | return Lists.newArrayList(); 68 | } 69 | return getIdDomElements(mapperDom); 70 | } 71 | 72 | protected abstract List getIdDomElements(@NotNull Mapper mapperDom); 73 | } 74 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/reference/MapperInclude2SqlReference.java: -------------------------------------------------------------------------------- 1 | package org.qunar.plugin.mybatis.reference; 2 | 3 | import com.intellij.psi.xml.XmlAttributeValue; 4 | import org.jetbrains.annotations.NotNull; 5 | import org.qunar.plugin.mybatis.bean.IdDomElement; 6 | import org.qunar.plugin.mybatis.bean.mapper.Mapper; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * mapper sql tag reference 12 | * 13 | * Author: jianyu.lin 14 | * Date: 16-11-27 Time: 下午1:57 15 | */ 16 | public class MapperInclude2SqlReference extends MapperIdAttrRefXmlTagReference { 17 | 18 | public MapperInclude2SqlReference(@NotNull XmlAttributeValue sqlRefAttrValue) { 19 | super(sqlRefAttrValue); 20 | } 21 | 22 | @Override 23 | protected List getIdDomElements(@NotNull Mapper mapperDom) { 24 | return mapperDom.getSqls(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/reference/StatementParamsReference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.reference; 5 | 6 | import com.google.common.collect.Sets; 7 | import com.intellij.openapi.util.TextRange; 8 | import com.intellij.psi.PsiAnnotationMemberValue; 9 | import com.intellij.psi.PsiElement; 10 | import com.intellij.psi.PsiIdentifier; 11 | import com.intellij.psi.PsiMethod; 12 | import com.intellij.psi.PsiReferenceBase; 13 | import com.intellij.psi.xml.XmlAttributeValue; 14 | import com.intellij.psi.xml.XmlTag; 15 | import com.intellij.util.xml.DomManager; 16 | import org.apache.commons.lang.StringUtils; 17 | import org.jetbrains.annotations.NotNull; 18 | import org.jetbrains.annotations.Nullable; 19 | import org.qunar.plugin.mybatis.bean.mapper.Statement; 20 | import org.qunar.plugin.mybatis.util.ParamPropertyHelper; 21 | 22 | import java.util.Arrays; 23 | import java.util.Set; 24 | 25 | /** 26 | * add inline sql parameter (${} #{}) reference 27 | * 28 | * Author: jianyu.lin 29 | * Date: 2016/12/3 Time: 下午12:40 30 | */ 31 | public class StatementParamsReference extends PsiReferenceBase { 32 | 33 | private final XmlTag parent; 34 | private final String text; 35 | /* add for support tags who adds temp parameters, 36 | * eg: 37 | **/ 38 | private final Set extraParams = Sets.newHashSet(); 39 | 40 | public StatementParamsReference(@NotNull XmlTag xmlTag, 41 | @NotNull XmlTag parentTag, @NotNull TextRange range) { 42 | super(xmlTag, range, true); 43 | this.parent = parentTag; 44 | text = xmlTag.getText().substring(range.getStartOffset(), range.getEndOffset()); 45 | } 46 | 47 | /** 48 | * add extra params 49 | * @param extraParams extra params 50 | * @return this 51 | */ 52 | public StatementParamsReference extraParams(PsiElement... extraParams) { 53 | if (extraParams != null) { 54 | this.extraParams.addAll(Arrays.asList(extraParams)); 55 | } 56 | return this; 57 | } 58 | 59 | @Nullable 60 | @Override 61 | public PsiElement resolve() { 62 | Statement statement = (Statement) DomManager.getDomManager(myElement.getProject()).getDomElement(parent); 63 | if (statement == null || statement.getId().getValue() == null) { 64 | return null; 65 | } 66 | PsiMethod psiMethod = statement.getId().getValue(); 67 | Set elements = ParamPropertyHelper.buildParamLookupElements(psiMethod); 68 | elements.addAll(extraParams); 69 | for (PsiElement element : elements) { 70 | if (checkPsiElementWithTargetText(element)) { 71 | return element; 72 | } 73 | } 74 | return null; 75 | } 76 | 77 | @NotNull 78 | @Override 79 | public Object[] getVariants() { 80 | return new Object[0]; 81 | } 82 | 83 | /** 84 | * check the reference psi element 85 | * @param element parameter element 86 | * @return boolean 87 | */ 88 | private boolean checkPsiElementWithTargetText(PsiElement element) { 89 | String psiName; 90 | if (element instanceof PsiAnnotationMemberValue) { // @Param 91 | // delete first letter " and last one " 92 | psiName = element.getText().substring(1, element.getTextLength() - 1); 93 | } else if (element instanceof PsiIdentifier) { // method name 94 | String getterProperty = ParamPropertyHelper.parseGetterMethod(element.getText()); 95 | psiName = getterProperty == null ? element.getText() : getterProperty; 96 | } else if (element instanceof XmlAttributeValue) { // xml attribute 97 | psiName = ((XmlAttributeValue) element).getValue(); 98 | } else { 99 | psiName = element.getText(); 100 | } 101 | return StringUtils.equals(text, psiName); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/reference/TypeAliasNameReference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.reference; 5 | 6 | import com.intellij.openapi.project.Project; 7 | import com.intellij.psi.PsiClass; 8 | import com.intellij.psi.PsiReferenceBase; 9 | import com.intellij.psi.xml.XmlAttributeValue; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.jetbrains.annotations.Nullable; 12 | import org.qunar.plugin.mybatis.util.TypeAliasResolver; 13 | import org.qunar.plugin.service.JavaService; 14 | import org.qunar.plugin.service.TypeAliasService; 15 | 16 | import java.util.Set; 17 | 18 | /** 19 | * type alias reference 20 | * 21 | * Author: jianyu.lin 22 | * Date: 2016/11/25 Time: 下午6:09 23 | */ 24 | public class TypeAliasNameReference extends PsiReferenceBase { 25 | 26 | public TypeAliasNameReference(@NotNull XmlAttributeValue element) { 27 | super(element); 28 | } 29 | 30 | @Nullable 31 | @Override 32 | public PsiClass resolve() { 33 | XmlAttributeValue xmlAttributeValue = getElement(); 34 | PsiClass qualifiedClass = JavaService.getInstance(getElement().getProject()).findClass(xmlAttributeValue.getValue()); 35 | return qualifiedClass != null ? qualifiedClass : TypeAliasService 36 | .INSTANCE(xmlAttributeValue.getProject()).getAliasClassByName(xmlAttributeValue.getValue()); 37 | } 38 | 39 | @NotNull 40 | @Override 41 | public Object[] getVariants() { 42 | Project project = getElement().getProject(); 43 | Set registerAliases = TypeAliasResolver.getAllTypeAlias(project).keySet(); 44 | return registerAliases.toArray(new String[registerAliases.size()]); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/typehandler/MapperSqlParamTypedHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.typehandler; 5 | 6 | import com.intellij.codeInsight.AutoPopupController; 7 | import com.intellij.codeInsight.editorActions.TypedHandlerDelegate; 8 | import com.intellij.openapi.editor.Editor; 9 | import com.intellij.openapi.project.Project; 10 | import com.intellij.openapi.util.Condition; 11 | import com.intellij.psi.PsiDocumentManager; 12 | import com.intellij.psi.PsiFile; 13 | import org.jetbrains.annotations.NotNull; 14 | import org.qunar.plugin.mybatis.contributor.StatementParamsCompletionContributor; 15 | import org.qunar.plugin.mybatis.util.DomElements; 16 | 17 | /** 18 | * allow #{ or ${ active auto completion
    19 | * add statement sql text auto pop with method params
    20 | * to see: {@link StatementParamsCompletionContributor}
    21 | * 22 | * Author: jianyu.lin 23 | * Date: 2016/11/28 Time: 下午6:35 24 | */ 25 | public class MapperSqlParamTypedHandler extends TypedHandlerDelegate { 26 | 27 | @Override 28 | public Result charTyped(char charTyped, Project project, @NotNull Editor editor, @NotNull PsiFile file) { 29 | if (charTyped == '{' && DomElements.isMapperXmlFile(file)) { 30 | int offset = editor.getCaretModel().getOffset(); 31 | char preChar = editor.getDocument().getCharsSequence().charAt(offset - 2); 32 | if (offset >= 2 && (preChar == '#' || preChar == '$')) { 33 | //noinspection unchecked 34 | AutoPopupController.getInstance(project).autoPopupMemberLookup(editor, Condition.TRUE); 35 | PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument()); 36 | } 37 | return Result.STOP; 38 | } 39 | return super.charTyped(charTyped, project, editor, file); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/ui/CreateMapperXmlDialog.form: -------------------------------------------------------------------------------- 1 | 2 |

    3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 |
    85 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/util/ConfigConfHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.util; 5 | 6 | import org.jetbrains.annotations.NotNull; 7 | import org.qunar.plugin.mybatis.bean.config.Configuration; 8 | import org.qunar.plugin.util.ConfHolder; 9 | 10 | /** 11 | * Author: jianyu.lin 12 | * Date: 2016/12/19 Time: 下午6:07 13 | */ 14 | public class ConfigConfHolder extends ConfHolder { 15 | 16 | public static final ConfigConfHolder INSTANCE = new ConfigConfHolder(Configuration.class); 17 | 18 | private ConfigConfHolder(@NotNull Class clazz) { 19 | super(clazz); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/util/DbDdlParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.util; 5 | 6 | import com.intellij.database.model.DasTypedObject; 7 | import com.intellij.database.model.MultiRef; 8 | import com.intellij.sql.psi.SqlColumnDefinition; 9 | import com.intellij.sql.psi.SqlCreateTableStatement; 10 | import com.intellij.sql.psi.SqlTableKeyDefinition; 11 | import org.jetbrains.annotations.NotNull; 12 | import org.qunar.plugin.mybatis.bean.model.DbColumn; 13 | import org.qunar.plugin.mybatis.bean.model.CreateTableDdl; 14 | import org.qunar.plugin.mybatis.bean.model.DbKey; 15 | import org.qunar.plugin.service.JavaService; 16 | import org.qunar.plugin.util.Javas; 17 | 18 | /** 19 | * psi ddl util 20 | * 21 | * Author: jianyu.lin 22 | * Date: 2016/12/24 Time: 上午12:23 23 | */ 24 | public class DbDdlParser { 25 | 26 | /** 27 | * parse create table ddl 28 | * @param createTableStatement psi create ddl 29 | * @return plain model 30 | */ 31 | public static CreateTableDdl parseCreateTableDdl(@NotNull SqlCreateTableStatement createTableStatement) { 32 | CreateTableDdl createTableDdl = new CreateTableDdl(createTableStatement.getName()); 33 | for (SqlColumnDefinition columnDefinition : createTableStatement.getDeclaredColumns()) { 34 | DbColumn dbColumn = new DbColumn(); 35 | dbColumn.setName(columnDefinition.getName()); 36 | dbColumn.setPropertyName(Javas.transUnderline2UpperLetter(columnDefinition.getName())); 37 | dbColumn.setTypeName(columnDefinition.getDataType().typeName); 38 | createTableDdl.getColumns().add(dbColumn); 39 | } 40 | for (SqlTableKeyDefinition keyDefinition : createTableStatement.getDeclaredKeys()) { 41 | DbKey dbKey = new DbKey(); 42 | dbKey.setKeyType(DbKey.KeyType.valueOf(keyDefinition.getClass())); 43 | MultiRef.It it = keyDefinition.getColumnsRef().iterate(); 44 | while (it.hasNext()) { 45 | dbKey.getRefColumns().add(it.next()); 46 | } 47 | createTableDdl.getDbKeys().add(dbKey); 48 | } 49 | return createTableDdl; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/util/DomElements.java: -------------------------------------------------------------------------------- 1 | package org.qunar.plugin.mybatis.util; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.intellij.codeInspection.InspectionManager; 5 | import com.intellij.codeInspection.ProblemDescriptor; 6 | import com.intellij.openapi.application.ApplicationManager; 7 | import com.intellij.openapi.util.Computable; 8 | import com.intellij.psi.PsiClass; 9 | import com.intellij.psi.PsiFile; 10 | import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; 11 | import com.intellij.psi.xml.XmlFile; 12 | import com.intellij.sql.psi.SqlFile; 13 | import org.apache.commons.lang.StringUtils; 14 | import org.jetbrains.annotations.NotNull; 15 | import org.qunar.plugin.mybatis.bean.mapper.Mapper; 16 | import org.qunar.plugin.mybatis.bean.mapper.Statement; 17 | import org.qunar.plugin.mybatis.util.domchecker.DeleteChecker; 18 | import org.qunar.plugin.mybatis.util.domchecker.InsertChecker; 19 | import org.qunar.plugin.mybatis.util.domchecker.SelectChecker; 20 | import org.qunar.plugin.mybatis.util.domchecker.UpdateChecker; 21 | import org.qunar.plugin.util.XmlUtils; 22 | 23 | import java.util.List; 24 | 25 | /** 26 | * author: jianyu.lin Date: 16-11-26. 27 | */ 28 | public class DomElements { 29 | 30 | /** 31 | * checkMapper dom elements 32 | * @param manager inspection manager 33 | * @param mapperDom mapper dom element 34 | * @return problems 35 | */ 36 | @NotNull 37 | public static List checkMapperDomElement(@NotNull InspectionManager manager, 38 | @NotNull Mapper mapperDom) { 39 | PsiClass mapperClass = XmlUtils.getAttrValue(mapperDom.getNamespace()); 40 | if (mapperClass == null) { 41 | return Lists.newArrayList(); 42 | } 43 | 44 | List allProblems = Lists.newArrayList(); 45 | allProblems.addAll(new InsertChecker(mapperClass).check(manager, mapperDom.getInserts())); 46 | allProblems.addAll(new DeleteChecker(mapperClass).check(manager, mapperDom.getDeletes())); 47 | allProblems.addAll(new SelectChecker(mapperClass).check(manager, mapperDom.getSelects())); 48 | allProblems.addAll(new UpdateChecker(mapperClass).check(manager, mapperDom.getUpdates())); 49 | return allProblems; 50 | } 51 | 52 | /** 53 | * collection all statements 54 | * @param mapperDom mapper root dom 55 | * @return statements 56 | */ 57 | @NotNull 58 | public static List collectStatements(final Mapper mapperDom) { 59 | if (mapperDom == null) { 60 | return Lists.newArrayList(); 61 | } 62 | return ApplicationManager.getApplication().runReadAction(new Computable>() { 63 | @Override 64 | public List compute() { 65 | List statements = Lists.newArrayList(); 66 | statements.addAll(mapperDom.getSelects()); 67 | statements.addAll(mapperDom.getInserts()); 68 | statements.addAll(mapperDom.getUpdates()); 69 | statements.addAll(mapperDom.getDeletes()); 70 | return statements; 71 | } 72 | }); 73 | } 74 | 75 | /** 76 | * is mapper xml file 77 | * @param psiFile file 78 | * @return boolean 79 | */ 80 | public static boolean isMapperXmlFile(PsiFile psiFile) { 81 | return isMybatisFile(psiFile, MapperConfHolder.INSTANCE.rootTagName); 82 | } 83 | 84 | /** 85 | * is mapper configuration file 86 | * @param psiFile file 87 | * @return boolean 88 | */ 89 | public static boolean isConfigurationXmlFile(PsiFile psiFile) { 90 | return isMybatisFile(psiFile, ConfigConfHolder.INSTANCE.rootTagName); 91 | } 92 | 93 | /** 94 | * is mybatis config file 95 | * @param psiFile file 96 | * @param rootTagName root tag name 97 | * @return boolean 98 | */ 99 | private static boolean isMybatisFile(PsiFile psiFile, String rootTagName) { 100 | if (psiFile == null) { 101 | return false; 102 | } 103 | if (psiFile instanceof XmlFile) { 104 | return isMybatisXmlFile((XmlFile) psiFile, rootTagName); 105 | } 106 | return psiFile instanceof SqlFile && isMybatisSqlFile((SqlFile) psiFile, rootTagName); 107 | } 108 | 109 | /** 110 | * judge sql file 111 | * @param sqlFile sql file 112 | * @param rootTagName root tag name 113 | * @return boolean 114 | */ 115 | private static boolean isMybatisSqlFile(SqlFile sqlFile, String rootTagName) { 116 | PsiFile psiFile = InjectedLanguageUtil.getTopLevelFile(sqlFile); 117 | return psiFile instanceof XmlFile && isMybatisFile(psiFile, rootTagName); 118 | } 119 | 120 | /** 121 | * judge sql file 122 | * @param xmlFile xml file 123 | * @param rootTagName root tag name 124 | * @return boolean 125 | */ 126 | private static boolean isMybatisXmlFile(XmlFile xmlFile, String rootTagName) { 127 | return xmlFile.getRootTag() != null && 128 | StringUtils.equals(xmlFile.getRootTag().getName(), rootTagName); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/util/MapperConfHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.util; 5 | 6 | import com.google.common.base.Predicate; 7 | import com.google.common.collect.Collections2; 8 | import com.intellij.openapi.application.ApplicationManager; 9 | import com.intellij.openapi.project.Project; 10 | import com.intellij.openapi.util.Computable; 11 | import com.intellij.psi.PsiClass; 12 | import com.intellij.psi.search.GlobalSearchScope; 13 | import com.intellij.util.xml.DomFileElement; 14 | import com.intellij.util.xml.DomService; 15 | import org.jetbrains.annotations.NotNull; 16 | import org.qunar.plugin.mybatis.bean.mapper.Mapper; 17 | import org.qunar.plugin.util.ConfHolder; 18 | import org.qunar.plugin.util.XmlUtils; 19 | 20 | import java.util.Collection; 21 | import java.util.List; 22 | 23 | /** 24 | * mapper dom cache util 25 | * 26 | * Author: jianyu.lin 27 | * Date: 2016/12/19 Time: 下午6:07 28 | */ 29 | public class MapperConfHolder extends ConfHolder { 30 | 31 | public static final MapperConfHolder INSTANCE = new MapperConfHolder(Mapper.class); 32 | 33 | private MapperConfHolder(@NotNull Class clazz) { 34 | super(clazz); 35 | } 36 | 37 | /** 38 | * get all mapping mapper xml 39 | * @param mapperClass class 40 | * @return mapper dom elements 41 | */ 42 | @NotNull 43 | public Collection getMapperDomElements(@NotNull final PsiClass mapperClass) { 44 | return ApplicationManager.getApplication().runReadAction(new Computable>() { 45 | @Override 46 | public Collection compute() { 47 | if (getAllDomElements().isEmpty()) { 48 | initAllMappers(mapperClass.getProject()); 49 | } 50 | Collection mappers = filterMapperDom(getAllDomElements(), mapperClass); 51 | if (mappers.isEmpty()) { 52 | initAllMappers(mapperClass.getProject()); 53 | } 54 | return filterMapperDom(getAllDomElements(), mapperClass); 55 | } 56 | }); 57 | } 58 | 59 | /** 60 | * filter mapper dom 61 | * @param allDocuments 所有mapper dom 62 | * @param targetClass mapper class 63 | * @return mapping mappers 64 | */ 65 | private Collection filterMapperDom(Collection allDocuments, final PsiClass targetClass) { 66 | return Collections2.filter(allDocuments, new Predicate() { 67 | @Override 68 | public boolean apply(final Mapper mapper) { 69 | return ApplicationManager.getApplication().runReadAction(new Computable() { 70 | @Override 71 | public Boolean compute() { 72 | if (mapper.getXmlTag() == null || !rootTagName.equals(mapper.getXmlTag().getName())) { 73 | return false; 74 | } 75 | mapper.getNamespace(); 76 | PsiClass psiClass = XmlUtils.getAttrValue(mapper.getNamespace()); 77 | return psiClass == targetClass; 78 | } 79 | }); 80 | } 81 | }); 82 | } 83 | 84 | /** 85 | * reload all mappers 86 | * @param project current project 87 | */ 88 | private void initAllMappers(Project project) { 89 | List> mapperFiles = DomService.getInstance() 90 | .getFileElements(Mapper.class, project, GlobalSearchScope.projectScope(project)); 91 | for (DomFileElement mapperFile : mapperFiles) { 92 | PsiClass psiClass = XmlUtils.getAttrValue(mapperFile.getRootElement().getNamespace()); 93 | if (psiClass != null) { 94 | holder.put(mapperFile.getFile(), mapperFile.getRootElement()); 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/util/domchecker/DeleteChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.util.domchecker; 5 | 6 | import com.intellij.psi.PsiClass; 7 | import org.qunar.plugin.mybatis.bean.mapper.Delete; 8 | 9 | /** 10 | * Author: jianyu.lin 11 | * Date: 2016/11/30 Time: 下午6:38 12 | */ 13 | public class DeleteChecker extends StatementChecker { 14 | 15 | public DeleteChecker(PsiClass mapperClass) { 16 | super(mapperClass); 17 | } 18 | } -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/util/domchecker/InsertChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.util.domchecker; 5 | 6 | import com.intellij.psi.PsiClass; 7 | import org.jetbrains.annotations.NotNull; 8 | import org.qunar.plugin.mybatis.bean.mapper.Insert; 9 | 10 | /** 11 | * Author: jianyu.lin 12 | * Date: 2016/11/30 Time: 下午6:37 13 | */ 14 | public class InsertChecker extends StatementChecker { 15 | 16 | public InsertChecker(@NotNull PsiClass mapperClass) { 17 | super(mapperClass); 18 | } 19 | } -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/util/domchecker/MappersChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.util.domchecker; 5 | 6 | import com.google.common.collect.Lists; 7 | import com.intellij.codeInspection.InspectionManager; 8 | import com.intellij.codeInspection.LocalQuickFix; 9 | import com.intellij.codeInspection.ProblemDescriptor; 10 | import com.intellij.codeInspection.ProblemHighlightType; 11 | import com.intellij.openapi.paths.GlobalPathReferenceProvider; 12 | import com.intellij.openapi.util.TextRange; 13 | import com.intellij.psi.PsiFile; 14 | import com.intellij.psi.xml.XmlAttributeValue; 15 | import com.intellij.util.xml.GenericAttributeValue; 16 | import org.apache.commons.lang.StringUtils; 17 | import org.jetbrains.annotations.NotNull; 18 | import org.qunar.plugin.mybatis.bean.config.Mapper; 19 | import org.qunar.plugin.mybatis.bean.config.Mappers; 20 | import org.qunar.plugin.util.DomChecker; 21 | import org.qunar.plugin.util.Inspections; 22 | 23 | import java.util.List; 24 | 25 | /** 26 | * Author: jianyu.lin 27 | * Date: 2016/11/30 Time: 下午7:22 28 | */ 29 | public class MappersChecker implements DomChecker { 30 | 31 | /** 32 | * reference to 'org.apache.ibatis.builder.xml.XMLConfigBuilder#mapperElement' 33 | * @param manager inspection manager 34 | * @param mappersList mappers nodes 35 | * @return check result 36 | */ 37 | @Override 38 | @NotNull 39 | public List check(@NotNull InspectionManager manager, @NotNull List mappersList) { 40 | List problemDescriptors = Lists.newArrayList(); 41 | for (Mappers mappers : mappersList) { 42 | for (Mapper mapper : mappers.getMappers()) { 43 | problemDescriptors.addAll(Inspections.buildPsiClassProblems(manager, mapper.getClazz())); 44 | problemDescriptors.addAll(buildUrlAttrProblems(manager, mapper.getUrl())); 45 | } 46 | } 47 | return problemDescriptors; 48 | } 49 | 50 | /** 51 | * valid resource attribute 52 | * @param manager inspection manager 53 | * @param resourceAttr resource attribute 54 | * @return problems 55 | */ 56 | @NotNull 57 | @SuppressWarnings("unused") 58 | private List buildResourceAttrProblems(@NotNull InspectionManager manager, 59 | GenericAttributeValue resourceAttr) { 60 | if (resourceAttr == null || resourceAttr.getXmlAttribute() == null) { 61 | return Lists.newArrayList(); 62 | } 63 | XmlAttributeValue xmlAttrValue = resourceAttr.getXmlAttributeValue(); 64 | if (resourceAttr.getValue() != null || xmlAttrValue == null) { 65 | return Lists.newArrayList(); 66 | } 67 | return Inspections.buildClassPathRelatedPathProblems(manager, xmlAttrValue); 68 | } 69 | 70 | /** 71 | * valid url attribute 72 | * @param manager inspection manager 73 | * @param urlAttr url attribute 74 | * @return problems 75 | */ 76 | @NotNull 77 | private List buildUrlAttrProblems(@NotNull InspectionManager manager, 78 | GenericAttributeValue urlAttr) { 79 | if (urlAttr == null || StringUtils.isBlank(urlAttr.getValue())) { 80 | return Lists.newArrayList(); 81 | } 82 | if (!GlobalPathReferenceProvider.isWebReferenceUrl(urlAttr.getValue())) { 83 | String errMsg = String.format("Cannot resolve url '%s'", urlAttr.getValue()); 84 | XmlAttributeValue urlAttrValue = urlAttr.getXmlAttributeValue(); 85 | if (urlAttrValue == null) { 86 | return Lists.newArrayList(); 87 | } 88 | TextRange textRange = TextRange.create(1, urlAttrValue.getTextLength()); 89 | return Lists.newArrayList(manager.createProblemDescriptor(urlAttrValue, textRange, 90 | errMsg, ProblemHighlightType.ERROR, true, LocalQuickFix.EMPTY_ARRAY)); 91 | } 92 | return Lists.newArrayList(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/org/qunar/plugin/mybatis/util/domchecker/SelectChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Qunar.com. All Rights Reserved. 3 | */ 4 | package org.qunar.plugin.mybatis.util.domchecker; 5 | 6 | import com.intellij.psi.PsiClass; 7 | import org.qunar.plugin.mybatis.bean.mapper.Select; 8 | 9 | /** 10 | * Author: jianyu.lin 11 | * Date: 2016/11/30 Time: 下午6:39 12 | */ 13 | public class SelectChecker extends StatementChecker